libtorrent-0.16.11/0000755000000000000000000000000015175073434007564 5libtorrent-0.16.11/Makefile.am0000644000000000000000000000041115175073411011527 SUBDIRS = src test pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libtorrent.pc EXTRA_DIST= \ scripts/checks.m4 \ scripts/common.m4 \ scripts/attributes.m4 \ scripts/ssl.m4 \ doc/main.xml \ doc/http.xml \ doc/torrent.xml ACLOCAL_AMFLAGS = -I scripts libtorrent-0.16.11/COPYING0000644000000000000000000004313115175073411010534 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. libtorrent-0.16.11/libtorrent.pc.in0000644000000000000000000000043215175073411012613 prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: libtorrent Description: A BitTorrent library Version: @VERSION@ Requires.private: zlib, libcrypto Libs: -L${libdir} -ltorrent Libs.private: @PTHREAD_LIBS@ @ATOMIC_LIBS@ Cflags: -I${includedir} libtorrent-0.16.11/scripts/0000755000000000000000000000000015175073434011253 5libtorrent-0.16.11/scripts/ssl.m40000644000000000000000000000024415175073411012231 AC_DEFUN([TORRENT_CHECK_OPENSSL], [ PKG_CHECK_MODULES(OPENSSL, libcrypto, CXXFLAGS="$CXXFLAGS $OPENSSL_CFLAGS"; LIBS="$LIBS $OPENSSL_LIBS") ] ) libtorrent-0.16.11/scripts/ltsugar.m40000644000000000000000000001045315175073420013114 # ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- # # Copyright (C) 2004-2005, 2007-2008, 2011-2019, 2021-2022 Free Software # Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 6 ltsugar.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) # lt_join(SEP, ARG1, [ARG2...]) # ----------------------------- # Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their # associated separator. # Needed until we can rely on m4_join from Autoconf 2.62, since all earlier # versions in m4sugar had bugs. m4_define([lt_join], [m4_if([$#], [1], [], [$#], [2], [[$2]], [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) m4_define([_lt_join], [m4_if([$#$2], [2], [], [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) # lt_car(LIST) # lt_cdr(LIST) # ------------ # Manipulate m4 lists. # These macros are necessary as long as will still need to support # Autoconf-2.59, which quotes differently. m4_define([lt_car], [[$1]]) m4_define([lt_cdr], [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], [$#], 1, [], [m4_dquote(m4_shift($@))])]) m4_define([lt_unquote], $1) # lt_append(MACRO-NAME, STRING, [SEPARATOR]) # ------------------------------------------ # Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'. # Note that neither SEPARATOR nor STRING are expanded; they are appended # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). # No SEPARATOR is output if MACRO-NAME was previously undefined (different # than defined and empty). # # This macro is needed until we can rely on Autoconf 2.62, since earlier # versions of m4sugar mistakenly expanded SEPARATOR but not STRING. m4_define([lt_append], [m4_define([$1], m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) # lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) # ---------------------------------------------------------- # Produce a SEP delimited list of all paired combinations of elements of # PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list # has the form PREFIXmINFIXSUFFIXn. # Needed until we can rely on m4_combine added in Autoconf 2.62. m4_define([lt_combine], [m4_if(m4_eval([$# > 3]), [1], [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl [[m4_foreach([_Lt_prefix], [$2], [m4_foreach([_Lt_suffix], ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) # lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) # ----------------------------------------------------------------------- # Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited # by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. m4_define([lt_if_append_uniq], [m4_ifdef([$1], [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], [lt_append([$1], [$2], [$3])$4], [$5])], [lt_append([$1], [$2], [$3])$4])]) # lt_dict_add(DICT, KEY, VALUE) # ----------------------------- m4_define([lt_dict_add], [m4_define([$1($2)], [$3])]) # lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) # -------------------------------------------- m4_define([lt_dict_add_subkey], [m4_define([$1($2:$3)], [$4])]) # lt_dict_fetch(DICT, KEY, [SUBKEY]) # ---------------------------------- m4_define([lt_dict_fetch], [m4_ifval([$3], m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) # lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) # ----------------------------------------------------------------- m4_define([lt_if_dict_fetch], [m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], [$5], [$6])]) # lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) # -------------------------------------------------------------- m4_define([lt_dict_filter], [m4_if([$5], [], [], [lt_join(m4_quote(m4_default([$4], [[, ]])), lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl ]) libtorrent-0.16.11/scripts/rak_compiler.m40000644000000000000000000000261115175073411014077 AC_DEFUN([RAK_CHECK_CFLAGS], [ AC_MSG_CHECKING([for user-defined CFLAGS]) if test "$CFLAGS" = ""; then unset CFLAGS AC_MSG_RESULT([undefined]) else AC_MSG_RESULT([user-defined "$CFLAGS"]) fi ]) AC_DEFUN([RAK_CHECK_CXXFLAGS], [ AC_MSG_CHECKING([for user-defined CXXFLAGS]) if test "$CXXFLAGS" = ""; then unset CXXFLAGS AC_MSG_RESULT([undefined]) else AC_MSG_RESULT([user-defined "$CXXFLAGS"]) fi ]) AC_DEFUN([RAK_ENABLE_DEBUG], [ AC_ARG_ENABLE(debug, AS_HELP_STRING([--enable-debug],[enable debug information [[default=yes]]]), [ if test "$enableval" = "yes"; then CXXFLAGS="$CXXFLAGS -g -DDEBUG" else CXXFLAGS="$CXXFLAGS -DNDEBUG" fi ],[ CXXFLAGS="$CXXFLAGS -g -DDEBUG" ]) ]) AC_DEFUN([RAK_ENABLE_WERROR], [ AC_ARG_ENABLE(werror, AS_HELP_STRING([--enable-werror],[enable the -Werror and -Wall flags [[default -Wall only]]]), [ if test "$enableval" = "yes"; then CXXFLAGS="$CXXFLAGS -Werror -Wall" fi ],[ CXXFLAGS="$CXXFLAGS -Wall" ]) ]) AC_DEFUN([RAK_ENABLE_EXTRA_DEBUG], [ AC_ARG_ENABLE(extra-debug, AS_HELP_STRING([--enable-extra-debug],[enable extra debugging checks [[default=no]]]), [ if test "$enableval" = "yes"; then AC_DEFINE(USE_EXTRA_DEBUG, 1, Enable extra debugging checks.) fi ]) ]) libtorrent-0.16.11/scripts/check_atomic.m40000644000000000000000000000243115175073411014041 # Some versions of gcc/libstdc++ require linking with -latomic if # using the C++ atomic library. # Copyright (c) 2015-2016 Tim Kosse # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. m4_define([_CHECK_ATOMIC_testbody], [[ #include #include int main() { std::atomic a{}; int64_t v = 5; int64_t r = a.fetch_add(v); return static_cast(r); } ]]) AC_DEFUN([CHECK_ATOMIC], [ AC_LANG_PUSH(C++) AC_MSG_CHECKING([whether std::atomic can be used without link library]) AC_LINK_IFELSE([AC_LANG_SOURCE([_CHECK_ATOMIC_testbody])],[ AC_MSG_RESULT([yes]) ],[ AC_MSG_RESULT([no]) AC_MSG_CHECKING([whether std::atomic needs -latomic]) OLD_LIBS="$LIBS" LIBS="$LIBS -latomic" AC_LINK_IFELSE([AC_LANG_SOURCE([_CHECK_ATOMIC_testbody])],[ AC_MSG_RESULT([yes]) ],[ AC_MSG_RESULT([no]) AC_MSG_FAILURE([cannot figure out how to use std::atomic]) ]) LIBS="$OLD_LIBS" ATOMIC_LIBS="-latomic" ]) AC_LANG_POP AC_SUBST([ATOMIC_LIBS]) ]) libtorrent-0.16.11/scripts/ax_execinfo.m40000644000000000000000000000476115175073411013730 # =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_execinfo.html # =========================================================================== # # SYNOPSIS # # AX_EXECINFO([ACTION-IF-EXECINFO-H-IS-FOUND], [ACTION-IF-EXECINFO-H-IS-NOT-FOUND], [ADDITIONAL-TYPES-LIST]) # # DESCRIPTION # # Checks for execinfo.h header and if the len parameter/return type can be # found from a list, also define backtrace_size_t to that type. # # By default the list of types to try contains int and size_t, but should # some yet undiscovered system use e.g. unsigned, the 3rd argument can be # used for extensions. I'd like to hear of further suggestions. # # Executes ACTION-IF-EXECINFO-H-IS-FOUND when present and the execinfo.h # header is found or ACTION-IF-EXECINFO-H-IS-NOT-FOUND in case the header # seems unavailable. # # Also adds -lexecinfo to LIBS on BSD if needed. # # LICENSE # # Copyright (c) 2014 Thomas Jahns # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 2 AC_DEFUN([AX_EXECINFO], [AC_CHECK_HEADERS([execinfo.h]) AS_IF([test x"$ac_cv_header_execinfo_h" = xyes], [AC_CACHE_CHECK([size parameter type for backtrace()], [ax_cv_proto_backtrace_type], [AC_LANG_PUSH([C]) for ax_cv_proto_backtrace_type in size_t int m4_ifnblank([$3],[$3 ])none; do AS_IF([test "${ax_cv_proto_backtrace_type}" = none], [ax_cv_proto_backtrace_type= ; break]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([ #include extern ${ax_cv_proto_backtrace_type} backtrace(void **addrlist, ${ax_cv_proto_backtrace_type} len); char **backtrace_symbols(void *const *buffer, ${ax_cv_proto_backtrace_type} size); ])], [break]) done AC_LANG_POP([C])])]) AS_IF([test x${ax_cv_proto_backtrace_type} != x], [AC_DEFINE_UNQUOTED([backtrace_size_t], [$ax_cv_proto_backtrace_type], [Defined to return type of backtrace().])]) AC_SEARCH_LIBS([backtrace],[execinfo]) AS_IF([test x"${ax_cv_proto_backtrace_type}" != x -a x"$ac_cv_header_execinfo_h" = xyes -a x"$ac_cv_search_backtrace" != xno], [AC_DEFINE([HAVE_BACKTRACE],[1], [Defined if backtrace() could be fully identified.]) ]m4_ifnblank([$1],[$1 ]),m4_ifnblank([$2],[$2 ]))]) dnl dnl Local Variables: dnl mode: autoconf dnl End: dnl libtorrent-0.16.11/scripts/attributes.m40000644000000000000000000000255215175073411013622 # Functions to check for attributes support in compiler AC_DEFUN([CC_ATTRIBUTE_INTERNAL], [ AC_CACHE_CHECK([if compiler supports __attribute__((visibility("internal")))], [cc_cv_attribute_internal], [AC_COMPILE_IFELSE([AC_LANG_SOURCE([ void __attribute__((visibility("internal"))) internal_function() { } ])], [cc_cv_attribute_internal=yes], [cc_cv_attribute_internal=no]) ]) if test "x$cc_cv_attribute_internal" = "xyes"; then AC_DEFINE([SUPPORT_ATTRIBUTE_INTERNAL], 1, [Define this if the compiler supports the internal visibility attribute]) $1 else true $2 fi ]) AC_DEFUN([CC_ATTRIBUTE_VISIBILITY], [ AC_LANG_PUSH(C++) tmp_CXXFLAGS=$CXXFLAGS CXXFLAGS="$CXXFLAGS -fvisibility=hidden" AC_CACHE_CHECK([if compiler supports __attribute__((visibility("default")))], [cc_cv_attribute_visibility], [AC_COMPILE_IFELSE([AC_LANG_SOURCE([ void __attribute__((visibility("default"))) visibility_function() { } ])], [cc_cv_attribute_visibility=yes], [cc_cv_attribute_visibility=no]) ]) CXXFLAGS=$tmp_CXXFLAGS AC_LANG_POP(C++) if test "x$cc_cv_attribute_visibility" = "xyes"; then AC_DEFINE([SUPPORT_ATTRIBUTE_VISIBILITY], 1, [Define this if the compiler supports the visibility attributes.]) CXXFLAGS="$CXXFLAGS -fvisibility=hidden" $1 else true $2 fi ]) libtorrent-0.16.11/scripts/libtool.m40000644000000000000000000112755115175073420013110 # libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # # Copyright (C) 1996-2001, 2003-2019, 2021-2022 Free Software # Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. m4_define([_LT_COPYING], [dnl # Copyright (C) 2014 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of of the License, or # (at your option) any later version. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program or library that is built # using GNU Libtool, you may include this file under the same # distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ]) # serial 59 LT_INIT # LT_PREREQ(VERSION) # ------------------ # Complain and exit if this libtool version is less that VERSION. m4_defun([LT_PREREQ], [m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, [m4_default([$3], [m4_fatal([Libtool version $1 or higher is required], 63)])], [$2])]) # _LT_CHECK_BUILDDIR # ------------------ # Complain if the absolute build directory name contains unusual characters m4_defun([_LT_CHECK_BUILDDIR], [case `pwd` in *\ * | *\ *) AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; esac ]) # LT_INIT([OPTIONS]) # ------------------ AC_DEFUN([LT_INIT], [AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl AC_BEFORE([$0], [LT_LANG])dnl AC_BEFORE([$0], [LT_OUTPUT])dnl AC_BEFORE([$0], [LTDL_INIT])dnl m4_require([_LT_CHECK_BUILDDIR])dnl dnl Autoconf doesn't catch unexpanded LT_ macros by default: m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 dnl unless we require an AC_DEFUNed macro: AC_REQUIRE([LTOPTIONS_VERSION])dnl AC_REQUIRE([LTSUGAR_VERSION])dnl AC_REQUIRE([LTVERSION_VERSION])dnl AC_REQUIRE([LTOBSOLETE_VERSION])dnl m4_require([_LT_PROG_LTMAIN])dnl _LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) dnl Parse OPTIONS _LT_SET_OPTIONS([$0], [$1]) # This can be used to rebuild libtool when needed LIBTOOL_DEPS=$ltmain # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' AC_SUBST(LIBTOOL)dnl _LT_SETUP # Only expand once: m4_define([LT_INIT]) ])# LT_INIT # Old names: AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PROG_LIBTOOL], []) dnl AC_DEFUN([AM_PROG_LIBTOOL], []) # _LT_PREPARE_CC_BASENAME # ----------------------- m4_defun([_LT_PREPARE_CC_BASENAME], [ # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. func_cc_basename () { for cc_temp in @S|@*""; do case $cc_temp in compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; \-*) ;; *) break;; esac done func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` } ])# _LT_PREPARE_CC_BASENAME # _LT_CC_BASENAME(CC) # ------------------- # It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME, # but that macro is also expanded into generated libtool script, which # arranges for $SED and $ECHO to be set by different means. m4_defun([_LT_CC_BASENAME], [m4_require([_LT_PREPARE_CC_BASENAME])dnl AC_REQUIRE([_LT_DECL_SED])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl func_cc_basename $1 cc_basename=$func_cc_basename_result ]) # _LT_FILEUTILS_DEFAULTS # ---------------------- # It is okay to use these file commands and assume they have been set # sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'. m4_defun([_LT_FILEUTILS_DEFAULTS], [: ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} ])# _LT_FILEUTILS_DEFAULTS # _LT_SETUP # --------- m4_defun([_LT_SETUP], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl _LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl dnl _LT_DECL([], [host_alias], [0], [The host system])dnl _LT_DECL([], [host], [0])dnl _LT_DECL([], [host_os], [0])dnl dnl _LT_DECL([], [build_alias], [0], [The build system])dnl _LT_DECL([], [build], [0])dnl _LT_DECL([], [build_os], [0])dnl dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl dnl AC_REQUIRE([AC_PROG_LN_S])dnl test -z "$LN_S" && LN_S="ln -s" _LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl dnl AC_REQUIRE([LT_CMD_MAX_LEN])dnl _LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl _LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl m4_require([_LT_CMD_RELOAD])dnl m4_require([_LT_DECL_FILECMD])dnl m4_require([_LT_CHECK_MAGIC_METHOD])dnl m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl m4_require([_LT_CMD_OLD_ARCHIVE])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_WITH_SYSROOT])dnl m4_require([_LT_CMD_TRUNCATE])dnl _LT_CONFIG_LIBTOOL_INIT([ # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi ]) if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi _LT_CHECK_OBJDIR m4_require([_LT_TAG_COMPILER])dnl case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a '.a' archive for static linking (except MSVC and # ICC, which need '.lib'). libext=a with_gnu_ld=$lt_cv_prog_gnu_ld old_CC=$CC old_CFLAGS=$CFLAGS # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o _LT_CC_BASENAME([$compiler]) # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then _LT_PATH_MAGIC fi ;; esac # Use C for the default configuration in the libtool script LT_SUPPORTED_TAG([CC]) _LT_LANG_C_CONFIG _LT_LANG_DEFAULT_CONFIG _LT_CONFIG_COMMANDS ])# _LT_SETUP # _LT_PREPARE_SED_QUOTE_VARS # -------------------------- # Define a few sed substitution that help us do robust quoting. m4_defun([_LT_PREPARE_SED_QUOTE_VARS], [# Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\([["`\\]]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ]) # _LT_PROG_LTMAIN # --------------- # Note that this code is called both from 'configure', and 'config.status' # now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, # 'config.status' has no value for ac_aux_dir unless we are using Automake, # so we pass a copy along to make sure it has a sensible value anyway. m4_defun([_LT_PROG_LTMAIN], [m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl _LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) ltmain=$ac_aux_dir/ltmain.sh ])# _LT_PROG_LTMAIN ## ------------------------------------- ## ## Accumulate code for creating libtool. ## ## ------------------------------------- ## # So that we can recreate a full libtool script including additional # tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS # in macros and then make a single call at the end using the 'libtool' # label. # _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) # ---------------------------------------- # Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL_INIT], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_INIT], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_INIT]) # _LT_CONFIG_LIBTOOL([COMMANDS]) # ------------------------------ # Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) # _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) # ----------------------------------------------------- m4_defun([_LT_CONFIG_SAVE_COMMANDS], [_LT_CONFIG_LIBTOOL([$1]) _LT_CONFIG_LIBTOOL_INIT([$2]) ]) # _LT_FORMAT_COMMENT([COMMENT]) # ----------------------------- # Add leading comment marks to the start of each line, and a trailing # full-stop to the whole comment if one is not present already. m4_define([_LT_FORMAT_COMMENT], [m4_ifval([$1], [ m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) )]) ## ------------------------ ## ## FIXME: Eliminate VARNAME ## ## ------------------------ ## # _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) # ------------------------------------------------------------------- # CONFIGNAME is the name given to the value in the libtool script. # VARNAME is the (base) name used in the configure script. # VALUE may be 0, 1 or 2 for a computed quote escaped value based on # VARNAME. Any other value will be used directly. m4_define([_LT_DECL], [lt_if_append_uniq([lt_decl_varnames], [$2], [, ], [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], [m4_ifval([$1], [$1], [$2])]) lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) m4_ifval([$4], [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) lt_dict_add_subkey([lt_decl_dict], [$2], [tagged?], [m4_ifval([$5], [yes], [no])])]) ]) # _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) # -------------------------------------------------------- m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) # lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_tag_varnames], [_lt_decl_filter([tagged?], [yes], $@)]) # _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) # --------------------------------------------------------- m4_define([_lt_decl_filter], [m4_case([$#], [0], [m4_fatal([$0: too few arguments: $#])], [1], [m4_fatal([$0: too few arguments: $#: $1])], [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], [lt_dict_filter([lt_decl_dict], $@)])[]dnl ]) # lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) # -------------------------------------------------- m4_define([lt_decl_quote_varnames], [_lt_decl_filter([value], [1], $@)]) # lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_dquote_varnames], [_lt_decl_filter([value], [2], $@)]) # lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_varnames_tagged], [m4_assert([$# <= 2])dnl _$0(m4_quote(m4_default([$1], [[, ]])), m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) m4_define([_lt_decl_varnames_tagged], [m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) # lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_all_varnames], [_$0(m4_quote(m4_default([$1], [[, ]])), m4_if([$2], [], m4_quote(lt_decl_varnames), m4_quote(m4_shift($@))))[]dnl ]) m4_define([_lt_decl_all_varnames], [lt_join($@, lt_decl_varnames_tagged([$1], lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl ]) # _LT_CONFIG_STATUS_DECLARE([VARNAME]) # ------------------------------------ # Quote a variable value, and forward it to 'config.status' so that its # declaration there will have the same value as in 'configure'. VARNAME # must have a single quote delimited value for this to work. m4_define([_LT_CONFIG_STATUS_DECLARE], [$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) # _LT_CONFIG_STATUS_DECLARATIONS # ------------------------------ # We delimit libtool config variables with single quotes, so when # we write them to config.status, we have to be sure to quote all # embedded single quotes properly. In configure, this macro expands # each variable declared with _LT_DECL (and _LT_TAGDECL) into: # # ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], [m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAGS # ---------------- # Output comment and list of tags supported by the script m4_defun([_LT_LIBTOOL_TAGS], [_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl available_tags='_LT_TAGS'dnl ]) # _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) # ----------------------------------- # Extract the dictionary values for VARNAME (optionally with TAG) and # expand to a commented shell variable setting: # # # Some comment about what VAR is for. # visible_name=$lt_internal_name m4_define([_LT_LIBTOOL_DECLARE], [_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [description])))[]dnl m4_pushdef([_libtool_name], m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), [0], [_libtool_name=[$]$1], [1], [_libtool_name=$lt_[]$1], [2], [_libtool_name=$lt_[]$1], [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl ]) # _LT_LIBTOOL_CONFIG_VARS # ----------------------- # Produce commented declarations of non-tagged libtool config variables # suitable for insertion in the LIBTOOL CONFIG section of the 'libtool' # script. Tagged libtool config variables (even for the LIBTOOL CONFIG # section) are produced by _LT_LIBTOOL_TAG_VARS. m4_defun([_LT_LIBTOOL_CONFIG_VARS], [m4_foreach([_lt_var], m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAG_VARS(TAG) # ------------------------- m4_define([_LT_LIBTOOL_TAG_VARS], [m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) # _LT_TAGVAR(VARNAME, [TAGNAME]) # ------------------------------ m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) # _LT_CONFIG_COMMANDS # ------------------- # Send accumulated output to $CONFIG_STATUS. Thanks to the lists of # variables for single and double quote escaping we saved from calls # to _LT_DECL, we can put quote escaped variables declarations # into 'config.status', and then the shell code to quote escape them in # for loops in 'config.status'. Finally, any additional code accumulated # from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. m4_defun([_LT_CONFIG_COMMANDS], [AC_PROVIDE_IFELSE([LT_OUTPUT], dnl If the libtool generation code has been placed in $CONFIG_LT, dnl instead of duplicating it all over again into config.status, dnl then we will have config.status run $CONFIG_LT later, so it dnl needs to know what name is stored there: [AC_CONFIG_COMMANDS([libtool], [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], dnl If the libtool generation code is destined for config.status, dnl expand the accumulated commands and init code now: [AC_CONFIG_COMMANDS([libtool], [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) ])#_LT_CONFIG_COMMANDS # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], [ # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' _LT_CONFIG_STATUS_DECLARATIONS LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$[]1 _LTECHO_EOF' } # Quote evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_quote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_dquote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done _LT_OUTPUT_LIBTOOL_INIT ]) # _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) # ------------------------------------ # Generate a child script FILE with all initialization necessary to # reuse the environment learned by the parent script, and make the # file executable. If COMMENT is supplied, it is inserted after the # '#!' sequence but before initialization text begins. After this # macro, additional text can be appended to FILE to form the body of # the child script. The macro ends with non-zero status if the # file could not be fully written (such as if the disk is full). m4_ifdef([AS_INIT_GENERATED], [m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], [m4_defun([_LT_GENERATED_FILE_INIT], [m4_require([AS_PREPARE])]dnl [m4_pushdef([AS_MESSAGE_LOG_FD])]dnl [lt_write_fail=0 cat >$1 <<_ASEOF || lt_write_fail=1 #! $SHELL # Generated by $as_me. $2 SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$1 <<\_ASEOF || lt_write_fail=1 AS_SHELL_SANITIZE _AS_PREPARE exec AS_MESSAGE_FD>&1 _ASEOF test 0 = "$lt_write_fail" && chmod +x $1[]dnl m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT # LT_OUTPUT # --------- # This macro allows early generation of the libtool script (before # AC_OUTPUT is called), incase it is used in configure for compilation # tests. AC_DEFUN([LT_OUTPUT], [: ${CONFIG_LT=./config.lt} AC_MSG_NOTICE([creating $CONFIG_LT]) _LT_GENERATED_FILE_INIT(["$CONFIG_LT"], [# Run this file to recreate a libtool stub with the current configuration.]) cat >>"$CONFIG_LT" <<\_LTEOF lt_cl_silent=false exec AS_MESSAGE_LOG_FD>>config.log { echo AS_BOX([Running $as_me.]) } >&AS_MESSAGE_LOG_FD lt_cl_help="\ '$as_me' creates a local libtool stub from the current configuration, for use in further configure time tests before the real libtool is generated. Usage: $[0] [[OPTIONS]] -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files Report bugs to ." lt_cl_version="\ m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) configured by $[0], generated by m4_PACKAGE_STRING. Copyright (C) 2011 Free Software Foundation, Inc. This config.lt script is free software; the Free Software Foundation gives unlimited permision to copy, distribute and modify it." while test 0 != $[#] do case $[1] in --version | --v* | -V ) echo "$lt_cl_version"; exit 0 ;; --help | --h* | -h ) echo "$lt_cl_help"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --quiet | --q* | --silent | --s* | -q ) lt_cl_silent=: ;; -*) AC_MSG_ERROR([unrecognized option: $[1] Try '$[0] --help' for more information.]) ;; *) AC_MSG_ERROR([unrecognized argument: $[1] Try '$[0] --help' for more information.]) ;; esac shift done if $lt_cl_silent; then exec AS_MESSAGE_FD>/dev/null fi _LTEOF cat >>"$CONFIG_LT" <<_LTEOF _LT_OUTPUT_LIBTOOL_COMMANDS_INIT _LTEOF cat >>"$CONFIG_LT" <<\_LTEOF AC_MSG_NOTICE([creating $ofile]) _LT_OUTPUT_LIBTOOL_COMMANDS AS_EXIT(0) _LTEOF chmod +x "$CONFIG_LT" # configure is writing to config.log, but config.lt does its own redirection, # appending to config.log, which fails on DOS, as config.log is still kept # open by configure. Here we exec the FD to /dev/null, effectively closing # config.log, so it can be properly (re)opened and appended to by config.lt. lt_cl_success=: test yes = "$silent" && lt_config_lt_args="$lt_config_lt_args --quiet" exec AS_MESSAGE_LOG_FD>/dev/null $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false exec AS_MESSAGE_LOG_FD>>config.log $lt_cl_success || AS_EXIT(1) ])# LT_OUTPUT # _LT_CONFIG(TAG) # --------------- # If TAG is the built-in tag, create an initial libtool script with a # default configuration from the untagged config vars. Otherwise add code # to config.status for appending the configuration named by TAG from the # matching tagged config vars. m4_defun([_LT_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_CONFIG_SAVE_COMMANDS([ m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl m4_if(_LT_TAG, [C], [ # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi cfgfile=${ofile}T trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # Generated automatically by $as_me ($PACKAGE) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # Provide generalized library-building support services. # Written by Gordon Matzigkeit, 1996 _LT_COPYING _LT_LIBTOOL_TAGS # Configured defaults for sys_lib_dlsearch_path munging. : \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} # ### BEGIN LIBTOOL CONFIG _LT_LIBTOOL_CONFIG_VARS _LT_LIBTOOL_TAG_VARS # ### END LIBTOOL CONFIG _LT_EOF cat <<'_LT_EOF' >> "$cfgfile" # ### BEGIN FUNCTIONS SHARED WITH CONFIGURE _LT_PREPARE_MUNGE_PATH_LIST _LT_PREPARE_CC_BASENAME # ### END FUNCTIONS SHARED WITH CONFIGURE _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac _LT_PROG_LTMAIN # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? $SED '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ], [cat <<_LT_EOF >> "$ofile" dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded dnl in a comment (ie after a #). # ### BEGIN LIBTOOL TAG CONFIG: $1 _LT_LIBTOOL_TAG_VARS(_LT_TAG) # ### END LIBTOOL TAG CONFIG: $1 _LT_EOF ])dnl /m4_if ], [m4_if([$1], [], [ PACKAGE='$PACKAGE' VERSION='$VERSION' RM='$RM' ofile='$ofile'], []) ])dnl /_LT_CONFIG_SAVE_COMMANDS ])# _LT_CONFIG # LT_SUPPORTED_TAG(TAG) # --------------------- # Trace this macro to discover what tags are supported by the libtool # --tag option, using: # autoconf --trace 'LT_SUPPORTED_TAG:$1' AC_DEFUN([LT_SUPPORTED_TAG], []) # C support is built-in for now m4_define([_LT_LANG_C_enabled], []) m4_define([_LT_TAGS], []) # LT_LANG(LANG) # ------------- # Enable libtool support for the given language if not already enabled. AC_DEFUN([LT_LANG], [AC_BEFORE([$0], [LT_OUTPUT])dnl m4_case([$1], [C], [_LT_LANG(C)], [C++], [_LT_LANG(CXX)], [Go], [_LT_LANG(GO)], [Java], [_LT_LANG(GCJ)], [Fortran 77], [_LT_LANG(F77)], [Fortran], [_LT_LANG(FC)], [Windows Resource], [_LT_LANG(RC)], [m4_ifdef([_LT_LANG_]$1[_CONFIG], [_LT_LANG($1)], [m4_fatal([$0: unsupported language: "$1"])])])dnl ])# LT_LANG # _LT_LANG(LANGNAME) # ------------------ m4_defun([_LT_LANG], [m4_ifdef([_LT_LANG_]$1[_enabled], [], [LT_SUPPORTED_TAG([$1])dnl m4_append([_LT_TAGS], [$1 ])dnl m4_define([_LT_LANG_]$1[_enabled], [])dnl _LT_LANG_$1_CONFIG($1)])dnl ])# _LT_LANG m4_ifndef([AC_PROG_GO], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_GO. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_GO], [AC_LANG_PUSH(Go)dnl AC_ARG_VAR([GOC], [Go compiler command])dnl AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl _AC_ARG_VAR_LDFLAGS()dnl AC_CHECK_TOOL(GOC, gccgo) if test -z "$GOC"; then if test -n "$ac_tool_prefix"; then AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) fi fi if test -z "$GOC"; then AC_CHECK_PROG(GOC, gccgo, gccgo, false) fi ])#m4_defun ])#m4_ifndef # _LT_LANG_DEFAULT_CONFIG # ----------------------- m4_defun([_LT_LANG_DEFAULT_CONFIG], [AC_PROVIDE_IFELSE([AC_PROG_CXX], [LT_LANG(CXX)], [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) AC_PROVIDE_IFELSE([AC_PROG_F77], [LT_LANG(F77)], [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) AC_PROVIDE_IFELSE([AC_PROG_FC], [LT_LANG(FC)], [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal dnl pulling things in needlessly. AC_PROVIDE_IFELSE([AC_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([LT_PROG_GCJ], [LT_LANG(GCJ)], [m4_ifdef([AC_PROG_GCJ], [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([A][M_PROG_GCJ], [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([LT_PROG_GCJ], [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) AC_PROVIDE_IFELSE([AC_PROG_GO], [LT_LANG(GO)], [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) AC_PROVIDE_IFELSE([LT_PROG_RC], [LT_LANG(RC)], [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) ])# _LT_LANG_DEFAULT_CONFIG # Obsolete macros: AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_CXX], []) dnl AC_DEFUN([AC_LIBTOOL_F77], []) dnl AC_DEFUN([AC_LIBTOOL_FC], []) dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) dnl AC_DEFUN([AC_LIBTOOL_RC], []) # _LT_TAG_COMPILER # ---------------- m4_defun([_LT_TAG_COMPILER], [AC_REQUIRE([AC_PROG_CC])dnl _LT_DECL([LTCC], [CC], [1], [A C compiler])dnl _LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl _LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl _LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC ])# _LT_TAG_COMPILER # _LT_COMPILER_BOILERPLATE # ------------------------ # Check for compiler boilerplate output or warnings with # the simple compiler test code. m4_defun([_LT_COMPILER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ])# _LT_COMPILER_BOILERPLATE # _LT_LINKER_BOILERPLATE # ---------------------- # Check for linker boilerplate output or warnings with # the simple link test code. m4_defun([_LT_LINKER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ])# _LT_LINKER_BOILERPLATE # _LT_REQUIRED_DARWIN_CHECKS # ------------------------- m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ case $host_os in rhapsody* | darwin*) AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) AC_CHECK_TOOL([LIPO], [lipo], [:]) AC_CHECK_TOOL([OTOOL], [otool], [:]) AC_CHECK_TOOL([OTOOL64], [otool64], [:]) _LT_DECL([], [DSYMUTIL], [1], [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) _LT_DECL([], [NMEDIT], [1], [Tool to change global to local symbols on Mac OS X]) _LT_DECL([], [LIPO], [1], [Tool to manipulate fat objects and archives on Mac OS X]) _LT_DECL([], [OTOOL], [1], [ldd/readelf like tool for Mach-O binaries on Mac OS X]) _LT_DECL([], [OTOOL64], [1], [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], [lt_cv_apple_cc_single_mod=no if test -z "$LT_MULTI_MODULE"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test 0 = "$_lt_result"; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -rf libconftest.dylib* rm -f conftest.* fi]) AC_CACHE_CHECK([for -exported_symbols_list linker flag], [lt_cv_ld_exported_symbols_list], [lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [lt_cv_ld_exported_symbols_list=yes], [lt_cv_ld_exported_symbols_list=no]) LDFLAGS=$save_LDFLAGS ]) AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], [lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD echo "$AR $AR_FLAGS libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD $AR $AR_FLAGS libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then lt_cv_ld_force_load=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM ]) case $host_os in rhapsody* | darwin1.[[012]]) _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; darwin*) case $MACOSX_DEPLOYMENT_TARGET,$host in 10.[[012]],*|,*powerpc*-darwin[[5-8]]*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; *) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test yes = "$lt_cv_apple_cc_single_mod"; then _lt_dar_single_mod='$single_module' fi if test yes = "$lt_cv_ld_exported_symbols_list"; then _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' fi if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac ]) # _LT_DARWIN_LINKER_FEATURES([TAG]) # --------------------------------- # Checks for linker and compiler features on darwin m4_defun([_LT_DARWIN_LINKER_FEATURES], [ m4_require([_LT_REQUIRED_DARWIN_CHECKS]) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported if test yes = "$lt_cv_ld_force_load"; then _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) else _LT_TAGVAR(whole_archive_flag_spec, $1)='' fi _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined case $cc_basename in ifort*|nagfor*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test yes = "$_lt_dar_can_shared"; then output_verbose_link_cmd=func_echo_all _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" _LT_TAGVAR(archive_expsym_cmds, $1)="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" _LT_TAGVAR(module_expsym_cmds, $1)="$SED -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" m4_if([$1], [CXX], [ if test yes != "$lt_cv_apple_cc_single_mod"; then _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" _LT_TAGVAR(archive_expsym_cmds, $1)="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" fi ],[]) else _LT_TAGVAR(ld_shlibs, $1)=no fi ]) # _LT_SYS_MODULE_PATH_AIX([TAGNAME]) # ---------------------------------- # Links a minimal program and checks the executable # for the system default hardcoded library path. In most cases, # this is /usr/lib:/lib, but when the MPI compilers are used # the location of the communication and MPI libs are included too. # If we don't find anything, use the default library path according # to the aix ld manual. # Store the results from the different compilers for each TAGNAME. # Allow to override them for all tags through lt_cv_aix_libpath. m4_defun([_LT_SYS_MODULE_PATH_AIX], [m4_require([_LT_DECL_SED])dnl if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ lt_aix_libpath_sed='[ /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }]' _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi],[]) if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib fi ]) aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) fi ])# _LT_SYS_MODULE_PATH_AIX # _LT_SHELL_INIT(ARG) # ------------------- m4_define([_LT_SHELL_INIT], [m4_divert_text([M4SH-INIT], [$1 ])])# _LT_SHELL_INIT # _LT_PROG_ECHO_BACKSLASH # ----------------------- # Find how we can fake an echo command that does not interpret backslash. # In particular, with Autoconf 2.60 or later we add some code to the start # of the generated configure script that will find a shell with a builtin # printf (that we can use as an echo command). m4_defun([_LT_PROG_ECHO_BACKSLASH], [ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO AC_MSG_CHECKING([how to print strings]) # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $[]1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } case $ECHO in printf*) AC_MSG_RESULT([printf]) ;; print*) AC_MSG_RESULT([print -r]) ;; *) AC_MSG_RESULT([cat]) ;; esac m4_ifdef([_AS_DETECT_SUGGESTED], [_AS_DETECT_SUGGESTED([ test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test "X`printf %s $ECHO`" = "X$ECHO" \ || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) _LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) _LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) ])# _LT_PROG_ECHO_BACKSLASH # _LT_WITH_SYSROOT # ---------------- AC_DEFUN([_LT_WITH_SYSROOT], [m4_require([_LT_DECL_SED])dnl AC_MSG_CHECKING([for sysroot]) AC_ARG_WITH([sysroot], [AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@], [Search for dependent libraries within DIR (or the compiler's sysroot if not specified).])], [], [with_sysroot=no]) dnl lt_sysroot will always be passed unquoted. We quote it here dnl in case the user passed a directory name. lt_sysroot= case $with_sysroot in #( yes) if test yes = "$GCC"; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | $SED -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) AC_MSG_RESULT([$with_sysroot]) AC_MSG_ERROR([The sysroot must be an absolute path.]) ;; esac AC_MSG_RESULT([${lt_sysroot:-no}]) _LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl [dependent libraries, and where our libraries should be installed.])]) # _LT_ENABLE_LOCK # --------------- m4_defun([_LT_ENABLE_LOCK], [AC_ARG_ENABLE([libtool-lock], [AS_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) test no = "$enable_libtool_lock" || enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out what ABI is being produced by ac_compile, and set mode # options accordingly. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `$FILECMD conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE=32 ;; *ELF-64*) HPUX_IA64_MODE=64 ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then if test yes = "$lt_cv_prog_gnu_ld"; then case `$FILECMD conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `$FILECMD conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; mips64*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then emul=elf case `$FILECMD conftest.$ac_objext` in *32-bit*) emul="${emul}32" ;; *64-bit*) emul="${emul}64" ;; esac case `$FILECMD conftest.$ac_objext` in *MSB*) emul="${emul}btsmip" ;; *LSB*) emul="${emul}ltsmip" ;; esac case `$FILECMD conftest.$ac_objext` in *N32*) emul="${emul}n32" ;; esac LD="${LD-ld} -m $emul" fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. Note that the listed cases only cover the # situations where additional linker options are needed (such as when # doing 32-bit compilation for a host where ld defaults to 64-bit, or # vice versa); the common cases where no linker options are needed do # not appear in the list. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `$FILECMD conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) case `$FILECMD conftest.o` in *x86-64*) LD="${LD-ld} -m elf32_x86_64" ;; *) LD="${LD-ld} -m elf_i386" ;; esac ;; powerpc64le-*linux*) LD="${LD-ld} -m elf32lppclinux" ;; powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; powerpcle-*linux*) LD="${LD-ld} -m elf64lppc" ;; powerpc-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS=$CFLAGS CFLAGS="$CFLAGS -belf" AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, [AC_LANG_PUSH(C) AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) AC_LANG_POP]) if test yes != "$lt_cv_cc_needs_belf"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS=$SAVE_CFLAGS fi ;; *-*solaris*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `$FILECMD conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*|x86_64-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD=${LD-ld}_sol2 fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks=$enable_libtool_lock ])# _LT_ENABLE_LOCK # _LT_PROG_AR # ----------- m4_defun([_LT_PROG_AR], [AC_CHECK_TOOLS(AR, [ar], false) : ${AR=ar} _LT_DECL([], [AR], [1], [The archiver]) # Use ARFLAGS variable as AR's operation code to sync the variable naming with # Automake. If both AR_FLAGS and ARFLAGS are specified, AR_FLAGS should have # higher priority because thats what people were doing historically (setting # ARFLAGS for automake and AR_FLAGS for libtool). FIXME: Make the AR_FLAGS # variable obsoleted/removed. test ${AR_FLAGS+y} || AR_FLAGS=${ARFLAGS-cr} lt_ar_flags=$AR_FLAGS _LT_DECL([], [lt_ar_flags], [0], [Flags to create an archive (by configure)]) # Make AR_FLAGS overridable by 'make ARFLAGS='. Don't try to run-time override # by AR_FLAGS because that was never working and AR_FLAGS is about to die. _LT_DECL([], [AR_FLAGS], [\@S|@{ARFLAGS-"\@S|@lt_ar_flags"}], [Flags to create an archive]) AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], [lt_cv_ar_at_file=no AC_COMPILE_IFELSE([AC_LANG_PROGRAM], [echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' AC_TRY_EVAL([lt_ar_try]) if test 0 -eq "$ac_status"; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a AC_TRY_EVAL([lt_ar_try]) if test 0 -ne "$ac_status"; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a ]) ]) if test no = "$lt_cv_ar_at_file"; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi _LT_DECL([], [archiver_list_spec], [1], [How to feed a file listing to the archiver]) ])# _LT_PROG_AR # _LT_CMD_OLD_ARCHIVE # ------------------- m4_defun([_LT_CMD_OLD_ARCHIVE], [_LT_PROG_AR AC_CHECK_TOOL(STRIP, strip, :) test -z "$STRIP" && STRIP=: _LT_DECL([], [STRIP], [1], [A symbol stripping program]) AC_CHECK_TOOL(RANLIB, ranlib, :) test -z "$RANLIB" && RANLIB=: _LT_DECL([], [RANLIB], [1], [Commands used to install an old-style archive]) # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in bitrig* | openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac _LT_DECL([], [old_postinstall_cmds], [2]) _LT_DECL([], [old_postuninstall_cmds], [2]) _LT_TAGDECL([], [old_archive_cmds], [2], [Commands used to build an old-style archive]) _LT_DECL([], [lock_old_archive_extraction], [0], [Whether to use a lock for old archive extraction]) ])# _LT_CMD_OLD_ARCHIVE # _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------------------- # Check whether the given compiler option works AC_DEFUN([_LT_COMPILER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$3" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi fi $RM conftest* ]) if test yes = "[$]$2"; then m4_if([$5], , :, [$5]) else m4_if([$6], , :, [$6]) fi ])# _LT_COMPILER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) # _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------- # Check whether the given linker option works AC_DEFUN([_LT_LINKER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $3" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&AS_MESSAGE_LOG_FD $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi else $2=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS ]) if test yes = "[$]$2"; then m4_if([$4], , :, [$4]) else m4_if([$5], , :, [$5]) fi ])# _LT_LINKER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) # LT_CMD_MAX_LEN #--------------- AC_DEFUN([LT_CMD_MAX_LEN], [AC_REQUIRE([AC_CANONICAL_HOST])dnl # find the maximum length of command line arguments AC_MSG_CHECKING([the maximum length of command line arguments]) AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl i=0 teststring=ABCD case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; bitrig* | darwin* | dragonfly* | freebsd* | midnightbsd* | netbsd* | openbsd*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | $SED 's/.*[[ ]]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len" && \ test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test X`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test 17 != "$i" # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac ]) if test -n "$lt_cv_sys_max_cmd_len"; then AC_MSG_RESULT($lt_cv_sys_max_cmd_len) else AC_MSG_RESULT(none) fi max_cmd_len=$lt_cv_sys_max_cmd_len _LT_DECL([], [max_cmd_len], [0], [What is the maximum length of a command?]) ])# LT_CMD_MAX_LEN # Old name: AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) # _LT_HEADER_DLFCN # ---------------- m4_defun([_LT_HEADER_DLFCN], [AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl ])# _LT_HEADER_DLFCN # _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, # ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) # ---------------------------------------------------------------- m4_defun([_LT_TRY_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test yes = "$cross_compiling"; then : [$4] else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF [#line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; }] _LT_EOF if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) $1 ;; x$lt_dlneed_uscore) $2 ;; x$lt_dlunknown|x*) $3 ;; esac else : # compilation failed $3 fi fi rm -fr conftest* ])# _LT_TRY_DLOPEN_SELF # LT_SYS_DLOPEN_SELF # ------------------ AC_DEFUN([LT_SYS_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test yes != "$enable_dlopen"; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen=load_add_on lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen=LoadLibrary lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen=dlopen lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[ lt_cv_dlopen=dyld lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ]) ;; tpf*) # Don't try to run any link tests for TPF. We know it's impossible # because TPF is a cross-compiler, and we know how we open DSOs. lt_cv_dlopen=dlopen lt_cv_dlopen_libs= lt_cv_dlopen_self=no ;; *) AC_CHECK_FUNC([shl_load], [lt_cv_dlopen=shl_load], [AC_CHECK_LIB([dld], [shl_load], [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld], [AC_CHECK_FUNC([dlopen], [lt_cv_dlopen=dlopen], [AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl], [AC_CHECK_LIB([svld], [dlopen], [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld], [AC_CHECK_LIB([dld], [dld_link], [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld]) ]) ]) ]) ]) ]) ;; esac if test no = "$lt_cv_dlopen"; then enable_dlopen=no else enable_dlopen=yes fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS=$CPPFLAGS test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS=$LDFLAGS wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS=$LIBS LIBS="$lt_cv_dlopen_libs $LIBS" AC_CACHE_CHECK([whether a program can dlopen itself], lt_cv_dlopen_self, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) ]) if test yes = "$lt_cv_dlopen_self"; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" AC_CACHE_CHECK([whether a statically linked program can dlopen itself], lt_cv_dlopen_self_static, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) ]) fi CPPFLAGS=$save_CPPFLAGS LDFLAGS=$save_LDFLAGS LIBS=$save_LIBS ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi _LT_DECL([dlopen_support], [enable_dlopen], [0], [Whether dlopen is supported]) _LT_DECL([dlopen_self], [enable_dlopen_self], [0], [Whether dlopen of programs is supported]) _LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], [Whether dlopen of statically linked programs is supported]) ])# LT_SYS_DLOPEN_SELF # Old name: AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) # _LT_COMPILER_C_O([TAGNAME]) # --------------------------- # Check to see if options -c and -o are simultaneously supported by compiler. # This macro does not hard code the compiler like AC_PROG_CC_C_O. m4_defun([_LT_COMPILER_C_O], [m4_require([_LT_DECL_SED])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes fi fi chmod u+w . 2>&AS_MESSAGE_LOG_FD $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* ]) _LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], [Does compiler simultaneously support -c and -o options?]) ])# _LT_COMPILER_C_O # _LT_COMPILER_FILE_LOCKS([TAGNAME]) # ---------------------------------- # Check to see if we can do hard links to lock some files if needed m4_defun([_LT_COMPILER_FILE_LOCKS], [m4_require([_LT_ENABLE_LOCK])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_COMPILER_C_O([$1]) hard_links=nottested if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then # do not overwrite the value of need_locks provided by the user AC_MSG_CHECKING([if we can lock with hard links]) hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no AC_MSG_RESULT([$hard_links]) if test no = "$hard_links"; then AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe]) need_locks=warn fi else need_locks=no fi _LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) ])# _LT_COMPILER_FILE_LOCKS # _LT_CHECK_OBJDIR # ---------------- m4_defun([_LT_CHECK_OBJDIR], [AC_CACHE_CHECK([for objdir], [lt_cv_objdir], [rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null]) objdir=$lt_cv_objdir _LT_DECL([], [objdir], [0], [The name of the directory that contains temporary libtool files])dnl m4_pattern_allow([LT_OBJDIR])dnl AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/", [Define to the sub-directory where libtool stores uninstalled libraries.]) ])# _LT_CHECK_OBJDIR # _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) # -------------------------------------- # Check hardcoding attributes. m4_defun([_LT_LINKER_HARDCODE_LIBPATH], [AC_MSG_CHECKING([how to hardcode library paths into programs]) _LT_TAGVAR(hardcode_action, $1)= if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || test -n "$_LT_TAGVAR(runpath_var, $1)" || test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then # We can hardcode non-existent directories. if test no != "$_LT_TAGVAR(hardcode_direct, $1)" && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" && test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then # Linking always hardcodes the temporary library directory. _LT_TAGVAR(hardcode_action, $1)=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. _LT_TAGVAR(hardcode_action, $1)=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. _LT_TAGVAR(hardcode_action, $1)=unsupported fi AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) if test relink = "$_LT_TAGVAR(hardcode_action, $1)" || test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then # Fast installation is not supported enable_fast_install=no elif test yes = "$shlibpath_overrides_runpath" || test no = "$enable_shared"; then # Fast installation is not necessary enable_fast_install=needless fi _LT_TAGDECL([], [hardcode_action], [0], [How to hardcode a shared library path into an executable]) ])# _LT_LINKER_HARDCODE_LIBPATH # _LT_CMD_STRIPLIB # ---------------- m4_defun([_LT_CMD_STRIPLIB], [m4_require([_LT_DECL_EGREP]) striplib= old_striplib= AC_MSG_CHECKING([whether stripping libraries is possible]) if test -z "$STRIP"; then AC_MSG_RESULT([no]) else if $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then old_striplib="$STRIP --strip-debug" striplib="$STRIP --strip-unneeded" AC_MSG_RESULT([yes]) else case $host_os in darwin*) # FIXME - insert some real tests, host_os isn't really good enough striplib="$STRIP -x" old_striplib="$STRIP -S" AC_MSG_RESULT([yes]) ;; freebsd*) if $STRIP -V 2>&1 | $GREP "elftoolchain" >/dev/null; then old_striplib="$STRIP --strip-debug" striplib="$STRIP --strip-unneeded" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi ;; *) AC_MSG_RESULT([no]) ;; esac fi fi _LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) _LT_DECL([], [striplib], [1]) ])# _LT_CMD_STRIPLIB # _LT_PREPARE_MUNGE_PATH_LIST # --------------------------- # Make sure func_munge_path_list() is defined correctly. m4_defun([_LT_PREPARE_MUNGE_PATH_LIST], [[# func_munge_path_list VARIABLE PATH # ----------------------------------- # VARIABLE is name of variable containing _space_ separated list of # directories to be munged by the contents of PATH, which is string # having a format: # "DIR[:DIR]:" # string "DIR[ DIR]" will be prepended to VARIABLE # ":DIR[:DIR]" # string "DIR[ DIR]" will be appended to VARIABLE # "DIRP[:DIRP]::[DIRA:]DIRA" # string "DIRP[ DIRP]" will be prepended to VARIABLE and string # "DIRA[ DIRA]" will be appended to VARIABLE # "DIR[:DIR]" # VARIABLE will be replaced by "DIR[ DIR]" func_munge_path_list () { case x@S|@2 in x) ;; *:) eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\" ;; x:*) eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\" ;; *::*) eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\" ;; *) eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\" ;; esac } ]])# _LT_PREPARE_PATH_LIST # _LT_SYS_DYNAMIC_LINKER([TAG]) # ----------------------------- # PORTME Fill in your ld.so characteristics m4_defun([_LT_SYS_DYNAMIC_LINKER], [AC_REQUIRE([AC_CANONICAL_HOST])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_OBJDUMP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl AC_MSG_CHECKING([dynamic linker characteristics]) m4_if([$1], [], [ if test yes = "$GCC"; then case $host_os in darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; *) lt_awk_arg='/^libraries:/' ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;; *) lt_sed_strip_eq='s|=/|/|g' ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary... lt_tmp_lt_search_path_spec= lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` # ...but if some path component already ends with the multilib dir we assume # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). case "$lt_multi_os_dir; $lt_search_path_spec " in "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) lt_multi_os_dir= ;; esac for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" elif test -n "$lt_multi_os_dir"; then test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS = " "; FS = "/|\n";} { lt_foo = ""; lt_count = 0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo = "/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[[lt_foo]]++; } if (lt_freq[[lt_foo]] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi]) library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=.so postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown AC_ARG_VAR([LT_SYS_LIBRARY_PATH], [User-defined run-time library search path.]) case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='$libname$release$shared_ext$major' ;; aix[[4-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test ia64 = "$host_cpu"; then # AIX 5 supports IA64 library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line '#! .'. This would cause the generated library to # depend on '.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[[01]] | aix4.[[01]].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # Using Import Files as archive members, it is possible to support # filename-based versioning of shared library archives on AIX. While # this would work for both with and without runtime linking, it will # prevent static linking of such archives. So we do filename-based # shared library versioning with .so extension only, which is used # when both runtime linking and shared linking is enabled. # Unfortunately, runtime linking may impact performance, so we do # not want this to be the default eventually. Also, we use the # versioned .so libs for executables only if there is the -brtl # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. # To allow for filename-based versioning support, we need to create # libNAME.so.V as an archive file, containing: # *) an Import File, referring to the versioned filename of the # archive as well as the shared archive member, telling the # bitwidth (32 or 64) of that shared object, and providing the # list of exported symbols of that shared object, eventually # decorated with the 'weak' keyword # *) the shared object with the F_LOADONLY flag set, to really avoid # it being seen by the linker. # At run time we better use the real file rather than another symlink, # but for link time we create the symlink libNAME.so -> libNAME.so.V case $with_aix_soname,$aix_use_runtimelinking in # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. aix,yes) # traditional libtool dynamic_linker='AIX unversionable lib.so' # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; aix,no) # traditional AIX only dynamic_linker='AIX lib.a[(]lib.so.V[)]' # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' ;; svr4,*) # full svr4 only dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,yes) # both, prefer svr4 dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # unpreferred sharedlib libNAME.a needs extra handling postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,no) # both, prefer aix dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]" library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' ;; esac shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='$libname$shared_ext' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[[45]]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo $libname | $SED -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo $libname | $SED -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl* | *,icl*) # Native MSVC or ICC libname_spec='$name' soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' library_names_spec='$libname.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec=$LIB if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC and ICC wrapper library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' soname_spec='$libname$release$major$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly* | midnightbsd*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[[23]].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[[01]]* | freebsdelf3.[[01]]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=no sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' if test 32 = "$HPUX_IA64_MODE"; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[[3-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test yes = "$lt_cv_prog_gnu_ld"; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; linux*android*) version_type=none # Android doesn't support versioned libraries. need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext' soname_spec='$libname$release$shared_ext' finish_cmds= shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes dynamic_linker='Android linker' # Don't embed -rpath directories since the linker doesn't support them. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], [lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], [lt_cv_shlibpath_overrides_runpath=yes])]) LDFLAGS=$save_LDFLAGS libdir=$save_libdir ]) shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Ideally, we could use ldconfig to report *all* directores which are # searched for libraries, however this is still not possible. Aside from not # being certain /sbin/ldconfig is available, command # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, # even though it is searched at run-time. Try to do the best guess by # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd* | bitrig*) version_type=sunos sys_lib_dlsearch_path_spec=/usr/lib need_lib_prefix=no if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then need_version=no else need_version=yes fi library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; os2*) libname_spec='$name' version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no # OS/2 can only load a DLL with a base name of 8 characters or less. soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; v=$($ECHO $release$versuffix | tr -d .-); n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); $ECHO $n$v`$shared_ext' library_names_spec='${libname}_dll.$libext' dynamic_linker='OS/2 ld.exe' shlibpath_var=BEGINLIBPATH sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test yes = "$with_gnu_ld"; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec; then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' soname_spec='$libname$shared_ext.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=sco need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test yes = "$with_gnu_ld"; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac AC_MSG_RESULT([$dynamic_linker]) test no = "$dynamic_linker" && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test yes = "$GCC"; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec fi if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec fi # remember unaugmented sys_lib_dlsearch_path content for libtool script decls... configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec # ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" # to be used as default LT_SYS_LIBRARY_PATH value in generated libtool configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH _LT_DECL([], [variables_saved_for_relink], [1], [Variables whose values should be saved in libtool wrapper scripts and restored at link time]) _LT_DECL([], [need_lib_prefix], [0], [Do we need the "lib" prefix for modules?]) _LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) _LT_DECL([], [version_type], [0], [Library versioning type]) _LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) _LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) _LT_DECL([], [shlibpath_overrides_runpath], [0], [Is shlibpath searched before the hard-coded library search path?]) _LT_DECL([], [libname_spec], [1], [Format of library name prefix]) _LT_DECL([], [library_names_spec], [1], [[List of archive names. First name is the real one, the rest are links. The last name is the one that the linker finds with -lNAME]]) _LT_DECL([], [soname_spec], [1], [[The coded name of the library, if different from the real name]]) _LT_DECL([], [install_override_mode], [1], [Permission mode override for installation of shared libraries]) _LT_DECL([], [postinstall_cmds], [2], [Command to use after installation of a shared archive]) _LT_DECL([], [postuninstall_cmds], [2], [Command to use after uninstallation of a shared archive]) _LT_DECL([], [finish_cmds], [2], [Commands used to finish a libtool library installation in a directory]) _LT_DECL([], [finish_eval], [1], [[As "finish_cmds", except a single script fragment to be evaled but not shown]]) _LT_DECL([], [hardcode_into_libs], [0], [Whether we should hardcode library paths into libraries]) _LT_DECL([], [sys_lib_search_path_spec], [2], [Compile-time system search path for libraries]) _LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2], [Detected run-time system search path for libraries]) _LT_DECL([], [configure_time_lt_sys_library_path], [2], [Explicit LT_SYS_LIBRARY_PATH set during ./configure time]) ])# _LT_SYS_DYNAMIC_LINKER # _LT_PATH_TOOL_PREFIX(TOOL) # -------------------------- # find a file program that can recognize shared library AC_DEFUN([_LT_PATH_TOOL_PREFIX], [m4_require([_LT_DECL_EGREP])dnl AC_MSG_CHECKING([for $1]) AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, [case $MAGIC_CMD in [[\\/*] | ?:[\\/]*]) lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD=$MAGIC_CMD lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR dnl $ac_dummy forces splitting on constant user-supplied paths. dnl POSIX.2 word splitting is done only on the output of word expansions, dnl not every word. This closes a longstanding sh security hole. ac_dummy="m4_if([$2], , $PATH, [$2])" for ac_dir in $ac_dummy; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$1"; then lt_cv_path_MAGIC_CMD=$ac_dir/"$1" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS=$lt_save_ifs MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac]) MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then AC_MSG_RESULT($MAGIC_CMD) else AC_MSG_RESULT(no) fi _LT_DECL([], [MAGIC_CMD], [0], [Used to examine libraries when file_magic_cmd begins with "file"])dnl ])# _LT_PATH_TOOL_PREFIX # Old name: AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) # _LT_PATH_MAGIC # -------------- # find a file program that can recognize a shared library m4_defun([_LT_PATH_MAGIC], [_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) else MAGIC_CMD=: fi fi ])# _LT_PATH_MAGIC # LT_PATH_LD # ---------- # find the pathname to the GNU or non-GNU linker AC_DEFUN([LT_PATH_LD], [AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PROG_ECHO_BACKSLASH])dnl AC_ARG_WITH([gnu-ld], [AS_HELP_STRING([--with-gnu-ld], [assume the C compiler uses GNU ld @<:@default=no@:>@])], [test no = "$withval" || with_gnu_ld=yes], [with_gnu_ld=no])dnl ac_prog=ld if test yes = "$GCC"; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by $CC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return, which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]]* | ?:[[\\/]]*) re_direlt='/[[^/]][[^/]]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD=$ac_prog ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test yes = "$with_gnu_ld"; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(lt_cv_path_LD, [if test -z "$LD"; then lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD=$ac_dir/$ac_prog # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &1 conftest.i cat conftest.i conftest.i >conftest2.i : ${lt_DD:=$DD} AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd], [if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: fi]) rm -f conftest.i conftest2.i conftest.out]) ])# _LT_PATH_DD # _LT_CMD_TRUNCATE # ---------------- # find command to truncate a binary pipe m4_defun([_LT_CMD_TRUNCATE], [m4_require([_LT_PATH_DD]) AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin], [printf 0123456789abcdef0123456789abcdef >conftest.i cat conftest.i conftest.i >conftest2.i lt_cv_truncate_bin= if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" fi rm -f conftest.i conftest2.i conftest.out test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"]) _LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1], [Command to truncate a binary pipe]) ])# _LT_CMD_TRUNCATE # _LT_CHECK_MAGIC_METHOD # ---------------------- # how to check for library dependencies # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_MAGIC_METHOD], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) AC_CACHE_CHECK([how to recognize dependent libraries], lt_cv_deplibs_check_method, [lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # 'unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # that responds to the $file_magic_cmd with a given extended regex. # If you have 'file' or equivalent on your system and you're not sure # whether 'pass_all' will *always* work, you probably want this one. case $host_os in aix[[4-9]]*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[[45]]*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='$FILECMD -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. if ( file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly* | midnightbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=$FILECMD lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=$FILECMD case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[[3-9]]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=$FILECMD lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd* | bitrig*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; os2*) lt_cv_deplibs_check_method=pass_all ;; esac ]) file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown _LT_DECL([], [deplibs_check_method], [1], [Method to check whether dependent libraries are shared objects]) _LT_DECL([], [file_magic_cmd], [1], [Command to use when deplibs_check_method = "file_magic"]) _LT_DECL([], [file_magic_glob], [1], [How to find potential files when deplibs_check_method = "file_magic"]) _LT_DECL([], [want_nocaseglob], [1], [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) ])# _LT_CHECK_MAGIC_METHOD # LT_PATH_NM # ---------- # find the pathname to a BSD- or MS-compatible name lister AC_DEFUN([LT_PATH_NM], [AC_REQUIRE([AC_PROG_CC])dnl AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, [if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM=$NM else lt_nm_to_check=${ac_tool_prefix}nm if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. tmp_nm=$ac_dir/$lt_tmp_nm if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then # Check to see if the nm accepts a BSD-compat flag. # Adding the 'sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty case $build_os in mingw*) lt_bad_file=conftest.nm/nofile ;; *) lt_bad_file=/dev/null ;; esac case `"$tmp_nm" -B $lt_bad_file 2>&1 | $SED '1q'` in *$lt_bad_file* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break 2 ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | $SED '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break 2 ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS=$lt_save_ifs done : ${lt_cv_path_NM=no} fi]) if test no != "$lt_cv_path_NM"; then NM=$lt_cv_path_NM else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) case `$DUMPBIN -symbols -headers /dev/null 2>&1 | $SED '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols -headers" ;; *) DUMPBIN=: ;; esac fi AC_SUBST([DUMPBIN]) if test : != "$DUMPBIN"; then NM=$DUMPBIN fi fi test -z "$NM" && NM=nm AC_SUBST([NM]) _LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], [lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) cat conftest.out >&AS_MESSAGE_LOG_FD if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest*]) ])# LT_PATH_NM # Old names: AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_PROG_NM], []) dnl AC_DEFUN([AC_PROG_NM], []) # _LT_CHECK_SHAREDLIB_FROM_LINKLIB # -------------------------------- # how to determine the name of the shared library # associated with a specific link library. # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) m4_require([_LT_DECL_DLLTOOL]) AC_CACHE_CHECK([how to associate runtime and link libraries], lt_cv_sharedlib_from_linklib_cmd, [lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh; # decide which one to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd=$ECHO ;; esac ]) sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO _LT_DECL([], [sharedlib_from_linklib_cmd], [1], [Command to associate shared and link libraries]) ])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB # _LT_PATH_MANIFEST_TOOL # ---------------------- # locate the manifest tool m4_defun([_LT_PATH_MANIFEST_TOOL], [AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], [lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&AS_MESSAGE_LOG_FD if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest*]) if test yes != "$lt_cv_path_mainfest_tool"; then MANIFEST_TOOL=: fi _LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl ])# _LT_PATH_MANIFEST_TOOL # _LT_DLL_DEF_P([FILE]) # --------------------- # True iff FILE is a Windows DLL '.def' file. # Keep in sync with func_dll_def_p in the libtool script AC_DEFUN([_LT_DLL_DEF_P], [dnl test DEF = "`$SED -n dnl -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl -e q dnl Only consider the first "real" line $1`" dnl ])# _LT_DLL_DEF_P # LT_LIB_M # -------- # check for math library AC_DEFUN([LT_LIB_M], [AC_REQUIRE([AC_CANONICAL_HOST])dnl LIBM= case $host in *-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) # These system don't have libm, or don't need it ;; *-ncr-sysv4.3*) AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw) AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") ;; *) AC_CHECK_LIB(m, cos, LIBM=-lm) ;; esac AC_SUBST([LIBM]) ])# LT_LIB_M # Old name: AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_CHECK_LIBM], []) # _LT_COMPILER_NO_RTTI([TAGNAME]) # ------------------------------- m4_defun([_LT_COMPILER_NO_RTTI], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= if test yes = "$GCC"; then case $cc_basename in nvcc*) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; *) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; esac _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], lt_cv_prog_compiler_rtti_exceptions, [-fno-rtti -fno-exceptions], [], [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) fi _LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], [Compiler flag to turn off builtin functions]) ])# _LT_COMPILER_NO_RTTI # _LT_CMD_GLOBAL_SYMBOLS # ---------------------- m4_defun([_LT_CMD_GLOBAL_SYMBOLS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([LT_PATH_NM])dnl AC_REQUIRE([LT_PATH_LD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_TAG_COMPILER])dnl # Check for command to grab the raw symbol name followed by C symbol from nm. AC_MSG_CHECKING([command to parse $NM output from $compiler object]) AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], [ # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[[BCDEGRST]]' # Regexp to match symbols that can be accessed directly from C. sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[[BCDT]]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[[ABCDGISTW]]' ;; hpux*) if test ia64 = "$host_cpu"; then symcode='[[ABCDEGRST]]' fi ;; irix* | nonstopux*) symcode='[[BCDEGRST]]' ;; osf*) symcode='[[BCDEGQRST]]' ;; solaris*) symcode='[[BDRT]]' ;; sco3.2v5*) symcode='[[DT]]' ;; sysv4.2uw2*) symcode='[[DT]]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[[ABDT]]' ;; sysv4) symcode='[[DFNSTU]]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[[ABCDGIRSTW]]' ;; esac if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Gets list of data symbols to import. lt_cv_sys_global_symbol_to_import="$SED -n -e 's/^I .* \(.*\)$/\1/p'" # Adjust the below global symbol transforms to fixup imported variables. lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" lt_c_name_lib_hook="\ -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" else # Disable hooks by default. lt_cv_sys_global_symbol_to_import= lt_cdecl_hook= lt_c_name_hook= lt_c_name_lib_hook= fi # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="$SED -n"\ $lt_cdecl_hook\ " -e 's/^T .* \(.*\)$/extern int \1();/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="$SED -n"\ $lt_c_name_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" # Transform an extracted symbol line into symbol name with lib prefix and # symbol address. lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="$SED -n"\ $lt_c_name_lib_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function, # D for any global variable and I for any imported variable. # Also find C++ and __fastcall symbols from MSVC++ or ICC, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK ['"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ " /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ " /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ " {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ " s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx]" else lt_cv_sys_global_symbol_pipe="$SED -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | $SED '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if AC_TRY_EVAL(ac_compile); then # Now try to grab the symbols. nlist=conftest.nm if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE /* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT@&t@_DLSYM_CONST #elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT@&t@_DLSYM_CONST #else # define LT@&t@_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT@&t@_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[[]] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS=conftstm.$ac_objext CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD fi else echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test yes = "$pipe_works"; then break else lt_cv_sys_global_symbol_pipe= fi done ]) if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then AC_MSG_RESULT(failed) else AC_MSG_RESULT(ok) fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then nm_file_list_spec='@' fi _LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], [Take the output of nm and produce a listing of raw symbols and C names]) _LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], [Transform the output of nm in a proper C declaration]) _LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1], [Transform the output of nm into a list of symbols to manually relocate]) _LT_DECL([global_symbol_to_c_name_address], [lt_cv_sys_global_symbol_to_c_name_address], [1], [Transform the output of nm in a C name address pair]) _LT_DECL([global_symbol_to_c_name_address_lib_prefix], [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], [Transform the output of nm in a C name address pair when lib prefix is needed]) _LT_DECL([nm_interface], [lt_cv_nm_interface], [1], [The name lister interface]) _LT_DECL([], [nm_file_list_spec], [1], [Specify filename containing input files for $NM]) ]) # _LT_CMD_GLOBAL_SYMBOLS # _LT_COMPILER_PIC([TAGNAME]) # --------------------------- m4_defun([_LT_COMPILER_PIC], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_wl, $1)= _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)= m4_if([$1], [CXX], [ # C++ specific cases for pic, static, wl, etc. if test yes = "$GXX"; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac else case $host_os in aix[[4-9]]*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; dgux*) case $cc_basename in ec++*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; ghcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; freebsd* | dragonfly* | midnightbsd*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' if test ia64 != "$host_cpu"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' fi ;; aCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # KAI C++ Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; ecpc* ) # old Intel C++ for x86_64, which still supported -KPIC. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; icpc* ) # Intel C++, used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL 8.0, 9.0 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | $SED 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' ;; *) ;; esac ;; netbsd*) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; cxx*) # Digital/Compaq C++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; lcc*) # Lucid _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; *) ;; esac ;; vxworks*) ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ], [ if test yes = "$GCC"; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' case $cc_basename in nagfor*) # NAG Fortran compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; hpux9* | hpux10* | hpux11*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC (with -KPIC) is the default. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in # old Intel for x86_64, which still supported -KPIC. ecc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # Lahey Fortran 8.1. lf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' ;; nagfor*) # NAG Fortran compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; tcc*) # Fabrice Bellard et al's Tiny C Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; ccc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All Alpha code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | $SED 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='' ;; *Sun\ F* | *Sun*Fortran*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' ;; *Intel*\ [[CF]]*Compiler*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; *Portland\ Group*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; esac ;; newsos6) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All OSF/1 code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; rdos*) _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; solaris*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; *) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; esac ;; sunos4*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; unicos*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; uts4*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ]) case $host_os in # For platforms that do not support PIC, -DPIC is meaningless: *djgpp*) _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" ;; esac AC_CACHE_CHECK([for $compiler option to produce PIC], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) _LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) # # Check to make sure the PIC flag actually works. # if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in "" | " "*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; esac], [_LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) fi _LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], [Additional compiler flags for building library objects]) _LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], [How to pass a linker flag through the compiler]) # # Check to make sure the static flag actually works. # wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" _LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), $lt_tmp_static_flag, [], [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) _LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], [Compiler flag to prevent dynamic linking]) ])# _LT_COMPILER_PIC # _LT_LINKER_SHLIBS([TAGNAME]) # ---------------------------- # See if the linker supports building shared libraries. m4_defun([_LT_LINKER_SHLIBS], [AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) m4_if([$1], [CXX], [ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] case $host_os in aix[[4-9]]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi ;; pw32*) _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds ;; cygwin* | mingw* | cegcc*) case $cc_basename in cl* | icl*) _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] ;; esac ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac ], [ runpath_var= _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_cmds, $1)= _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(old_archive_from_new_cmds, $1)= _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= _LT_TAGVAR(thread_safe_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list _LT_TAGVAR(include_expsyms, $1)= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ' (' and ')$', so one must not match beginning or # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', # as well as any symbol that contains 'd'. _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. dnl Note also adjust exclude_expsyms for C++ above. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ and ICC port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++ or Intel C++ Compiler. if test yes != "$GCC"; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++ or ICC) with_gnu_ld=yes ;; openbsd* | bitrig*) with_gnu_ld=no ;; esac _LT_TAGVAR(ld_shlibs, $1)=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test yes = "$with_gnu_ld"; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test yes = "$lt_use_gnu_ld_interface"; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='$wl' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi supports_anon_versioning=no case `$LD -v | $SED -e 's/([[^)]]\+)\s\+//' 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[[3-9]]*) # On AIX/PPC, the GNU linker is very broken if test ia64 != "$host_cpu"; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test linux-dietlibc = "$host_os"; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test no = "$tmp_diet" then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 _LT_TAGVAR(whole_archive_flag_spec, $1)= tmp_sharedflag='--shared' ;; nagfor*) # NAGFOR 5.3 tmp_sharedflag='-Wl,-shared' ;; xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes ;; esac case `$CC -V 2>&1 | $SED 5q` in *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi case $cc_basename in tcc*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic' ;; xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; sunos4*) _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then runpath_var= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. _LT_TAGVAR(hardcode_minus_L, $1)=yes if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. _LT_TAGVAR(hardcode_direct, $1)=unsupported fi ;; aix[[4-9]]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then aix_use_runtimelinking=yes break fi done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # traditional, no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no ;; esac if test yes = "$GCC"; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi ;; esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag="$shared_flag "'$wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_TAGVAR(always_export_symbols, $1)=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; bsdi[[45]]*) _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++ or Intel C++ Compiler. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl* | icl*) # Native MSVC or ICC _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC and ICC wrapper _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' # FIXME: Should let the user specify the lib program. _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly* | midnightbsd*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; hpux9*) if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' ;; hpux10*) if test yes,no = "$GCC,$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes fi ;; hpux11*) if test yes,no = "$GCC,$with_gnu_ld"; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) m4_if($1, [], [ # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) _LT_LINKER_OPTION([if $CC understands -b], _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) ;; esac fi if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], [lt_cv_irix_exported_symbol], [save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" AC_LINK_IFELSE( [AC_LANG_SOURCE( [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], [C++], [[int foo (void) { return 0; }]], [Fortran 77], [[ subroutine foo end]], [Fortran], [[ subroutine foo end]])])], [lt_cv_irix_exported_symbol=yes], [lt_cv_irix_exported_symbol=no]) LDFLAGS=$save_LDFLAGS]) if test yes = "$lt_cv_irix_exported_symbol"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' fi else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes _LT_TAGVAR(link_all_deplibs, $1)=yes ;; linux*) case $cc_basename in tcc*) # Fabrice Bellard et al's Tiny C Compiler _LT_TAGVAR(ld_shlibs, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; newsos6) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *nto* | *qnx*) ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' fi else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' ;; osf3*) if test yes = "$GCC"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test yes = "$GCC"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; solaris*) _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' if test yes = "$GCC"; then wlarc='$wl' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='$wl' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. GCC discards it without '$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test yes = "$GCC"; then _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' else _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' fi ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes ;; sunos4*) if test sequent = "$host_vendor"; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4) case $host_vendor in sni) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' _LT_TAGVAR(hardcode_direct, $1)=no ;; motorola) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4.3*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes _LT_TAGVAR(ld_shlibs, $1)=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(ld_shlibs, $1)=no ;; esac if test sni = "$host_vendor"; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym' ;; esac fi fi ]) AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no _LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld _LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl _LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl _LT_DECL([], [extract_expsyms_cmds], [2], [The commands to extract the exported symbol list from a shared archive]) # # Do we need to explicitly link libc? # case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in x|xyes) # Assume -lc should be added _LT_TAGVAR(archive_cmds_need_lc, $1)=yes if test yes,yes = "$GCC,$enable_shared"; then case $_LT_TAGVAR(archive_cmds, $1) in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. AC_CACHE_CHECK([whether -lc should be explicitly linked in], [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), [$RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if AC_TRY_EVAL(ac_compile) 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) _LT_TAGVAR(allow_undefined_flag, $1)= if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) then lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no else lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes fi _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* ]) _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) ;; esac fi ;; esac _LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], [Whether or not to add -lc for building shared libraries]) _LT_TAGDECL([allow_libtool_libs_with_static_runtimes], [enable_shared_with_static_runtimes], [0], [Whether or not to disallow shared libs when runtime libs are static]) _LT_TAGDECL([], [export_dynamic_flag_spec], [1], [Compiler flag to allow reflexive dlopens]) _LT_TAGDECL([], [whole_archive_flag_spec], [1], [Compiler flag to generate shared objects directly from archives]) _LT_TAGDECL([], [compiler_needs_object], [1], [Whether the compiler copes with passing no objects directly]) _LT_TAGDECL([], [old_archive_from_new_cmds], [2], [Create an old-style archive from a shared archive]) _LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], [Create a temporary old-style archive to link instead of a shared archive]) _LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) _LT_TAGDECL([], [archive_expsym_cmds], [2]) _LT_TAGDECL([], [module_cmds], [2], [Commands used to build a loadable module if different from building a shared archive.]) _LT_TAGDECL([], [module_expsym_cmds], [2]) _LT_TAGDECL([], [with_gnu_ld], [1], [Whether we are building with GNU ld or not]) _LT_TAGDECL([], [allow_undefined_flag], [1], [Flag that allows shared libraries with undefined symbols to be built]) _LT_TAGDECL([], [no_undefined_flag], [1], [Flag that enforces no undefined symbols]) _LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], [Flag to hardcode $libdir into a binary during linking. This must work even if $libdir does not exist]) _LT_TAGDECL([], [hardcode_libdir_separator], [1], [Whether we need a single "-rpath" flag with a separated argument]) _LT_TAGDECL([], [hardcode_direct], [0], [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_direct_absolute], [0], [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes DIR into the resulting binary and the resulting library dependency is "absolute", i.e impossible to change by setting $shlibpath_var if the library is relocated]) _LT_TAGDECL([], [hardcode_minus_L], [0], [Set to "yes" if using the -LDIR flag during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_shlibpath_var], [0], [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_automatic], [0], [Set to "yes" if building a shared library automatically hardcodes DIR into the library and all subsequent libraries and executables linked against it]) _LT_TAGDECL([], [inherit_rpath], [0], [Set to yes if linker adds runtime paths of dependent libraries to runtime path list]) _LT_TAGDECL([], [link_all_deplibs], [0], [Whether libtool must link a program against all its dependency libraries]) _LT_TAGDECL([], [always_export_symbols], [0], [Set to "yes" if exported symbols are required]) _LT_TAGDECL([], [export_symbols_cmds], [2], [The commands to list exported symbols]) _LT_TAGDECL([], [exclude_expsyms], [1], [Symbols that should not be listed in the preloaded symbols]) _LT_TAGDECL([], [include_expsyms], [1], [Symbols that must always be exported]) _LT_TAGDECL([], [prelink_cmds], [2], [Commands necessary for linking programs (against libraries) with templates]) _LT_TAGDECL([], [postlink_cmds], [2], [Commands necessary for finishing linking programs]) _LT_TAGDECL([], [file_list_spec], [1], [Specify filename containing input files]) dnl FIXME: Not yet implemented dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], dnl [Compiler flag to generate thread safe objects]) ])# _LT_LINKER_SHLIBS # _LT_LANG_C_CONFIG([TAG]) # ------------------------ # Ensure that the configuration variables for a C compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to 'libtool'. m4_defun([_LT_LANG_C_CONFIG], [m4_require([_LT_DECL_EGREP])dnl lt_save_CC=$CC AC_LANG_PUSH(C) # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' _LT_TAG_COMPILER # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) LT_SYS_DLOPEN_SELF _LT_CMD_STRIPLIB # Report what library types will actually be built AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_CONFIG($1) fi AC_LANG_POP CC=$lt_save_CC ])# _LT_LANG_C_CONFIG # _LT_LANG_CXX_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a C++ compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to 'libtool'. m4_defun([_LT_LANG_CXX_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl if test -n "$CXX" && ( test no != "$CXX" && ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || (test g++ != "$CXX"))); then AC_PROG_CXXCPP else _lt_caught_CXX_error=yes fi AC_LANG_PUSH(C++) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_caught_CXX_error"; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} CFLAGS=$CXXFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately if test yes = "$GXX"; then _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' else _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= fi if test yes = "$GXX"; then # Set up default GNU C++ configuration LT_PATH_LD # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test yes = "$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='$wl' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) _LT_TAGVAR(ld_shlibs, $1)=yes case $host_os in aix3*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aix[[4-9]]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no ;; esac if test yes = "$GXX"; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag=$shared_flag' $wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. _LT_TAGVAR(always_export_symbols, $1)=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. # The "-G" linker flag allows undefined symbols. _LT_TAGVAR(no_undefined_flag, $1)='-bernotok' # Determine the default libpath from the value encoded in an empty # executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' fi fi ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; cygwin* | mingw* | pw32* | cegcc*) case $GXX,$cc_basename in ,cl* | no,cl* | ,icl* | no,icl*) # Native MSVC or ICC # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ func_to_tool_file "$lt_outputfile"~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # g++ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; freebsd2.*) # C++ shared libraries reported to be fairly broken before # switch to ELF _LT_TAGVAR(ld_shlibs, $1)=no ;; freebsd-elf*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; freebsd* | dragonfly* | midnightbsd*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions _LT_TAGVAR(ld_shlibs, $1)=yes ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; hpux9*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; hpux10*|hpux11*) if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) ;; *) _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' fi fi _LT_TAGVAR(link_all_deplibs, $1)=yes ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc* | ecpc* ) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ $RANLIB $oldlib' _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 6 and above use weak symbols _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' ;; cxx*) # Compaq C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi ;; *) case `$CC -V 2>&1 | $SED 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; m88k*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; *nto* | *qnx*) _LT_TAGVAR(ld_shlibs, $1)=yes ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using # the KAI C++ compiler. case $host in osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; esac ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; cxx*) case $host in osf3*) _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' ;; *) _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ $RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' ;; esac _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes,no = "$GXX,$with_gnu_ld"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' case $host in osf3*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test yes,no = "$GXX,$with_gnu_ld"; then _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # g++ 2.7 appears to require '-G' NOT '-shared' on this # platform. _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir' case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ '"$_LT_TAGVAR(old_archive_cmds, $1)" _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ '"$_LT_TAGVAR(reload_cmds, $1)" ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no _LT_TAGVAR(GCC, $1)=$GXX _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld fi # test yes != "$_lt_caught_CXX_error" AC_LANG_POP ])# _LT_LANG_CXX_CONFIG # _LT_FUNC_STRIPNAME_CNF # ---------------------- # func_stripname_cnf prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # # This function is identical to the (non-XSI) version of func_stripname, # except this one can be used by m4 code that may be executed by configure, # rather than the libtool script. m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl AC_REQUIRE([_LT_DECL_SED]) AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) func_stripname_cnf () { case @S|@2 in .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;; *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;; esac } # func_stripname_cnf ])# _LT_FUNC_STRIPNAME_CNF # _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) # --------------------------------- # Figure out "hidden" library dependencies from verbose # compiler output when linking a shared library. # Parse the compiler output and extract the necessary # objects, libraries and library flags. m4_defun([_LT_SYS_HIDDEN_LIBDEPS], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl # Dependencies to place before and after the object being linked: _LT_TAGVAR(predep_objects, $1)= _LT_TAGVAR(postdep_objects, $1)= _LT_TAGVAR(predeps, $1)= _LT_TAGVAR(postdeps, $1)= _LT_TAGVAR(compiler_lib_search_path, $1)= dnl we can't use the lt_simple_compile_test_code here, dnl because it contains code intended for an executable, dnl not a library. It's possible we should let each dnl tag define a new lt_????_link_test_code variable, dnl but it's only used here... m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF int a; void foo (void) { a = 0; } _LT_EOF ], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; _LT_EOF ], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer*4 a a=0 return end _LT_EOF ], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer a a=0 return end _LT_EOF ], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF public class foo { private int a; public void bar (void) { a = 0; } }; _LT_EOF ], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF package foo func foo() { } _LT_EOF ]) _lt_libdeps_save_CFLAGS=$CFLAGS case "$CC $CFLAGS " in #( *\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; *\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; *\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; esac dnl Parse the compiler output and extract the necessary dnl objects, libraries and library flags. if AC_TRY_EVAL(ac_compile); then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do case $prev$p in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test x-L = "$p" || test x-R = "$p"; then prev=$p continue fi # Expand the sysroot to ease extracting the directories later. if test -z "$prev"; then case $p in -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; esac fi case $p in =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; esac if test no = "$pre_test_object_deps_done"; then case $prev in -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p else _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$_LT_TAGVAR(postdeps, $1)"; then _LT_TAGVAR(postdeps, $1)=$prev$p else _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p" fi fi prev= ;; *.lto.$objext) ;; # Ignore GCC LTO objects *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test no = "$pre_test_object_deps_done"; then if test -z "$_LT_TAGVAR(predep_objects, $1)"; then _LT_TAGVAR(predep_objects, $1)=$p else _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" fi else if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then _LT_TAGVAR(postdep_objects, $1)=$p else _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling $1 test program" fi $RM -f confest.$objext CFLAGS=$_lt_libdeps_save_CFLAGS # PORTME: override above test on systems where it is broken m4_if([$1], [CXX], [case $host_os in interix[[3-9]]*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. _LT_TAGVAR(predep_objects,$1)= _LT_TAGVAR(postdep_objects,$1)= _LT_TAGVAR(postdeps,$1)= ;; esac ]) case " $_LT_TAGVAR(postdeps, $1) " in *" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; esac _LT_TAGVAR(compiler_lib_search_dirs, $1)= if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'` fi _LT_TAGDECL([], [compiler_lib_search_dirs], [1], [The directories searched by this compiler when creating a shared library]) _LT_TAGDECL([], [predep_objects], [1], [Dependencies to place before and after the objects being linked to create a shared library]) _LT_TAGDECL([], [postdep_objects], [1]) _LT_TAGDECL([], [predeps], [1]) _LT_TAGDECL([], [postdeps], [1]) _LT_TAGDECL([], [compiler_lib_search_path], [1], [The library search path used internally by the compiler when linking a shared library]) ])# _LT_SYS_HIDDEN_LIBDEPS # _LT_LANG_F77_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a Fortran 77 compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_F77_CONFIG], [AC_LANG_PUSH(Fortran 77) if test -z "$F77" || test no = "$F77"; then _lt_disable_F77=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for f77 test sources. ac_ext=f # Object file extension for compiled f77 test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the F77 compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_disable_F77"; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${F77-"f77"} CFLAGS=$FFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) GCC=$G77 if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)=$G77 _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS fi # test yes != "$_lt_disable_F77" AC_LANG_POP ])# _LT_LANG_F77_CONFIG # _LT_LANG_FC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for a Fortran compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_FC_CONFIG], [AC_LANG_PUSH(Fortran) if test -z "$FC" || test no = "$FC"; then _lt_disable_FC=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for fc test sources. ac_ext=${ac_fc_srcext-f} # Object file extension for compiled fc test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the FC compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_disable_FC"; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${FC-"f95"} CFLAGS=$FCFLAGS compiler=$CC GCC=$ac_cv_fc_compiler_gnu _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS fi # test yes != "$_lt_disable_FC" AC_LANG_POP ])# _LT_LANG_FC_CONFIG # _LT_LANG_GCJ_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Java Compiler compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_GCJ_CONFIG], [AC_REQUIRE([LT_PROG_GCJ])dnl AC_LANG_SAVE # Source file extension for Java test sources. ac_ext=java # Object file extension for compiled Java test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="class foo {}" # Code to be used in simple link tests lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GCJ-"gcj"} CFLAGS=$GCJFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)=$LD _LT_CC_BASENAME([$compiler]) # GCJ did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GCJ_CONFIG # _LT_LANG_GO_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Go compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_GO_CONFIG], [AC_REQUIRE([LT_PROG_GO])dnl AC_LANG_SAVE # Source file extension for Go test sources. ac_ext=go # Object file extension for compiled Go test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="package main; func main() { }" # Code to be used in simple link tests lt_simple_link_test_code='package main; func main() { }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GOC-"gccgo"} CFLAGS=$GOFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)=$LD _LT_CC_BASENAME([$compiler]) # Go did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GO_CONFIG # _LT_LANG_RC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for the Windows resource compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_RC_CONFIG], [AC_REQUIRE([LT_PROG_RC])dnl AC_LANG_SAVE # Source file extension for RC test sources. ac_ext=rc # Object file extension for compiled RC test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' # Code to be used in simple link tests lt_simple_link_test_code=$lt_simple_compile_test_code # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC= CC=${RC-"windres"} CFLAGS= compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes if test -n "$compiler"; then : _LT_CONFIG($1) fi GCC=$lt_save_GCC AC_LANG_RESTORE CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_RC_CONFIG # LT_PROG_GCJ # ----------- AC_DEFUN([LT_PROG_GCJ], [m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], [AC_CHECK_TOOL(GCJ, gcj,) test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2" AC_SUBST(GCJFLAGS)])])[]dnl ]) # Old name: AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_GCJ], []) # LT_PROG_GO # ---------- AC_DEFUN([LT_PROG_GO], [AC_CHECK_TOOL(GOC, gccgo,) ]) # LT_PROG_RC # ---------- AC_DEFUN([LT_PROG_RC], [AC_CHECK_TOOL(RC, windres,) ]) # Old name: AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_RC], []) # _LT_DECL_EGREP # -------------- # If we don't have a new enough Autoconf to choose the best grep # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_EGREP], [AC_REQUIRE([AC_PROG_EGREP])dnl AC_REQUIRE([AC_PROG_FGREP])dnl test -z "$GREP" && GREP=grep _LT_DECL([], [GREP], [1], [A grep program that handles long lines]) _LT_DECL([], [EGREP], [1], [An ERE matcher]) _LT_DECL([], [FGREP], [1], [A literal string matcher]) dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too AC_SUBST([GREP]) ]) # _LT_DECL_OBJDUMP # -------------- # If we don't have a new enough Autoconf to choose the best objdump # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_OBJDUMP], [AC_CHECK_TOOL(OBJDUMP, objdump, false) test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) AC_SUBST([OBJDUMP]) ]) # _LT_DECL_DLLTOOL # ---------------- # Ensure DLLTOOL variable is set. m4_defun([_LT_DECL_DLLTOOL], [AC_CHECK_TOOL(DLLTOOL, dlltool, false) test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program]) AC_SUBST([DLLTOOL]) ]) # _LT_DECL_FILECMD # ---------------- # Check for a file(cmd) program that can be used to detect file type and magic m4_defun([_LT_DECL_FILECMD], [AC_CHECK_TOOL([FILECMD], [file], [:]) _LT_DECL([], [FILECMD], [1], [A file(cmd) program that detects file types]) ])# _LD_DECL_FILECMD # _LT_DECL_SED # ------------ # Check for a fully-functional sed program, that truncates # as few characters as possible. Prefer GNU sed if found. m4_defun([_LT_DECL_SED], [AC_PROG_SED test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" _LT_DECL([], [SED], [1], [A sed program that does not truncate output]) _LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], [Sed that helps us avoid accidentally triggering echo(1) options like -n]) ])# _LT_DECL_SED m4_ifndef([AC_PROG_SED], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_SED. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_SED], [AC_MSG_CHECKING([for a sed that does not truncate output]) AC_CACHE_VAL(lt_cv_path_SED, [# Loop through the user's path and test for sed and gsed. # Then use that list of sed's as ones to test for truncation. as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for lt_ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" fi done done done IFS=$as_save_IFS lt_ac_max=0 lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do test ! -f "$lt_ac_sed" && continue cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in # Check for GNU sed and select it if it is found. if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then lt_cv_path_SED=$lt_ac_sed break fi while true; do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo >>conftest.nl $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough test 10 -lt "$lt_ac_count" && break lt_ac_count=`expr $lt_ac_count + 1` if test "$lt_ac_count" -gt "$lt_ac_max"; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi done done ]) SED=$lt_cv_path_SED AC_SUBST([SED]) AC_MSG_RESULT([$SED]) ])#AC_PROG_SED ])#m4_ifndef # Old name: AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_SED], []) # _LT_CHECK_SHELL_FEATURES # ------------------------ # Find out whether the shell is Bourne or XSI compatible, # or has some other useful features. m4_defun([_LT_CHECK_SHELL_FEATURES], [if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi _LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac _LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl _LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl ])# _LT_CHECK_SHELL_FEATURES # _LT_PATH_CONVERSION_FUNCTIONS # ----------------------------- # Determine what file name conversion functions should be used by # func_to_host_file (and, implicitly, by func_to_host_path). These are needed # for certain cross-compile configurations and native mingw. m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_MSG_CHECKING([how to convert $build file names to $host format]) AC_CACHE_VAL(lt_cv_to_host_file_cmd, [case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac ]) to_host_file_cmd=$lt_cv_to_host_file_cmd AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) _LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], [0], [convert $build file names to $host format])dnl AC_MSG_CHECKING([how to convert $build file names to toolchain format]) AC_CACHE_VAL(lt_cv_to_tool_file_cmd, [#assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac ]) to_tool_file_cmd=$lt_cv_to_tool_file_cmd AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) _LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], [0], [convert $build files to toolchain format])dnl ])# _LT_PATH_CONVERSION_FUNCTIONS libtorrent-0.16.11/scripts/common.m40000644000000000000000000001506015175073411012722 AC_DEFUN([TORRENT_WITH_SYSROOT], [ AC_ARG_WITH(sysroot, AS_HELP_STRING([--with-sysroot=PATH], [compile and link with a specific sysroot]), [ AC_MSG_CHECKING(for sysroot) if test "$withval" = "no"; then AC_MSG_RESULT(no) elif test "$withval" = "yes"; then AC_MSG_RESULT(not a path) AC_MSG_ERROR(The sysroot option must point to a directory, like f.ex "/Developer/SDKs/MacOSX10.4u.sdk".) else AC_MSG_RESULT($withval) CXXFLAGS="$CXXFLAGS -isysroot $withval" LDFLAGS="$LDFLAGS -Wl,-syslibroot,$withval" fi ]) ]) AC_DEFUN([TORRENT_REMOVE_UNWANTED], [ AC_REQUIRE([AC_PROG_GREP]) values_to_check=`for i in $2; do echo $i; done` unwanted_values=`for i in $3; do echo $i; done` if test -z "${unwanted_values}"; then $1="$2" else result=`echo "${values_to_check}" | $GREP -Fvx -- "${unwanted_values}" | $GREP -v '^$'` # join with spaces, squeeze repeats, and trim trailing space $1=$(printf '%s\n' "$result" | tr '\n' ' ' | sed 's/ */ /g; s/ *$//') fi ]) AC_DEFUN([TORRENT_ENABLE_ARCH], [ AC_ARG_ENABLE(arch, AS_HELP_STRING([--enable-arch=ARCH], [comma seprated list of architectures to compile for]), [ AC_MSG_CHECKING(for target architectures) if test "$enableval" = "yes"; then AC_MSG_ERROR(no arch supplied) elif test "$enableval" = "no"; then AC_MSG_RESULT(using default) else AC_MSG_RESULT($enableval) for i in `IFS=,; echo $enableval`; do CFLAGS="$CFLAGS -march=$i" CXXFLAGS="$CXXFLAGS -march=$i" LDFLAGS="$LDFLAGS -march=$i" done fi ]) ]) AC_DEFUN([TORRENT_MINCORE_SIGNEDNESS], [ AC_LANG_PUSH(C++) AC_MSG_CHECKING(signedness of mincore parameter) AC_COMPILE_IFELSE([AC_LANG_SOURCE([ #include #include #include void f() { mincore((char*)0, 0, (unsigned char*)0); } ])], [ AC_DEFINE(USE_MINCORE, 1, Use mincore) AC_DEFINE(USE_MINCORE_UNSIGNED, 1, use unsigned char* in mincore) AC_MSG_RESULT(unsigned) ], [ AC_COMPILE_IFELSE([AC_LANG_SOURCE([ #include #include #include void f() { mincore((char*)0, 0, (char*)0); } ])], [ AC_DEFINE(USE_MINCORE, 1, Use mincore) AC_DEFINE(USE_MINCORE_UNSIGNED, 0, use char* in mincore) AC_MSG_RESULT(signed) ], [ AC_MSG_ERROR([failed, do *not* attempt fix this with --disable-mincore unless you are running Win32 or OpenBSD.]) ]) ]) AC_LANG_POP(C++) ]) AC_DEFUN([TORRENT_MINCORE], [ AC_ARG_ENABLE(mincore, AS_HELP_STRING([--disable-mincore], [disable mincore check [[default=enable]]]), [ if test "$enableval" = "yes"; then TORRENT_MINCORE_SIGNEDNESS() else AC_MSG_CHECKING(for mincore) AC_MSG_RESULT(disabled) fi ],[ TORRENT_MINCORE_SIGNEDNESS() ]) ]) AC_DEFUN([TORRENT_CHECK_MADVISE], [ AC_MSG_CHECKING(for madvise) AC_COMPILE_IFELSE([AC_LANG_SOURCE([ #include #include void f() { static char test@<:@1024@:>@; madvise((void *)test, sizeof(test), MADV_NORMAL); } ])], [ AC_MSG_RESULT(yes) AC_DEFINE(USE_MADVISE, 1, Use madvise) ], [ AC_MSG_RESULT(no) ]) ]) AC_DEFUN([TORRENT_CHECK_POSIX_FADVISE], [ AC_MSG_CHECKING(for posix_fadvise) AC_COMPILE_IFELSE([AC_LANG_SOURCE([ #include void f() { posix_fadvise(0, 0, 0, POSIX_FADV_RANDOM); } ])], [ AC_MSG_RESULT(yes) AC_DEFINE(USE_POSIX_FADVISE, 1, Use posix_fadvise) ], [ AC_MSG_RESULT(no) ]) ]) AC_DEFUN([TORRENT_CHECK_POPCOUNT], [ AC_MSG_CHECKING(for __builtin_popcount) AC_COMPILE_IFELSE([AC_LANG_SOURCE([ int f() { return __builtin_popcount(0); } ])], [ AC_MSG_RESULT(yes) AC_DEFINE(USE_BUILTIN_POPCOUNT, 1, Use __builtin_popcount.) ], [ AC_MSG_RESULT(no) ]) ]) AC_DEFUN([TORRENT_CHECK_CACHELINE], [ AC_MSG_CHECKING(for cacheline) AC_COMPILE_IFELSE([AC_LANG_SOURCE([ #include #include void* vptr __cacheline_aligned; void f() { posix_memalign(&vptr, SMP_CACHE_BYTES, 42); } ])], [ AC_MSG_RESULT(found builtin) dnl Need to fix this so that it uses the stuff defined by the system. AC_DEFINE(LT_SMP_CACHE_BYTES, 128, Largest L1 cache size we know of should work on all archs.) ], [ AC_MSG_RESULT(using default 128 bytes) AC_DEFINE(LT_SMP_CACHE_BYTES, 128, Largest L1 cache size we know of should work on all archs.) ]) ]) AC_DEFUN([TORRENT_CHECK_ALIGNED], [ AC_MSG_CHECKING(the byte alignment) AC_RUN_IFELSE([AC_LANG_SOURCE([ #include int main() { char buf@<:@8@:>@ = { 0, 0, 0, 0, 1, 0, 0, 0 }; int i; for (i = 1; i < 4; ++i) if (*(uint32_t*)(buf + i) == 0) return -1; return 0; } ])], [ AC_MSG_RESULT(none needed) ], [ AC_DEFINE(USE_ALIGNED, 1, Require byte alignment) AC_MSG_RESULT(required) ]) ]) AC_DEFUN([TORRENT_ENABLE_ALIGNED], [ AC_ARG_ENABLE(aligned, AS_HELP_STRING([--enable-aligned], [enable alignment safe code [[default=check]]]), [ if test "$enableval" = "yes"; then AC_DEFINE(USE_ALIGNED, 1, Require byte alignment) fi ],[ TORRENT_CHECK_ALIGNED ]) ]) AC_DEFUN([TORRENT_DISABLE_INSTRUMENTATION], [ AC_MSG_CHECKING([if instrumentation should be included]) AC_ARG_ENABLE(instrumentation, AS_HELP_STRING([--disable-instrumentation], [disable instrumentation [[default=enabled]]]), [ if test "$enableval" = "yes"; then AC_DEFINE(LT_INSTRUMENTATION, 1, enable instrumentation) AC_MSG_RESULT(yes) else AC_MSG_RESULT(no) fi ],[ AC_DEFINE(LT_INSTRUMENTATION, 1, enable instrumentation) AC_MSG_RESULT(yes) ]) ]) AC_DEFUN([TORRENT_ENABLE_INTERRUPT_SOCKET], [ AC_ARG_ENABLE(interrupt-socket, AS_HELP_STRING([--enable-interrupt-socket], [enable interrupt socket [[default=no]]]), [ if test "$enableval" = "yes"; then AC_DEFINE(USE_INTERRUPT_SOCKET, 1, Use interrupt socket instead of pthread_kill) fi ] ) ]) AC_DEFUN([TORRENT_DISABLE_IPV6], [ AC_ARG_ENABLE(ipv6, AS_HELP_STRING([--enable-ipv6], [enable ipv6 [[default=no]]]), [ if test "$enableval" = "yes"; then AC_DEFINE(RAK_USE_INET6, 1, enable ipv6 stuff) fi ]) ]) libtorrent-0.16.11/scripts/checks.m40000644000000000000000000002754015175073411012700 AC_DEFUN([TORRENT_CHECK_XFS], [ AC_MSG_CHECKING(for XFS support) AC_COMPILE_IFELSE([AC_LANG_SOURCE([ #include #include int main() { struct xfs_flock64 l; ioctl(0, XFS_IOC_RESVSP64, &l); return 0; } ])], [ AC_DEFINE(USE_XFS, 1, Use XFS filesystem stuff.) AC_MSG_RESULT(yes) ], [ AC_MSG_RESULT(no) ]) ]) AC_DEFUN([TORRENT_WITHOUT_XFS], [ AC_ARG_WITH(xfs, AS_HELP_STRING([--without-xfs],[do not check for XFS filesystem support]), [ if test "$withval" = "yes"; then TORRENT_CHECK_XFS fi ], [ TORRENT_CHECK_XFS ]) ]) AC_DEFUN([TORRENT_WITH_XFS], [ AC_ARG_WITH(xfs, AS_HELP_STRING([--with-xfs],[check for XFS filesystem support]), [ if test "$withval" = "yes"; then TORRENT_CHECK_XFS fi ]) ]) AC_DEFUN([TORRENT_CHECK_EPOLL], [ AC_MSG_CHECKING(for epoll support) AC_COMPILE_IFELSE([AC_LANG_SOURCE([ #include int main() { int fd = epoll_create(100); return 0; } ])], [ AC_DEFINE(USE_EPOLL, 1, Use epoll.) use_epoll=yes AC_MSG_RESULT(yes) ], [ AC_MSG_RESULT(no) ]) ]) AC_DEFUN([TORRENT_WITHOUT_EPOLL], [ AC_ARG_WITH(epoll, AS_HELP_STRING([--without-epoll],[do not check for epoll support]), [ if test "$withval" = "yes"; then TORRENT_CHECK_EPOLL fi ], [ TORRENT_CHECK_EPOLL ]) ]) AC_DEFUN([TORRENT_CHECK_KQUEUE], [ AC_MSG_CHECKING(for kqueue support) AC_LINK_IFELSE([AC_LANG_SOURCE([ #include /* Because OpenBSD's sys/event.h fails to compile otherwise. Yeah... */ #include int main() { int fd = kqueue(); return 0; } ])], [ AC_DEFINE(USE_KQUEUE, 1, Use kqueue.) use_kqueue=yes AC_MSG_RESULT(yes) ], [ AC_MSG_RESULT(no) ]) ]) AC_DEFUN([TORRENT_WITH_KQUEUE], [ AC_ARG_WITH(kqueue, AS_HELP_STRING([--with-kqueue],[enable kqueue [[default=no]]]), [ if test "$withval" = "yes"; then TORRENT_CHECK_KQUEUE fi ]) ]) AC_DEFUN([TORRENT_WITHOUT_KQUEUE], [ AC_ARG_WITH(kqueue, AS_HELP_STRING([--without-kqueue],[do not check for kqueue support]), [ if test "$withval" = "yes"; then TORRENT_CHECK_KQUEUE fi ], [ TORRENT_CHECK_KQUEUE ]) ]) AC_DEFUN([TORRENT_WITHOUT_VARIABLE_FDSET], [ AC_ARG_WITH(variable-fdset, AS_HELP_STRING([--without-variable-fdset],[do not use non-portable variable sized fd_set's]), [ if test "$withval" = "yes"; then AC_DEFINE(USE_VARIABLE_FDSET, 1, defined when we allow the use of fd_set's of any size) fi ], [ AC_DEFINE(USE_VARIABLE_FDSET, 1, defined when we allow the use of fd_set's of any size) ]) ]) AC_DEFUN([TORRENT_CHECK_FALLOCATE], [ AC_MSG_CHECKING(for fallocate) AC_LINK_IFELSE([AC_LANG_PROGRAM([[#define _GNU_SOURCE #include ]], [[ fallocate(0, FALLOC_FL_KEEP_SIZE, 0, 0); return 0; ]])],[ AC_DEFINE(USE_FALLOCATE, 1, Linux's fallocate supported.) AC_MSG_RESULT(yes) ],[ AC_MSG_RESULT(no) ]) ]) AC_DEFUN([TORRENT_CHECK_POSIX_FALLOCATE], [ AC_MSG_CHECKING(for posix_fallocate) AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ posix_fallocate(0, 0, 0); ]])],[ AC_DEFINE(USE_POSIX_FALLOCATE, 1, posix_fallocate supported.) AC_MSG_RESULT(yes) ],[ AC_MSG_RESULT(no) ]) ]) AC_DEFUN([TORRENT_WITH_POSIX_FALLOCATE], [ AC_ARG_WITH(posix-fallocate, AS_HELP_STRING([--with-posix-fallocate],[check for and use posix_fallocate to allocate files]), [ if test "$withval" = "yes"; then TORRENT_CHECK_POSIX_FALLOCATE fi ]) ]) AC_DEFUN([TORRENT_CHECK_STATVFS], [ AC_CHECK_HEADERS(sys/vfs.h sys/statvfs.h sys/statfs.h) AC_MSG_CHECKING(for statvfs) AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #if HAVE_SYS_VFS_H #include #endif #if HAVE_SYS_STATVFS_H #include #endif #if HAVE_SYS_STATFS_H #include #endif ]], [[ struct statvfs s; fsblkcnt_t c; statvfs("", &s); fstatvfs(0, &s); ]])],[ AC_DEFINE(FS_STAT_FD, [fstatvfs(fd, &m_stat) == 0], Function to determine filesystem stats from fd) AC_DEFINE(FS_STAT_FN, [statvfs(fn, &m_stat) == 0], Function to determine filesystem stats from filename) AC_DEFINE(FS_STAT_STRUCT, [struct statvfs], Type of second argument to statfs function) AC_DEFINE(FS_STAT_SIZE_TYPE, [unsigned long], Type of block size member in stat struct) AC_DEFINE(FS_STAT_COUNT_TYPE, [fsblkcnt_t], Type of block count member in stat struct) AC_DEFINE(FS_STAT_BLOCK_SIZE, [(m_stat.f_frsize)], Determine the block size) AC_MSG_RESULT(ok) have_stat_vfs=yes ],[ AC_MSG_RESULT(no) have_stat_vfs=no ]) ]) AC_DEFUN([TORRENT_CHECK_STATFS], [ AC_CHECK_HEADERS(sys/statfs.h) AC_MSG_CHECKING(for statfs) AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #if HAVE_SYS_STATFS_H #include #endif ]], [[ struct statfs s; statfs("", &s); fstatfs(0, &s); ]])],[ AC_DEFINE(FS_STAT_FD, [fstatfs(fd, &m_stat) == 0], Function to determine filesystem stats from fd) AC_DEFINE(FS_STAT_FN, [statfs(fn, &m_stat) == 0], Function to determine filesystem stats from filename) AC_DEFINE(FS_STAT_STRUCT, [struct statfs], Type of second argument to statfs function) AC_DEFINE(FS_STAT_SIZE_TYPE, [long], Type of block size member in stat struct) AC_DEFINE(FS_STAT_COUNT_TYPE, [long], Type of block count member in stat struct) AC_DEFINE(FS_STAT_BLOCK_SIZE, [(m_stat.f_bsize)], Determine the block size) AC_MSG_RESULT(ok) have_stat_vfs=yes ],[ AC_MSG_RESULT(no) have_stat_vfs=no ]) ]) AC_DEFUN([TORRENT_DISABLED_STATFS], [ AC_DEFINE(FS_STAT_FD, [(errno = ENOSYS) == 0], Function to determine filesystem stats from fd) AC_DEFINE(FS_STAT_FN, [(errno = ENOSYS) == 0], Function to determine filesystem stats from filename) AC_DEFINE(FS_STAT_STRUCT, [struct {blocksize_type f_bsize; blockcount_type f_bavail;}], Type of second argument to statfs function) AC_DEFINE(FS_STAT_SIZE_TYPE, [int], Type of block size member in stat struct) AC_DEFINE(FS_STAT_COUNT_TYPE, [int], Type of block count member in stat struct) AC_DEFINE(FS_STAT_BLOCK_SIZE, [(4096)], Determine the block size) AC_MSG_RESULT(No filesystem stats available) ]) AC_DEFUN([TORRENT_WITHOUT_STATVFS], [ AC_ARG_WITH(statvfs, AS_HELP_STRING([--without-statvfs],[don't try to use statvfs to find free diskspace]), [ if test "$withval" = "yes"; then TORRENT_CHECK_STATVFS else have_stat_vfs=no fi ], [ TORRENT_CHECK_STATVFS ]) ]) AC_DEFUN([TORRENT_WITHOUT_STATFS], [ AC_ARG_WITH(statfs, AS_HELP_STRING([--without-statfs],[don't try to use statfs to find free diskspace]), [ if test "$have_stat_vfs" = "no"; then if test "$withval" = "yes"; then TORRENT_CHECK_STATFS else TORRENT_DISABLED_STATFS fi fi ], [ if test "$have_stat_vfs" = "no"; then TORRENT_CHECK_STATFS if test "$have_stat_vfs" = "no"; then TORRENT_DISABLED_STATFS fi fi ]) ]) AC_DEFUN([TORRENT_WITH_ADDRESS_SPACE], [ AC_ARG_WITH(address-space, AS_HELP_STRING([--with-address-space=MB],[change the default address space size [[default=1024mb]]]), [ if test ! -z $withval -a "$withval" != "yes" -a "$withval" != "no"; then AC_DEFINE_UNQUOTED(DEFAULT_ADDRESS_SPACE_SIZE, [$withval]) else AC_MSG_ERROR(--with-address-space requires a parameter.) fi ], [ AC_CHECK_SIZEOF(long) if test $ac_cv_sizeof_long = 8; then AC_DEFINE(DEFAULT_ADDRESS_SPACE_SIZE, 4096, Default address space size.) else AC_DEFINE(DEFAULT_ADDRESS_SPACE_SIZE, 1024, Default address space size.) fi ]) ]) AC_DEFUN([TORRENT_WITH_FASTCGI], [ AC_ARG_WITH(fastcgi, AS_HELP_STRING([--with-fastcgi=PATH],[enable FastCGI RPC support (DO NOT USE)]), [ AC_MSG_CHECKING([for FastCGI (DO NOT USE)]) if test "$withval" = "no"; then AC_MSG_RESULT(no) elif test "$withval" = "yes"; then CXXFLAGS="$CXXFLAGS" LIBS="$LIBS -lfcgi" AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ FCGX_Init(); ]])],[ AC_MSG_RESULT(ok) ],[ AC_MSG_RESULT(not found) AC_MSG_ERROR(Could not compile FastCGI test.) ]) AC_DEFINE(HAVE_FASTCGI, 1, Support for FastCGI.) else CXXFLAGS="$CXXFLAGS -I$withval/include" LIBS="$LIBS -lfcgi -L$withval/lib" AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ FCGX_Init(); ]])],[ AC_MSG_RESULT(ok) ],[ AC_MSG_RESULT(not found) AC_MSG_ERROR(Could not compile FastCGI test.) ]) AC_DEFINE(HAVE_FASTCGI, 1, Support for FastCGI.) fi ]) ]) AC_DEFUN([TORRENT_WITH_XMLRPC_C], [ AC_MSG_CHECKING(for XMLRPC-C) AC_ARG_WITH(xmlrpc-c, AS_HELP_STRING([--with-xmlrpc-c=PATH],[enable XMLRPC-C support]), [ if test "$withval" = "no"; then AC_MSG_RESULT(no) else if test "$withval" = "yes"; then xmlrpc_cc_prg="xmlrpc-c-config" else xmlrpc_cc_prg="$withval" fi if eval $xmlrpc_cc_prg --version 2>/dev/null >/dev/null; then CXXFLAGS="$CXXFLAGS `$xmlrpc_cc_prg --cflags server-util`" LIBS="$LIBS `$xmlrpc_cc_prg server-util --libs`" AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ xmlrpc_registry_new(NULL); ]])],[ AC_MSG_RESULT(ok) ],[ AC_MSG_RESULT(failed) AC_MSG_ERROR(Could not compile XMLRPC-C test.) ]) AC_DEFINE(HAVE_XMLRPC_C, 1, Support for XMLRPC-C.) else AC_MSG_RESULT(failed) AC_MSG_ERROR(Could not compile XMLRPC-C test.) fi fi ],[ AC_MSG_RESULT(ignored) ]) ]) AC_DEFUN([TORRENT_WITH_INOTIFY], [ AC_LANG_PUSH(C++) AC_CHECK_HEADERS([sys/inotify.h]) AC_MSG_CHECKING([whether sys/inotify.h actually works]) AC_COMPILE_IFELSE([AC_LANG_SOURCE([ #include int main(int,const char**) { return (-1 == inotify_init()); }]) ],[ AC_DEFINE(USE_INOTIFY, 1, [sys/inotify.h exists and works correctly]) AC_MSG_RESULT(yes)], [AC_MSG_RESULT(failed)] ) AC_LANG_POP(C++) ]) AC_DEFUN([TORRENT_CHECK_PTHREAD_SETNAME_NP], [ AC_CHECK_HEADERS(pthread.h) AC_MSG_CHECKING(for pthread_setname_np type) AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #define _GNU_SOURCE #include #include ]], [[ pthread_t t; pthread_setname_np(t, "foo"); ]])],[ AC_DEFINE(HAS_PTHREAD_SETNAME_NP_GENERIC, 1, The function to set pthread name has a pthread_t argumet.) AC_MSG_RESULT(generic) ],[ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include #include ]],[[ pthread_t t; pthread_setname_np("foo"); ]])],[ AC_DEFINE(HAS_PTHREAD_SETNAME_NP_DARWIN, 1, The function to set pthread name has no pthread argument.) AC_MSG_RESULT(darwin) ],[ AC_MSG_RESULT(no) ]) ]) ]) AC_DEFUN([TORRENT_DISABLE_PTHREAD_SETNAME_NP], [ AC_MSG_CHECKING([for pthread_setname_no]) AC_ARG_ENABLE(pthread-setname-np, AS_HELP_STRING([--disable-pthread-setname-np],[disable pthread_setname_np]), [ if test "$enableval" = "no"; then AC_MSG_RESULT(disabled) else AC_MSG_RESULT(checking) TORRENT_CHECK_PTHREAD_SETNAME_NP fi ], [ TORRENT_CHECK_PTHREAD_SETNAME_NP ] ) ]) libtorrent-0.16.11/scripts/ax_pthread.m40000644000000000000000000005403415175073411013555 # =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_pthread.html # =========================================================================== # # SYNOPSIS # # AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) # # DESCRIPTION # # This macro figures out how to build C programs using POSIX threads. It # sets the PTHREAD_LIBS output variable to the threads library and linker # flags, and the PTHREAD_CFLAGS output variable to any special C compiler # flags that are needed. (The user can also force certain compiler # flags/libs to be tested by setting these environment variables.) # # Also sets PTHREAD_CC and PTHREAD_CXX to any special C compiler that is # needed for multi-threaded programs (defaults to the value of CC # respectively CXX otherwise). (This is necessary on e.g. AIX to use the # special cc_r/CC_r compiler alias.) # # NOTE: You are assumed to not only compile your program with these flags, # but also to link with them as well. For example, you might link with # $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS # $PTHREAD_CXX $CXXFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS # # If you are only building threaded programs, you may wish to use these # variables in your default LIBS, CFLAGS, and CC: # # LIBS="$PTHREAD_LIBS $LIBS" # CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS" # CC="$PTHREAD_CC" # CXX="$PTHREAD_CXX" # # In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant # has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to # that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX). # # Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the # PTHREAD_PRIO_INHERIT symbol is defined when compiling with # PTHREAD_CFLAGS. # # ACTION-IF-FOUND is a list of shell commands to run if a threads library # is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it # is not found. If ACTION-IF-FOUND is not specified, the default action # will define HAVE_PTHREAD. # # Please let the authors know if this macro fails on any platform, or if # you have any other suggestions or comments. This macro was based on work # by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help # from M. Frigo), as well as ac_pthread and hb_pthread macros posted by # Alejandro Forero Cuervo to the autoconf macro repository. We are also # grateful for the helpful feedback of numerous users. # # Updated for Autoconf 2.68 by Daniel Richard G. # # LICENSE # # Copyright (c) 2008 Steven G. Johnson # Copyright (c) 2011 Daniel Richard G. # Copyright (c) 2019 Marc Stevens # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation, either version 3 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 31 AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) AC_DEFUN([AX_PTHREAD], [ AC_REQUIRE([AC_CANONICAL_HOST]) AC_REQUIRE([AC_PROG_CC]) AC_REQUIRE([AC_PROG_SED]) AC_LANG_PUSH([C]) ax_pthread_ok=no # We used to check for pthread.h first, but this fails if pthread.h # requires special compiler flags (e.g. on Tru64 or Sequent). # It gets checked for in the link test anyway. # First of all, check if the user has set any of the PTHREAD_LIBS, # etcetera environment variables, and if threads linking works using # them: if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then ax_pthread_save_CC="$CC" ax_pthread_save_CFLAGS="$CFLAGS" ax_pthread_save_LIBS="$LIBS" AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"]) AS_IF([test "x$PTHREAD_CXX" != "x"], [CXX="$PTHREAD_CXX"]) CFLAGS="$CFLAGS $PTHREAD_CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS]) AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes]) AC_MSG_RESULT([$ax_pthread_ok]) if test "x$ax_pthread_ok" = "xno"; then PTHREAD_LIBS="" PTHREAD_CFLAGS="" fi CC="$ax_pthread_save_CC" CFLAGS="$ax_pthread_save_CFLAGS" LIBS="$ax_pthread_save_LIBS" fi # We must check for the threads library under a number of different # names; the ordering is very important because some systems # (e.g. DEC) have both -lpthread and -lpthreads, where one of the # libraries is broken (non-POSIX). # Create a list of thread flags to try. Items with a "," contain both # C compiler flags (before ",") and linker flags (after ","). Other items # starting with a "-" are C compiler flags, and remaining items are # library names, except for "none" which indicates that we try without # any flags at all, and "pthread-config" which is a program returning # the flags for the Pth emulation library. ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" # The ordering *is* (sometimes) important. Some notes on the # individual items follow: # pthreads: AIX (must check this before -lpthread) # none: in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) # -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64 # (Note: HP C rejects this with "bad form for `-t' option") # -pthreads: Solaris/gcc (Note: HP C also rejects) # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it # doesn't hurt to check since this sometimes defines pthreads and # -D_REENTRANT too), HP C (must be checked before -lpthread, which # is present but should not be used directly; and before -mthreads, # because the compiler interprets this as "-mt" + "-hreads") # -mthreads: Mingw32/gcc, Lynx/gcc # pthread: Linux, etcetera # --thread-safe: KAI C++ # pthread-config: use pthread-config program (for GNU Pth library) case $host_os in freebsd*) # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) ax_pthread_flags="-kthread lthread $ax_pthread_flags" ;; hpux*) # From the cc(1) man page: "[-mt] Sets various -D flags to enable # multi-threading and also sets -lpthread." ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags" ;; openedition*) # IBM z/OS requires a feature-test macro to be defined in order to # enable POSIX threads at all, so give the user a hint if this is # not set. (We don't define these ourselves, as they can affect # other portions of the system API in unpredictable ways.) AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING], [ # if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS) AX_PTHREAD_ZOS_MISSING # endif ], [AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])]) ;; solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based # tests will erroneously succeed. (N.B.: The stubs are missing # pthread_cleanup_push, or rather a function called by this macro, # so we could check for that, but who knows whether they'll stub # that too in a future libc.) So we'll check first for the # standard Solaris way of linking pthreads (-mt -lpthread). ax_pthread_flags="-mt,-lpthread pthread $ax_pthread_flags" ;; esac # Are we compiling with Clang? AC_CACHE_CHECK([whether $CC is Clang], [ax_cv_PTHREAD_CLANG], [ax_cv_PTHREAD_CLANG=no # Note that Autoconf sets GCC=yes for Clang as well as GCC if test "x$GCC" = "xyes"; then AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG], [/* Note: Clang 2.7 lacks __clang_[a-z]+__ */ # if defined(__clang__) && defined(__llvm__) AX_PTHREAD_CC_IS_CLANG # endif ], [ax_cv_PTHREAD_CLANG=yes]) fi ]) ax_pthread_clang="$ax_cv_PTHREAD_CLANG" # GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC) # Note that for GCC and Clang -pthread generally implies -lpthread, # except when -nostdlib is passed. # This is problematic using libtool to build C++ shared libraries with pthread: # [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25460 # [2] https://bugzilla.redhat.com/show_bug.cgi?id=661333 # [3] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=468555 # To solve this, first try -pthread together with -lpthread for GCC AS_IF([test "x$GCC" = "xyes"], [ax_pthread_flags="-pthread,-lpthread -pthread -pthreads $ax_pthread_flags"]) # Clang takes -pthread (never supported any other flag), but we'll try with -lpthread first AS_IF([test "x$ax_pthread_clang" = "xyes"], [ax_pthread_flags="-pthread,-lpthread -pthread"]) # The presence of a feature test macro requesting re-entrant function # definitions is, on some systems, a strong hint that pthreads support is # correctly enabled case $host_os in darwin* | hpux* | linux* | osf* | solaris*) ax_pthread_check_macro="_REENTRANT" ;; aix*) ax_pthread_check_macro="_THREAD_SAFE" ;; *) ax_pthread_check_macro="--" ;; esac AS_IF([test "x$ax_pthread_check_macro" = "x--"], [ax_pthread_check_cond=0], [ax_pthread_check_cond="!defined($ax_pthread_check_macro)"]) if test "x$ax_pthread_ok" = "xno"; then for ax_pthread_try_flag in $ax_pthread_flags; do case $ax_pthread_try_flag in none) AC_MSG_CHECKING([whether pthreads work without any flags]) ;; *,*) PTHREAD_CFLAGS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\1/"` PTHREAD_LIBS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\2/"` AC_MSG_CHECKING([whether pthreads work with "$PTHREAD_CFLAGS" and "$PTHREAD_LIBS"]) ;; -*) AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag]) PTHREAD_CFLAGS="$ax_pthread_try_flag" ;; pthread-config) AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no]) AS_IF([test "x$ax_pthread_config" = "xno"], [continue]) PTHREAD_CFLAGS="`pthread-config --cflags`" PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" ;; *) AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag]) PTHREAD_LIBS="-l$ax_pthread_try_flag" ;; esac ax_pthread_save_CFLAGS="$CFLAGS" ax_pthread_save_LIBS="$LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" # Check for various functions. We must include pthread.h, # since some functions may be macros. (On the Sequent, we # need a special flag -Kthread to make this header compile.) # We check for pthread_join because it is in -lpthread on IRIX # while pthread_create is in libc. We check for pthread_attr_init # due to DEC craziness with -lpthreads. We check for # pthread_cleanup_push because it is one of the few pthread # functions on Solaris that doesn't have a non-functional libc stub. # We try pthread_create on general principles. AC_LINK_IFELSE([AC_LANG_PROGRAM([#include # if $ax_pthread_check_cond # error "$ax_pthread_check_macro must be defined" # endif static void *some_global = NULL; static void routine(void *a) { /* To avoid any unused-parameter or unused-but-set-parameter warning. */ some_global = a; } static void *start_routine(void *a) { return a; }], [pthread_t th; pthread_attr_t attr; pthread_create(&th, 0, start_routine, 0); pthread_join(th, 0); pthread_attr_init(&attr); pthread_cleanup_push(routine, 0); pthread_cleanup_pop(0) /* ; */])], [ax_pthread_ok=yes], []) CFLAGS="$ax_pthread_save_CFLAGS" LIBS="$ax_pthread_save_LIBS" AC_MSG_RESULT([$ax_pthread_ok]) AS_IF([test "x$ax_pthread_ok" = "xyes"], [break]) PTHREAD_LIBS="" PTHREAD_CFLAGS="" done fi # Clang needs special handling, because older versions handle the -pthread # option in a rather... idiosyncratic way if test "x$ax_pthread_clang" = "xyes"; then # Clang takes -pthread; it has never supported any other flag # (Note 1: This will need to be revisited if a system that Clang # supports has POSIX threads in a separate library. This tends not # to be the way of modern systems, but it's conceivable.) # (Note 2: On some systems, notably Darwin, -pthread is not needed # to get POSIX threads support; the API is always present and # active. We could reasonably leave PTHREAD_CFLAGS empty. But # -pthread does define _REENTRANT, and while the Darwin headers # ignore this macro, third-party headers might not.) # However, older versions of Clang make a point of warning the user # that, in an invocation where only linking and no compilation is # taking place, the -pthread option has no effect ("argument unused # during compilation"). They expect -pthread to be passed in only # when source code is being compiled. # # Problem is, this is at odds with the way Automake and most other # C build frameworks function, which is that the same flags used in # compilation (CFLAGS) are also used in linking. Many systems # supported by AX_PTHREAD require exactly this for POSIX threads # support, and in fact it is often not straightforward to specify a # flag that is used only in the compilation phase and not in # linking. Such a scenario is extremely rare in practice. # # Even though use of the -pthread flag in linking would only print # a warning, this can be a nuisance for well-run software projects # that build with -Werror. So if the active version of Clang has # this misfeature, we search for an option to squash it. AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread], [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG], [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown # Create an alternate version of $ac_link that compiles and # links in two steps (.c -> .o, .o -> exe) instead of one # (.c -> exe), because the warning occurs only in the second # step ax_pthread_save_ac_link="$ac_link" ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g' ax_pthread_link_step=`AS_ECHO(["$ac_link"]) | sed "$ax_pthread_sed"` ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)" ax_pthread_save_CFLAGS="$CFLAGS" for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do AS_IF([test "x$ax_pthread_try" = "xunknown"], [break]) CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS" ac_link="$ax_pthread_save_ac_link" AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], [ac_link="$ax_pthread_2step_ac_link" AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], [break]) ]) done ac_link="$ax_pthread_save_ac_link" CFLAGS="$ax_pthread_save_CFLAGS" AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no]) ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try" ]) case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in no | unknown) ;; *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;; esac fi # $ax_pthread_clang = yes # Various other checks: if test "x$ax_pthread_ok" = "xyes"; then ax_pthread_save_CFLAGS="$CFLAGS" ax_pthread_save_LIBS="$LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. AC_CACHE_CHECK([for joinable pthread attribute], [ax_cv_PTHREAD_JOINABLE_ATTR], [ax_cv_PTHREAD_JOINABLE_ATTR=unknown for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], [int attr = $ax_pthread_attr; return attr /* ; */])], [ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break], []) done ]) AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \ test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \ test "x$ax_pthread_joinable_attr_defined" != "xyes"], [AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], [$ax_cv_PTHREAD_JOINABLE_ATTR], [Define to necessary symbol if this constant uses a non-standard name on your system.]) ax_pthread_joinable_attr_defined=yes ]) AC_CACHE_CHECK([whether more special flags are required for pthreads], [ax_cv_PTHREAD_SPECIAL_FLAGS], [ax_cv_PTHREAD_SPECIAL_FLAGS=no case $host_os in solaris*) ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS" ;; esac ]) AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \ test "x$ax_pthread_special_flags_added" != "xyes"], [PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS" ax_pthread_special_flags_added=yes]) AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], [ax_cv_PTHREAD_PRIO_INHERIT], [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[int i = PTHREAD_PRIO_INHERIT; return i;]])], [ax_cv_PTHREAD_PRIO_INHERIT=yes], [ax_cv_PTHREAD_PRIO_INHERIT=no]) ]) AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \ test "x$ax_pthread_prio_inherit_defined" != "xyes"], [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.]) ax_pthread_prio_inherit_defined=yes ]) CFLAGS="$ax_pthread_save_CFLAGS" LIBS="$ax_pthread_save_LIBS" # More AIX lossage: compile with *_r variant if test "x$GCC" != "xyes"; then case $host_os in aix*) AS_CASE(["x/$CC"], [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6], [#handle absolute path differently from PATH based program lookup AS_CASE(["x$CC"], [x/*], [ AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"]) AS_IF([test "x${CXX}" != "x"], [AS_IF([AS_EXECUTABLE_P([${CXX}_r])],[PTHREAD_CXX="${CXX}_r"])]) ], [ AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC]) AS_IF([test "x${CXX}" != "x"], [AC_CHECK_PROGS([PTHREAD_CXX],[${CXX}_r],[$CXX])]) ] ) ]) ;; esac fi fi test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" test -n "$PTHREAD_CXX" || PTHREAD_CXX="$CXX" AC_SUBST([PTHREAD_LIBS]) AC_SUBST([PTHREAD_CFLAGS]) AC_SUBST([PTHREAD_CC]) AC_SUBST([PTHREAD_CXX]) # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: if test "x$ax_pthread_ok" = "xyes"; then ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1]) : else ax_pthread_ok=no $2 fi AC_LANG_POP ])dnl AX_PTHREAD libtorrent-0.16.11/scripts/lt~obsolete.m40000644000000000000000000001400715175073420014004 # lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # # Copyright (C) 2004-2005, 2007, 2009, 2011-2019, 2021-2022 Free # Software Foundation, Inc. # Written by Scott James Remnant, 2004. # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 5 lt~obsolete.m4 # These exist entirely to fool aclocal when bootstrapping libtool. # # In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN), # which have later been changed to m4_define as they aren't part of the # exported API, or moved to Autoconf or Automake where they belong. # # The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN # in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us # using a macro with the same name in our local m4/libtool.m4 it'll # pull the old libtool.m4 in (it doesn't see our shiny new m4_define # and doesn't know about Autoconf macros at all.) # # So we provide this file, which has a silly filename so it's always # included after everything else. This provides aclocal with the # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything # because those macros already exist, or will be overwritten later. # We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. # # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. # Yes, that means every name once taken will need to remain here until # we give up compatibility with versions before 1.7, at which point # we need to keep only those names which we still refer to. # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) libtorrent-0.16.11/scripts/ax_cxx_compile_stdcxx.m40000644000000000000000000004655015175073411016041 # =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html # =========================================================================== # # SYNOPSIS # # AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional]) # # DESCRIPTION # # Check for baseline language coverage in the compiler for the specified # version of the C++ standard. If necessary, add switches to CXX and # CXXCPP to enable support. VERSION may be '11' (for the C++11 standard) # or '14' (for the C++14 standard). # # The second argument, if specified, indicates whether you insist on an # extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. # -std=c++11). If neither is specified, you get whatever works, with # preference for no added switch, and then for an extended mode. # # The third argument, if specified 'mandatory' or if left unspecified, # indicates that baseline support for the specified C++ standard is # required and that the macro should error out if no mode with that # support is found. If specified 'optional', then configuration proceeds # regardless, after defining HAVE_CXX${VERSION} if and only if a # supporting mode is found. # # LICENSE # # Copyright (c) 2008 Benjamin Kosnik # Copyright (c) 2012 Zack Weinberg # Copyright (c) 2013 Roy Stogner # Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov # Copyright (c) 2015 Paul Norman # Copyright (c) 2015 Moritz Klammler # Copyright (c) 2016, 2018 Krzesimir Nowak # Copyright (c) 2019 Enji Cooper # Copyright (c) 2020 Jason Merrill # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 12 dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro dnl (serial version number 13). AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"], [$1], [14], [ax_cxx_compile_alternatives="14 1y"], [$1], [17], [ax_cxx_compile_alternatives="17 1z"], [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl m4_if([$2], [], [], [$2], [ext], [], [$2], [noext], [], [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true], [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true], [$3], [optional], [ax_cxx_compile_cxx$1_required=false], [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])]) AC_LANG_PUSH([C++])dnl ac_success=no m4_if([$2], [], [dnl AC_CACHE_CHECK(whether $CXX supports C++$1 features by default, ax_cv_cxx_compile_cxx$1, [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], [ax_cv_cxx_compile_cxx$1=yes], [ax_cv_cxx_compile_cxx$1=no])]) if test x$ax_cv_cxx_compile_cxx$1 = xyes; then ac_success=yes fi]) m4_if([$2], [noext], [], [dnl if test x$ac_success = xno; then for alternative in ${ax_cxx_compile_alternatives}; do switch="-std=gnu++${alternative}" cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, $cachevar, [ac_save_CXX="$CXX" CXX="$CXX $switch" AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], [eval $cachevar=yes], [eval $cachevar=no]) CXX="$ac_save_CXX"]) if eval test x\$$cachevar = xyes; then CXX="$CXX $switch" if test -n "$CXXCPP" ; then CXXCPP="$CXXCPP $switch" fi ac_success=yes break fi done fi]) m4_if([$2], [ext], [], [dnl if test x$ac_success = xno; then dnl HP's aCC needs +std=c++11 according to: dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf dnl Cray's crayCC needs "-h std=c++11" for alternative in ${ax_cxx_compile_alternatives}; do for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, $cachevar, [ac_save_CXX="$CXX" CXX="$CXX $switch" AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], [eval $cachevar=yes], [eval $cachevar=no]) CXX="$ac_save_CXX"]) if eval test x\$$cachevar = xyes; then CXX="$CXX $switch" if test -n "$CXXCPP" ; then CXXCPP="$CXXCPP $switch" fi ac_success=yes break fi done if test x$ac_success = xyes; then break fi done fi]) AC_LANG_POP([C++]) if test x$ax_cxx_compile_cxx$1_required = xtrue; then if test x$ac_success = xno; then AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.]) fi fi if test x$ac_success = xno; then HAVE_CXX$1=0 AC_MSG_NOTICE([No compiler with C++$1 support was found]) else HAVE_CXX$1=1 AC_DEFINE(HAVE_CXX$1,1, [define if the compiler supports basic C++$1 syntax]) fi AC_SUBST(HAVE_CXX$1) ]) dnl Test body for checking C++11 support m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 ) dnl Test body for checking C++14 support m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 ) m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17], _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 ) dnl Tests for new features in C++11 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ // If the compiler admits that it is not ready for C++11, why torture it? // Hopefully, this will speed up the test. #ifndef __cplusplus #error "This is not a C++ compiler" #elif __cplusplus < 201103L #error "This is not a C++11 compiler" #else namespace cxx11 { namespace test_static_assert { template struct check { static_assert(sizeof(int) <= sizeof(T), "not big enough"); }; } namespace test_final_override { struct Base { virtual ~Base() {} virtual void f() {} }; struct Derived : public Base { virtual ~Derived() override {} virtual void f() override {} }; } namespace test_double_right_angle_brackets { template < typename T > struct check {}; typedef check single_type; typedef check> double_type; typedef check>> triple_type; typedef check>>> quadruple_type; } namespace test_decltype { int f() { int a = 1; decltype(a) b = 2; return a + b; } } namespace test_type_deduction { template < typename T1, typename T2 > struct is_same { static const bool value = false; }; template < typename T > struct is_same { static const bool value = true; }; template < typename T1, typename T2 > auto add(T1 a1, T2 a2) -> decltype(a1 + a2) { return a1 + a2; } int test(const int c, volatile int v) { static_assert(is_same::value == true, ""); static_assert(is_same::value == false, ""); static_assert(is_same::value == false, ""); auto ac = c; auto av = v; auto sumi = ac + av + 'x'; auto sumf = ac + av + 1.0; static_assert(is_same::value == true, ""); static_assert(is_same::value == true, ""); static_assert(is_same::value == true, ""); static_assert(is_same::value == false, ""); static_assert(is_same::value == true, ""); return (sumf > 0.0) ? sumi : add(c, v); } } namespace test_noexcept { int f() { return 0; } int g() noexcept { return 0; } static_assert(noexcept(f()) == false, ""); static_assert(noexcept(g()) == true, ""); } namespace test_constexpr { template < typename CharT > unsigned long constexpr strlen_c_r(const CharT *const s, const unsigned long acc) noexcept { return *s ? strlen_c_r(s + 1, acc + 1) : acc; } template < typename CharT > unsigned long constexpr strlen_c(const CharT *const s) noexcept { return strlen_c_r(s, 0UL); } static_assert(strlen_c("") == 0UL, ""); static_assert(strlen_c("1") == 1UL, ""); static_assert(strlen_c("example") == 7UL, ""); static_assert(strlen_c("another\0example") == 7UL, ""); } namespace test_rvalue_references { template < int N > struct answer { static constexpr int value = N; }; answer<1> f(int&) { return answer<1>(); } answer<2> f(const int&) { return answer<2>(); } answer<3> f(int&&) { return answer<3>(); } void test() { int i = 0; const int c = 0; static_assert(decltype(f(i))::value == 1, ""); static_assert(decltype(f(c))::value == 2, ""); static_assert(decltype(f(0))::value == 3, ""); } } namespace test_uniform_initialization { struct test { static const int zero {}; static const int one {1}; }; static_assert(test::zero == 0, ""); static_assert(test::one == 1, ""); } namespace test_lambdas { void test1() { auto lambda1 = [](){}; auto lambda2 = lambda1; lambda1(); lambda2(); } int test2() { auto a = [](int i, int j){ return i + j; }(1, 2); auto b = []() -> int { return '0'; }(); auto c = [=](){ return a + b; }(); auto d = [&](){ return c; }(); auto e = [a, &b](int x) mutable { const auto identity = [](int y){ return y; }; for (auto i = 0; i < a; ++i) a += b--; return x + identity(a + b); }(0); return a + b + c + d + e; } int test3() { const auto nullary = [](){ return 0; }; const auto unary = [](int x){ return x; }; using nullary_t = decltype(nullary); using unary_t = decltype(unary); const auto higher1st = [](nullary_t f){ return f(); }; const auto higher2nd = [unary](nullary_t f1){ return [unary, f1](unary_t f2){ return f2(unary(f1())); }; }; return higher1st(nullary) + higher2nd(nullary)(unary); } } namespace test_variadic_templates { template struct sum; template struct sum { static constexpr auto value = N0 + sum::value; }; template <> struct sum<> { static constexpr auto value = 0; }; static_assert(sum<>::value == 0, ""); static_assert(sum<1>::value == 1, ""); static_assert(sum<23>::value == 23, ""); static_assert(sum<1, 2>::value == 3, ""); static_assert(sum<5, 5, 11>::value == 21, ""); static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); } // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function // because of this. namespace test_template_alias_sfinae { struct foo {}; template using member = typename T::member_type; template void func(...) {} template void func(member*) {} void test(); void test() { func(0); } } } // namespace cxx11 #endif // __cplusplus >= 201103L ]]) dnl Tests for new features in C++14 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[ // If the compiler admits that it is not ready for C++14, why torture it? // Hopefully, this will speed up the test. #ifndef __cplusplus #error "This is not a C++ compiler" #elif __cplusplus < 201402L #error "This is not a C++14 compiler" #else namespace cxx14 { namespace test_polymorphic_lambdas { int test() { const auto lambda = [](auto&&... args){ const auto istiny = [](auto x){ return (sizeof(x) == 1UL) ? 1 : 0; }; const int aretiny[] = { istiny(args)... }; return aretiny[0]; }; return lambda(1, 1L, 1.0f, '1'); } } namespace test_binary_literals { constexpr auto ivii = 0b0000000000101010; static_assert(ivii == 42, "wrong value"); } namespace test_generalized_constexpr { template < typename CharT > constexpr unsigned long strlen_c(const CharT *const s) noexcept { auto length = 0UL; for (auto p = s; *p; ++p) ++length; return length; } static_assert(strlen_c("") == 0UL, ""); static_assert(strlen_c("x") == 1UL, ""); static_assert(strlen_c("test") == 4UL, ""); static_assert(strlen_c("another\0test") == 7UL, ""); } namespace test_lambda_init_capture { int test() { auto x = 0; const auto lambda1 = [a = x](int b){ return a + b; }; const auto lambda2 = [a = lambda1(x)](){ return a; }; return lambda2(); } } namespace test_digit_separators { constexpr auto ten_million = 100'000'000; static_assert(ten_million == 100000000, ""); } namespace test_return_type_deduction { auto f(int& x) { return x; } decltype(auto) g(int& x) { return x; } template < typename T1, typename T2 > struct is_same { static constexpr auto value = false; }; template < typename T > struct is_same { static constexpr auto value = true; }; int test() { auto x = 0; static_assert(is_same::value, ""); static_assert(is_same::value, ""); return x; } } } // namespace cxx14 #endif // __cplusplus >= 201402L ]]) dnl Tests for new features in C++17 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[ // If the compiler admits that it is not ready for C++17, why torture it? // Hopefully, this will speed up the test. #ifndef __cplusplus #error "This is not a C++ compiler" #elif __cplusplus < 201703L #error "This is not a C++17 compiler" #else #include #include #include namespace cxx17 { namespace test_constexpr_lambdas { constexpr int foo = [](){return 42;}(); } namespace test::nested_namespace::definitions { } namespace test_fold_expression { template int multiply(Args... args) { return (args * ... * 1); } template bool all(Args... args) { return (args && ...); } } namespace test_extended_static_assert { static_assert (true); } namespace test_auto_brace_init_list { auto foo = {5}; auto bar {5}; static_assert(std::is_same, decltype(foo)>::value); static_assert(std::is_same::value); } namespace test_typename_in_template_template_parameter { template typename X> struct D; } namespace test_fallthrough_nodiscard_maybe_unused_attributes { int f1() { return 42; } [[nodiscard]] int f2() { [[maybe_unused]] auto unused = f1(); switch (f1()) { case 17: f1(); [[fallthrough]]; case 42: f1(); } return f1(); } } namespace test_extended_aggregate_initialization { struct base1 { int b1, b2 = 42; }; struct base2 { base2() { b3 = 42; } int b3; }; struct derived : base1, base2 { int d; }; derived d1 {{1, 2}, {}, 4}; // full initialization derived d2 {{}, {}, 4}; // value-initialized bases } namespace test_general_range_based_for_loop { struct iter { int i; int& operator* () { return i; } const int& operator* () const { return i; } iter& operator++() { ++i; return *this; } }; struct sentinel { int i; }; bool operator== (const iter& i, const sentinel& s) { return i.i == s.i; } bool operator!= (const iter& i, const sentinel& s) { return !(i == s); } struct range { iter begin() const { return {0}; } sentinel end() const { return {5}; } }; void f() { range r {}; for (auto i : r) { [[maybe_unused]] auto v = i; } } } namespace test_lambda_capture_asterisk_this_by_value { struct t { int i; int foo() { return [*this]() { return i; }(); } }; } namespace test_enum_class_construction { enum class byte : unsigned char {}; byte foo {42}; } namespace test_constexpr_if { template int f () { if constexpr(cond) { return 13; } else { return 42; } } } namespace test_selection_statement_with_initializer { int f() { return 13; } int f2() { if (auto i = f(); i > 0) { return 3; } switch (auto i = f(); i + 4) { case 17: return 2; default: return 1; } } } namespace test_template_argument_deduction_for_class_templates { template struct pair { pair (T1 p1, T2 p2) : m1 {p1}, m2 {p2} {} T1 m1; T2 m2; }; void f() { [[maybe_unused]] auto p = pair{13, 42u}; } } namespace test_non_type_auto_template_parameters { template struct B {}; B<5> b1; B<'a'> b2; } namespace test_structured_bindings { int arr[2] = { 1, 2 }; std::pair pr = { 1, 2 }; auto f1() -> int(&)[2] { return arr; } auto f2() -> std::pair& { return pr; } struct S { int x1 : 2; volatile double y1; }; S f3() { return {}; } auto [ x1, y1 ] = f1(); auto& [ xr1, yr1 ] = f1(); auto [ x2, y2 ] = f2(); auto& [ xr2, yr2 ] = f2(); const auto [ x3, y3 ] = f3(); } namespace test_exception_spec_type_system { struct Good {}; struct Bad {}; void g1() noexcept; void g2(); template Bad f(T*, T*); template Good f(T1*, T2*); static_assert (std::is_same_v); } namespace test_inline_variables { template void f(T) {} template inline T g(T) { return T{}; } template<> inline void f<>(int) {} template<> int g<>(int) { return 5; } } } // namespace cxx17 #endif // __cplusplus < 201703L ]]) libtorrent-0.16.11/scripts/ltoptions.m40000644000000000000000000003427515175073420013476 # Helper functions for option handling. -*- Autoconf -*- # # Copyright (C) 2004-2005, 2007-2009, 2011-2019, 2021-2022 Free # Software Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 8 ltoptions.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) # _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) # ------------------------------------------ m4_define([_LT_MANGLE_OPTION], [[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) # _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) # --------------------------------------- # Set option OPTION-NAME for macro MACRO-NAME, and if there is a # matching handler defined, dispatch to it. Other OPTION-NAMEs are # saved as a flag. m4_define([_LT_SET_OPTION], [m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), _LT_MANGLE_DEFUN([$1], [$2]), [m4_warning([Unknown $1 option '$2'])])[]dnl ]) # _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) # ------------------------------------------------------------ # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. m4_define([_LT_IF_OPTION], [m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) # _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) # ------------------------------------------------------- # Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME # are set. m4_define([_LT_UNLESS_OPTIONS], [m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), [m4_define([$0_found])])])[]dnl m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 ])[]dnl ]) # _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) # ---------------------------------------- # OPTION-LIST is a space-separated list of Libtool options associated # with MACRO-NAME. If any OPTION has a matching handler declared with # LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about # the unknown option and exit. m4_defun([_LT_SET_OPTIONS], [# Set options m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [_LT_SET_OPTION([$1], _LT_Option)]) m4_if([$1],[LT_INIT],[ dnl dnl Simply set some default values (i.e off) if boolean options were not dnl specified: _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no ]) _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no ]) dnl dnl If no reference was made to various pairs of opposing options, then dnl we run the default mode handler for the pair. For example, if neither dnl 'shared' nor 'disable-shared' was passed, we enable building of shared dnl archives by default: _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], [_LT_ENABLE_FAST_INSTALL]) _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4], [_LT_WITH_AIX_SONAME([aix])]) ]) ])# _LT_SET_OPTIONS ## --------------------------------- ## ## Macros to handle LT_INIT options. ## ## --------------------------------- ## # _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) # ----------------------------------------- m4_define([_LT_MANGLE_DEFUN], [[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) # LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) # ----------------------------------------------- m4_define([LT_OPTION_DEFINE], [m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl ])# LT_OPTION_DEFINE # dlopen # ------ LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes ]) AU_DEFUN([AC_LIBTOOL_DLOPEN], [_LT_SET_OPTION([LT_INIT], [dlopen]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'dlopen' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) # win32-dll # --------- # Declare package support for building win32 dll's. LT_OPTION_DEFINE([LT_INIT], [win32-dll], [enable_win32_dll=yes case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) AC_CHECK_TOOL(AS, as, false) AC_CHECK_TOOL(DLLTOOL, dlltool, false) AC_CHECK_TOOL(OBJDUMP, objdump, false) ;; esac test -z "$AS" && AS=as _LT_DECL([], [AS], [1], [Assembler program])dnl test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl ])# win32-dll AU_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_REQUIRE([AC_CANONICAL_HOST])dnl _LT_SET_OPTION([LT_INIT], [win32-dll]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'win32-dll' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) # _LT_ENABLE_SHARED([DEFAULT]) # ---------------------------- # implement the --enable-shared flag, and supports the 'shared' and # 'disable-shared' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_SHARED], [m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([shared], [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS=$lt_save_ifs ;; esac], [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) _LT_DECL([build_libtool_libs], [enable_shared], [0], [Whether or not to build shared libraries]) ])# _LT_ENABLE_SHARED LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) # Old names: AC_DEFUN([AC_ENABLE_SHARED], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) ]) AC_DEFUN([AC_DISABLE_SHARED], [_LT_SET_OPTION([LT_INIT], [disable-shared]) ]) AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_SHARED], []) dnl AC_DEFUN([AM_DISABLE_SHARED], []) # _LT_ENABLE_STATIC([DEFAULT]) # ---------------------------- # implement the --enable-static flag, and support the 'static' and # 'disable-static' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_STATIC], [m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([static], [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS=$lt_save_ifs ;; esac], [enable_static=]_LT_ENABLE_STATIC_DEFAULT) _LT_DECL([build_old_libs], [enable_static], [0], [Whether or not to build static libraries]) ])# _LT_ENABLE_STATIC LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) # Old names: AC_DEFUN([AC_ENABLE_STATIC], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) ]) AC_DEFUN([AC_DISABLE_STATIC], [_LT_SET_OPTION([LT_INIT], [disable-static]) ]) AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_STATIC], []) dnl AC_DEFUN([AM_DISABLE_STATIC], []) # _LT_ENABLE_FAST_INSTALL([DEFAULT]) # ---------------------------------- # implement the --enable-fast-install flag, and support the 'fast-install' # and 'disable-fast-install' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_FAST_INSTALL], [m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([fast-install], [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS=$lt_save_ifs ;; esac], [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) _LT_DECL([fast_install], [enable_fast_install], [0], [Whether or not to optimize for fast installation])dnl ])# _LT_ENABLE_FAST_INSTALL LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) # Old names: AU_DEFUN([AC_ENABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'fast-install' option into LT_INIT's first parameter.]) ]) AU_DEFUN([AC_DISABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], [disable-fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'disable-fast-install' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) # _LT_WITH_AIX_SONAME([DEFAULT]) # ---------------------------------- # implement the --with-aix-soname flag, and support the `aix-soname=aix' # and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT # is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'. m4_define([_LT_WITH_AIX_SONAME], [m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl shared_archive_member_spec= case $host,$enable_shared in power*-*-aix[[5-9]]*,yes) AC_MSG_CHECKING([which variant of shared library versioning to provide]) AC_ARG_WITH([aix-soname], [AS_HELP_STRING([--with-aix-soname=aix|svr4|both], [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])], [case $withval in aix|svr4|both) ;; *) AC_MSG_ERROR([Unknown argument to --with-aix-soname]) ;; esac lt_cv_with_aix_soname=$with_aix_soname], [AC_CACHE_VAL([lt_cv_with_aix_soname], [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT) with_aix_soname=$lt_cv_with_aix_soname]) AC_MSG_RESULT([$with_aix_soname]) if test aix != "$with_aix_soname"; then # For the AIX way of multilib, we name the shared archive member # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, # the AIX toolchain works better with OBJECT_MODE set (default 32). if test 64 = "${OBJECT_MODE-32}"; then shared_archive_member_spec=shr_64 else shared_archive_member_spec=shr fi fi ;; *) with_aix_soname=aix ;; esac _LT_DECL([], [shared_archive_member_spec], [0], [Shared archive member basename, for filename based shared library versioning on AIX])dnl ])# _LT_WITH_AIX_SONAME LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])]) LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])]) LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])]) # _LT_WITH_PIC([MODE]) # -------------------- # implement the --with-pic flag, and support the 'pic-only' and 'no-pic' # LT_INIT options. # MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'. m4_define([_LT_WITH_PIC], [AC_ARG_WITH([pic], [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], [lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for lt_pkg in $withval; do IFS=$lt_save_ifs if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS=$lt_save_ifs ;; esac], [pic_mode=m4_default([$1], [default])]) _LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl ])# _LT_WITH_PIC LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) # Old name: AU_DEFUN([AC_LIBTOOL_PICMODE], [_LT_SET_OPTION([LT_INIT], [pic-only]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'pic-only' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) ## ----------------- ## ## LTDL_INIT Options ## ## ----------------- ## m4_define([_LTDL_MODE], []) LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], [m4_define([_LTDL_MODE], [nonrecursive])]) LT_OPTION_DEFINE([LTDL_INIT], [recursive], [m4_define([_LTDL_MODE], [recursive])]) LT_OPTION_DEFINE([LTDL_INIT], [subproject], [m4_define([_LTDL_MODE], [subproject])]) m4_define([_LTDL_TYPE], []) LT_OPTION_DEFINE([LTDL_INIT], [installable], [m4_define([_LTDL_TYPE], [installable])]) LT_OPTION_DEFINE([LTDL_INIT], [convenience], [m4_define([_LTDL_TYPE], [convenience])]) libtorrent-0.16.11/scripts/ltversion.m40000644000000000000000000000131215175073420013452 # ltversion.m4 -- version numbers -*- Autoconf -*- # # Copyright (C) 2004, 2011-2019, 2021-2022 Free Software Foundation, # Inc. # Written by Scott James Remnant, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # @configure_input@ # serial 4245 ltversion.m4 # This file is part of GNU Libtool m4_define([LT_PACKAGE_VERSION], [2.4.7]) m4_define([LT_PACKAGE_REVISION], [2.4.7]) AC_DEFUN([LTVERSION_VERSION], [macro_version='2.4.7' macro_revision='2.4.7' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) ]) libtorrent-0.16.11/config.sub0000755000000000000000000010775615175073426011510 #! /bin/sh # Configuration validation subroutine script. # Copyright 1992-2024 Free Software Foundation, Inc. # shellcheck disable=SC2006,SC2268 # see below for rationale timestamp='2024-01-01' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # Please send patches to . # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: # https://git.savannah.gnu.org/cgit/config.git/plain/config.sub # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. # The "shellcheck disable" line above the timestamp inhibits complaints # about features and limitations of the classic Bourne shell that were # superseded or lifted in POSIX. However, this script identifies a wide # variety of pre-POSIX systems that do not have POSIX shells at all, and # even some reasonably current systems (Solaris 10 as case-in-point) still # have a pre-POSIX /bin/sh. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS Canonicalize a configuration name. Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright 1992-2024 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try '$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; *local*) # First pass through any local machine types. echo "$1" exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Split fields of configuration type # shellcheck disable=SC2162 saved_IFS=$IFS IFS="-" read field1 field2 field3 field4 <&2 exit 1 ;; *-*-*-*) basic_machine=$field1-$field2 basic_os=$field3-$field4 ;; *-*-*) # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two # parts maybe_os=$field2-$field3 case $maybe_os in nto-qnx* | linux-* | uclinux-uclibc* \ | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \ | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \ | storm-chaos* | os2-emx* | rtmk-nova* | managarm-* \ | windows-* ) basic_machine=$field1 basic_os=$maybe_os ;; android-linux) basic_machine=$field1-unknown basic_os=linux-android ;; *) basic_machine=$field1-$field2 basic_os=$field3 ;; esac ;; *-*) # A lone config we happen to match not fitting any pattern case $field1-$field2 in decstation-3100) basic_machine=mips-dec basic_os= ;; *-*) # Second component is usually, but not always the OS case $field2 in # Prevent following clause from handling this valid os sun*os*) basic_machine=$field1 basic_os=$field2 ;; zephyr*) basic_machine=$field1-unknown basic_os=$field2 ;; # Manufacturers dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \ | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \ | unicom* | ibm* | next | hp | isi* | apollo | altos* \ | convergent* | ncr* | news | 32* | 3600* | 3100* \ | hitachi* | c[123]* | convex* | sun | crds | omron* | dg \ | ultra | tti* | harris | dolphin | highlevel | gould \ | cbm | ns | masscomp | apple | axis | knuth | cray \ | microblaze* | sim | cisco \ | oki | wec | wrs | winbond) basic_machine=$field1-$field2 basic_os= ;; *) basic_machine=$field1 basic_os=$field2 ;; esac ;; esac ;; *) # Convert single-component short-hands not valid as part of # multi-component configurations. case $field1 in 386bsd) basic_machine=i386-pc basic_os=bsd ;; a29khif) basic_machine=a29k-amd basic_os=udi ;; adobe68k) basic_machine=m68010-adobe basic_os=scout ;; alliant) basic_machine=fx80-alliant basic_os= ;; altos | altos3068) basic_machine=m68k-altos basic_os= ;; am29k) basic_machine=a29k-none basic_os=bsd ;; amdahl) basic_machine=580-amdahl basic_os=sysv ;; amiga) basic_machine=m68k-unknown basic_os= ;; amigaos | amigados) basic_machine=m68k-unknown basic_os=amigaos ;; amigaunix | amix) basic_machine=m68k-unknown basic_os=sysv4 ;; apollo68) basic_machine=m68k-apollo basic_os=sysv ;; apollo68bsd) basic_machine=m68k-apollo basic_os=bsd ;; aros) basic_machine=i386-pc basic_os=aros ;; aux) basic_machine=m68k-apple basic_os=aux ;; balance) basic_machine=ns32k-sequent basic_os=dynix ;; blackfin) basic_machine=bfin-unknown basic_os=linux ;; cegcc) basic_machine=arm-unknown basic_os=cegcc ;; convex-c1) basic_machine=c1-convex basic_os=bsd ;; convex-c2) basic_machine=c2-convex basic_os=bsd ;; convex-c32) basic_machine=c32-convex basic_os=bsd ;; convex-c34) basic_machine=c34-convex basic_os=bsd ;; convex-c38) basic_machine=c38-convex basic_os=bsd ;; cray) basic_machine=j90-cray basic_os=unicos ;; crds | unos) basic_machine=m68k-crds basic_os= ;; da30) basic_machine=m68k-da30 basic_os= ;; decstation | pmax | pmin | dec3100 | decstatn) basic_machine=mips-dec basic_os= ;; delta88) basic_machine=m88k-motorola basic_os=sysv3 ;; dicos) basic_machine=i686-pc basic_os=dicos ;; djgpp) basic_machine=i586-pc basic_os=msdosdjgpp ;; ebmon29k) basic_machine=a29k-amd basic_os=ebmon ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson basic_os=ose ;; gmicro) basic_machine=tron-gmicro basic_os=sysv ;; go32) basic_machine=i386-pc basic_os=go32 ;; h8300hms) basic_machine=h8300-hitachi basic_os=hms ;; h8300xray) basic_machine=h8300-hitachi basic_os=xray ;; h8500hms) basic_machine=h8500-hitachi basic_os=hms ;; harris) basic_machine=m88k-harris basic_os=sysv3 ;; hp300 | hp300hpux) basic_machine=m68k-hp basic_os=hpux ;; hp300bsd) basic_machine=m68k-hp basic_os=bsd ;; hppaosf) basic_machine=hppa1.1-hp basic_os=osf ;; hppro) basic_machine=hppa1.1-hp basic_os=proelf ;; i386mach) basic_machine=i386-mach basic_os=mach ;; isi68 | isi) basic_machine=m68k-isi basic_os=sysv ;; m68knommu) basic_machine=m68k-unknown basic_os=linux ;; magnum | m3230) basic_machine=mips-mips basic_os=sysv ;; merlin) basic_machine=ns32k-utek basic_os=sysv ;; mingw64) basic_machine=x86_64-pc basic_os=mingw64 ;; mingw32) basic_machine=i686-pc basic_os=mingw32 ;; mingw32ce) basic_machine=arm-unknown basic_os=mingw32ce ;; monitor) basic_machine=m68k-rom68k basic_os=coff ;; morphos) basic_machine=powerpc-unknown basic_os=morphos ;; moxiebox) basic_machine=moxie-unknown basic_os=moxiebox ;; msdos) basic_machine=i386-pc basic_os=msdos ;; msys) basic_machine=i686-pc basic_os=msys ;; mvs) basic_machine=i370-ibm basic_os=mvs ;; nacl) basic_machine=le32-unknown basic_os=nacl ;; ncr3000) basic_machine=i486-ncr basic_os=sysv4 ;; netbsd386) basic_machine=i386-pc basic_os=netbsd ;; netwinder) basic_machine=armv4l-rebel basic_os=linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony basic_os=newsos ;; news1000) basic_machine=m68030-sony basic_os=newsos ;; necv70) basic_machine=v70-nec basic_os=sysv ;; nh3000) basic_machine=m68k-harris basic_os=cxux ;; nh[45]000) basic_machine=m88k-harris basic_os=cxux ;; nindy960) basic_machine=i960-intel basic_os=nindy ;; mon960) basic_machine=i960-intel basic_os=mon960 ;; nonstopux) basic_machine=mips-compaq basic_os=nonstopux ;; os400) basic_machine=powerpc-ibm basic_os=os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson basic_os=ose ;; os68k) basic_machine=m68k-none basic_os=os68k ;; paragon) basic_machine=i860-intel basic_os=osf ;; parisc) basic_machine=hppa-unknown basic_os=linux ;; psp) basic_machine=mipsallegrexel-sony basic_os=psp ;; pw32) basic_machine=i586-unknown basic_os=pw32 ;; rdos | rdos64) basic_machine=x86_64-pc basic_os=rdos ;; rdos32) basic_machine=i386-pc basic_os=rdos ;; rom68k) basic_machine=m68k-rom68k basic_os=coff ;; sa29200) basic_machine=a29k-amd basic_os=udi ;; sei) basic_machine=mips-sei basic_os=seiux ;; sequent) basic_machine=i386-sequent basic_os= ;; sps7) basic_machine=m68k-bull basic_os=sysv2 ;; st2000) basic_machine=m68k-tandem basic_os= ;; stratus) basic_machine=i860-stratus basic_os=sysv4 ;; sun2) basic_machine=m68000-sun basic_os= ;; sun2os3) basic_machine=m68000-sun basic_os=sunos3 ;; sun2os4) basic_machine=m68000-sun basic_os=sunos4 ;; sun3) basic_machine=m68k-sun basic_os= ;; sun3os3) basic_machine=m68k-sun basic_os=sunos3 ;; sun3os4) basic_machine=m68k-sun basic_os=sunos4 ;; sun4) basic_machine=sparc-sun basic_os= ;; sun4os3) basic_machine=sparc-sun basic_os=sunos3 ;; sun4os4) basic_machine=sparc-sun basic_os=sunos4 ;; sun4sol2) basic_machine=sparc-sun basic_os=solaris2 ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun basic_os= ;; sv1) basic_machine=sv1-cray basic_os=unicos ;; symmetry) basic_machine=i386-sequent basic_os=dynix ;; t3e) basic_machine=alphaev5-cray basic_os=unicos ;; t90) basic_machine=t90-cray basic_os=unicos ;; toad1) basic_machine=pdp10-xkl basic_os=tops20 ;; tpf) basic_machine=s390x-ibm basic_os=tpf ;; udi29k) basic_machine=a29k-amd basic_os=udi ;; ultra3) basic_machine=a29k-nyu basic_os=sym1 ;; v810 | necv810) basic_machine=v810-nec basic_os=none ;; vaxv) basic_machine=vax-dec basic_os=sysv ;; vms) basic_machine=vax-dec basic_os=vms ;; vsta) basic_machine=i386-pc basic_os=vsta ;; vxworks960) basic_machine=i960-wrs basic_os=vxworks ;; vxworks68) basic_machine=m68k-wrs basic_os=vxworks ;; vxworks29k) basic_machine=a29k-wrs basic_os=vxworks ;; xbox) basic_machine=i686-pc basic_os=mingw32 ;; ymp) basic_machine=ymp-cray basic_os=unicos ;; *) basic_machine=$1 basic_os= ;; esac ;; esac # Decode 1-component or ad-hoc basic machines case $basic_machine in # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) cpu=hppa1.1 vendor=winbond ;; op50n) cpu=hppa1.1 vendor=oki ;; op60c) cpu=hppa1.1 vendor=oki ;; ibm*) cpu=i370 vendor=ibm ;; orion105) cpu=clipper vendor=highlevel ;; mac | mpw | mac-mpw) cpu=m68k vendor=apple ;; pmac | pmac-mpw) cpu=powerpc vendor=apple ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) cpu=m68000 vendor=att ;; 3b*) cpu=we32k vendor=att ;; bluegene*) cpu=powerpc vendor=ibm basic_os=cnk ;; decsystem10* | dec10*) cpu=pdp10 vendor=dec basic_os=tops10 ;; decsystem20* | dec20*) cpu=pdp10 vendor=dec basic_os=tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) cpu=m68k vendor=motorola ;; dpx2*) cpu=m68k vendor=bull basic_os=sysv3 ;; encore | umax | mmax) cpu=ns32k vendor=encore ;; elxsi) cpu=elxsi vendor=elxsi basic_os=${basic_os:-bsd} ;; fx2800) cpu=i860 vendor=alliant ;; genix) cpu=ns32k vendor=ns ;; h3050r* | hiux*) cpu=hppa1.1 vendor=hitachi basic_os=hiuxwe2 ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) cpu=hppa1.0 vendor=hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) cpu=m68000 vendor=hp ;; hp9k3[2-9][0-9]) cpu=m68k vendor=hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) cpu=hppa1.0 vendor=hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) cpu=hppa1.1 vendor=hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp cpu=hppa1.1 vendor=hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp cpu=hppa1.1 vendor=hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) cpu=hppa1.1 vendor=hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) cpu=hppa1.0 vendor=hp ;; i*86v32) cpu=`echo "$1" | sed -e 's/86.*/86/'` vendor=pc basic_os=sysv32 ;; i*86v4*) cpu=`echo "$1" | sed -e 's/86.*/86/'` vendor=pc basic_os=sysv4 ;; i*86v) cpu=`echo "$1" | sed -e 's/86.*/86/'` vendor=pc basic_os=sysv ;; i*86sol2) cpu=`echo "$1" | sed -e 's/86.*/86/'` vendor=pc basic_os=solaris2 ;; j90 | j90-cray) cpu=j90 vendor=cray basic_os=${basic_os:-unicos} ;; iris | iris4d) cpu=mips vendor=sgi case $basic_os in irix*) ;; *) basic_os=irix4 ;; esac ;; miniframe) cpu=m68000 vendor=convergent ;; *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*) cpu=m68k vendor=atari basic_os=mint ;; news-3600 | risc-news) cpu=mips vendor=sony basic_os=newsos ;; next | m*-next) cpu=m68k vendor=next case $basic_os in openstep*) ;; nextstep*) ;; ns2*) basic_os=nextstep2 ;; *) basic_os=nextstep3 ;; esac ;; np1) cpu=np1 vendor=gould ;; op50n-* | op60c-*) cpu=hppa1.1 vendor=oki basic_os=proelf ;; pa-hitachi) cpu=hppa1.1 vendor=hitachi basic_os=hiuxwe2 ;; pbd) cpu=sparc vendor=tti ;; pbb) cpu=m68k vendor=tti ;; pc532) cpu=ns32k vendor=pc532 ;; pn) cpu=pn vendor=gould ;; power) cpu=power vendor=ibm ;; ps2) cpu=i386 vendor=ibm ;; rm[46]00) cpu=mips vendor=siemens ;; rtpc | rtpc-*) cpu=romp vendor=ibm ;; sde) cpu=mipsisa32 vendor=sde basic_os=${basic_os:-elf} ;; simso-wrs) cpu=sparclite vendor=wrs basic_os=vxworks ;; tower | tower-32) cpu=m68k vendor=ncr ;; vpp*|vx|vx-*) cpu=f301 vendor=fujitsu ;; w65) cpu=w65 vendor=wdc ;; w89k-*) cpu=hppa1.1 vendor=winbond basic_os=proelf ;; none) cpu=none vendor=none ;; leon|leon[3-9]) cpu=sparc vendor=$basic_machine ;; leon-*|leon[3-9]-*) cpu=sparc vendor=`echo "$basic_machine" | sed 's/-.*//'` ;; *-*) # shellcheck disable=SC2162 saved_IFS=$IFS IFS="-" read cpu vendor <&2 exit 1 ;; esac ;; esac # Here we canonicalize certain aliases for manufacturers. case $vendor in digital*) vendor=dec ;; commodore*) vendor=cbm ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if test x"$basic_os" != x then # First recognize some ad-hoc cases, or perhaps split kernel-os, or else just # set os. obj= case $basic_os in gnu/linux*) kernel=linux os=`echo "$basic_os" | sed -e 's|gnu/linux|gnu|'` ;; os2-emx) kernel=os2 os=`echo "$basic_os" | sed -e 's|os2-emx|emx|'` ;; nto-qnx*) kernel=nto os=`echo "$basic_os" | sed -e 's|nto-qnx|qnx|'` ;; *-*) # shellcheck disable=SC2162 saved_IFS=$IFS IFS="-" read kernel os <&2 fi ;; *) echo "Invalid configuration '$1': OS '$os' not recognized" 1>&2 exit 1 ;; esac case $obj in aout* | coff* | elf* | pe*) ;; '') # empty is fine ;; *) echo "Invalid configuration '$1': Machine code format '$obj' not recognized" 1>&2 exit 1 ;; esac # Here we handle the constraint that a (synthetic) cpu and os are # valid only in combination with each other and nowhere else. case $cpu-$os in # The "javascript-unknown-ghcjs" triple is used by GHC; we # accept it here in order to tolerate that, but reject any # variations. javascript-ghcjs) ;; javascript-* | *-ghcjs) echo "Invalid configuration '$1': cpu '$cpu' is not valid with os '$os$obj'" 1>&2 exit 1 ;; esac # As a final step for OS-related things, validate the OS-kernel combination # (given a valid OS), if there is a kernel. case $kernel-$os-$obj in linux-gnu*- | linux-android*- | linux-dietlibc*- | linux-llvm*- \ | linux-mlibc*- | linux-musl*- | linux-newlib*- \ | linux-relibc*- | linux-uclibc*- ) ;; uclinux-uclibc*- ) ;; managarm-mlibc*- | managarm-kernel*- ) ;; windows*-msvc*-) ;; -dietlibc*- | -llvm*- | -mlibc*- | -musl*- | -newlib*- | -relibc*- \ | -uclibc*- ) # These are just libc implementations, not actual OSes, and thus # require a kernel. echo "Invalid configuration '$1': libc '$os' needs explicit kernel." 1>&2 exit 1 ;; -kernel*- ) echo "Invalid configuration '$1': '$os' needs explicit kernel." 1>&2 exit 1 ;; *-kernel*- ) echo "Invalid configuration '$1': '$kernel' does not support '$os'." 1>&2 exit 1 ;; *-msvc*- ) echo "Invalid configuration '$1': '$os' needs 'windows'." 1>&2 exit 1 ;; kfreebsd*-gnu*- | kopensolaris*-gnu*-) ;; vxworks-simlinux- | vxworks-simwindows- | vxworks-spe-) ;; nto-qnx*-) ;; os2-emx-) ;; *-eabi*- | *-gnueabi*-) ;; none--*) # None (no kernel, i.e. freestanding / bare metal), # can be paired with an machine code file format ;; -*-) # Blank kernel with real OS is always fine. ;; --*) # Blank kernel and OS with real machine code file format is always fine. ;; *-*-*) echo "Invalid configuration '$1': Kernel '$kernel' not known to work with OS '$os'." 1>&2 exit 1 ;; esac # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. case $vendor in unknown) case $cpu-$os in *-riscix*) vendor=acorn ;; *-sunos*) vendor=sun ;; *-cnk* | *-aix*) vendor=ibm ;; *-beos*) vendor=be ;; *-hpux*) vendor=hp ;; *-mpeix*) vendor=hp ;; *-hiux*) vendor=hitachi ;; *-unos*) vendor=crds ;; *-dgux*) vendor=dg ;; *-luna*) vendor=omron ;; *-genix*) vendor=ns ;; *-clix*) vendor=intergraph ;; *-mvs* | *-opened*) vendor=ibm ;; *-os400*) vendor=ibm ;; s390-* | s390x-*) vendor=ibm ;; *-ptx*) vendor=sequent ;; *-tpf*) vendor=ibm ;; *-vxsim* | *-vxworks* | *-windiss*) vendor=wrs ;; *-aux*) vendor=apple ;; *-hms*) vendor=hitachi ;; *-mpw* | *-macos*) vendor=apple ;; *-*mint | *-mint[0-9]* | *-*MiNT | *-MiNT[0-9]*) vendor=atari ;; *-vos*) vendor=stratus ;; esac ;; esac echo "$cpu-$vendor${kernel:+-$kernel}${os:+-$os}${obj:+-$obj}" exit # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: libtorrent-0.16.11/Makefile.in0000644000000000000000000007264115175073426011564 # Makefile.in generated by automake 1.17 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2024 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) am__rm_f = rm -f $(am__rm_f_notfound) am__rm_rf = rm -rf $(am__rm_f_notfound) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/scripts/attributes.m4 \ $(top_srcdir)/scripts/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/scripts/ax_execinfo.m4 \ $(top_srcdir)/scripts/ax_pthread.m4 \ $(top_srcdir)/scripts/check_atomic.m4 \ $(top_srcdir)/scripts/checks.m4 \ $(top_srcdir)/scripts/common.m4 \ $(top_srcdir)/scripts/libtool.m4 \ $(top_srcdir)/scripts/ltoptions.m4 \ $(top_srcdir)/scripts/ltsugar.m4 \ $(top_srcdir)/scripts/ltversion.m4 \ $(top_srcdir)/scripts/lt~obsolete.m4 \ $(top_srcdir)/scripts/rak_compiler.m4 \ $(top_srcdir)/scripts/ssl.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ $(am__configure_deps) $(am__DIST_COMMON) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = libtorrent.pc CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && echo $$files | $(am__xargs_n) 40 $(am__rm_f); }; \ } am__installdirs = "$(DESTDIR)$(pkgconfigdir)" DATA = $(pkgconfig_DATA) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ cscope distdir distdir-am dist dist-all distcheck am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) \ config.h.in # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \ $(srcdir)/libtorrent.pc.in AUTHORS COPYING INSTALL README.md \ compile config.guess config.sub install-sh ltmain.sh missing DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ if test -d "$(distdir)"; then \ find "$(distdir)" -type d ! -perm -700 -exec chmod u+rwx {} ';' \ ; rm -rf "$(distdir)" \ || { sleep 5 && rm -rf "$(distdir)"; }; \ else :; fi am__post_remove_distdir = $(am__remove_distdir) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = -9 DIST_TARGETS = dist-gzip # Exists only to be overridden by the user if desired. AM_DISTCHECK_DVI_TARGET = dvi distuninstallcheck_listfiles = find . -type f -print am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' distcleancheck_listfiles = \ find . \( -type f -a \! \ \( -name .nfs* -o -name .smb* -o -name .__afs* \) \) -print ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ ATOMIC_LIBS = @ATOMIC_LIBS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPUNIT_CFLAGS = @CPPUNIT_CFLAGS@ CPPUNIT_LIBS = @CPPUNIT_LIBS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FILECMD = @FILECMD@ GREP = @GREP@ HAVE_CXX17 = @HAVE_CXX17@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBCURL = @LIBCURL@ LIBCURL_CFLAGS = @LIBCURL_CFLAGS@ LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@ LIBCURL_LIBS = @LIBCURL_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTORRENT_CFLAGS = @LIBTORRENT_CFLAGS@ LIBTORRENT_CURRENT = @LIBTORRENT_CURRENT@ LIBTORRENT_INTERFACE_VERSION_INFO = @LIBTORRENT_INTERFACE_VERSION_INFO@ LIBTORRENT_INTERFACE_VERSION_NO = @LIBTORRENT_INTERFACE_VERSION_NO@ LIBTORRENT_LIBS = @LIBTORRENT_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_CXX = @PTHREAD_CXX@ PTHREAD_LIBS = @PTHREAD_LIBS@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ _libcurl_config = @_libcurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__rm_f_notfound = @am__rm_f_notfound@ am__tar = @am__tar@ am__untar = @am__untar@ am__xargs_n = @am__xargs_n@ ax_pthread_config = @ax_pthread_config@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = src test pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libtorrent.pc EXTRA_DIST = \ scripts/checks.m4 \ scripts/common.m4 \ scripts/attributes.m4 \ scripts/ssl.m4 \ doc/main.xml \ doc/http.xml \ doc/torrent.xml ACLOCAL_AMFLAGS = -I scripts all: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: am--refresh: Makefile @: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): config.h: stamp-h1 @test -f $@ || rm -f stamp-h1 @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status $(AM_V_at)rm -f stamp-h1 $(AM_V_GEN)cd $(top_builddir) && $(SHELL) ./config.status config.h $(srcdir)/config.h.in: $(am__configure_deps) $(AM_V_GEN)($(am__cd) $(top_srcdir) && $(AUTOHEADER)) $(AM_V_at)rm -f stamp-h1 $(AM_V_at)touch $@ distclean-hdr: -rm -f config.h stamp-h1 libtorrent.pc: $(top_builddir)/config.status $(srcdir)/libtorrent.pc.in cd $(top_builddir) && $(SHELL) ./config.status $@ mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool config.lt install-pkgconfigDATA: $(pkgconfig_DATA) @$(NORMAL_INSTALL) @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ done uninstall-pkgconfigDATA: @$(NORMAL_UNINSTALL) @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir) # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscope: cscope.files test ! -s cscope.files \ || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) clean-cscope: -rm -f cscope.files cscope.files: clean-cscope cscopelist cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f cscope.out cscope.in.out cscope.po.out cscope.files distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) $(am__remove_distdir) $(AM_V_at)$(MKDIR_P) "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done -test -n "$(am__skip_mode_fix)" \ || find "$(distdir)" -type d ! -perm -755 \ -exec chmod u+rwx,go+rx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz $(am__post_remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 $(am__post_remove_distdir) dist-lzip: distdir tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz $(am__post_remove_distdir) dist-xz: distdir tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz $(am__post_remove_distdir) dist-zstd: distdir tardir=$(distdir) && $(am__tar) | zstd -c $${ZSTD_CLEVEL-$${ZSTD_OPT--19}} >$(distdir).tar.zst $(am__post_remove_distdir) dist-tarZ: distdir @echo WARNING: "Support for distribution archives compressed with" \ "legacy program 'compress' is deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir @echo WARNING: "Support for shar distribution archives is" \ "deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__post_remove_distdir) dist dist-all: $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' $(am__post_remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ eval GZIP= gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ *.tar.xz*) \ xz -dc $(distdir).tar.xz | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ eval GZIP= gzip -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ *.tar.zst*) \ zstd -dc $(distdir).tar.zst | $(am__untar) ;;\ esac chmod -R a-w $(distdir) chmod u+w $(distdir) mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ && $(am__cd) $(distdir)/_build/sub \ && ../../configure \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ --srcdir=../.. --prefix="$$dc_install_base" \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) $(AM_DISTCHECK_DVI_TARGET) \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && rm -rf $(DIST_ARCHIVES) \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ && cd "$$am__cwd" \ || exit 1 $(am__post_remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' distuninstallcheck: @test -n '$(distuninstallcheck_dir)' || { \ echo 'ERROR: trying to run $@ with an empty' \ '$$(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ $(am__cd) '$(distuninstallcheck_dir)' || { \ echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am check: check-recursive all-am: Makefile $(DATA) config.h installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(pkgconfigdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -$(am__rm_f) $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || $(am__rm_f) $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -f Makefile distclean-am: clean-am distclean-generic distclean-hdr \ distclean-libtool distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-pkgconfigDATA install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-pkgconfigDATA .MAKE: $(am__recursive_targets) all install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ am--refresh check check-am clean clean-cscope clean-generic \ clean-libtool cscope cscopelist-am ctags ctags-am dist \ dist-all dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ \ dist-xz dist-zip dist-zstd distcheck distclean \ distclean-generic distclean-hdr distclean-libtool \ distclean-tags distcleancheck distdir distuninstallcheck dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-pkgconfigDATA install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ps ps-am tags tags-am uninstall uninstall-am \ uninstall-pkgconfigDATA .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: # Tell GNU make to disable its built-in pattern rules. %:: %,v %:: RCS/%,v %:: RCS/% %:: s.% %:: SCCS/s.% libtorrent-0.16.11/depcomp0000755000000000000000000005621715175073426011075 #! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2024-06-19.01; # UTC # Copyright (C) 1999-2024 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by 'PROGRAMS ARGS'. object Object file output by 'PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputting dependencies. libtool Whether libtool is used (yes/no). Report bugs to . GNU Automake home page: . General help using GNU software: . EOF exit $? ;; -v | --v*) echo "depcomp (GNU Automake) $scriptversion" exit $? ;; esac # Get the directory component of the given path, and save it in the # global variables '$dir'. Note that this directory component will # be either empty or ending with a '/' character. This is deliberate. set_dir_from () { case $1 in */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; *) dir=;; esac } # Get the suffix-stripped basename of the given path, and save it the # global variable '$base'. set_base_from () { base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` } # If no dependency file was actually created by the compiler invocation, # we still have to create a dummy depfile, to avoid errors with the # Makefile "include basename.Plo" scheme. make_dummy_depfile () { echo "#dummy" > "$depfile" } # Factor out some common post-processing of the generated depfile. # Requires the auxiliary global variable '$tmpdepfile' to be set. aix_post_process_depfile () { # If the compiler actually managed to produce a dependency file, # post-process it. if test -f "$tmpdepfile"; then # Each line is of the form 'foo.o: dependency.h'. # Do two passes, one to just change these to # $object: dependency.h # and one to simply output # dependency.h: # which is needed to avoid the deleted-header problem. { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" } > "$depfile" rm -f "$tmpdepfile" else make_dummy_depfile fi } # A tabulation character. tab=' ' # A newline character. nl=' ' # Character ranges might be problematic outside the C locale. # These definitions help. upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ lower=abcdefghijklmnopqrstuvwxyz alpha=${upper}${lower} if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Avoid interference from the environment. gccflag= dashmflag= # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi cygpath_u="cygpath -u -f -" if test "$depmode" = msvcmsys; then # This is just like msvisualcpp but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvisualcpp fi if test "$depmode" = msvc7msys; then # This is just like msvc7 but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvc7 fi if test "$depmode" = xlc; then # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. gccflag=-qmakedep=gcc,-MF depmode=gcc fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. ## Unfortunately, FreeBSD c89 acceptance of flags depends upon ## the command line argument order; so add the flags where they ## appear in depend2.am. Note that the slowdown incurred here ## affects only configure: in makefiles, %FASTDEP% shortcuts this. for arg do case $arg in -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; *) set fnord "$@" "$arg" ;; esac shift # fnord shift # $arg done "$@" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## Note that this doesn't just cater to obsolete pre-3.x GCC compilers. ## but also to in-use compilers like IBM xlc/xlC and the HP C compiler. ## (see the conditional assignment to $gccflag above). ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). Also, it might not be ## supported by the other compilers which use the 'gcc' depmode. ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The second -e expression handles DOS-style file names with drive # letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the "deleted header file" problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. ## Some versions of gcc put a space before the ':'. On the theory ## that the space means something, we add a space to the output as ## well. hp depmode also adds that space, but also prefixes the VPATH ## to the object. Take care to not repeat it in the output. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like '#:fec' to the end of the # dependency line. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ | tr "$nl" ' ' >> "$depfile" echo >> "$depfile" # The second pass generates a dummy entry for each header file. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" ;; xlc) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts '$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.u tmpdepfile2=$base.u tmpdepfile3=$dir.libs/$base.u "$@" -Wc,-M else tmpdepfile1=$dir$base.u tmpdepfile2=$dir$base.u tmpdepfile3=$dir$base.u "$@" -M fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done aix_post_process_depfile ;; tcc) # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 # FIXME: That version still under development at the moment of writing. # Make that this statement remains true also for stable, released # versions. # It will wrap lines (doesn't matter whether long or short) with a # trailing '\', as in: # # foo.o : \ # foo.c \ # foo.h \ # # It will put a trailing '\' even on the last line, and will use leading # spaces rather than leading tabs (at least since its commit 0394caf7 # "Emit spaces for -MD"). "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. # We have to change lines of the first kind to '$object: \'. sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" # And for each line of the second kind, we have to emit a 'dep.h:' # dummy dependency, to avoid the deleted-header problem. sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" rm -f "$tmpdepfile" ;; ## The order of this option in the case statement is important, since the ## shell code in configure will try each of these formats in the order ## listed in this file. A plain '-MD' option would be understood by many ## compilers, so we must ensure this comes after the gcc and icc options. pgcc) # Portland's C compiler understands '-MD'. # Will always output deps to 'file.d' where file is the root name of the # source file under compilation, even if file resides in a subdirectory. # The object file name does not affect the name of the '.d' file. # pgcc 10.2 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using '\' : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... set_dir_from "$object" # Use the source, not the object, to determine the base name, since # that's sadly what pgcc will do too. set_base_from "$source" tmpdepfile=$base.d # For projects that build the same source file twice into different object # files, the pgcc approach of using the *source* file root name can cause # problems in parallel builds. Use a locking strategy to avoid stomping on # the same $tmpdepfile. lockdir=$base.d-lock trap " echo '$0: caught signal, cleaning up...' >&2 rmdir '$lockdir' exit 1 " 1 2 13 15 numtries=100 i=$numtries while test $i -gt 0; do # mkdir is a portable test-and-set. if mkdir "$lockdir" 2>/dev/null; then # This process acquired the lock. "$@" -MD stat=$? # Release the lock. rmdir "$lockdir" break else # If the lock is being held by a different process, wait # until the winning process is done or we timeout. while test -d "$lockdir" && test $i -gt 0; do sleep 1 i=`expr $i - 1` done fi i=`expr $i - 1` done trap - 1 2 13 15 if test $i -le 0; then echo "$0: failed to acquire lock after $numtries attempts" >&2 echo "$0: check lockdir '$lockdir'" >&2 exit 1 fi if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp2) # The "hp" stanza above does not work with aCC (C++) and HP's ia64 # compilers, which have integrated preprocessors. The correct option # to use with these is +Maked; it writes dependencies to a file named # 'foo.d', which lands next to the object file, wherever that # happens to be. # Much of this is similar to the tru64 case; see comments there. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.d tmpdepfile2=$dir.libs/$base.d "$@" -Wc,+Maked else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d "$@" +Maked fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" # Add 'dependent.h:' lines. sed -ne '2,${ s/^ *// s/ \\*$// s/$/:/ p }' "$tmpdepfile" >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" "$tmpdepfile2" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in 'foo.d' instead, so we check for that too. # Subdirectories are respected. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then # Libtool generates 2 separate objects for the 2 libraries. These # two compilations output dependencies in $dir.libs/$base.o.d and # in $dir$base.o.d. We have to check for both files, because # one of the two compilations can be disabled. We should prefer # $dir$base.o.d over $dir.libs/$base.o.d because the latter is # automatically cleaned when .libs/ is deleted, while ignoring # the former would cause a distcleancheck panic. tmpdepfile1=$dir$base.o.d # libtool 1.5 tmpdepfile2=$dir.libs/$base.o.d # Likewise. tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d "$@" -MD fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done # Same post-processing that is required for AIX mode. aix_post_process_depfile ;; msvc7) if test "$libtool" = yes; then showIncludes=-Wc,-showIncludes else showIncludes=-showIncludes fi "$@" $showIncludes > "$tmpdepfile" stat=$? grep -v '^Note: including file: ' "$tmpdepfile" if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The first sed program below extracts the file names and escapes # backslashes for cygpath. The second sed program outputs the file # name when reading, but also accumulates all include files in the # hold buffer in order to output them again at the end. This only # works with sed implementations that can handle large buffers. sed < "$tmpdepfile" -n ' /^Note: including file: *\(.*\)/ { s//\1/ s/\\/\\\\/g p }' | $cygpath_u | sort -u | sed -n ' s/ /\\ /g s/\(.*\)/'"$tab"'\1 \\/p s/.\(.*\) \\/\1:/ H $ { s/.*/'"$tab"'/ G p }' >> "$depfile" echo >> "$depfile" # make sure the fragment doesn't end with a backslash rm -f "$tmpdepfile" ;; msvc7msys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for ':' # in the target name. This is to cope with DOS-style filenames: # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. "$@" $dashmflag | sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this sed invocation # correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # X makedepend shift cleared=no eat=no for arg do case $cleared in no) set ""; shift cleared=yes ;; esac if test $eat = yes; then eat=no continue fi case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -arch) eat=yes ;; -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix=`echo "$object" | sed 's/^.*\././'` touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" # makedepend may prepend the VPATH from the source file name to the object. # No need to regex-escape $object, excess matching of '.' is harmless. sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process the last invocation # correctly. Breaking it into two sed invocations is a workaround. sed '1,2d' "$tmpdepfile" \ | tr ' ' "$nl" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E \ | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi IFS=" " for arg do case "$arg" in -o) shift ;; $object) shift ;; "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E 2>/dev/null | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" echo "$tab" >> "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; msvcmsys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: libtorrent-0.16.11/configure.ac0000644000000000000000000000613215175073411011767 AC_INIT([[libtorrent]],[[0.16.11]],[[sundell.software@gmail.com]]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_MACRO_DIRS([scripts]) AM_INIT_AUTOMAKE([serial-tests subdir-objects foreign]) LT_INIT([[disable-static]]) # When releasing the first 1.x.y version, we need to start with 1.1.0 (or higher) as we've already # used 0.16.x. AC_DEFINE([[PEER_NAME]], [["-lt100B-"]], [[Identifier that is part of the default peer id.]]) AC_DEFINE([[PEER_VERSION]], [["lt\x10\x0B"]], [[4 byte client and version identifier for DHT.]]) LIBTORRENT_CURRENT=41 LIBTORRENT_REVISION=0 LIBTORRENT_AGE=0 LIBTORRENT_INTERFACE_VERSION_INFO=$LIBTORRENT_CURRENT:$LIBTORRENT_REVISION:$LIBTORRENT_AGE LIBTORRENT_INTERFACE_VERSION_NO=$LIBTORRENT_CURRENT.$LIBTORRENT_AGE.$LIBTORRENT_REVISION AC_SUBST(LIBTORRENT_CURRENT) AC_SUBST(LIBTORRENT_INTERFACE_VERSION_INFO) AC_SUBST(LIBTORRENT_INTERFACE_VERSION_NO) AC_PROG_CXX # Filter out unwanted flags added by autoconf on some systems, e.g. MacOS. TORRENT_REMOVE_UNWANTED(CXX, $CXX, -std=c++11 -std=gnu++11) AX_CXX_COMPILE_STDCXX(17, noext, mandatory) AC_SYS_LARGEFILE AC_C_BIGENDIAN( AC_DEFINE(IS_BIG_ENDIAN, 1, Big endian), AC_DEFINE(IS_LITTLE_ENDIAN, 1, Little endian), AC_MSG_ERROR([Could not determine endianness]) ) RAK_CHECK_CFLAGS RAK_CHECK_CXXFLAGS RAK_ENABLE_DEBUG RAK_ENABLE_EXTRA_DEBUG RAK_ENABLE_WERROR TORRENT_ENABLE_ALIGNED TORRENT_ENABLE_INTERRUPT_SOCKET TORRENT_ENABLE_ARCH TORRENT_WITH_SYSROOT dnl TORRENT_WITH_XFS TORRENT_WITHOUT_KQUEUE TORRENT_WITHOUT_EPOLL TORRENT_CHECK_FALLOCATE TORRENT_WITH_POSIX_FALLOCATE TORRENT_WITH_ADDRESS_SPACE TORRENT_WITHOUT_STATVFS TORRENT_WITHOUT_STATFS TORRENT_WITH_INOTIFY AC_ARG_ENABLE(attribute-visibility, AS_HELP_STRING([--disable-attribute-visibility],[disable symbol visibility attribute [[default=enable]]]), [ if test "$enableval" = "yes"; then CC_ATTRIBUTE_VISIBILITY fi ],[ CC_ATTRIBUTE_VISIBILITY ]) AC_ARG_ENABLE(execinfo, AS_HELP_STRING([--disable-execinfo],[disable libexecinfo [[default=enable]]]), [ if test "$enableval" = "yes"; then AX_EXECINFO fi ],[ AX_EXECINFO ]) if test "x$use_kqueue" != "xyes" && test "x$use_epoll" != "xyes"; then AC_MSG_ERROR([Must enable at least one of either kqueue or epoll]) fi AX_PTHREAD CHECK_ATOMIC PKG_CHECK_MODULES([LIBCURL], [libcurl],, [LIBCURL_CHECK_CONFIG]) PKG_CHECK_MODULES([CPPUNIT], [cppunit],, [no_cppunit="yes"]) PKG_CHECK_MODULES([ZLIB], [zlib]) CFLAGS="$LIBCURL_CFLAGS $PTHREAD_CFLAGS $ZLIB_CFLAGS $CFLAGS" CXXFLAGS="$LIBCURL_CFLAGS $LIBCURL_CPPFLAGS $PTHREAD_CFLAGS $ZLIB_CFLAGS $CXXFLAGS" LIBS="$LIBCURL_LIBS $ATOMIC_LIBS $PTHREAD_LIBS $ZLIB_LIBS $LIBS" TORRENT_CHECK_OPENSSL TORRENT_CHECK_CACHELINE TORRENT_CHECK_POPCOUNT TORRENT_CHECK_MADVISE TORRENT_CHECK_POSIX_FADVISE TORRENT_DISABLE_PTHREAD_SETNAME_NP TORRENT_MINCORE TORRENT_DISABLE_INSTRUMENTATION LIBTORRENT_LIBS="-ltorrent" AC_SUBST(LIBTORRENT_LIBS) LIBTORRENT_CFLAGS="" AC_SUBST(LIBTORRENT_CFLAGS) AC_DEFINE(HAVE_CONFIG_H, 1, true if config.h was included) AC_CONFIG_FILES([ libtorrent.pc Makefile src/Makefile src/torrent/Makefile test/Makefile ]) AC_OUTPUT libtorrent-0.16.11/install-sh0000755000000000000000000003611515175073426011517 #!/bin/sh # install - install a program, script, or datafile scriptversion=2024-06-19.01; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # 'make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. tab=' ' nl=' ' IFS=" $tab$nl" # Set DOITPROG to "echo" to test this script. doit=${DOITPROG-} doit_exec=${doit:-exec} # Put in absolute file names if you don't have them in your path; # or use environment vars. chgrpprog=${CHGRPPROG-chgrp} chmodprog=${CHMODPROG-chmod} chownprog=${CHOWNPROG-chown} cmpprog=${CMPPROG-cmp} cpprog=${CPPROG-cp} mkdirprog=${MKDIRPROG-mkdir} mvprog=${MVPROG-mv} rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} posix_mkdir= # Desired mode of installed file. mode=0755 # Create dirs (including intermediate dirs) using mode 755. # This is like GNU 'install' as of coreutils 8.32 (2020). mkdir_umask=22 backupsuffix= chgrpcmd= chmodcmd=$chmodprog chowncmd= mvcmd=$mvprog rmcmd="$rmprog -f" stripcmd= src= dst= dir_arg= dst_arg= copy_on_change=false is_target_a_directory=possibly usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: --help display this help and exit. --version display version info and exit. -c (ignored) -C install only if different (preserve data modification time) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -p pass -p to $cpprog. -s $stripprog installed files. -S SUFFIX attempt to back up existing files, with suffix SUFFIX. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG By default, rm is invoked with -f; when overridden with RMPROG, it's up to you to specify -f if you want it. If -S is not specified, no backups are attempted. Report bugs to . GNU Automake home page: . General help using GNU software: ." while test $# -ne 0; do case $1 in -c) ;; -C) copy_on_change=true;; -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 case $mode in *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -p) cpprog="$cpprog -p";; -s) stripcmd=$stripprog;; -S) backupsuffix="$2" shift;; -t) is_target_a_directory=always dst_arg=$2 # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac shift;; -T) is_target_a_directory=never;; --version) echo "$0 (GNU Automake) $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done # We allow the use of options -d and -T together, by making -d # take the precedence; this is for compatibility with GNU install. if test -n "$dir_arg"; then if test -n "$dst_arg"; then echo "$0: target directory not allowed when installing a directory." >&2 exit 1 fi fi if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dst_arg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dst_arg" shift # fnord fi shift # arg dst_arg=$arg # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac done fi if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call 'install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi if test -z "$dir_arg"; then if test $# -gt 1 || test "$is_target_a_directory" = always; then if test ! -d "$dst_arg"; then echo "$0: $dst_arg: Is not a directory." >&2 exit 1 fi fi fi if test -z "$dir_arg"; then do_exit='(exit $ret); exit $ret' trap "ret=129; $do_exit" 1 trap "ret=130; $do_exit" 2 trap "ret=141; $do_exit" 13 trap "ret=143; $do_exit" 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. case $mode in # Optimize common cases. *644) cp_umask=133;; *755) cp_umask=22;; *[0-7]) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac fi for src do # Protect names problematic for 'test' and other utilities. case $src in -* | [=\(\)!]) src=./$src;; esac if test -n "$dir_arg"; then dst=$src dstdir=$dst test -d "$dstdir" dstdir_status=$? # Don't chown directories that already exist. if test $dstdir_status = 0; then chowncmd="" fi else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dst_arg # If destination is a directory, append the input filename. if test -d "$dst"; then if test "$is_target_a_directory" = never; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dstbase=`basename "$src"` case $dst in */) dst=$dst$dstbase;; *) dst=$dst/$dstbase;; esac dstdir_status=0 else dstdir=`dirname "$dst"` test -d "$dstdir" dstdir_status=$? fi fi case $dstdir in */) dstdirslash=$dstdir;; *) dstdirslash=$dstdir/;; esac obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # With -d, create the new directory with the user-specified mode. # Otherwise, rely on $mkdir_umask. if test -n "$dir_arg"; then mkdir_mode=-m$mode else mkdir_mode= fi posix_mkdir=false # The $RANDOM variable is not portable (e.g., dash). Use it # here however when possible just to lower collision chance. tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap ' ret=$? rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null exit $ret ' 0 # Because "mkdir -p" follows existing symlinks and we likely work # directly in world-writable /tmp, make sure that the '$tmpdir' # directory is successfully created first before we actually test # 'mkdir -p'. if (umask $mkdir_umask && $mkdirprog $mkdir_mode "$tmpdir" && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibility with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. test_tmpdir="$tmpdir/a" ls_ld_tmpdir=`ls -ld "$test_tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null fi trap '' 0;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. case $dstdir in /*) prefix='/';; [-=\(\)!]*) prefix='./';; *) prefix='';; esac oIFS=$IFS IFS=/ set -f set fnord $dstdir shift set +f IFS=$oIFS prefixes= for d do test X"$d" = X && continue prefix=$prefix$d if test -d "$prefix"; then prefixes= else if $posix_mkdir; then (umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break # Don't fail if two instances are running concurrently. test -d "$prefix" || exit 1 else case $prefix in *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; *) qprefix=$prefix;; esac prefixes="$prefixes '$qprefix'" fi fi prefix=$prefix/ done if test -n "$prefixes"; then # Don't fail if two instances are running concurrently. (umask $mkdir_umask && eval "\$doit_exec \$mkdirprog $prefixes") || test -d "$dstdir" || exit 1 obsolete_mkdir_used=true fi fi fi if test -n "$dir_arg"; then { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else # Make a couple of temp file names in the proper directory. dsttmp=${dstdirslash}_inst.$$_ rmtmp=${dstdirslash}_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. (umask $cp_umask && { test -z "$stripcmd" || { # Create $dsttmp read-write so that cp doesn't create it read-only, # which would cause strip to fail. if test -z "$doit"; then : >"$dsttmp" # No need to fork-exec 'touch'. else $doit touch "$dsttmp" fi } } && $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # If $backupsuffix is set, and the file being installed # already exists, attempt a backup. Don't worry if it fails, # e.g., if mv doesn't support -f. if test -n "$backupsuffix" && test -f "$dst"; then $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null fi # Rename the file to the real destination. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. { # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { test ! -f "$dst" || $doit $rmcmd "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd "$rmtmp" 2>/dev/null; :; } } || { echo "$0: cannot unlink or rename $dst" >&2 (exit 1); exit 1 } } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 trap '' 0 fi done # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: libtorrent-0.16.11/config.h.in0000644000000000000000000001603015175073426011530 /* config.h.in. Generated from configure.ac by autoheader. */ /* Define if building universal (internal helper macro) */ #undef AC_APPLE_UNIVERSAL_BUILD /* Default address space size. */ #undef DEFAULT_ADDRESS_SPACE_SIZE /* Determine the block size */ #undef FS_STAT_BLOCK_SIZE /* Type of block count member in stat struct */ #undef FS_STAT_COUNT_TYPE /* Function to determine filesystem stats from fd */ #undef FS_STAT_FD /* Function to determine filesystem stats from filename */ #undef FS_STAT_FN /* Type of block size member in stat struct */ #undef FS_STAT_SIZE_TYPE /* Type of second argument to statfs function */ #undef FS_STAT_STRUCT /* The function to set pthread name has no pthread argument. */ #undef HAS_PTHREAD_SETNAME_NP_DARWIN /* The function to set pthread name has a pthread_t argumet. */ #undef HAS_PTHREAD_SETNAME_NP_GENERIC /* Defined if backtrace() could be fully identified. */ #undef HAVE_BACKTRACE /* true if config.h was included */ #undef HAVE_CONFIG_H /* define if the compiler supports basic C++17 syntax */ #undef HAVE_CXX17 /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H /* Define to 1 if you have the header file. */ #undef HAVE_EXECINFO_H /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have a functional curl library. */ #undef HAVE_LIBCURL /* Define if you have POSIX threads libraries and header files. */ #undef HAVE_PTHREAD /* Define to 1 if you have the header file. */ #undef HAVE_PTHREAD_H /* Have PTHREAD_PRIO_INHERIT. */ #undef HAVE_PTHREAD_PRIO_INHERIT /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDIO_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_INOTIFY_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STATFS_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STATVFS_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_VFS_H /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Big endian */ #undef IS_BIG_ENDIAN /* Little endian */ #undef IS_LITTLE_ENDIAN /* Defined if libcurl supports AsynchDNS */ #undef LIBCURL_FEATURE_ASYNCHDNS /* Defined if libcurl supports IDN */ #undef LIBCURL_FEATURE_IDN /* Defined if libcurl supports IPv6 */ #undef LIBCURL_FEATURE_IPV6 /* Defined if libcurl supports KRB4 */ #undef LIBCURL_FEATURE_KRB4 /* Defined if libcurl supports libz */ #undef LIBCURL_FEATURE_LIBZ /* Defined if libcurl supports NTLM */ #undef LIBCURL_FEATURE_NTLM /* Defined if libcurl supports SSL */ #undef LIBCURL_FEATURE_SSL /* Defined if libcurl supports SSPI */ #undef LIBCURL_FEATURE_SSPI /* Defined if libcurl supports DICT */ #undef LIBCURL_PROTOCOL_DICT /* Defined if libcurl supports FILE */ #undef LIBCURL_PROTOCOL_FILE /* Defined if libcurl supports FTP */ #undef LIBCURL_PROTOCOL_FTP /* Defined if libcurl supports FTPS */ #undef LIBCURL_PROTOCOL_FTPS /* Defined if libcurl supports HTTP */ #undef LIBCURL_PROTOCOL_HTTP /* Defined if libcurl supports HTTPS */ #undef LIBCURL_PROTOCOL_HTTPS /* Defined if libcurl supports IMAP */ #undef LIBCURL_PROTOCOL_IMAP /* Defined if libcurl supports LDAP */ #undef LIBCURL_PROTOCOL_LDAP /* Defined if libcurl supports POP3 */ #undef LIBCURL_PROTOCOL_POP3 /* Defined if libcurl supports RTSP */ #undef LIBCURL_PROTOCOL_RTSP /* Defined if libcurl supports SMTP */ #undef LIBCURL_PROTOCOL_SMTP /* Defined if libcurl supports TELNET */ #undef LIBCURL_PROTOCOL_TELNET /* Defined if libcurl supports TFTP */ #undef LIBCURL_PROTOCOL_TFTP /* enable instrumentation */ #undef LT_INSTRUMENTATION /* Define to the sub-directory where libtool stores uninstalled libraries. */ #undef LT_OBJDIR /* Largest L1 cache size we know of should work on all archs. */ #undef LT_SMP_CACHE_BYTES /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* [Identifier that is part of the default peer id.] */ #undef PEER_NAME /* [4 byte client and version identifier for DHT.] */ #undef PEER_VERSION /* Define to necessary symbol if this constant uses a non-standard name on your system. */ #undef PTHREAD_CREATE_JOINABLE /* The size of 'long', as computed by sizeof. */ #undef SIZEOF_LONG /* Define to 1 if all of the C89 standard headers exist (not just the ones required in a freestanding environment). This macro is provided for backward compatibility; new code need not use it. */ #undef STDC_HEADERS /* Define this if the compiler supports the visibility attributes. */ #undef SUPPORT_ATTRIBUTE_VISIBILITY /* Require byte alignment */ #undef USE_ALIGNED /* Use __builtin_popcount. */ #undef USE_BUILTIN_POPCOUNT /* Use epoll. */ #undef USE_EPOLL /* Enable extra debugging checks. */ #undef USE_EXTRA_DEBUG /* Linux's fallocate supported. */ #undef USE_FALLOCATE /* sys/inotify.h exists and works correctly */ #undef USE_INOTIFY /* Use interrupt socket instead of pthread_kill */ #undef USE_INTERRUPT_SOCKET /* Use kqueue. */ #undef USE_KQUEUE /* Use madvise */ #undef USE_MADVISE /* Use mincore */ #undef USE_MINCORE /* use char* in mincore */ #undef USE_MINCORE_UNSIGNED /* Use posix_fadvise */ #undef USE_POSIX_FADVISE /* posix_fallocate supported. */ #undef USE_POSIX_FALLOCATE /* Version number of package */ #undef VERSION /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel). */ #if defined AC_APPLE_UNIVERSAL_BUILD # if defined __BIG_ENDIAN__ # define WORDS_BIGENDIAN 1 # endif #else # ifndef WORDS_BIGENDIAN # undef WORDS_BIGENDIAN # endif #endif /* Number of bits in a file offset, on hosts where this is settable. */ #undef _FILE_OFFSET_BITS /* Define to 1 on platforms where this makes off_t a 64-bit type. */ #undef _LARGE_FILES /* Number of bits in time_t, on hosts where this is settable. */ #undef _TIME_BITS /* Define to 1 on platforms where this makes time_t a 64-bit type. */ #undef __MINGW_USE_VC2005_COMPAT /* Defined to return type of backtrace(). */ #undef backtrace_size_t /* Define curl_free() as free() if our version of curl lacks curl_free. */ #undef curl_free libtorrent-0.16.11/README.md0000644000000000000000000000345015175073411010760 LibTorrent ======== Introduction ------------ High performance torrent library for multiple clients. LibTorrent is a BitTorrent library written in C++ for *nix, with a focus on high performance and good code. The library differentiates itself from other implementations by transferring directly from file pages to the network stack. To learn how to use libtorrent visit the [Wiki](https://github.com/rakshasa/libtorrent/wiki). Related Projects ---------------- * [https://github.com/rakshasa/rbedit](https://github.com/rakshasa/rbedit): A dependency-free bencode editor. * [https://github.com/rakshasa/rtorrent](https://github.com/rakshasa/rtorrent): high performance ncurses based torrent client Donate to rTorrent development ------------------------------ * [Paypal](https://paypal.me/jarisundellno) * [Patreon](https://www.patreon.com/rtorrent) * [SubscribeStar](https://www.subscribestar.com/rtorrent) * Bitcoin: 1MpmXm5AHtdBoDaLZstJw8nupJJaeKu8V8 * Ethereum: 0x9AB1e3C3d8a875e870f161b3e9287Db0E6DAfF78 * Litecoin: LdyaVR67LBnTf6mAT4QJnjSG2Zk67qxmfQ * Cardano: addr1qytaslmqmk6dspltw06sp0zf83dh09u79j49ceh5y26zdcccgq4ph7nmx6kgmzeldauj43254ey97f3x4xw49d86aguqwfhlte Help keep rTorrent development going by donating to its creator. BUILD DEPENDENCIES -------- Ubuntu, for example ``` sudo apt install make curl-libcurlpp-dev autoconf ``` BUILDING -------- Jump into the github cloned directory ``` cd libtorrent ``` Create config files ``` autoreconf -ivf ``` Perform configuration ``` ./configure ``` Compile, slowest option. ``` make ``` OR Optionally compile with multiple worker threads, optimal number of threads is number of cores -1 for fastest compile time. For example : a 4 core machine should compile with only 3 cores, an 8-core machine 7, etc.) ``` make -j7 ``` Install ``` make install ``` libtorrent-0.16.11/aclocal.m40000644000000000000000000021747615175073424011364 # generated automatically by aclocal 1.17 -*- Autoconf -*- # Copyright (C) 1996-2024 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.72],, [m4_warning([this file was generated for autoconf 2.72. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) #*************************************************************************** # _ _ ____ _ # Project ___| | | | _ \| | # / __| | | | |_) | | # | (__| |_| | _ <| |___ # \___|\___/|_| \_\_____| # # Copyright (C) David Shaw # # This software is licensed as described in the file COPYING, which # you should have received as part of this distribution. The terms # are also available at https://curl.se/docs/copyright.html. # # You may opt to use, copy, modify, merge, publish, distribute and/or sell # copies of the Software, and permit persons to whom the Software is # furnished to do so, under the terms of the COPYING file. # # This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY # KIND, either express or implied. # # SPDX-License-Identifier: curl # # LIBCURL_CHECK_CONFIG ([DEFAULT-ACTION], [MINIMUM-VERSION], # [ACTION-IF-YES], [ACTION-IF-NO]) # ---------------------------------------------------------- # David Shaw May-09-2006 # # Checks for libcurl. DEFAULT-ACTION is the string yes or no to # specify whether to default to --with-libcurl or --without-libcurl. # If not supplied, DEFAULT-ACTION is yes. MINIMUM-VERSION is the # minimum version of libcurl to accept. Pass the version as a regular # version number like 7.10.1. If not supplied, any version is # accepted. ACTION-IF-YES is a list of shell commands to run if # libcurl was successfully found and passed the various tests. # ACTION-IF-NO is a list of shell commands that are run otherwise. # Note that using --without-libcurl does run ACTION-IF-NO. # # This macro #defines HAVE_LIBCURL if a working libcurl setup is # found, and sets @LIBCURL@ and @LIBCURL_CPPFLAGS@ to the necessary # values. Other useful defines are LIBCURL_FEATURE_xxx where xxx are # the various features supported by libcurl, and LIBCURL_PROTOCOL_yyy # where yyy are the various protocols supported by libcurl. Both xxx # and yyy are capitalized. See the list of AH_TEMPLATEs at the top of # the macro for the complete list of possible defines. Shell # variables $libcurl_feature_xxx and $libcurl_protocol_yyy are also # defined to 'yes' for those features and protocols that were found. # Note that xxx and yyy keep the same capitalization as in the # curl-config list (e.g. it's "HTTP" and not "http"). # # Users may override the detected values by doing something like: # LIBCURL="-lcurl" LIBCURL_CPPFLAGS="-I/usr/myinclude" ./configure # # For the sake of sanity, this macro assumes that any libcurl that is found is # after version 7.7.2, the first version that included the curl-config script. # Note that it is important for people packaging binary versions of libcurl to # include this script! Without curl-config, we can only guess what protocols # are available, or use curl_version_info to figure it out at runtime. AC_DEFUN([LIBCURL_CHECK_CONFIG], [ AH_TEMPLATE([LIBCURL_FEATURE_SSL],[Defined if libcurl supports SSL]) AH_TEMPLATE([LIBCURL_FEATURE_KRB4],[Defined if libcurl supports KRB4]) AH_TEMPLATE([LIBCURL_FEATURE_IPV6],[Defined if libcurl supports IPv6]) AH_TEMPLATE([LIBCURL_FEATURE_LIBZ],[Defined if libcurl supports libz]) AH_TEMPLATE([LIBCURL_FEATURE_ASYNCHDNS],[Defined if libcurl supports AsynchDNS]) AH_TEMPLATE([LIBCURL_FEATURE_IDN],[Defined if libcurl supports IDN]) AH_TEMPLATE([LIBCURL_FEATURE_SSPI],[Defined if libcurl supports SSPI]) AH_TEMPLATE([LIBCURL_FEATURE_NTLM],[Defined if libcurl supports NTLM]) AH_TEMPLATE([LIBCURL_PROTOCOL_HTTP],[Defined if libcurl supports HTTP]) AH_TEMPLATE([LIBCURL_PROTOCOL_HTTPS],[Defined if libcurl supports HTTPS]) AH_TEMPLATE([LIBCURL_PROTOCOL_FTP],[Defined if libcurl supports FTP]) AH_TEMPLATE([LIBCURL_PROTOCOL_FTPS],[Defined if libcurl supports FTPS]) AH_TEMPLATE([LIBCURL_PROTOCOL_FILE],[Defined if libcurl supports FILE]) AH_TEMPLATE([LIBCURL_PROTOCOL_TELNET],[Defined if libcurl supports TELNET]) AH_TEMPLATE([LIBCURL_PROTOCOL_LDAP],[Defined if libcurl supports LDAP]) AH_TEMPLATE([LIBCURL_PROTOCOL_DICT],[Defined if libcurl supports DICT]) AH_TEMPLATE([LIBCURL_PROTOCOL_TFTP],[Defined if libcurl supports TFTP]) AH_TEMPLATE([LIBCURL_PROTOCOL_RTSP],[Defined if libcurl supports RTSP]) AH_TEMPLATE([LIBCURL_PROTOCOL_POP3],[Defined if libcurl supports POP3]) AH_TEMPLATE([LIBCURL_PROTOCOL_IMAP],[Defined if libcurl supports IMAP]) AH_TEMPLATE([LIBCURL_PROTOCOL_SMTP],[Defined if libcurl supports SMTP]) AC_ARG_WITH(libcurl, AS_HELP_STRING([--with-libcurl=PREFIX],[look for the curl library in PREFIX/lib and headers in PREFIX/include]), [_libcurl_with=$withval],[_libcurl_with=ifelse([$1],,[yes],[$1])]) if test "$_libcurl_with" != "no" ; then AC_PROG_AWK _libcurl_version_parse="eval $AWK '{split(\$NF,A,\".\"); X=256*256*A[[1]]+256*A[[2]]+A[[3]]; print X;}'" _libcurl_try_link=yes if test -d "$_libcurl_with" ; then LIBCURL_CPPFLAGS="-I$withval/include" _libcurl_ldflags="-L$withval/lib" AC_PATH_PROG([_libcurl_config],[curl-config],[], ["$withval/bin"]) else AC_PATH_PROG([_libcurl_config],[curl-config],[],[$PATH]) fi if test x$_libcurl_config != "x" ; then AC_CACHE_CHECK([for the version of libcurl], [libcurl_cv_lib_curl_version], [libcurl_cv_lib_curl_version=`$_libcurl_config --version | $AWK '{print $[]2}'`]) _libcurl_version=`echo $libcurl_cv_lib_curl_version | $_libcurl_version_parse` _libcurl_wanted=`echo ifelse([$2],,[0],[$2]) | $_libcurl_version_parse` if test $_libcurl_wanted -gt 0 ; then AC_CACHE_CHECK([for libcurl >= version $2], [libcurl_cv_lib_version_ok], [ if test $_libcurl_version -ge $_libcurl_wanted ; then libcurl_cv_lib_version_ok=yes else libcurl_cv_lib_version_ok=no fi ]) fi if test $_libcurl_wanted -eq 0 || test x$libcurl_cv_lib_version_ok = xyes ; then if test x"$LIBCURL_CPPFLAGS" = "x" ; then LIBCURL_CPPFLAGS=`$_libcurl_config --cflags` fi if test x"$LIBCURL" = "x" ; then LIBCURL=`$_libcurl_config --libs` # This is so silly, but Apple actually has a bug in their # curl-config script. Fixed in Tiger, but there are still # lots of Panther installs around. case "${host}" in powerpc-apple-darwin7*) LIBCURL=`echo $LIBCURL | sed -e 's|-arch i386||g'` ;; esac fi # All curl-config scripts support --feature _libcurl_features=`$_libcurl_config --feature` # Is it modern enough to have --protocols? (7.12.4) if test $_libcurl_version -ge 461828 ; then _libcurl_protocols=`$_libcurl_config --protocols` fi else _libcurl_try_link=no fi unset _libcurl_wanted fi if test $_libcurl_try_link = yes ; then # we did not find curl-config, so let's see if the user-supplied # link line (or failing that, "-lcurl") is enough. LIBCURL=${LIBCURL-"$_libcurl_ldflags -lcurl"} AC_CACHE_CHECK([whether libcurl is usable], [libcurl_cv_lib_curl_usable], [ _libcurl_save_cppflags=$CPPFLAGS CPPFLAGS="$LIBCURL_CPPFLAGS $CPPFLAGS" _libcurl_save_libs=$LIBS LIBS="$LIBCURL $LIBS" AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]],[[ /* Try to use a few common options to force a failure if we are missing symbols or cannot link. */ int x; curl_easy_setopt(NULL,CURLOPT_URL,NULL); x=CURL_ERROR_SIZE; x=CURLOPT_WRITEFUNCTION; x=CURLOPT_WRITEDATA; x=CURLOPT_ERRORBUFFER; x=CURLOPT_STDERR; x=CURLOPT_VERBOSE; if (x) {;} ]])],libcurl_cv_lib_curl_usable=yes,libcurl_cv_lib_curl_usable=no) CPPFLAGS=$_libcurl_save_cppflags LIBS=$_libcurl_save_libs unset _libcurl_save_cppflags unset _libcurl_save_libs ]) if test $libcurl_cv_lib_curl_usable = yes ; then # Does curl_free() exist in this version of libcurl? # If not, fake it with free() _libcurl_save_cppflags=$CPPFLAGS CPPFLAGS="$CPPFLAGS $LIBCURL_CPPFLAGS" _libcurl_save_libs=$LIBS LIBS="$LIBS $LIBCURL" AC_CHECK_DECL([curl_free],[], [AC_DEFINE([curl_free],[free], [Define curl_free() as free() if our version of curl lacks curl_free.])], [[#include ]]) CPPFLAGS=$_libcurl_save_cppflags LIBS=$_libcurl_save_libs unset _libcurl_save_cppflags unset _libcurl_save_libs AC_DEFINE(HAVE_LIBCURL,1, [Define to 1 if you have a functional curl library.]) AC_SUBST(LIBCURL_CPPFLAGS) AC_SUBST(LIBCURL) for _libcurl_feature in $_libcurl_features ; do AC_DEFINE_UNQUOTED(AS_TR_CPP(libcurl_feature_$_libcurl_feature),[1]) eval AS_TR_SH(libcurl_feature_$_libcurl_feature)=yes done if test "x$_libcurl_protocols" = "x" ; then # We do not have --protocols, so just assume that all # protocols are available _libcurl_protocols="HTTP FTP FILE TELNET LDAP DICT TFTP" if test x$libcurl_feature_SSL = xyes ; then _libcurl_protocols="$_libcurl_protocols HTTPS" # FTPS was not standards-compliant until version # 7.11.0 (0x070b00 == 461568) if test $_libcurl_version -ge 461568; then _libcurl_protocols="$_libcurl_protocols FTPS" fi fi # RTSP, IMAP, POP3 and SMTP were added in # 7.20.0 (0x071400 == 463872) if test $_libcurl_version -ge 463872; then _libcurl_protocols="$_libcurl_protocols RTSP IMAP POP3 SMTP" fi fi for _libcurl_protocol in $_libcurl_protocols ; do AC_DEFINE_UNQUOTED(AS_TR_CPP(libcurl_protocol_$_libcurl_protocol),[1]) eval AS_TR_SH(libcurl_protocol_$_libcurl_protocol)=yes done else unset LIBCURL unset LIBCURL_CPPFLAGS fi fi unset _libcurl_try_link unset _libcurl_version_parse unset _libcurl_config unset _libcurl_feature unset _libcurl_features unset _libcurl_protocol unset _libcurl_protocols unset _libcurl_version unset _libcurl_ldflags fi if test x$_libcurl_with = xno || test x$libcurl_cv_lib_curl_usable != xyes ; then # This is the IF-NO path ifelse([$4],,:,[$4]) else # This is the IF-YES path ifelse([$3],,:,[$3]) fi unset _libcurl_with ]) # pkg.m4 - Macros to locate and use pkg-config. -*- Autoconf -*- # serial 12 (pkg-config-0.29.2) dnl Copyright © 2004 Scott James Remnant . dnl Copyright © 2012-2015 Dan Nicholson dnl dnl This program is free software; you can redistribute it and/or modify dnl it under the terms of the GNU General Public License as published by dnl the Free Software Foundation; either version 2 of the License, or dnl (at your option) any later version. dnl dnl This program is distributed in the hope that it will be useful, but dnl WITHOUT ANY WARRANTY; without even the implied warranty of dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU dnl General Public License for more details. dnl dnl You should have received a copy of the GNU General Public License dnl along with this program; if not, write to the Free Software dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA dnl 02111-1307, USA. dnl dnl As a special exception to the GNU General Public License, if you dnl distribute this file as part of a program that contains a dnl configuration script generated by Autoconf, you may include it under dnl the same distribution terms that you use for the rest of that dnl program. dnl PKG_PREREQ(MIN-VERSION) dnl ----------------------- dnl Since: 0.29 dnl dnl Verify that the version of the pkg-config macros are at least dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's dnl installed version of pkg-config, this checks the developer's version dnl of pkg.m4 when generating configure. dnl dnl To ensure that this macro is defined, also add: dnl m4_ifndef([PKG_PREREQ], dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) dnl dnl See the "Since" comment for each macro you use to see what version dnl of the macros you require. m4_defun([PKG_PREREQ], [m4_define([PKG_MACROS_VERSION], [0.29.2]) m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) ])dnl PKG_PREREQ dnl PKG_PROG_PKG_CONFIG([MIN-VERSION], [ACTION-IF-NOT-FOUND]) dnl --------------------------------------------------------- dnl Since: 0.16 dnl dnl Search for the pkg-config tool and set the PKG_CONFIG variable to dnl first found in the path. Checks that the version of pkg-config found dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is dnl used since that's the first version where most current features of dnl pkg-config existed. dnl dnl If pkg-config is not found or older than specified, it will result dnl in an empty PKG_CONFIG variable. To avoid widespread issues with dnl scripts not checking it, ACTION-IF-NOT-FOUND defaults to aborting. dnl You can specify [PKG_CONFIG=false] as an action instead, which would dnl result in pkg-config tests failing, but no bogus error messages. AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) fi if test -n "$PKG_CONFIG"; then _pkg_min_version=m4_default([$1], [0.9.0]) AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) PKG_CONFIG="" fi fi if test -z "$PKG_CONFIG"; then m4_default([$2], [AC_MSG_ERROR([pkg-config not found])]) fi[]dnl ])dnl PKG_PROG_PKG_CONFIG dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) dnl ------------------------------------------------------------------- dnl Since: 0.18 dnl dnl Check to see whether a particular set of modules exists. Similar to dnl PKG_CHECK_MODULES(), but does not set variables or print errors. dnl dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) dnl only at the first occurrence in configure.ac, so if the first place dnl it's called might be skipped (such as if it is within an "if", you dnl have to call PKG_CHECK_EXISTS manually AC_DEFUN([PKG_CHECK_EXISTS], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl if test -n "$PKG_CONFIG" && \ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then m4_default([$2], [:]) m4_ifvaln([$3], [else $3])dnl fi]) dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) dnl --------------------------------------------- dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting dnl pkg_failed based on the result. m4_define([_PKG_CONFIG], [if test -n "$$1"; then pkg_cv_[]$1="$$1" elif test -n "$PKG_CONFIG"; then PKG_CHECK_EXISTS([$3], [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes ], [pkg_failed=yes]) else pkg_failed=untried fi[]dnl ])dnl _PKG_CONFIG dnl _PKG_SHORT_ERRORS_SUPPORTED dnl --------------------------- dnl Internal check to see if pkg-config supports short errors. AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi[]dnl ])dnl _PKG_SHORT_ERRORS_SUPPORTED dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], dnl [ACTION-IF-NOT-FOUND]) dnl -------------------------------------------------------------- dnl Since: 0.4.0 dnl dnl Note that if there is a possibility the first call to dnl PKG_CHECK_MODULES might not happen, you should be sure to include an dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl pkg_failed=no AC_MSG_CHECKING([for $2]) _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) _PKG_CONFIG([$1][_LIBS], [libs], [$2]) m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS and $1[]_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.]) if test $pkg_failed = yes; then AC_MSG_RESULT([no]) _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` else $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD m4_default([$4], [AC_MSG_ERROR( [Package requirements ($2) were not met: $$1_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. _PKG_TEXT])[]dnl ]) elif test $pkg_failed = untried; then AC_MSG_RESULT([no]) m4_default([$4], [AC_MSG_FAILURE( [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. _PKG_TEXT To get pkg-config, see .])[]dnl ]) else $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS $1[]_LIBS=$pkg_cv_[]$1[]_LIBS AC_MSG_RESULT([yes]) $3 fi[]dnl ])dnl PKG_CHECK_MODULES dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], dnl [ACTION-IF-NOT-FOUND]) dnl --------------------------------------------------------------------- dnl Since: 0.29 dnl dnl Checks for existence of MODULES and gathers its build flags with dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags dnl and VARIABLE-PREFIX_LIBS from --libs. dnl dnl Note that if there is a possibility the first call to dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to dnl include an explicit call to PKG_PROG_PKG_CONFIG in your dnl configure.ac. AC_DEFUN([PKG_CHECK_MODULES_STATIC], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl _save_PKG_CONFIG=$PKG_CONFIG PKG_CONFIG="$PKG_CONFIG --static" PKG_CHECK_MODULES($@) PKG_CONFIG=$_save_PKG_CONFIG[]dnl ])dnl PKG_CHECK_MODULES_STATIC dnl PKG_INSTALLDIR([DIRECTORY]) dnl ------------------------- dnl Since: 0.27 dnl dnl Substitutes the variable pkgconfigdir as the location where a module dnl should install pkg-config .pc files. By default the directory is dnl $libdir/pkgconfig, but the default can be changed by passing dnl DIRECTORY. The user can override through the --with-pkgconfigdir dnl parameter. AC_DEFUN([PKG_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([pkgconfigdir], [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, [with_pkgconfigdir=]pkg_default) AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ])dnl PKG_INSTALLDIR dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) dnl -------------------------------- dnl Since: 0.27 dnl dnl Substitutes the variable noarch_pkgconfigdir as the location where a dnl module should install arch-independent pkg-config .pc files. By dnl default the directory is $datadir/pkgconfig, but the default can be dnl changed by passing DIRECTORY. The user can override through the dnl --with-noarch-pkgconfigdir parameter. AC_DEFUN([PKG_NOARCH_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([noarch-pkgconfigdir], [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, [with_noarch_pkgconfigdir=]pkg_default) AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ])dnl PKG_NOARCH_INSTALLDIR dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) dnl ------------------------------------------- dnl Since: 0.28 dnl dnl Retrieves the value of the pkg-config variable for the given module. AC_DEFUN([PKG_CHECK_VAR], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl _PKG_CONFIG([$1], [variable="][$3]["], [$2]) AS_VAR_COPY([$1], [pkg_cv_][$1]) AS_VAR_IF([$1], [""], [$5], [$4])dnl ])dnl PKG_CHECK_VAR dnl PKG_WITH_MODULES(VARIABLE-PREFIX, MODULES, dnl [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND], dnl [DESCRIPTION], [DEFAULT]) dnl ------------------------------------------ dnl dnl Prepare a "--with-" configure option using the lowercase dnl [VARIABLE-PREFIX] name, merging the behaviour of AC_ARG_WITH and dnl PKG_CHECK_MODULES in a single macro. AC_DEFUN([PKG_WITH_MODULES], [ m4_pushdef([with_arg], m4_tolower([$1])) m4_pushdef([description], [m4_default([$5], [build with ]with_arg[ support])]) m4_pushdef([def_arg], [m4_default([$6], [auto])]) m4_pushdef([def_action_if_found], [AS_TR_SH([with_]with_arg)=yes]) m4_pushdef([def_action_if_not_found], [AS_TR_SH([with_]with_arg)=no]) m4_case(def_arg, [yes],[m4_pushdef([with_without], [--without-]with_arg)], [m4_pushdef([with_without],[--with-]with_arg)]) AC_ARG_WITH(with_arg, AS_HELP_STRING(with_without, description[ @<:@default=]def_arg[@:>@]),, [AS_TR_SH([with_]with_arg)=def_arg]) AS_CASE([$AS_TR_SH([with_]with_arg)], [yes],[PKG_CHECK_MODULES([$1],[$2],$3,$4)], [auto],[PKG_CHECK_MODULES([$1],[$2], [m4_n([def_action_if_found]) $3], [m4_n([def_action_if_not_found]) $4])]) m4_popdef([with_arg]) m4_popdef([description]) m4_popdef([def_arg]) ])dnl PKG_WITH_MODULES dnl PKG_HAVE_WITH_MODULES(VARIABLE-PREFIX, MODULES, dnl [DESCRIPTION], [DEFAULT]) dnl ----------------------------------------------- dnl dnl Convenience macro to trigger AM_CONDITIONAL after PKG_WITH_MODULES dnl check._[VARIABLE-PREFIX] is exported as make variable. AC_DEFUN([PKG_HAVE_WITH_MODULES], [ PKG_WITH_MODULES([$1],[$2],,,[$3],[$4]) AM_CONDITIONAL([HAVE_][$1], [test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"]) ])dnl PKG_HAVE_WITH_MODULES dnl PKG_HAVE_DEFINE_WITH_MODULES(VARIABLE-PREFIX, MODULES, dnl [DESCRIPTION], [DEFAULT]) dnl ------------------------------------------------------ dnl dnl Convenience macro to run AM_CONDITIONAL and AC_DEFINE after dnl PKG_WITH_MODULES check. HAVE_[VARIABLE-PREFIX] is exported as make dnl and preprocessor variable. AC_DEFUN([PKG_HAVE_DEFINE_WITH_MODULES], [ PKG_HAVE_WITH_MODULES([$1],[$2],[$3],[$4]) AS_IF([test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"], [AC_DEFINE([HAVE_][$1], 1, [Enable ]m4_tolower([$1])[ support])]) ])dnl PKG_HAVE_DEFINE_WITH_MODULES # Copyright (C) 2002-2024 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.17' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. m4_if([$1], [1.17], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) # _AM_AUTOCONF_VERSION(VERSION) # ----------------------------- # aclocal traces this macro to find the Autoconf version. # This is a private macro too. Using m4_define simplifies # the logic in aclocal, which can simply ignore this definition. m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.17])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001-2024 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to # '$srcdir', '$srcdir/..', or '$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is '.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl # Expand $ac_aux_dir to an absolute path. am_aux_dir=`cd "$ac_aux_dir" && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997-2024 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ([2.52])dnl m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl _AM_SUBST_NOTMAKE([$1_FALSE])dnl m4_define([_AM_COND_VALUE_$1], [$2])dnl if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999-2024 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], [$1], [CXX], [depcc="$CXX" am_compiler_list=], [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], [$1], [UPC], [depcc="$UPC" am_compiler_list=], [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi am__universal=false m4_case([$1], [CC], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac], [CXX], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac]) for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thus: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES. AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE([dependency-tracking], [dnl AS_HELP_STRING( [--enable-dependency-tracking], [do not reject slow dependency extractors]) AS_HELP_STRING( [--disable-dependency-tracking], [speeds up one-time build])]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl AC_SUBST([am__nodep])dnl _AM_SUBST_NOTMAKE([am__nodep])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999-2024 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. # TODO: see whether this extra hack can be removed once we start # requiring Autoconf 2.70 or later. AS_CASE([$CONFIG_FILES], [*\'*], [eval set x "$CONFIG_FILES"], [*], [set x $CONFIG_FILES]) shift # Used to flag and report bootstrapping failures. am_rc=0 for am_mf do # Strip MF so we end up with the name of the file. am_mf=`AS_ECHO(["$am_mf"]) | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile which includes # dependency-tracking related rules and includes. # Grep'ing the whole file directly is not great: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ || continue am_dirpart=`AS_DIRNAME(["$am_mf"])` am_filepart=`AS_BASENAME(["$am_mf"])` AM_RUN_LOG([cd "$am_dirpart" \ && sed -e '/# am--include-marker/d' "$am_filepart" \ | $MAKE -f - am--depfiles]) || am_rc=$? done if test $am_rc -ne 0; then AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments for automatic dependency tracking. If GNU make was not used, consider re-running the configure script with MAKE="gmake" (or whatever is necessary). You can also try re-running configure with the '--disable-dependency-tracking' option to at least be able to build the package (albeit without support for automatic dependency tracking).]) fi AS_UNSET([am_dirpart]) AS_UNSET([am_filepart]) AS_UNSET([am_mf]) AS_UNSET([am_rc]) rm -f conftest-deps.mk } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking is enabled. # This creates each '.Po' and '.Plo' makefile fragment that we'll need in # order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"])]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996-2024 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC]) [_AM_PROG_CC_C_O ]) # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.65])dnl m4_ifdef([_$0_ALREADY_INIT], [m4_fatal([$0 expanded multiple times ]m4_defn([_$0_ALREADY_INIT]))], [m4_define([_$0_ALREADY_INIT], m4_expansion_stack)])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl # test to see if srcdir already configured if test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [AC_DIAGNOSE([obsolete], [$0: two- and three-arguments forms are deprecated.]) m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. m4_if( m4_ifset([AC_PACKAGE_NAME], [ok]):m4_ifset([AC_PACKAGE_VERSION], [ok]), [ok:ok],, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) AM_MISSING_PROG([AUTOCONF], [autoconf]) AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) AM_MISSING_PROG([AUTOHEADER], [autoheader]) AM_MISSING_PROG([MAKEINFO], [makeinfo]) AC_REQUIRE([AM_PROG_INSTALL_SH])dnl AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # AC_SUBST([mkdir_p], ['$(MKDIR_P)']) # We need awk for the "check" target (and possibly the TAP driver). The # system "awk" is bad on some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES([CC])], [m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES([CXX])], [m4_define([AC_PROG_CXX], m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES([OBJC])], [m4_define([AC_PROG_OBJC], m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], [_AM_DEPENDENCIES([OBJCXX])], [m4_define([AC_PROG_OBJCXX], m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl ]) # Variables for tags utilities; see am/tags.am if test -z "$CTAGS"; then CTAGS=ctags fi AC_SUBST([CTAGS]) if test -z "$ETAGS"; then ETAGS=etags fi AC_SUBST([ETAGS]) if test -z "$CSCOPE"; then CSCOPE=cscope fi AC_SUBST([CSCOPE]) AC_REQUIRE([_AM_SILENT_RULES])dnl dnl The testsuite driver may need to know about EXEEXT, so add the dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl AC_REQUIRE([_AM_PROG_RM_F]) AC_REQUIRE([_AM_PROG_XARGS_N]) dnl The trailing newline in this macro's definition is deliberate, for dnl backward compatibility and to allow trailing 'dnl'-style comments dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. ]) dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further dnl mangled by Autoconf and run in a shell conditional statement. m4_define([_AC_COMPILER_EXEEXT], m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001-2024 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi AC_SUBST([install_sh])]) # Copyright (C) 2003-2024 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001-2024 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MAKE_INCLUDE() # ----------------- # Check whether make has an 'include' directive that can support all # the idioms we need for our automatic dependency tracking code. AC_DEFUN([AM_MAKE_INCLUDE], [AC_MSG_CHECKING([whether ${MAKE-make} supports the include directive]) cat > confinc.mk << 'END' am__doit: @echo this is the am__doit target >confinc.out .PHONY: am__doit END am__include="#" am__quote= # BSD make does it like this. echo '.include "confinc.mk" # ignored' > confmf.BSD # Other make implementations (GNU, Solaris 10, AIX) do it like this. echo 'include confinc.mk # ignored' > confmf.GNU _am_result=no for s in GNU BSD; do AM_RUN_LOG([${MAKE-make} -f confmf.$s && cat confinc.out]) AS_CASE([$?:`cat confinc.out 2>/dev/null`], ['0:this is the am__doit target'], [AS_CASE([$s], [BSD], [am__include='.include' am__quote='"'], [am__include='include' am__quote=''])]) if test "$am__include" != "#"; then _am_result="yes ($s style)" break fi done rm -f confinc.* confmf.* AC_MSG_RESULT([${_am_result}]) AC_SUBST([am__include])]) AC_SUBST([am__quote])]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997-2024 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it is modern enough. # If it is, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl if test x"${MISSING+set}" != xset; then MISSING="\${SHELL} '$am_aux_dir/missing'" fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= AC_MSG_WARN(['missing' script is too old or missing]) fi ]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001-2024 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # -------------------- # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), [1])]) # _AM_SET_OPTIONS(OPTIONS) # ------------------------ # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Copyright (C) 1999-2024 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_CC_C_O # --------------- # Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC # to automatically call this. AC_DEFUN([_AM_PROG_CC_C_O], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([compile])dnl AC_LANG_PUSH([C])dnl AC_CACHE_CHECK( [whether $CC understands -c and -o together], [am_cv_prog_cc_c_o], [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i]) if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi AC_LANG_POP([C])]) # For backward compatibility. AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) # Copyright (C) 2022-2024 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_RM_F # --------------- # Check whether 'rm -f' without any arguments works. # https://bugs.gnu.org/10828 AC_DEFUN([_AM_PROG_RM_F], [am__rm_f_notfound= AS_IF([(rm -f && rm -fr && rm -rf) 2>/dev/null], [], [am__rm_f_notfound='""']) AC_SUBST(am__rm_f_notfound) ]) # Copyright (C) 2001-2024 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_RUN_LOG(COMMAND) # ------------------- # Run COMMAND, save the exit status in ac_status, and log it. # (This has been adapted from Autoconf's _AC_RUN_LOG macro.) AC_DEFUN([AM_RUN_LOG], [{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD (exit $ac_status); }]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996-2024 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_SLEEP_FRACTIONAL_SECONDS # ---------------------------- AC_DEFUN([_AM_SLEEP_FRACTIONAL_SECONDS], [dnl AC_CACHE_CHECK([whether sleep supports fractional seconds], am_cv_sleep_fractional_seconds, [dnl AS_IF([sleep 0.001 2>/dev/null], [am_cv_sleep_fractional_seconds=yes], [am_cv_sleep_fractional_seconds=no]) ])]) # _AM_FILESYSTEM_TIMESTAMP_RESOLUTION # ----------------------------------- # Determine the filesystem's resolution for file modification # timestamps. The coarsest we know of is FAT, with a resolution # of only two seconds, even with the most recent "exFAT" extensions. # The finest (e.g. ext4 with large inodes, XFS, ZFS) is one # nanosecond, matching clock_gettime. However, it is probably not # possible to delay execution of a shell script for less than one # millisecond, due to process creation overhead and scheduling # granularity, so we don't check for anything finer than that. (See below.) AC_DEFUN([_AM_FILESYSTEM_TIMESTAMP_RESOLUTION], [dnl AC_REQUIRE([_AM_SLEEP_FRACTIONAL_SECONDS]) AC_CACHE_CHECK([filesystem timestamp resolution], am_cv_filesystem_timestamp_resolution, [dnl # Default to the worst case. am_cv_filesystem_timestamp_resolution=2 # Only try to go finer than 1 sec if sleep can do it. # Don't try 1 sec, because if 0.01 sec and 0.1 sec don't work, # - 1 sec is not much of a win compared to 2 sec, and # - it takes 2 seconds to perform the test whether 1 sec works. # # Instead, just use the default 2s on platforms that have 1s resolution, # accept the extra 1s delay when using $sleep in the Automake tests, in # exchange for not incurring the 2s delay for running the test for all # packages. # am_try_resolutions= if test "$am_cv_sleep_fractional_seconds" = yes; then # Even a millisecond often causes a bunch of false positives, # so just try a hundredth of a second. The time saved between .001 and # .01 is not terribly consequential. am_try_resolutions="0.01 0.1 $am_try_resolutions" fi # In order to catch current-generation FAT out, we must *modify* files # that already exist; the *creation* timestamp is finer. Use names # that make ls -t sort them differently when they have equal # timestamps than when they have distinct timestamps, keeping # in mind that ls -t prints the *newest* file first. rm -f conftest.ts? : > conftest.ts1 : > conftest.ts2 : > conftest.ts3 # Make sure ls -t actually works. Do 'set' in a subshell so we don't # clobber the current shell's arguments. (Outer-level square brackets # are removed by m4; they're present so that m4 does not expand # ; be careful, easy to get confused.) if ( set X `[ls -t conftest.ts[12]]` && { test "$[]*" != "X conftest.ts1 conftest.ts2" || test "$[]*" != "X conftest.ts2 conftest.ts1"; } ); then :; else # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". _AS_ECHO_UNQUOTED( ["Bad output from ls -t: \"`[ls -t conftest.ts[12]]`\""], [AS_MESSAGE_LOG_FD]) AC_MSG_FAILURE([ls -t produces unexpected output. Make sure there is not a broken ls alias in your environment.]) fi for am_try_res in $am_try_resolutions; do # Any one fine-grained sleep might happen to cross the boundary # between two values of a coarser actual resolution, but if we do # two fine-grained sleeps in a row, at least one of them will fall # entirely within a coarse interval. echo alpha > conftest.ts1 sleep $am_try_res echo beta > conftest.ts2 sleep $am_try_res echo gamma > conftest.ts3 # We assume that 'ls -t' will make use of high-resolution # timestamps if the operating system supports them at all. if (set X `ls -t conftest.ts?` && test "$[]2" = conftest.ts3 && test "$[]3" = conftest.ts2 && test "$[]4" = conftest.ts1); then # # Ok, ls -t worked. If we're at a resolution of 1 second, we're done, # because we don't need to test make. make_ok=true if test $am_try_res != 1; then # But if we've succeeded so far with a subsecond resolution, we # have one more thing to check: make. It can happen that # everything else supports the subsecond mtimes, but make doesn't; # notably on macOS, which ships make 3.81 from 2006 (the last one # released under GPLv2). https://bugs.gnu.org/68808 # # We test $MAKE if it is defined in the environment, else "make". # It might get overridden later, but our hope is that in practice # it does not matter: it is the system "make" which is (by far) # the most likely to be broken, whereas if the user overrides it, # probably they did so with a better, or at least not worse, make. # https://lists.gnu.org/archive/html/automake/2024-06/msg00051.html # # Create a Makefile (real tab character here): rm -f conftest.mk echo 'conftest.ts1: conftest.ts2' >conftest.mk echo ' touch conftest.ts2' >>conftest.mk # # Now, running # touch conftest.ts1; touch conftest.ts2; make # should touch ts1 because ts2 is newer. This could happen by luck, # but most often, it will fail if make's support is insufficient. So # test for several consecutive successes. # # (We reuse conftest.ts[12] because we still want to modify existing # files, not create new ones, per above.) n=0 make=${MAKE-make} until test $n -eq 3; do echo one > conftest.ts1 sleep $am_try_res echo two > conftest.ts2 # ts2 should now be newer than ts1 if $make -f conftest.mk | grep 'up to date' >/dev/null; then make_ok=false break # out of $n loop fi n=`expr $n + 1` done fi # if $make_ok; then # Everything we know to check worked out, so call this resolution good. am_cv_filesystem_timestamp_resolution=$am_try_res break # out of $am_try_res loop fi # Otherwise, we'll go on to check the next resolution. fi done rm -f conftest.ts? # (end _am_filesystem_timestamp_resolution) ])]) # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_REQUIRE([_AM_FILESYSTEM_TIMESTAMP_RESOLUTION]) # This check should not be cached, as it may vary across builds of # different projects. AC_MSG_CHECKING([whether build environment is sane]) # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[[\\\"\#\$\&\'\`$am_lf]]*) AC_MSG_ERROR([unsafe absolute working directory name]);; esac case $srcdir in *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). am_build_env_is_sane=no am_has_slept=no rm -f conftest.file for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file if ( set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$[]*" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi test "$[]2" = conftest.file ); then am_build_env_is_sane=yes break fi # Just in case. sleep "$am_cv_filesystem_timestamp_resolution" am_has_slept=yes done AC_MSG_RESULT([$am_build_env_is_sane]) if test "$am_build_env_is_sane" = no; then AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= AS_IF([test -e conftest.file || grep 'slept: no' conftest.file >/dev/null 2>&1],, [dnl ( sleep "$am_cv_filesystem_timestamp_resolution" ) & am_sleep_pid=$! ]) AC_CONFIG_COMMANDS_PRE( [AC_MSG_CHECKING([that generated files are newer than configure]) if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi AC_MSG_RESULT([done])]) rm -f conftest.file ]) # Copyright (C) 2009-2024 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_SILENT_RULES # ---------------- # Enable less verbose build rules support. AC_DEFUN([_AM_SILENT_RULES], [AM_DEFAULT_VERBOSITY=1 AC_ARG_ENABLE([silent-rules], [dnl AS_HELP_STRING( [--enable-silent-rules], [less verbose build output (undo: "make V=1")]) AS_HELP_STRING( [--disable-silent-rules], [verbose build output (undo: "make V=0")])dnl ]) dnl dnl A few 'make' implementations (e.g., NonStop OS and NextStep) dnl do not support nested variable expansions. dnl See automake bug#9928 and bug#10237. am_make=${MAKE-make} AC_CACHE_CHECK([whether $am_make supports nested variables], [am_cv_make_support_nested_variables], [if AS_ECHO([['TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi]) AC_SUBST([AM_V])dnl AM_SUBST_NOTMAKE([AM_V])dnl AC_SUBST([AM_DEFAULT_V])dnl AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl AC_SUBST([AM_DEFAULT_VERBOSITY])dnl AM_BACKSLASH='\' AC_SUBST([AM_BACKSLASH])dnl _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl dnl Delay evaluation of AM_DEFAULT_VERBOSITY to the end to allow multiple calls dnl to AM_SILENT_RULES to change the default value. AC_CONFIG_COMMANDS_PRE([dnl case $enable_silent_rules in @%:@ ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; esac if test $am_cv_make_support_nested_variables = yes; then dnl Using '$V' instead of '$(V)' breaks IRIX make. AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi ])dnl ]) # AM_SILENT_RULES([DEFAULT]) # -------------------------- # Set the default verbosity level to DEFAULT ("yes" being less verbose, "no" or # empty being verbose). AC_DEFUN([AM_SILENT_RULES], [AC_REQUIRE([_AM_SILENT_RULES]) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1])]) # Copyright (C) 2001-2024 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor 'install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in "make install-strip", and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Copyright (C) 2006-2024 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) # AM_SUBST_NOTMAKE(VARIABLE) # -------------------------- # Public sister of _AM_SUBST_NOTMAKE. AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004-2024 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of 'v7', 'ustar', or 'pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar # AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AC_SUBST([AMTAR], ['$${TAR-tar}']) # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' m4_if([$1], [v7], [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], [m4_case([$1], [ustar], [# The POSIX 1988 'ustar' format is defined with fixed-size fields. # There is notably a 21 bits limit for the UID and the GID. In fact, # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 # and bug#13588). am_max_uid=2097151 # 2^21 - 1 am_max_gid=$am_max_uid # The $UID and $GID variables are not portable, so we need to resort # to the POSIX-mandated id(1) utility. Errors in the 'id' calls # below are definitely unexpected, so allow the users to see them # (that is, avoid stderr redirection). am_uid=`id -u || echo unknown` am_gid=`id -g || echo unknown` AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) if test x$am_uid = xunknown; then AC_MSG_WARN([ancient id detected; assuming current UID is ok, but dist-ustar might not work]) elif test $am_uid -le $am_max_uid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) if test x$gm_gid = xunknown; then AC_MSG_WARN([ancient id detected; assuming current GID is ok, but dist-ustar might not work]) elif test $am_gid -le $am_max_gid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi], [pax], [], [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Go ahead even if we have the value already cached. We do so because we # need to set the values for the 'am__tar' and 'am__untar' variables. _am_tools=${am_cv_prog_tar_$1-$_am_tools} for _am_tool in $_am_tools; do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works. rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR # Copyright (C) 2022-2024 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_XARGS_N # ---------------- # Check whether 'xargs -n' works. It should work everywhere, so the fallback # is not optimized at all as we never expect to use it. AC_DEFUN([_AM_PROG_XARGS_N], [AC_CACHE_CHECK([xargs -n works], am_cv_xargs_n_works, [dnl AS_IF([test "`echo 1 2 3 | xargs -n2 echo`" = "1 2 3"], [am_cv_xargs_n_works=yes], [am_cv_xargs_n_works=no])]) AS_IF([test "$am_cv_xargs_n_works" = yes], [am__xargs_n='xargs -n'], [dnl am__xargs_n='am__xargs_n () { shift; sed "s/ /\\n/g" | while read am__xargs_n_arg; do "$@" "$am__xargs_n_arg"; done; }' ])dnl AC_SUBST(am__xargs_n) ]) m4_include([scripts/attributes.m4]) m4_include([scripts/ax_cxx_compile_stdcxx.m4]) m4_include([scripts/ax_execinfo.m4]) m4_include([scripts/ax_pthread.m4]) m4_include([scripts/check_atomic.m4]) m4_include([scripts/checks.m4]) m4_include([scripts/common.m4]) m4_include([scripts/libtool.m4]) m4_include([scripts/ltoptions.m4]) m4_include([scripts/ltsugar.m4]) m4_include([scripts/ltversion.m4]) m4_include([scripts/lt~obsolete.m4]) m4_include([scripts/rak_compiler.m4]) m4_include([scripts/ssl.m4]) libtorrent-0.16.11/compile0000755000000000000000000001670515175073426011074 #! /bin/sh # Wrapper for compilers which do not understand '-c -o'. scriptversion=2024-06-19.01; # UTC # Copyright (C) 1999-2024 Free Software Foundation, Inc. # Written by Tom Tromey . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . nl=' ' # We need space, tab and new line, in precisely that order. Quoting is # there to prevent tools from complaining about whitespace usage. IFS=" "" $nl" file_conv= # func_file_conv build_file lazy # Convert a $build file to $host form and store it in $file # Currently only supports Windows hosts. If the determined conversion # type is listed in (the comma separated) LAZY, no conversion will # take place. func_file_conv () { file=$1 case $file in / | /[!/]*) # absolute file, and not a UNC file if test -z "$file_conv"; then # lazily determine how to convert abs files case `uname -s` in MINGW*) file_conv=mingw ;; CYGWIN* | MSYS*) file_conv=cygwin ;; *) file_conv=wine ;; esac fi case $file_conv/,$2, in *,$file_conv,*) ;; mingw/*) file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` ;; cygwin/* | msys/*) file=`cygpath -m "$file" || echo "$file"` ;; wine/*) file=`winepath -w "$file" || echo "$file"` ;; esac ;; esac } # func_cl_dashL linkdir # Make cl look for libraries in LINKDIR func_cl_dashL () { func_file_conv "$1" if test -z "$lib_path"; then lib_path=$file else lib_path="$lib_path;$file" fi linker_opts="$linker_opts -LIBPATH:$file" } # func_cl_dashl library # Do a library search-path lookup for cl func_cl_dashl () { lib=$1 found=no save_IFS=$IFS IFS=';' for dir in $lib_path $LIB do IFS=$save_IFS if $shared && test -f "$dir/$lib.dll.lib"; then found=yes lib=$dir/$lib.dll.lib break fi if test -f "$dir/$lib.lib"; then found=yes lib=$dir/$lib.lib break fi if test -f "$dir/lib$lib.a"; then found=yes lib=$dir/lib$lib.a break fi done IFS=$save_IFS if test "$found" != yes; then lib=$lib.lib fi } # func_cl_wrapper cl arg... # Adjust compile command to suit cl func_cl_wrapper () { # Assume a capable shell lib_path= shared=: linker_opts= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. eat=1 case $2 in *.o | *.lo | *.[oO][bB][jJ]) func_file_conv "$2" set x "$@" -Fo"$file" shift ;; *) func_file_conv "$2" set x "$@" -Fe"$file" shift ;; esac ;; -I) eat=1 func_file_conv "$2" mingw set x "$@" -I"$file" shift ;; -I*) func_file_conv "${1#-I}" mingw set x "$@" -I"$file" shift ;; -l) eat=1 func_cl_dashl "$2" set x "$@" "$lib" shift ;; -l*) func_cl_dashl "${1#-l}" set x "$@" "$lib" shift ;; -L) eat=1 func_cl_dashL "$2" ;; -L*) func_cl_dashL "${1#-L}" ;; -static) shared=false ;; -Wl,*) arg=${1#-Wl,} save_ifs="$IFS"; IFS=',' for flag in $arg; do IFS="$save_ifs" linker_opts="$linker_opts $flag" done IFS="$save_ifs" ;; -Xlinker) eat=1 linker_opts="$linker_opts $2" ;; -*) set x "$@" "$1" shift ;; *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) func_file_conv "$1" set x "$@" -Tp"$file" shift ;; *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) func_file_conv "$1" mingw set x "$@" "$file" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -n "$linker_opts"; then linker_opts="-link$linker_opts" fi exec "$@" $linker_opts exit 1 } eat= case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: compile [--help] [--version] PROGRAM [ARGS] Wrapper for compilers which do not understand '-c -o'. Remove '-o dest.o' from ARGS, run PROGRAM with the remaining arguments, and rename the output as expected. If you are trying to build a whole package this is not the right script to run: please start by reading the file 'INSTALL'. Report bugs to . GNU Automake home page: . General help using GNU software: . EOF exit $? ;; -v | --v*) echo "compile (GNU Automake) $scriptversion" exit $? ;; cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \ clang-cl | *[/\\]clang-cl | clang-cl.exe | *[/\\]clang-cl.exe | \ icl | *[/\\]icl | icl.exe | *[/\\]icl.exe ) func_cl_wrapper "$@" # Doesn't return... ;; esac ofile= cfile= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. # So we strip '-o arg' only if arg is an object. eat=1 case $2 in *.o | *.obj) ofile=$2 ;; *) set x "$@" -o "$2" shift ;; esac ;; *.c) cfile=$1 set x "$@" "$1" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -z "$ofile" || test -z "$cfile"; then # If no '-o' option was seen then we might have been invoked from a # pattern rule where we don't need one. That is ok -- this is a # normal compilation that the losing compiler can handle. If no # '.c' file was seen then we are probably linking. That is also # ok. exec "$@" fi # Name of file we expect compiler to create. cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` # Create the lock directory. # Note: use '[/\\:.-]' here to ensure that we don't use the same name # that we are using for the .o file. Also, base the name on the expected # object file name, since that is what matters with a parallel build. lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d while true; do if mkdir "$lockdir" >/dev/null 2>&1; then break fi sleep 1 done # FIXME: race condition here if user kills between mkdir and trap. trap "rmdir '$lockdir'; exit 1" 1 2 15 # Run the compile. "$@" ret=$? if test -f "$cofile"; then test "$cofile" = "$ofile" || mv "$cofile" "$ofile" elif test -f "${cofile}bj"; then test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" fi rmdir "$lockdir" exit $ret # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: libtorrent-0.16.11/config.guess0000755000000000000000000014304615175073426012035 #! /bin/sh # Attempt to guess a canonical system name. # Copyright 1992-2024 Free Software Foundation, Inc. # shellcheck disable=SC2006,SC2268 # see below for rationale timestamp='2024-01-01' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # # Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # # You can get the latest version of this script from: # https://git.savannah.gnu.org/cgit/config.git/plain/config.guess # # Please send patches to . # The "shellcheck disable" line above the timestamp inhibits complaints # about features and limitations of the classic Bourne shell that were # superseded or lifted in POSIX. However, this script identifies a wide # variety of pre-POSIX systems that do not have POSIX shells at all, and # even some reasonably current systems (Solaris 10 as case-in-point) still # have a pre-POSIX /bin/sh. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system '$me' is run on. Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright 1992-2024 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try '$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi # Just in case it came from the environment. GUESS= # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, 'CC_FOR_BUILD' used to be named 'HOST_CC'. We still # use 'HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. tmp= # shellcheck disable=SC2172 trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15 set_cc_for_build() { # prevent multiple calls if $tmp is already set test "$tmp" && return 0 : "${TMPDIR=/tmp}" # shellcheck disable=SC2039,SC3028 { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } dummy=$tmp/dummy case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in ,,) echo "int x;" > "$dummy.c" for driver in cc gcc c89 c99 ; do if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then CC_FOR_BUILD=$driver break fi done if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac } # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if test -f /.attbin/uname ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown case $UNAME_SYSTEM in Linux|GNU|GNU/*) LIBC=unknown set_cc_for_build cat <<-EOF > "$dummy.c" #if defined(__ANDROID__) LIBC=android #else #include #if defined(__UCLIBC__) LIBC=uclibc #elif defined(__dietlibc__) LIBC=dietlibc #elif defined(__GLIBC__) LIBC=gnu #elif defined(__LLVM_LIBC__) LIBC=llvm #else #include /* First heuristic to detect musl libc. */ #ifdef __DEFINED_va_list LIBC=musl #endif #endif #endif EOF cc_set_libc=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` eval "$cc_set_libc" # Second heuristic to detect musl libc. if [ "$LIBC" = unknown ] && command -v ldd >/dev/null && ldd --version 2>&1 | grep -q ^musl; then LIBC=musl fi # If the system lacks a compiler, then just pick glibc. # We could probably try harder. if [ "$LIBC" = unknown ]; then LIBC=gnu fi ;; esac # Note: order is significant - the case branches are not exclusive. case $UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ /sbin/sysctl -n hw.machine_arch 2>/dev/null || \ /usr/sbin/sysctl -n hw.machine_arch 2>/dev/null || \ echo unknown)` case $UNAME_MACHINE_ARCH in aarch64eb) machine=aarch64_be-unknown ;; armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; earmv*) arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'` endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'` machine=${arch}${endian}-unknown ;; *) machine=$UNAME_MACHINE_ARCH-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently (or will in the future) and ABI. case $UNAME_MACHINE_ARCH in earm*) os=netbsdelf ;; arm*|i386|m68k|ns32k|sh3*|sparc|vax) set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # Determine ABI tags. case $UNAME_MACHINE_ARCH in earm*) expr='s/^earmv[0-9]/-eabi/;s/eb$//' abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"` ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case $UNAME_VERSION in Debian*) release='-gnu' ;; *) release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. GUESS=$machine-${os}${release}${abi-} ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` GUESS=$UNAME_MACHINE_ARCH-unknown-bitrig$UNAME_RELEASE ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` GUESS=$UNAME_MACHINE_ARCH-unknown-openbsd$UNAME_RELEASE ;; *:SecBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/SecBSD.//'` GUESS=$UNAME_MACHINE_ARCH-unknown-secbsd$UNAME_RELEASE ;; *:LibertyBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` GUESS=$UNAME_MACHINE_ARCH-unknown-libertybsd$UNAME_RELEASE ;; *:MidnightBSD:*:*) GUESS=$UNAME_MACHINE-unknown-midnightbsd$UNAME_RELEASE ;; *:ekkoBSD:*:*) GUESS=$UNAME_MACHINE-unknown-ekkobsd$UNAME_RELEASE ;; *:SolidBSD:*:*) GUESS=$UNAME_MACHINE-unknown-solidbsd$UNAME_RELEASE ;; *:OS108:*:*) GUESS=$UNAME_MACHINE-unknown-os108_$UNAME_RELEASE ;; macppc:MirBSD:*:*) GUESS=powerpc-unknown-mirbsd$UNAME_RELEASE ;; *:MirBSD:*:*) GUESS=$UNAME_MACHINE-unknown-mirbsd$UNAME_RELEASE ;; *:Sortix:*:*) GUESS=$UNAME_MACHINE-unknown-sortix ;; *:Twizzler:*:*) GUESS=$UNAME_MACHINE-unknown-twizzler ;; *:Redox:*:*) GUESS=$UNAME_MACHINE-unknown-redox ;; mips:OSF1:*.*) GUESS=mips-dec-osf1 ;; alpha:OSF1:*:*) # Reset EXIT trap before exiting to avoid spurious non-zero exit code. trap '' 0 case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case $ALPHA_CPU_TYPE in "EV4 (21064)") UNAME_MACHINE=alpha ;; "EV4.5 (21064)") UNAME_MACHINE=alpha ;; "LCA4 (21066/21068)") UNAME_MACHINE=alpha ;; "EV5 (21164)") UNAME_MACHINE=alphaev5 ;; "EV5.6 (21164A)") UNAME_MACHINE=alphaev56 ;; "EV5.6 (21164PC)") UNAME_MACHINE=alphapca56 ;; "EV5.7 (21164PC)") UNAME_MACHINE=alphapca57 ;; "EV6 (21264)") UNAME_MACHINE=alphaev6 ;; "EV6.7 (21264A)") UNAME_MACHINE=alphaev67 ;; "EV6.8CB (21264C)") UNAME_MACHINE=alphaev68 ;; "EV6.8AL (21264B)") UNAME_MACHINE=alphaev68 ;; "EV6.8CX (21264D)") UNAME_MACHINE=alphaev68 ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE=alphaev69 ;; "EV7 (21364)") UNAME_MACHINE=alphaev7 ;; "EV7.9 (21364A)") UNAME_MACHINE=alphaev79 ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. OSF_REL=`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` GUESS=$UNAME_MACHINE-dec-osf$OSF_REL ;; Amiga*:UNIX_System_V:4.0:*) GUESS=m68k-unknown-sysv4 ;; *:[Aa]miga[Oo][Ss]:*:*) GUESS=$UNAME_MACHINE-unknown-amigaos ;; *:[Mm]orph[Oo][Ss]:*:*) GUESS=$UNAME_MACHINE-unknown-morphos ;; *:OS/390:*:*) GUESS=i370-ibm-openedition ;; *:z/VM:*:*) GUESS=s390-ibm-zvmoe ;; *:OS400:*:*) GUESS=powerpc-ibm-os400 ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) GUESS=arm-acorn-riscix$UNAME_RELEASE ;; arm*:riscos:*:*|arm*:RISCOS:*:*) GUESS=arm-unknown-riscos ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) GUESS=hppa1.1-hitachi-hiuxmpp ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. case `(/bin/universe) 2>/dev/null` in att) GUESS=pyramid-pyramid-sysv3 ;; *) GUESS=pyramid-pyramid-bsd ;; esac ;; NILE*:*:*:dcosx) GUESS=pyramid-pyramid-svr4 ;; DRS?6000:unix:4.0:6*) GUESS=sparc-icl-nx6 ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) GUESS=sparc-icl-nx7 ;; esac ;; s390x:SunOS:*:*) SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` GUESS=$UNAME_MACHINE-ibm-solaris2$SUN_REL ;; sun4H:SunOS:5.*:*) SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` GUESS=sparc-hal-solaris2$SUN_REL ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` GUESS=sparc-sun-solaris2$SUN_REL ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) GUESS=i386-pc-auroraux$UNAME_RELEASE ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) set_cc_for_build SUN_ARCH=i386 # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. if test "$CC_FOR_BUILD" != no_compiler_found; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -m64 -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH=x86_64 fi fi SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` GUESS=$SUN_ARCH-pc-solaris2$SUN_REL ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` GUESS=sparc-sun-solaris3$SUN_REL ;; sun4*:SunOS:*:*) case `/usr/bin/arch -k` in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like '4.1.3-JL'. SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/'` GUESS=sparc-sun-sunos$SUN_REL ;; sun3*:SunOS:*:*) GUESS=m68k-sun-sunos$UNAME_RELEASE ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3 case `/bin/arch` in sun3) GUESS=m68k-sun-sunos$UNAME_RELEASE ;; sun4) GUESS=sparc-sun-sunos$UNAME_RELEASE ;; esac ;; aushp:SunOS:*:*) GUESS=sparc-auspex-sunos$UNAME_RELEASE ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) GUESS=m68k-atari-mint$UNAME_RELEASE ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) GUESS=m68k-atari-mint$UNAME_RELEASE ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) GUESS=m68k-atari-mint$UNAME_RELEASE ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) GUESS=m68k-milan-mint$UNAME_RELEASE ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) GUESS=m68k-hades-mint$UNAME_RELEASE ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) GUESS=m68k-unknown-mint$UNAME_RELEASE ;; m68k:machten:*:*) GUESS=m68k-apple-machten$UNAME_RELEASE ;; powerpc:machten:*:*) GUESS=powerpc-apple-machten$UNAME_RELEASE ;; RISC*:Mach:*:*) GUESS=mips-dec-mach_bsd4.3 ;; RISC*:ULTRIX:*:*) GUESS=mips-dec-ultrix$UNAME_RELEASE ;; VAX*:ULTRIX*:*:*) GUESS=vax-dec-ultrix$UNAME_RELEASE ;; 2020:CLIX:*:* | 2430:CLIX:*:*) GUESS=clipper-intergraph-clix$UNAME_RELEASE ;; mips:*:*:UMIPS | mips:*:*:RISCos) set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o "$dummy" "$dummy.c" && dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`"$dummy" "$dummyarg"` && { echo "$SYSTEM_NAME"; exit; } GUESS=mips-mips-riscos$UNAME_RELEASE ;; Motorola:PowerMAX_OS:*:*) GUESS=powerpc-motorola-powermax ;; Motorola:*:4.3:PL8-*) GUESS=powerpc-harris-powermax ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) GUESS=powerpc-harris-powermax ;; Night_Hawk:Power_UNIX:*:*) GUESS=powerpc-harris-powerunix ;; m88k:CX/UX:7*:*) GUESS=m88k-harris-cxux7 ;; m88k:*:4*:R4*) GUESS=m88k-motorola-sysv4 ;; m88k:*:3*:R3*) GUESS=m88k-motorola-sysv3 ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = mc88110 then if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \ test "$TARGET_BINARY_INTERFACE"x = x then GUESS=m88k-dg-dgux$UNAME_RELEASE else GUESS=m88k-dg-dguxbcs$UNAME_RELEASE fi else GUESS=i586-dg-dgux$UNAME_RELEASE fi ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) GUESS=m88k-dolphin-sysv3 ;; M88*:*:R3*:*) # Delta 88k system running SVR3 GUESS=m88k-motorola-sysv3 ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) GUESS=m88k-tektronix-sysv3 ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) GUESS=m68k-tektronix-bsd ;; *:IRIX*:*:*) IRIX_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/g'` GUESS=mips-sgi-irix$IRIX_REL ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. GUESS=romp-ibm-aix # uname -m gives an 8 hex-code CPU id ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) GUESS=i386-ibm-aix ;; ia64:AIX:*:*) if test -x /usr/bin/oslevel ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=$UNAME_VERSION.$UNAME_RELEASE fi GUESS=$UNAME_MACHINE-ibm-aix$IBM_REV ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` then GUESS=$SYSTEM_NAME else GUESS=rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then GUESS=rs6000-ibm-aix3.2.4 else GUESS=rs6000-ibm-aix3.2 fi ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if test -x /usr/bin/lslpp ; then IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | \ awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` else IBM_REV=$UNAME_VERSION.$UNAME_RELEASE fi GUESS=$IBM_ARCH-ibm-aix$IBM_REV ;; *:AIX:*:*) GUESS=rs6000-ibm-aix ;; ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) GUESS=romp-ibm-bsd4.4 ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and GUESS=romp-ibm-bsd$UNAME_RELEASE # 4.3 with uname added to ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) GUESS=rs6000-bull-bosx ;; DPX/2?00:B.O.S.:*:*) GUESS=m68k-bull-sysv3 ;; 9000/[34]??:4.3bsd:1.*:*) GUESS=m68k-hp-bsd ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) GUESS=m68k-hp-bsd4.4 ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'` case $UNAME_MACHINE in 9000/31?) HP_ARCH=m68000 ;; 9000/[34]??) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if test -x /usr/bin/getconf; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case $sc_cpu_version in 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case $sc_kernel_bits in 32) HP_ARCH=hppa2.0n ;; 64) HP_ARCH=hppa2.0w ;; '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 esac ;; esac fi if test "$HP_ARCH" = ""; then set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if test "$HP_ARCH" = hppa2.0w then set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then HP_ARCH=hppa2.0w else HP_ARCH=hppa64 fi fi GUESS=$HP_ARCH-hp-hpux$HPUX_REV ;; ia64:HP-UX:*:*) HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'` GUESS=ia64-hp-hpux$HPUX_REV ;; 3050*:HI-UX:*:*) set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` && { echo "$SYSTEM_NAME"; exit; } GUESS=unknown-hitachi-hiuxwe2 ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) GUESS=hppa1.1-hp-bsd ;; 9000/8??:4.3bsd:*:*) GUESS=hppa1.0-hp-bsd ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) GUESS=hppa1.0-hp-mpeix ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) GUESS=hppa1.1-hp-osf ;; hp8??:OSF1:*:*) GUESS=hppa1.0-hp-osf ;; i*86:OSF1:*:*) if test -x /usr/sbin/sysversion ; then GUESS=$UNAME_MACHINE-unknown-osf1mk else GUESS=$UNAME_MACHINE-unknown-osf1 fi ;; parisc*:Lites*:*:*) GUESS=hppa1.1-hp-lites ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) GUESS=c1-convex-bsd ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) GUESS=c34-convex-bsd ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) GUESS=c38-convex-bsd ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) GUESS=c4-convex-bsd ;; CRAY*Y-MP:*:*:*) CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` GUESS=ymp-cray-unicos$CRAY_REL ;; CRAY*[A-Z]90:*:*:*) echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` GUESS=t90-cray-unicos$CRAY_REL ;; CRAY*T3E:*:*:*) CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` GUESS=alphaev5-cray-unicosmk$CRAY_REL ;; CRAY*SV1:*:*:*) CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` GUESS=sv1-cray-unicos$CRAY_REL ;; *:UNICOS/mp:*:*) CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` GUESS=craynv-cray-unicosmp$CRAY_REL ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'` GUESS=${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL} ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` GUESS=sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL} ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) GUESS=$UNAME_MACHINE-pc-bsdi$UNAME_RELEASE ;; sparc*:BSD/OS:*:*) GUESS=sparc-unknown-bsdi$UNAME_RELEASE ;; *:BSD/OS:*:*) GUESS=$UNAME_MACHINE-unknown-bsdi$UNAME_RELEASE ;; arm:FreeBSD:*:*) UNAME_PROCESSOR=`uname -p` set_cc_for_build if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabi else FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabihf fi ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`uname -p` case $UNAME_PROCESSOR in amd64) UNAME_PROCESSOR=x86_64 ;; i386) UNAME_PROCESSOR=i586 ;; esac FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL ;; i*:CYGWIN*:*) GUESS=$UNAME_MACHINE-pc-cygwin ;; *:MINGW64*:*) GUESS=$UNAME_MACHINE-pc-mingw64 ;; *:MINGW*:*) GUESS=$UNAME_MACHINE-pc-mingw32 ;; *:MSYS*:*) GUESS=$UNAME_MACHINE-pc-msys ;; i*:PW*:*) GUESS=$UNAME_MACHINE-pc-pw32 ;; *:SerenityOS:*:*) GUESS=$UNAME_MACHINE-pc-serenity ;; *:Interix*:*) case $UNAME_MACHINE in x86) GUESS=i586-pc-interix$UNAME_RELEASE ;; authenticamd | genuineintel | EM64T) GUESS=x86_64-unknown-interix$UNAME_RELEASE ;; IA64) GUESS=ia64-unknown-interix$UNAME_RELEASE ;; esac ;; i*:UWIN*:*) GUESS=$UNAME_MACHINE-pc-uwin ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) GUESS=x86_64-pc-cygwin ;; prep*:SunOS:5.*:*) SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` GUESS=powerpcle-unknown-solaris2$SUN_REL ;; *:GNU:*:*) # the GNU system GNU_ARCH=`echo "$UNAME_MACHINE" | sed -e 's,[-/].*$,,'` GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's,/.*$,,'` GUESS=$GNU_ARCH-unknown-$LIBC$GNU_REL ;; *:GNU/*:*:*) # other systems with GNU libc and userland GNU_SYS=`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"` GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` GUESS=$UNAME_MACHINE-unknown-$GNU_SYS$GNU_REL-$LIBC ;; x86_64:[Mm]anagarm:*:*|i?86:[Mm]anagarm:*:*) GUESS="$UNAME_MACHINE-pc-managarm-mlibc" ;; *:[Mm]anagarm:*:*) GUESS="$UNAME_MACHINE-unknown-managarm-mlibc" ;; *:Minix:*:*) GUESS=$UNAME_MACHINE-unknown-minix ;; aarch64:Linux:*:*) set_cc_for_build CPU=$UNAME_MACHINE LIBCABI=$LIBC if test "$CC_FOR_BUILD" != no_compiler_found; then ABI=64 sed 's/^ //' << EOF > "$dummy.c" #ifdef __ARM_EABI__ #ifdef __ARM_PCS_VFP ABI=eabihf #else ABI=eabi #endif #endif EOF cc_set_abi=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^ABI' | sed 's, ,,g'` eval "$cc_set_abi" case $ABI in eabi | eabihf) CPU=armv8l; LIBCABI=$LIBC$ABI ;; esac fi GUESS=$CPU-unknown-linux-$LIBCABI ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC=gnulibc1 ; fi GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; arc:Linux:*:* | arceb:Linux:*:* | arc32:Linux:*:* | arc64:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; arm*:Linux:*:*) set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then GUESS=$UNAME_MACHINE-unknown-linux-$LIBC else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabi else GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabihf fi fi ;; avr32*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; cris:Linux:*:*) GUESS=$UNAME_MACHINE-axis-linux-$LIBC ;; crisv32:Linux:*:*) GUESS=$UNAME_MACHINE-axis-linux-$LIBC ;; e2k:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; frv:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; hexagon:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; i*86:Linux:*:*) GUESS=$UNAME_MACHINE-pc-linux-$LIBC ;; ia64:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; k1om:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; kvx:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; kvx:cos:*:*) GUESS=$UNAME_MACHINE-unknown-cos ;; kvx:mbr:*:*) GUESS=$UNAME_MACHINE-unknown-mbr ;; loongarch32:Linux:*:* | loongarch64:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; m32r*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; m68*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; mips:Linux:*:* | mips64:Linux:*:*) set_cc_for_build IS_GLIBC=0 test x"${LIBC}" = xgnu && IS_GLIBC=1 sed 's/^ //' << EOF > "$dummy.c" #undef CPU #undef mips #undef mipsel #undef mips64 #undef mips64el #if ${IS_GLIBC} && defined(_ABI64) LIBCABI=gnuabi64 #else #if ${IS_GLIBC} && defined(_ABIN32) LIBCABI=gnuabin32 #else LIBCABI=${LIBC} #endif #endif #if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 CPU=mipsisa64r6 #else #if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 CPU=mipsisa32r6 #else #if defined(__mips64) CPU=mips64 #else CPU=mips #endif #endif #endif #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) MIPS_ENDIAN=el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) MIPS_ENDIAN= #else MIPS_ENDIAN= #endif #endif EOF cc_set_vars=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI'` eval "$cc_set_vars" test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; } ;; mips64el:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; openrisc*:Linux:*:*) GUESS=or1k-unknown-linux-$LIBC ;; or32:Linux:*:* | or1k*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; padre:Linux:*:*) GUESS=sparc-unknown-linux-$LIBC ;; parisc64:Linux:*:* | hppa64:Linux:*:*) GUESS=hppa64-unknown-linux-$LIBC ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) GUESS=hppa1.1-unknown-linux-$LIBC ;; PA8*) GUESS=hppa2.0-unknown-linux-$LIBC ;; *) GUESS=hppa-unknown-linux-$LIBC ;; esac ;; ppc64:Linux:*:*) GUESS=powerpc64-unknown-linux-$LIBC ;; ppc:Linux:*:*) GUESS=powerpc-unknown-linux-$LIBC ;; ppc64le:Linux:*:*) GUESS=powerpc64le-unknown-linux-$LIBC ;; ppcle:Linux:*:*) GUESS=powerpcle-unknown-linux-$LIBC ;; riscv32:Linux:*:* | riscv32be:Linux:*:* | riscv64:Linux:*:* | riscv64be:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; s390:Linux:*:* | s390x:Linux:*:*) GUESS=$UNAME_MACHINE-ibm-linux-$LIBC ;; sh64*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; sh*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; sparc:Linux:*:* | sparc64:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; tile*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; vax:Linux:*:*) GUESS=$UNAME_MACHINE-dec-linux-$LIBC ;; x86_64:Linux:*:*) set_cc_for_build CPU=$UNAME_MACHINE LIBCABI=$LIBC if test "$CC_FOR_BUILD" != no_compiler_found; then ABI=64 sed 's/^ //' << EOF > "$dummy.c" #ifdef __i386__ ABI=x86 #else #ifdef __ILP32__ ABI=x32 #endif #endif EOF cc_set_abi=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^ABI' | sed 's, ,,g'` eval "$cc_set_abi" case $ABI in x86) CPU=i686 ;; x32) LIBCABI=${LIBC}x32 ;; esac fi GUESS=$CPU-pc-linux-$LIBCABI ;; xtensa*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. GUESS=i386-sequent-sysv4 ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. GUESS=$UNAME_MACHINE-pc-sysv4.2uw$UNAME_VERSION ;; i*86:OS/2:*:*) # If we were able to find 'uname', then EMX Unix compatibility # is probably installed. GUESS=$UNAME_MACHINE-pc-os2-emx ;; i*86:XTS-300:*:STOP) GUESS=$UNAME_MACHINE-unknown-stop ;; i*86:atheos:*:*) GUESS=$UNAME_MACHINE-unknown-atheos ;; i*86:syllable:*:*) GUESS=$UNAME_MACHINE-pc-syllable ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) GUESS=i386-unknown-lynxos$UNAME_RELEASE ;; i*86:*DOS:*:*) GUESS=$UNAME_MACHINE-pc-msdosdjgpp ;; i*86:*:4.*:*) UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then GUESS=$UNAME_MACHINE-univel-sysv$UNAME_REL else GUESS=$UNAME_MACHINE-pc-sysv$UNAME_REL fi ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac GUESS=$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 GUESS=$UNAME_MACHINE-pc-sco$UNAME_REL else GUESS=$UNAME_MACHINE-pc-sysv32 fi ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub # prints for the "djgpp" host, or else GDB configure will decide that # this is a cross-build. GUESS=i586-pc-msdosdjgpp ;; Intel:Mach:3*:*) GUESS=i386-pc-mach3 ;; paragon:*:*:*) GUESS=i860-intel-osf1 ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then GUESS=i860-stardent-sysv$UNAME_RELEASE # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. GUESS=i860-unknown-sysv$UNAME_RELEASE # Unknown i860-SVR4 fi ;; mini*:CTIX:SYS*5:*) # "miniframe" GUESS=m68010-convergent-sysv ;; mc68k:UNIX:SYSTEM5:3.51m) GUESS=m68k-convergent-sysv ;; M680?0:D-NIX:5.3:*) GUESS=m68k-diab-dnix ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; NCR*:*:4.2:* | MPRAS*:*:4.2:*) OS_REL='.3' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) GUESS=m68k-unknown-lynxos$UNAME_RELEASE ;; mc68030:UNIX_System_V:4.*:*) GUESS=m68k-atari-sysv4 ;; TSUNAMI:LynxOS:2.*:*) GUESS=sparc-unknown-lynxos$UNAME_RELEASE ;; rs6000:LynxOS:2.*:*) GUESS=rs6000-unknown-lynxos$UNAME_RELEASE ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) GUESS=powerpc-unknown-lynxos$UNAME_RELEASE ;; SM[BE]S:UNIX_SV:*:*) GUESS=mips-dde-sysv$UNAME_RELEASE ;; RM*:ReliantUNIX-*:*:*) GUESS=mips-sni-sysv4 ;; RM*:SINIX-*:*:*) GUESS=mips-sni-sysv4 ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` GUESS=$UNAME_MACHINE-sni-sysv4 else GUESS=ns32k-sni-sysv fi ;; PENTIUM:*:4.0*:*) # Unisys 'ClearPath HMP IX 4000' SVR4/MP effort # says GUESS=i586-unisys-sysv4 ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm GUESS=hppa1.1-stratus-sysv4 ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. GUESS=i860-stratus-sysv4 ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. GUESS=$UNAME_MACHINE-stratus-vos ;; *:VOS:*:*) # From Paul.Green@stratus.com. GUESS=hppa1.1-stratus-vos ;; mc68*:A/UX:*:*) GUESS=m68k-apple-aux$UNAME_RELEASE ;; news*:NEWS-OS:6*:*) GUESS=mips-sony-newsos6 ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if test -d /usr/nec; then GUESS=mips-nec-sysv$UNAME_RELEASE else GUESS=mips-unknown-sysv$UNAME_RELEASE fi ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. GUESS=powerpc-be-beos ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. GUESS=powerpc-apple-beos ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. GUESS=i586-pc-beos ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. GUESS=i586-pc-haiku ;; ppc:Haiku:*:*) # Haiku running on Apple PowerPC GUESS=powerpc-apple-haiku ;; *:Haiku:*:*) # Haiku modern gcc (not bound by BeOS compat) GUESS=$UNAME_MACHINE-unknown-haiku ;; SX-4:SUPER-UX:*:*) GUESS=sx4-nec-superux$UNAME_RELEASE ;; SX-5:SUPER-UX:*:*) GUESS=sx5-nec-superux$UNAME_RELEASE ;; SX-6:SUPER-UX:*:*) GUESS=sx6-nec-superux$UNAME_RELEASE ;; SX-7:SUPER-UX:*:*) GUESS=sx7-nec-superux$UNAME_RELEASE ;; SX-8:SUPER-UX:*:*) GUESS=sx8-nec-superux$UNAME_RELEASE ;; SX-8R:SUPER-UX:*:*) GUESS=sx8r-nec-superux$UNAME_RELEASE ;; SX-ACE:SUPER-UX:*:*) GUESS=sxace-nec-superux$UNAME_RELEASE ;; Power*:Rhapsody:*:*) GUESS=powerpc-apple-rhapsody$UNAME_RELEASE ;; *:Rhapsody:*:*) GUESS=$UNAME_MACHINE-apple-rhapsody$UNAME_RELEASE ;; arm64:Darwin:*:*) GUESS=aarch64-apple-darwin$UNAME_RELEASE ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` case $UNAME_PROCESSOR in unknown) UNAME_PROCESSOR=powerpc ;; esac if command -v xcode-select > /dev/null 2> /dev/null && \ ! xcode-select --print-path > /dev/null 2> /dev/null ; then # Avoid executing cc if there is no toolchain installed as # cc will be a stub that puts up a graphical alert # prompting the user to install developer tools. CC_FOR_BUILD=no_compiler_found else set_cc_for_build fi if test "$CC_FOR_BUILD" != no_compiler_found; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then case $UNAME_PROCESSOR in i386) UNAME_PROCESSOR=x86_64 ;; powerpc) UNAME_PROCESSOR=powerpc64 ;; esac fi # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_PPC >/dev/null then UNAME_PROCESSOR=powerpc fi elif test "$UNAME_PROCESSOR" = i386 ; then # uname -m returns i386 or x86_64 UNAME_PROCESSOR=$UNAME_MACHINE fi GUESS=$UNAME_PROCESSOR-apple-darwin$UNAME_RELEASE ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = x86; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi GUESS=$UNAME_PROCESSOR-$UNAME_MACHINE-nto-qnx$UNAME_RELEASE ;; *:QNX:*:4*) GUESS=i386-pc-qnx ;; NEO-*:NONSTOP_KERNEL:*:*) GUESS=neo-tandem-nsk$UNAME_RELEASE ;; NSE-*:NONSTOP_KERNEL:*:*) GUESS=nse-tandem-nsk$UNAME_RELEASE ;; NSR-*:NONSTOP_KERNEL:*:*) GUESS=nsr-tandem-nsk$UNAME_RELEASE ;; NSV-*:NONSTOP_KERNEL:*:*) GUESS=nsv-tandem-nsk$UNAME_RELEASE ;; NSX-*:NONSTOP_KERNEL:*:*) GUESS=nsx-tandem-nsk$UNAME_RELEASE ;; *:NonStop-UX:*:*) GUESS=mips-compaq-nonstopux ;; BS2000:POSIX*:*:*) GUESS=bs2000-siemens-sysv ;; DS/*:UNIX_System_V:*:*) GUESS=$UNAME_MACHINE-$UNAME_SYSTEM-$UNAME_RELEASE ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "${cputype-}" = 386; then UNAME_MACHINE=i386 elif test "x${cputype-}" != x; then UNAME_MACHINE=$cputype fi GUESS=$UNAME_MACHINE-unknown-plan9 ;; *:TOPS-10:*:*) GUESS=pdp10-unknown-tops10 ;; *:TENEX:*:*) GUESS=pdp10-unknown-tenex ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) GUESS=pdp10-dec-tops20 ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) GUESS=pdp10-xkl-tops20 ;; *:TOPS-20:*:*) GUESS=pdp10-unknown-tops20 ;; *:ITS:*:*) GUESS=pdp10-unknown-its ;; SEI:*:*:SEIUX) GUESS=mips-sei-seiux$UNAME_RELEASE ;; *:DragonFly:*:*) DRAGONFLY_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` GUESS=$UNAME_MACHINE-unknown-dragonfly$DRAGONFLY_REL ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case $UNAME_MACHINE in A*) GUESS=alpha-dec-vms ;; I*) GUESS=ia64-dec-vms ;; V*) GUESS=vax-dec-vms ;; esac ;; *:XENIX:*:SysV) GUESS=i386-pc-xenix ;; i*86:skyos:*:*) SKYOS_REL=`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'` GUESS=$UNAME_MACHINE-pc-skyos$SKYOS_REL ;; i*86:rdos:*:*) GUESS=$UNAME_MACHINE-pc-rdos ;; i*86:Fiwix:*:*) GUESS=$UNAME_MACHINE-pc-fiwix ;; *:AROS:*:*) GUESS=$UNAME_MACHINE-unknown-aros ;; x86_64:VMkernel:*:*) GUESS=$UNAME_MACHINE-unknown-esx ;; amd64:Isilon\ OneFS:*:*) GUESS=x86_64-unknown-onefs ;; *:Unleashed:*:*) GUESS=$UNAME_MACHINE-unknown-unleashed$UNAME_RELEASE ;; *:Ironclad:*:*) GUESS=$UNAME_MACHINE-unknown-ironclad ;; esac # Do we have a guess based on uname results? if test "x$GUESS" != x; then echo "$GUESS" exit fi # No uname command or uname output not recognized. set_cc_for_build cat > "$dummy.c" < #include #endif #if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) #if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) #include #if defined(_SIZE_T_) || defined(SIGLOST) #include #endif #endif #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) #if !defined (ultrix) #include #if defined (BSD) #if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); #else #if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); #else printf ("vax-dec-bsd\n"); exit (0); #endif #endif #else printf ("vax-dec-bsd\n"); exit (0); #endif #else #if defined(_SIZE_T_) || defined(SIGLOST) struct utsname un; uname (&un); printf ("vax-dec-ultrix%s\n", un.release); exit (0); #else printf ("vax-dec-ultrix\n"); exit (0); #endif #endif #endif #if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) #if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) #if defined(_SIZE_T_) || defined(SIGLOST) struct utsname *un; uname (&un); printf ("mips-dec-ultrix%s\n", un.release); exit (0); #else printf ("mips-dec-ultrix\n"); exit (0); #endif #endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=`"$dummy"` && { echo "$SYSTEM_NAME"; exit; } # Apollos put the system type in the environment. test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; } echo "$0: unable to guess system type" >&2 case $UNAME_MACHINE:$UNAME_SYSTEM in mips:Linux | mips64:Linux) # If we got here on MIPS GNU/Linux, output extra information. cat >&2 <&2 <&2 </dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = "$UNAME_MACHINE" UNAME_RELEASE = "$UNAME_RELEASE" UNAME_SYSTEM = "$UNAME_SYSTEM" UNAME_VERSION = "$UNAME_VERSION" EOF fi exit 1 # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: libtorrent-0.16.11/test/0000755000000000000000000000000015175073435010544 5libtorrent-0.16.11/test/Makefile.am0000644000000000000000000001064715175073411012522 TESTS = \ LibTorrent_Test_Torrent_Net \ LibTorrent_Test_Torrent_Utils \ LibTorrent_Test_Torrent \ LibTorrent_Test_Data \ LibTorrent_Test_Net \ LibTorrent_Test_Tracker \ LibTorrent_Test check_PROGRAMS = $(TESTS) # This can cause duplicate symbols, so export anything that causes issues. # LibTorrent_Test_LDADD = ../src/libtorrent.la LibTorrent_Test_LDADD = \ ../src/libtorrent.la \ ../src/libtorrent_other.la \ ../src/torrent/libtorrent_torrent.la LibTorrent_Test_Torrent_Net_LDADD = $(LibTorrent_Test_LDADD) LibTorrent_Test_Torrent_Utils_LDADD = $(LibTorrent_Test_LDADD) LibTorrent_Test_Torrent_LDADD = $(LibTorrent_Test_LDADD) LibTorrent_Test_Data_LDADD = $(LibTorrent_Test_LDADD) LibTorrent_Test_Net_LDADD = $(LibTorrent_Test_LDADD) LibTorrent_Test_Tracker_LDADD = $(LibTorrent_Test_LDADD) LibTorrent_Test_Common = \ main.cc \ helpers/expect_fd.h \ helpers/expect_utils.h \ helpers/mock_compare.h \ helpers/mock_function.cc \ helpers/mock_function.h \ helpers/network.cc \ helpers/network.h \ helpers/progress_listener.cc \ helpers/progress_listener.h \ helpers/protectors.cc \ helpers/protectors.h \ helpers/test_fixture.cc \ helpers/test_fixture.h \ helpers/test_main_thread.cc \ helpers/test_main_thread.h \ helpers/test_thread.cc \ helpers/test_thread.h \ helpers/test_utils.h \ helpers/tracker_test.cc \ helpers/tracker_test.h \ helpers/utils.h LibTorrent_Test_Torrent_Net_SOURCES = $(LibTorrent_Test_Common) \ torrent/net/test_address_info.cc \ torrent/net/test_address_info.h \ torrent/net/test_fd.cc \ torrent/net/test_fd.h \ torrent/net/test_socket_address.cc \ torrent/net/test_socket_address.h LibTorrent_Test_Torrent_Utils_SOURCES = $(LibTorrent_Test_Common) \ torrent/utils/test_extents.cc \ torrent/utils/test_extents.h \ torrent/utils/test_log.cc \ torrent/utils/test_log.h \ torrent/utils/test_log_buffer.cc \ torrent/utils/test_log_buffer.h \ torrent/utils/test_option_strings.cc \ torrent/utils/test_option_strings.h \ torrent/utils/test_queue_buckets.cc \ torrent/utils/test_queue_buckets.h \ torrent/utils/test_signal_bitfield.cc \ torrent/utils/test_signal_bitfield.h \ torrent/utils/test_signal_interrupt.cc \ torrent/utils/test_signal_interrupt.h \ torrent/utils/test_thread_base.cc \ torrent/utils/test_thread_base.h \ torrent/utils/test_uri_parser.cc \ torrent/utils/test_uri_parser.h LibTorrent_Test_Torrent_SOURCES = $(LibTorrent_Test_Common) \ torrent/object_test.cc \ torrent/object_test.h \ torrent/object_test_utils.cc \ torrent/object_test_utils.h \ torrent/object_static_map_test.cc \ torrent/object_static_map_test.h \ torrent/object_stream_test.cc \ torrent/object_stream_test.h \ torrent/test_tracker_controller.cc \ torrent/test_tracker_controller.h \ torrent/test_tracker_controller_features.cc \ torrent/test_tracker_controller_features.h \ torrent/test_tracker_controller_requesting.cc \ torrent/test_tracker_controller_requesting.h \ torrent/test_tracker_list.cc \ torrent/test_tracker_list.h \ torrent/test_tracker_list_features.cc \ torrent/test_tracker_list_features.h \ torrent/test_tracker_timeout.cc \ torrent/test_tracker_timeout.h LibTorrent_Test_Data_SOURCES = $(LibTorrent_Test_Common) \ data/test_chunk_list.cc \ data/test_chunk_list.h \ data/test_hash_check_queue.cc \ data/test_hash_check_queue.h \ data/test_hash_queue.cc \ data/test_hash_queue.h LibTorrent_Test_Net_SOURCES = $(LibTorrent_Test_Common) LibTorrent_Test_Tracker_SOURCES = $(LibTorrent_Test_Common) \ tracker/test_tracker_http.cc \ tracker/test_tracker_http.h LibTorrent_Test_SOURCES = $(LibTorrent_Test_Common) \ \ rak/ranges_test.cc \ rak/ranges_test.h \ \ protocol/test_request_list.cc \ protocol/test_request_list.h LibTorrent_Test_Torrent_Net_CXXFLAGS = $(CPPUNIT_CFLAGS) LibTorrent_Test_Torrent_Net_LDFLAGS = $(CPPUNIT_LIBS) LibTorrent_Test_Torrent_Utils_CXXFLAGS = $(CPPUNIT_CFLAGS) LibTorrent_Test_Torrent_Utils_LDFLAGS = $(CPPUNIT_LIBS) LibTorrent_Test_Torrent_CXXFLAGS = $(CPPUNIT_CFLAGS) LibTorrent_Test_Torrent_LDFLAGS = $(CPPUNIT_LIBS) LibTorrent_Test_Data_CXXFLAGS = $(CPPUNIT_CFLAGS) LibTorrent_Test_Data_LDFLAGS = $(CPPUNIT_LIBS) LibTorrent_Test_Net_CXXFLAGS = $(CPPUNIT_CFLAGS) LibTorrent_Test_Net_LDFLAGS = $(CPPUNIT_LIBS) LibTorrent_Test_Tracker_CXXFLAGS = $(CPPUNIT_CFLAGS) LibTorrent_Test_Tracker_LDFLAGS = $(CPPUNIT_LIBS) LibTorrent_Test_CXXFLAGS = $(CPPUNIT_CFLAGS) LibTorrent_Test_LDFLAGS = $(CPPUNIT_LIBS) AM_CPPFLAGS = -I$(srcdir) -I$(top_srcdir) -I$(top_srcdir)/src libtorrent-0.16.11/test/torrent/0000755000000000000000000000000015175073435012241 5libtorrent-0.16.11/test/torrent/test_tracker_list_features.h0000644000000000000000000000117415175073411017752 #include "test/helpers/test_main_thread.h" class TestTrackerListFeatures : public TestFixtureWithMainAndTrackerThread { CPPUNIT_TEST_SUITE(TestTrackerListFeatures); CPPUNIT_TEST(test_new_peers); CPPUNIT_TEST(test_has_active); CPPUNIT_TEST(test_find_next_to_request); CPPUNIT_TEST(test_find_next_to_request_groups); CPPUNIT_TEST(test_count_active); CPPUNIT_TEST(test_request_safeguard); CPPUNIT_TEST_SUITE_END(); public: void test_new_peers(); void test_has_active(); void test_find_next_to_request(); void test_find_next_to_request_groups(); void test_count_active(); void test_request_safeguard(); }; libtorrent-0.16.11/test/torrent/net/0000755000000000000000000000000015175073435013027 5libtorrent-0.16.11/test/torrent/net/test_socket_address.cc0000644000000000000000000004575515175073411017324 #include "config.h" #include "test_socket_address.h" #include "helpers/network.h" #include "torrent/exceptions.h" #include "torrent/net/socket_address.h" CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(test_socket_address, "torrent/net"); void test_socket_address::test_sa_is_any() { TEST_DEFAULT_SA; CPPUNIT_ASSERT(torrent::sap_is_any(sin_any)); CPPUNIT_ASSERT(torrent::sap_is_any(sin_any_5000)); CPPUNIT_ASSERT(torrent::sap_is_any(sin6_v4_any)); CPPUNIT_ASSERT(torrent::sap_is_any(sin6_v4_any_5000)); CPPUNIT_ASSERT(!torrent::sap_is_any(sin_bc)); CPPUNIT_ASSERT(!torrent::sap_is_any(sin_1)); CPPUNIT_ASSERT(!torrent::sap_is_any(sin6_1)); CPPUNIT_ASSERT(!torrent::sap_is_any(sin_bc_5000)); CPPUNIT_ASSERT(!torrent::sap_is_any(sin_1_5000)); CPPUNIT_ASSERT(!torrent::sap_is_any(sin6_1_5000)); CPPUNIT_ASSERT(!torrent::sap_is_any(c_sin_bc)); CPPUNIT_ASSERT(!torrent::sap_is_any(c_sin_1)); CPPUNIT_ASSERT(!torrent::sap_is_any(c_sin6_1)); CPPUNIT_ASSERT(!torrent::sap_is_any(c_sin_bc_5000)); CPPUNIT_ASSERT(!torrent::sap_is_any(c_sin_1_5000)); CPPUNIT_ASSERT(!torrent::sap_is_any(c_sin6_1_5000)); } void test_socket_address::test_sa_is_broadcast() { TEST_DEFAULT_SA; CPPUNIT_ASSERT(torrent::sap_is_broadcast(sin_bc)); CPPUNIT_ASSERT(torrent::sap_is_broadcast(sin_bc_5000)); CPPUNIT_ASSERT(torrent::sap_is_broadcast(sin6_v4_bc)); CPPUNIT_ASSERT(torrent::sap_is_broadcast(sin6_v4_bc_5000)); CPPUNIT_ASSERT(!torrent::sap_is_broadcast(sin_any)); CPPUNIT_ASSERT(!torrent::sap_is_broadcast(sin_1)); CPPUNIT_ASSERT(!torrent::sap_is_broadcast(sin6_any)); CPPUNIT_ASSERT(!torrent::sap_is_broadcast(sin6_1)); CPPUNIT_ASSERT(!torrent::sap_is_broadcast(sin_any_5000)); CPPUNIT_ASSERT(!torrent::sap_is_broadcast(sin_1_5000)); CPPUNIT_ASSERT(!torrent::sap_is_broadcast(sin6_any_5000)); CPPUNIT_ASSERT(!torrent::sap_is_broadcast(sin6_1_5000)); CPPUNIT_ASSERT(!torrent::sap_is_broadcast(c_sin_any)); CPPUNIT_ASSERT(!torrent::sap_is_broadcast(c_sin_1)); CPPUNIT_ASSERT(!torrent::sap_is_broadcast(c_sin6_any)); CPPUNIT_ASSERT(!torrent::sap_is_broadcast(c_sin6_1)); CPPUNIT_ASSERT(!torrent::sap_is_broadcast(c_sin_any_5000)); CPPUNIT_ASSERT(!torrent::sap_is_broadcast(c_sin_1_5000)); CPPUNIT_ASSERT(!torrent::sap_is_broadcast(c_sin6_any_5000)); CPPUNIT_ASSERT(!torrent::sap_is_broadcast(c_sin6_1_5000)); } void test_socket_address::test_make() { torrent::sa_unique_ptr sa_unspec = torrent::sa_make_unspec(); CPPUNIT_ASSERT(sa_unspec != nullptr); CPPUNIT_ASSERT(sa_unspec->sa_family == AF_UNSPEC); torrent::sa_unique_ptr sa_inet = torrent::sa_make_inet(); CPPUNIT_ASSERT(sa_inet != nullptr); CPPUNIT_ASSERT(sa_inet->sa_family == AF_INET); sockaddr_in* sin_inet = reinterpret_cast(sa_inet.get()); CPPUNIT_ASSERT(sin_inet->sin_family == AF_INET); CPPUNIT_ASSERT(sin_inet->sin_port == 0); CPPUNIT_ASSERT(sin_inet->sin_addr.s_addr == in_addr().s_addr); torrent::sa_unique_ptr sa_inet6 = torrent::sa_make_inet6(); CPPUNIT_ASSERT(sa_inet6 != nullptr); CPPUNIT_ASSERT(sa_inet6->sa_family == AF_INET6); sockaddr_in6* sin6_inet6 = reinterpret_cast(sa_inet6.get()); CPPUNIT_ASSERT(sin6_inet6->sin6_family == AF_INET6); CPPUNIT_ASSERT(sin6_inet6->sin6_port == 0); CPPUNIT_ASSERT(sin6_inet6->sin6_flowinfo == 0); CPPUNIT_ASSERT(compare_sin6_addr(sin6_inet6->sin6_addr, (in6_addr{{}}))); CPPUNIT_ASSERT(sin6_inet6->sin6_scope_id == 0); torrent::sa_unique_ptr sa_unix = torrent::sa_make_unix(""); CPPUNIT_ASSERT(sa_unix != nullptr); CPPUNIT_ASSERT(sa_unix->sa_family == AF_UNIX); } void test_socket_address::test_sin_from_sa() { torrent::sa_unique_ptr sa_zero = wrap_ai_get_first_sa("0.0.0.0"); torrent::sin_unique_ptr sin_zero; CPPUNIT_ASSERT(sa_zero != nullptr); CPPUNIT_ASSERT_NO_THROW({ sin_zero = torrent::sin_from_sa(std::move(sa_zero)); }); CPPUNIT_ASSERT(sa_zero == nullptr); CPPUNIT_ASSERT(sin_zero != nullptr); CPPUNIT_ASSERT(sin_zero->sin_addr.s_addr == htonl(0x0)); torrent::sa_unique_ptr sa_inet = wrap_ai_get_first_sa("1.2.3.4"); torrent::sin_unique_ptr sin_inet; CPPUNIT_ASSERT(sa_inet != nullptr); CPPUNIT_ASSERT_NO_THROW({ sin_inet = torrent::sin_from_sa(std::move(sa_inet)); }); CPPUNIT_ASSERT(sa_inet == nullptr); CPPUNIT_ASSERT(sin_inet != nullptr); CPPUNIT_ASSERT(sin_inet->sin_addr.s_addr == htonl(0x01020304)); CPPUNIT_ASSERT_THROW(torrent::sin_from_sa(torrent::sa_unique_ptr()), torrent::internal_error); CPPUNIT_ASSERT_THROW(torrent::sin_from_sa(torrent::sa_make_unspec()), torrent::internal_error); CPPUNIT_ASSERT_THROW(torrent::sin_from_sa(torrent::sa_make_inet6()), torrent::internal_error); } void test_socket_address::test_sin6_from_sa() { torrent::sa_unique_ptr sa_zero = wrap_ai_get_first_sa("::"); torrent::sin6_unique_ptr sin6_zero; CPPUNIT_ASSERT(sa_zero != nullptr); CPPUNIT_ASSERT_NO_THROW({ sin6_zero = torrent::sin6_from_sa(std::move(sa_zero)); }); CPPUNIT_ASSERT(sa_zero == nullptr); CPPUNIT_ASSERT(sin6_zero != nullptr); CPPUNIT_ASSERT(sin6_zero->sin6_addr.s6_addr[0] == 0x0); CPPUNIT_ASSERT(sin6_zero->sin6_addr.s6_addr[1] == 0x0); CPPUNIT_ASSERT(sin6_zero->sin6_addr.s6_addr[15] == 0x0); torrent::sa_unique_ptr sa_inet6 = wrap_ai_get_first_sa("ff01::1"); torrent::sin6_unique_ptr sin6_inet6; CPPUNIT_ASSERT(sa_inet6 != nullptr); CPPUNIT_ASSERT_NO_THROW({ sin6_inet6 = torrent::sin6_from_sa(std::move(sa_inet6)); }); CPPUNIT_ASSERT(sa_inet6 == nullptr); CPPUNIT_ASSERT(sin6_inet6 != nullptr); CPPUNIT_ASSERT(sin6_inet6->sin6_addr.s6_addr[0] == 0xff); CPPUNIT_ASSERT(sin6_inet6->sin6_addr.s6_addr[1] == 0x01); CPPUNIT_ASSERT(sin6_inet6->sin6_addr.s6_addr[15] == 0x01); CPPUNIT_ASSERT_THROW(torrent::sin6_from_sa(torrent::sa_unique_ptr()), torrent::internal_error); CPPUNIT_ASSERT_THROW(torrent::sin6_from_sa(torrent::sa_make_unspec()), torrent::internal_error); CPPUNIT_ASSERT_THROW(torrent::sin6_from_sa(torrent::sa_make_inet()), torrent::internal_error); } void test_socket_address::test_sa_equal() { TEST_DEFAULT_SA; CPPUNIT_ASSERT(torrent::sap_equal(torrent::sa_make_unspec(), torrent::sa_make_unspec())); CPPUNIT_ASSERT(torrent::sap_equal(torrent::sa_make_inet(), torrent::sa_make_inet())); CPPUNIT_ASSERT(torrent::sap_equal(torrent::sa_make_inet6(), torrent::sa_make_inet6())); CPPUNIT_ASSERT(!torrent::sap_equal(torrent::sa_make_unspec(), torrent::sa_make_inet())); CPPUNIT_ASSERT(!torrent::sap_equal(torrent::sa_make_unspec(), torrent::sa_make_inet6())); CPPUNIT_ASSERT(!torrent::sap_equal(torrent::sa_make_inet(), torrent::sa_make_inet6())); CPPUNIT_ASSERT(!torrent::sap_equal(torrent::sa_make_inet6(), torrent::sa_make_inet())); CPPUNIT_ASSERT(torrent::sap_equal(sin_1, sin_1)); CPPUNIT_ASSERT(torrent::sap_equal(sin_1, c_sin_1)); CPPUNIT_ASSERT(torrent::sap_equal(c_sin_1, sin_1)); CPPUNIT_ASSERT(torrent::sap_equal(c_sin_1, c_sin_1)); CPPUNIT_ASSERT(!torrent::sap_equal(sin_1, sin_2)); CPPUNIT_ASSERT(!torrent::sap_equal(sin_1, c_sin_2)); CPPUNIT_ASSERT(!torrent::sap_equal(c_sin_1, sin_2)); CPPUNIT_ASSERT(!torrent::sap_equal(c_sin_1, c_sin_2)); CPPUNIT_ASSERT(torrent::sap_equal(sin6_1, sin6_1)); CPPUNIT_ASSERT(torrent::sap_equal(sin6_1, c_sin6_1)); CPPUNIT_ASSERT(torrent::sap_equal(c_sin6_1, sin6_1)); CPPUNIT_ASSERT(torrent::sap_equal(c_sin6_1, c_sin6_1)); CPPUNIT_ASSERT(!torrent::sap_equal(sin6_1, sin6_2)); CPPUNIT_ASSERT(!torrent::sap_equal(sin6_1, c_sin6_2)); CPPUNIT_ASSERT(!torrent::sap_equal(c_sin6_1, sin6_2)); CPPUNIT_ASSERT(!torrent::sap_equal(c_sin6_1, c_sin6_2)); CPPUNIT_ASSERT(torrent::sap_equal(sin_1_5000, sin_1_5000)); CPPUNIT_ASSERT(torrent::sap_equal(sin6_1_5000, sin6_1_5000)); CPPUNIT_ASSERT(!torrent::sap_equal(sin_1_5000, sin_1_5100)); CPPUNIT_ASSERT(!torrent::sap_equal(sin6_1_5000, sin6_1_5100)); CPPUNIT_ASSERT(!torrent::sap_equal(sin_1_5000, sin_2_5000)); CPPUNIT_ASSERT(!torrent::sap_equal(sin6_1_5000, sin6_2_5000)); CPPUNIT_ASSERT(!torrent::sap_equal(sin_1_5000, sin_2_5100)); CPPUNIT_ASSERT(!torrent::sap_equal(sin6_1_5000, sin6_2_5100)); CPPUNIT_ASSERT_THROW(torrent::sap_equal(torrent::sa_make_unix(""), torrent::sa_make_unix("")), torrent::internal_error); CPPUNIT_ASSERT_THROW(torrent::sap_equal(torrent::sa_make_unix(""), sin6_1), torrent::internal_error); CPPUNIT_ASSERT_THROW(torrent::sap_equal(sin6_1, torrent::sa_make_unix("")), torrent::internal_error); } void test_socket_address::test_sa_equal_addr() { TEST_DEFAULT_SA; CPPUNIT_ASSERT(torrent::sap_equal_addr(torrent::sa_make_unspec(), torrent::sa_make_unspec())); CPPUNIT_ASSERT(torrent::sap_equal_addr(torrent::sa_make_inet(), torrent::sa_make_inet())); CPPUNIT_ASSERT(torrent::sap_equal_addr(torrent::sa_make_inet6(), torrent::sa_make_inet6())); CPPUNIT_ASSERT(!torrent::sap_equal_addr(torrent::sa_make_unspec(), torrent::sa_make_inet())); CPPUNIT_ASSERT(!torrent::sap_equal_addr(torrent::sa_make_unspec(), torrent::sa_make_inet6())); CPPUNIT_ASSERT(!torrent::sap_equal_addr(torrent::sa_make_inet(), torrent::sa_make_inet6())); CPPUNIT_ASSERT(!torrent::sap_equal_addr(torrent::sa_make_inet6(), torrent::sa_make_inet())); CPPUNIT_ASSERT(torrent::sap_equal_addr(sin_1, sin_1)); CPPUNIT_ASSERT(torrent::sap_equal_addr(sin_1, c_sin_1)); CPPUNIT_ASSERT(torrent::sap_equal_addr(c_sin_1, sin_1)); CPPUNIT_ASSERT(torrent::sap_equal_addr(c_sin_1, c_sin_1)); CPPUNIT_ASSERT(!torrent::sap_equal_addr(sin_1, sin_2)); CPPUNIT_ASSERT(!torrent::sap_equal_addr(sin_1, c_sin_2)); CPPUNIT_ASSERT(!torrent::sap_equal_addr(c_sin_1, sin_2)); CPPUNIT_ASSERT(!torrent::sap_equal_addr(c_sin_1, c_sin_2)); CPPUNIT_ASSERT(torrent::sap_equal_addr(sin6_1, sin6_1)); CPPUNIT_ASSERT(torrent::sap_equal_addr(sin6_1, c_sin6_1)); CPPUNIT_ASSERT(torrent::sap_equal_addr(c_sin6_1, sin6_1)); CPPUNIT_ASSERT(torrent::sap_equal_addr(c_sin6_1, c_sin6_1)); CPPUNIT_ASSERT(!torrent::sap_equal_addr(sin6_1, sin6_2)); CPPUNIT_ASSERT(!torrent::sap_equal_addr(sin6_1, c_sin6_2)); CPPUNIT_ASSERT(!torrent::sap_equal_addr(c_sin6_1, sin6_2)); CPPUNIT_ASSERT(!torrent::sap_equal_addr(c_sin6_1, c_sin6_2)); CPPUNIT_ASSERT(torrent::sap_equal_addr(sin_1_5000, sin_1_5000)); CPPUNIT_ASSERT(torrent::sap_equal_addr(sin6_1_5000, sin6_1_5000)); CPPUNIT_ASSERT(torrent::sap_equal_addr(sin_1_5000, sin_1_5100)); CPPUNIT_ASSERT(torrent::sap_equal_addr(sin6_1_5000, sin6_1_5100)); CPPUNIT_ASSERT(!torrent::sap_equal_addr(sin_1_5000, sin_2_5000)); CPPUNIT_ASSERT(!torrent::sap_equal_addr(sin6_1_5000, sin6_2_5000)); CPPUNIT_ASSERT(!torrent::sap_equal_addr(sin_1_5000, sin_2_5100)); CPPUNIT_ASSERT(!torrent::sap_equal_addr(sin6_1_5000, sin6_2_5100)); CPPUNIT_ASSERT_THROW(torrent::sap_equal_addr(torrent::sa_make_unix(""), torrent::sa_make_unix("")), torrent::internal_error); CPPUNIT_ASSERT_THROW(torrent::sap_equal_addr(torrent::sa_make_unix(""), sin6_1), torrent::internal_error); CPPUNIT_ASSERT_THROW(torrent::sap_equal_addr(sin6_1, torrent::sa_make_unix("")), torrent::internal_error); } void test_socket_address::test_sa_copy() { TEST_DEFAULT_SA; CPPUNIT_ASSERT(torrent::sap_equal(torrent::sap_copy(torrent::sa_make_unspec()), torrent::sa_make_unspec())); CPPUNIT_ASSERT(torrent::sap_equal(torrent::sap_copy(torrent::sa_make_inet()), sin_any)); CPPUNIT_ASSERT(torrent::sap_equal(torrent::sap_copy(torrent::sa_make_inet6()), sin6_any)); CPPUNIT_ASSERT(torrent::sap_copy(sin_1).get() != sin_1.get()); CPPUNIT_ASSERT(torrent::sap_copy(c_sin_1).get() != c_sin_1.get()); CPPUNIT_ASSERT(torrent::sap_copy(sin6_1).get() != sin6_1.get()); CPPUNIT_ASSERT(torrent::sap_copy(c_sin6_1).get() != c_sin6_1.get()); CPPUNIT_ASSERT(torrent::sap_copy(sin_1_5000).get() != sin_1_5000.get()); CPPUNIT_ASSERT(torrent::sap_copy(sin6_1_5000).get() != sin6_1_5000.get()); CPPUNIT_ASSERT(torrent::sap_equal(torrent::sap_copy(sin_1), sin_1)); CPPUNIT_ASSERT(torrent::sap_equal(torrent::sap_copy(sin_1), c_sin_1)); CPPUNIT_ASSERT(torrent::sap_equal(torrent::sap_copy(c_sin_1), sin_1)); CPPUNIT_ASSERT(torrent::sap_equal(torrent::sap_copy(c_sin_1), c_sin_1)); CPPUNIT_ASSERT(torrent::sap_equal(torrent::sap_copy(sin6_1), sin6_1)); CPPUNIT_ASSERT(torrent::sap_equal(torrent::sap_copy(sin6_1), c_sin6_1)); CPPUNIT_ASSERT(torrent::sap_equal(torrent::sap_copy(c_sin6_1), sin6_1)); CPPUNIT_ASSERT(torrent::sap_equal(torrent::sap_copy(c_sin6_1), c_sin6_1)); CPPUNIT_ASSERT(torrent::sap_equal(torrent::sap_copy(sin_1_5000), sin_1_5000)); CPPUNIT_ASSERT(torrent::sap_equal(torrent::sap_copy(sin6_1_5000), sin6_1_5000)); auto sin6_flags = torrent::sap_copy(sin6_1_5000); reinterpret_cast(sin6_flags.get())->sin6_flowinfo = 0x12345678; reinterpret_cast(sin6_flags.get())->sin6_scope_id = 0x12345678; // TODO: Need 'strict' equal test. CPPUNIT_ASSERT(torrent::sap_equal(torrent::sap_copy(sin6_flags), sin6_flags)); CPPUNIT_ASSERT_THROW(torrent::sap_copy(torrent::sa_unique_ptr()), torrent::internal_error); CPPUNIT_ASSERT_THROW(torrent::sap_copy(torrent::c_sa_unique_ptr()), torrent::internal_error); } void test_socket_address::test_sa_copy_addr() { TEST_DEFAULT_SA; CPPUNIT_ASSERT(torrent::sap_equal(torrent::sap_copy_addr(torrent::sa_make_unspec()), torrent::sa_make_unspec())); CPPUNIT_ASSERT(torrent::sap_equal(torrent::sap_copy_addr(torrent::sa_make_inet()), sin_any)); CPPUNIT_ASSERT(torrent::sap_equal(torrent::sap_copy_addr(torrent::sa_make_inet6()), sin6_any)); CPPUNIT_ASSERT(torrent::sap_equal(torrent::sap_copy_addr(torrent::sa_make_unspec(), 5000), torrent::sa_make_unspec())); CPPUNIT_ASSERT(torrent::sap_equal(torrent::sap_copy_addr(torrent::sa_make_inet(), 5000), sin_any_5000)); CPPUNIT_ASSERT(torrent::sap_equal(torrent::sap_copy_addr(torrent::sa_make_inet6(), 5000), sin6_any_5000)); CPPUNIT_ASSERT(torrent::sap_copy_addr(sin_1).get() != sin_1.get()); CPPUNIT_ASSERT(torrent::sap_copy_addr(c_sin_1).get() != c_sin_1.get()); CPPUNIT_ASSERT(torrent::sap_copy_addr(sin6_1).get() != sin6_1.get()); CPPUNIT_ASSERT(torrent::sap_copy_addr(c_sin6_1).get() != c_sin6_1.get()); CPPUNIT_ASSERT(torrent::sap_copy_addr(sin_1_5000).get() != sin_1_5000.get()); CPPUNIT_ASSERT(torrent::sap_copy_addr(sin6_1_5000).get() != sin6_1_5000.get()); CPPUNIT_ASSERT(torrent::sap_equal(torrent::sap_copy_addr(sin_1), sin_1)); CPPUNIT_ASSERT(torrent::sap_equal(torrent::sap_copy_addr(sin_1), c_sin_1)); CPPUNIT_ASSERT(torrent::sap_equal(torrent::sap_copy_addr(c_sin_1), sin_1)); CPPUNIT_ASSERT(torrent::sap_equal(torrent::sap_copy_addr(c_sin_1), c_sin_1)); CPPUNIT_ASSERT(torrent::sap_equal(torrent::sap_copy_addr(sin_1, 5000), sin_1_5000)); CPPUNIT_ASSERT(torrent::sap_equal(torrent::sap_copy_addr(sin_1, 5000), c_sin_1_5000)); CPPUNIT_ASSERT(torrent::sap_equal(torrent::sap_copy_addr(c_sin_1, 5000), sin_1_5000)); CPPUNIT_ASSERT(torrent::sap_equal(torrent::sap_copy_addr(c_sin_1, 5000), c_sin_1_5000)); CPPUNIT_ASSERT(torrent::sap_equal(torrent::sap_copy_addr(sin6_1), sin6_1)); CPPUNIT_ASSERT(torrent::sap_equal(torrent::sap_copy_addr(sin6_1), c_sin6_1)); CPPUNIT_ASSERT(torrent::sap_equal(torrent::sap_copy_addr(c_sin6_1), sin6_1)); CPPUNIT_ASSERT(torrent::sap_equal(torrent::sap_copy_addr(c_sin6_1), c_sin6_1)); CPPUNIT_ASSERT(torrent::sap_equal(torrent::sap_copy_addr(sin6_1, 5000), sin6_1_5000)); CPPUNIT_ASSERT(torrent::sap_equal(torrent::sap_copy_addr(sin6_1, 5000), c_sin6_1_5000)); CPPUNIT_ASSERT(torrent::sap_equal(torrent::sap_copy_addr(c_sin6_1, 5000), sin6_1_5000)); CPPUNIT_ASSERT(torrent::sap_equal(torrent::sap_copy_addr(c_sin6_1, 5000), c_sin6_1_5000)); CPPUNIT_ASSERT(torrent::sap_equal(torrent::sap_copy_addr(sin_1_5000), sin_1)); CPPUNIT_ASSERT(torrent::sap_equal(torrent::sap_copy_addr(sin6_1_5000), sin6_1)); CPPUNIT_ASSERT(torrent::sap_equal(torrent::sap_copy_addr(sin_1_5000, 5100), sin_1_5100)); CPPUNIT_ASSERT(torrent::sap_equal(torrent::sap_copy_addr(sin6_1_5000, 5100), sin6_1_5100)); auto sin6_flags = wrap_ai_get_first_sa("ff01::1", "5555"); reinterpret_cast(sin6_flags.get())->sin6_flowinfo = 0x12345678; reinterpret_cast(sin6_flags.get())->sin6_scope_id = 0x12345678; CPPUNIT_ASSERT(torrent::sap_equal(torrent::sap_copy_addr(sin6_flags), sin6_1)); CPPUNIT_ASSERT_THROW(torrent::sap_copy_addr(torrent::sa_unique_ptr()), torrent::internal_error); CPPUNIT_ASSERT_THROW(torrent::sap_copy_addr(torrent::c_sa_unique_ptr()), torrent::internal_error); CPPUNIT_ASSERT_THROW(torrent::sap_copy_addr(torrent::sa_unique_ptr(), 5000), torrent::internal_error); CPPUNIT_ASSERT_THROW(torrent::sap_copy_addr(torrent::c_sa_unique_ptr(), 5000), torrent::internal_error); } void test_socket_address::test_sa_from_v4mapped() { TEST_DEFAULT_SA; CPPUNIT_ASSERT(torrent::sap_equal_addr(torrent::sap_from_v4mapped(sin6_v4_any), sin_any)); CPPUNIT_ASSERT(torrent::sap_is_port_any(torrent::sap_from_v4mapped(sin6_v4_any))); CPPUNIT_ASSERT(torrent::sap_equal_addr(torrent::sap_from_v4mapped(sin6_v4_1), sin_1)); CPPUNIT_ASSERT(torrent::sap_is_port_any(torrent::sap_from_v4mapped(sin6_v4_1))); CPPUNIT_ASSERT(torrent::sap_equal_addr(torrent::sap_from_v4mapped(sin6_v4_bc), sin_bc)); CPPUNIT_ASSERT(torrent::sap_is_port_any(torrent::sap_from_v4mapped(sin6_v4_bc))); CPPUNIT_ASSERT_THROW(torrent::sap_from_v4mapped(torrent::sa_make_unspec()), torrent::internal_error); CPPUNIT_ASSERT_THROW(torrent::sap_from_v4mapped(torrent::sa_make_inet()), torrent::internal_error); CPPUNIT_ASSERT_THROW(torrent::sap_from_v4mapped(torrent::sa_make_unix("")), torrent::internal_error); CPPUNIT_ASSERT_THROW(torrent::sap_from_v4mapped(sin_any), torrent::internal_error); CPPUNIT_ASSERT_THROW(torrent::sap_from_v4mapped(sin_bc), torrent::internal_error); CPPUNIT_ASSERT_THROW(torrent::sap_from_v4mapped(sin_1), torrent::internal_error); } void test_socket_address::test_sa_to_v4mapped() { TEST_DEFAULT_SA; CPPUNIT_ASSERT(torrent::sap_equal_addr(torrent::sap_to_v4mapped(sin_any), sin6_v4_any)); CPPUNIT_ASSERT(torrent::sap_is_v4mapped(torrent::sap_to_v4mapped(sin_any))); CPPUNIT_ASSERT(torrent::sap_is_port_any(torrent::sap_to_v4mapped(sin_any))); CPPUNIT_ASSERT(torrent::sap_equal_addr(torrent::sap_to_v4mapped(sin_bc), sin6_v4_bc)); CPPUNIT_ASSERT(torrent::sap_is_v4mapped(torrent::sap_to_v4mapped(sin_bc))); CPPUNIT_ASSERT(torrent::sap_is_port_any(torrent::sap_to_v4mapped(sin_bc))); CPPUNIT_ASSERT(torrent::sap_equal_addr(torrent::sap_to_v4mapped(sin_1), sin6_v4_1)); CPPUNIT_ASSERT(torrent::sap_is_v4mapped(torrent::sap_to_v4mapped(sin_1))); CPPUNIT_ASSERT(torrent::sap_is_port_any(torrent::sap_to_v4mapped(sin_1))); CPPUNIT_ASSERT_THROW(torrent::sap_to_v4mapped(torrent::sa_make_unspec()), torrent::internal_error); CPPUNIT_ASSERT_THROW(torrent::sap_to_v4mapped(torrent::sa_make_inet6()), torrent::internal_error); CPPUNIT_ASSERT_THROW(torrent::sap_to_v4mapped(torrent::sa_make_unix("")), torrent::internal_error); CPPUNIT_ASSERT_THROW(torrent::sap_to_v4mapped(sin6_any), torrent::internal_error); CPPUNIT_ASSERT_THROW(torrent::sap_to_v4mapped(sin6_1), torrent::internal_error); CPPUNIT_ASSERT_THROW(torrent::sap_to_v4mapped(sin6_v4_any), torrent::internal_error); CPPUNIT_ASSERT_THROW(torrent::sap_to_v4mapped(sin6_v4_bc), torrent::internal_error); CPPUNIT_ASSERT_THROW(torrent::sap_to_v4mapped(sin6_v4_1), torrent::internal_error); } libtorrent-0.16.11/test/torrent/net/test_address_info.cc0000644000000000000000000001071515175073411016753 #include "config.h" #include "test_address_info.h" #include "helpers/network.h" #include "torrent/net/address_info.h" #include "torrent/net/socket_address.h" CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(test_address_info, "torrent/net"); void test_address_info::test_basic() { CPPUNIT_ASSERT(test_valid_ai_ref (std::bind(torrent::ai_get_addrinfo, "0.0.0.0", nullptr, nullptr, std::placeholders::_1))); CPPUNIT_ASSERT(test_valid_ai_ref(std::bind(torrent::ai_get_addrinfo, "::", nullptr, nullptr, std::placeholders::_1))); CPPUNIT_ASSERT(test_valid_ai_ref (std::bind(torrent::ai_get_addrinfo, "1.1.1.1", nullptr, nullptr, std::placeholders::_1))); CPPUNIT_ASSERT(test_valid_ai_ref(std::bind(torrent::ai_get_addrinfo, "ff01::1", nullptr, nullptr, std::placeholders::_1))); CPPUNIT_ASSERT(test_valid_ai_ref(std::bind(torrent::ai_get_addrinfo, "2001:0db8:85a3:0000:0000:8a2e:0370:7334", nullptr, nullptr, std::placeholders::_1))); CPPUNIT_ASSERT(test_valid_ai_ref (std::bind(torrent::ai_get_addrinfo, "1.1.1.1", "22123", nullptr, std::placeholders::_1), 22123)); CPPUNIT_ASSERT(test_valid_ai_ref(std::bind(torrent::ai_get_addrinfo, "2001:db8:a::", "22123", nullptr, std::placeholders::_1), 22123)); CPPUNIT_ASSERT(test_valid_ai_ref (std::bind(torrent::ai_get_addrinfo, "localhost", nullptr, nullptr, std::placeholders::_1))); // Glibc 2.28+ returns EAI_NONAME for invalid IPv4 addresses, which likely should only happen when // using AI_NUMERICHOST. CPPUNIT_ASSERT(test_valid_ai_ref_err(std::bind(torrent::ai_get_addrinfo, "1.1.1.300", nullptr, nullptr, std::placeholders::_1), EAI_NONAME) || test_valid_ai_ref_err(std::bind(torrent::ai_get_addrinfo, "1.1.1.300", nullptr, nullptr, std::placeholders::_1), EAI_NODATA) || test_valid_ai_ref_err(std::bind(torrent::ai_get_addrinfo, "1.1.1.300", nullptr, nullptr, std::placeholders::_1), EAI_AGAIN)); CPPUNIT_ASSERT(test_valid_ai_ref_err(std::bind(torrent::ai_get_addrinfo, "2001:db8:a::22123", nullptr, nullptr, std::placeholders::_1), EAI_NONAME) || test_valid_ai_ref_err(std::bind(torrent::ai_get_addrinfo, "2001:db8:a::22123", nullptr, nullptr, std::placeholders::_1), EAI_NODATA) || test_valid_ai_ref_err(std::bind(torrent::ai_get_addrinfo, "2001:db8:a::22123", nullptr, nullptr, std::placeholders::_1), EAI_AGAIN) || test_valid_ai_ref_err(std::bind(torrent::ai_get_addrinfo, "2001:db8:a::22123", nullptr, nullptr, std::placeholders::_1), EAI_ADDRFAMILY) || test_valid_ai_ref_err(std::bind(torrent::ai_get_addrinfo, "2001:db8:a::22123", nullptr, nullptr, std::placeholders::_1), EAI_FAIL)); } void test_address_info::test_numericserv() { CPPUNIT_ASSERT(test_valid_ai_ref (std::bind(torrent::ai_get_addrinfo, "1.1.1.1", nullptr, torrent::ai_make_hint(AI_NUMERICHOST, 0, 0).get(), std::placeholders::_1))); CPPUNIT_ASSERT(test_valid_ai_ref_err(std::bind(torrent::ai_get_addrinfo, "localhost", nullptr, torrent::ai_make_hint(AI_NUMERICHOST, 0, 0).get(), std::placeholders::_1), EAI_NONAME)); } void test_address_info::test_helpers() { torrent::sin_unique_ptr sin_zero = torrent::sin_from_sa(wrap_ai_get_first_sa("0.0.0.0")); CPPUNIT_ASSERT(sin_zero != nullptr); CPPUNIT_ASSERT(sin_zero->sin_family == AF_INET); CPPUNIT_ASSERT(sin_zero->sin_port == 0); CPPUNIT_ASSERT(sin_zero->sin_addr.s_addr == in_addr().s_addr); torrent::sin_unique_ptr sin_1 = torrent::sin_from_sa(wrap_ai_get_first_sa("1.2.3.4")); CPPUNIT_ASSERT(sin_1 != nullptr); CPPUNIT_ASSERT(sin_1->sin_family == AF_INET); CPPUNIT_ASSERT(sin_1->sin_port == 0); CPPUNIT_ASSERT(sin_1->sin_addr.s_addr == htonl(0x01020304)); torrent::sin6_unique_ptr sin6_zero = torrent::sin6_from_sa(wrap_ai_get_first_sa("::")); CPPUNIT_ASSERT(sin6_zero != nullptr); CPPUNIT_ASSERT(sin6_zero->sin6_family == AF_INET6); CPPUNIT_ASSERT(sin6_zero->sin6_port == 0); CPPUNIT_ASSERT(compare_sin6_addr(sin6_zero->sin6_addr, in6_addr{})); torrent::sin6_unique_ptr sin6_1 = torrent::sin6_from_sa(wrap_ai_get_first_sa("ff01::1")); CPPUNIT_ASSERT(sin6_1 != nullptr); CPPUNIT_ASSERT(sin6_1->sin6_family == AF_INET6); CPPUNIT_ASSERT(sin6_1->sin6_port == 0); CPPUNIT_ASSERT(compare_sin6_addr(sin6_1->sin6_addr, in6_addr{0xff, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1})); CPPUNIT_ASSERT(!compare_sin6_addr(sin6_1->sin6_addr, in6_addr{0xff, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2})); } libtorrent-0.16.11/test/torrent/net/test_fd.cc0000644000000000000000000000351215175073411014701 #include "config.h" #include "test_fd.h" #include CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(test_fd, "torrent/net"); void test_fd::test_valid_flags() { CPPUNIT_ASSERT(torrent::fd_valid_flags(torrent::fd_flag_stream)); CPPUNIT_ASSERT(torrent::fd_valid_flags(torrent::fd_flag_datagram)); CPPUNIT_ASSERT(!torrent::fd_valid_flags(torrent::fd_flag_stream | torrent::fd_flag_datagram)); CPPUNIT_ASSERT(torrent::fd_valid_flags(torrent::fd_flag_stream | torrent::fd_flag_nonblock)); CPPUNIT_ASSERT(torrent::fd_valid_flags(torrent::fd_flag_stream | torrent::fd_flag_reuse_address)); CPPUNIT_ASSERT(torrent::fd_valid_flags(torrent::fd_flag_stream | torrent::fd_flag_v4only)); CPPUNIT_ASSERT(torrent::fd_valid_flags(torrent::fd_flag_stream | torrent::fd_flag_v6only)); CPPUNIT_ASSERT(torrent::fd_valid_flags(torrent::fd_flag_datagram | torrent::fd_flag_nonblock)); CPPUNIT_ASSERT(torrent::fd_valid_flags(torrent::fd_flag_datagram | torrent::fd_flag_reuse_address)); CPPUNIT_ASSERT(torrent::fd_valid_flags(torrent::fd_flag_datagram | torrent::fd_flag_v4only)); CPPUNIT_ASSERT(torrent::fd_valid_flags(torrent::fd_flag_datagram | torrent::fd_flag_v6only)); CPPUNIT_ASSERT(!torrent::fd_valid_flags(torrent::fd_flag_v4only | torrent::fd_flag_v6only)); CPPUNIT_ASSERT(!torrent::fd_valid_flags(torrent::fd_flag_stream | torrent::fd_flag_v4only | torrent::fd_flag_v6only)); CPPUNIT_ASSERT(!torrent::fd_valid_flags(torrent::fd_flag_datagram | torrent::fd_flag_v4only | torrent::fd_flag_v6only)); CPPUNIT_ASSERT(!torrent::fd_valid_flags(torrent::fd_flags())); CPPUNIT_ASSERT(!torrent::fd_valid_flags(torrent::fd_flags(~torrent::fd_flag_all))); CPPUNIT_ASSERT(!torrent::fd_valid_flags(torrent::fd_flags(torrent::fd_flag_stream | ~torrent::fd_flag_all))); CPPUNIT_ASSERT(!torrent::fd_valid_flags(torrent::fd_flags(0x3245132))); } libtorrent-0.16.11/test/torrent/net/test_fd.h0000644000000000000000000000033315175073411014541 #include "helpers/test_fixture.h" class test_fd : public test_fixture { CPPUNIT_TEST_SUITE(test_fd); CPPUNIT_TEST(test_valid_flags); CPPUNIT_TEST_SUITE_END(); public: void test_valid_flags(); }; libtorrent-0.16.11/test/torrent/net/test_socket_address.h0000644000000000000000000000154415175073411017152 #include class test_socket_address : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(test_socket_address); CPPUNIT_TEST(test_sa_is_any); CPPUNIT_TEST(test_sa_is_broadcast); CPPUNIT_TEST(test_make); CPPUNIT_TEST(test_sin_from_sa); CPPUNIT_TEST(test_sin6_from_sa); CPPUNIT_TEST(test_sa_equal); CPPUNIT_TEST(test_sa_equal_addr); CPPUNIT_TEST(test_sa_copy); CPPUNIT_TEST(test_sa_copy_addr); CPPUNIT_TEST(test_sa_from_v4mapped); CPPUNIT_TEST(test_sa_to_v4mapped); CPPUNIT_TEST_SUITE_END(); public: void test_sa_is_any(); void test_sa_is_broadcast(); void test_make(); void test_sin_from_sa(); void test_sin6_from_sa(); void test_sa_equal(); void test_sa_equal_addr(); void test_sa_copy(); void test_sa_copy_addr(); void test_sa_from_v4mapped(); void test_sa_to_v4mapped(); }; libtorrent-0.16.11/test/torrent/net/test_address_info.h0000644000000000000000000000053415175073411016613 #include class test_address_info : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(test_address_info); CPPUNIT_TEST(test_basic); CPPUNIT_TEST(test_numericserv); CPPUNIT_TEST(test_helpers); CPPUNIT_TEST_SUITE_END(); public: void test_basic(); void test_numericserv(); void test_helpers(); }; libtorrent-0.16.11/test/torrent/object_stream_test.cc0000644000000000000000000001603015175073411016342 #include "config.h" #include #include #include #include #include "object_stream_test.h" #include "object_test_utils.h" CPPUNIT_TEST_SUITE_REGISTRATION(ObjectStreamTest); namespace { const auto ordered_bencode = "d1:ei0e4:ipv44:XXXX4:ipv616:XXXXXXXXXXXXXXXX1:md11:upload_onlyi3e12:ut_holepunchi4e11:ut_metadatai2e6:ut_pexi1ee13:metadata_sizei15408e1:pi16033e4:reqqi255e1:v15:uuTorrent 1.8.46:yourip4:XXXXe"; const auto unordered_bencode = "d1:ei0e1:md11:upload_onlyi3e12:ut_holepunchi4e11:ut_metadatai2e6:ut_pexi1ee4:ipv44:XXXX4:ipv616:XXXXXXXXXXXXXXXX13:metadata_sizei15408e1:pi16033e4:reqqi255e1:v15:uuTorrent 1.8.46:yourip4:XXXXe"; const auto string_bencode = "32:aaaaaaaabbbbbbbbccccccccdddddddd"; // Dummy function that invalidates the buffer once called. torrent::object_buffer_t object_write_to_invalidate(void* data, torrent::object_buffer_t buffer) { return torrent::object_buffer_t(buffer.second, buffer.second); } bool object_write_bencode(const torrent::Object& obj, const char* original) { try { char buffer[1025]; char* last = torrent::object_write_bencode(buffer, buffer + 1024, &obj).first; return std::strncmp(buffer, original, std::distance(buffer, last)) == 0; } catch (const torrent::bencode_error&) { return false; } } bool object_stream_read_skip(const char* input) { try { torrent::Object tmp; return torrent::object_read_bencode_c(input, input + strlen(input), &tmp) == input + strlen(input) && torrent::object_read_bencode_skip_c(input, input + strlen(input)) == input + strlen(input); } catch (const torrent::bencode_error&) { return false; } } bool object_stream_read_skip_catch(const char* input) { try { torrent::Object tmp; torrent::object_read_bencode_c(input, input + strlen(input), &tmp); std::cout << "(N)"; return false; } catch (const torrent::bencode_error&) { } try { torrent::object_read_bencode_skip_c(input, input + strlen(input)); std::cout << "(S)"; return false; } catch (const torrent::bencode_error&) { return true; } } } // namespace void ObjectStreamTest::testInputOrdered() { torrent::Object orderedObj = create_bencode(ordered_bencode); torrent::Object unorderedObj = create_bencode(unordered_bencode); CPPUNIT_ASSERT(!(orderedObj.flags() & torrent::Object::flag_unordered)); CPPUNIT_ASSERT(unorderedObj.flags() & torrent::Object::flag_unordered); } void ObjectStreamTest::testInputNullKey() { torrent::Object obj = create_bencode("d0:i1e5:filesi2ee"); CPPUNIT_ASSERT(!(obj.flags() & torrent::Object::flag_unordered)); } void ObjectStreamTest::testOutputMask() { torrent::Object normalObj = create_bencode("d1:ai1e1:bi2e1:ci3ee"); CPPUNIT_ASSERT(compare_bencode(normalObj, "d1:ai1e1:bi2e1:ci3ee")); normalObj.get_key("b").set_flags(torrent::Object::flag_session_data); normalObj.get_key("c").set_flags(torrent::Object::flag_static_data); CPPUNIT_ASSERT(compare_bencode(normalObj, "d1:ai1e1:ci3ee", torrent::Object::flag_session_data)); } // // Testing for bugs in bencode write. // void ObjectStreamTest::testBuffer() { char raw_buffer[16]; torrent::object_buffer_t buffer(raw_buffer, raw_buffer + 16); torrent::Object obj = create_bencode(string_bencode); object_write_bencode_c(&object_write_to_invalidate, NULL, buffer, &obj); } static const char* single_level_bencode = "d1:ai1e1:bi2e1:cl1:ai1e1:bi2eee"; void ObjectStreamTest::testReadBencodeC() { torrent::Object orderedObj = create_bencode_c(ordered_bencode); torrent::Object unorderedObj = create_bencode_c(unordered_bencode); CPPUNIT_ASSERT(!(orderedObj.flags() & torrent::Object::flag_unordered)); CPPUNIT_ASSERT(unorderedObj.flags() & torrent::Object::flag_unordered); CPPUNIT_ASSERT(compare_bencode(orderedObj, ordered_bencode)); // torrent::Object single_level = create_bencode_c(single_level_bencode); torrent::Object single_level = create_bencode_c(single_level_bencode); CPPUNIT_ASSERT(compare_bencode(single_level, single_level_bencode)); } void ObjectStreamTest::test_read_skip() { CPPUNIT_ASSERT(object_stream_read_skip("i0e")); CPPUNIT_ASSERT(object_stream_read_skip("i9999e")); CPPUNIT_ASSERT(object_stream_read_skip("i-1e")); CPPUNIT_ASSERT(object_stream_read_skip("i-9999e")); CPPUNIT_ASSERT(object_stream_read_skip("0:")); CPPUNIT_ASSERT(object_stream_read_skip("4:test")); CPPUNIT_ASSERT(object_stream_read_skip("le")); CPPUNIT_ASSERT(object_stream_read_skip("li1ee")); CPPUNIT_ASSERT(object_stream_read_skip("llee")); CPPUNIT_ASSERT(object_stream_read_skip("ll1:a1:bel1:c1:dee")); CPPUNIT_ASSERT(object_stream_read_skip("de")); CPPUNIT_ASSERT(object_stream_read_skip("d1:ai1e1:b1:xe")); CPPUNIT_ASSERT(object_stream_read_skip("d1:ali1eee")); CPPUNIT_ASSERT(object_stream_read_skip("d1:ad1:bi1eee")); CPPUNIT_ASSERT(object_stream_read_skip("d1:md6:ut_pexi0eee")); } void ObjectStreamTest::test_read_skip_invalid() { CPPUNIT_ASSERT(object_stream_read_skip_catch("")); CPPUNIT_ASSERT(object_stream_read_skip_catch("i")); CPPUNIT_ASSERT(object_stream_read_skip_catch("1")); CPPUNIT_ASSERT(object_stream_read_skip_catch("d")); CPPUNIT_ASSERT(object_stream_read_skip_catch("i-0e")); CPPUNIT_ASSERT(object_stream_read_skip_catch("i--1e")); CPPUNIT_ASSERT(object_stream_read_skip_catch("-1")); CPPUNIT_ASSERT(object_stream_read_skip_catch("-1a")); CPPUNIT_ASSERT(object_stream_read_skip_catch("llllllll" "llllllll" "llllllll" "llllllll" "llllllll" "llllllll" "llllllll" "llllllll" "llllllll" "llllllll" "llllllll" "llllllll" "llllllll" "llllllll" "llllllll" "llllllll")); } void ObjectStreamTest::test_write() { torrent::Object obj; CPPUNIT_ASSERT(object_write_bencode(torrent::Object(), "")); CPPUNIT_ASSERT(object_write_bencode(torrent::Object((int64_t)0), "i0e")); CPPUNIT_ASSERT(object_write_bencode(torrent::Object((int64_t)1), "i1e")); CPPUNIT_ASSERT(object_write_bencode(torrent::Object((int64_t)-1), "i-1e")); CPPUNIT_ASSERT(object_write_bencode(torrent::Object(INT64_C(123456789012345)), "i123456789012345e")); CPPUNIT_ASSERT(object_write_bencode(torrent::Object(INT64_C(-123456789012345)), "i-123456789012345e")); CPPUNIT_ASSERT(object_write_bencode(torrent::Object("test"), "4:test")); CPPUNIT_ASSERT(object_write_bencode(torrent::Object::create_list(), "le")); CPPUNIT_ASSERT(object_write_bencode(torrent::Object::create_map(), "de")); obj = torrent::Object::create_map(); obj.as_map()["a"] = (int64_t)1; CPPUNIT_ASSERT(object_write_bencode(obj, "d1:ai1ee")); obj.as_map()["b"] = "test"; CPPUNIT_ASSERT(object_write_bencode(obj, "d1:ai1e1:b4:teste")); obj.as_map()["c"] = torrent::Object::create_list(); obj.as_map()["c"].as_list().emplace_back("foo"); CPPUNIT_ASSERT(object_write_bencode(obj, "d1:ai1e1:b4:test1:cl3:fooee")); obj.as_map()["c"].as_list().emplace_back(); obj.as_map()["d"] = torrent::Object(); CPPUNIT_ASSERT(object_write_bencode(obj, "d1:ai1e1:b4:test1:cl3:fooee")); } libtorrent-0.16.11/test/torrent/test_tracker_controller.h0000644000000000000000000002001215175073411017254 #include "test/helpers/test_main_thread.h" #include "torrent/download_info.h" #include "tracker/tracker_controller.h" class TestTrackerController : public TestFixtureWithMainAndTrackerThread { CPPUNIT_TEST_SUITE(TestTrackerController); CPPUNIT_TEST(test_basic); CPPUNIT_TEST(test_enable); CPPUNIT_TEST(test_requesting); CPPUNIT_TEST(test_timeout); CPPUNIT_TEST(test_single_success); CPPUNIT_TEST(test_single_failure); CPPUNIT_TEST(test_single_disable); CPPUNIT_TEST(test_send_start); CPPUNIT_TEST(test_send_stop_normal); CPPUNIT_TEST(test_send_completed_normal); CPPUNIT_TEST(test_send_update_normal); CPPUNIT_TEST(test_send_update_failure); CPPUNIT_TEST(test_send_task_timeout); CPPUNIT_TEST(test_send_close_on_enable); CPPUNIT_TEST(test_multiple_success); CPPUNIT_TEST(test_multiple_failure); CPPUNIT_TEST(test_multiple_cycle); CPPUNIT_TEST(test_multiple_cycle_second_group); CPPUNIT_TEST(test_multiple_send_stop); CPPUNIT_TEST(test_timeout_lacking_usable); CPPUNIT_TEST(test_disable_tracker); CPPUNIT_TEST(test_new_peers); CPPUNIT_TEST_SUITE_END(); public: void test_basic(); void test_enable(); void test_disable(); void test_requesting(); void test_timeout(); void test_single_success(); void test_single_failure(); void test_single_disable(); void test_send_start(); void test_send_stop_normal(); void test_send_completed_normal(); void test_send_update_normal(); void test_send_update_failure(); void test_send_task_timeout(); void test_send_close_on_enable(); void test_multiple_success(); void test_multiple_failure(); void test_multiple_cycle(); void test_multiple_cycle_second_group(); void test_multiple_send_stop(); void test_multiple_send_update(); void test_timeout_lacking_usable(); void test_disable_tracker(); void test_new_peers(); }; #define TRACKER_CONTROLLER_SETUP() \ torrent::DownloadInfo download_info; \ torrent::TrackerList tracker_list; \ TestTrackerListWrapper(&tracker_list).set_info(&download_info); \ \ torrent::TrackerController tracker_controller(&tracker_list); \ \ int success_counter = 0; \ int failure_counter = 0; \ int timeout_counter = 0; \ int enabled_counter = 0; \ int disabled_counter = 0; \ \ tracker_controller.slot_success() = std::bind(&increment_value_uint, &success_counter); \ tracker_controller.slot_failure() = std::bind(&increment_value_void, &failure_counter); \ tracker_controller.slot_timeout() = std::bind(&increment_value_void, &timeout_counter); \ tracker_controller.slot_tracker_enabled() = std::bind(&increment_value_void, &enabled_counter); \ tracker_controller.slot_tracker_disabled() = std::bind(&increment_value_void, &disabled_counter); \ \ tracker_list.slot_success() = std::bind(&torrent::TrackerController::receive_success, &tracker_controller, std::placeholders::_1, std::placeholders::_2); \ tracker_list.slot_failure() = std::bind(&torrent::TrackerController::receive_failure, &tracker_controller, std::placeholders::_1, std::placeholders::_2); \ tracker_list.slot_tracker_enabled() = std::bind(&torrent::TrackerController::receive_tracker_enabled, &tracker_controller, std::placeholders::_1); \ tracker_list.slot_tracker_disabled() = std::bind(&torrent::TrackerController::receive_tracker_disabled, &tracker_controller, std::placeholders::_1); #define TEST_SINGLE_BEGIN() \ TRACKER_CONTROLLER_SETUP(); \ TRACKER_INSERT(0, tracker_0_0); \ \ tracker_controller.enable(); \ CPPUNIT_ASSERT(!(tracker_controller.flags() & torrent::TrackerController::mask_send)); \ #define TEST_SINGLE_END(succeeded, failed) \ tracker_controller.disable(); \ CPPUNIT_ASSERT(!tracker_list.has_active()); \ CPPUNIT_ASSERT(success_counter == succeeded && \ failure_counter == failure_counter); #define TEST_SEND_SINGLE_BEGIN(event_name) \ tracker_controller.send_##event_name##_event(); \ CPPUNIT_ASSERT((tracker_controller.flags() & torrent::TrackerController::mask_send) == \ torrent::TrackerController::flag_send_##event_name); \ \ CPPUNIT_ASSERT(tracker_controller.is_active()); \ CPPUNIT_ASSERT(TrackerTest::count_active(&tracker_list) == 1); #define TEST_SEND_SINGLE_END(succeeded, failed) \ TEST_SINGLE_END(succeeded, failed) \ CPPUNIT_ASSERT(tracker_controller.seconds_to_next_timeout() == 0); \ //CPPUNIT_ASSERT(tracker_controller.seconds_to_promicious_mode() != 0); #define TEST_MULTI3_BEGIN() \ TRACKER_CONTROLLER_SETUP(); \ TRACKER_INSERT(0, tracker_0_0); \ TRACKER_INSERT(0, tracker_0_1); \ TRACKER_INSERT(1, tracker_1_0); \ TRACKER_INSERT(2, tracker_2_0); \ TRACKER_INSERT(3, tracker_3_0); \ \ tracker_controller.enable(); \ CPPUNIT_ASSERT(!(tracker_controller.flags() & torrent::TrackerController::mask_send)); \ #define TEST_GROUP_BEGIN() \ TRACKER_CONTROLLER_SETUP(); \ TRACKER_INSERT(0, tracker_0_0); \ TRACKER_INSERT(0, tracker_0_1); \ TRACKER_INSERT(0, tracker_0_2); \ TRACKER_INSERT(1, tracker_1_0); \ TRACKER_INSERT(1, tracker_1_1); \ TRACKER_INSERT(2, tracker_2_0); \ \ tracker_controller.enable(); \ CPPUNIT_ASSERT(!(tracker_controller.flags() & torrent::TrackerController::mask_send)); #define TEST_MULTIPLE_END(succeeded, failed) \ tracker_controller.disable(); \ CPPUNIT_ASSERT(!tracker_list.has_active()); \ CPPUNIT_ASSERT(success_counter == succeeded && \ failure_counter == failed); #define TEST_GOTO_NEXT_SCRAPE(assumed_scrape) \ CPPUNIT_ASSERT(tracker_controller.is_scrape_queued()); \ CPPUNIT_ASSERT(assumed_scrape == tracker_controller.seconds_to_next_scrape()); \ CPPUNIT_ASSERT(test_goto_next_timeout(this, &tracker_controller, assumed_scrape, true)); bool test_tracker_value_in_range(uint32_t value, int32_t min, uint32_t max); void test_tracker_step_time(TestFixtureWithMainAndTrackerThread* fixture, int32_t seconds); bool test_goto_next_timeout(TestFixtureWithMainAndTrackerThread*, torrent::TrackerController*, uint32_t assumed_timeout, bool is_scrape = false); libtorrent-0.16.11/test/torrent/test_tracker_controller_requesting.h0000644000000000000000000000330315175073411021526 #include "test/helpers/test_main_thread.h" #include "test/torrent/test_tracker_controller.h" class TestTrackerControllerRequesting : public TestFixtureWithMainAndTrackerThread { CPPUNIT_TEST_SUITE(TestTrackerControllerRequesting); CPPUNIT_TEST(test_hammering_basic_success); CPPUNIT_TEST(test_hammering_basic_success_long_timeout); CPPUNIT_TEST(test_hammering_basic_success_short_timeout); CPPUNIT_TEST(test_hammering_basic_failure); CPPUNIT_TEST(test_hammering_basic_failure_long_timeout); CPPUNIT_TEST(test_hammering_basic_failure_short_timeout); CPPUNIT_TEST(test_hammering_multi_success); CPPUNIT_TEST(test_hammering_multi_success_long_timeout); CPPUNIT_TEST(test_hammering_multi_success_short_timeout); CPPUNIT_TEST(test_hammering_multi_failure); // CPPUNIT_TEST(test_hammering_multi_failure_long_timeout); // CPPUNIT_TEST(test_hammering_multi_failure_short_timeout); CPPUNIT_TEST_SUITE_END(); public: void test_hammering_basic_success(); void test_hammering_basic_success_long_timeout(); void test_hammering_basic_success_short_timeout(); void test_hammering_basic_failure(); void test_hammering_basic_failure_long_timeout(); void test_hammering_basic_failure_short_timeout(); void test_hammering_multi_success(); void test_hammering_multi_success_long_timeout(); void test_hammering_multi_success_short_timeout(); void test_hammering_multi_failure(); void test_hammering_multi_failure_long_timeout(); void test_hammering_multi_failure_short_timeout(); void do_test_hammering_basic(bool success1, bool success2, bool success3, uint32_t min_interval = 0); void do_test_hammering_multi3(bool success1, bool success2, bool success3, uint32_t min_interval = 0); }; libtorrent-0.16.11/test/torrent/object_static_map_test.h0000644000000000000000000000201015175073411017026 #include #include "torrent/object.h" class ObjectStaticMapTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(ObjectStaticMapTest); CPPUNIT_TEST(test_basics); CPPUNIT_TEST(test_write); CPPUNIT_TEST(test_read); CPPUNIT_TEST(test_read_extensions); CPPUNIT_TEST(test_read_empty); CPPUNIT_TEST(test_read_single); CPPUNIT_TEST(test_read_single_raw); CPPUNIT_TEST(test_read_raw_types); CPPUNIT_TEST(test_read_multiple); CPPUNIT_TEST(test_read_dict); CPPUNIT_TEST(test_write_empty); CPPUNIT_TEST(test_write_single); CPPUNIT_TEST(test_write_multiple); CPPUNIT_TEST_SUITE_END(); public: void test_basics(); void test_write(); void test_read(); void test_read_extensions(); // Proper unit tests: void test_read_empty(); void test_read_single(); void test_read_single_raw(); void test_read_raw_types(); void test_read_multiple(); void test_read_dict(); void test_write_empty(); void test_write_single(); void test_write_multiple(); }; libtorrent-0.16.11/test/torrent/object_test.h0000644000000000000000000000070315175073411014631 #include #include "torrent/object.h" class ObjectTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(ObjectTest); CPPUNIT_TEST(test_basic); CPPUNIT_TEST(test_flags); CPPUNIT_TEST(test_swap_and_move); CPPUNIT_TEST(test_create_normal); CPPUNIT_TEST_SUITE_END(); public: void test_basic(); void test_flags(); void test_merge(); void test_swap_and_move(); void test_create_normal(); }; libtorrent-0.16.11/test/torrent/utils/0000755000000000000000000000000015175073435013401 5libtorrent-0.16.11/test/torrent/utils/test_uri_parser.h0000644000000000000000000000054215175073411016677 #include "helpers/test_main_thread.h" class test_uri_parser : public TestFixtureWithMainThread { CPPUNIT_TEST_SUITE(test_uri_parser); CPPUNIT_TEST(test_basic); CPPUNIT_TEST(test_basic_magnet); CPPUNIT_TEST(test_query_magnet); CPPUNIT_TEST_SUITE_END(); public: void test_basic(); void test_basic_magnet(); void test_query_magnet(); }; libtorrent-0.16.11/test/torrent/utils/test_signal_interrupt.h0000644000000000000000000000103515175073411020113 #ifndef TEST_TORRENT_UTILS_SIGNAL_INTERRUPT_H #define TEST_TORRENT_UTILS_SIGNAL_INTERRUPT_H #include "test/helpers/test_fixture.h" class TestSignalInterrupt : public test_fixture { CPPUNIT_TEST_SUITE(TestSignalInterrupt); CPPUNIT_TEST(test_basic); CPPUNIT_TEST(test_thread_interrupt); CPPUNIT_TEST(test_latency); CPPUNIT_TEST(test_hammer); CPPUNIT_TEST_SUITE_END(); public: void test_basic(); void test_thread_interrupt(); void test_latency(); void test_hammer(); }; #endif // TEST_TORRENT_UTILS_SIGNAL_INTERRUPT_H libtorrent-0.16.11/test/torrent/utils/test_log.cc0000644000000000000000000001342215175073411015444 #include "config.h" #include "test_log.h" #include #include #include #include #include #include #include "torrent/exceptions.h" #include "torrent/utils/log.h" CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(test_log, "torrent/utils"); namespace { const char* expected_output = nullptr; unsigned int output_mask; void test_output(const char* output, unsigned int length, unsigned int mask) { CPPUNIT_ASSERT_MESSAGE("'" + std::string(output) + "' != '" + std::string(expected_output) + "'", std::strcmp(output, expected_output) == 0); CPPUNIT_ASSERT_MESSAGE("'" + std::string(output) + "'", std::strlen(output) == length); output_mask |= mask; } } // namespace namespace torrent { typedef std::vector > log_output_list; extern log_output_list log_outputs; } #define LTUNIT_ASSERT_OUTPUT(group, mask, expected, ...) \ output_mask = 0; expected_output = expected; \ lt_log_print(group, __VA_ARGS__); \ CPPUNIT_ASSERT(output_mask == (mask)); void test_log::setUp() { TestFixtureWithMainThread::setUp(); // Don't initialize since this creates the group->child connections. torrent::log_cleanup(); } void test_log::test_basic() { CPPUNIT_ASSERT(!torrent::log_groups.empty()); CPPUNIT_ASSERT(torrent::log_groups.size() == torrent::LOG_GROUP_MAX_SIZE); CPPUNIT_ASSERT(std::find_if(torrent::log_groups.begin(), torrent::log_groups.end(), std::bind(&torrent::log_group::valid, std::placeholders::_1)) == torrent::log_groups.end()); } inline void open_output(const char* name, int mask = 0) { torrent::log_open_output(name, std::bind(&::test_output, std::placeholders::_1, std::placeholders::_2, mask)); } void test_log::test_output_open() { CPPUNIT_ASSERT(torrent::log_groups[0].size_outputs() == 0); // Add test for unknown output names. open_output("test_output_1", 0x0); torrent::log_add_group_output(0, "test_output_1"); CPPUNIT_ASSERT(torrent::log_outputs.size() == 1); CPPUNIT_ASSERT(torrent::log_outputs[0].first == "test_output_1"); CPPUNIT_ASSERT(torrent::log_groups[0].outputs() == 0x1); CPPUNIT_ASSERT(torrent::log_groups[0].size_outputs() == 1); // Test inserting duplicate names, should catch. // CPPUNIT_ASSERT_THROW(torrent::log_open_output("test_output_1", torrent::log_slot());, torrent::input_error); // try { // torrent::log_open_output("test_output_1", torrent::log_slot()); // } catch (const torrent::input_error&) { // return; // } // CPPUNIT_ASSERT(false); // Test more than 64 entries. } // Test to make sure we don't call functions when using lt_log_print // on unused log items. void test_log::test_print() { open_output("test_print_1", 0x1); open_output("test_print_2", 0x2); torrent::log_add_group_output(0, "test_print_1"); LTUNIT_ASSERT_OUTPUT(0, 0x1, "foo_bar", "foo_bar"); LTUNIT_ASSERT_OUTPUT(0, 0x1, "foo 123 bar", "foo %i %s", 123, "bar"); torrent::log_add_group_output(0, "test_print_2"); LTUNIT_ASSERT_OUTPUT(0, 0x1|0x2, "test_multiple", "test_multiple"); } enum { GROUP_PARENT_1, GROUP_PARENT_2, GROUP_CHILD_1, GROUP_CHILD_1_1 }; void test_log::test_children() { open_output("test_children_1", 0x1); open_output("test_children_2", 0x2); torrent::log_add_group_output(GROUP_PARENT_1, "test_children_1"); torrent::log_add_group_output(GROUP_PARENT_2, "test_children_2"); torrent::log_add_child(GROUP_PARENT_1, GROUP_CHILD_1); torrent::log_add_child(GROUP_CHILD_1, GROUP_CHILD_1_1); // std::cout << "cached_output(" << torrent::log_groups[GROUP_PARENT_1].cached_outputs() << ')'; LTUNIT_ASSERT_OUTPUT(GROUP_PARENT_1, 0x1, "parent_1", "parent_1"); LTUNIT_ASSERT_OUTPUT(GROUP_CHILD_1, 0x1, "child_1", "child_1"); LTUNIT_ASSERT_OUTPUT(GROUP_CHILD_1_1, 0x1, "child_1", "child_1"); torrent::log_add_child(GROUP_PARENT_2, GROUP_CHILD_1); LTUNIT_ASSERT_OUTPUT(GROUP_PARENT_2, 0x2, "parent_2", "parent_2"); LTUNIT_ASSERT_OUTPUT(GROUP_CHILD_1, 0x3, "child_1", "child_1"); LTUNIT_ASSERT_OUTPUT(GROUP_CHILD_1_1, 0x3, "child_1", "child_1"); } void test_log::test_file_output() { std::string filename = "test_log.XXXXXX"; mktemp(&*filename.begin()); torrent::log_open_file_output("test_file", filename.c_str()); torrent::log_add_group_output(GROUP_PARENT_1, "test_file"); lt_log_print(GROUP_PARENT_1, "test_file"); torrent::log_cleanup(); // To ensure we flush the buffers. std::ifstream temp_file(filename.c_str()); CPPUNIT_ASSERT(temp_file.good()); char buffer[256]; temp_file.getline(buffer, 256); CPPUNIT_ASSERT_MESSAGE(buffer, std::string(buffer).find("test_file") != std::string::npos); std::remove(filename.c_str()); } void test_log::test_file_output_append() { std::string filename = "test_log.XXXXXX"; mktemp(&*filename.begin()); torrent::log_open_file_output("test_file", filename.c_str(), false); torrent::log_add_group_output(GROUP_PARENT_1, "test_file"); lt_log_print(GROUP_PARENT_1, "test_line_1"); torrent::log_cleanup(); // To ensure we flush the buffers. // re-open and write 2nd line torrent::log_open_file_output("test_file", filename.c_str(), true); torrent::log_add_group_output(GROUP_PARENT_1, "test_file"); lt_log_print(GROUP_PARENT_1, "test_line_2"); torrent::log_cleanup(); // To ensure we flush the buffers. std::ifstream temp_file(filename.c_str()); CPPUNIT_ASSERT(temp_file.good()); char buffer_line1[256]; temp_file.getline(buffer_line1, 256); char buffer_line2[256]; temp_file.getline(buffer_line2, 256); CPPUNIT_ASSERT_MESSAGE(buffer_line1, std::string(buffer_line1).find("test_line_1") != std::string::npos); CPPUNIT_ASSERT_MESSAGE(buffer_line2, std::string(buffer_line2).find("test_line_2") != std::string::npos); std::remove(filename.c_str()); } libtorrent-0.16.11/test/torrent/utils/test_log_buffer.h0000644000000000000000000000043715175073411016641 #include "helpers/test_main_thread.h" class test_log_buffer : public TestFixtureWithMainThread { CPPUNIT_TEST_SUITE(test_log_buffer); CPPUNIT_TEST(test_basic); CPPUNIT_TEST(test_timestamps); CPPUNIT_TEST_SUITE_END(); public: void test_basic(); void test_timestamps(); }; libtorrent-0.16.11/test/torrent/utils/test_uri_parser.cc0000644000000000000000000000621415175073411017037 #include "config.h" #include "test_uri_parser.h" #include #include CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(test_uri_parser, "torrent/utils"); namespace { void test_print_uri_state(torrent::utils::uri_state state) { lt_log_print(torrent::LOG_MOCK_CALLS, "state.uri: %s", state.uri.c_str()); lt_log_print(torrent::LOG_MOCK_CALLS, "state.scheme: %s", state.scheme.c_str()); lt_log_print(torrent::LOG_MOCK_CALLS, "state.resource: %s", state.resource.c_str()); lt_log_print(torrent::LOG_MOCK_CALLS, "state.query: %s", state.query.c_str()); lt_log_print(torrent::LOG_MOCK_CALLS, "state.fragment: %s", state.fragment.c_str()); } } // namespace void test_uri_parser::test_basic() { torrent::utils::uri_state state; CPPUNIT_ASSERT(state.state == torrent::utils::uri_state::state_empty); CPPUNIT_ASSERT(state.state != torrent::utils::uri_state::state_valid); CPPUNIT_ASSERT(state.state != torrent::utils::uri_state::state_invalid); } #define MAGNET_BASIC "magnet:?xt=urn:sha1:YNCKHTQCWBTRNJIV4WNAE52SJUQCZO5C" void test_uri_parser::test_basic_magnet() { torrent::utils::uri_state state; uri_parse_str(MAGNET_BASIC, state); test_print_uri_state(state); CPPUNIT_ASSERT(state.state == torrent::utils::uri_state::state_valid); CPPUNIT_ASSERT(state.uri == MAGNET_BASIC); CPPUNIT_ASSERT(state.scheme == "magnet"); CPPUNIT_ASSERT(state.resource == ""); CPPUNIT_ASSERT(state.query == "xt=urn:sha1:YNCKHTQCWBTRNJIV4WNAE52SJUQCZO5C"); CPPUNIT_ASSERT(state.fragment == ""); } #define QUERY_MAGNET_QUERY \ "xt=urn:ed2k:31D6CFE0D16AE931B73C59D7E0C089C0" \ "&xl=0&dn=zero_len.fil" \ "&xt=urn:bitprint:3I42H3S6NNFQ2MSVX7XZKYAYSCX5QBYJ" \ ".LWPNACQDBZRYXW3VHJVCJ64QBZNGHOHHHZWCLNQ" \ "&xt=urn:md5:D41D8CD98F00B204E9800998ECF8427E" #define QUERY_MAGNET "magnet:?" QUERY_MAGNET_QUERY void test_uri_parser::test_query_magnet() { torrent::utils::uri_state state; torrent::utils::uri_query_state query_state; uri_parse_str(QUERY_MAGNET, state); test_print_uri_state(state); CPPUNIT_ASSERT(state.state == torrent::utils::uri_state::state_valid); CPPUNIT_ASSERT(state.uri == QUERY_MAGNET); CPPUNIT_ASSERT(state.scheme == "magnet"); CPPUNIT_ASSERT(state.resource == ""); CPPUNIT_ASSERT(state.query == QUERY_MAGNET_QUERY); CPPUNIT_ASSERT(state.fragment == ""); uri_parse_query_str(state.query, query_state); for (auto element : query_state.elements) lt_log_print(torrent::LOG_MOCK_CALLS, "query_element: %s", element.c_str()); CPPUNIT_ASSERT(query_state.state == torrent::utils::uri_query_state::state_valid); CPPUNIT_ASSERT(query_state.elements.size() == 5); CPPUNIT_ASSERT(query_state.elements.at(0) == "xt=urn:ed2k:31D6CFE0D16AE931B73C59D7E0C089C0"); CPPUNIT_ASSERT(query_state.elements.at(1) == "xl=0"); CPPUNIT_ASSERT(query_state.elements.at(2) == "dn=zero_len.fil"); CPPUNIT_ASSERT(query_state.elements.at(3) == "xt=urn:bitprint:3I42H3S6NNFQ2MSVX7XZKYAYSCX5QBYJ.LWPNACQDBZRYXW3VHJVCJ64QBZNGHOHHHZWCLNQ"); CPPUNIT_ASSERT(query_state.elements.at(4) == "xt=urn:md5:D41D8CD98F00B204E9800998ECF8427E"); } libtorrent-0.16.11/test/torrent/utils/test_thread_base.cc0000644000000000000000000000557415175073411017135 #include "config.h" #include "test_thread_base.h" #include #include #include #include #include "runtime.h" #include "helpers/test_thread.h" #include "helpers/test_utils.h" #include "torrent/exceptions.h" #include "torrent/utils/log.h" #include "torrent/system/thread.h" CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(test_thread_base, "torrent/utils"); void test_thread_base::test_basic() { auto thread = test_thread::create(); CPPUNIT_ASSERT(thread->flags() == 0); CPPUNIT_ASSERT(!thread->is_active()); CPPUNIT_ASSERT(thread->internal_poll() != nullptr); // Check active... } void test_thread_base::test_lifecycle() { auto thread = test_thread::create(); torrent::Runtime::initialize(thread.get()); CPPUNIT_ASSERT(thread->state() == torrent::system::Thread::STATE_UNKNOWN); CPPUNIT_ASSERT(thread->test_state() == test_thread::TEST_NONE); thread->init_thread(); CPPUNIT_ASSERT(thread->state() == torrent::system::Thread::STATE_INITIALIZED); CPPUNIT_ASSERT(thread->is_initialized()); CPPUNIT_ASSERT(thread->test_state() == test_thread::TEST_PRE_START); thread->set_pre_stop(); CPPUNIT_ASSERT(!wait_for_true(std::bind(&test_thread::is_test_state, thread.get(), test_thread::TEST_PRE_STOP))); thread->start_thread(); CPPUNIT_ASSERT(wait_for_true(std::bind(&test_thread::is_state, thread.get(), test_thread::STATE_ACTIVE))); CPPUNIT_ASSERT(thread->is_active()); CPPUNIT_ASSERT(wait_for_true(std::bind(&test_thread::is_test_state, thread.get(), test_thread::TEST_PRE_STOP))); thread->stop_thread_wait(); CPPUNIT_ASSERT(wait_for_true(std::bind(&test_thread::is_state, thread.get(), test_thread::STATE_INACTIVE))); CPPUNIT_ASSERT(thread->is_inactive()); torrent::Runtime::cleanup(); } void test_thread_base::test_interrupt() { auto thread = test_thread::create(); torrent::Runtime::initialize(thread.get()); thread->set_test_flag(test_thread::test_flag_long_timeout); thread->init_thread(); thread->start_thread(); // Vary the various timeouts. for (int i = 0; i < 100; i++) { thread->interrupt(); usleep(0); thread->set_test_flag(test_thread::test_flag_do_work); thread->interrupt(); // Wait for flag to clear. CPPUNIT_ASSERT(wait_for_true(std::bind(&test_thread::is_not_test_flags, thread.get(), test_thread::test_flag_do_work))); } thread->stop_thread_wait(); CPPUNIT_ASSERT(wait_for_true(std::bind(&test_thread::is_state, thread.get(), test_thread::STATE_INACTIVE))); torrent::Runtime::cleanup(); } void test_thread_base::test_stop() { for (int i = 0; i < 20; i++) { auto thread = test_thread::create(); torrent::Runtime::initialize(thread.get()); thread->set_test_flag(test_thread::test_flag_do_work); thread->init_thread(); thread->start_thread(); thread->stop_thread_wait(); CPPUNIT_ASSERT(thread->is_inactive()); torrent::Runtime::cleanup(); } } libtorrent-0.16.11/test/torrent/utils/test_thread_base.h0000644000000000000000000000063015175073411016763 #include "helpers/test_fixture.h" class test_thread_base : public test_fixture { CPPUNIT_TEST_SUITE(test_thread_base); CPPUNIT_TEST(test_basic); CPPUNIT_TEST(test_lifecycle); CPPUNIT_TEST(test_interrupt); CPPUNIT_TEST(test_stop); CPPUNIT_TEST_SUITE_END(); public: void test_basic(); void test_lifecycle(); void test_interrupt(); void test_interrupt_legacy(); void test_stop(); }; libtorrent-0.16.11/test/torrent/utils/test_queue_buckets.cc0000644000000000000000000001620015175073411017524 #include "config.h" #include "test_queue_buckets.h" #include "utils/instrumentation.h" #include "utils/queue_buckets.h" CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(test_queue_buckets, "torrent/utils"); struct test_constants { static const int bucket_count = 2; static const torrent::instrumentation_enum instrumentation_added[bucket_count]; static const torrent::instrumentation_enum instrumentation_moved[bucket_count]; static const torrent::instrumentation_enum instrumentation_removed[bucket_count]; static const torrent::instrumentation_enum instrumentation_total[bucket_count]; template static void destroy(Type& obj); }; const int test_constants::bucket_count; const torrent::instrumentation_enum test_constants::instrumentation_added[bucket_count] = { torrent::INSTRUMENTATION_TRANSFER_REQUESTS_QUEUED_ADDED, torrent::INSTRUMENTATION_TRANSFER_REQUESTS_UNORDERED_ADDED }; const torrent::instrumentation_enum test_constants::instrumentation_moved[bucket_count] = { torrent::INSTRUMENTATION_TRANSFER_REQUESTS_QUEUED_MOVED, torrent::INSTRUMENTATION_TRANSFER_REQUESTS_UNORDERED_MOVED }; const torrent::instrumentation_enum test_constants::instrumentation_removed[bucket_count] = { torrent::INSTRUMENTATION_TRANSFER_REQUESTS_QUEUED_REMOVED, torrent::INSTRUMENTATION_TRANSFER_REQUESTS_UNORDERED_REMOVED }; const torrent::instrumentation_enum test_constants::instrumentation_total[bucket_count] = { torrent::INSTRUMENTATION_TRANSFER_REQUESTS_QUEUED_TOTAL, torrent::INSTRUMENTATION_TRANSFER_REQUESTS_UNORDERED_TOTAL }; typedef torrent::queue_buckets buckets_type; static int items_destroyed = 0; template <> void test_constants::destroy([[maybe_unused]] int& obj) { items_destroyed++; } struct test_queue_bucket_compare { test_queue_bucket_compare(int v) : m_v(v) {} bool operator () (int obj) { return m_v == obj; } int m_v; }; #define FILL_BUCKETS(s_0, s_1) \ for (int i = 0; i < s_0; i++) \ buckets.push_back(0, i); \ for (int i = 0; i < s_1; i++) \ buckets.push_back(1, s_0 + i); #define VERIFY_QUEUE_SIZES(s_0, s_1) \ CPPUNIT_ASSERT(buckets.queue_size(0) == s_0); \ CPPUNIT_ASSERT(buckets.queue_size(1) == s_1); #ifdef LT_INSTRUMENTATION #define VERIFY_INSTRUMENTATION(a_0, m_0, r_0, t_0, a_1, m_1, r_1, t_1) \ CPPUNIT_ASSERT(torrent::instrumentation_values[test_constants::instrumentation_added[0]] == a_0); \ CPPUNIT_ASSERT(torrent::instrumentation_values[test_constants::instrumentation_moved[0]] == m_0); \ CPPUNIT_ASSERT(torrent::instrumentation_values[test_constants::instrumentation_removed[0]] == r_0); \ CPPUNIT_ASSERT(torrent::instrumentation_values[test_constants::instrumentation_total[0]] == t_0); \ CPPUNIT_ASSERT(torrent::instrumentation_values[test_constants::instrumentation_added[1]] == a_1); \ CPPUNIT_ASSERT(torrent::instrumentation_values[test_constants::instrumentation_moved[1]] == m_1); \ CPPUNIT_ASSERT(torrent::instrumentation_values[test_constants::instrumentation_removed[1]] == r_1); \ CPPUNIT_ASSERT(torrent::instrumentation_values[test_constants::instrumentation_total[1]] == t_1); #else #define VERIFY_INSTRUMENTATION(a_0, m_0, r_0, t_0, a_1, m_1, r_1, t_1) #endif #define VERIFY_ITEMS_DESTROYED(count) \ CPPUNIT_ASSERT(items_destroyed == count); \ items_destroyed = 0; // // Basic tests: // void test_queue_buckets::test_basic() { torrent::instrumentation_initialize(); buckets_type buckets; VERIFY_QUEUE_SIZES(0, 0); CPPUNIT_ASSERT(buckets.empty()); buckets.push_front(0, int()); VERIFY_QUEUE_SIZES(1, 0); buckets.push_back(0, int()); VERIFY_QUEUE_SIZES(2, 0); VERIFY_INSTRUMENTATION(2, 0, 0, 2, 0, 0, 0, 0); CPPUNIT_ASSERT(!buckets.empty()); buckets.push_front(1, int()); VERIFY_QUEUE_SIZES(2, 1); buckets.push_back(1, int()); VERIFY_QUEUE_SIZES(2, 2); VERIFY_INSTRUMENTATION(2, 0, 0, 2, 2, 0, 0, 2); CPPUNIT_ASSERT(!buckets.empty()); buckets.pop_front(0); VERIFY_QUEUE_SIZES(1, 2); buckets.pop_back(0); VERIFY_QUEUE_SIZES(0, 2); VERIFY_INSTRUMENTATION(2, 0, 2, 0, 2, 0, 0, 2); CPPUNIT_ASSERT(!buckets.empty()); buckets.pop_front(1); VERIFY_QUEUE_SIZES(0, 1); buckets.pop_back(1); VERIFY_QUEUE_SIZES(0, 0); VERIFY_INSTRUMENTATION(2, 0, 2, 0, 2, 0, 2, 0); CPPUNIT_ASSERT(buckets.empty()); } void test_queue_buckets::test_erase() { items_destroyed = 0; torrent::instrumentation_initialize(); buckets_type buckets; FILL_BUCKETS(10, 5); VERIFY_QUEUE_SIZES(10, 5); VERIFY_INSTRUMENTATION(10, 0, 0, 10, 5, 0, 0, 5); buckets.destroy(0, buckets.begin(0) + 3, buckets.begin(0) + 7); VERIFY_ITEMS_DESTROYED(4); VERIFY_QUEUE_SIZES(6, 5); VERIFY_INSTRUMENTATION(10, 0, 4, 6, 5, 0, 0, 5); buckets.destroy(1, buckets.begin(1) + 0, buckets.begin(1) + 5); VERIFY_ITEMS_DESTROYED(5); VERIFY_QUEUE_SIZES(6, 0); VERIFY_INSTRUMENTATION(10, 0, 4, 6, 5, 0, 5, 0); } static buckets_type::const_iterator bucket_queue_find_in_queue(const buckets_type& buckets, int idx, int value) { return torrent::queue_bucket_find_if_in_queue(buckets, idx, test_queue_bucket_compare(value)); } static std::pair bucket_queue_find_in_any(const buckets_type& buckets, int value) { return torrent::queue_bucket_find_if_in_any(buckets, test_queue_bucket_compare(value)); } void test_queue_buckets::test_find() { items_destroyed = 0; torrent::instrumentation_initialize(); buckets_type buckets; FILL_BUCKETS(10, 5); CPPUNIT_ASSERT(bucket_queue_find_in_queue(buckets, 0, 0) == buckets.begin(0)); CPPUNIT_ASSERT(bucket_queue_find_in_queue(buckets, 0, 10) == buckets.end(0)); CPPUNIT_ASSERT(bucket_queue_find_in_queue(buckets, 1, 10) == buckets.begin(1)); CPPUNIT_ASSERT(bucket_queue_find_in_any(buckets, 0).first == 0); CPPUNIT_ASSERT(bucket_queue_find_in_any(buckets, 0).second == buckets.begin(0)); CPPUNIT_ASSERT(bucket_queue_find_in_any(buckets, 10).first == 1); CPPUNIT_ASSERT(bucket_queue_find_in_any(buckets, 10).second == buckets.begin(1)); CPPUNIT_ASSERT(bucket_queue_find_in_any(buckets, 20).first == 2); CPPUNIT_ASSERT(bucket_queue_find_in_any(buckets, 20).second == buckets.end(1)); } void test_queue_buckets::test_destroy_range() { items_destroyed = 0; torrent::instrumentation_initialize(); buckets_type buckets; FILL_BUCKETS(10, 5); VERIFY_QUEUE_SIZES(10, 5); VERIFY_INSTRUMENTATION(10, 0, 0, 10, 5, 0, 0, 5); buckets.destroy(0, buckets.begin(0) + 3, buckets.begin(0) + 7); VERIFY_ITEMS_DESTROYED(4); VERIFY_QUEUE_SIZES(6, 5); VERIFY_INSTRUMENTATION(10, 0, 4, 6, 5, 0, 0, 5); buckets.destroy(1, buckets.begin(1) + 0, buckets.begin(1) + 5); VERIFY_ITEMS_DESTROYED(5); VERIFY_QUEUE_SIZES(6, 0); VERIFY_INSTRUMENTATION(10, 0, 4, 6, 5, 0, 5, 0); } void test_queue_buckets::test_move_range() { items_destroyed = 0; torrent::instrumentation_initialize(); buckets_type buckets; FILL_BUCKETS(10, 5); torrent::instrumentation_reset(); buckets.move_to(0, buckets.begin(0) + 3, buckets.begin(0) + 7, 1); VERIFY_ITEMS_DESTROYED(0); VERIFY_QUEUE_SIZES(6, 9); VERIFY_INSTRUMENTATION(0, 4, 0, 6, 4, 0, 0, 9); } libtorrent-0.16.11/test/torrent/utils/test_log.h0000644000000000000000000000103715175073411015305 #include "helpers/test_main_thread.h" class test_log : public TestFixtureWithMainThread { CPPUNIT_TEST_SUITE(test_log); CPPUNIT_TEST(test_basic); CPPUNIT_TEST(test_output_open); CPPUNIT_TEST(test_print); CPPUNIT_TEST(test_children); CPPUNIT_TEST(test_file_output); CPPUNIT_TEST(test_file_output_append); CPPUNIT_TEST_SUITE_END(); public: void setUp() override; void test_basic(); void test_output_open(); void test_print(); void test_children(); void test_file_output(); void test_file_output_append(); }; libtorrent-0.16.11/test/torrent/utils/test_signal_interrupt.cc0000644000000000000000000001114415175073411020253 #include "config.h" #include "test_signal_interrupt.h" #include #include "runtime.h" #include "test/helpers/test_thread.h" #include "test/helpers/network.h" #include "torrent/exceptions.h" #include "torrent/system/thread.h" #include "utils/signal_interrupt.h" CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(TestSignalInterrupt, "torrent/utils"); void TestSignalInterrupt::test_basic() { mock_redirect_defaults(); auto pair = torrent::SignalInterrupt::create_pair(); CPPUNIT_ASSERT(pair.first != nullptr); CPPUNIT_ASSERT(pair.second != nullptr); CPPUNIT_ASSERT(pair.first->file_descriptor() >= 0); CPPUNIT_ASSERT(pair.second->file_descriptor() >= 0); CPPUNIT_ASSERT(pair.first->file_descriptor() != pair.second->file_descriptor()); for (int i = 0; i < 10; i++) { CPPUNIT_ASSERT(!pair.first->is_poking()); CPPUNIT_ASSERT(!pair.second->is_poking()); CPPUNIT_ASSERT(!check_event_is_readable(pair.second.get(), 0ms)); CPPUNIT_ASSERT(!check_event_is_readable(pair.first.get(), 0ms)); pair.first->poke(); CPPUNIT_ASSERT(!pair.first->is_poking()); CPPUNIT_ASSERT(pair.second->is_poking()); CPPUNIT_ASSERT(check_event_is_readable(pair.second.get(), 1ms)); CPPUNIT_ASSERT(!check_event_is_readable(pair.first.get(), 0ms)); auto start_time = std::chrono::steady_clock::now(); pair.second->event_read(); auto end_time = std::chrono::steady_clock::now(); CPPUNIT_ASSERT((end_time - start_time) < 1ms); } } // TODO: Add some allowance for loop_count checks not being ready after 1ms. void TestSignalInterrupt::test_thread_interrupt() { auto thread = test_thread::create(); thread->set_test_flag(test_thread::test_flag_long_timeout); thread->init_thread(); torrent::Runtime::initialize(thread.get()); thread->start_thread(); std::this_thread::sleep_for(10ms); CPPUNIT_ASSERT(thread->is_state(test_thread::STATE_ACTIVE)); int loop_count = thread->loop_count(); std::this_thread::sleep_for(500ms); CPPUNIT_ASSERT(thread->loop_count() == loop_count); thread->interrupt(); std::this_thread::sleep_for(1ms); CPPUNIT_ASSERT(thread->loop_count() == loop_count + 2); thread->stop_thread_wait(); torrent::Runtime::cleanup(); } void TestSignalInterrupt::test_latency() { auto thread = test_thread::create(); thread->set_test_flag(test_thread::test_flag_long_timeout); thread->init_thread(); torrent::Runtime::initialize(thread.get()); thread->start_thread(); std::this_thread::sleep_for(10ms); CPPUNIT_ASSERT(thread->is_state(test_thread::STATE_ACTIVE)); int loop_count = thread->loop_count(); auto start_time = std::chrono::steady_clock::now(); for (int i = 0; i < 1000; i++) { thread->interrupt(); for (int j = 0; j < 10; j++) { if (thread->loop_count() >= loop_count + 2) continue; std::this_thread::sleep_for(1ms); } auto new_count = thread->loop_count(); CPPUNIT_ASSERT(new_count <= loop_count + 2); CPPUNIT_ASSERT(new_count == loop_count + 2); loop_count = new_count; } auto end_time = std::chrono::steady_clock::now(); auto ignore_signal_latency = std::getenv("TEST_IGNORE_SIGNAL_INTERRUPT_LATENCY"); if (ignore_signal_latency != nullptr && ignore_signal_latency == std::string("YES")) return; CPPUNIT_ASSERT((end_time - start_time) < 2s); thread->stop_thread_wait(); torrent::Runtime::cleanup(); } void TestSignalInterrupt::test_hammer() { auto thread = test_thread::create(); thread->set_test_flag(test_thread::test_flag_long_timeout); thread->init_thread(); torrent::Runtime::initialize(thread.get()); thread->start_thread(); std::this_thread::sleep_for(10ms); CPPUNIT_ASSERT(thread->is_state(test_thread::STATE_ACTIVE)); int loop_count = thread->loop_count(); auto start_time = std::chrono::steady_clock::now(); for (int i = 0; i < 1000; i++) { for (int j = 0; j < 10; j++) thread->interrupt(); for (int j = 0; j < 10; j++) { if (thread->loop_count() >= loop_count + 2) continue; std::this_thread::sleep_for(1ms); } auto new_count = thread->loop_count(); // Since we hammer the interrupt, we can't expect the loop count to just increment by 2. CPPUNIT_ASSERT(new_count <= loop_count + 20); loop_count = new_count; } auto end_time = std::chrono::steady_clock::now(); auto ignore_signal_latency = std::getenv("TEST_IGNORE_SIGNAL_INTERRUPT_LATENCY"); if (ignore_signal_latency != nullptr && ignore_signal_latency == std::string("YES")) return; CPPUNIT_ASSERT((end_time - start_time) < 2s); thread->stop_thread_wait(); torrent::Runtime::cleanup(); } // TODO: Test with high load / long process. libtorrent-0.16.11/test/torrent/utils/test_extents.h0000644000000000000000000000034315175073411016215 #include "test/helpers/test_main_thread.h" class test_extents : public TestFixtureWithMainThread { CPPUNIT_TEST_SUITE(test_extents); CPPUNIT_TEST(test_basic); CPPUNIT_TEST_SUITE_END(); public: void test_basic(); }; libtorrent-0.16.11/test/torrent/utils/test_signal_bitfield.h0000644000000000000000000000060015175073411017636 #include "helpers/test_fixture.h" class test_signal_bitfield : public test_fixture { CPPUNIT_TEST_SUITE(test_signal_bitfield); CPPUNIT_TEST(test_basic); CPPUNIT_TEST(test_single); CPPUNIT_TEST(test_multiple); CPPUNIT_TEST(test_threaded); CPPUNIT_TEST_SUITE_END(); public: void test_basic(); void test_single(); void test_multiple(); void test_threaded(); }; libtorrent-0.16.11/test/torrent/utils/test_option_strings.cc0000644000000000000000000000233715175073411017747 #include "config.h" #include "test_option_strings.h" #include #include #include CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(test_option_strings, "torrent/utils"); #define TEST_ENTRY(group, name, value) \ { lt_log_print(torrent::LOG_MOCK_CALLS, "option_string: %s", name); \ std::string result(torrent::option_as_string(torrent::group, value)); \ CPPUNIT_ASSERT_MESSAGE("Not found '" + result + "'", result == name); \ CPPUNIT_ASSERT(torrent::option_find_string(torrent::group, name) == value); \ } void test_option_strings::test_entries() { TEST_ENTRY(OPTION_CONNECTION_TYPE, "leech", torrent::Download::CONNECTION_LEECH); TEST_ENTRY(OPTION_CONNECTION_TYPE, "seed", torrent::Download::CONNECTION_SEED); TEST_ENTRY(OPTION_CONNECTION_TYPE, "initial_seed", torrent::Download::CONNECTION_INITIAL_SEED); TEST_ENTRY(OPTION_CONNECTION_TYPE, "metadata", torrent::Download::CONNECTION_METADATA); TEST_ENTRY(OPTION_LOG_GROUP, "critical", torrent::LOG_CRITICAL); TEST_ENTRY(OPTION_LOG_GROUP, "storage_notice", torrent::LOG_STORAGE_NOTICE); TEST_ENTRY(OPTION_LOG_GROUP, "torrent_debug", torrent::LOG_TORRENT_DEBUG); } libtorrent-0.16.11/test/torrent/utils/test_option_strings.h0000644000000000000000000000035615175073411017610 #include "helpers/test_main_thread.h" class test_option_strings : public TestFixtureWithMainThread { CPPUNIT_TEST_SUITE(test_option_strings); CPPUNIT_TEST(test_entries); CPPUNIT_TEST_SUITE_END(); public: void test_entries(); }; libtorrent-0.16.11/test/torrent/utils/test_queue_buckets.h0000644000000000000000000000066715175073411017400 #include "helpers/test_fixture.h" class test_queue_buckets : public test_fixture { CPPUNIT_TEST_SUITE(test_queue_buckets); CPPUNIT_TEST(test_basic); CPPUNIT_TEST(test_erase); CPPUNIT_TEST(test_find); CPPUNIT_TEST(test_destroy_range); CPPUNIT_TEST(test_move_range); CPPUNIT_TEST_SUITE_END(); public: void test_basic(); void test_erase(); void test_find(); void test_destroy_range(); void test_move_range(); }; libtorrent-0.16.11/test/torrent/utils/test_signal_bitfield.cc0000644000000000000000000001006115175073411017776 #include "config.h" #include "test_signal_bitfield.h" #include "helpers/test_thread.h" #include "helpers/test_utils.h" #include "runtime.h" #include "torrent/exceptions.h" #include "torrent/utils/signal_bitfield.h" #include "torrent/system/thread.h" CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(test_signal_bitfield, "torrent/utils"); inline void bitfield_mark_index(std::atomic_uint32_t& bitfield, unsigned int index) { bitfield |= 1 << index; } static bool check_index(std::atomic_uint32_t& bitfield, unsigned int index) { return bitfield & (1 << index); } static bool verify_did_internal_error(std::function func, bool should_throw) { bool did_throw = false; try { func(); } catch (const torrent::internal_error&) { did_throw = true; } return should_throw == did_throw; } #define SETUP_SIGNAL_BITFIELD() \ std::atomic_uint32_t marked_bitfield{0}; \ torrent::signal_bitfield signal_bitfield; #define SIGNAL_BITFIELD_DID_INTERNAL_ERROR(verify_slot, did_throw) \ CPPUNIT_ASSERT(verify_did_internal_error(std::bind(&torrent::signal_bitfield::add_signal, \ &signal_bitfield, \ torrent::signal_bitfield::slot_type(verify_slot)), \ did_throw)); void test_signal_bitfield::test_basic() { SETUP_SIGNAL_BITFIELD(); CPPUNIT_ASSERT(torrent::signal_bitfield::max_size == sizeof(torrent::signal_bitfield::bitfield_type) * 8); SIGNAL_BITFIELD_DID_INTERNAL_ERROR(torrent::signal_bitfield::slot_type(), true); for (unsigned int i = 0; i < torrent::signal_bitfield::max_size; i++) CPPUNIT_ASSERT(signal_bitfield.add_signal([i, &marked_bitfield] () { bitfield_mark_index(marked_bitfield, i); }) == i); SIGNAL_BITFIELD_DID_INTERNAL_ERROR([&marked_bitfield] () { bitfield_mark_index(marked_bitfield, torrent::signal_bitfield::max_size); }, true); } void test_signal_bitfield::test_single() { SETUP_SIGNAL_BITFIELD(); CPPUNIT_ASSERT(signal_bitfield.add_signal([&marked_bitfield] () { bitfield_mark_index(marked_bitfield, 0); }) == 0); signal_bitfield.signal(0); CPPUNIT_ASSERT(marked_bitfield == 0x0); signal_bitfield.work(); CPPUNIT_ASSERT(marked_bitfield == 0x1); marked_bitfield = 0; signal_bitfield.work(); CPPUNIT_ASSERT(marked_bitfield == 0x0); } void test_signal_bitfield::test_multiple() { SETUP_SIGNAL_BITFIELD(); for (unsigned int i = 0; i < torrent::signal_bitfield::max_size; i++) CPPUNIT_ASSERT(signal_bitfield.add_signal([i, &marked_bitfield] () { bitfield_mark_index(marked_bitfield, i); }) == i); signal_bitfield.signal(2); signal_bitfield.signal(31); CPPUNIT_ASSERT(marked_bitfield == 0x0); signal_bitfield.work(); CPPUNIT_ASSERT(marked_bitfield == (((unsigned int)1 << 2) | ((unsigned int)1 << 31))); marked_bitfield = 0; signal_bitfield.work(); CPPUNIT_ASSERT(marked_bitfield == 0x0); } void test_signal_bitfield::test_threaded() { std::atomic_uint32_t marked_bitfield{0}; auto thread = test_thread::create(); // thread->set_test_flag(test_thread::test_flag_long_timeout); torrent::Runtime::initialize(thread.get()); for (unsigned int i = 0; i < torrent::signal_bitfield::max_size; i++) CPPUNIT_ASSERT(thread->signal_bitfield()->add_signal([i, &marked_bitfield] () { bitfield_mark_index(marked_bitfield, i); }) == i); thread->init_thread(); thread->start_thread(); // Vary the various timeouts. for (int i = 0; i < 100; i++) { // thread->interrupt(); // usleep(0); thread->signal_bitfield()->signal(i % 20); // thread->interrupt(); CPPUNIT_ASSERT(wait_for_true([i, &marked_bitfield] () { return check_index(marked_bitfield, i % 20); })); marked_bitfield &= ~uint32_t(); } thread->stop_thread_wait(); torrent::Runtime::cleanup(); CPPUNIT_ASSERT(wait_for_true(std::bind(&test_thread::is_state, thread.get(), test_thread::STATE_INACTIVE))); } // Test invalid signal added. // Test overflow signals added. // Test multiple signals triggered. // Stresstest with real thread/polling. libtorrent-0.16.11/test/torrent/utils/test_extents.cc0000644000000000000000000000304215175073411016352 #include "config.h" #include "test_extents.h" #include #include CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(test_extents, "torrent/utils"); #define TEST_EXTENT_BEGIN(name) \ lt_log_print(torrent::LOG_MOCK_CALLS, "extent: %s", name); typedef torrent::extents extent_type_1; template bool verify_extent_data(Extent& extent, const uint32_t* idx, const int* val) { while (*idx != *(idx + 1)) { for (auto i = *idx; i != *(idx + 1); i++) { lt_log_print(torrent::LOG_MOCK_CALLS, "extent: at %u", i); if (extent.at(i) != *val) return false; } idx++; val++; } return true; } static const uint32_t idx_empty[] = {0, 256, 256}; static const int val_empty[] = {0}; static const uint32_t idx_basic_1[] = {0, 1, 255, 256, 256}; static const int val_basic_1[] = {1, 0, 1}; void test_extents::test_basic() { extent_type_1 extent_1; extent_1.insert(0, 255, int()); { TEST_EXTENT_BEGIN("empty"); CPPUNIT_ASSERT(verify_extent_data(extent_1, idx_empty, val_empty)); CPPUNIT_ASSERT(extent_1.at(0) == int()); CPPUNIT_ASSERT(extent_1.at(255) == int()); }; { TEST_EXTENT_BEGIN("borders"); extent_1.insert(0, 0, 1); extent_1.insert(255, 255, 1); // This step shouldn't be needed. extent_1.insert(1, 254, int()); CPPUNIT_ASSERT(extent_1.at(0) == 1); CPPUNIT_ASSERT(extent_1.at(255) == 1); CPPUNIT_ASSERT(verify_extent_data(extent_1, idx_basic_1, val_basic_1)); }; } libtorrent-0.16.11/test/torrent/utils/test_log_buffer.cc0000644000000000000000000000356215175073411017001 #include "config.h" #include "test_log_buffer.h" #include "torrent/utils/log_buffer.h" CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(test_log_buffer, "torrent/utils"); void test_log_buffer::test_basic() { torrent::log_buffer log; m_main_thread->test_set_cached_time(1000s); log.lock(); CPPUNIT_ASSERT(log.empty()); CPPUNIT_ASSERT(log.find_older(0) == log.end()); log.unlock(); log.lock_and_push_log("foobar", 6, -1); CPPUNIT_ASSERT(log.empty()); auto timestamp = std::chrono::seconds(365 * 24h + 1000s).count(); log.lock_and_push_log("foobar", 6, 0); CPPUNIT_ASSERT(log.size() == 1); CPPUNIT_ASSERT(log.back().timestamp == timestamp); CPPUNIT_ASSERT(log.back().group == 0); CPPUNIT_ASSERT(log.back().message == "foobar"); m_main_thread->test_add_cached_time(1s); log.lock_and_push_log("barbaz", 6, 0); CPPUNIT_ASSERT(log.size() == 2); CPPUNIT_ASSERT(log.back().timestamp == timestamp + 1); CPPUNIT_ASSERT(log.back().group == 0); CPPUNIT_ASSERT(log.back().message == "barbaz"); } void test_log_buffer::test_timestamps() { torrent::log_buffer log; m_main_thread->test_set_cached_time(1000s); auto timestamp = std::chrono::seconds(365 * 24h + 1000s).count(); log.lock_and_push_log("foobar", 6, 0); CPPUNIT_ASSERT(log.back().timestamp == timestamp); CPPUNIT_ASSERT(log.find_older(timestamp - 1) == log.begin()); CPPUNIT_ASSERT(log.find_older(timestamp) == log.end()); CPPUNIT_ASSERT(log.find_older(timestamp + 1) == log.end()); m_main_thread->test_add_cached_time(10s); log.lock_and_push_log("foobar", 6, 0); CPPUNIT_ASSERT(log.back().timestamp == timestamp + 10); CPPUNIT_ASSERT(log.find_older(timestamp) == log.begin()); CPPUNIT_ASSERT(log.find_older(timestamp + 10 - 1) == log.begin() + 1); CPPUNIT_ASSERT(log.find_older(timestamp + 10) == log.end()); CPPUNIT_ASSERT(log.find_older(timestamp + 10 + 1) == log.end()); } libtorrent-0.16.11/test/torrent/test_tracker_list_features.cc0000644000000000000000000002646315175073411020120 #include "config.h" #include #include "net/address_list.h" #include "test/torrent/test_tracker_list.h" #include "test/torrent/test_tracker_list_features.h" CPPUNIT_TEST_SUITE_REGISTRATION(TestTrackerListFeatures); namespace { [[maybe_unused]] bool verify_did_internal_error(std::function func, bool should_throw) { bool did_throw = false; try { func(); } catch (const torrent::internal_error&) { did_throw = true; } return should_throw == did_throw; } } // namespace void TestTrackerListFeatures::test_new_peers() { TRACKER_LIST_SETUP(); TRACKER_INSERT(0, tracker_0_0); auto tracker_0_0_worker = TrackerTest::test_worker(tracker_0_0); CPPUNIT_ASSERT(tracker_0_0.state().latest_new_peers() == 0); CPPUNIT_ASSERT(tracker_0_0.state().latest_sum_peers() == 0); tracker_list.send_event(tracker_list.at(0), torrent::tracker::TrackerState::EVENT_NONE); CPPUNIT_ASSERT(tracker_0_0_worker->trigger_success(10, 20)); CPPUNIT_ASSERT(tracker_0_0.state().latest_new_peers() == 10); CPPUNIT_ASSERT(tracker_0_0.state().latest_sum_peers() == 20); tracker_list.send_event(tracker_list.at(0), torrent::tracker::TrackerState::EVENT_NONE); CPPUNIT_ASSERT(tracker_0_0_worker->trigger_failure()); CPPUNIT_ASSERT(tracker_0_0.state().latest_new_peers() == 10); CPPUNIT_ASSERT(tracker_0_0.state().latest_sum_peers() == 20); tracker_list.clear_stats(); CPPUNIT_ASSERT(tracker_0_0.state().latest_new_peers() == 0); CPPUNIT_ASSERT(tracker_0_0.state().latest_sum_peers() == 0); } // test last_connect timer. // test has_active, and then clean up TrackerManager. void TestTrackerListFeatures::test_has_active() { TRACKER_LIST_SETUP(); TRACKER_INSERT(0, tracker_0_0); TRACKER_INSERT(0, tracker_0_1); TRACKER_INSERT(1, tracker_1_0); auto tracker_0_0_worker = TrackerTest::test_worker(tracker_0_0); auto tracker_0_1_worker = TrackerTest::test_worker(tracker_0_1); auto tracker_1_0_worker = TrackerTest::test_worker(tracker_1_0); CPPUNIT_ASSERT(!tracker_list.has_active()); CPPUNIT_ASSERT(!tracker_list.has_active_not_scrape()); tracker_list.send_event(tracker_list.at(0), torrent::tracker::TrackerState::EVENT_NONE); CPPUNIT_ASSERT(tracker_list.has_active()); CPPUNIT_ASSERT(tracker_list.has_active_not_scrape()); tracker_0_0_worker->trigger_success(); CPPUNIT_ASSERT(!tracker_list.has_active()); CPPUNIT_ASSERT(!tracker_list.has_active_not_scrape()); tracker_list.send_event(tracker_list.at(2), torrent::tracker::TrackerState::EVENT_NONE); CPPUNIT_ASSERT(tracker_list.has_active()); tracker_1_0_worker->trigger_success(); CPPUNIT_ASSERT(!tracker_list.has_active()); // Test multiple active trackers. tracker_list.send_event(tracker_list.at(0), torrent::tracker::TrackerState::EVENT_NONE); CPPUNIT_ASSERT(tracker_list.has_active()); tracker_list.send_event(tracker_list.at(1), torrent::tracker::TrackerState::EVENT_NONE); tracker_0_0_worker->trigger_success(); CPPUNIT_ASSERT(tracker_list.has_active()); tracker_0_1_worker->trigger_success(); CPPUNIT_ASSERT(!tracker_list.has_active()); tracker_1_0_worker->set_scrapable(); tracker_list.send_scrape(tracker_1_0); CPPUNIT_ASSERT(tracker_list.has_active()); CPPUNIT_ASSERT(!tracker_list.has_active_not_scrape()); } void TestTrackerListFeatures::test_find_next_to_request() { TRACKER_LIST_SETUP(); TRACKER_INSERT(0, tracker_0); TRACKER_INSERT(0, tracker_1); TRACKER_INSERT(0, tracker_2); TRACKER_INSERT(0, tracker_3); auto tracker_0_worker = TrackerTest::test_worker(tracker_0); auto tracker_1_worker = TrackerTest::test_worker(tracker_1); auto tracker_2_worker = TrackerTest::test_worker(tracker_2); auto tracker_3_worker = TrackerTest::test_worker(tracker_3); CPPUNIT_ASSERT(tracker_list.find_next_to_request(tracker_list.begin()) == tracker_list.begin()); CPPUNIT_ASSERT(tracker_list.find_next_to_request(tracker_list.begin() + 1) == tracker_list.begin() + 1); CPPUNIT_ASSERT(tracker_list.find_next_to_request(tracker_list.end()) == tracker_list.end()); tracker_0.disable(); CPPUNIT_ASSERT(tracker_list.find_next_to_request(tracker_list.begin()) == tracker_list.begin() + 1); tracker_0.enable(); tracker_0_worker->set_failed(1, torrent::this_thread::cached_seconds().count() - 0); CPPUNIT_ASSERT(tracker_list.find_next_to_request(tracker_list.begin()) == tracker_list.begin() + 1); tracker_1_worker->set_failed(1, torrent::this_thread::cached_seconds().count() - 0); tracker_2_worker->set_failed(1, torrent::this_thread::cached_seconds().count() - 0); CPPUNIT_ASSERT(tracker_list.find_next_to_request(tracker_list.begin()) == tracker_list.begin() + 3); tracker_3_worker->set_failed(1, torrent::this_thread::cached_seconds().count() - 0); CPPUNIT_ASSERT(tracker_list.find_next_to_request(tracker_list.begin()) == tracker_list.begin() + 0); tracker_0_worker->set_failed(1, torrent::this_thread::cached_seconds().count() - 3); tracker_1_worker->set_failed(1, torrent::this_thread::cached_seconds().count() - 2); tracker_2_worker->set_failed(1, torrent::this_thread::cached_seconds().count() - 4); tracker_3_worker->set_failed(1, torrent::this_thread::cached_seconds().count() - 2); CPPUNIT_ASSERT(tracker_list.find_next_to_request(tracker_list.begin()) == tracker_list.begin() + 2); tracker_1_worker->set_failed(0, torrent::this_thread::cached_seconds().count() - 1); tracker_1_worker->set_success(1, torrent::this_thread::cached_seconds().count() - 1); CPPUNIT_ASSERT(tracker_list.find_next_to_request(tracker_list.begin()) == tracker_list.begin() + 0); tracker_1_worker->set_success(1, torrent::this_thread::cached_seconds().count() - (tracker_1.state().normal_interval() - 1)); CPPUNIT_ASSERT(tracker_list.find_next_to_request(tracker_list.begin()) == tracker_list.begin() + 1); } void TestTrackerListFeatures::test_find_next_to_request_groups() { TRACKER_LIST_SETUP(); TRACKER_INSERT(0, tracker_0); TRACKER_INSERT(0, tracker_1); TRACKER_INSERT(1, tracker_2); TRACKER_INSERT(1, tracker_3); auto tracker_0_worker = TrackerTest::test_worker(tracker_0); auto tracker_1_worker = TrackerTest::test_worker(tracker_1); auto tracker_2_worker = TrackerTest::test_worker(tracker_2); CPPUNIT_ASSERT(tracker_list.find_next_to_request(tracker_list.begin()) == tracker_list.begin()); tracker_0_worker->set_failed(1, torrent::this_thread::cached_seconds().count() - 0); CPPUNIT_ASSERT(tracker_list.find_next_to_request(tracker_list.begin()) == tracker_list.begin() + 1); tracker_1_worker->set_failed(1, torrent::this_thread::cached_seconds().count() - 0); CPPUNIT_ASSERT(tracker_list.find_next_to_request(tracker_list.begin()) == tracker_list.begin() + 2); tracker_2_worker->set_failed(1, torrent::this_thread::cached_seconds().count() - 0); CPPUNIT_ASSERT(tracker_list.find_next_to_request(tracker_list.begin()) == tracker_list.begin() + 3); tracker_1_worker->set_failed(0, torrent::this_thread::cached_seconds().count() - 0); CPPUNIT_ASSERT(tracker_list.find_next_to_request(tracker_list.begin()) == tracker_list.begin() + 1); } void TestTrackerListFeatures::test_count_active() { TRACKER_LIST_SETUP(); TRACKER_INSERT(0, tracker_0_0); TRACKER_INSERT(0, tracker_0_1); TRACKER_INSERT(1, tracker_1_0); TRACKER_INSERT(2, tracker_2_0); auto tracker_0_0_worker = TrackerTest::test_worker(tracker_0_0); auto tracker_0_1_worker = TrackerTest::test_worker(tracker_0_1); auto tracker_1_0_worker = TrackerTest::test_worker(tracker_1_0); auto tracker_2_0_worker = TrackerTest::test_worker(tracker_2_0); CPPUNIT_ASSERT(TrackerTest::count_active(&tracker_list) == 0); tracker_list.send_event(tracker_list.at(0), torrent::tracker::TrackerState::EVENT_NONE); CPPUNIT_ASSERT(TrackerTest::count_active(&tracker_list) == 1); tracker_list.send_event(tracker_list.at(3), torrent::tracker::TrackerState::EVENT_NONE); CPPUNIT_ASSERT(TrackerTest::count_active(&tracker_list) == 2); tracker_list.send_event(tracker_list.at(1), torrent::tracker::TrackerState::EVENT_NONE); tracker_list.send_event(tracker_list.at(2), torrent::tracker::TrackerState::EVENT_NONE); CPPUNIT_ASSERT(TrackerTest::count_active(&tracker_list) == 4); tracker_0_0_worker->trigger_success(); CPPUNIT_ASSERT(TrackerTest::count_active(&tracker_list) == 3); tracker_0_1_worker->trigger_success(); tracker_2_0_worker->trigger_success(); CPPUNIT_ASSERT(TrackerTest::count_active(&tracker_list) == 1); tracker_1_0_worker->trigger_success(); CPPUNIT_ASSERT(TrackerTest::count_active(&tracker_list) == 0); } // Add separate functions for sending state to multiple trackers... void TestTrackerListFeatures::test_request_safeguard() { // TODO: Reimplement tracker hammering properly. // TRACKER_LIST_SETUP(); // TRACKER_INSERT(0, tracker_1); // TRACKER_INSERT(0, tracker_2); // TRACKER_INSERT(0, tracker_3); // TRACKER_INSERT(0, tracker_foo); // auto tracker_1_worker = TrackerTest::test_worker(tracker_1); // auto tracker_2_worker = TrackerTest::test_worker(tracker_2); // auto tracker_3_worker = TrackerTest::test_worker(tracker_3); // auto tracker_foo_worker = TrackerTest::test_worker(tracker_foo); // for (unsigned int i = 0; i < 9; i++) { // CPPUNIT_ASSERT(verify_did_internal_error(std::bind(&torrent::TrackerList::send_event, &tracker_list, tracker_1, torrent::tracker::TrackerState::EVENT_NONE), false)); // CPPUNIT_ASSERT(tracker_1_worker->trigger_success()); // CPPUNIT_ASSERT(tracker_1.state().success_counter() == (i + 1)); // } // CPPUNIT_ASSERT(verify_did_internal_error(std::bind(&torrent::TrackerList::send_event, &tracker_list, tracker_1, torrent::tracker::TrackerState::EVENT_NONE), true)); // CPPUNIT_ASSERT(tracker_1_worker->trigger_success()); // cached_time += rak::timer::from_seconds(1000); // for (unsigned int i = 0; i < 9; i++) { // CPPUNIT_ASSERT(verify_did_internal_error(std::bind(&torrent::TrackerList::send_event, &tracker_list, tracker_foo, torrent::tracker::TrackerState::EVENT_NONE), false)); // CPPUNIT_ASSERT(tracker_foo_worker->trigger_success()); // CPPUNIT_ASSERT(tracker_foo.state().success_counter() == (i + 1)); // CPPUNIT_ASSERT(tracker_foo->is_usable()); // } // CPPUNIT_ASSERT(verify_did_internal_error(std::bind(&torrent::TrackerList::send_event, &tracker_list, tracker_foo, torrent::tracker::TrackerState::EVENT_NONE), true)); // CPPUNIT_ASSERT(tracker_foo_worker->trigger_success()); // for (unsigned int i = 0; i < 40; i++) { // CPPUNIT_ASSERT(verify_did_internal_error(std::bind(&torrent::TrackerList::send_event, &tracker_list, tracker_2, torrent::tracker::TrackerState::EVENT_NONE), false)); // CPPUNIT_ASSERT(tracker_2_worker->trigger_success()); // CPPUNIT_ASSERT(tracker_2.state().success_counter() == (i + 1)); // cached_time += rak::timer::from_seconds(1); // } // for (unsigned int i = 0; i < 17; i++) { // CPPUNIT_ASSERT(verify_did_internal_error(std::bind(&torrent::TrackerList::send_event, &tracker_list, tracker_3, torrent::tracker::TrackerState::EVENT_NONE), false)); // CPPUNIT_ASSERT(tracker_3_worker->trigger_success()); // CPPUNIT_ASSERT(tracker_3.state().success_counter() == (i + 1)); // if (i % 2) // cached_time += rak::timer::from_seconds(1); // } // CPPUNIT_ASSERT(verify_did_internal_error(std::bind(&torrent::TrackerList::send_event, &tracker_list, tracker_3, torrent::tracker::TrackerState::EVENT_NONE), true)); // CPPUNIT_ASSERT(tracker_3_worker->trigger_success()); // TRACKER_LIST_CLEANUP(); } libtorrent-0.16.11/test/torrent/object_test_utils.h0000644000000000000000000000142215175073411016050 #include #include "torrent/object.h" torrent::Object create_bencode(const char* str); torrent::Object create_bencode_c(const char* str); inline torrent::Object create_bencode_raw_bencode_c(const char* str) { return torrent::raw_bencode(str, std::strlen(str)); } inline torrent::Object create_bencode_raw_string_c(const char* str) { return torrent::raw_string(str, std::strlen(str)); } inline torrent::Object create_bencode_raw_list_c(const char* str) { return torrent::raw_list(str, std::strlen(str)); } inline torrent::Object create_bencode_raw_map_c(const char* str) { return torrent::raw_map(str, std::strlen(str)); } bool validate_bencode(const char* first, const char* last); bool compare_bencode(const torrent::Object& obj, const char* str, uint32_t skip_mask = 0); libtorrent-0.16.11/test/torrent/object_test_utils.cc0000644000000000000000000000270615175073411016214 #include "config.h" #include #include #include "torrent/object_stream.h" #include "object_test_utils.h" torrent::Object create_bencode(const char* str) { torrent::Object obj; std::stringstream stream(str); stream >> obj; CPPUNIT_ASSERT(!stream.fail()); return obj; } torrent::Object create_bencode_c(const char* str) { torrent::Object obj; const char* last = str + strlen(str); CPPUNIT_ASSERT(object_read_bencode_c(str, last, &obj) == last); return obj; } // torrent::Object // create_bencode_raw_bencode_c(const char* str) { // torrent::Object obj; // const char* last = str + strlen(str); // CPPUNIT_ASSERT(object_read_bencode_skip_c(str, last) == last); // return torrent::raw_bencode(str, std::distance(str, last)); // } // torrent::Object // create_bencode_raw_list_c(const char* str) { // torrent::Object obj; // const char* last = str + strlen(str); // CPPUNIT_ASSERT(object_read_bencode_skip_c(str, last) == last); // return torrent::raw_bencode(str, std::distance(str, last)); // } bool validate_bencode(const char* first, const char* last) { torrent::Object obj; return object_read_bencode_c(first, last, &obj) == last; } bool compare_bencode(const torrent::Object& obj, const char* str, uint32_t skip_mask) { char buffer[256]; std::memset(buffer, 0, 256); torrent::object_write_bencode(buffer, buffer + 256, &obj, skip_mask); return strcmp(buffer, str) == 0; } libtorrent-0.16.11/test/torrent/test_tracker_list.h0000644000000000000000000001172615175073411016060 #include "test/helpers/test_main_thread.h" #include "test/helpers/tracker_test.h" #include "torrent/download_info.h" class TestTrackerList : public TestFixtureWithMainNetTrackerThread { CPPUNIT_TEST_SUITE(TestTrackerList); CPPUNIT_TEST(test_basic); CPPUNIT_TEST(test_enable); CPPUNIT_TEST(test_close); CPPUNIT_TEST(test_tracker_flags); CPPUNIT_TEST(test_find_url); CPPUNIT_TEST(test_can_scrape); CPPUNIT_TEST(test_single_success); CPPUNIT_TEST(test_single_failure); CPPUNIT_TEST(test_single_closing); CPPUNIT_TEST(test_multiple_success); CPPUNIT_TEST(test_scrape_success); CPPUNIT_TEST(test_scrape_failure); CPPUNIT_TEST(test_has_active); CPPUNIT_TEST_SUITE_END(); public: void test_basic(); void test_enable(); void test_close(); void test_tracker_flags(); void test_find_url(); void test_can_scrape(); void test_single_success(); void test_single_failure(); void test_single_closing(); void test_multiple_success(); void test_scrape_success(); void test_scrape_failure(); void test_has_active(); }; bool check_has_active_in_group(const torrent::TrackerList* tracker_list, const char* states, bool scrape); struct TestTrackerListWrapper { TestTrackerListWrapper(torrent::TrackerList* tracker_list) : m_tracker_list(tracker_list) {} void set_info(torrent::DownloadInfo* info) { m_tracker_list->set_info(info); } torrent::TrackerList* m_tracker_list; }; #define TRACKER_LIST_SETUP() \ torrent::DownloadInfo download_info; \ torrent::TrackerList tracker_list; \ TestTrackerListWrapper(&tracker_list).set_info(&download_info); \ \ int success_counter = 0; \ int failure_counter = 0; \ int scrape_success_counter = 0; \ int scrape_failure_counter = 0; \ \ tracker_list.slot_success() = std::bind(&increment_value_uint, &success_counter); \ tracker_list.slot_failure() = std::bind(&increment_value_void, &failure_counter); \ tracker_list.slot_scrape_success() = std::bind(&increment_value_void, &scrape_success_counter); \ tracker_list.slot_scrape_failure() = std::bind(&increment_value_void, &scrape_failure_counter); #define TRACKER_INSERT(group, name) \ auto name = TrackerTest::new_tracker(&tracker_list, ""); \ TrackerTest::insert_tracker(&tracker_list, group, name); #define TEST_TRACKER_IS_BUSY(tracker, state) \ CPPUNIT_ASSERT(state == '0' || tracker.is_busy()); \ CPPUNIT_ASSERT(state == '1' || !tracker.is_busy()); #define TEST_MULTI3_IS_BUSY(original, rearranged) \ TEST_TRACKER_IS_BUSY(tracker_0_0, original[0]); \ TEST_TRACKER_IS_BUSY(tracker_0_1, original[1]); \ TEST_TRACKER_IS_BUSY(tracker_1_0, original[2]); \ TEST_TRACKER_IS_BUSY(tracker_2_0, original[3]); \ TEST_TRACKER_IS_BUSY(tracker_3_0, original[4]); \ TEST_TRACKER_IS_BUSY(tracker_list.at(0), rearranged[0]); \ TEST_TRACKER_IS_BUSY(tracker_list.at(1), rearranged[1]); \ TEST_TRACKER_IS_BUSY(tracker_list.at(2), rearranged[2]); \ TEST_TRACKER_IS_BUSY(tracker_list.at(3), rearranged[3]); \ TEST_TRACKER_IS_BUSY(tracker_list.at(4), rearranged[4]); #define TEST_GROUP_IS_BUSY(original, rearranged) \ TEST_TRACKER_IS_BUSY(tracker_0_0, original[0]); \ TEST_TRACKER_IS_BUSY(tracker_0_1, original[1]); \ TEST_TRACKER_IS_BUSY(tracker_0_2, original[2]); \ TEST_TRACKER_IS_BUSY(tracker_1_0, original[3]); \ TEST_TRACKER_IS_BUSY(tracker_1_1, original[4]); \ TEST_TRACKER_IS_BUSY(tracker_2_0, original[5]); \ TEST_TRACKER_IS_BUSY(tracker_list.at(0), rearranged[0]); \ TEST_TRACKER_IS_BUSY(tracker_list.at(1), rearranged[1]); \ TEST_TRACKER_IS_BUSY(tracker_list.at(2), rearranged[2]); \ TEST_TRACKER_IS_BUSY(tracker_list.at(3), rearranged[3]); \ TEST_TRACKER_IS_BUSY(tracker_list.at(4), rearranged[4]); \ TEST_TRACKER_IS_BUSY(tracker_list.at(5), rearranged[5]); #define TEST_TRACKERS_IS_BUSY_5(original, rearranged) \ TEST_TRACKER_IS_BUSY(tracker_0, original[0]); \ TEST_TRACKER_IS_BUSY(tracker_1, original[1]); \ TEST_TRACKER_IS_BUSY(tracker_2, original[2]); \ TEST_TRACKER_IS_BUSY(tracker_3, original[3]); \ TEST_TRACKER_IS_BUSY(tracker_4, original[4]); \ TEST_TRACKER_IS_BUSY(tracker_list.at(0), rearranged[0]); \ TEST_TRACKER_IS_BUSY(tracker_list.at(1), rearranged[1]); \ TEST_TRACKER_IS_BUSY(tracker_list.at(2), rearranged[2]); \ TEST_TRACKER_IS_BUSY(tracker_list.at(3), rearranged[3]); \ TEST_TRACKER_IS_BUSY(tracker_list.at(4), rearranged[4]); libtorrent-0.16.11/test/torrent/test_tracker_controller_features.cc0000644000000000000000000003312315175073411021317 #include "config.h" #include "test/torrent/test_tracker_controller_features.h" #include #include #include "test/helpers/test_thread.h" #include "test/torrent/test_tracker_controller.h" #include "test/torrent/test_tracker_list.h" #include "src/tracker/thread_tracker.h" CPPUNIT_TEST_SUITE_REGISTRATION(test_tracker_controller_features); void test_tracker_controller_features::test_requesting_basic() { TEST_MULTI3_BEGIN(); TEST_SEND_SINGLE_BEGIN(update); auto tracker_0_0_worker = TrackerTest::test_worker(tracker_0_0); auto tracker_1_0_worker = TrackerTest::test_worker(tracker_1_0); auto tracker_2_0_worker = TrackerTest::test_worker(tracker_2_0); auto tracker_3_0_worker = TrackerTest::test_worker(tracker_3_0); CPPUNIT_ASSERT(tracker_0_0_worker->trigger_success(8, 9)); tracker_controller.start_requesting(); CPPUNIT_ASSERT(test_goto_next_timeout(this, &tracker_controller, 0)); TEST_MULTI3_IS_BUSY("00111", "00111"); CPPUNIT_ASSERT(tracker_1_0_worker->trigger_success()); CPPUNIT_ASSERT(tracker_2_0_worker->trigger_success()); CPPUNIT_ASSERT(tracker_3_0_worker->trigger_success()); // TODO: Change this so that requesting state results in tracker // requests from many peers. Also, add a limit so we don't keep // requesting from spent trackers. // Next timeout should be soon... CPPUNIT_ASSERT(test_goto_next_timeout(this, &tracker_controller, 30)); TEST_MULTI3_IS_BUSY("00000", "00000"); CPPUNIT_ASSERT(test_goto_next_timeout(this, &tracker_controller, tracker_0_0.state().min_interval() - 30)); TEST_MULTI3_IS_BUSY("10111", "10111"); CPPUNIT_ASSERT(tracker_0_0_worker->trigger_success()); CPPUNIT_ASSERT(tracker_1_0_worker->trigger_success()); CPPUNIT_ASSERT(tracker_2_0_worker->trigger_success()); CPPUNIT_ASSERT(tracker_3_0_worker->trigger_success()); tracker_controller.stop_requesting(); TEST_MULTIPLE_END(8, 0); } void test_tracker_controller_features::test_requesting_timeout() { TEST_MULTI3_BEGIN(); TEST_SEND_SINGLE_BEGIN(update); tracker_controller.start_requesting(); CPPUNIT_ASSERT(test_goto_next_timeout(this, &tracker_controller, 0)); TEST_MULTI3_IS_BUSY("10111", "10111"); auto tracker_0_0_worker = TrackerTest::test_worker(tracker_0_0); auto tracker_0_1_worker = TrackerTest::test_worker(tracker_0_1); auto tracker_1_0_worker = TrackerTest::test_worker(tracker_1_0); auto tracker_2_0_worker = TrackerTest::test_worker(tracker_2_0); auto tracker_3_0_worker = TrackerTest::test_worker(tracker_3_0); CPPUNIT_ASSERT(tracker_0_0_worker->trigger_failure()); auto next_timeout_1 = tracker_controller.seconds_to_next_timeout(); CPPUNIT_ASSERT(next_timeout_1 == 5 || next_timeout_1 == 6); // CPPUNIT_ASSERT(tracker_0_1_worker->trigger_failure()); CPPUNIT_ASSERT(tracker_1_0_worker->trigger_failure()); CPPUNIT_ASSERT(tracker_2_0_worker->trigger_failure()); CPPUNIT_ASSERT(tracker_3_0_worker->trigger_failure()); // CPPUNIT_ASSERT(test_goto_next_timeout(this, &tracker_controller, 0)); TEST_MULTI3_IS_BUSY("01000", "01000"); CPPUNIT_ASSERT(test_goto_next_timeout(this, &tracker_controller, 5)); TEST_MULTI3_IS_BUSY("01111", "01111"); CPPUNIT_ASSERT(!tracker_controller.is_timeout_queued()); CPPUNIT_ASSERT(tracker_0_1_worker->trigger_success()); auto next_timeout_2 = tracker_controller.seconds_to_next_timeout(); CPPUNIT_ASSERT(next_timeout_2 == 30 || next_timeout_2 == 31); TEST_MULTIPLE_END(1, 4); } void test_tracker_controller_features::test_promiscious_timeout() { TEST_MULTI3_BEGIN(); TEST_SEND_SINGLE_BEGIN(start); CPPUNIT_ASSERT(test_goto_next_timeout(this, &tracker_controller, 3)); TEST_MULTI3_IS_BUSY("10111", "10111"); CPPUNIT_ASSERT(!tracker_controller.is_timeout_queued()); auto tracker_0_0_worker = TrackerTest::test_worker(tracker_0_0); auto tracker_1_0_worker = TrackerTest::test_worker(tracker_1_0); auto tracker_2_0_worker = TrackerTest::test_worker(tracker_2_0); auto tracker_3_0_worker = TrackerTest::test_worker(tracker_3_0); CPPUNIT_ASSERT(tracker_0_0_worker->trigger_success()); CPPUNIT_ASSERT(!(tracker_controller.flags() & torrent::TrackerController::flag_promiscuous_mode)); // CPPUNIT_ASSERT(tracker_0_1_worker->trigger_success()); CPPUNIT_ASSERT(tracker_1_0_worker->trigger_success()); CPPUNIT_ASSERT(tracker_2_0_worker->trigger_success()); CPPUNIT_ASSERT(!tracker_controller.is_timeout_queued()); CPPUNIT_ASSERT(tracker_3_0_worker->trigger_success()); CPPUNIT_ASSERT(test_goto_next_timeout(this, &tracker_controller, tracker_0_0.state().normal_interval())); TEST_MULTIPLE_END(4, 0); } // Fix failure event handler so that it properly handles multi-request // situations. This includes fixing old tests. void test_tracker_controller_features::test_promiscious_failed() { TEST_MULTI3_BEGIN(); TEST_SEND_SINGLE_BEGIN(start); auto tracker_0_0_worker = TrackerTest::test_worker(tracker_0_0); [[maybe_unused]] auto tracker_0_1_worker = TrackerTest::test_worker(tracker_0_1); [[maybe_unused]] auto tracker_1_0_worker = TrackerTest::test_worker(tracker_1_0); auto tracker_2_0_worker = TrackerTest::test_worker(tracker_2_0); auto tracker_3_0_worker = TrackerTest::test_worker(tracker_3_0); CPPUNIT_ASSERT(tracker_0_0_worker->trigger_failure()); CPPUNIT_ASSERT((tracker_controller.flags() & torrent::TrackerController::flag_promiscuous_mode)); TEST_MULTI3_IS_BUSY("01111", "01111"); CPPUNIT_ASSERT(tracker_controller.is_timeout_queued()); CPPUNIT_ASSERT(tracker_3_0_worker->trigger_failure()); test_tracker_step_time(this, 2); TEST_MULTI3_IS_BUSY("01110", "01110"); CPPUNIT_ASSERT(tracker_2_0_worker->trigger_failure()); test_tracker_step_time(this, 0); TEST_MULTI3_IS_BUSY("01100", "01100"); CPPUNIT_ASSERT(test_goto_next_timeout(this, &tracker_controller, 3 - 1)); TEST_MULTIPLE_END(0, 3); // TODO: This is now failing after cached_time deprecation, and we already need to rewrite more // tracker code so skip for now. // TEST_MULTI3_IS_BUSY("01101", "01101"); // CPPUNIT_ASSERT(tracker_0_1_worker->trigger_failure()); // CPPUNIT_ASSERT(tracker_1_0_worker->trigger_failure()); // CPPUNIT_ASSERT(tracker_3_0_worker->trigger_failure()); // CPPUNIT_ASSERT(tracker_0_0_worker->trigger_failure()); // CPPUNIT_ASSERT(!tracker_list.has_active()); // CPPUNIT_ASSERT(tracker_controller.is_timeout_queued()); // TEST_MULTIPLE_END(0, 7); } void test_tracker_controller_features::test_scrape_basic() { TEST_GROUP_BEGIN(); tracker_controller.disable(); auto tracker_0_1_worker = TrackerTest::test_worker(tracker_0_1); auto tracker_0_2_worker = TrackerTest::test_worker(tracker_0_2); auto tracker_2_0_worker = TrackerTest::test_worker(tracker_2_0); CPPUNIT_ASSERT(!tracker_controller.is_scrape_queued()); tracker_0_1_worker->set_scrapable(); tracker_0_2_worker->set_scrapable(); tracker_2_0_worker->set_scrapable(); tracker_controller.scrape_request(0); TEST_GROUP_IS_BUSY("000000", "000000"); CPPUNIT_ASSERT(!tracker_controller.is_timeout_queued()); CPPUNIT_ASSERT(tracker_controller.is_scrape_queued()); CPPUNIT_ASSERT(tracker_0_1.state().latest_event() == torrent::tracker::TrackerState::EVENT_NONE); CPPUNIT_ASSERT(tracker_0_2.state().latest_event() == torrent::tracker::TrackerState::EVENT_NONE); CPPUNIT_ASSERT(tracker_2_0.state().latest_event() == torrent::tracker::TrackerState::EVENT_NONE); TEST_GOTO_NEXT_SCRAPE(0); TEST_GROUP_IS_BUSY("010001", "010001"); CPPUNIT_ASSERT(!tracker_controller.is_timeout_queued()); CPPUNIT_ASSERT(!tracker_controller.is_scrape_queued()); CPPUNIT_ASSERT(tracker_0_1.state().latest_event() == torrent::tracker::TrackerState::EVENT_SCRAPE); CPPUNIT_ASSERT(tracker_0_2.state().latest_event() == torrent::tracker::TrackerState::EVENT_NONE); CPPUNIT_ASSERT(tracker_2_0.state().latest_event() == torrent::tracker::TrackerState::EVENT_SCRAPE); CPPUNIT_ASSERT(tracker_0_1_worker->trigger_scrape()); CPPUNIT_ASSERT(tracker_2_0_worker->trigger_scrape()); TEST_GROUP_IS_BUSY("000000", "000000"); CPPUNIT_ASSERT(!tracker_controller.is_timeout_queued()); CPPUNIT_ASSERT(!tracker_controller.is_scrape_queued()); CPPUNIT_ASSERT(tracker_0_1.state().scrape_time_last() != 0); CPPUNIT_ASSERT(tracker_0_2.state().scrape_time_last() == 0); CPPUNIT_ASSERT(tracker_2_0.state().scrape_time_last() != 0); TEST_MULTIPLE_END(0, 0); } void test_tracker_controller_features::test_scrape_priority() { TEST_SINGLE_BEGIN(); CPPUNIT_ASSERT(test_goto_next_timeout(this, &tracker_controller, 0)); auto tracker_0_0_worker = TrackerTest::test_worker(tracker_0_0); tracker_0_0_worker->trigger_success(); tracker_0_0_worker->set_scrapable(); tracker_controller.scrape_request(0); TEST_GOTO_NEXT_SCRAPE(0); CPPUNIT_ASSERT(tracker_0_0.is_busy()); CPPUNIT_ASSERT(tracker_0_0.state().latest_event() == torrent::tracker::TrackerState::EVENT_SCRAPE); // Check the other event types too? tracker_controller.send_update_event(); CPPUNIT_ASSERT(tracker_0_0.is_busy()); CPPUNIT_ASSERT(tracker_0_0.state().latest_event() == torrent::tracker::TrackerState::EVENT_NONE); CPPUNIT_ASSERT(tracker_controller.is_timeout_queued()); CPPUNIT_ASSERT(!tracker_controller.is_scrape_queued()); tracker_0_0_worker->trigger_success(); CPPUNIT_ASSERT(tracker_controller.seconds_to_next_timeout() > 1); test_tracker_step_time(this, tracker_controller.seconds_to_next_timeout() - 1); tracker_controller.scrape_request(0); TEST_GOTO_NEXT_SCRAPE(0); TEST_SINGLE_END(2, 0); // test_tracker_step_time(this, 0); // CPPUNIT_ASSERT(tracker_0_0.is_busy()); // CPPUNIT_ASSERT(tracker_0_0.state().latest_event() == torrent::tracker::TrackerState::EVENT_SCRAPE); // CPPUNIT_ASSERT(test_goto_next_timeout(this, &tracker_controller, 1)); // CPPUNIT_ASSERT(tracker_0_0.is_busy()); // CPPUNIT_ASSERT(tracker_0_0.state().latest_event() == torrent::tracker::TrackerState::EVENT_NONE); // TEST_SINGLE_END(2, 0); } void test_tracker_controller_features::test_groups_requesting() { TEST_GROUP_BEGIN(); TEST_SEND_SINGLE_BEGIN(start); // CPPUNIT_ASSERT(tracker_0_0_worker->trigger_success(10, 20)); tracker_controller.start_requesting(); CPPUNIT_ASSERT(test_goto_next_timeout(this, &tracker_controller, 0)); TEST_GROUP_IS_BUSY("100101", "100101"); auto tracker_0_0_worker = TrackerTest::test_worker(tracker_0_0); auto tracker_1_0_worker = TrackerTest::test_worker(tracker_1_0); auto tracker_2_0_worker = TrackerTest::test_worker(tracker_2_0); CPPUNIT_ASSERT(tracker_0_0_worker->trigger_success()); CPPUNIT_ASSERT(tracker_1_0_worker->trigger_success()); CPPUNIT_ASSERT(tracker_2_0_worker->trigger_success()); // TODO: Change this so that requesting state results in tracker // requests from many peers. Also, add a limit so we don't keep // requesting from spent trackers. // Next timeout should be soon... CPPUNIT_ASSERT(test_goto_next_timeout(this, &tracker_controller, 30)); TEST_GROUP_IS_BUSY("000000", "000000"); CPPUNIT_ASSERT(test_goto_next_timeout(this, &tracker_controller, tracker_0_0.state().min_interval() - 30)); TEST_GROUP_IS_BUSY("100101", "100101"); CPPUNIT_ASSERT(tracker_0_0_worker->trigger_success()); CPPUNIT_ASSERT(tracker_1_0_worker->trigger_success()); CPPUNIT_ASSERT(tracker_2_0_worker->trigger_success()); // Once we've requested twice, it should stop requesting from that tier. CPPUNIT_ASSERT(test_goto_next_timeout(this, &tracker_controller, 30)); TEST_GROUP_IS_BUSY("000000", "000000"); tracker_controller.stop_requesting(); TEST_MULTIPLE_END(6, 0); } void test_tracker_controller_features::test_groups_scrape() { TEST_GROUP_BEGIN(); tracker_controller.disable(); auto tracker_0_0_worker = TrackerTest::test_worker(tracker_0_0); auto tracker_0_1_worker = TrackerTest::test_worker(tracker_0_1); auto tracker_0_2_worker = TrackerTest::test_worker(tracker_0_2); auto tracker_1_0_worker = TrackerTest::test_worker(tracker_1_0); auto tracker_1_1_worker = TrackerTest::test_worker(tracker_1_1); auto tracker_2_0_worker = TrackerTest::test_worker(tracker_2_0); tracker_0_0_worker->set_scrapable(); tracker_0_1_worker->set_scrapable(); tracker_0_2_worker->set_scrapable(); tracker_1_0_worker->set_scrapable(); tracker_1_1_worker->set_scrapable(); tracker_2_0_worker->set_scrapable(); CPPUNIT_ASSERT(!tracker_controller.is_scrape_queued()); tracker_controller.scrape_request(0); TEST_GROUP_IS_BUSY("000000", "000000"); TEST_GOTO_NEXT_SCRAPE(0); CPPUNIT_ASSERT(tracker_0_0.state().latest_event() == torrent::tracker::TrackerState::EVENT_SCRAPE); CPPUNIT_ASSERT(tracker_0_1.state().latest_event() == torrent::tracker::TrackerState::EVENT_NONE); CPPUNIT_ASSERT(tracker_0_2.state().latest_event() == torrent::tracker::TrackerState::EVENT_NONE); CPPUNIT_ASSERT(tracker_1_0.state().latest_event() == torrent::tracker::TrackerState::EVENT_SCRAPE); CPPUNIT_ASSERT(tracker_1_1.state().latest_event() == torrent::tracker::TrackerState::EVENT_NONE); CPPUNIT_ASSERT(tracker_2_0.state().latest_event() == torrent::tracker::TrackerState::EVENT_SCRAPE); TEST_GROUP_IS_BUSY("100101", "100101"); CPPUNIT_ASSERT(tracker_0_0_worker->trigger_scrape()); CPPUNIT_ASSERT(tracker_1_0_worker->trigger_scrape()); CPPUNIT_ASSERT(tracker_2_0_worker->trigger_scrape()); // Test with a non-can_scrape !busy tracker? // TEST_GROUP_IS_BUSY("100101", "100101"); // CPPUNIT_ASSERT(tracker_0_0_worker->trigger_scrape()); // CPPUNIT_ASSERT(tracker_0_1_worker->trigger_scrape()); // CPPUNIT_ASSERT(tracker_0_2_worker->trigger_scrape()); // CPPUNIT_ASSERT(tracker_1_0_worker->trigger_scrape()); // CPPUNIT_ASSERT(tracker_1_1_worker->trigger_scrape()); // CPPUNIT_ASSERT(tracker_2_0_worker->trigger_scrape()); TEST_GROUP_IS_BUSY("000000", "000000"); TEST_MULTIPLE_END(0, 0); } libtorrent-0.16.11/test/torrent/object_static_map_test.cc0000644000000000000000000003303715175073411017201 #include "config.h" #include #include #include "torrent/object_static_map.h" #include "protocol/extensions.h" #include "object_test_utils.h" #include "object_static_map_test.h" CPPUNIT_TEST_SUITE_REGISTRATION(ObjectStaticMapTest); // Possible bencode keys in a DHT message. enum keys { key_d_a, key_d_d_a, key_d_b, key_e_0, key_e_1, key_e_2, key_s_a, key_s_b, key_v_a, key_v_b, key_LAST, }; enum keys_2 { key_2_d_x_y, key_2_d_x_z, key_2_l_x_1, key_2_l_x_2, key_2_s_a, key_2_v_a, key_2_LAST }; typedef torrent::static_map_type test_map_type; typedef torrent::static_map_type test_map_2_type; // List of all possible keys we need/support in a DHT message. // Unsupported keys we receive are dropped (ignored) while decoding. // See torrent/object_static_map.h for how this works. template <> const test_map_type::key_list_type test_map_type::keys = { { key_d_a, "d_a::b" }, { key_d_d_a, "d_a::c::a" }, { key_d_b, "d_a::d" }, { key_e_0, "e[]" }, { key_e_1, "e[]" }, { key_e_2, "e[]" }, { key_s_a, "s_a" }, { key_s_b, "s_b" }, { key_v_a, "v_a" }, { key_v_b, "v_b" }, }; template <> const test_map_2_type::key_list_type test_map_2_type::keys = { { key_2_d_x_y, "d_x::f" }, { key_2_d_x_z, "d_x::g" }, { key_2_l_x_1, "l_x[]" }, { key_2_l_x_2, "l_x[]" }, { key_2_s_a, "s_a" }, { key_2_v_a, "v_a" }, }; void ObjectStaticMapTest::test_basics() { test_map_type test_map; test_map[key_v_a] = int64_t(1); test_map[key_v_b] = int64_t(2); test_map[key_s_a] = std::string("a"); test_map[key_s_b] = std::string("b"); CPPUNIT_ASSERT(test_map[key_v_a].as_value() == 1); CPPUNIT_ASSERT(test_map[key_v_b].as_value() == 2); CPPUNIT_ASSERT(test_map[key_s_a].as_string() == "a"); CPPUNIT_ASSERT(test_map[key_s_b].as_string() == "b"); } void ObjectStaticMapTest::test_write() { test_map_type test_map; test_map[key_v_a] = int64_t(1); test_map[key_v_b] = int64_t(2); test_map[key_s_a] = std::string("a"); // test_map[key_s_b] = std::string("b"); test_map[key_d_a] = std::string("xx"); test_map[key_d_d_a] = std::string("a"); test_map[key_d_b] = std::string("yy"); test_map[key_e_0] = std::string("f"); test_map[key_e_1] = torrent::object_create_raw_bencode_c_str("1:g"); test_map[key_e_2] = std::string("h"); char buffer[1024]; torrent::object_buffer_t result = torrent::static_map_write_bencode_c(torrent::object_write_to_buffer, NULL, std::make_pair(buffer, buffer + sizeof(buffer)), test_map); // std::cout << "static map write: '" << std::string(buffer, std::distance(buffer, result.first)) << "'" << std::endl; CPPUNIT_ASSERT(validate_bencode(buffer, result.first)); } static const char* test_read_bencode = "d3:d_xd1:fi3e1:gli4ei5eee3:l_xli1ei2ei3ee3:s_a1:a3:v_ai2ee"; static const char* test_read_skip_bencode = "d3:d_xd1:fi3e1:gli4ei5eee1:fi1e3:l_xli1ei2ei3ee3:s_a1:a3:v_ai2ee"; template bool static_map_read_bencode(map_type& map, const char* str) { try { return torrent::static_map_read_bencode(str, str + strlen(str), map) == str + strlen(str); } catch (const torrent::bencode_error&) { return false; } } template bool static_map_read_bencode_exception(map_type& map, const char* str) { try { torrent::static_map_read_bencode(str, str + strlen(str), map); return false; } catch (const torrent::bencode_error&) { return true; } } void ObjectStaticMapTest::test_read() { test_map_2_type test_map; CPPUNIT_ASSERT(static_map_read_bencode(test_map, test_read_bencode)); CPPUNIT_ASSERT(test_map[key_2_d_x_y].as_value() == 3); CPPUNIT_ASSERT(test_map[key_2_d_x_z].as_list().size() == 2); CPPUNIT_ASSERT(test_map[key_2_l_x_1].as_value() == 1); CPPUNIT_ASSERT(test_map[key_2_l_x_2].as_value() == 2); CPPUNIT_ASSERT(test_map[key_2_s_a].as_string() == "a"); CPPUNIT_ASSERT(test_map[key_2_v_a].as_value() == 2); test_map_2_type test_skip_map; CPPUNIT_ASSERT(static_map_read_bencode(test_skip_map, test_read_skip_bencode)); } enum ext_test_keys { key_e, // key_m_utMetadata, key_m_utPex, // key_metadataSize, key_p, key_reqq, key_v, key_test_LAST }; typedef torrent::static_map_type ext_test_message; template <> const ext_test_message::key_list_type ext_test_message::keys = { { key_e, "e" }, { key_m_utPex, "m::ut_pex" }, { key_p, "p" }, { key_reqq, "reqq" }, { key_v, "v" }, }; void ObjectStaticMapTest::test_read_extensions() { ext_test_message test_ext; CPPUNIT_ASSERT(static_map_read_bencode(test_ext, "d1:ai1ee")); CPPUNIT_ASSERT(static_map_read_bencode(test_ext, "d1:mi1ee")); CPPUNIT_ASSERT(static_map_read_bencode(test_ext, "d1:mdee")); CPPUNIT_ASSERT(static_map_read_bencode(test_ext, "d6:ut_pexi0ee")); CPPUNIT_ASSERT(static_map_read_bencode(test_ext, "d1:md6:ut_pexi0eee")); } template bool static_map_write_bencode(map_type map, const char* original) { try { char buffer[1024]; char* last = torrent::static_map_write_bencode_c(&torrent::object_write_to_buffer, NULL, torrent::object_buffer_t(buffer, buffer + 1024), map).first; return std::strncmp(buffer, original, std::distance(buffer, last)) == 0; } catch (const torrent::bencode_error&) { return false; } } // // Proper unit tests: // enum keys_empty { key_empty_LAST }; enum keys_single { key_single_a, key_single_LAST }; enum keys_raw { key_raw_a, key_raw_LAST }; enum keys_raw_types { key_raw_types_empty, key_raw_types_list, key_raw_types_map, key_raw_types_str, key_raw_types_LAST}; enum keys_multiple { key_multiple_a, key_multiple_b, key_multiple_c, key_multiple_LAST }; enum keys_dict { key_dict_a_b, key_dict_LAST }; typedef torrent::static_map_type test_empty_type; typedef torrent::static_map_type test_single_type; typedef torrent::static_map_type test_raw_type; typedef torrent::static_map_type test_raw_types_type; typedef torrent::static_map_type test_multiple_type; typedef torrent::static_map_type test_dict_type; template <> const test_empty_type::key_list_type test_empty_type::keys = { }; template <> const test_single_type::key_list_type test_single_type::keys = { { key_single_a, "b" } }; template <> const test_raw_type::key_list_type test_raw_type::keys = { { key_raw_a, "b*" } }; template <> const test_raw_types_type::key_list_type test_raw_types_type::keys = { { key_raw_types_empty, "e*"}, { key_raw_types_list, "l*L"}, { key_raw_types_map, "m*M"}, { key_raw_types_str, "s*S"} }; template <> const test_multiple_type::key_list_type test_multiple_type::keys = { { key_multiple_a, "a" }, { key_multiple_b, "b*" }, { key_multiple_c, "c" } }; template <> const test_dict_type::key_list_type test_dict_type::keys = { { key_dict_a_b, "a::b" } }; void ObjectStaticMapTest::test_read_empty() { test_empty_type map_normal; test_empty_type map_skip; test_empty_type map_incomplete; CPPUNIT_ASSERT(static_map_read_bencode(map_normal, "de")); CPPUNIT_ASSERT(static_map_read_bencode(map_skip, "d1:ai1ee")); CPPUNIT_ASSERT(static_map_read_bencode_exception(map_incomplete, "")); CPPUNIT_ASSERT(static_map_read_bencode_exception(map_incomplete, "d")); } void ObjectStaticMapTest::test_read_single() { test_single_type map_normal; test_single_type map_skip; test_single_type map_incomplete; CPPUNIT_ASSERT(static_map_read_bencode(map_normal, "d1:bi1ee")); CPPUNIT_ASSERT(map_normal[key_single_a].as_value() == 1); CPPUNIT_ASSERT(static_map_read_bencode(map_skip, "d1:ai0e1:bi1e1:ci2ee")); CPPUNIT_ASSERT(map_skip[key_single_a].as_value() == 1); CPPUNIT_ASSERT(static_map_read_bencode_exception(map_incomplete, "d")); CPPUNIT_ASSERT(static_map_read_bencode_exception(map_incomplete, "d1:b")); CPPUNIT_ASSERT(static_map_read_bencode_exception(map_incomplete, "d1:bi1")); CPPUNIT_ASSERT(static_map_read_bencode_exception(map_incomplete, "d1:bi1e")); } void ObjectStaticMapTest::test_read_single_raw() { test_raw_type map_raw; CPPUNIT_ASSERT(static_map_read_bencode(map_raw, "d1:bi1ee")); CPPUNIT_ASSERT(torrent::raw_bencode_equal_c_str(map_raw[key_raw_a].as_raw_bencode(), "i1e")); CPPUNIT_ASSERT(static_map_read_bencode(map_raw, "d1:b2:abe")); CPPUNIT_ASSERT(torrent::raw_bencode_equal_c_str(map_raw[key_raw_a].as_raw_bencode(), "2:ab")); CPPUNIT_ASSERT(torrent::raw_bencode_equal_c_str(map_raw[key_raw_a].as_raw_bencode().as_raw_string(), "ab")); CPPUNIT_ASSERT(static_map_read_bencode(map_raw, "d1:bli1ei2eee")); CPPUNIT_ASSERT(torrent::raw_bencode_equal_c_str(map_raw[key_raw_a].as_raw_bencode(), "li1ei2ee")); CPPUNIT_ASSERT(torrent::raw_bencode_equal_c_str(map_raw[key_raw_a].as_raw_bencode().as_raw_list(), "i1ei2e")); CPPUNIT_ASSERT(static_map_read_bencode(map_raw, "d1:bd1:ai1e1:bi2eee")); CPPUNIT_ASSERT(torrent::raw_bencode_equal_c_str(map_raw[key_raw_a].as_raw_bencode(), "d1:ai1e1:bi2ee")); CPPUNIT_ASSERT(torrent::raw_bencode_equal_c_str(map_raw[key_raw_a].as_raw_bencode().as_raw_map(), "1:ai1e1:bi2e")); } void ObjectStaticMapTest::test_read_raw_types() { test_raw_types_type map_raw; CPPUNIT_ASSERT(static_map_read_bencode(map_raw, "d" "1:ei1e" "1:lli1ei2ee" "1:md1:ai1e1:bi2ee" "1:s2:ab" "e")); CPPUNIT_ASSERT(torrent::raw_bencode_equal_c_str(map_raw[key_raw_types_empty].as_raw_bencode(), "i1e")); CPPUNIT_ASSERT(torrent::raw_bencode_equal_c_str(map_raw[key_raw_types_str].as_raw_string(), "ab")); CPPUNIT_ASSERT(torrent::raw_bencode_equal_c_str(map_raw[key_raw_types_list].as_raw_list(), "i1ei2e")); CPPUNIT_ASSERT(torrent::raw_bencode_equal_c_str(map_raw[key_raw_types_map].as_raw_map(), "1:ai1e1:bi2e")); } void ObjectStaticMapTest::test_read_multiple() { test_multiple_type map_normal; CPPUNIT_ASSERT(static_map_read_bencode(map_normal, "d1:ai1ee")); CPPUNIT_ASSERT(map_normal[key_multiple_a].as_value() == 1); CPPUNIT_ASSERT(map_normal[key_multiple_b].is_empty()); CPPUNIT_ASSERT(map_normal[key_multiple_c].is_empty()); map_normal = test_multiple_type(); CPPUNIT_ASSERT(static_map_read_bencode(map_normal, "d1:ci3ee")); CPPUNIT_ASSERT(map_normal[key_multiple_a].is_empty()); CPPUNIT_ASSERT(map_normal[key_multiple_b].is_empty()); CPPUNIT_ASSERT(map_normal[key_multiple_c].as_value() == 3); map_normal = test_multiple_type(); CPPUNIT_ASSERT(static_map_read_bencode(map_normal, "d1:ai1e1:ci3ee")); CPPUNIT_ASSERT(map_normal[key_multiple_a].as_value() == 1); CPPUNIT_ASSERT(map_normal[key_multiple_b].is_empty()); CPPUNIT_ASSERT(map_normal[key_multiple_c].as_value() == 3); map_normal = test_multiple_type(); CPPUNIT_ASSERT(static_map_read_bencode(map_normal, "d1:ai1e1:bi2e1:ci3ee")); CPPUNIT_ASSERT(map_normal[key_multiple_a].as_value() == 1); // CPPUNIT_ASSERT(map_normal[key_multiple_b].as_raw_bencode().as_raw_value().size() == 1); // CPPUNIT_ASSERT(map_normal[key_multiple_b].as_raw_bencode().as_raw_value().data()[0] == '2'); CPPUNIT_ASSERT(map_normal[key_multiple_c].as_value() == 3); } void ObjectStaticMapTest::test_read_dict() { test_dict_type map_normal; CPPUNIT_ASSERT(static_map_read_bencode(map_normal, "d1:ai1ee")); CPPUNIT_ASSERT(map_normal[key_dict_a_b].is_empty()); CPPUNIT_ASSERT(static_map_read_bencode(map_normal, "d1:adee")); CPPUNIT_ASSERT(map_normal[key_dict_a_b].is_empty()); CPPUNIT_ASSERT(static_map_read_bencode(map_normal, "d1:ad1:bi1eee")); CPPUNIT_ASSERT(map_normal[key_dict_a_b].as_value() == 1); } void ObjectStaticMapTest::test_write_empty() { test_empty_type map_normal; CPPUNIT_ASSERT(static_map_write_bencode(map_normal, "de")); } void ObjectStaticMapTest::test_write_single() { test_single_type map_value; CPPUNIT_ASSERT(static_map_write_bencode(map_value, "de")); map_value[key_single_a] = (int64_t)1; CPPUNIT_ASSERT(static_map_write_bencode(map_value, "d1:bi1ee")); map_value[key_single_a] = "test"; CPPUNIT_ASSERT(static_map_write_bencode(map_value, "d1:b4:teste")); map_value[key_single_a] = torrent::Object::create_list(); map_value[key_single_a].as_list().emplace_back("test"); CPPUNIT_ASSERT(static_map_write_bencode(map_value, "d1:bl4:testee")); map_value[key_single_a] = torrent::raw_bencode("i1e", 3); CPPUNIT_ASSERT(static_map_write_bencode(map_value, "d1:bi1ee")); // map_value[key_single_a] = torrent::raw_value("1", 1); // CPPUNIT_ASSERT(static_map_write_bencode(map_value, "d1:bi1ee")); map_value[key_single_a] = torrent::raw_string("test", 4); CPPUNIT_ASSERT(static_map_write_bencode(map_value, "d1:b4:teste")); map_value[key_single_a] = torrent::raw_list("1:a2:bb", strlen("1:a2:bb")); CPPUNIT_ASSERT(static_map_write_bencode(map_value, "d1:bl1:a2:bbee")); map_value[key_single_a] = torrent::raw_map("1:a2:bb", strlen("1:a2:bb")); CPPUNIT_ASSERT(static_map_write_bencode(map_value, "d1:bd1:a2:bbee")); } void ObjectStaticMapTest::test_write_multiple() { // test_multiple_type map_value; // CPPUNIT_ASSERT(static_map_write_bencode(map_value, "de")); } libtorrent-0.16.11/test/torrent/test_tracker_controller.cc0000644000000000000000000005335215175073411017427 #include "config.h" #include #include "test/torrent/test_tracker_controller.h" #include "test/torrent/test_tracker_list.h" #include "test/helpers/test_main_thread.h" #include "torrent/utils/log.h" CPPUNIT_TEST_SUITE_REGISTRATION(TestTrackerController); bool test_tracker_value_in_range(uint32_t value, int32_t min, uint32_t max) { uint32_t range_min = min < 0 ? 0 : min; if (value < range_min || value > max) { lt_log_print(torrent::LOG_TRACKER_EVENTS, "test_tracker_value_in_range: %u not in range [%u, %u]", value, range_min, max); return false; } return true; } void test_tracker_step_time(TestFixtureWithMainAndTrackerThread* fixture, int32_t seconds) { fixture->m_main_thread->test_add_cached_time(std::chrono::seconds(seconds)); std::this_thread::sleep_for(50ms); fixture->m_main_thread->test_process_events_without_cached_time(); std::this_thread::sleep_for(50ms); } bool test_goto_next_timeout(TestFixtureWithMainAndTrackerThread* fixture, torrent::TrackerController* tracker_controller, uint32_t assumed_timeout, bool is_scrape) { uint32_t next_timeout = tracker_controller->is_timeout_queued() ? tracker_controller->seconds_to_next_timeout() : ~uint32_t(); uint32_t next_scrape = tracker_controller->is_scrape_queued() ? tracker_controller->seconds_to_next_scrape() : ~uint32_t(); bool result = true; std::string message; if (next_timeout == next_scrape && next_timeout == ~uint32_t()) { message = "(no timeout or scrape queued) "; result = false; } if (next_timeout < next_scrape) { if (is_scrape) { message += "ntest_process_events_without_cached_time(); CPPUNIT_ASSERT(timeout_counter == 1); TEST_SINGLE_END(0, 0); } void TestTrackerController::test_single_success() { TEST_SINGLE_BEGIN(); auto tracker_0_0_worker = TrackerTest::test_worker(tracker_0_0); tracker_list.send_event(tracker_list.at(0), torrent::tracker::TrackerState::EVENT_NONE); CPPUNIT_ASSERT(tracker_0_0_worker->trigger_success()); CPPUNIT_ASSERT(success_counter == 1 && failure_counter == 0); tracker_list.send_event(tracker_list.at(0), torrent::tracker::TrackerState::EVENT_COMPLETED); CPPUNIT_ASSERT(tracker_0_0_worker->trigger_failure()); TEST_SINGLE_END(1, 1); } #define TEST_SINGLE_FAILURE_TIMEOUT(test_interval) \ lt_log_print(torrent::LOG_TRACKER_EVENTS, "test_single_failure: main_thread->cached_time:%" PRIu64, torrent::this_thread::cached_time().count()); \ \ std::this_thread::sleep_for(100ms); \ m_main_thread->test_process_events_without_cached_time(); \ \ CPPUNIT_ASSERT(tracker_0_0_worker->trigger_failure()); \ CPPUNIT_ASSERT(tracker_controller.seconds_to_next_timeout() == test_interval); \ \ m_main_thread->test_add_cached_time(std::chrono::seconds(test_interval + 1)); void TestTrackerController::test_single_failure() { m_main_thread->test_set_cached_time(0s); TEST_SINGLE_BEGIN(); // TOOD: Need separate test handler for ThreadTracker? // TODO: Add a 'wait-for-one-event-loop' function to threads? // TODO: Add test-specific ThreadTracker that allows us to trigger process events and cached_time. auto tracker_0_0_worker = TrackerTest::test_worker(tracker_0_0); TEST_SINGLE_FAILURE_TIMEOUT(5); TEST_SINGLE_FAILURE_TIMEOUT(10); TEST_SINGLE_FAILURE_TIMEOUT(20); TEST_SINGLE_FAILURE_TIMEOUT(40); TEST_SINGLE_FAILURE_TIMEOUT(80); TEST_SINGLE_FAILURE_TIMEOUT(160); TEST_SINGLE_FAILURE_TIMEOUT(299); TEST_SINGLE_FAILURE_TIMEOUT(299); // TODO: Test with cached_time not rounded to second. TEST_SINGLE_END(0, 4); } void TestTrackerController::test_single_disable() { TEST_SINGLE_BEGIN(); tracker_list.send_event(tracker_list.at(0), torrent::tracker::TrackerState::EVENT_NONE); TEST_SINGLE_END(0, 0); } void TestTrackerController::test_send_start() { TEST_SINGLE_BEGIN(); TEST_SEND_SINGLE_BEGIN(start); auto tracker_0_0_worker = TrackerTest::test_worker(tracker_0_0); CPPUNIT_ASSERT(!tracker_controller.is_timeout_queued()); CPPUNIT_ASSERT(tracker_0_0.is_busy()); CPPUNIT_ASSERT(tracker_0_0_worker->requesting_state() == torrent::tracker::TrackerState::EVENT_STARTED); CPPUNIT_ASSERT(tracker_0_0_worker->trigger_success()); CPPUNIT_ASSERT(!(tracker_controller.flags() & torrent::TrackerController::mask_send)); CPPUNIT_ASSERT(tracker_controller.seconds_to_next_timeout() != 0); tracker_controller.send_start_event(); tracker_controller.disable(); CPPUNIT_ASSERT(!tracker_0_0.is_busy()); TEST_SEND_SINGLE_END(1, 0); } void TestTrackerController::test_send_stop_normal() { TEST_SINGLE_BEGIN(); TEST_SEND_SINGLE_BEGIN(update); auto tracker_0_0_worker = TrackerTest::test_worker(tracker_0_0); CPPUNIT_ASSERT(tracker_controller.is_timeout_queued()); CPPUNIT_ASSERT(tracker_0_0_worker->trigger_success()); tracker_controller.send_stop_event(); CPPUNIT_ASSERT((tracker_controller.flags() & torrent::TrackerController::mask_send) == torrent::TrackerController::flag_send_stop); CPPUNIT_ASSERT(tracker_controller.seconds_to_next_timeout() == 0); CPPUNIT_ASSERT(tracker_0_0_worker->trigger_success()); CPPUNIT_ASSERT((tracker_controller.flags() & torrent::TrackerController::mask_send) == 0); tracker_controller.send_stop_event(); tracker_controller.disable(); CPPUNIT_ASSERT(tracker_0_0.is_busy()); tracker_0_0_worker->trigger_success(); TEST_SEND_SINGLE_END(3, 0); } // send_stop during request and right after start, send stop failed. void TestTrackerController::test_send_completed_normal() { TEST_SINGLE_BEGIN(); TEST_SEND_SINGLE_BEGIN(update); auto tracker_0_0_worker = TrackerTest::test_worker(tracker_0_0); CPPUNIT_ASSERT(tracker_controller.is_timeout_queued()); CPPUNIT_ASSERT(tracker_0_0_worker->trigger_success()); tracker_controller.send_completed_event(); CPPUNIT_ASSERT((tracker_controller.flags() & torrent::TrackerController::mask_send) == torrent::TrackerController::flag_send_completed); CPPUNIT_ASSERT(tracker_controller.seconds_to_next_timeout() == 0); CPPUNIT_ASSERT(tracker_0_0_worker->trigger_success()); CPPUNIT_ASSERT((tracker_controller.flags() & torrent::TrackerController::mask_send) == 0); tracker_controller.send_completed_event(); tracker_controller.disable(); CPPUNIT_ASSERT(tracker_0_0.is_busy()); tracker_0_0_worker->trigger_success(); TEST_SEND_SINGLE_END(3, 0); } void TestTrackerController::test_send_update_normal() { TEST_SINGLE_BEGIN(); TEST_SEND_SINGLE_BEGIN(update); auto tracker_0_0_worker = TrackerTest::test_worker(tracker_0_0); CPPUNIT_ASSERT((tracker_controller.flags() & torrent::TrackerController::mask_send) == torrent::TrackerController::flag_send_update); CPPUNIT_ASSERT(tracker_controller.is_timeout_queued()); CPPUNIT_ASSERT(tracker_0_0.state().latest_event() == torrent::tracker::TrackerState::EVENT_NONE); CPPUNIT_ASSERT(tracker_0_0_worker->trigger_success()); TEST_SEND_SINGLE_END(1, 0); } void TestTrackerController::test_send_update_failure() { m_main_thread->test_set_cached_time(0s); TEST_SINGLE_BEGIN(); auto tracker_0_0_worker = TrackerTest::test_worker(tracker_0_0); tracker_controller.send_update_event(); TEST_SINGLE_FAILURE_TIMEOUT(5); TEST_SINGLE_FAILURE_TIMEOUT(10); TEST_SINGLE_END(0, 2); } void TestTrackerController::test_send_task_timeout() { TEST_SINGLE_BEGIN(); TEST_SEND_SINGLE_BEGIN(update); CPPUNIT_ASSERT(tracker_controller.is_timeout_queued()); TEST_SEND_SINGLE_END(0, 0); } void TestTrackerController::test_send_close_on_enable() { TRACKER_CONTROLLER_SETUP(); TRACKER_INSERT(0, tracker_0); TRACKER_INSERT(0, tracker_1); TRACKER_INSERT(0, tracker_2); TRACKER_INSERT(0, tracker_3); tracker_list.send_event(tracker_list.at(0), torrent::tracker::TrackerState::EVENT_NONE); tracker_list.send_event(tracker_list.at(1), torrent::tracker::TrackerState::EVENT_STARTED); tracker_list.send_event(tracker_list.at(2), torrent::tracker::TrackerState::EVENT_STOPPED); tracker_list.send_event(tracker_list.at(3), torrent::tracker::TrackerState::EVENT_COMPLETED); tracker_controller.enable(); CPPUNIT_ASSERT(!tracker_0.is_busy()); CPPUNIT_ASSERT(!tracker_1.is_busy()); CPPUNIT_ASSERT(!tracker_2.is_busy()); CPPUNIT_ASSERT(tracker_3.is_busy()); } void TestTrackerController::test_multiple_success() { TEST_MULTI3_BEGIN(); TEST_SEND_SINGLE_BEGIN(update); auto tracker_0_0_worker = TrackerTest::test_worker(tracker_0_0); CPPUNIT_ASSERT(tracker_0_0_worker->trigger_success()); CPPUNIT_ASSERT(test_goto_next_timeout(this, &tracker_controller, tracker_0_0.state().normal_interval())); TEST_MULTI3_IS_BUSY("10000", "10000"); CPPUNIT_ASSERT(tracker_0_0_worker->trigger_success()); CPPUNIT_ASSERT(test_goto_next_timeout(this, &tracker_controller, tracker_0_0.state().normal_interval())); TEST_MULTI3_IS_BUSY("10000", "10000"); CPPUNIT_ASSERT(tracker_0_0_worker->trigger_success()); CPPUNIT_ASSERT(!tracker_list.has_active()); CPPUNIT_ASSERT(tracker_0_0.state().success_counter() == 3); TEST_MULTIPLE_END(3, 0); } void TestTrackerController::test_multiple_failure() { TEST_MULTI3_BEGIN(); TEST_SEND_SINGLE_BEGIN(update); auto tracker_0_0_worker = TrackerTest::test_worker(tracker_0_0); auto tracker_0_1_worker = TrackerTest::test_worker(tracker_0_1); auto tracker_1_0_worker = TrackerTest::test_worker(tracker_1_0); auto tracker_2_0_worker = TrackerTest::test_worker(tracker_2_0); auto tracker_3_0_worker = TrackerTest::test_worker(tracker_3_0); CPPUNIT_ASSERT(tracker_0_0_worker->trigger_failure()); CPPUNIT_ASSERT(!tracker_controller.is_failure_mode()); TEST_MULTI3_IS_BUSY("01000", "01000"); CPPUNIT_ASSERT(tracker_0_1_worker->trigger_failure()); TEST_MULTI3_IS_BUSY("00100", "00100"); CPPUNIT_ASSERT(tracker_1_0_worker->trigger_success()); CPPUNIT_ASSERT(test_goto_next_timeout(this, &tracker_controller, tracker_1_0.state().normal_interval())); TEST_MULTI3_IS_BUSY("10000", "10000"); CPPUNIT_ASSERT(tracker_0_0_worker->trigger_failure()); TEST_MULTI3_IS_BUSY("01000", "01000"); CPPUNIT_ASSERT(tracker_0_1_worker->trigger_failure()); CPPUNIT_ASSERT(!tracker_controller.is_failure_mode()); TEST_MULTI3_IS_BUSY("00100", "00100"); CPPUNIT_ASSERT(tracker_1_0_worker->trigger_failure()); CPPUNIT_ASSERT(tracker_controller.is_failure_mode()); TEST_MULTI3_IS_BUSY("00010", "00010"); CPPUNIT_ASSERT(tracker_2_0_worker->trigger_failure()); TEST_MULTI3_IS_BUSY("00001", "00001"); CPPUNIT_ASSERT(tracker_3_0_worker->trigger_failure()); // Properly tests that we're going into timeouts... Disable remaining trackers. // for (int i = 0; i < 5; i++) // std::cout << std::endl << i << ": " // << tracker_list[i]->activity_time_last() << ' ' // << tracker_list[i]->success_time_last() << ' ' // << tracker_list[i]->failed_time_last() << std::endl; // Try inserting some delays in order to test the timers. CPPUNIT_ASSERT(test_goto_next_timeout(this, &tracker_controller, 5)); TEST_MULTI3_IS_BUSY("00100", "00100"); CPPUNIT_ASSERT(tracker_1_0_worker->trigger_success()); CPPUNIT_ASSERT(!tracker_controller.is_failure_mode()); // CPPUNIT_ASSERT(test_goto_next_timeout(this, &tracker_controller, tracker_list[0].state().normal_interval())); // TEST_MULTI3_IS_BUSY("01000", "10000"); // CPPUNIT_ASSERT(tracker_0_1_worker->trigger_success()); CPPUNIT_ASSERT(TrackerTest::count_active(&tracker_list) == 0); TEST_MULTIPLE_END(2, 7); } void TestTrackerController::test_multiple_cycle() { TEST_MULTI3_BEGIN(); TEST_SEND_SINGLE_BEGIN(update); auto tracker_0_0_worker = TrackerTest::test_worker(tracker_0_0); auto tracker_0_1_worker = TrackerTest::test_worker(tracker_0_1); CPPUNIT_ASSERT(tracker_0_0_worker->trigger_failure()); CPPUNIT_ASSERT(tracker_0_1_worker->trigger_success()); CPPUNIT_ASSERT(tracker_list.front() == tracker_0_1); CPPUNIT_ASSERT(test_goto_next_timeout(this, &tracker_controller, tracker_0_1.state().normal_interval())); TEST_MULTI3_IS_BUSY("01000", "10000"); CPPUNIT_ASSERT(tracker_0_1_worker->trigger_success()); CPPUNIT_ASSERT(TrackerTest::count_active(&tracker_list) == 0); TEST_MULTIPLE_END(2, 1); } void TestTrackerController::test_multiple_cycle_second_group() { TEST_MULTI3_BEGIN(); TEST_SEND_SINGLE_BEGIN(update); auto tracker_0_0_worker = TrackerTest::test_worker(tracker_0_0); auto tracker_0_1_worker = TrackerTest::test_worker(tracker_0_1); auto tracker_1_0_worker = TrackerTest::test_worker(tracker_1_0); CPPUNIT_ASSERT(tracker_0_0_worker->trigger_failure()); CPPUNIT_ASSERT(tracker_0_1_worker->trigger_failure()); CPPUNIT_ASSERT(tracker_1_0_worker->trigger_success()); CPPUNIT_ASSERT(tracker_list.at(0) == tracker_0_0); CPPUNIT_ASSERT(tracker_list.at(1) == tracker_0_1); CPPUNIT_ASSERT(tracker_list.at(2) == tracker_1_0); CPPUNIT_ASSERT(tracker_list.at(3) == tracker_2_0); CPPUNIT_ASSERT(tracker_list.at(4) == tracker_3_0); TEST_MULTIPLE_END(1, 2); } void TestTrackerController::test_multiple_send_stop() { TEST_MULTI3_BEGIN(); auto tracker_0_1_worker = TrackerTest::test_worker(tracker_0_1); auto tracker_2_0_worker = TrackerTest::test_worker(tracker_2_0); auto tracker_3_0_worker = TrackerTest::test_worker(tracker_3_0); tracker_list.send_event(tracker_list.at(1), torrent::tracker::TrackerState::EVENT_NONE); tracker_list.send_event(tracker_list.at(3), torrent::tracker::TrackerState::EVENT_NONE); tracker_list.send_event(tracker_list.at(4), torrent::tracker::TrackerState::EVENT_NONE); CPPUNIT_ASSERT(tracker_0_1_worker->trigger_success()); CPPUNIT_ASSERT(tracker_2_0_worker->trigger_success()); CPPUNIT_ASSERT(tracker_3_0_worker->trigger_success()); CPPUNIT_ASSERT(TrackerTest::count_active(&tracker_list) == 0); tracker_controller.send_stop_event(); CPPUNIT_ASSERT(TrackerTest::count_active(&tracker_list) == 3); TEST_MULTI3_IS_BUSY("01011", "10011"); CPPUNIT_ASSERT(tracker_0_1_worker->trigger_success()); CPPUNIT_ASSERT((tracker_controller.flags() & torrent::TrackerController::mask_send) != torrent::TrackerController::flag_send_stop); CPPUNIT_ASSERT(tracker_2_0_worker->trigger_success()); CPPUNIT_ASSERT(tracker_3_0_worker->trigger_success()); CPPUNIT_ASSERT(TrackerTest::count_active(&tracker_list) == 0); tracker_controller.send_stop_event(); tracker_controller.disable(); CPPUNIT_ASSERT((tracker_controller.flags() & torrent::TrackerController::mask_send) == torrent::TrackerController::flag_send_stop); TEST_MULTI3_IS_BUSY("01011", "10011"); tracker_controller.enable(torrent::TrackerController::enable_dont_reset_stats); TEST_MULTI3_IS_BUSY("00000", "00000"); CPPUNIT_ASSERT((tracker_controller.flags() & torrent::TrackerController::mask_send) == 0); tracker_controller.send_stop_event(); TEST_MULTI3_IS_BUSY("01011", "10011"); tracker_controller.disable(); tracker_controller.enable(); TEST_MULTI3_IS_BUSY("00000", "00000"); CPPUNIT_ASSERT((tracker_controller.flags() & torrent::TrackerController::mask_send) == 0); tracker_controller.send_stop_event(); TEST_MULTI3_IS_BUSY("00000", "00000"); // Test also that after closing the tracker controller, and // reopening it a 'send stop' event causes no tracker to be busy. TEST_MULTIPLE_END(6, 0); } void TestTrackerController::test_multiple_send_update() { TEST_MULTI3_BEGIN(); auto tracker_0_0_worker = TrackerTest::test_worker(tracker_0_0); auto tracker_0_1_worker = TrackerTest::test_worker(tracker_0_1); tracker_controller.send_update_event(); CPPUNIT_ASSERT(test_goto_next_timeout(this, &tracker_controller, 0)); TEST_MULTI3_IS_BUSY("10000", "10000"); CPPUNIT_ASSERT(tracker_0_0_worker->trigger_success()); tracker_0_0_worker->set_failed(1, torrent::this_thread::cached_seconds().count()); tracker_controller.send_update_event(); CPPUNIT_ASSERT(test_goto_next_timeout(this, &tracker_controller, 0)); TEST_MULTI3_IS_BUSY("01000", "01000"); CPPUNIT_ASSERT(tracker_0_1_worker->trigger_failure()); CPPUNIT_ASSERT(test_goto_next_timeout(this, &tracker_controller, 0)); TEST_MULTI3_IS_BUSY("00100", "00100"); TEST_MULTIPLE_END(2, 0); } // Test timeout called, no usable trackers at all which leads to // disabling the timeout. // // The enable/disable tracker functions will poke the tracker // controller, ensuring the tast timeout gets re-started. void TestTrackerController::test_timeout_lacking_usable() { TEST_MULTI3_BEGIN(); std::for_each(tracker_list.begin(), tracker_list.end(), std::mem_fn(&torrent::tracker::Tracker::disable)); CPPUNIT_ASSERT(tracker_controller.is_timeout_queued()); CPPUNIT_ASSERT(test_goto_next_timeout(this, &tracker_controller, 0)); TEST_MULTI3_IS_BUSY("00000", "00000"); CPPUNIT_ASSERT(!tracker_controller.is_timeout_queued()); tracker_1_0.enable(); CPPUNIT_ASSERT(tracker_controller.is_timeout_queued()); CPPUNIT_ASSERT(tracker_controller.seconds_to_next_timeout() == 0); CPPUNIT_ASSERT(test_goto_next_timeout(this, &tracker_controller, 0)); TEST_MULTI3_IS_BUSY("00100", "00100"); CPPUNIT_ASSERT(!tracker_controller.is_timeout_queued()); tracker_3_0.enable(); CPPUNIT_ASSERT(!tracker_controller.is_timeout_queued()); CPPUNIT_ASSERT(enabled_counter == 5 + 2 && disabled_counter == 5); TEST_MULTIPLE_END(0, 0); } void TestTrackerController::test_disable_tracker() { TEST_SINGLE_BEGIN(); TEST_SEND_SINGLE_BEGIN(update); CPPUNIT_ASSERT(tracker_controller.is_timeout_queued()); CPPUNIT_ASSERT(tracker_0_0.is_busy()); tracker_0_0.disable(); CPPUNIT_ASSERT(!tracker_0_0.is_busy()); CPPUNIT_ASSERT(tracker_controller.is_timeout_queued()); TEST_SINGLE_END(0, 0); } void TestTrackerController::test_new_peers() { TRACKER_CONTROLLER_SETUP(); TRACKER_INSERT(0, tracker_0_0); auto tracker_0_0_worker = TrackerTest::test_worker(tracker_0_0); tracker_list.send_event(tracker_list.at(0), torrent::tracker::TrackerState::EVENT_NONE); CPPUNIT_ASSERT(tracker_0_0_worker->trigger_success(10)); CPPUNIT_ASSERT(tracker_0_0.state().latest_new_peers() == 10); tracker_controller.enable(); CPPUNIT_ASSERT(test_goto_next_timeout(this, &tracker_controller, 0)); CPPUNIT_ASSERT(tracker_0_0_worker->trigger_success(20)); CPPUNIT_ASSERT(tracker_0_0.state().latest_new_peers() == 20); } // Add new function for finding the first tracker that will time out, // e.g. both with failure mode and normal rerequesting. // Make sure that adding a new tracker to a tracker list with no // usable tracker restarts the tracker requests. // Test timeout called, usable trackers exist but could not be called // at this moment, thus leading to no active trackers. (Rather, clean // up the 'is_usable()' functions, and make it a new function that is // independent of enabled, or is itself manipulating/dependent on // enabled) // Add checks to ensure we don't prematurely do timeout on a tracker // after disabling the lead one. // Make sure that we always remain with timeout, even if we send a // request that somehow doesn't actually activate any // trackers. e.g. check all send_tracker_itr uses. // Add test for promiscious mode while with a single tracker? // Test send_* with controller not enabled. // Test cleanup after disable. // Test cleanup of timers at disable (and empty timers at enable). // Test trying to send_start twice, etc. // Test send_start promiscious... // - Make sure we check that no timer is inserted while still having active trackers. // - Calculate the next timeout according to a list of in-use trackers, with the first timeout as the interval. // Test clearing of recv/failed counter on trackers. libtorrent-0.16.11/test/torrent/object_test.cc0000644000000000000000000001167715175073411015003 #include "config.h" #include #include #include "object_test.h" #include "object_test_utils.h" CPPUNIT_TEST_SUITE_REGISTRATION(ObjectTest); namespace { [[maybe_unused]] void object_test_return_void() { } } // namespace // template // struct object_void_wrapper { // typedef // object_void_wrapper(Slot s) : m_slot(s) {} // torrent::Object operator () () { m_slot( // Slot m_slot; // } void ObjectTest::test_basic() { // std::cout << "sizeof(torrent::Object) = " << sizeof(torrent::Object) << std::endl; // std::cout << "sizeof(torrent::Object::list_type) = " << sizeof(torrent::Object::list_type) << std::endl; // std::cout << "sizeof(torrent::Object::map_type) = " << sizeof(torrent::Object::map_type) << std::endl; // torrent::Object obj_void(object_test_return_void()); } void ObjectTest::test_flags() { torrent::Object objectFlagsValue = torrent::Object(int64_t()); torrent::Object objectNoFlagsEmpty = torrent::Object(); torrent::Object objectNoFlagsValue = torrent::Object(int64_t()); objectFlagsValue.set_flags(torrent::Object::flag_static_data | torrent::Object::flag_session_data); CPPUNIT_ASSERT(objectNoFlagsEmpty.flags() == 0); CPPUNIT_ASSERT(objectNoFlagsValue.flags() == 0); CPPUNIT_ASSERT(objectFlagsValue.flags() & torrent::Object::flag_session_data && objectFlagsValue.flags() & torrent::Object::flag_static_data); objectFlagsValue.unset_flags(torrent::Object::flag_session_data); CPPUNIT_ASSERT(!(objectFlagsValue.flags() & torrent::Object::flag_session_data) && objectFlagsValue.flags() & torrent::Object::flag_static_data); } void ObjectTest::test_merge() { } #define TEST_VALUE_A "i10e" #define TEST_VALUE_B "i20e" #define TEST_STRING_A "1:g" #define TEST_STRING_B "1:h" #define TEST_MAP_A "d1:ai1e1:bi2ee" #define TEST_MAP_B "d1:ci4e1:di5ee" #define TEST_LIST_A "l1:e1:fe" #define TEST_LIST_B "li1ei2ee" static bool swap_compare(const char* left, const char* right) { torrent::Object obj_left = create_bencode(left); torrent::Object obj_right = create_bencode(right); obj_left.swap(obj_right); if (!compare_bencode(obj_left, right) || !compare_bencode(obj_right, left)) return false; obj_left.swap(obj_right); if (!compare_bencode(obj_left, left) || !compare_bencode(obj_right, right)) return false; return true; } static bool swap_compare_dict_key(const char* left_key, const char* left_obj, const char* right_key, const char* right_obj) { torrent::Object obj_left = torrent::Object::create_dict_key(); torrent::Object obj_right = torrent::Object::create_dict_key(); obj_left.as_dict_key() = left_key; obj_left.as_dict_obj() = create_bencode(left_obj); obj_right.as_dict_key() = right_key; obj_right.as_dict_obj() = create_bencode(right_obj); obj_left.swap(obj_right); if (obj_left.as_dict_key() != right_key || !compare_bencode(obj_left.as_dict_obj(), right_obj) || obj_right.as_dict_key() != left_key || !compare_bencode(obj_right.as_dict_obj(), left_obj)) return false; obj_left.swap(obj_right); if (obj_left.as_dict_key() != left_key || !compare_bencode(obj_left.as_dict_obj(), left_obj) || obj_right.as_dict_key() != right_key || !compare_bencode(obj_right.as_dict_obj(), right_obj)) return false; return true; } void ObjectTest::test_swap_and_move() { CPPUNIT_ASSERT(swap_compare(TEST_VALUE_A, TEST_VALUE_B)); CPPUNIT_ASSERT(swap_compare(TEST_STRING_A, TEST_STRING_B)); CPPUNIT_ASSERT(swap_compare(TEST_MAP_A, TEST_MAP_B)); CPPUNIT_ASSERT(swap_compare(TEST_LIST_A, TEST_LIST_B)); CPPUNIT_ASSERT(swap_compare(TEST_VALUE_A, TEST_STRING_B)); CPPUNIT_ASSERT(swap_compare(TEST_STRING_A, TEST_MAP_B)); CPPUNIT_ASSERT(swap_compare(TEST_MAP_A, TEST_LIST_B)); CPPUNIT_ASSERT(swap_compare(TEST_LIST_A, TEST_VALUE_B)); CPPUNIT_ASSERT(swap_compare("i1e", TEST_VALUE_A)); CPPUNIT_ASSERT(swap_compare("i1e", TEST_MAP_A)); CPPUNIT_ASSERT(swap_compare("i1e", TEST_LIST_A)); CPPUNIT_ASSERT(swap_compare_dict_key("a", TEST_VALUE_A, "b", TEST_STRING_B)); CPPUNIT_ASSERT(swap_compare_dict_key("a", TEST_STRING_A, "b", TEST_STRING_B)); } void ObjectTest::test_create_normal() { torrent::Object obj; CPPUNIT_ASSERT(torrent::object_create_normal(create_bencode_raw_bencode_c("i45e")).as_value() == 45); CPPUNIT_ASSERT(torrent::object_create_normal(create_bencode_raw_bencode_c("4:test")).as_string() == "test"); CPPUNIT_ASSERT(torrent::object_create_normal(create_bencode_raw_bencode_c("li5ee")).as_list().front().as_value() == 5); CPPUNIT_ASSERT(torrent::object_create_normal(create_bencode_raw_bencode_c("d1:ai6ee")).as_map()["a"].as_value() == 6); CPPUNIT_ASSERT(torrent::object_create_normal(create_bencode_raw_string_c("test")).as_string() == "test"); CPPUNIT_ASSERT(torrent::object_create_normal(create_bencode_raw_list_c("i5ei6e")).as_list().back().as_value() == 6); CPPUNIT_ASSERT(torrent::object_create_normal(create_bencode_raw_map_c("1:ai2e1:bi3e")).as_map()["b"].as_value() == 3); } libtorrent-0.16.11/test/torrent/test_tracker_list.cc0000644000000000000000000004320715175073411016215 #include "config.h" #include "test/torrent/test_tracker_list.h" #include "net/address_list.h" #include "torrent/utils/uri_parser.h" CPPUNIT_TEST_SUITE_REGISTRATION(TestTrackerList); void TestTrackerList::test_basic() { TRACKER_LIST_SETUP(); TRACKER_INSERT(0, tracker_0); CPPUNIT_ASSERT(tracker_0 == tracker_list.at(0)); CPPUNIT_ASSERT(std::distance(tracker_list.begin_group(0), tracker_list.end_group(0)) == 1); auto usable_itr = std::find_if(tracker_list.begin(), tracker_list.end(), std::mem_fn(&torrent::tracker::Tracker::is_usable)); CPPUNIT_ASSERT(usable_itr != tracker_list.end()); } void TestTrackerList::test_enable() { TRACKER_LIST_SETUP(); int enabled_counter = 0; int disabled_counter = 0; tracker_list.slot_tracker_enabled() = std::bind(&increment_value_void, &enabled_counter); tracker_list.slot_tracker_disabled() = std::bind(&increment_value_void, &disabled_counter); TRACKER_INSERT(0, tracker_0); TRACKER_INSERT(1, tracker_1); CPPUNIT_ASSERT(enabled_counter == 2 && disabled_counter == 0); tracker_0.enable(); tracker_1.enable(); CPPUNIT_ASSERT(enabled_counter == 2 && disabled_counter == 0); tracker_0.disable(); tracker_1.enable(); CPPUNIT_ASSERT(enabled_counter == 2 && disabled_counter == 1); tracker_1.disable(); tracker_0.disable(); CPPUNIT_ASSERT(enabled_counter == 2 && disabled_counter == 2); tracker_0.enable(); tracker_1.enable(); tracker_0.enable(); tracker_1.enable(); CPPUNIT_ASSERT(enabled_counter == 4 && disabled_counter == 2); } void TestTrackerList::test_close() { TRACKER_LIST_SETUP(); TRACKER_INSERT(0, tracker_0); TRACKER_INSERT(0, tracker_1); TRACKER_INSERT(0, tracker_2); TRACKER_INSERT(0, tracker_3); tracker_list.send_event(tracker_list.at(0), torrent::tracker::TrackerState::EVENT_NONE); tracker_list.send_event(tracker_list.at(1), torrent::tracker::TrackerState::EVENT_STARTED); tracker_list.send_event(tracker_list.at(2), torrent::tracker::TrackerState::EVENT_STOPPED); tracker_list.send_event(tracker_list.at(3), torrent::tracker::TrackerState::EVENT_COMPLETED); CPPUNIT_ASSERT(tracker_0.is_busy()); CPPUNIT_ASSERT(tracker_1.is_busy()); CPPUNIT_ASSERT(tracker_2.is_busy()); CPPUNIT_ASSERT(tracker_3.is_busy()); tracker_list.close_all_excluding((1 << torrent::tracker::TrackerState::EVENT_STARTED) | (1 << torrent::tracker::TrackerState::EVENT_STOPPED)); CPPUNIT_ASSERT(!tracker_0.is_busy()); CPPUNIT_ASSERT(tracker_1.is_busy()); CPPUNIT_ASSERT(tracker_2.is_busy()); CPPUNIT_ASSERT(!tracker_3.is_busy()); tracker_list.close_all(); CPPUNIT_ASSERT(!tracker_0.is_busy()); CPPUNIT_ASSERT(!tracker_1.is_busy()); CPPUNIT_ASSERT(!tracker_2.is_busy()); CPPUNIT_ASSERT(!tracker_3.is_busy()); tracker_list.send_event(tracker_list.at(0), torrent::tracker::TrackerState::EVENT_NONE); tracker_list.send_event(tracker_list.at(1), torrent::tracker::TrackerState::EVENT_STARTED); tracker_list.send_event(tracker_list.at(2), torrent::tracker::TrackerState::EVENT_STOPPED); tracker_list.send_event(tracker_list.at(3), torrent::tracker::TrackerState::EVENT_COMPLETED); tracker_list.close_all_excluding((1 << torrent::tracker::TrackerState::EVENT_NONE) | (1 << torrent::tracker::TrackerState::EVENT_COMPLETED)); CPPUNIT_ASSERT(tracker_0.is_busy()); CPPUNIT_ASSERT(!tracker_1.is_busy()); CPPUNIT_ASSERT(!tracker_2.is_busy()); CPPUNIT_ASSERT(tracker_3.is_busy()); } // Test clear. void TestTrackerList::test_tracker_flags() { TRACKER_LIST_SETUP(); tracker_list.insert(0, TrackerTest::new_tracker(&tracker_list, "")); tracker_list.insert(0, TrackerTest::new_tracker(&tracker_list, "", 0)); tracker_list.insert(0, TrackerTest::new_tracker(&tracker_list, "", torrent::tracker::TrackerState::flag_enabled)); tracker_list.insert(0, TrackerTest::new_tracker(&tracker_list, "", torrent::tracker::TrackerState::flag_extra_tracker)); tracker_list.insert(0, TrackerTest::new_tracker(&tracker_list, "", torrent::tracker::TrackerState::flag_enabled | torrent::tracker::TrackerState::flag_extra_tracker)); CPPUNIT_ASSERT((TrackerTest::test_flags(tracker_list.at(0)) & 0xf) == torrent::tracker::TrackerState::flag_enabled); CPPUNIT_ASSERT((TrackerTest::test_flags(tracker_list.at(1)) & 0xf) == 0); CPPUNIT_ASSERT((TrackerTest::test_flags(tracker_list.at(2)) & 0xf) == torrent::tracker::TrackerState::flag_enabled); CPPUNIT_ASSERT((TrackerTest::test_flags(tracker_list.at(3)) & 0xf) == torrent::tracker::TrackerState::flag_extra_tracker); CPPUNIT_ASSERT((TrackerTest::test_flags(tracker_list.at(4)) & 0xf) == (torrent::tracker::TrackerState::flag_enabled | torrent::tracker::TrackerState::flag_extra_tracker)); } void TestTrackerList::test_find_url() { TRACKER_LIST_SETUP(); tracker_list.insert(0, TrackerTest::new_tracker(&tracker_list, "http://1")); tracker_list.insert(0, TrackerTest::new_tracker(&tracker_list, "http://2")); tracker_list.insert(1, TrackerTest::new_tracker(&tracker_list, "http://3")); CPPUNIT_ASSERT(tracker_list.find_url("http://") == tracker_list.end()); CPPUNIT_ASSERT(tracker_list.find_url("http://1") != tracker_list.end()); CPPUNIT_ASSERT(*tracker_list.find_url("http://1") == tracker_list.at(0)); CPPUNIT_ASSERT(tracker_list.find_url("http://2") != tracker_list.end()); CPPUNIT_ASSERT(*tracker_list.find_url("http://2") == tracker_list.at(1)); CPPUNIT_ASSERT(tracker_list.find_url("http://3") != tracker_list.end()); CPPUNIT_ASSERT(*tracker_list.find_url("http://3") == tracker_list.at(2)); } void TestTrackerList::test_can_scrape() { TRACKER_LIST_SETUP(); tracker_list.insert_url(0, "http://example.com/announce"); CPPUNIT_ASSERT(tracker_list.back().is_scrapable()); CPPUNIT_ASSERT(torrent::utils::uri_generate_scrape_url(tracker_list.back().url()) == "http://example.com/scrape"); tracker_list.insert_url(0, "http://example.com/x/announce"); CPPUNIT_ASSERT(tracker_list.back().is_scrapable()); CPPUNIT_ASSERT(torrent::utils::uri_generate_scrape_url(tracker_list.back().url()) == "http://example.com/x/scrape"); tracker_list.insert_url(0, "http://example.com/announce.php"); CPPUNIT_ASSERT(tracker_list.back().is_scrapable()); CPPUNIT_ASSERT(torrent::utils::uri_generate_scrape_url(tracker_list.back().url()) == "http://example.com/scrape.php"); tracker_list.insert_url(0, "http://example.com/a"); CPPUNIT_ASSERT(!tracker_list.back().is_scrapable()); tracker_list.insert_url(0, "http://example.com/announce?x2%0644"); CPPUNIT_ASSERT(tracker_list.back().is_scrapable()); CPPUNIT_ASSERT(torrent::utils::uri_generate_scrape_url(tracker_list.back().url()) == "http://example.com/scrape?x2%0644"); tracker_list.insert_url(0, "http://example.com/announce?x=2/4"); CPPUNIT_ASSERT(!tracker_list.back().is_scrapable()); tracker_list.insert_url(0, "http://example.com/x%064announce"); CPPUNIT_ASSERT(!tracker_list.back().is_scrapable()); } void TestTrackerList::test_single_success() { TRACKER_LIST_SETUP(); TRACKER_INSERT(0, tracker_0); auto tracker_0_worker = TrackerTest::test_worker(tracker_0); CPPUNIT_ASSERT(!tracker_0.is_busy()); CPPUNIT_ASSERT(!tracker_0.is_busy_not_scrape()); CPPUNIT_ASSERT(!tracker_0_worker->is_open()); CPPUNIT_ASSERT(tracker_0_worker->requesting_state() == -1); CPPUNIT_ASSERT(tracker_0.state().latest_event() == torrent::tracker::TrackerState::EVENT_NONE); tracker_list.send_event(tracker_list.at(0), torrent::tracker::TrackerState::EVENT_STARTED); CPPUNIT_ASSERT(tracker_0.is_busy()); CPPUNIT_ASSERT(tracker_0.is_busy_not_scrape()); CPPUNIT_ASSERT(tracker_0_worker->is_open()); CPPUNIT_ASSERT(tracker_0_worker->requesting_state() == torrent::tracker::TrackerState::EVENT_STARTED); CPPUNIT_ASSERT(tracker_0.state().latest_event() == torrent::tracker::TrackerState::EVENT_STARTED); CPPUNIT_ASSERT(tracker_0_worker->trigger_success()); CPPUNIT_ASSERT(!tracker_0.is_busy()); CPPUNIT_ASSERT(!tracker_0.is_busy_not_scrape()); CPPUNIT_ASSERT(!tracker_0_worker->is_open()); CPPUNIT_ASSERT(tracker_0_worker->requesting_state() == -1); CPPUNIT_ASSERT(tracker_0.state().latest_event() == torrent::tracker::TrackerState::EVENT_STARTED); CPPUNIT_ASSERT(success_counter == 1 && failure_counter == 0); CPPUNIT_ASSERT(tracker_0.state().success_counter() == 1); CPPUNIT_ASSERT(tracker_0.state().failed_counter() == 0); } void TestTrackerList::test_single_failure() { TRACKER_LIST_SETUP(); TRACKER_INSERT(0, tracker_0); auto tracker_0_worker = TrackerTest::test_worker(tracker_0); tracker_list.send_event(tracker_list.at(0), torrent::tracker::TrackerState::EVENT_NONE); CPPUNIT_ASSERT(tracker_0_worker->trigger_failure()); CPPUNIT_ASSERT(!tracker_0.is_busy()); CPPUNIT_ASSERT(!tracker_0_worker->is_open()); CPPUNIT_ASSERT(tracker_0_worker->requesting_state() == -1); CPPUNIT_ASSERT(success_counter == 0 && failure_counter == 1); CPPUNIT_ASSERT(tracker_0.state().success_counter() == 0); CPPUNIT_ASSERT(tracker_0.state().failed_counter() == 1); tracker_list.send_event(tracker_list.at(0), torrent::tracker::TrackerState::EVENT_NONE); CPPUNIT_ASSERT(tracker_0_worker->trigger_success()); CPPUNIT_ASSERT(success_counter == 1 && failure_counter == 1); CPPUNIT_ASSERT(tracker_0.state().success_counter() == 1); CPPUNIT_ASSERT(tracker_0.state().failed_counter() == 0); } void TestTrackerList::test_single_closing() { TRACKER_LIST_SETUP(); TRACKER_INSERT(0, tracker_0); auto tracker_0_worker = TrackerTest::test_worker(tracker_0); CPPUNIT_ASSERT(!tracker_0_worker->is_open()); tracker_0_worker->set_close_on_done(false); tracker_list.send_event(tracker_list.at(0), torrent::tracker::TrackerState::EVENT_NONE); CPPUNIT_ASSERT(tracker_0_worker->is_open()); CPPUNIT_ASSERT(tracker_0_worker->trigger_success()); CPPUNIT_ASSERT(!tracker_0.is_busy()); CPPUNIT_ASSERT(tracker_0_worker->is_open()); tracker_list.close_all(); tracker_list.clear_stats(); CPPUNIT_ASSERT(!tracker_0_worker->is_open()); CPPUNIT_ASSERT(tracker_0.state().success_counter() == 0); CPPUNIT_ASSERT(tracker_0.state().failed_counter() == 0); } void TestTrackerList::test_multiple_success() { TRACKER_LIST_SETUP(); TRACKER_INSERT(0, tracker_0_0); TRACKER_INSERT(0, tracker_0_1); TRACKER_INSERT(1, tracker_1_0); TRACKER_INSERT(1, tracker_1_1); auto tracker_0_0_worker = TrackerTest::test_worker(tracker_0_0); auto tracker_0_1_worker = TrackerTest::test_worker(tracker_0_1); auto tracker_1_1_worker = TrackerTest::test_worker(tracker_1_1); CPPUNIT_ASSERT(!tracker_0_0.is_busy()); CPPUNIT_ASSERT(!tracker_0_1.is_busy()); CPPUNIT_ASSERT(!tracker_1_0.is_busy()); CPPUNIT_ASSERT(!tracker_1_1.is_busy()); tracker_list.send_event(tracker_list.at(0), torrent::tracker::TrackerState::EVENT_NONE); CPPUNIT_ASSERT(tracker_0_0.is_busy()); CPPUNIT_ASSERT(!tracker_0_1.is_busy()); CPPUNIT_ASSERT(!tracker_1_0.is_busy()); CPPUNIT_ASSERT(!tracker_1_1.is_busy()); CPPUNIT_ASSERT(tracker_0_0_worker->trigger_success()); CPPUNIT_ASSERT(!tracker_0_0.is_busy()); CPPUNIT_ASSERT(!tracker_0_1.is_busy()); CPPUNIT_ASSERT(!tracker_1_0.is_busy()); CPPUNIT_ASSERT(!tracker_1_1.is_busy()); tracker_list.send_event(tracker_list.at(1), torrent::tracker::TrackerState::EVENT_NONE); tracker_list.send_event(tracker_list.at(3), torrent::tracker::TrackerState::EVENT_NONE); CPPUNIT_ASSERT(!tracker_0_0.is_busy()); CPPUNIT_ASSERT(tracker_0_1.is_busy()); CPPUNIT_ASSERT(!tracker_1_0.is_busy()); CPPUNIT_ASSERT(tracker_1_1.is_busy()); CPPUNIT_ASSERT(tracker_1_1_worker->trigger_success()); CPPUNIT_ASSERT(!tracker_0_0.is_busy()); CPPUNIT_ASSERT(tracker_0_1.is_busy()); CPPUNIT_ASSERT(!tracker_1_0.is_busy()); CPPUNIT_ASSERT(!tracker_1_1.is_busy()); CPPUNIT_ASSERT(tracker_0_1_worker->trigger_success()); CPPUNIT_ASSERT(!tracker_0_0.is_busy()); CPPUNIT_ASSERT(!tracker_0_1.is_busy()); CPPUNIT_ASSERT(!tracker_1_0.is_busy()); CPPUNIT_ASSERT(!tracker_1_1.is_busy()); CPPUNIT_ASSERT(success_counter == 3 && failure_counter == 0); } void TestTrackerList::test_scrape_success() { TRACKER_LIST_SETUP(); TRACKER_INSERT(0, tracker_0); auto tracker_0_worker = TrackerTest::test_worker(tracker_0); tracker_0_worker->set_scrapable(); tracker_list.send_scrape(tracker_0); CPPUNIT_ASSERT(tracker_0.is_busy()); CPPUNIT_ASSERT(!tracker_0.is_busy_not_scrape()); CPPUNIT_ASSERT(tracker_0_worker->is_open()); CPPUNIT_ASSERT(tracker_0_worker->requesting_state() == torrent::tracker::TrackerState::EVENT_SCRAPE); CPPUNIT_ASSERT(tracker_0.state().latest_event() == torrent::tracker::TrackerState::EVENT_SCRAPE); CPPUNIT_ASSERT(tracker_0_worker->trigger_scrape()); CPPUNIT_ASSERT(!tracker_0.is_busy()); CPPUNIT_ASSERT(!tracker_0.is_busy_not_scrape()); CPPUNIT_ASSERT(!tracker_0_worker->is_open()); CPPUNIT_ASSERT(tracker_0_worker->requesting_state() == -1); CPPUNIT_ASSERT(tracker_0.state().latest_event() == torrent::tracker::TrackerState::EVENT_SCRAPE); CPPUNIT_ASSERT(success_counter == 0 && failure_counter == 0); CPPUNIT_ASSERT(scrape_success_counter == 1 && scrape_failure_counter == 0); CPPUNIT_ASSERT(tracker_0.state().success_counter() == 0); CPPUNIT_ASSERT(tracker_0.state().failed_counter() == 0); CPPUNIT_ASSERT(tracker_0.state().scrape_counter() == 1); } void TestTrackerList::test_scrape_failure() { TRACKER_LIST_SETUP(); TRACKER_INSERT(0, tracker_0); auto tracker_0_worker = TrackerTest::test_worker(tracker_0); tracker_0_worker->set_scrapable(); tracker_list.send_scrape(tracker_0); CPPUNIT_ASSERT(tracker_0_worker->trigger_failure()); CPPUNIT_ASSERT(!tracker_0.is_busy()); CPPUNIT_ASSERT(!tracker_0_worker->is_open()); CPPUNIT_ASSERT(tracker_0_worker->requesting_state() == -1); CPPUNIT_ASSERT(tracker_0.state().latest_event() == torrent::tracker::TrackerState::EVENT_SCRAPE); CPPUNIT_ASSERT(success_counter == 0 && failure_counter == 0); CPPUNIT_ASSERT(scrape_success_counter == 0 && scrape_failure_counter == 1); CPPUNIT_ASSERT(tracker_0.state().success_counter() == 0); CPPUNIT_ASSERT(tracker_0.state().failed_counter() == 0); CPPUNIT_ASSERT(tracker_0.state().scrape_counter() == 0); } bool check_has_active_in_group(const torrent::TrackerList* tracker_list, const char* states, bool scrape) { int group = 0; while (*states != '\0') { bool result = scrape ? tracker_list->has_active_in_group(group++) : tracker_list->has_active_not_scrape_in_group(group++); if ((*states == '1' && !result) || (*states == '0' && result)) return false; states++; } return true; } void TestTrackerList::test_has_active() { TRACKER_LIST_SETUP(); TRACKER_INSERT(0, tracker_0); TRACKER_INSERT(0, tracker_1); TRACKER_INSERT(1, tracker_2); TRACKER_INSERT(3, tracker_3); TRACKER_INSERT(4, tracker_4); // TODO: Test scrape... auto tracker_0_worker = TrackerTest::test_worker(tracker_0); auto tracker_1_worker = TrackerTest::test_worker(tracker_1); auto tracker_2_worker = TrackerTest::test_worker(tracker_2); auto tracker_3_worker = TrackerTest::test_worker(tracker_3); TEST_TRACKERS_IS_BUSY_5("00000", "00000"); CPPUNIT_ASSERT(!tracker_list.has_active()); CPPUNIT_ASSERT(!tracker_list.has_active_not_scrape()); CPPUNIT_ASSERT(check_has_active_in_group(&tracker_list, "000000", false)); CPPUNIT_ASSERT(check_has_active_in_group(&tracker_list, "000000", true)); tracker_list.send_event(tracker_list.at(0), torrent::tracker::TrackerState::EVENT_NONE); TEST_TRACKERS_IS_BUSY_5("10000", "10000"); CPPUNIT_ASSERT( tracker_list.has_active()); CPPUNIT_ASSERT( tracker_list.has_active_not_scrape()); CPPUNIT_ASSERT(check_has_active_in_group(&tracker_list, "100000", false)); CPPUNIT_ASSERT(check_has_active_in_group(&tracker_list, "100000", true)); CPPUNIT_ASSERT(tracker_0_worker->trigger_success()); TEST_TRACKERS_IS_BUSY_5("00000", "00000"); CPPUNIT_ASSERT(!tracker_list.has_active()); CPPUNIT_ASSERT(!tracker_list.has_active_not_scrape()); CPPUNIT_ASSERT(check_has_active_in_group(&tracker_list, "000000", false)); CPPUNIT_ASSERT(check_has_active_in_group(&tracker_list, "000000", true)); tracker_list.send_event(tracker_list.at(1), torrent::tracker::TrackerState::EVENT_NONE); tracker_list.send_event(tracker_list.at(3), torrent::tracker::TrackerState::EVENT_NONE); TEST_TRACKERS_IS_BUSY_5("01010", "01010"); CPPUNIT_ASSERT( tracker_list.has_active()); CPPUNIT_ASSERT( tracker_list.has_active_not_scrape()); CPPUNIT_ASSERT(check_has_active_in_group(&tracker_list, "100100", false)); CPPUNIT_ASSERT(check_has_active_in_group(&tracker_list, "100100", true)); tracker_2_worker->set_scrapable(); tracker_list.send_scrape(tracker_2); tracker_list.send_event(tracker_list.at(1), torrent::tracker::TrackerState::EVENT_NONE); tracker_list.send_event(tracker_list.at(3), torrent::tracker::TrackerState::EVENT_NONE); TEST_TRACKERS_IS_BUSY_5("01110", "01110"); CPPUNIT_ASSERT( tracker_list.has_active()); CPPUNIT_ASSERT( tracker_list.has_active_not_scrape()); CPPUNIT_ASSERT(check_has_active_in_group(&tracker_list, "100100", false)); CPPUNIT_ASSERT(check_has_active_in_group(&tracker_list, "110100", true)); CPPUNIT_ASSERT(tracker_1_worker->trigger_success()); TEST_TRACKERS_IS_BUSY_5("00110", "00110"); CPPUNIT_ASSERT( tracker_list.has_active()); CPPUNIT_ASSERT( tracker_list.has_active_not_scrape()); CPPUNIT_ASSERT(check_has_active_in_group(&tracker_list, "000100", false)); CPPUNIT_ASSERT(check_has_active_in_group(&tracker_list, "010100", true)); CPPUNIT_ASSERT(tracker_2_worker->trigger_scrape()); CPPUNIT_ASSERT(tracker_3_worker->trigger_success()); TEST_TRACKERS_IS_BUSY_5("00000", "00000"); CPPUNIT_ASSERT(!tracker_list.has_active()); CPPUNIT_ASSERT(!tracker_list.has_active_not_scrape()); CPPUNIT_ASSERT(check_has_active_in_group(&tracker_list, "000000", false)); CPPUNIT_ASSERT(check_has_active_in_group(&tracker_list, "000000", true)); } libtorrent-0.16.11/test/torrent/test_tracker_controller_requesting.cc0000644000000000000000000001550415175073411021672 #include "config.h" #include #include #include "test/helpers/test_thread.h" #include "test/torrent/test_tracker_controller_requesting.h" #include "test/torrent/test_tracker_list.h" #include "src/tracker/thread_tracker.h" CPPUNIT_TEST_SUITE_REGISTRATION(TestTrackerControllerRequesting); void TestTrackerControllerRequesting::do_test_hammering_basic(bool success1, bool success2, bool success3, uint32_t min_interval) { TEST_SINGLE_BEGIN(); TEST_SEND_SINGLE_BEGIN(start); auto tracker_0_0_worker = TrackerTest::test_worker(tracker_0_0); if (min_interval != 0) tracker_0_0_worker->set_new_min_interval(min_interval); else tracker_0_0_worker->set_new_min_interval(600); CPPUNIT_ASSERT(tracker_0_0.is_busy()); CPPUNIT_ASSERT(success1 ? tracker_0_0_worker->trigger_success() : tracker_0_0_worker->trigger_failure()); CPPUNIT_ASSERT(test_tracker_value_in_range(tracker_controller.seconds_to_next_timeout(), tracker_0_0.state().normal_interval() - 2, tracker_0_0.state().normal_interval() + 2)); CPPUNIT_ASSERT(!(tracker_controller.flags() & torrent::TrackerController::flag_promiscuous_mode)); tracker_controller.start_requesting(); CPPUNIT_ASSERT(!tracker_0_0.is_busy()); CPPUNIT_ASSERT(test_goto_next_timeout(this, &tracker_controller, 0)); CPPUNIT_ASSERT(!tracker_0_0.is_busy()); CPPUNIT_ASSERT((tracker_controller.flags() & torrent::TrackerController::flag_requesting)); CPPUNIT_ASSERT(test_goto_next_timeout(this, &tracker_controller, tracker_0_0.state().min_interval())); CPPUNIT_ASSERT(tracker_0_0.is_busy()); if (success2) { CPPUNIT_ASSERT(tracker_0_0_worker->trigger_success()); CPPUNIT_ASSERT(test_goto_next_timeout(this, &tracker_controller, 30)); CPPUNIT_ASSERT(test_goto_next_timeout(this, &tracker_controller, tracker_0_0.state().min_interval() - 30)); } else { CPPUNIT_ASSERT(tracker_0_0_worker->trigger_failure()); CPPUNIT_ASSERT(test_goto_next_timeout(this, &tracker_controller, 5)); CPPUNIT_ASSERT(tracker_0_0.is_busy()); } tracker_controller.stop_requesting(); CPPUNIT_ASSERT(tracker_0_0.is_busy()); CPPUNIT_ASSERT(success3 ? tracker_0_0_worker->trigger_success() : tracker_0_0_worker->trigger_failure()); TEST_SINGLE_END(success1 + success2 + success3, !success1 + !success2 + !success3); } void TestTrackerControllerRequesting::test_hammering_basic_success() { do_test_hammering_basic(true, true, true); } void TestTrackerControllerRequesting::test_hammering_basic_success_long_timeout() { do_test_hammering_basic(true, true, true, 1000); } void TestTrackerControllerRequesting::test_hammering_basic_success_short_timeout() { do_test_hammering_basic(true, true, true, 300); } void TestTrackerControllerRequesting::test_hammering_basic_failure() { do_test_hammering_basic(true, false, false); } void TestTrackerControllerRequesting::test_hammering_basic_failure_long_timeout() { do_test_hammering_basic(true, false, false, 1000); } void TestTrackerControllerRequesting::test_hammering_basic_failure_short_timeout() { do_test_hammering_basic(true, false, false, 300); } // Differentiate between failure connection / http error and tracker returned error. void TestTrackerControllerRequesting::do_test_hammering_multi3(bool success1, bool success2, bool success3, uint32_t min_interval) { TEST_MULTI3_BEGIN(); TEST_SEND_SINGLE_BEGIN(start); auto tracker_0_0_worker = TrackerTest::test_worker(tracker_0_0); auto tracker_2_0_worker = TrackerTest::test_worker(tracker_2_0); if (min_interval != 0) tracker_0_0_worker->set_new_min_interval(min_interval); else tracker_0_0_worker->set_new_min_interval(600); TEST_MULTI3_IS_BUSY("10000", "10000"); CPPUNIT_ASSERT(success1 ? tracker_0_0_worker->trigger_success() : tracker_0_0_worker->trigger_failure()); CPPUNIT_ASSERT(test_tracker_value_in_range(tracker_controller.seconds_to_next_timeout(), tracker_0_0.state().normal_interval() - 2, tracker_0_0.state().normal_interval() + 2)); CPPUNIT_ASSERT(!(tracker_controller.flags() & torrent::TrackerController::flag_promiscuous_mode)); tracker_controller.start_requesting(); TEST_MULTI3_IS_BUSY("00000", "00000"); CPPUNIT_ASSERT(test_goto_next_timeout(this, &tracker_controller, 0)); TEST_MULTI3_IS_BUSY("00111", "00111"); if (success2) CPPUNIT_ASSERT(tracker_2_0_worker->trigger_success()); else CPPUNIT_ASSERT(tracker_2_0_worker->trigger_failure()); CPPUNIT_ASSERT(test_goto_next_timeout(this, &tracker_controller, 30)); TEST_MULTI3_IS_BUSY("00101", "00101"); TrackerTest* next_tracker = tracker_0_0_worker; unsigned int next_timeout = next_tracker->test_state().min_interval(); const char* next_is_busy = "10111"; if (tracker_0_0.state().min_interval() < tracker_2_0.state().min_interval()) { CPPUNIT_ASSERT(test_goto_next_timeout(this, &tracker_controller, next_tracker->test_state().min_interval() - 30)); TEST_MULTI3_IS_BUSY("10101", "10101"); } else if (tracker_0_0.state().min_interval() > tracker_2_0.state().min_interval()) { next_tracker = tracker_2_0_worker; next_timeout = tracker_0_0.state().min_interval() - tracker_2_0.state().min_interval(); next_is_busy = "10101"; CPPUNIT_ASSERT(test_goto_next_timeout(this, &tracker_controller, next_tracker->test_state().min_interval() - 30)); TEST_MULTI3_IS_BUSY("00111", "00111"); } else { CPPUNIT_ASSERT(test_goto_next_timeout(this, &tracker_controller, next_tracker->test_state().min_interval() - 30)); TEST_MULTI3_IS_BUSY("10111", "10111"); } if (success2) { CPPUNIT_ASSERT(next_tracker->trigger_success()); CPPUNIT_ASSERT(test_goto_next_timeout(this, &tracker_controller, 30)); CPPUNIT_ASSERT(test_goto_next_timeout(this, &tracker_controller, next_timeout - 30)); TEST_MULTI3_IS_BUSY(next_is_busy, next_is_busy); } else { CPPUNIT_ASSERT(next_tracker->trigger_failure()); CPPUNIT_ASSERT(test_goto_next_timeout(this, &tracker_controller, 5)); TEST_MULTI3_IS_BUSY("10000", "10000"); } tracker_controller.stop_requesting(); TEST_MULTI3_IS_BUSY(next_is_busy, next_is_busy); CPPUNIT_ASSERT(success3 ? tracker_0_0_worker->trigger_success() : tracker_0_0_worker->trigger_failure()); TEST_MULTIPLE_END(success1 + 2*success2 + success3, !success1 + 2*!success2 + !success3); } void TestTrackerControllerRequesting::test_hammering_multi_success() { do_test_hammering_multi3(true, true, true); } void TestTrackerControllerRequesting::test_hammering_multi_success_long_timeout() { do_test_hammering_multi3(true, true, true, 1000); } void TestTrackerControllerRequesting::test_hammering_multi_success_short_timeout() { do_test_hammering_multi3(true, true, true, 300); } void TestTrackerControllerRequesting::test_hammering_multi_failure() { } libtorrent-0.16.11/test/torrent/test_tracker_timeout.cc0000644000000000000000000001620115175073411016722 #include "config.h" #include "test/torrent/test_tracker_timeout.h" #include "test/torrent/test_tracker_list.h" #include "tracker/tracker_controller.h" CPPUNIT_TEST_SUITE_REGISTRATION(test_tracker_timeout); void test_tracker_timeout::test_set_timeout() { auto tracker = TrackerTest::new_tracker(NULL, ""); auto tracker_worker = TrackerTest::test_worker(tracker); CPPUNIT_ASSERT(tracker.state().normal_interval() == 0); tracker_worker->set_new_normal_interval(100); CPPUNIT_ASSERT(tracker.state().normal_interval() == 600); tracker_worker->set_new_normal_interval(8 * 4000); CPPUNIT_ASSERT(tracker.state().normal_interval() == 8 * 3600); tracker_worker->set_new_min_interval(100); CPPUNIT_ASSERT_EQUAL((uint32_t)300, tracker.state().min_interval()); tracker_worker->set_new_min_interval(4 * 4000); CPPUNIT_ASSERT(tracker.state().min_interval() == 4 * 3600); } void test_tracker_timeout::test_timeout_tracker() { auto tracker = TrackerTest::new_tracker(NULL, "http://tracker.com/announce"); auto tracker_worker = TrackerTest::test_worker(tracker); int flags = 0; CPPUNIT_ASSERT(torrent::tracker_next_timeout(tracker, flags) == 0); m_main_thread->test_add_cached_time(std::chrono::seconds(3)); CPPUNIT_ASSERT(torrent::tracker_next_timeout(tracker, flags) == 0); flags = torrent::TrackerController::flag_active; CPPUNIT_ASSERT(torrent::tracker_next_timeout(tracker, flags) == 0); tracker_worker->send_event(torrent::tracker::TrackerState::EVENT_NONE); CPPUNIT_ASSERT(torrent::tracker_next_timeout(tracker, flags) == ~uint32_t()); tracker_worker->send_event(torrent::tracker::TrackerState::EVENT_SCRAPE); CPPUNIT_ASSERT(torrent::tracker_next_timeout(tracker, flags) == 0); tracker_worker->close(); tracker_worker->set_success(1, torrent::this_thread::cached_seconds().count()); // Check also failed... CPPUNIT_ASSERT_EQUAL((uint32_t)1800, torrent::tracker_next_timeout(tracker, flags)); // CPPUNIT_ASSERT(1800 <= torrent::tracker_next_timeout(tracker, flags) && torrent::tracker_next_timeout(tracker, flags) <= 1800 + 3); tracker_worker->send_event(torrent::tracker::TrackerState::EVENT_NONE); CPPUNIT_ASSERT(torrent::tracker_next_timeout(tracker, flags) == ~uint32_t()); tracker_worker->send_event(torrent::tracker::TrackerState::EVENT_SCRAPE); CPPUNIT_ASSERT_EQUAL((uint32_t)1800, torrent::tracker_next_timeout(tracker, flags)); // CPPUNIT_ASSERT(1800 <= torrent::tracker_next_timeout(tracker, flags) && torrent::tracker_next_timeout(tracker, flags) <= 1800 + 3); tracker_worker->close(); tracker_worker->set_success(1, torrent::this_thread::cached_seconds().count() - 3); CPPUNIT_ASSERT_EQUAL((uint32_t)(1800 - 3), torrent::tracker_next_timeout(tracker, flags)); tracker_worker->set_success(1, torrent::this_thread::cached_seconds().count() + 3); CPPUNIT_ASSERT_EQUAL((uint32_t)(1800 + 3), torrent::tracker_next_timeout(tracker, flags)); tracker_worker->close(); flags = torrent::TrackerController::flag_active | torrent::TrackerController::flag_promiscuous_mode; CPPUNIT_ASSERT(torrent::tracker_next_timeout(tracker, flags) == 0); tracker_worker->send_event(torrent::tracker::TrackerState::EVENT_NONE); CPPUNIT_ASSERT(torrent::tracker_next_timeout(tracker, flags) == ~uint32_t()); tracker_worker->send_event(torrent::tracker::TrackerState::EVENT_SCRAPE); CPPUNIT_ASSERT(torrent::tracker_next_timeout(tracker, flags) == 0); } void test_tracker_timeout::test_timeout_update() { auto tracker = TrackerTest::new_tracker(NULL, "http://tracker.com/announce"); auto tracker_worker = TrackerTest::test_worker(tracker); int flags = 0; flags = torrent::TrackerController::flag_active | torrent::TrackerController::flag_send_update; CPPUNIT_ASSERT(torrent::tracker_next_timeout(tracker, flags) == 0); tracker_worker->send_event(torrent::tracker::TrackerState::EVENT_SCRAPE); CPPUNIT_ASSERT(torrent::tracker_next_timeout(tracker, flags) == 0); tracker_worker->send_event(torrent::tracker::TrackerState::EVENT_NONE); CPPUNIT_ASSERT(torrent::tracker_next_timeout(tracker, flags) == ~uint32_t()); tracker_worker->close(); tracker_worker->set_failed(1, torrent::this_thread::cached_seconds().count()); CPPUNIT_ASSERT(torrent::tracker_next_timeout(tracker, flags) == 0); tracker_worker->set_failed(0, torrent::this_thread::cached_seconds().count()); tracker_worker->set_success(0, torrent::this_thread::cached_seconds().count()); CPPUNIT_ASSERT(torrent::tracker_next_timeout(tracker, flags) == 0); } void test_tracker_timeout::test_timeout_requesting() { auto tracker = TrackerTest::new_tracker(NULL, "http://tracker.com/announce"); auto tracker_worker = TrackerTest::test_worker(tracker); int flags = 0; flags = torrent::TrackerController::flag_active | torrent::TrackerController::flag_requesting; CPPUNIT_ASSERT(torrent::tracker_next_timeout(tracker, flags) == 0); tracker_worker->send_event(torrent::tracker::TrackerState::EVENT_SCRAPE); CPPUNIT_ASSERT(torrent::tracker_next_timeout(tracker, flags) == 0); tracker_worker->send_event(torrent::tracker::TrackerState::EVENT_NONE); CPPUNIT_ASSERT(torrent::tracker_next_timeout(tracker, flags) == ~uint32_t()); // tracker_worker->set_latest_new_peers(10 - 1); tracker_worker->close(); tracker_worker->set_failed(1, torrent::this_thread::cached_seconds().count()); CPPUNIT_ASSERT(torrent::tracker_next_timeout(tracker, flags) == 5); tracker_worker->set_failed(2, torrent::this_thread::cached_seconds().count()); CPPUNIT_ASSERT(torrent::tracker_next_timeout(tracker, flags) == 10); tracker_worker->set_failed(6 + 1, torrent::this_thread::cached_seconds().count()); CPPUNIT_ASSERT_EQUAL((uint32_t)299, torrent::tracker_next_timeout(tracker, flags)); tracker_worker->set_failed(7 + 1, torrent::this_thread::cached_seconds().count()); CPPUNIT_ASSERT_EQUAL((uint32_t)299, torrent::tracker_next_timeout(tracker, flags)); //std::cout << "timeout:" << torrent::tracker_next_timeout(tracker, flags) << std::endl; tracker_worker->set_failed(0, torrent::this_thread::cached_seconds().count()); tracker_worker->set_success(0, torrent::this_thread::cached_seconds().count()); // CPPUNIT_ASSERT(torrent::tracker_next_timeout(tracker, flags) == 10); // tracker_worker->set_success(1, torrent::this_thread::cached_seconds().count()); // CPPUNIT_ASSERT(torrent::tracker_next_timeout(tracker, flags) == 20); // tracker_worker->set_success(2, torrent::this_thread::cached_seconds().count()); CPPUNIT_ASSERT(torrent::tracker_next_timeout(tracker, flags) == 600); tracker_worker->set_success(6, torrent::this_thread::cached_seconds().count()); CPPUNIT_ASSERT(torrent::tracker_next_timeout(tracker, flags) == 600); tracker_worker->set_success(1, torrent::this_thread::cached_seconds().count()); // tracker_worker->set_latest_sum_peers(9); // CPPUNIT_ASSERT(torrent::tracker_next_timeout(tracker, flags) == 20); tracker_worker->set_latest_sum_peers(10); CPPUNIT_ASSERT(torrent::tracker_next_timeout(tracker, flags) == 600); tracker_worker->set_latest_sum_peers(10); tracker_worker->set_latest_new_peers(10); tracker_worker->set_success(1, torrent::this_thread::cached_seconds().count()); CPPUNIT_ASSERT(torrent::tracker_next_timeout(tracker, flags) == 600); } libtorrent-0.16.11/test/torrent/test_tracker_controller_features.h0000644000000000000000000000144015175073411021156 #include "test/helpers/test_main_thread.h" class test_tracker_controller_features : public TestFixtureWithMainAndTrackerThread { CPPUNIT_TEST_SUITE(test_tracker_controller_features); CPPUNIT_TEST(test_requesting_basic); CPPUNIT_TEST(test_requesting_timeout); CPPUNIT_TEST(test_promiscious_timeout); CPPUNIT_TEST(test_promiscious_failed); CPPUNIT_TEST(test_scrape_basic); CPPUNIT_TEST(test_scrape_priority); CPPUNIT_TEST(test_groups_requesting); CPPUNIT_TEST(test_groups_scrape); CPPUNIT_TEST_SUITE_END(); public: void test_requesting_basic(); void test_requesting_timeout(); void test_promiscious_timeout(); void test_promiscious_failed(); void test_scrape_basic(); void test_scrape_priority(); void test_groups_requesting(); void test_groups_scrape(); }; libtorrent-0.16.11/test/torrent/object_stream_test.h0000644000000000000000000000126215175073411016205 #include #include "torrent/object_stream.h" class ObjectStreamTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(ObjectStreamTest); CPPUNIT_TEST(testInputOrdered); CPPUNIT_TEST(testInputNullKey); CPPUNIT_TEST(testOutputMask); CPPUNIT_TEST(testBuffer); CPPUNIT_TEST(testReadBencodeC); CPPUNIT_TEST(test_read_skip); CPPUNIT_TEST(test_read_skip_invalid); CPPUNIT_TEST(test_write); CPPUNIT_TEST_SUITE_END(); public: void testInputOrdered(); void testInputNullKey(); void testOutputMask(); void testBuffer(); void testReadBencodeC(); void test_read_skip(); void test_read_skip_invalid(); void test_write(); }; libtorrent-0.16.11/test/torrent/test_tracker_timeout.h0000644000000000000000000000073615175073411016572 #include "test/helpers/test_main_thread.h" class test_tracker_timeout : public TestFixtureWithMainAndTrackerThread { CPPUNIT_TEST_SUITE(test_tracker_timeout); CPPUNIT_TEST(test_set_timeout); CPPUNIT_TEST(test_timeout_tracker); CPPUNIT_TEST(test_timeout_update); CPPUNIT_TEST(test_timeout_requesting); CPPUNIT_TEST_SUITE_END(); public: void test_set_timeout(); void test_timeout_tracker(); void test_timeout_update(); void test_timeout_requesting(); }; libtorrent-0.16.11/test/protocol/0000755000000000000000000000000015175073435012405 5libtorrent-0.16.11/test/protocol/test_request_list.h0000644000000000000000000000110615175073411016250 #include "test/helpers/test_fixture.h" class TestRequestList : public test_fixture { CPPUNIT_TEST_SUITE(TestRequestList); CPPUNIT_TEST(test_basic); CPPUNIT_TEST(test_single_request); CPPUNIT_TEST(test_single_canceled); CPPUNIT_TEST(test_choke_normal); CPPUNIT_TEST(test_choke_unchoke_discard); CPPUNIT_TEST(test_choke_unchoke_transfer); CPPUNIT_TEST_SUITE_END(); public: void test_basic(); void test_single_request(); void test_single_canceled(); void test_choke_normal(); void test_choke_unchoke_discard(); void test_choke_unchoke_transfer(); }; libtorrent-0.16.11/test/protocol/test_request_list.cc0000644000000000000000000002143015175073411016410 #include "config.h" #include "test/protocol/test_request_list.h" #include "download/delegator.h" #include "protocol/peer_chunks.h" #include "protocol/request_list.h" #include "test/helpers/network.h" #include "test/helpers/test_main_thread.h" #include "torrent/exceptions.h" #include "torrent/peer/peer_info.h" CPPUNIT_TEST_SUITE_REGISTRATION(TestRequestList); static uint32_t chunk_index_size([[maybe_unused]] uint32_t index) { return 1 << 10; } static void transfer_list_void() { // std::cout << "list_void" << std::endl; } static void transfer_list_completed(torrent::TransferList* transfer_list, uint32_t index) { torrent::TransferList::iterator itr = transfer_list->find(index); // std::cout << "list_completed:" << index << " found: " << (itr != transfer_list->end()) << std::endl; CPPUNIT_ASSERT(itr != transfer_list->end()); transfer_list->erase(itr); } struct RequestListGuard { RequestListGuard(torrent::RequestList* rl) : request_list(rl) {} ~RequestListGuard() { if (request_list == nullptr || completed) return; request_list->clear(); request_list->delegator()->transfer_list()->clear(); } bool completed{false}; torrent::RequestList* request_list; }; #define SETUP_DELEGATOR(fpc_prefix) \ auto delegator = std::make_unique(); \ delegator->slot_chunk_find() = std::bind(&fpc_prefix ## _find_peer_chunk, std::placeholders::_1, std::placeholders::_2); \ delegator->slot_chunk_size() = std::bind(&chunk_index_size, std::placeholders::_1); \ delegator->transfer_list()->slot_canceled() = std::bind(&transfer_list_void); \ delegator->transfer_list()->slot_queued() = std::bind(&transfer_list_void); \ delegator->transfer_list()->slot_completed() = std::bind(&transfer_list_completed, delegator->transfer_list(), std::placeholders::_1); \ delegator->transfer_list()->slot_corrupt() = std::bind(&transfer_list_void); // Set bitfield size... #define SETUP_PEER_CHUNKS() \ auto peer_info = std::make_unique(wrap_ai_get_first_sa("1.2.3.4", "5000").get()); \ auto peer_chunks = std::make_unique(); \ peer_chunks->set_peer_info(peer_info.get()); #define SETUP_REQUEST_LIST() \ auto request_list = std::make_unique(); \ RequestListGuard request_list_guard(request_list.get()); \ request_list->set_delegator(delegator.get()); \ request_list->set_peer_chunks(peer_chunks.get()); #define SETUP_ALL(fpc_prefix) \ auto test_main_thread = TestMainThread::create(); \ test_main_thread->init_thread(); \ test_main_thread->test_set_cached_time(0s); \ SETUP_DELEGATOR(basic); \ SETUP_PEER_CHUNKS(); \ SETUP_REQUEST_LIST(); #define SETUP_ALL_WITH_3(fpc_prefix) \ SETUP_ALL(fpc_prefix); \ auto pieces = request_list->delegate(3); \ CPPUNIT_ASSERT(pieces.size() == 3); \ const torrent::Piece* piece_1 = pieces[0]; \ const torrent::Piece* piece_2 = pieces[1]; \ const torrent::Piece* piece_3 = pieces[2]; \ CPPUNIT_ASSERT(piece_1 && piece_2 && piece_3); #define CLEAR_TRANSFERS(fpc_prefix) \ delegator->transfer_list()->clear(); \ request_list_guard.completed = true; // // // #define VERIFY_QUEUE_SIZES(s_0, s_1, s_2, s_3) \ CPPUNIT_ASSERT(request_list->queued_size() == s_0); \ CPPUNIT_ASSERT(request_list->unordered_size() == s_1); \ CPPUNIT_ASSERT(request_list->stalled_size() == s_2); \ CPPUNIT_ASSERT(request_list->choked_size() == s_3); #define VERIFY_PIECE_IS_LEADER(piece) \ CPPUNIT_ASSERT(request_list->transfer() != NULL); \ CPPUNIT_ASSERT(request_list->transfer()->is_leader()); \ CPPUNIT_ASSERT(request_list->transfer()->peer_info() != NULL); \ CPPUNIT_ASSERT(request_list->transfer()->peer_info() == peer_info.get()); #define VERIFY_TRANSFER_COUNTER(transfer, count) \ CPPUNIT_ASSERT(transfer != NULL); \ CPPUNIT_ASSERT(transfer->peer_info() != NULL); \ CPPUNIT_ASSERT(transfer->peer_info()->transfer_counter() == count); // // Basic tests: // static uint32_t basic_find_peer_chunk([[maybe_unused]] torrent::PeerChunks* peerChunk, [[maybe_unused]] bool highPriority) { static int next_index = 0; return next_index++; } void TestRequestList::test_basic() { SETUP_ALL(basic); CPPUNIT_ASSERT(!request_list->is_downloading()); CPPUNIT_ASSERT(!request_list->is_interested_in_active()); VERIFY_QUEUE_SIZES(0, 0, 0, 0); CPPUNIT_ASSERT(request_list->calculate_pipe_size(1024 * 0) == 2); CPPUNIT_ASSERT(request_list->calculate_pipe_size(1024 * 10) == 12); CPPUNIT_ASSERT(request_list->transfer() == NULL); } void TestRequestList::test_single_request() { SETUP_ALL(basic); auto pieces = request_list->delegate(1); CPPUNIT_ASSERT(pieces.size() == 1); const torrent::Piece* piece = pieces[0]; // std::cout << piece->index() << ' ' << piece->offset() << ' ' << piece->length() << std::endl; // std::cout << peer_info->transfer_counter() << std::endl; CPPUNIT_ASSERT(request_list->downloading(*piece)); VERIFY_PIECE_IS_LEADER(*piece); VERIFY_TRANSFER_COUNTER(request_list->transfer(), 1); request_list->transfer()->adjust_position(piece->length()); CPPUNIT_ASSERT(request_list->transfer()->is_finished()); request_list->finished(); CPPUNIT_ASSERT(peer_info->transfer_counter() == 0); } void TestRequestList::test_single_canceled() { SETUP_ALL(basic); auto pieces = request_list->delegate(1); CPPUNIT_ASSERT(pieces.size() == 1); const torrent::Piece* piece = pieces[0]; // std::cout << piece->index() << ' ' << piece->offset() << ' ' << piece->length() << std::endl; // std::cout << peer_info->transfer_counter() << std::endl; CPPUNIT_ASSERT(request_list->downloading(*piece)); VERIFY_PIECE_IS_LEADER(*piece); // REMOVE VERIFY_TRANSFER_COUNTER(request_list->transfer(), 1); // REMOVE request_list->transfer()->adjust_position(piece->length() / 2); CPPUNIT_ASSERT(!request_list->transfer()->is_finished()); request_list->skipped(); // The transfer remains in Block until it gets the block has a // transfer trigger finished. // TODO: We need to have a way of clearing disowned transfers, then // make transfer list delete Block's(?) with those before dtor... CPPUNIT_ASSERT(peer_info->transfer_counter() == 0); CLEAR_TRANSFERS(); } void TestRequestList::test_choke_normal() { SETUP_ALL_WITH_3(basic); VERIFY_QUEUE_SIZES(3, 0, 0, 0); request_list->choked(); test_main_thread->test_set_cached_time(1s); test_main_thread->test_process_events_without_cached_time(); VERIFY_QUEUE_SIZES(0, 0, 0, 3); test_main_thread->test_set_cached_time(1s + 6s); test_main_thread->test_process_events_without_cached_time(); VERIFY_QUEUE_SIZES(0, 0, 0, 0); CLEAR_TRANSFERS(); } void TestRequestList::test_choke_unchoke_discard() { SETUP_ALL_WITH_3(basic); request_list->choked(); test_main_thread->test_set_cached_time(5s); test_main_thread->test_process_events_without_cached_time(); request_list->unchoked(); test_main_thread->test_set_cached_time(5s + 5s); test_main_thread->test_process_events_without_cached_time(); VERIFY_QUEUE_SIZES(0, 0, 0, 3); test_main_thread->test_set_cached_time(5s + 60s); test_main_thread->test_process_events_without_cached_time(); VERIFY_QUEUE_SIZES(0, 0, 0, 0); CLEAR_TRANSFERS(); } void TestRequestList::test_choke_unchoke_transfer() { SETUP_ALL_WITH_3(basic); request_list->choked(); test_main_thread->test_set_cached_time(5s); test_main_thread->test_process_events_without_cached_time(); request_list->unchoked(); test_main_thread->test_set_cached_time(5s + 5s); test_main_thread->test_process_events_without_cached_time(); CPPUNIT_ASSERT(request_list->downloading(*piece_1)); request_list->transfer()->adjust_position(piece_1->length()); request_list->finished(); test_main_thread->test_set_cached_time(10s + 50s); test_main_thread->test_process_events_without_cached_time(); CPPUNIT_ASSERT(request_list->downloading(*piece_2)); request_list->transfer()->adjust_position(piece_2->length()); request_list->finished(); test_main_thread->test_set_cached_time(60s + 50s); test_main_thread->test_process_events_without_cached_time(); CPPUNIT_ASSERT(request_list->downloading(*piece_3)); request_list->transfer()->adjust_position(piece_3->length()); request_list->finished(); VERIFY_QUEUE_SIZES(0, 0, 0, 0); CLEAR_TRANSFERS(); } libtorrent-0.16.11/test/rak/0000755000000000000000000000000015175073435011321 5libtorrent-0.16.11/test/rak/ranges_test.h0000644000000000000000000000061115175073411013720 #include #include #include "torrent/utils/ranges.h" class RangesTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(RangesTest); CPPUNIT_TEST(test_basic); CPPUNIT_TEST(test_intersect); CPPUNIT_TEST(test_create_union); CPPUNIT_TEST_SUITE_END(); public: void test_basic(); void test_intersect(); void test_create_union(); }; libtorrent-0.16.11/test/rak/ranges_test.cc0000644000000000000000000000776415175073411014076 #include "config.h" #include #include "ranges_test.h" CPPUNIT_TEST_SUITE_REGISTRATION(RangesTest); template bool verify_ranges(const torrent::ranges& ranges) { typename torrent::ranges::const_iterator first = ranges.begin(); typename torrent::ranges::const_iterator last = ranges.begin(); if (first == last) return true; if (first->second <= first->first) return false; Type boundary = first++->second; do { if (first->first <= boundary) return false; if (first->second <= first->first) return false; } while (++first != last); return true; } void RangesTest::test_basic() { } void RangesTest::test_intersect() { torrent::ranges range; CPPUNIT_ASSERT(verify_ranges(range)); CPPUNIT_ASSERT(range.intersect_distance(0, 0) == 0); CPPUNIT_ASSERT(range.intersect_distance(0, 10) == 0); range.insert(0, 5); CPPUNIT_ASSERT(verify_ranges(range)); CPPUNIT_ASSERT(range.intersect_distance(0, 5) == 5); CPPUNIT_ASSERT(range.intersect_distance(0, 10) == 5); CPPUNIT_ASSERT(range.intersect_distance(-5, 5) == 5); CPPUNIT_ASSERT(range.intersect_distance(-5, 10) == 5); CPPUNIT_ASSERT(range.intersect_distance(2, 2) == 0); CPPUNIT_ASSERT(range.intersect_distance(1, 4) == 3); CPPUNIT_ASSERT(range.intersect_distance(1, 10) == 4); CPPUNIT_ASSERT(range.intersect_distance(-5, 4) == 4); range.insert(10, 15); CPPUNIT_ASSERT(verify_ranges(range)); CPPUNIT_ASSERT(range.intersect_distance(0, 15) == 10); CPPUNIT_ASSERT(range.intersect_distance(0, 20) == 10); CPPUNIT_ASSERT(range.intersect_distance(-5, 15) == 10); CPPUNIT_ASSERT(range.intersect_distance(-5, 20) == 10); CPPUNIT_ASSERT(range.intersect_distance(2, 12) == 5); CPPUNIT_ASSERT(range.intersect_distance(1, 14) == 8); CPPUNIT_ASSERT(range.intersect_distance(1, 20) == 9); CPPUNIT_ASSERT(range.intersect_distance(-5, 14) == 9); } void RangesTest::test_create_union() { torrent::ranges range_1l; torrent::ranges range_1r; torrent::ranges range_1u; // Empty: range_1u = torrent::ranges::create_union(range_1l, range_1r); CPPUNIT_ASSERT(verify_ranges(range_1u)); CPPUNIT_ASSERT(range_1u.intersect_distance(-5, 20) == 0); range_1l.insert(0, 5); // Left one entry: range_1u = torrent::ranges::create_union(range_1l, range_1r); CPPUNIT_ASSERT(verify_ranges(range_1u)); CPPUNIT_ASSERT(range_1u.intersect_distance(-5, 20) == 5); // Right one entry: range_1u = torrent::ranges::create_union(range_1r, range_1l); CPPUNIT_ASSERT(verify_ranges(range_1u)); CPPUNIT_ASSERT(range_1u.intersect_distance(-5, 20) == 5); range_1r.insert(10, 15); // Both one entry: range_1u = torrent::ranges::create_union(range_1l, range_1r); // std::cout << "range_1u.intersect_distance(-5, 20) = " << range_1u.intersect_distance(-5, 20) << std::endl; CPPUNIT_ASSERT(verify_ranges(range_1u)); CPPUNIT_ASSERT(range_1u.intersect_distance(-5, 20) == 10); range_1r.insert(4, 6); // Overlap: range_1u = torrent::ranges::create_union(range_1l, range_1r); // std::cout << "range_1u.intersect_distance(-5, 20) = " << range_1u.intersect_distance(-5, 20) << std::endl; CPPUNIT_ASSERT(verify_ranges(range_1u)); CPPUNIT_ASSERT(range_1u.intersect_distance(-5, 20) == 11); range_1r.insert(9, 10); // Boundary: range_1u = torrent::ranges::create_union(range_1l, range_1r); CPPUNIT_ASSERT(verify_ranges(range_1u)); CPPUNIT_ASSERT(range_1u.intersect_distance(-5, 20) == 12); // Trailing ranges left. range_1l.insert(25, 30); range_1l.insert(35, 40); range_1u = torrent::ranges::create_union(range_1l, range_1r); CPPUNIT_ASSERT(verify_ranges(range_1u)); CPPUNIT_ASSERT(range_1u.intersect_distance(-5, 50) == 22); // Trailing ranges right. range_1r.insert(37, 45); range_1r.insert(50, 55); range_1u = torrent::ranges::create_union(range_1l, range_1r); CPPUNIT_ASSERT(verify_ranges(range_1u)); CPPUNIT_ASSERT(range_1u.intersect_distance(-5, 60) == 32); } libtorrent-0.16.11/test/helpers/0000755000000000000000000000000015175073435012206 5libtorrent-0.16.11/test/helpers/mock_function.h0000644000000000000000000001327015175073411015132 #ifndef LIBTORRENT_HELPERS_MOCK_FUNCTION_H #define LIBTORRENT_HELPERS_MOCK_FUNCTION_H #include #include #include #include #include #include #include #include #include "test/helpers/mock_compare.h" namespace torrent { extern int fd__accept(int socket, sockaddr *address, socklen_t *address_len); extern int fd__bind(int socket, const sockaddr *address, socklen_t address_len); extern int fd__close(int fildes); extern int fd__connect(int socket, const sockaddr *address, socklen_t address_len); extern int fd__fcntl_int(int fildes, int cmd, int arg); extern int fd__listen(int socket, int backlog); extern int fd__setsockopt_int(int socket, int level, int option_name, int option_value); extern int fd__socket(int domain, int type, int protocol); } enum mock_redirect_flags { mock_redirect_all = ~0, }; void mock_init(); void mock_cleanup(); void mock_redirect_defaults(mock_redirect_flags flags = mock_redirect_all); template struct mock_function_map { typedef std::tuple call_type; typedef std::vector call_list_type; typedef std::map func_map_type; typedef std::function function_type; typedef std::map redirect_map_type; static std::mutex mutex; static func_map_type functions; static redirect_map_type redirects; static bool cleanup(void* fn) { std::lock_guard lock(mutex); redirects.erase(fn); return functions.erase(fn) == 0; } static R ret_erase(void* fn) { auto itr = functions.find(fn); auto ret = std::get<0>(itr->second.front()); itr->second.erase(itr->second.begin()); if (itr->second.empty()) functions.erase(itr); return ret; } }; template std::mutex mock_function_map::mutex; template typename mock_function_map::func_map_type mock_function_map::functions; template typename mock_function_map::redirect_map_type mock_function_map::redirects; struct mock_void {}; template struct mock_function_type { typedef mock_function_map type; static int compare_expected(typename type::call_type lhs, Args... rhs) { return mock_compare_tuple(lhs, std::make_tuple(rhs...)); } static R ret_erase(void* fn) { return type::ret_erase(fn); } static bool has_redirect(void* fn) { std::lock_guard lock(type::mutex); return type::redirects.find(fn) != type::redirects.end(); } static R call_redirect(void* fn, Args... args) { std::lock_guard lock(type::mutex); return type::redirects.find(fn)->second(args...); } }; template struct mock_function_type { typedef mock_function_map type; static int compare_expected(typename type::call_type lhs, Args... rhs) { return mock_compare_tuple(lhs, std::make_tuple(rhs...)); } static void ret_erase(void* fn) { type::ret_erase(fn); } static bool has_redirect(void* fn) { std::lock_guard lock(type::mutex); return type::redirects.find(fn) != type::redirects.end(); } static void call_redirect(void* fn, Args... args) { std::lock_guard lock(type::mutex); type::redirects.find(fn)->second(args...); } }; template bool mock_cleanup_map(R fn(Args...)) { return mock_function_type::type::cleanup(reinterpret_cast(fn)); } template void mock_expect(R fn(Args...), R ret, Args... args) { typedef mock_function_map mock_map; std::lock_guard lock(mock_map::mutex); mock_map::functions[reinterpret_cast(fn)].push_back(std::tuple(ret, args...)); } template void mock_expect(void fn(Args...), Args... args) { typedef mock_function_map mock_map; std::lock_guard lock(mock_map::mutex); mock_map::functions[reinterpret_cast(fn)].push_back(std::tuple(mock_void(), args...)); } template void mock_redirect(R fn(Args...), std::function func) { typedef mock_function_map mock_map; std::lock_guard lock(mock_map::mutex); mock_map::redirects[reinterpret_cast(fn)] = func; } template auto mock_call_direct(std::string name, R fn(Args...), Args... args) -> decltype(fn(args...)) { typedef mock_function_type mock_type; std::lock_guard lock(mock_type::type::mutex); auto itr = mock_type::type::functions.find(reinterpret_cast(fn)); CPPUNIT_ASSERT_MESSAGE(("mock_call expected function calls exhausted by '" + name + "'").c_str(), itr != mock_type::type::functions.end()); auto mismatch_arg = mock_type::compare_expected(itr->second.front(), args...); CPPUNIT_ASSERT_MESSAGE(("mock_call expected function call argument " + std::to_string(mismatch_arg) + " mismatch for '" + name + "'").c_str(), mismatch_arg == 0); return mock_type::ret_erase(reinterpret_cast(fn)); } template auto mock_call(std::string name, R fn(Args...), Args... args) -> decltype(fn(args...)) { typedef mock_function_type mock_type; if (mock_type::has_redirect(reinterpret_cast(fn))) return mock_type::call_redirect(reinterpret_cast(fn), args...); return mock_call_direct(name, fn, args...); } #endif libtorrent-0.16.11/test/helpers/test_main_thread.cc0000644000000000000000000001015215175073411015740 #include "config.h" #include "test_main_thread.h" #include #include "runtime.h" #include "data/thread_disk.h" #include "net/thread_net.h" #include "test/helpers/mock_function.h" #include "torrent/exceptions.h" #include "torrent/net/resolver.h" #include "torrent/utils/log.h" #include "torrent/utils/scheduler.h" #include "tracker/thread_tracker.h" std::unique_ptr TestMainThread::create() { // Needs to be called before Thread is created. mock_redirect_defaults(); return std::unique_ptr(new TestMainThread()); } std::unique_ptr TestMainThread::create_with_mock() { return std::unique_ptr(new TestMainThread()); } void TestMainThread::init_thread() { m_resolver = std::make_unique(); m_state = STATE_INITIALIZED; //m_instrumentation_index = INSTRUMENTATION_POLLING_DO_POLL_MAIN - INSTRUMENTATION_POLLING_DO_POLL; init_thread_local(); } void TestMainThread::cleanup_thread() { } void TestMainThread::call_events() { process_callbacks(); } std::chrono::microseconds TestMainThread::next_timeout() { return 10min; } void TestFixtureWithMainThread::setUp() { test_fixture::setUp(); m_main_thread = TestMainThread::create(); torrent::Runtime::initialize(m_main_thread.get()); m_main_thread->init_thread(); } void TestFixtureWithMainThread::tearDown() { torrent::Runtime::cleanup(); m_main_thread.reset(); test_fixture::tearDown(); } void TestFixtureWithMainAndDiskThread::setUp() { test_fixture::setUp(); m_main_thread = TestMainThread::create(); torrent::Runtime::initialize(m_main_thread.get()); m_main_thread->init_thread(); // m_hash_check_queue.slot_chunk_done() binds to main_thread(). torrent::ThreadDisk::create_thread(); torrent::thread_disk()->init_thread(); torrent::thread_disk()->start_thread(); signal(SIGUSR1, [](auto){}); } void TestFixtureWithMainAndDiskThread::tearDown() { torrent::thread_disk()->stop_thread_wait(); torrent::Runtime::cleanup(); torrent::ThreadDisk::destroy_thread(); m_main_thread.reset(); test_fixture::tearDown(); } void TestFixtureWithMainAndTrackerThread::setUp() { test_fixture::setUp(); m_main_thread = TestMainThread::create(); torrent::Runtime::initialize(m_main_thread.get()); m_main_thread->init_thread(); log_add_group_output(torrent::LOG_TRACKER_EVENTS, "test_output"); log_add_group_output(torrent::LOG_TRACKER_REQUESTS, "test_output"); torrent::ThreadTracker::create_thread(m_main_thread.get()); torrent::thread_tracker()->init_thread(); torrent::thread_tracker()->start_thread(); } void TestFixtureWithMainAndTrackerThread::tearDown() { torrent::thread_tracker()->stop_thread_wait(); torrent::Runtime::cleanup(); torrent::ThreadTracker::destroy_thread(); m_main_thread.reset(); test_fixture::tearDown(); } void TestFixtureWithMainNetTrackerThread::setUp() { test_fixture::setUp(); m_main_thread = TestMainThread::create(); torrent::Runtime::initialize(m_main_thread.get()); m_main_thread->init_thread(); log_add_group_output(torrent::LOG_TRACKER_EVENTS, "test_output"); log_add_group_output(torrent::LOG_TRACKER_REQUESTS, "test_output"); torrent::ThreadNet::create_thread(); torrent::ThreadTracker::create_thread(m_main_thread.get()); torrent::net_thread::thread()->init_thread(); torrent::thread_tracker()->init_thread(); torrent::net_thread::thread()->start_thread(); torrent::thread_tracker()->start_thread(); } void TestFixtureWithMainNetTrackerThread::tearDown() { torrent::thread_tracker()->stop_thread_wait(); torrent::net_thread::thread()->stop_thread_wait(); torrent::Runtime::cleanup(); torrent::ThreadTracker::destroy_thread(); torrent::ThreadNet::destroy_thread(); m_main_thread.reset(); test_fixture::tearDown(); } void TestFixtureWithMockAndMainThread::setUp() { test_fixture::setUp(); m_main_thread = TestMainThread::create_with_mock(); torrent::Runtime::initialize(m_main_thread.get()); m_main_thread->init_thread(); } void TestFixtureWithMockAndMainThread::tearDown() { torrent::Runtime::cleanup(); m_main_thread.reset(); test_fixture::tearDown(); } libtorrent-0.16.11/test/helpers/expect_utils.h0000644000000000000000000000052115175073411014777 #ifndef LIBTORRENT_HELPER_EXPECT_UTILS_H #define LIBTORRENT_HELPER_EXPECT_UTILS_H #include "helpers/mock_function.h" #include inline void expect_random_uniform_uint16(uint16_t result, uint16_t first, uint16_t last) { mock_expect(&torrent::random_uniform_uint16, result, first, last); } #endif libtorrent-0.16.11/test/helpers/network.h0000644000000000000000000002153015175073411013763 #ifndef LIBTORRENT_HELPER_NETWORK_H #define LIBTORRENT_HELPER_NETWORK_H #include #include #include #include "torrent/common.h" #include "torrent/net/address_info.h" #include "torrent/utils/chrono.h" bool check_event_is_readable(torrent::Event* event, std::chrono::microseconds timeout); // // Socket addresses // #define TEST_DEFAULT_SA \ auto sin_any = wrap_ai_get_first_sa("0.0.0.0"); \ auto sin_any_5000 = wrap_ai_get_first_sa("0.0.0.0", "5000"); \ auto sin_any_5005 = wrap_ai_get_first_sa("0.0.0.0", "5005"); \ auto sin_bc = wrap_ai_get_first_sa("255.255.255.255"); \ auto sin_bc_5000 = wrap_ai_get_first_sa("255.255.255.255", "5000"); \ auto sin_bnd = wrap_ai_get_first_sa("123.123.123.123"); \ auto sin_1 = wrap_ai_get_first_sa("1.2.3.4"); \ auto sin_1_5000 = wrap_ai_get_first_sa("1.2.3.4", "5000"); \ auto sin_1_5005 = wrap_ai_get_first_sa("1.2.3.4", "5005"); \ auto sin_1_5100 = wrap_ai_get_first_sa("1.2.3.4", "5100"); \ auto sin_2 = wrap_ai_get_first_sa("4.3.2.1"); \ auto sin_2_5000 = wrap_ai_get_first_sa("4.3.2.1", "5000"); \ auto sin_2_5100 = wrap_ai_get_first_sa("4.3.2.1", "5100"); \ \ auto sin6_any = wrap_ai_get_first_sa("::"); \ auto sin6_any_5000 = wrap_ai_get_first_sa("::", "5000"); \ auto sin6_any_5005 = wrap_ai_get_first_sa("::", "5005"); \ auto sin6_bnd = wrap_ai_get_first_sa("ff01::123"); \ auto sin6_1 = wrap_ai_get_first_sa("ff01::1"); \ auto sin6_1_5000 = wrap_ai_get_first_sa("ff01::1", "5000"); \ auto sin6_1_5005 = wrap_ai_get_first_sa("ff01::1", "5005"); \ auto sin6_1_5100 = wrap_ai_get_first_sa("ff01::1", "5100"); \ auto sin6_2 = wrap_ai_get_first_sa("ff02::2"); \ auto sin6_2_5000 = wrap_ai_get_first_sa("ff02::2", "5000"); \ auto sin6_2_5100 = wrap_ai_get_first_sa("ff02::2", "5100"); \ auto sin6_v4_1 = wrap_ai_get_first_sa("::ffff:1.2.3.4"); \ auto sin6_v4_1_5000 = wrap_ai_get_first_sa("::ffff:1.2.3.4", "5000"); \ auto sin6_v4_any = wrap_ai_get_first_sa("::ffff:0.0.0.0"); \ auto sin6_v4_any_5000 = wrap_ai_get_first_sa("::ffff:0.0.0.0", "5000"); \ auto sin6_v4_bc = wrap_ai_get_first_sa("::ffff:255.255.255.255"); \ auto sin6_v4_bc_5000 = wrap_ai_get_first_sa("::ffff:255.255.255.255", "5000"); \ auto sin6_v4_bnd = wrap_ai_get_first_sa("::ffff:123.123.123.123"); \ \ auto c_sin_any = wrap_ai_get_first_c_sa("0.0.0.0"); \ auto c_sin_any_5000 = wrap_ai_get_first_c_sa("0.0.0.0", "5000"); \ auto c_sin_any_5005 = wrap_ai_get_first_c_sa("0.0.0.0", "5005"); \ auto c_sin_any_5010 = wrap_ai_get_first_c_sa("0.0.0.0", "5010"); \ auto c_sin_any_6881 = wrap_ai_get_first_c_sa("0.0.0.0", "6881"); \ auto c_sin_any_6900 = wrap_ai_get_first_c_sa("0.0.0.0", "6900"); \ auto c_sin_any_6999 = wrap_ai_get_first_c_sa("0.0.0.0", "6999"); \ auto c_sin_bc = wrap_ai_get_first_c_sa("255.255.255.255"); \ auto c_sin_bc_5000 = wrap_ai_get_first_c_sa("255.255.255.255", "5000"); \ auto c_sin_bnd = wrap_ai_get_first_c_sa("123.123.123.123"); \ auto c_sin_bnd_5000 = wrap_ai_get_first_c_sa("123.123.123.123", "5000"); \ auto c_sin_bnd_6881 = wrap_ai_get_first_c_sa("123.123.123.123", "6881"); \ auto c_sin_bnd_6900 = wrap_ai_get_first_c_sa("123.123.123.123", "6900"); \ auto c_sin_bnd_6999 = wrap_ai_get_first_c_sa("123.123.123.123", "6999"); \ auto c_sin_1 = wrap_ai_get_first_c_sa("1.2.3.4"); \ auto c_sin_1_5000 = wrap_ai_get_first_c_sa("1.2.3.4", "5000"); \ auto c_sin_1_5005 = wrap_ai_get_first_c_sa("1.2.3.4", "5005"); \ auto c_sin_1_5010 = wrap_ai_get_first_c_sa("1.2.3.4", "5010"); \ auto c_sin_1_6881 = wrap_ai_get_first_c_sa("1.2.3.4", "6881"); \ auto c_sin_1_6900 = wrap_ai_get_first_c_sa("1.2.3.4", "6900"); \ auto c_sin_1_6999 = wrap_ai_get_first_c_sa("1.2.3.4", "6999"); \ auto c_sin_2 = wrap_ai_get_first_c_sa("4.3.2.1"); \ auto c_sin_2_5000 = wrap_ai_get_first_c_sa("4.3.2.1", "5000"); \ auto c_sin_2_5100 = wrap_ai_get_first_c_sa("4.3.2.1", "5100"); \ \ auto c_sin6_any = wrap_ai_get_first_c_sa("::"); \ auto c_sin6_any_5000 = wrap_ai_get_first_c_sa("::", "5000"); \ auto c_sin6_any_5005 = wrap_ai_get_first_c_sa("::", "5005"); \ auto c_sin6_any_5010 = wrap_ai_get_first_c_sa("::", "5010"); \ auto c_sin6_any_6881 = wrap_ai_get_first_c_sa("::", "6881"); \ auto c_sin6_any_6900 = wrap_ai_get_first_c_sa("::", "6900"); \ auto c_sin6_any_6999 = wrap_ai_get_first_c_sa("::", "6999"); \ auto c_sin6_bnd = wrap_ai_get_first_c_sa("ff01::123"); \ auto c_sin6_bnd_5000 = wrap_ai_get_first_c_sa("ff01::123", "5000"); \ auto c_sin6_bnd_6881 = wrap_ai_get_first_c_sa("ff01::123", "6881"); \ auto c_sin6_bnd_6900 = wrap_ai_get_first_c_sa("ff01::123", "6900"); \ auto c_sin6_bnd_6999 = wrap_ai_get_first_c_sa("ff01::123", "6999"); \ auto c_sin6_v4_1_5000 = wrap_ai_get_first_c_sa("::ffff:1.2.3.4", "5000"); \ auto c_sin6_1 = wrap_ai_get_first_c_sa("ff01::1"); \ auto c_sin6_1_5000 = wrap_ai_get_first_c_sa("ff01::1", "5000"); \ auto c_sin6_1_5005 = wrap_ai_get_first_c_sa("ff01::1", "5005"); \ auto c_sin6_1_5010 = wrap_ai_get_first_c_sa("ff01::1", "5010"); \ auto c_sin6_1_5100 = wrap_ai_get_first_c_sa("ff01::1", "5100"); \ auto c_sin6_1_6881 = wrap_ai_get_first_c_sa("ff01::1", "6881"); \ auto c_sin6_1_6900 = wrap_ai_get_first_c_sa("ff01::1", "6900"); \ auto c_sin6_1_6999 = wrap_ai_get_first_c_sa("ff01::1", "6999"); \ auto c_sin6_2 = wrap_ai_get_first_c_sa("ff02::2"); \ auto c_sin6_2_5000 = wrap_ai_get_first_c_sa("ff02::2", "5000"); \ auto c_sin6_2_5100 = wrap_ai_get_first_c_sa("ff02::2", "5100"); inline bool compare_sin6_addr(in6_addr lhs, in6_addr rhs) { return std::equal(lhs.s6_addr, lhs.s6_addr + 16, rhs.s6_addr); } inline bool compare_listen_result(const torrent::listen_result_type& lhs, int rhs_fd, const torrent::c_sa_unique_ptr& rhs_sap) { return lhs.fd == rhs_fd && ((lhs.address && rhs_sap) || ((lhs.address && rhs_sap) && torrent::sap_equal(lhs.address, rhs_sap))); } inline torrent::sa_unique_ptr wrap_ai_get_first_sa(const char* nodename, const char* servname = nullptr, const addrinfo* hints = nullptr) { auto sa = torrent::ai_get_first_sa(nodename, servname, hints); CPPUNIT_ASSERT_MESSAGE(("wrap_ai_get_first_sa: nodename:'" + std::string(nodename) + "'").c_str(), sa != nullptr); return sa; } inline torrent::c_sa_unique_ptr wrap_ai_get_first_c_sa(const char* nodename, const char* servname = nullptr, const addrinfo* hints = nullptr) { auto sa = torrent::ai_get_first_sa(nodename, servname, hints); CPPUNIT_ASSERT_MESSAGE(("wrap_ai_get_first_sa: nodename:'" + std::string(nodename) + "'").c_str(), sa != nullptr); return torrent::c_sa_unique_ptr(sa.release()); } // // Address info tests: // typedef std::function test_ai_ref; enum ai_flags_enum : int { aif_none = 0x0, aif_inet = 0x1, aif_inet6 = 0x2, aif_any = 0x4, }; constexpr ai_flags_enum operator | (ai_flags_enum a, ai_flags_enum b) { return static_cast(static_cast(a) | static_cast(b)); } template inline bool test_valid_ai_ref(test_ai_ref ftor, uint16_t port = 0) { torrent::ai_unique_ptr ai; if (int err = ftor(ai)) { std::cout << std::endl << "valid_ai_ref got error '" << gai_strerror(err) << "'" << std::endl; return false; } if ((ai_flags & aif_inet) && !torrent::sa_is_inet(ai->ai_addr)) return false; if ((ai_flags & aif_inet6) && !torrent::sa_is_inet6(ai->ai_addr)) return false; if (!!(ai_flags & aif_any) == !torrent::sa_is_any(ai->ai_addr)) return false; if (torrent::sa_port(ai->ai_addr) != port) return false; return true; } inline bool test_valid_ai_ref_err(test_ai_ref ftor, int expect_err) { torrent::ai_unique_ptr ai; int err = ftor(ai); if (err != expect_err) { std::cout << std::endl << "ai_ref_err got wrong error, expected '" << gai_strerror(expect_err) << "', got '" << gai_strerror(err) << "'" << std::endl; return false; } return true; } #endif libtorrent-0.16.11/test/helpers/test_fixture.cc0000644000000000000000000000052115175073411015152 #include "config.h" #include "test_fixture.h" #include "torrent/utils/log.h" #include void test_fixture::setUp() { mock_init(); log_add_group_output(torrent::LOG_CONNECTION_BIND, "test_output"); log_add_group_output(torrent::LOG_CONNECTION_FD, "test_output"); } void test_fixture::tearDown() { mock_cleanup(); } libtorrent-0.16.11/test/helpers/test_thread.cc0000644000000000000000000000342115175073411014735 #include "config.h" #include "test_thread.h" #include #include "test/helpers/mock_function.h" #include "torrent/exceptions.h" #include "torrent/net/poll.h" const int test_thread::test_flag_pre_stop; const int test_thread::test_flag_long_timeout; const int test_thread::test_flag_do_work; const int test_thread::test_flag_pre_poke; const int test_thread::test_flag_post_poke; std::unique_ptr test_thread::create() { // Needs to be called before Thread is created. mock_redirect_defaults(); auto thread = new test_thread(); return std::unique_ptr(thread); } test_thread::test_thread() : m_test_state(TEST_NONE), m_test_flags(0) { } test_thread::~test_thread() { if (is_active()) stop_thread_wait(); } void test_thread::init_thread() { m_state = STATE_INITIALIZED; m_test_state = TEST_PRE_START; } void test_thread::cleanup_thread() { } void test_thread::call_events() { m_loop_count++; if ((m_test_flags & test_flag_pre_stop) && m_test_state == TEST_PRE_START && m_state == STATE_ACTIVE) m_test_state = TEST_PRE_STOP; if ((m_flags & flag_do_shutdown)) { if ((m_flags & flag_did_shutdown)) throw torrent::internal_error("Already trigged shutdown."); m_flags |= flag_did_shutdown; throw torrent::shutdown_exception(); } if ((m_test_flags & test_flag_pre_poke)) { } if ((m_test_flags & test_flag_do_work)) { usleep(10 * 1000); // TODO: Don't just sleep, as that give up core. m_test_flags &= ~test_flag_do_work; } if ((m_test_flags & test_flag_post_poke)) { } process_callbacks(); } std::chrono::microseconds test_thread::next_timeout() { if ((m_test_flags & test_flag_long_timeout)) return std::chrono::microseconds(10s); else return std::chrono::microseconds(100ms); } libtorrent-0.16.11/test/helpers/test_fixture.h0000644000000000000000000000043115175073411015014 #ifndef LIBTORRENT_HELPER_TEST_FIXTURE_H #define LIBTORRENT_HELPER_TEST_FIXTURE_H #include #include "test/helpers/mock_function.h" class test_fixture : public CppUnit::TestFixture { public: void setUp() override; void tearDown() override; }; #endif libtorrent-0.16.11/test/helpers/tracker_test.h0000644000000000000000000001004315175073411014761 #ifndef LIBTORRENT_HELPER_TRACKER_TEST_H #define LIBTORRENT_HELPER_TRACKER_TEST_H #include "tracker/tracker_list.h" #include "tracker/tracker_worker.h" class TrackerTest : public torrent::TrackerWorker { public: static const int flag_close_on_done = 0x10; static const int flag_scrape_on_success = 0x20; // TODO: Clean up tracker related enums. TrackerTest(torrent::TrackerInfo info, int flags = torrent::tracker::TrackerState::flag_enabled); bool is_busy() const override { return m_busy; } bool is_open() const { return m_open; } torrent::tracker_enum type() const override { return (torrent::tracker_enum)(torrent::TRACKER_DHT + 1); } int requesting_state() const { return m_requesting_state; } bool trigger_success(uint32_t new_peers = 0, uint32_t sum_peers = 0); bool trigger_success(torrent::AddressList* address_list, uint32_t new_peers = 0); bool trigger_failure(); bool trigger_scrape(); void set_close_on_done(bool state); void set_scrape_on_success(bool state); void set_scrapable(); void set_success(uint32_t counter, uint32_t time_last); void set_failed(uint32_t counter, uint32_t time_last); void set_latest_new_peers(uint32_t peers); void set_latest_sum_peers(uint32_t peers); void set_new_normal_interval(uint32_t timeout); void set_new_min_interval(uint32_t timeout); void send_event(torrent::tracker::TrackerState::event_enum new_state) override; void send_scrape() override; void close() override { m_busy = false; m_open = false; m_requesting_state = -1; } static torrent::tracker::Tracker new_tracker(torrent::TrackerList* parent, const std::string& url, int flags = torrent::tracker::TrackerState::flag_enabled); static void insert_tracker(torrent::TrackerList* parent, int group, torrent::tracker::Tracker tracker); torrent::tracker::TrackerState& test_state() { return state(); } static TrackerTest* test_worker(torrent::tracker::Tracker& tracker); static int test_flags(torrent::tracker::Tracker& tracker); static torrent::tracker::TrackerState& test_state(torrent::tracker::Tracker& tracker); static int count_active(torrent::TrackerList* parent); static int count_usable(torrent::TrackerList* parent); private: bool m_busy{false}; bool m_open{false}; int m_requesting_state{-1}; }; inline TrackerTest::TrackerTest(torrent::TrackerInfo info, int flags) : torrent::TrackerWorker(std::move(info), flags) { state().m_flags |= flag_close_on_done; } inline void TrackerTest::set_close_on_done(bool s) { if (s) state().m_flags |= flag_close_on_done; else state().m_flags &= ~flag_close_on_done; } inline void TrackerTest::set_scrape_on_success(bool s) { if (s) state().m_flags |= flag_scrape_on_success; else state().m_flags &= ~flag_scrape_on_success; } inline void TrackerTest::set_scrapable() { state().m_flags |= torrent::tracker::TrackerState::flag_scrapable; } inline TrackerTest* TrackerTest::test_worker(torrent::tracker::Tracker& tracker) { return dynamic_cast(tracker.get_worker()); } inline int TrackerTest::test_flags(torrent::tracker::Tracker& tracker) { return dynamic_cast(tracker.get_worker())->state().flags(); } inline torrent::tracker::TrackerState& TrackerTest::test_state(torrent::tracker::Tracker& tracker) { return dynamic_cast(tracker.get_worker())->state(); } extern uint32_t return_new_peers; inline uint32_t increment_value(int* value) { (*value)++; return return_new_peers; } inline void increment_value_void(int* value) { (*value)++; } inline unsigned int increment_value_uint(int* value) { (*value)++; return return_new_peers; } #endif // LIBTORRENT_HELPER_TRACKER_TEST_H libtorrent-0.16.11/test/helpers/progress_listener.cc0000644000000000000000000000326315175073411016204 #include "config.h" #include "progress_listener.h" #include #include #include #include #include #include "torrent/utils/log.h" #include "torrent/utils/log_buffer.h" #include static std::string get_test_path(const test_list_type& tl) { if (tl.size() < 2) return ""; return std::accumulate(std::next(tl.begin()), std::prev(tl.end()), std::string(), [](std::string result, CppUnit::Test* test) { return std::move(result) + test->getName() + "::"; }); } void progress_listener::startTest(CppUnit::Test *test) { std::cout << get_test_path(m_test_path) << test->getName() << std::flush; torrent::log_cleanup(); m_last_test_failed = false; m_current_log_buffer = torrent::log_open_log_buffer("test_output"); } void progress_listener::addFailure(const CppUnit::TestFailure &failure) { // AddFailure is called for parent test suits, so only deal with leafs. if (m_current_log_buffer == nullptr) return; std::cout << " : " << (failure.isError() ? "error" : "assertion") << std::flush; m_last_test_failed = true; m_failures.push_back(failure_type{ failure.failedTestName(), std::move(m_current_log_buffer) }); } void progress_listener::endTest(CppUnit::Test *test) { std::cout << (m_last_test_failed ? "" : " : OK") << std::endl; m_current_log_buffer.reset(); torrent::log_cleanup(); } void progress_listener::startSuite(CppUnit::Test *suite) { m_test_path.push_back(suite); if (suite->countTestCases() > 0) std::cout << std::endl << get_test_path(m_test_path) << suite->getName() << ":" << std::endl; } void progress_listener::endSuite(CppUnit::Test *suite) { m_test_path.pop_back(); } libtorrent-0.16.11/test/helpers/progress_listener.h0000644000000000000000000000273115175073411016045 #include #include #include #include #include #include "torrent/utils/log_buffer.h" struct failure_type { std::string name; torrent::log_buffer_ptr log; }; typedef std::unique_ptr test_failure_ptr; typedef std::vector test_list_type; typedef std::vector failure_list_type; class progress_listener : public CppUnit::TestListener { public: progress_listener() : m_last_test_failed(false) {} void startTest(CppUnit::Test *test) override; void addFailure(const CppUnit::TestFailure &failure) override; void endTest(CppUnit::Test *test) override; void startSuite(CppUnit::Test *suite) override; void endSuite(CppUnit::Test *suite) override; //Called by a TestRunner before running the test. // void startTestRun(CppUnit::Test *test, CppUnit::TestResult *event_manager) override; // Called by a TestRunner after running the test. // void endTestRun(CppUnit::Test *test, CppUnit::TestResult *event_manager) override; const failure_list_type& failures() { return m_failures; } failure_list_type&& move_failures() { return std::move(m_failures); } private: progress_listener(const progress_listener& rhs) = delete; void operator =(const progress_listener& rhs) = delete; test_list_type m_test_path; failure_list_type m_failures; bool m_last_test_failed; torrent::log_buffer_ptr m_current_log_buffer; }; libtorrent-0.16.11/test/helpers/test_main_thread.h0000644000000000000000000000373015175073411015606 #ifndef TEST_HELPERS_TEST_MAIN_THREAD_H #define TEST_HELPERS_TEST_MAIN_THREAD_H #include #include "test/helpers/test_fixture.h" #include "test/helpers/test_thread.h" #include "torrent/common.h" #include "torrent/system/thread.h" class TestMainThread : public torrent::system::Thread { public: static std::unique_ptr create(); static std::unique_ptr create_with_mock(); const char* name() const override { return "rtorrent test main"; } void init_thread() override; void cleanup_thread() override; void test_set_cached_time(std::chrono::microseconds t) { set_cached_time(365 * 24h + t); } void test_add_cached_time(std::chrono::microseconds t) { set_cached_time(cached_time() + t); } void test_process_events_without_cached_time() { process_events_without_cached_time(); } private: TestMainThread() = default; void call_events() override; std::chrono::microseconds next_timeout() override; }; class TestFixtureWithMainThread : public test_fixture { public: void setUp() override; void tearDown() override; std::unique_ptr m_main_thread; }; class TestFixtureWithMainAndDiskThread : public test_fixture { public: void setUp() override; void tearDown() override; std::unique_ptr m_main_thread; }; class TestFixtureWithMainAndTrackerThread : public test_fixture { public: void setUp() override; void tearDown() override; std::unique_ptr m_main_thread; }; class TestFixtureWithMainNetTrackerThread : public test_fixture { public: void setUp() override; void tearDown() override; std::unique_ptr m_main_thread; }; class TestFixtureWithMockAndMainThread : public test_fixture { public: void setUp() override; void tearDown() override; std::unique_ptr m_main_thread; }; #endif // TEST_HELPERS_TEST_MAIN_THREAD_H libtorrent-0.16.11/test/helpers/test_thread.h0000644000000000000000000000361115175073411014600 #ifndef TEST_HELPERS_TEST_THREAD_H #define TEST_HELPERS_TEST_THREAD_H #include #include #include "test/helpers/test_utils.h" #include "torrent/common.h" #include "torrent/system/thread.h" class test_thread : public torrent::system::Thread { public: enum test_state { TEST_NONE, TEST_PRE_START, TEST_PRE_STOP, TEST_STOP }; static const int test_flag_pre_stop = 0x1; static const int test_flag_long_timeout = 0x2; static const int test_flag_do_work = 0x100; static const int test_flag_pre_poke = 0x200; static const int test_flag_post_poke = 0x400; static std::unique_ptr create(); ~test_thread() override; int test_state() const { return m_test_state; } bool is_state(int state) const { return m_state == state; } bool is_test_state(int state) const { return m_test_state == state; } bool is_test_flags(int flags) const { return (m_test_flags & flags) == flags; } bool is_not_test_flags(int flags) const { return !(m_test_flags & flags); } // Loop count increments twice each loop. int loop_count() const { return m_loop_count; } const char* name() const override { return "test_thread"; } void init_thread() override; void cleanup_thread() override; void set_pre_stop() { m_test_flags |= test_flag_pre_stop; } void set_test_flag(int flags) { m_test_flags |= flags; } auto* internal_poll() const { return m_poll.get(); } private: test_thread(); void call_events() override; std::chrono::microseconds next_timeout() override; std::atomic_int m_test_state; std::atomic_int m_test_flags; std::atomic_int m_loop_count{0}; }; #endif libtorrent-0.16.11/test/helpers/network.cc0000644000000000000000000000114615175073411014122 #include "config.h" #include "test/helpers/network.h" #include #include "torrent/event.h" bool check_event_is_readable(torrent::Event* event, std::chrono::microseconds timeout) { int fd = event->file_descriptor(); fd_set read_fds; FD_ZERO(&read_fds); FD_SET(fd, &read_fds); struct timeval t = { static_cast(std::chrono::duration_cast(timeout).count()), static_cast(timeout.count() % 1000000) }; int result = select(fd + 1, &read_fds, nullptr, nullptr, &t); CPPUNIT_ASSERT(result != -1); return FD_ISSET(fd, &read_fds); } libtorrent-0.16.11/test/helpers/mock_compare.h0000644000000000000000000000614715175073411014740 #ifndef LIBTORRENT_HELPERS_MOCK_COMPARE_H #define LIBTORRENT_HELPERS_MOCK_COMPARE_H #include #include #include #include #include // Compare arguments to mock functions with what is expected. The lhs // are the expected arguments, rhs are the ones called with. template inline bool mock_compare_arg(Arg lhs, Arg rhs) { return lhs == rhs; } template std::enable_if_t mock_compare_tuple(const std::tuple& lhs, const std::tuple& rhs) { return mock_compare_arg(std::get(lhs), std::get(rhs)) ? 0 : 1; } template std::enable_if_t<1 < I, int> mock_compare_tuple(const std::tuple& lhs, const std::tuple& rhs) { auto res = mock_compare_tuple(lhs, rhs); if (res != 0) return res; return mock_compare_arg(std::get(lhs), std::get(rhs)) ? 0 : I; } //template ::value, int>::type = 0> template struct mock_compare_map { typedef std::map values_type; static T* begin_pointer() { return reinterpret_cast(0x1000); } static T* end_pointer() { return reinterpret_cast(0x2000); } static bool is_key(const T* k) { return k >= begin_pointer() && k < end_pointer(); } static bool has_key(const T* k) { return values.find(k) != values.end(); } static bool has_value(const T* v) { return std::find_if(values.begin(), values.end(), [v](typename values_type::value_type& kv) { return v == kv.second; }) != values.end(); } static const T* get(const T* k) { auto itr = values.find(k); CPPUNIT_ASSERT_MESSAGE("mock_compare_map get failed, not inserted", itr != values.end()); return itr->second; } static values_type values; }; template typename mock_compare_map::values_type mock_compare_map::values; template void mock_compare_add(T* v) { mock_compare_map::add_value(v); } // // Specialize: // constexpr int mock_compare_gt_two_int = -0xFD30; template <> inline bool mock_compare_arg(int lhs, int rhs) { if (lhs == mock_compare_gt_two_int) return rhs > 2; if (rhs == mock_compare_gt_two_int) return lhs > 2; return lhs == rhs; } template <> inline bool mock_compare_arg(sockaddr* lhs, sockaddr* rhs) { return lhs != nullptr && rhs != nullptr && torrent::sa_equal(lhs, rhs); } template <> inline bool mock_compare_arg(const sockaddr* lhs, const sockaddr* rhs) { return lhs != nullptr && rhs != nullptr && torrent::sa_equal(lhs, rhs); } template <> inline bool mock_compare_arg(torrent::Event* lhs, torrent::Event* rhs) { if (mock_compare_map::is_key(lhs)) { if (!mock_compare_map::has_value(rhs)) { mock_compare_map::values[lhs] = rhs; return true; } return mock_compare_map::has_key(lhs) && mock_compare_map::get(lhs) == rhs; } return lhs == rhs; } #endif libtorrent-0.16.11/test/helpers/expect_fd.h0000644000000000000000000001033215175073411014231 #ifndef LIBTORRENT_HELPER_EXPECT_FD_H #define LIBTORRENT_HELPER_EXPECT_FD_H #include "helpers/mock_function.h" #include #include #include #include typedef std::vector sap_cache_type; inline const sockaddr* sap_cache_copy_addr_c_ptr(sap_cache_type& sap_cache, const torrent::c_sa_unique_ptr& sap, uint16_t port = 0) { sap_cache.push_back(torrent::sap_copy_addr(sap, port)); return sap_cache.back().get(); } inline void expect_event_open_re(int idx) { mock_expect(&torrent::this_thread::event_open_and_count, mock_compare_map::begin_pointer() + idx); mock_expect(&torrent::this_thread::event_insert_read, mock_compare_map::begin_pointer() + idx); mock_expect(&torrent::this_thread::event_insert_error, mock_compare_map::begin_pointer() + idx); } inline void expect_event_closed_fd(int idx, int fd) { mock_expect(&torrent::fd__close, 0, fd); mock_expect(&torrent::this_thread::event_closed_and_count, mock_compare_map::begin_pointer() + idx); } inline void expect_fd_inet_tcp(int fd) { mock_expect(&torrent::fd__socket, fd, (int)PF_INET, (int)SOCK_STREAM, (int)IPPROTO_TCP); } inline void expect_fd_inet6_tcp(int fd) { mock_expect(&torrent::fd__socket, fd, (int)PF_INET6, (int)SOCK_STREAM, (int)IPPROTO_TCP); } inline void expect_fd_inet_tcp_nonblock(int fd) { mock_expect(&torrent::fd__socket, fd, (int)PF_INET, (int)SOCK_STREAM, (int)IPPROTO_TCP); mock_expect(&torrent::fd__fcntl_int, 0, fd, F_SETFL, O_NONBLOCK); } inline void expect_fd_inet6_tcp_nonblock(int fd) { mock_expect(&torrent::fd__socket, fd, (int)PF_INET6, (int)SOCK_STREAM, (int)IPPROTO_TCP); mock_expect(&torrent::fd__fcntl_int, 0, fd, F_SETFL, O_NONBLOCK); } inline void expect_fd_inet_tcp_nonblock_reuseaddr(int fd) { mock_expect(&torrent::fd__socket, fd, (int)PF_INET, (int)SOCK_STREAM, (int)IPPROTO_TCP); mock_expect(&torrent::fd__fcntl_int, 0, fd, F_SETFL, O_NONBLOCK); mock_expect(&torrent::fd__setsockopt_int, 0, fd, (int)SOL_SOCKET, (int)SO_REUSEADDR, (int)true); } inline void expect_fd_inet6_tcp_nonblock_reuseaddr(int fd) { mock_expect(&torrent::fd__socket, fd, (int)PF_INET6, (int)SOCK_STREAM, (int)IPPROTO_TCP); mock_expect(&torrent::fd__fcntl_int, 0, fd, F_SETFL, O_NONBLOCK); mock_expect(&torrent::fd__setsockopt_int, 0, fd, (int)SOL_SOCKET, (int)SO_REUSEADDR, (int)true); } inline void expect_fd_inet6_tcp_v6only_nonblock(int fd) { mock_expect(&torrent::fd__socket, fd, (int)PF_INET6, (int)SOCK_STREAM, (int)IPPROTO_TCP); mock_expect(&torrent::fd__setsockopt_int, 0, fd, (int)IPPROTO_IPV6, (int)IPV6_V6ONLY, (int)true); mock_expect(&torrent::fd__fcntl_int, 0, fd, F_SETFL, O_NONBLOCK); } inline void expect_fd_inet6_tcp_v6only_nonblock_reuseaddr(int fd) { mock_expect(&torrent::fd__socket, fd, (int)PF_INET6, (int)SOCK_STREAM, (int)IPPROTO_TCP); mock_expect(&torrent::fd__setsockopt_int, 0, fd, (int)IPPROTO_IPV6, (int)IPV6_V6ONLY, (int)true); mock_expect(&torrent::fd__fcntl_int, 0, fd, F_SETFL, O_NONBLOCK); mock_expect(&torrent::fd__setsockopt_int, 0, fd, (int)SOL_SOCKET, (int)SO_REUSEADDR, (int)true); } inline void expect_fd_bind_connect(int fd, const torrent::c_sa_unique_ptr& bind_sap, const torrent::c_sa_unique_ptr& connect_sap) { mock_expect(&torrent::fd__bind, 0, fd, bind_sap.get(), (socklen_t)torrent::sap_length(bind_sap)); mock_expect(&torrent::fd__connect, 0, fd, connect_sap.get(), (socklen_t)torrent::sap_length(connect_sap)); } inline void expect_fd_bind_fail_range(int fd, sap_cache_type& sap_cache, const torrent::c_sa_unique_ptr& sap, uint16_t first_port, uint16_t last_port) { do { mock_expect(&torrent::fd__bind, -1, fd, sap_cache_copy_addr_c_ptr(sap_cache, sap, first_port), (socklen_t)torrent::sap_length(sap)); } while (first_port++ != last_port); } inline void expect_fd_bind_listen(int fd, const torrent::c_sa_unique_ptr& sap) { mock_expect(&torrent::fd__bind, 0, fd, sap.get(), (socklen_t)torrent::sap_length(sap)); mock_expect(&torrent::fd__listen, 0, fd, SOMAXCONN); } inline void expect_fd_connect(int fd, const torrent::c_sa_unique_ptr& sap) { mock_expect(&torrent::fd__connect, 0, fd, sap.get(), (socklen_t)torrent::sap_length(sap)); } #endif libtorrent-0.16.11/test/helpers/utils.h0000644000000000000000000000321715175073411013434 #ifndef LIBTORRENT_HELPER_UTILS_H #define LIBTORRENT_HELPER_UTILS_H #include #include #include #include static void dump_failure_log(const failure_type& failure) { if (failure.log->empty()) return; std::cout << std::endl << failure.name << std::endl; // Doesn't print dump messages as log_buffer drops them. std::for_each(failure.log->begin(), failure.log->end(), [](const torrent::log_entry& entry) { std::cout << entry.timestamp << ' ' << entry.message << '\n'; }); std::cout << std::flush; } static void dump_failures(const failure_list_type& failures) { if (failures.empty()) return; std::cout << std::endl << "=================" << std::endl << "Failed Test Logs:" << std::endl << "=================" << std::endl; std::for_each(failures.begin(), failures.end(), [](const failure_type& failure) { dump_failure_log(failure); }); std::cout << std::endl; } static void add_tests(CppUnit::TextUi::TestRunner& runner, const char* c_test_names) { if (c_test_names == NULL || std::string(c_test_names).empty()) { runner.addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest()); return; } const std::string& test_names(c_test_names); size_t pos = 0; size_t next = 0; while ((next = test_names.find(',', pos)) < test_names.size()) { runner.addTest(CppUnit::TestFactoryRegistry::getRegistry(test_names.substr(pos, next - pos)).makeTest()); pos = next + 1; } runner.addTest(CppUnit::TestFactoryRegistry::getRegistry(test_names.substr(pos)).makeTest()); } #endif libtorrent-0.16.11/test/helpers/tracker_test.cc0000644000000000000000000001436315175073411015130 #include "config.h" #include "test/helpers/tracker_test.h" #include "net/address_list.h" #include "test/torrent/test_tracker_list.h" #include // TrackerTest does not fully support threaded tracker yet, so review the code if such a requirement // is needed. uint32_t return_new_peers = 0xdeadbeef; torrent::tracker::Tracker TrackerTest::new_tracker([[maybe_unused]] torrent::TrackerList* parent, const std::string& url, int flags) { auto tracker_info = torrent::TrackerInfo{ // .info_hash = m_info->hash(), // .obfuscated_hash = m_info->hash_obfuscated(), // .local_id = m_info->local_id(), // .key = m_key }; tracker_info.url = url; return torrent::tracker::Tracker(std::make_shared(std::move(tracker_info), flags)); } void TrackerTest::insert_tracker(torrent::TrackerList* parent, int group, torrent::tracker::Tracker tracker) { // Insert into partent then override slots. parent->insert(group, tracker); tracker.get_worker()->m_slot_enabled = [parent, tracker]() { if (parent->slot_tracker_enabled()) parent->slot_tracker_enabled()(tracker); }; tracker.get_worker()->m_slot_disabled = [parent, tracker]() { if (parent->slot_tracker_disabled()) parent->slot_tracker_disabled()(tracker); }; tracker.get_worker()->m_slot_success = [parent, tracker](torrent::AddressList&& l) { auto t = tracker; parent->receive_success(std::move(t), &l); }; tracker.get_worker()->m_slot_failure = [parent, tracker](const std::string& msg) { auto t = tracker; parent->receive_failed(std::move(t), msg); }; tracker.get_worker()->m_slot_scrape_success = [parent, tracker]() { auto t = tracker; parent->receive_scrape_success(std::move(t)); }; tracker.get_worker()->m_slot_scrape_failure = [parent, tracker](const std::string& msg) { auto t = tracker; parent->receive_scrape_failed(std::move(t), msg); }; } void TrackerTest::set_success(uint32_t counter, uint32_t time_last) { auto guard = lock_guard(); state().m_success_counter = counter; state().m_success_time_last = time_last; state().set_normal_interval(torrent::tracker::TrackerState::default_normal_interval); state().set_min_interval(torrent::tracker::TrackerState::default_min_interval); } void TrackerTest::set_failed(uint32_t counter, uint32_t time_last) { auto guard = lock_guard(); state().m_failed_counter = counter; state().m_failed_time_last = time_last; state().m_normal_interval = 0; state().m_min_interval = 0; } void TrackerTest::set_latest_new_peers(uint32_t peers) { auto guard = lock_guard(); state().m_latest_new_peers = peers; } void TrackerTest::set_latest_sum_peers(uint32_t peers) { auto guard = lock_guard(); state().m_latest_sum_peers = peers; } void TrackerTest::set_new_normal_interval(uint32_t timeout) { auto guard = lock_guard(); state().set_normal_interval(timeout); } void TrackerTest::set_new_min_interval(uint32_t timeout) { auto guard = lock_guard(); state().set_min_interval(timeout); } void TrackerTest::send_event(torrent::tracker::TrackerState::event_enum new_state) { // Trackers close on-going requests when new state is sent. m_busy = true; m_open = true; m_requesting_state = new_state; lock_and_set_latest_event(new_state); } void TrackerTest::send_scrape() { // We ignore scrapes if we're already making a request. // if (m_open) // return; m_busy = true; m_open = true; m_requesting_state = torrent::tracker::TrackerState::EVENT_SCRAPE; lock_and_set_latest_event(torrent::tracker::TrackerState::EVENT_SCRAPE); } bool TrackerTest::trigger_success(uint32_t new_peers, uint32_t sum_peers) { CPPUNIT_ASSERT(is_busy() && "TrackerTest::trigger_success: is_busy()"); CPPUNIT_ASSERT(is_open() && "TrackerTest::trigger_success: is_open()"); torrent::AddressList address_list; for (unsigned int i = 0; i != sum_peers; i++) { torrent::sa_inet_union sa{}; sa.inet.sin_family = AF_INET; sa.inet.sin_port = htons(0x100 + i); address_list.push_back(sa); } address_list.sort_and_unique(); return trigger_success(&address_list, new_peers); } bool TrackerTest::trigger_success(torrent::AddressList* address_list, uint32_t new_peers) { CPPUNIT_ASSERT(is_busy() && "TrackerTest::trigger_success: is_busy()"); CPPUNIT_ASSERT(is_open() && "TrackerTest::trigger_success: is_open()"); CPPUNIT_ASSERT(address_list != nullptr && "TrackerTest::trigger_success: address_list == nullptr"); m_busy = false; m_open = !(state().flags() & flag_close_on_done); return_new_peers = new_peers; if (state().latest_event() == torrent::tracker::TrackerState::EVENT_SCRAPE) { if (m_slot_scrape_success) m_slot_scrape_success(); } else { { auto guard = lock_guard(); state().set_normal_interval(torrent::tracker::TrackerState::default_normal_interval); state().set_min_interval(torrent::tracker::TrackerState::default_min_interval); } if (m_slot_success) m_slot_success(std::move(*address_list)); } m_requesting_state = -1; return true; } bool TrackerTest::trigger_failure() { CPPUNIT_ASSERT(is_busy() && "TrackerTest::trigger_failure: is_busy()"); CPPUNIT_ASSERT(is_open() && "TrackerTest::trigger_failure: is_open()"); m_busy = false; m_open = !(state().flags() & flag_close_on_done); return_new_peers = 0; if (state().latest_event() == torrent::tracker::TrackerState::EVENT_SCRAPE) { if (m_slot_scrape_failure) m_slot_scrape_failure("failed"); } else { { auto guard = lock_guard(); state().set_normal_interval(0); state().set_min_interval(0); } if (m_slot_failure) m_slot_failure("failed"); } m_requesting_state = -1; return true; } bool TrackerTest::trigger_scrape() { if (!is_busy() || !is_open()) return false; if (state().latest_event() != torrent::tracker::TrackerState::EVENT_SCRAPE) return false; return trigger_success(); } int TrackerTest::count_active(torrent::TrackerList* parent) { return std::count_if(parent->begin(), parent->end(), std::mem_fn(&torrent::tracker::Tracker::is_busy)); } int TrackerTest::count_usable(torrent::TrackerList* parent) { return std::count_if(parent->begin(), parent->end(), std::mem_fn(&torrent::tracker::Tracker::is_usable)); } libtorrent-0.16.11/test/helpers/protectors.cc0000644000000000000000000000210015175073411014624 #include #include #include #include #include #include bool ExceptionProtector::protect(const CppUnit::Functor& functor, const CppUnit::ProtectorContext& context) { try { return functor(); } catch (const CppUnit::Exception& failure) { reportFailure( context, failure ); } catch (const torrent::base_error& e) { std::string short_description("uncaught exception of base type torrent::base_error: " + std::string(typeid(e).name())); CppUnit::Message message(short_description, e.what()); reportError(context, message); } catch (const std::exception& e) { std::string short_description("uncaught exception of type "); short_description += CppUnit::TypeInfoHelper::getClassName(typeid(e)); CppUnit::Message message(short_description, e.what()); reportError(context, message); } catch (...) { reportError(context, CppUnit::Message("uncaught exception of unknown type")); } return false; } libtorrent-0.16.11/test/helpers/mock_function.cc0000644000000000000000000001720715175073411015274 #include "config.h" #include "test/helpers/mock_function.h" #include #include #include #include "torrent/event.h" #include "torrent/net/socket_address.h" #include "torrent/net/fd.h" #include "torrent/utils/log.h" #include "torrent/utils/random.h" #define MOCK_CLEANUP_MAP(MOCK_FUNC) \ CPPUNIT_ASSERT_MESSAGE("expected mock function calls not completed for '" #MOCK_FUNC "'", mock_cleanup_map(&MOCK_FUNC) || ignore_assert); #define MOCK_LOG(log_fmt, ...) \ lt_log_print(torrent::LOG_MOCK_CALLS, "%s: " log_fmt, __func__, __VA_ARGS__); namespace { void mock_clear(bool ignore_assert) { MOCK_CLEANUP_MAP(torrent::fd__accept); MOCK_CLEANUP_MAP(torrent::fd__bind); MOCK_CLEANUP_MAP(torrent::fd__close); MOCK_CLEANUP_MAP(torrent::fd__connect); MOCK_CLEANUP_MAP(torrent::fd__fcntl_int); MOCK_CLEANUP_MAP(torrent::fd__listen); MOCK_CLEANUP_MAP(torrent::fd__setsockopt_int); MOCK_CLEANUP_MAP(torrent::fd__socket); MOCK_CLEANUP_MAP(torrent::this_thread::event_open); MOCK_CLEANUP_MAP(torrent::this_thread::event_open_and_count); MOCK_CLEANUP_MAP(torrent::this_thread::event_close_and_count); MOCK_CLEANUP_MAP(torrent::this_thread::event_closed_and_count); MOCK_CLEANUP_MAP(torrent::this_thread::event_insert_read); MOCK_CLEANUP_MAP(torrent::this_thread::event_insert_write); MOCK_CLEANUP_MAP(torrent::this_thread::event_insert_error); MOCK_CLEANUP_MAP(torrent::this_thread::event_remove_read); MOCK_CLEANUP_MAP(torrent::this_thread::event_remove_write); MOCK_CLEANUP_MAP(torrent::this_thread::event_remove_error); MOCK_CLEANUP_MAP(torrent::this_thread::event_remove_and_close); MOCK_CLEANUP_MAP(torrent::random_uniform_uint16); MOCK_CLEANUP_MAP(torrent::random_uniform_uint32); mock_compare_map::values.clear(); } } // namespace void mock_init() { log_add_group_output(torrent::LOG_MOCK_CALLS, "test_output"); mock_clear(true); } void mock_cleanup() { mock_clear(false); } void mock_redirect_defaults([[maybe_unused]] mock_redirect_flags flags) { mock_redirect(torrent::fd__close, std::function([](int fildes) { return ::close(fildes); })); mock_redirect(torrent::fd__fcntl_int, std::function([](int fildes, int cmd, int arg) { return ::fcntl(fildes, cmd, arg); })); mock_redirect(torrent::fd__setsockopt_int, std::function([](int socket, int level, int option_name, int option_value) { return ::setsockopt(socket, level, option_name, &option_value, sizeof(int)); })); mock_redirect(torrent::fd__socket, std::function([](int domain, int type, int protocol) { return ::socket(domain, type, protocol); })); } namespace torrent { // // Mock functions for 'torrent/net/fd.h': // int fd__accept(int socket, sockaddr *address, socklen_t *address_len) { MOCK_LOG("entry socket:%i address:%s address_len:%u", socket, torrent::sa_pretty_str(address).c_str(), (unsigned int)(*address_len)); auto ret = mock_call(__func__, &torrent::fd__accept, socket, address, address_len); MOCK_LOG("exit socket:%i address:%s address_len:%u", socket, torrent::sa_pretty_str(address).c_str(), (unsigned int)(*address_len)); return ret; } int fd__bind(int socket, const sockaddr *address, socklen_t address_len) { MOCK_LOG("socket:%i address:%s address_len:%u", socket, torrent::sa_pretty_str(address).c_str(), (unsigned int)address_len); return mock_call(__func__, &torrent::fd__bind, socket, address, address_len); } int fd__close(int fildes) { MOCK_LOG("filedes:%i", fildes); return mock_call(__func__, &torrent::fd__close, fildes); } int fd__connect(int socket, const sockaddr *address, socklen_t address_len) { MOCK_LOG("socket:%i address:%s address_len:%u", socket, torrent::sa_pretty_str(address).c_str(), (unsigned int)address_len); return mock_call(__func__, &torrent::fd__connect, socket, address, address_len); } int fd__fcntl_int(int fildes, int cmd, int arg) { MOCK_LOG("filedes:%i cmd:%i arg:%i", fildes, cmd, arg); return mock_call(__func__, &torrent::fd__fcntl_int, fildes, cmd, arg); } int fd__listen(int socket, int backlog) { MOCK_LOG("socket:%i backlog:%i", socket, backlog); return mock_call(__func__, &torrent::fd__listen, socket, backlog); } int fd__setsockopt_int(int socket, int level, int option_name, int option_value) { MOCK_LOG("socket:%i level:%i option_name:%i option_value:%i", socket, level, option_name, option_value); return mock_call(__func__, &torrent::fd__setsockopt_int, socket, level, option_name, option_value); } int fd__socket(int domain, int type, int protocol) { MOCK_LOG("domain:%i type:%i protocol:%i", domain, type, protocol); return mock_call(__func__, &torrent::fd__socket, domain, type, protocol); } // // Mock functions for 'torrent/common.h': // namespace this_thread { void event_open(Event* event) { MOCK_LOG("fd:%i type_name:%s", event->file_descriptor(), event->type_name()); return mock_call(__func__, &torrent::this_thread::event_open, event); } void event_open_and_count(Event* event) { MOCK_LOG("fd:%i type_name:%s", event->file_descriptor(), event->type_name()); return mock_call(__func__, &torrent::this_thread::event_open_and_count, event); } void event_close_and_count(Event* event) { MOCK_LOG("fd:%i type_name:%s", event->file_descriptor(), event->type_name()); return mock_call(__func__, &torrent::this_thread::event_close_and_count, event); } void event_closed_and_count(Event* event) { MOCK_LOG("fd:%i type_name:%s", event->file_descriptor(), event->type_name()); return mock_call(__func__, &torrent::this_thread::event_closed_and_count, event); } void event_insert_read(Event* event) { MOCK_LOG("fd:%i type_name:%s", event->file_descriptor(), event->type_name()); return mock_call(__func__, &torrent::this_thread::event_insert_read, event); } void event_insert_write(Event* event) { MOCK_LOG("fd:%i type_name:%s", event->file_descriptor(), event->type_name()); return mock_call(__func__, &torrent::this_thread::event_insert_write, event); } void event_insert_error(Event* event) { MOCK_LOG("fd:%i type_name:%s", event->file_descriptor(), event->type_name()); return mock_call(__func__, &torrent::this_thread::event_insert_error, event); } void event_remove_read(Event* event) { MOCK_LOG("fd:%i type_name:%s", event->file_descriptor(), event->type_name()); return mock_call(__func__, &torrent::this_thread::event_remove_read, event); } void event_remove_write(Event* event) { MOCK_LOG("fd:%i type_name:%s", event->file_descriptor(), event->type_name()); return mock_call(__func__, &torrent::this_thread::event_remove_write, event); } void event_remove_error(Event* event) { MOCK_LOG("fd:%i type_name:%s", event->file_descriptor(), event->type_name()); return mock_call(__func__, &torrent::this_thread::event_remove_error, event); } void event_remove_and_close(Event* event) { MOCK_LOG("fd:%i type_name:%s", event->file_descriptor(), event->type_name()); return mock_call(__func__, &torrent::this_thread::event_remove_and_close, event); } } // // Mock functions for 'torrent/utils/random.h': // uint16_t random_uniform_uint16(uint16_t min, uint16_t max) { MOCK_LOG("min:%" PRIu16 " max:%" PRIu16, min, max); return mock_call(__func__, &torrent::random_uniform_uint16, min, max); } uint32_t random_uniform_uint32(uint32_t min, uint32_t max) { MOCK_LOG("min:%" PRIu32 " max:%" PRIu32, min, max); return mock_call(__func__, &torrent::random_uniform_uint32, min, max); } } libtorrent-0.16.11/test/helpers/protectors.h0000644000000000000000000000054715175073411014503 #ifndef LIBTORRENT_HELPER_PROTECTORS_H #define LIBTORRENT_HELPER_PROTECTORS_H #include #include #include class ExceptionProtector : public CppUnit::Protector { public: bool protect(const CppUnit::Functor &functor, const CppUnit::ProtectorContext &context) override; }; #endif // LIBTORRENT_HELPER_PROTECTORS_H libtorrent-0.16.11/test/helpers/test_utils.h0000644000000000000000000000052015175073411014465 #ifndef LIBTORRENT_TEST_UTILS_H #define LIBTORRENT_TEST_UTILS_H #include #include inline bool wait_for_true(std::function test_function) { int i = 100; do { if (test_function()) return true; usleep(10 * 1000); } while (--i); return false; } #endif // LIBTORRENT_TEST_UTILS_H libtorrent-0.16.11/test/Makefile.in0000644000000000000000000115026515175073426012543 # Makefile.in generated by automake 1.17 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2024 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) am__rm_f = rm -f $(am__rm_f_notfound) am__rm_rf = rm -rf $(am__rm_f_notfound) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ TESTS = LibTorrent_Test_Torrent_Net$(EXEEXT) \ LibTorrent_Test_Torrent_Utils$(EXEEXT) \ LibTorrent_Test_Torrent$(EXEEXT) LibTorrent_Test_Data$(EXEEXT) \ LibTorrent_Test_Net$(EXEEXT) LibTorrent_Test_Tracker$(EXEEXT) \ LibTorrent_Test$(EXEEXT) check_PROGRAMS = $(am__EXEEXT_1) subdir = test ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/scripts/attributes.m4 \ $(top_srcdir)/scripts/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/scripts/ax_execinfo.m4 \ $(top_srcdir)/scripts/ax_pthread.m4 \ $(top_srcdir)/scripts/check_atomic.m4 \ $(top_srcdir)/scripts/checks.m4 \ $(top_srcdir)/scripts/common.m4 \ $(top_srcdir)/scripts/libtool.m4 \ $(top_srcdir)/scripts/ltoptions.m4 \ $(top_srcdir)/scripts/ltsugar.m4 \ $(top_srcdir)/scripts/ltversion.m4 \ $(top_srcdir)/scripts/lt~obsolete.m4 \ $(top_srcdir)/scripts/rak_compiler.m4 \ $(top_srcdir)/scripts/ssl.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__EXEEXT_1 = LibTorrent_Test_Torrent_Net$(EXEEXT) \ LibTorrent_Test_Torrent_Utils$(EXEEXT) \ LibTorrent_Test_Torrent$(EXEEXT) LibTorrent_Test_Data$(EXEEXT) \ LibTorrent_Test_Net$(EXEEXT) LibTorrent_Test_Tracker$(EXEEXT) \ LibTorrent_Test$(EXEEXT) am__dirstamp = $(am__leading_dot)dirstamp am__objects_1 = LibTorrent_Test-main.$(OBJEXT) \ helpers/LibTorrent_Test-mock_function.$(OBJEXT) \ helpers/LibTorrent_Test-network.$(OBJEXT) \ helpers/LibTorrent_Test-progress_listener.$(OBJEXT) \ helpers/LibTorrent_Test-protectors.$(OBJEXT) \ helpers/LibTorrent_Test-test_fixture.$(OBJEXT) \ helpers/LibTorrent_Test-test_main_thread.$(OBJEXT) \ helpers/LibTorrent_Test-test_thread.$(OBJEXT) \ helpers/LibTorrent_Test-tracker_test.$(OBJEXT) am_LibTorrent_Test_OBJECTS = $(am__objects_1) \ rak/LibTorrent_Test-ranges_test.$(OBJEXT) \ protocol/LibTorrent_Test-test_request_list.$(OBJEXT) LibTorrent_Test_OBJECTS = $(am_LibTorrent_Test_OBJECTS) LibTorrent_Test_DEPENDENCIES = ../src/libtorrent.la \ ../src/libtorrent_other.la \ ../src/torrent/libtorrent_torrent.la AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = LibTorrent_Test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) \ $(LibTorrent_Test_LDFLAGS) $(LDFLAGS) -o $@ am__objects_2 = LibTorrent_Test_Data-main.$(OBJEXT) \ helpers/LibTorrent_Test_Data-mock_function.$(OBJEXT) \ helpers/LibTorrent_Test_Data-network.$(OBJEXT) \ helpers/LibTorrent_Test_Data-progress_listener.$(OBJEXT) \ helpers/LibTorrent_Test_Data-protectors.$(OBJEXT) \ helpers/LibTorrent_Test_Data-test_fixture.$(OBJEXT) \ helpers/LibTorrent_Test_Data-test_main_thread.$(OBJEXT) \ helpers/LibTorrent_Test_Data-test_thread.$(OBJEXT) \ helpers/LibTorrent_Test_Data-tracker_test.$(OBJEXT) am_LibTorrent_Test_Data_OBJECTS = $(am__objects_2) \ data/LibTorrent_Test_Data-test_chunk_list.$(OBJEXT) \ data/LibTorrent_Test_Data-test_hash_check_queue.$(OBJEXT) \ data/LibTorrent_Test_Data-test_hash_queue.$(OBJEXT) LibTorrent_Test_Data_OBJECTS = $(am_LibTorrent_Test_Data_OBJECTS) LibTorrent_Test_Data_DEPENDENCIES = $(LibTorrent_Test_LDADD) LibTorrent_Test_Data_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) \ $(LibTorrent_Test_Data_LDFLAGS) $(LDFLAGS) -o $@ am__objects_3 = LibTorrent_Test_Net-main.$(OBJEXT) \ helpers/LibTorrent_Test_Net-mock_function.$(OBJEXT) \ helpers/LibTorrent_Test_Net-network.$(OBJEXT) \ helpers/LibTorrent_Test_Net-progress_listener.$(OBJEXT) \ helpers/LibTorrent_Test_Net-protectors.$(OBJEXT) \ helpers/LibTorrent_Test_Net-test_fixture.$(OBJEXT) \ helpers/LibTorrent_Test_Net-test_main_thread.$(OBJEXT) \ helpers/LibTorrent_Test_Net-test_thread.$(OBJEXT) \ helpers/LibTorrent_Test_Net-tracker_test.$(OBJEXT) am_LibTorrent_Test_Net_OBJECTS = $(am__objects_3) LibTorrent_Test_Net_OBJECTS = $(am_LibTorrent_Test_Net_OBJECTS) LibTorrent_Test_Net_DEPENDENCIES = $(LibTorrent_Test_LDADD) LibTorrent_Test_Net_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(LibTorrent_Test_Net_CXXFLAGS) $(CXXFLAGS) \ $(LibTorrent_Test_Net_LDFLAGS) $(LDFLAGS) -o $@ am__objects_4 = LibTorrent_Test_Torrent-main.$(OBJEXT) \ helpers/LibTorrent_Test_Torrent-mock_function.$(OBJEXT) \ helpers/LibTorrent_Test_Torrent-network.$(OBJEXT) \ helpers/LibTorrent_Test_Torrent-progress_listener.$(OBJEXT) \ helpers/LibTorrent_Test_Torrent-protectors.$(OBJEXT) \ helpers/LibTorrent_Test_Torrent-test_fixture.$(OBJEXT) \ helpers/LibTorrent_Test_Torrent-test_main_thread.$(OBJEXT) \ helpers/LibTorrent_Test_Torrent-test_thread.$(OBJEXT) \ helpers/LibTorrent_Test_Torrent-tracker_test.$(OBJEXT) am_LibTorrent_Test_Torrent_OBJECTS = $(am__objects_4) \ torrent/LibTorrent_Test_Torrent-object_test.$(OBJEXT) \ torrent/LibTorrent_Test_Torrent-object_test_utils.$(OBJEXT) \ torrent/LibTorrent_Test_Torrent-object_static_map_test.$(OBJEXT) \ torrent/LibTorrent_Test_Torrent-object_stream_test.$(OBJEXT) \ torrent/LibTorrent_Test_Torrent-test_tracker_controller.$(OBJEXT) \ torrent/LibTorrent_Test_Torrent-test_tracker_controller_features.$(OBJEXT) \ torrent/LibTorrent_Test_Torrent-test_tracker_controller_requesting.$(OBJEXT) \ torrent/LibTorrent_Test_Torrent-test_tracker_list.$(OBJEXT) \ torrent/LibTorrent_Test_Torrent-test_tracker_list_features.$(OBJEXT) \ torrent/LibTorrent_Test_Torrent-test_tracker_timeout.$(OBJEXT) LibTorrent_Test_Torrent_OBJECTS = \ $(am_LibTorrent_Test_Torrent_OBJECTS) LibTorrent_Test_Torrent_DEPENDENCIES = $(LibTorrent_Test_LDADD) LibTorrent_Test_Torrent_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) \ $(LibTorrent_Test_Torrent_LDFLAGS) $(LDFLAGS) -o $@ am__objects_5 = LibTorrent_Test_Torrent_Net-main.$(OBJEXT) \ helpers/LibTorrent_Test_Torrent_Net-mock_function.$(OBJEXT) \ helpers/LibTorrent_Test_Torrent_Net-network.$(OBJEXT) \ helpers/LibTorrent_Test_Torrent_Net-progress_listener.$(OBJEXT) \ helpers/LibTorrent_Test_Torrent_Net-protectors.$(OBJEXT) \ helpers/LibTorrent_Test_Torrent_Net-test_fixture.$(OBJEXT) \ helpers/LibTorrent_Test_Torrent_Net-test_main_thread.$(OBJEXT) \ helpers/LibTorrent_Test_Torrent_Net-test_thread.$(OBJEXT) \ helpers/LibTorrent_Test_Torrent_Net-tracker_test.$(OBJEXT) am_LibTorrent_Test_Torrent_Net_OBJECTS = $(am__objects_5) \ torrent/net/LibTorrent_Test_Torrent_Net-test_address_info.$(OBJEXT) \ torrent/net/LibTorrent_Test_Torrent_Net-test_fd.$(OBJEXT) \ torrent/net/LibTorrent_Test_Torrent_Net-test_socket_address.$(OBJEXT) LibTorrent_Test_Torrent_Net_OBJECTS = \ $(am_LibTorrent_Test_Torrent_Net_OBJECTS) LibTorrent_Test_Torrent_Net_DEPENDENCIES = $(LibTorrent_Test_LDADD) LibTorrent_Test_Torrent_Net_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) \ $(LibTorrent_Test_Torrent_Net_LDFLAGS) $(LDFLAGS) -o $@ am__objects_6 = LibTorrent_Test_Torrent_Utils-main.$(OBJEXT) \ helpers/LibTorrent_Test_Torrent_Utils-mock_function.$(OBJEXT) \ helpers/LibTorrent_Test_Torrent_Utils-network.$(OBJEXT) \ helpers/LibTorrent_Test_Torrent_Utils-progress_listener.$(OBJEXT) \ helpers/LibTorrent_Test_Torrent_Utils-protectors.$(OBJEXT) \ helpers/LibTorrent_Test_Torrent_Utils-test_fixture.$(OBJEXT) \ helpers/LibTorrent_Test_Torrent_Utils-test_main_thread.$(OBJEXT) \ helpers/LibTorrent_Test_Torrent_Utils-test_thread.$(OBJEXT) \ helpers/LibTorrent_Test_Torrent_Utils-tracker_test.$(OBJEXT) am_LibTorrent_Test_Torrent_Utils_OBJECTS = $(am__objects_6) \ torrent/utils/LibTorrent_Test_Torrent_Utils-test_extents.$(OBJEXT) \ torrent/utils/LibTorrent_Test_Torrent_Utils-test_log.$(OBJEXT) \ torrent/utils/LibTorrent_Test_Torrent_Utils-test_log_buffer.$(OBJEXT) \ torrent/utils/LibTorrent_Test_Torrent_Utils-test_option_strings.$(OBJEXT) \ torrent/utils/LibTorrent_Test_Torrent_Utils-test_queue_buckets.$(OBJEXT) \ torrent/utils/LibTorrent_Test_Torrent_Utils-test_signal_bitfield.$(OBJEXT) \ torrent/utils/LibTorrent_Test_Torrent_Utils-test_signal_interrupt.$(OBJEXT) \ torrent/utils/LibTorrent_Test_Torrent_Utils-test_thread_base.$(OBJEXT) \ torrent/utils/LibTorrent_Test_Torrent_Utils-test_uri_parser.$(OBJEXT) LibTorrent_Test_Torrent_Utils_OBJECTS = \ $(am_LibTorrent_Test_Torrent_Utils_OBJECTS) LibTorrent_Test_Torrent_Utils_DEPENDENCIES = $(LibTorrent_Test_LDADD) LibTorrent_Test_Torrent_Utils_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) \ $(LibTorrent_Test_Torrent_Utils_LDFLAGS) $(LDFLAGS) -o $@ am__objects_7 = LibTorrent_Test_Tracker-main.$(OBJEXT) \ helpers/LibTorrent_Test_Tracker-mock_function.$(OBJEXT) \ helpers/LibTorrent_Test_Tracker-network.$(OBJEXT) \ helpers/LibTorrent_Test_Tracker-progress_listener.$(OBJEXT) \ helpers/LibTorrent_Test_Tracker-protectors.$(OBJEXT) \ helpers/LibTorrent_Test_Tracker-test_fixture.$(OBJEXT) \ helpers/LibTorrent_Test_Tracker-test_main_thread.$(OBJEXT) \ helpers/LibTorrent_Test_Tracker-test_thread.$(OBJEXT) \ helpers/LibTorrent_Test_Tracker-tracker_test.$(OBJEXT) am_LibTorrent_Test_Tracker_OBJECTS = $(am__objects_7) \ tracker/LibTorrent_Test_Tracker-test_tracker_http.$(OBJEXT) LibTorrent_Test_Tracker_OBJECTS = \ $(am_LibTorrent_Test_Tracker_OBJECTS) LibTorrent_Test_Tracker_DEPENDENCIES = $(LibTorrent_Test_LDADD) LibTorrent_Test_Tracker_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(LibTorrent_Test_Tracker_CXXFLAGS) $(CXXFLAGS) \ $(LibTorrent_Test_Tracker_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/LibTorrent_Test-main.Po \ ./$(DEPDIR)/LibTorrent_Test_Data-main.Po \ ./$(DEPDIR)/LibTorrent_Test_Net-main.Po \ ./$(DEPDIR)/LibTorrent_Test_Torrent-main.Po \ ./$(DEPDIR)/LibTorrent_Test_Torrent_Net-main.Po \ ./$(DEPDIR)/LibTorrent_Test_Torrent_Utils-main.Po \ ./$(DEPDIR)/LibTorrent_Test_Tracker-main.Po \ data/$(DEPDIR)/LibTorrent_Test_Data-test_chunk_list.Po \ data/$(DEPDIR)/LibTorrent_Test_Data-test_hash_check_queue.Po \ data/$(DEPDIR)/LibTorrent_Test_Data-test_hash_queue.Po \ helpers/$(DEPDIR)/LibTorrent_Test-mock_function.Po \ helpers/$(DEPDIR)/LibTorrent_Test-network.Po \ helpers/$(DEPDIR)/LibTorrent_Test-progress_listener.Po \ helpers/$(DEPDIR)/LibTorrent_Test-protectors.Po \ helpers/$(DEPDIR)/LibTorrent_Test-test_fixture.Po \ helpers/$(DEPDIR)/LibTorrent_Test-test_main_thread.Po \ helpers/$(DEPDIR)/LibTorrent_Test-test_thread.Po \ helpers/$(DEPDIR)/LibTorrent_Test-tracker_test.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Data-mock_function.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Data-network.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Data-progress_listener.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Data-protectors.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Data-test_fixture.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Data-test_main_thread.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Data-test_thread.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Data-tracker_test.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Net-mock_function.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Net-network.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Net-progress_listener.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Net-protectors.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Net-test_fixture.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Net-test_main_thread.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Net-test_thread.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Net-tracker_test.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Torrent-mock_function.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Torrent-network.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Torrent-progress_listener.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Torrent-protectors.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Torrent-test_fixture.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Torrent-test_main_thread.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Torrent-test_thread.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Torrent-tracker_test.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-mock_function.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-network.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-progress_listener.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-protectors.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_fixture.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_main_thread.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_thread.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-tracker_test.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-mock_function.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-network.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-progress_listener.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-protectors.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_fixture.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_main_thread.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_thread.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-tracker_test.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Tracker-mock_function.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Tracker-network.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Tracker-progress_listener.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Tracker-protectors.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Tracker-test_fixture.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Tracker-test_main_thread.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Tracker-test_thread.Po \ helpers/$(DEPDIR)/LibTorrent_Test_Tracker-tracker_test.Po \ protocol/$(DEPDIR)/LibTorrent_Test-test_request_list.Po \ rak/$(DEPDIR)/LibTorrent_Test-ranges_test.Po \ torrent/$(DEPDIR)/LibTorrent_Test_Torrent-object_static_map_test.Po \ torrent/$(DEPDIR)/LibTorrent_Test_Torrent-object_stream_test.Po \ torrent/$(DEPDIR)/LibTorrent_Test_Torrent-object_test.Po \ torrent/$(DEPDIR)/LibTorrent_Test_Torrent-object_test_utils.Po \ torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_controller.Po \ torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_controller_features.Po \ torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_controller_requesting.Po \ torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_list.Po \ torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_list_features.Po \ torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_timeout.Po \ torrent/net/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_address_info.Po \ torrent/net/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_fd.Po \ torrent/net/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_socket_address.Po \ torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_extents.Po \ torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_log.Po \ torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_log_buffer.Po \ torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_option_strings.Po \ torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_queue_buckets.Po \ torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_signal_bitfield.Po \ torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_signal_interrupt.Po \ torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_thread_base.Po \ torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_uri_parser.Po \ tracker/$(DEPDIR)/LibTorrent_Test_Tracker-test_tracker_http.Po am__mv = mv -f CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) AM_V_CXX = $(am__v_CXX_@AM_V@) am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) am__v_CXX_0 = @echo " CXX " $@; am__v_CXX_1 = CXXLD = $(CXX) CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(LibTorrent_Test_SOURCES) $(LibTorrent_Test_Data_SOURCES) \ $(LibTorrent_Test_Net_SOURCES) \ $(LibTorrent_Test_Torrent_SOURCES) \ $(LibTorrent_Test_Torrent_Net_SOURCES) \ $(LibTorrent_Test_Torrent_Utils_SOURCES) \ $(LibTorrent_Test_Tracker_SOURCES) DIST_SOURCES = $(LibTorrent_Test_SOURCES) \ $(LibTorrent_Test_Data_SOURCES) $(LibTorrent_Test_Net_SOURCES) \ $(LibTorrent_Test_Torrent_SOURCES) \ $(LibTorrent_Test_Torrent_Net_SOURCES) \ $(LibTorrent_Test_Torrent_Utils_SOURCES) \ $(LibTorrent_Test_Tracker_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ ATOMIC_LIBS = @ATOMIC_LIBS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPUNIT_CFLAGS = @CPPUNIT_CFLAGS@ CPPUNIT_LIBS = @CPPUNIT_LIBS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FILECMD = @FILECMD@ GREP = @GREP@ HAVE_CXX17 = @HAVE_CXX17@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBCURL = @LIBCURL@ LIBCURL_CFLAGS = @LIBCURL_CFLAGS@ LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@ LIBCURL_LIBS = @LIBCURL_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTORRENT_CFLAGS = @LIBTORRENT_CFLAGS@ LIBTORRENT_CURRENT = @LIBTORRENT_CURRENT@ LIBTORRENT_INTERFACE_VERSION_INFO = @LIBTORRENT_INTERFACE_VERSION_INFO@ LIBTORRENT_INTERFACE_VERSION_NO = @LIBTORRENT_INTERFACE_VERSION_NO@ LIBTORRENT_LIBS = @LIBTORRENT_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_CXX = @PTHREAD_CXX@ PTHREAD_LIBS = @PTHREAD_LIBS@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ _libcurl_config = @_libcurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__rm_f_notfound = @am__rm_f_notfound@ am__tar = @am__tar@ am__untar = @am__untar@ am__xargs_n = @am__xargs_n@ ax_pthread_config = @ax_pthread_config@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ # This can cause duplicate symbols, so export anything that causes issues. # LibTorrent_Test_LDADD = ../src/libtorrent.la LibTorrent_Test_LDADD = \ ../src/libtorrent.la \ ../src/libtorrent_other.la \ ../src/torrent/libtorrent_torrent.la LibTorrent_Test_Torrent_Net_LDADD = $(LibTorrent_Test_LDADD) LibTorrent_Test_Torrent_Utils_LDADD = $(LibTorrent_Test_LDADD) LibTorrent_Test_Torrent_LDADD = $(LibTorrent_Test_LDADD) LibTorrent_Test_Data_LDADD = $(LibTorrent_Test_LDADD) LibTorrent_Test_Net_LDADD = $(LibTorrent_Test_LDADD) LibTorrent_Test_Tracker_LDADD = $(LibTorrent_Test_LDADD) LibTorrent_Test_Common = \ main.cc \ helpers/expect_fd.h \ helpers/expect_utils.h \ helpers/mock_compare.h \ helpers/mock_function.cc \ helpers/mock_function.h \ helpers/network.cc \ helpers/network.h \ helpers/progress_listener.cc \ helpers/progress_listener.h \ helpers/protectors.cc \ helpers/protectors.h \ helpers/test_fixture.cc \ helpers/test_fixture.h \ helpers/test_main_thread.cc \ helpers/test_main_thread.h \ helpers/test_thread.cc \ helpers/test_thread.h \ helpers/test_utils.h \ helpers/tracker_test.cc \ helpers/tracker_test.h \ helpers/utils.h LibTorrent_Test_Torrent_Net_SOURCES = $(LibTorrent_Test_Common) \ torrent/net/test_address_info.cc \ torrent/net/test_address_info.h \ torrent/net/test_fd.cc \ torrent/net/test_fd.h \ torrent/net/test_socket_address.cc \ torrent/net/test_socket_address.h LibTorrent_Test_Torrent_Utils_SOURCES = $(LibTorrent_Test_Common) \ torrent/utils/test_extents.cc \ torrent/utils/test_extents.h \ torrent/utils/test_log.cc \ torrent/utils/test_log.h \ torrent/utils/test_log_buffer.cc \ torrent/utils/test_log_buffer.h \ torrent/utils/test_option_strings.cc \ torrent/utils/test_option_strings.h \ torrent/utils/test_queue_buckets.cc \ torrent/utils/test_queue_buckets.h \ torrent/utils/test_signal_bitfield.cc \ torrent/utils/test_signal_bitfield.h \ torrent/utils/test_signal_interrupt.cc \ torrent/utils/test_signal_interrupt.h \ torrent/utils/test_thread_base.cc \ torrent/utils/test_thread_base.h \ torrent/utils/test_uri_parser.cc \ torrent/utils/test_uri_parser.h LibTorrent_Test_Torrent_SOURCES = $(LibTorrent_Test_Common) \ torrent/object_test.cc \ torrent/object_test.h \ torrent/object_test_utils.cc \ torrent/object_test_utils.h \ torrent/object_static_map_test.cc \ torrent/object_static_map_test.h \ torrent/object_stream_test.cc \ torrent/object_stream_test.h \ torrent/test_tracker_controller.cc \ torrent/test_tracker_controller.h \ torrent/test_tracker_controller_features.cc \ torrent/test_tracker_controller_features.h \ torrent/test_tracker_controller_requesting.cc \ torrent/test_tracker_controller_requesting.h \ torrent/test_tracker_list.cc \ torrent/test_tracker_list.h \ torrent/test_tracker_list_features.cc \ torrent/test_tracker_list_features.h \ torrent/test_tracker_timeout.cc \ torrent/test_tracker_timeout.h LibTorrent_Test_Data_SOURCES = $(LibTorrent_Test_Common) \ data/test_chunk_list.cc \ data/test_chunk_list.h \ data/test_hash_check_queue.cc \ data/test_hash_check_queue.h \ data/test_hash_queue.cc \ data/test_hash_queue.h LibTorrent_Test_Net_SOURCES = $(LibTorrent_Test_Common) LibTorrent_Test_Tracker_SOURCES = $(LibTorrent_Test_Common) \ tracker/test_tracker_http.cc \ tracker/test_tracker_http.h LibTorrent_Test_SOURCES = $(LibTorrent_Test_Common) \ \ rak/ranges_test.cc \ rak/ranges_test.h \ \ protocol/test_request_list.cc \ protocol/test_request_list.h LibTorrent_Test_Torrent_Net_CXXFLAGS = $(CPPUNIT_CFLAGS) LibTorrent_Test_Torrent_Net_LDFLAGS = $(CPPUNIT_LIBS) LibTorrent_Test_Torrent_Utils_CXXFLAGS = $(CPPUNIT_CFLAGS) LibTorrent_Test_Torrent_Utils_LDFLAGS = $(CPPUNIT_LIBS) LibTorrent_Test_Torrent_CXXFLAGS = $(CPPUNIT_CFLAGS) LibTorrent_Test_Torrent_LDFLAGS = $(CPPUNIT_LIBS) LibTorrent_Test_Data_CXXFLAGS = $(CPPUNIT_CFLAGS) LibTorrent_Test_Data_LDFLAGS = $(CPPUNIT_LIBS) LibTorrent_Test_Net_CXXFLAGS = $(CPPUNIT_CFLAGS) LibTorrent_Test_Net_LDFLAGS = $(CPPUNIT_LIBS) LibTorrent_Test_Tracker_CXXFLAGS = $(CPPUNIT_CFLAGS) LibTorrent_Test_Tracker_LDFLAGS = $(CPPUNIT_LIBS) LibTorrent_Test_CXXFLAGS = $(CPPUNIT_CFLAGS) LibTorrent_Test_LDFLAGS = $(CPPUNIT_LIBS) AM_CPPFLAGS = -I$(srcdir) -I$(top_srcdir) -I$(top_srcdir)/src all: all-am .SUFFIXES: .SUFFIXES: .cc .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign test/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-checkPROGRAMS: $(am__rm_f) $(check_PROGRAMS) test -z "$(EXEEXT)" || $(am__rm_f) $(check_PROGRAMS:$(EXEEXT)=) helpers/$(am__dirstamp): @$(MKDIR_P) helpers @: >>helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) helpers/$(DEPDIR) @: >>helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test-mock_function.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test-network.$(OBJEXT): helpers/$(am__dirstamp) \ helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test-progress_listener.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test-protectors.$(OBJEXT): helpers/$(am__dirstamp) \ helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test-test_fixture.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test-test_main_thread.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test-test_thread.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test-tracker_test.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) rak/$(am__dirstamp): @$(MKDIR_P) rak @: >>rak/$(am__dirstamp) rak/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) rak/$(DEPDIR) @: >>rak/$(DEPDIR)/$(am__dirstamp) rak/LibTorrent_Test-ranges_test.$(OBJEXT): rak/$(am__dirstamp) \ rak/$(DEPDIR)/$(am__dirstamp) protocol/$(am__dirstamp): @$(MKDIR_P) protocol @: >>protocol/$(am__dirstamp) protocol/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) protocol/$(DEPDIR) @: >>protocol/$(DEPDIR)/$(am__dirstamp) protocol/LibTorrent_Test-test_request_list.$(OBJEXT): \ protocol/$(am__dirstamp) protocol/$(DEPDIR)/$(am__dirstamp) LibTorrent_Test$(EXEEXT): $(LibTorrent_Test_OBJECTS) $(LibTorrent_Test_DEPENDENCIES) $(EXTRA_LibTorrent_Test_DEPENDENCIES) @rm -f LibTorrent_Test$(EXEEXT) $(AM_V_CXXLD)$(LibTorrent_Test_LINK) $(LibTorrent_Test_OBJECTS) $(LibTorrent_Test_LDADD) $(LIBS) helpers/LibTorrent_Test_Data-mock_function.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test_Data-network.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test_Data-progress_listener.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test_Data-protectors.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test_Data-test_fixture.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test_Data-test_main_thread.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test_Data-test_thread.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test_Data-tracker_test.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) data/$(am__dirstamp): @$(MKDIR_P) data @: >>data/$(am__dirstamp) data/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) data/$(DEPDIR) @: >>data/$(DEPDIR)/$(am__dirstamp) data/LibTorrent_Test_Data-test_chunk_list.$(OBJEXT): \ data/$(am__dirstamp) data/$(DEPDIR)/$(am__dirstamp) data/LibTorrent_Test_Data-test_hash_check_queue.$(OBJEXT): \ data/$(am__dirstamp) data/$(DEPDIR)/$(am__dirstamp) data/LibTorrent_Test_Data-test_hash_queue.$(OBJEXT): \ data/$(am__dirstamp) data/$(DEPDIR)/$(am__dirstamp) LibTorrent_Test_Data$(EXEEXT): $(LibTorrent_Test_Data_OBJECTS) $(LibTorrent_Test_Data_DEPENDENCIES) $(EXTRA_LibTorrent_Test_Data_DEPENDENCIES) @rm -f LibTorrent_Test_Data$(EXEEXT) $(AM_V_CXXLD)$(LibTorrent_Test_Data_LINK) $(LibTorrent_Test_Data_OBJECTS) $(LibTorrent_Test_Data_LDADD) $(LIBS) helpers/LibTorrent_Test_Net-mock_function.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test_Net-network.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test_Net-progress_listener.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test_Net-protectors.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test_Net-test_fixture.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test_Net-test_main_thread.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test_Net-test_thread.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test_Net-tracker_test.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) LibTorrent_Test_Net$(EXEEXT): $(LibTorrent_Test_Net_OBJECTS) $(LibTorrent_Test_Net_DEPENDENCIES) $(EXTRA_LibTorrent_Test_Net_DEPENDENCIES) @rm -f LibTorrent_Test_Net$(EXEEXT) $(AM_V_CXXLD)$(LibTorrent_Test_Net_LINK) $(LibTorrent_Test_Net_OBJECTS) $(LibTorrent_Test_Net_LDADD) $(LIBS) helpers/LibTorrent_Test_Torrent-mock_function.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test_Torrent-network.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test_Torrent-progress_listener.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test_Torrent-protectors.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test_Torrent-test_fixture.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test_Torrent-test_main_thread.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test_Torrent-test_thread.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test_Torrent-tracker_test.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) torrent/$(am__dirstamp): @$(MKDIR_P) torrent @: >>torrent/$(am__dirstamp) torrent/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) torrent/$(DEPDIR) @: >>torrent/$(DEPDIR)/$(am__dirstamp) torrent/LibTorrent_Test_Torrent-object_test.$(OBJEXT): \ torrent/$(am__dirstamp) torrent/$(DEPDIR)/$(am__dirstamp) torrent/LibTorrent_Test_Torrent-object_test_utils.$(OBJEXT): \ torrent/$(am__dirstamp) torrent/$(DEPDIR)/$(am__dirstamp) torrent/LibTorrent_Test_Torrent-object_static_map_test.$(OBJEXT): \ torrent/$(am__dirstamp) torrent/$(DEPDIR)/$(am__dirstamp) torrent/LibTorrent_Test_Torrent-object_stream_test.$(OBJEXT): \ torrent/$(am__dirstamp) torrent/$(DEPDIR)/$(am__dirstamp) torrent/LibTorrent_Test_Torrent-test_tracker_controller.$(OBJEXT): \ torrent/$(am__dirstamp) torrent/$(DEPDIR)/$(am__dirstamp) torrent/LibTorrent_Test_Torrent-test_tracker_controller_features.$(OBJEXT): \ torrent/$(am__dirstamp) torrent/$(DEPDIR)/$(am__dirstamp) torrent/LibTorrent_Test_Torrent-test_tracker_controller_requesting.$(OBJEXT): \ torrent/$(am__dirstamp) torrent/$(DEPDIR)/$(am__dirstamp) torrent/LibTorrent_Test_Torrent-test_tracker_list.$(OBJEXT): \ torrent/$(am__dirstamp) torrent/$(DEPDIR)/$(am__dirstamp) torrent/LibTorrent_Test_Torrent-test_tracker_list_features.$(OBJEXT): \ torrent/$(am__dirstamp) torrent/$(DEPDIR)/$(am__dirstamp) torrent/LibTorrent_Test_Torrent-test_tracker_timeout.$(OBJEXT): \ torrent/$(am__dirstamp) torrent/$(DEPDIR)/$(am__dirstamp) LibTorrent_Test_Torrent$(EXEEXT): $(LibTorrent_Test_Torrent_OBJECTS) $(LibTorrent_Test_Torrent_DEPENDENCIES) $(EXTRA_LibTorrent_Test_Torrent_DEPENDENCIES) @rm -f LibTorrent_Test_Torrent$(EXEEXT) $(AM_V_CXXLD)$(LibTorrent_Test_Torrent_LINK) $(LibTorrent_Test_Torrent_OBJECTS) $(LibTorrent_Test_Torrent_LDADD) $(LIBS) helpers/LibTorrent_Test_Torrent_Net-mock_function.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test_Torrent_Net-network.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test_Torrent_Net-progress_listener.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test_Torrent_Net-protectors.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test_Torrent_Net-test_fixture.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test_Torrent_Net-test_main_thread.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test_Torrent_Net-test_thread.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test_Torrent_Net-tracker_test.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) torrent/net/$(am__dirstamp): @$(MKDIR_P) torrent/net @: >>torrent/net/$(am__dirstamp) torrent/net/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) torrent/net/$(DEPDIR) @: >>torrent/net/$(DEPDIR)/$(am__dirstamp) torrent/net/LibTorrent_Test_Torrent_Net-test_address_info.$(OBJEXT): \ torrent/net/$(am__dirstamp) \ torrent/net/$(DEPDIR)/$(am__dirstamp) torrent/net/LibTorrent_Test_Torrent_Net-test_fd.$(OBJEXT): \ torrent/net/$(am__dirstamp) \ torrent/net/$(DEPDIR)/$(am__dirstamp) torrent/net/LibTorrent_Test_Torrent_Net-test_socket_address.$(OBJEXT): \ torrent/net/$(am__dirstamp) \ torrent/net/$(DEPDIR)/$(am__dirstamp) LibTorrent_Test_Torrent_Net$(EXEEXT): $(LibTorrent_Test_Torrent_Net_OBJECTS) $(LibTorrent_Test_Torrent_Net_DEPENDENCIES) $(EXTRA_LibTorrent_Test_Torrent_Net_DEPENDENCIES) @rm -f LibTorrent_Test_Torrent_Net$(EXEEXT) $(AM_V_CXXLD)$(LibTorrent_Test_Torrent_Net_LINK) $(LibTorrent_Test_Torrent_Net_OBJECTS) $(LibTorrent_Test_Torrent_Net_LDADD) $(LIBS) helpers/LibTorrent_Test_Torrent_Utils-mock_function.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test_Torrent_Utils-network.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test_Torrent_Utils-progress_listener.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test_Torrent_Utils-protectors.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test_Torrent_Utils-test_fixture.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test_Torrent_Utils-test_main_thread.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test_Torrent_Utils-test_thread.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test_Torrent_Utils-tracker_test.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) torrent/utils/$(am__dirstamp): @$(MKDIR_P) torrent/utils @: >>torrent/utils/$(am__dirstamp) torrent/utils/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) torrent/utils/$(DEPDIR) @: >>torrent/utils/$(DEPDIR)/$(am__dirstamp) torrent/utils/LibTorrent_Test_Torrent_Utils-test_extents.$(OBJEXT): \ torrent/utils/$(am__dirstamp) \ torrent/utils/$(DEPDIR)/$(am__dirstamp) torrent/utils/LibTorrent_Test_Torrent_Utils-test_log.$(OBJEXT): \ torrent/utils/$(am__dirstamp) \ torrent/utils/$(DEPDIR)/$(am__dirstamp) torrent/utils/LibTorrent_Test_Torrent_Utils-test_log_buffer.$(OBJEXT): \ torrent/utils/$(am__dirstamp) \ torrent/utils/$(DEPDIR)/$(am__dirstamp) torrent/utils/LibTorrent_Test_Torrent_Utils-test_option_strings.$(OBJEXT): \ torrent/utils/$(am__dirstamp) \ torrent/utils/$(DEPDIR)/$(am__dirstamp) torrent/utils/LibTorrent_Test_Torrent_Utils-test_queue_buckets.$(OBJEXT): \ torrent/utils/$(am__dirstamp) \ torrent/utils/$(DEPDIR)/$(am__dirstamp) torrent/utils/LibTorrent_Test_Torrent_Utils-test_signal_bitfield.$(OBJEXT): \ torrent/utils/$(am__dirstamp) \ torrent/utils/$(DEPDIR)/$(am__dirstamp) torrent/utils/LibTorrent_Test_Torrent_Utils-test_signal_interrupt.$(OBJEXT): \ torrent/utils/$(am__dirstamp) \ torrent/utils/$(DEPDIR)/$(am__dirstamp) torrent/utils/LibTorrent_Test_Torrent_Utils-test_thread_base.$(OBJEXT): \ torrent/utils/$(am__dirstamp) \ torrent/utils/$(DEPDIR)/$(am__dirstamp) torrent/utils/LibTorrent_Test_Torrent_Utils-test_uri_parser.$(OBJEXT): \ torrent/utils/$(am__dirstamp) \ torrent/utils/$(DEPDIR)/$(am__dirstamp) LibTorrent_Test_Torrent_Utils$(EXEEXT): $(LibTorrent_Test_Torrent_Utils_OBJECTS) $(LibTorrent_Test_Torrent_Utils_DEPENDENCIES) $(EXTRA_LibTorrent_Test_Torrent_Utils_DEPENDENCIES) @rm -f LibTorrent_Test_Torrent_Utils$(EXEEXT) $(AM_V_CXXLD)$(LibTorrent_Test_Torrent_Utils_LINK) $(LibTorrent_Test_Torrent_Utils_OBJECTS) $(LibTorrent_Test_Torrent_Utils_LDADD) $(LIBS) helpers/LibTorrent_Test_Tracker-mock_function.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test_Tracker-network.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test_Tracker-progress_listener.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test_Tracker-protectors.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test_Tracker-test_fixture.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test_Tracker-test_main_thread.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test_Tracker-test_thread.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) helpers/LibTorrent_Test_Tracker-tracker_test.$(OBJEXT): \ helpers/$(am__dirstamp) helpers/$(DEPDIR)/$(am__dirstamp) tracker/$(am__dirstamp): @$(MKDIR_P) tracker @: >>tracker/$(am__dirstamp) tracker/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) tracker/$(DEPDIR) @: >>tracker/$(DEPDIR)/$(am__dirstamp) tracker/LibTorrent_Test_Tracker-test_tracker_http.$(OBJEXT): \ tracker/$(am__dirstamp) tracker/$(DEPDIR)/$(am__dirstamp) LibTorrent_Test_Tracker$(EXEEXT): $(LibTorrent_Test_Tracker_OBJECTS) $(LibTorrent_Test_Tracker_DEPENDENCIES) $(EXTRA_LibTorrent_Test_Tracker_DEPENDENCIES) @rm -f LibTorrent_Test_Tracker$(EXEEXT) $(AM_V_CXXLD)$(LibTorrent_Test_Tracker_LINK) $(LibTorrent_Test_Tracker_OBJECTS) $(LibTorrent_Test_Tracker_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) -rm -f data/*.$(OBJEXT) -rm -f helpers/*.$(OBJEXT) -rm -f protocol/*.$(OBJEXT) -rm -f rak/*.$(OBJEXT) -rm -f torrent/*.$(OBJEXT) -rm -f torrent/net/*.$(OBJEXT) -rm -f torrent/utils/*.$(OBJEXT) -rm -f tracker/*.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/LibTorrent_Test-main.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/LibTorrent_Test_Data-main.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/LibTorrent_Test_Net-main.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/LibTorrent_Test_Torrent-main.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/LibTorrent_Test_Torrent_Net-main.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/LibTorrent_Test_Torrent_Utils-main.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/LibTorrent_Test_Tracker-main.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@data/$(DEPDIR)/LibTorrent_Test_Data-test_chunk_list.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@data/$(DEPDIR)/LibTorrent_Test_Data-test_hash_check_queue.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@data/$(DEPDIR)/LibTorrent_Test_Data-test_hash_queue.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test-mock_function.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test-network.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test-progress_listener.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test-protectors.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test-test_fixture.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test-test_main_thread.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test-test_thread.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test-tracker_test.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Data-mock_function.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Data-network.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Data-progress_listener.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Data-protectors.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Data-test_fixture.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Data-test_main_thread.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Data-test_thread.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Data-tracker_test.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Net-mock_function.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Net-network.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Net-progress_listener.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Net-protectors.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Net-test_fixture.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Net-test_main_thread.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Net-test_thread.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Net-tracker_test.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Torrent-mock_function.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Torrent-network.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Torrent-progress_listener.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Torrent-protectors.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Torrent-test_fixture.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Torrent-test_main_thread.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Torrent-test_thread.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Torrent-tracker_test.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-mock_function.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-network.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-progress_listener.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-protectors.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_fixture.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_main_thread.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_thread.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-tracker_test.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-mock_function.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-network.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-progress_listener.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-protectors.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_fixture.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_main_thread.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_thread.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-tracker_test.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Tracker-mock_function.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Tracker-network.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Tracker-progress_listener.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Tracker-protectors.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Tracker-test_fixture.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Tracker-test_main_thread.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Tracker-test_thread.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@helpers/$(DEPDIR)/LibTorrent_Test_Tracker-tracker_test.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@protocol/$(DEPDIR)/LibTorrent_Test-test_request_list.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@rak/$(DEPDIR)/LibTorrent_Test-ranges_test.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@torrent/$(DEPDIR)/LibTorrent_Test_Torrent-object_static_map_test.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@torrent/$(DEPDIR)/LibTorrent_Test_Torrent-object_stream_test.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@torrent/$(DEPDIR)/LibTorrent_Test_Torrent-object_test.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@torrent/$(DEPDIR)/LibTorrent_Test_Torrent-object_test_utils.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_controller.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_controller_features.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_controller_requesting.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_list.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_list_features.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_timeout.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@torrent/net/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_address_info.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@torrent/net/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_fd.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@torrent/net/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_socket_address.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_extents.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_log.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_log_buffer.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_option_strings.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_queue_buckets.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_signal_bitfield.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_signal_interrupt.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_thread_base.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_uri_parser.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@tracker/$(DEPDIR)/LibTorrent_Test_Tracker-test_tracker_http.Po@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @: >>$@ am--depfiles: $(am__depfiles_remade) .cc.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cc.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cc.lo: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< LibTorrent_Test-main.o: main.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -MT LibTorrent_Test-main.o -MD -MP -MF $(DEPDIR)/LibTorrent_Test-main.Tpo -c -o LibTorrent_Test-main.o `test -f 'main.cc' || echo '$(srcdir)/'`main.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/LibTorrent_Test-main.Tpo $(DEPDIR)/LibTorrent_Test-main.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='main.cc' object='LibTorrent_Test-main.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -c -o LibTorrent_Test-main.o `test -f 'main.cc' || echo '$(srcdir)/'`main.cc LibTorrent_Test-main.obj: main.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -MT LibTorrent_Test-main.obj -MD -MP -MF $(DEPDIR)/LibTorrent_Test-main.Tpo -c -o LibTorrent_Test-main.obj `if test -f 'main.cc'; then $(CYGPATH_W) 'main.cc'; else $(CYGPATH_W) '$(srcdir)/main.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/LibTorrent_Test-main.Tpo $(DEPDIR)/LibTorrent_Test-main.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='main.cc' object='LibTorrent_Test-main.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -c -o LibTorrent_Test-main.obj `if test -f 'main.cc'; then $(CYGPATH_W) 'main.cc'; else $(CYGPATH_W) '$(srcdir)/main.cc'; fi` helpers/LibTorrent_Test-mock_function.o: helpers/mock_function.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test-mock_function.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test-mock_function.Tpo -c -o helpers/LibTorrent_Test-mock_function.o `test -f 'helpers/mock_function.cc' || echo '$(srcdir)/'`helpers/mock_function.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test-mock_function.Tpo helpers/$(DEPDIR)/LibTorrent_Test-mock_function.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/mock_function.cc' object='helpers/LibTorrent_Test-mock_function.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test-mock_function.o `test -f 'helpers/mock_function.cc' || echo '$(srcdir)/'`helpers/mock_function.cc helpers/LibTorrent_Test-mock_function.obj: helpers/mock_function.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test-mock_function.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test-mock_function.Tpo -c -o helpers/LibTorrent_Test-mock_function.obj `if test -f 'helpers/mock_function.cc'; then $(CYGPATH_W) 'helpers/mock_function.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/mock_function.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test-mock_function.Tpo helpers/$(DEPDIR)/LibTorrent_Test-mock_function.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/mock_function.cc' object='helpers/LibTorrent_Test-mock_function.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test-mock_function.obj `if test -f 'helpers/mock_function.cc'; then $(CYGPATH_W) 'helpers/mock_function.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/mock_function.cc'; fi` helpers/LibTorrent_Test-network.o: helpers/network.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test-network.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test-network.Tpo -c -o helpers/LibTorrent_Test-network.o `test -f 'helpers/network.cc' || echo '$(srcdir)/'`helpers/network.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test-network.Tpo helpers/$(DEPDIR)/LibTorrent_Test-network.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/network.cc' object='helpers/LibTorrent_Test-network.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test-network.o `test -f 'helpers/network.cc' || echo '$(srcdir)/'`helpers/network.cc helpers/LibTorrent_Test-network.obj: helpers/network.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test-network.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test-network.Tpo -c -o helpers/LibTorrent_Test-network.obj `if test -f 'helpers/network.cc'; then $(CYGPATH_W) 'helpers/network.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/network.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test-network.Tpo helpers/$(DEPDIR)/LibTorrent_Test-network.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/network.cc' object='helpers/LibTorrent_Test-network.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test-network.obj `if test -f 'helpers/network.cc'; then $(CYGPATH_W) 'helpers/network.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/network.cc'; fi` helpers/LibTorrent_Test-progress_listener.o: helpers/progress_listener.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test-progress_listener.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test-progress_listener.Tpo -c -o helpers/LibTorrent_Test-progress_listener.o `test -f 'helpers/progress_listener.cc' || echo '$(srcdir)/'`helpers/progress_listener.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test-progress_listener.Tpo helpers/$(DEPDIR)/LibTorrent_Test-progress_listener.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/progress_listener.cc' object='helpers/LibTorrent_Test-progress_listener.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test-progress_listener.o `test -f 'helpers/progress_listener.cc' || echo '$(srcdir)/'`helpers/progress_listener.cc helpers/LibTorrent_Test-progress_listener.obj: helpers/progress_listener.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test-progress_listener.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test-progress_listener.Tpo -c -o helpers/LibTorrent_Test-progress_listener.obj `if test -f 'helpers/progress_listener.cc'; then $(CYGPATH_W) 'helpers/progress_listener.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/progress_listener.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test-progress_listener.Tpo helpers/$(DEPDIR)/LibTorrent_Test-progress_listener.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/progress_listener.cc' object='helpers/LibTorrent_Test-progress_listener.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test-progress_listener.obj `if test -f 'helpers/progress_listener.cc'; then $(CYGPATH_W) 'helpers/progress_listener.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/progress_listener.cc'; fi` helpers/LibTorrent_Test-protectors.o: helpers/protectors.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test-protectors.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test-protectors.Tpo -c -o helpers/LibTorrent_Test-protectors.o `test -f 'helpers/protectors.cc' || echo '$(srcdir)/'`helpers/protectors.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test-protectors.Tpo helpers/$(DEPDIR)/LibTorrent_Test-protectors.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/protectors.cc' object='helpers/LibTorrent_Test-protectors.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test-protectors.o `test -f 'helpers/protectors.cc' || echo '$(srcdir)/'`helpers/protectors.cc helpers/LibTorrent_Test-protectors.obj: helpers/protectors.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test-protectors.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test-protectors.Tpo -c -o helpers/LibTorrent_Test-protectors.obj `if test -f 'helpers/protectors.cc'; then $(CYGPATH_W) 'helpers/protectors.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/protectors.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test-protectors.Tpo helpers/$(DEPDIR)/LibTorrent_Test-protectors.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/protectors.cc' object='helpers/LibTorrent_Test-protectors.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test-protectors.obj `if test -f 'helpers/protectors.cc'; then $(CYGPATH_W) 'helpers/protectors.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/protectors.cc'; fi` helpers/LibTorrent_Test-test_fixture.o: helpers/test_fixture.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test-test_fixture.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test-test_fixture.Tpo -c -o helpers/LibTorrent_Test-test_fixture.o `test -f 'helpers/test_fixture.cc' || echo '$(srcdir)/'`helpers/test_fixture.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test-test_fixture.Tpo helpers/$(DEPDIR)/LibTorrent_Test-test_fixture.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/test_fixture.cc' object='helpers/LibTorrent_Test-test_fixture.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test-test_fixture.o `test -f 'helpers/test_fixture.cc' || echo '$(srcdir)/'`helpers/test_fixture.cc helpers/LibTorrent_Test-test_fixture.obj: helpers/test_fixture.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test-test_fixture.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test-test_fixture.Tpo -c -o helpers/LibTorrent_Test-test_fixture.obj `if test -f 'helpers/test_fixture.cc'; then $(CYGPATH_W) 'helpers/test_fixture.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/test_fixture.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test-test_fixture.Tpo helpers/$(DEPDIR)/LibTorrent_Test-test_fixture.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/test_fixture.cc' object='helpers/LibTorrent_Test-test_fixture.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test-test_fixture.obj `if test -f 'helpers/test_fixture.cc'; then $(CYGPATH_W) 'helpers/test_fixture.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/test_fixture.cc'; fi` helpers/LibTorrent_Test-test_main_thread.o: helpers/test_main_thread.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test-test_main_thread.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test-test_main_thread.Tpo -c -o helpers/LibTorrent_Test-test_main_thread.o `test -f 'helpers/test_main_thread.cc' || echo '$(srcdir)/'`helpers/test_main_thread.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test-test_main_thread.Tpo helpers/$(DEPDIR)/LibTorrent_Test-test_main_thread.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/test_main_thread.cc' object='helpers/LibTorrent_Test-test_main_thread.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test-test_main_thread.o `test -f 'helpers/test_main_thread.cc' || echo '$(srcdir)/'`helpers/test_main_thread.cc helpers/LibTorrent_Test-test_main_thread.obj: helpers/test_main_thread.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test-test_main_thread.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test-test_main_thread.Tpo -c -o helpers/LibTorrent_Test-test_main_thread.obj `if test -f 'helpers/test_main_thread.cc'; then $(CYGPATH_W) 'helpers/test_main_thread.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/test_main_thread.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test-test_main_thread.Tpo helpers/$(DEPDIR)/LibTorrent_Test-test_main_thread.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/test_main_thread.cc' object='helpers/LibTorrent_Test-test_main_thread.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test-test_main_thread.obj `if test -f 'helpers/test_main_thread.cc'; then $(CYGPATH_W) 'helpers/test_main_thread.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/test_main_thread.cc'; fi` helpers/LibTorrent_Test-test_thread.o: helpers/test_thread.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test-test_thread.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test-test_thread.Tpo -c -o helpers/LibTorrent_Test-test_thread.o `test -f 'helpers/test_thread.cc' || echo '$(srcdir)/'`helpers/test_thread.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test-test_thread.Tpo helpers/$(DEPDIR)/LibTorrent_Test-test_thread.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/test_thread.cc' object='helpers/LibTorrent_Test-test_thread.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test-test_thread.o `test -f 'helpers/test_thread.cc' || echo '$(srcdir)/'`helpers/test_thread.cc helpers/LibTorrent_Test-test_thread.obj: helpers/test_thread.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test-test_thread.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test-test_thread.Tpo -c -o helpers/LibTorrent_Test-test_thread.obj `if test -f 'helpers/test_thread.cc'; then $(CYGPATH_W) 'helpers/test_thread.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/test_thread.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test-test_thread.Tpo helpers/$(DEPDIR)/LibTorrent_Test-test_thread.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/test_thread.cc' object='helpers/LibTorrent_Test-test_thread.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test-test_thread.obj `if test -f 'helpers/test_thread.cc'; then $(CYGPATH_W) 'helpers/test_thread.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/test_thread.cc'; fi` helpers/LibTorrent_Test-tracker_test.o: helpers/tracker_test.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test-tracker_test.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test-tracker_test.Tpo -c -o helpers/LibTorrent_Test-tracker_test.o `test -f 'helpers/tracker_test.cc' || echo '$(srcdir)/'`helpers/tracker_test.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test-tracker_test.Tpo helpers/$(DEPDIR)/LibTorrent_Test-tracker_test.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/tracker_test.cc' object='helpers/LibTorrent_Test-tracker_test.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test-tracker_test.o `test -f 'helpers/tracker_test.cc' || echo '$(srcdir)/'`helpers/tracker_test.cc helpers/LibTorrent_Test-tracker_test.obj: helpers/tracker_test.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test-tracker_test.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test-tracker_test.Tpo -c -o helpers/LibTorrent_Test-tracker_test.obj `if test -f 'helpers/tracker_test.cc'; then $(CYGPATH_W) 'helpers/tracker_test.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/tracker_test.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test-tracker_test.Tpo helpers/$(DEPDIR)/LibTorrent_Test-tracker_test.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/tracker_test.cc' object='helpers/LibTorrent_Test-tracker_test.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test-tracker_test.obj `if test -f 'helpers/tracker_test.cc'; then $(CYGPATH_W) 'helpers/tracker_test.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/tracker_test.cc'; fi` rak/LibTorrent_Test-ranges_test.o: rak/ranges_test.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -MT rak/LibTorrent_Test-ranges_test.o -MD -MP -MF rak/$(DEPDIR)/LibTorrent_Test-ranges_test.Tpo -c -o rak/LibTorrent_Test-ranges_test.o `test -f 'rak/ranges_test.cc' || echo '$(srcdir)/'`rak/ranges_test.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) rak/$(DEPDIR)/LibTorrent_Test-ranges_test.Tpo rak/$(DEPDIR)/LibTorrent_Test-ranges_test.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rak/ranges_test.cc' object='rak/LibTorrent_Test-ranges_test.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -c -o rak/LibTorrent_Test-ranges_test.o `test -f 'rak/ranges_test.cc' || echo '$(srcdir)/'`rak/ranges_test.cc rak/LibTorrent_Test-ranges_test.obj: rak/ranges_test.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -MT rak/LibTorrent_Test-ranges_test.obj -MD -MP -MF rak/$(DEPDIR)/LibTorrent_Test-ranges_test.Tpo -c -o rak/LibTorrent_Test-ranges_test.obj `if test -f 'rak/ranges_test.cc'; then $(CYGPATH_W) 'rak/ranges_test.cc'; else $(CYGPATH_W) '$(srcdir)/rak/ranges_test.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) rak/$(DEPDIR)/LibTorrent_Test-ranges_test.Tpo rak/$(DEPDIR)/LibTorrent_Test-ranges_test.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='rak/ranges_test.cc' object='rak/LibTorrent_Test-ranges_test.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -c -o rak/LibTorrent_Test-ranges_test.obj `if test -f 'rak/ranges_test.cc'; then $(CYGPATH_W) 'rak/ranges_test.cc'; else $(CYGPATH_W) '$(srcdir)/rak/ranges_test.cc'; fi` protocol/LibTorrent_Test-test_request_list.o: protocol/test_request_list.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -MT protocol/LibTorrent_Test-test_request_list.o -MD -MP -MF protocol/$(DEPDIR)/LibTorrent_Test-test_request_list.Tpo -c -o protocol/LibTorrent_Test-test_request_list.o `test -f 'protocol/test_request_list.cc' || echo '$(srcdir)/'`protocol/test_request_list.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) protocol/$(DEPDIR)/LibTorrent_Test-test_request_list.Tpo protocol/$(DEPDIR)/LibTorrent_Test-test_request_list.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='protocol/test_request_list.cc' object='protocol/LibTorrent_Test-test_request_list.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -c -o protocol/LibTorrent_Test-test_request_list.o `test -f 'protocol/test_request_list.cc' || echo '$(srcdir)/'`protocol/test_request_list.cc protocol/LibTorrent_Test-test_request_list.obj: protocol/test_request_list.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -MT protocol/LibTorrent_Test-test_request_list.obj -MD -MP -MF protocol/$(DEPDIR)/LibTorrent_Test-test_request_list.Tpo -c -o protocol/LibTorrent_Test-test_request_list.obj `if test -f 'protocol/test_request_list.cc'; then $(CYGPATH_W) 'protocol/test_request_list.cc'; else $(CYGPATH_W) '$(srcdir)/protocol/test_request_list.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) protocol/$(DEPDIR)/LibTorrent_Test-test_request_list.Tpo protocol/$(DEPDIR)/LibTorrent_Test-test_request_list.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='protocol/test_request_list.cc' object='protocol/LibTorrent_Test-test_request_list.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_CXXFLAGS) $(CXXFLAGS) -c -o protocol/LibTorrent_Test-test_request_list.obj `if test -f 'protocol/test_request_list.cc'; then $(CYGPATH_W) 'protocol/test_request_list.cc'; else $(CYGPATH_W) '$(srcdir)/protocol/test_request_list.cc'; fi` LibTorrent_Test_Data-main.o: main.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -MT LibTorrent_Test_Data-main.o -MD -MP -MF $(DEPDIR)/LibTorrent_Test_Data-main.Tpo -c -o LibTorrent_Test_Data-main.o `test -f 'main.cc' || echo '$(srcdir)/'`main.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/LibTorrent_Test_Data-main.Tpo $(DEPDIR)/LibTorrent_Test_Data-main.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='main.cc' object='LibTorrent_Test_Data-main.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -c -o LibTorrent_Test_Data-main.o `test -f 'main.cc' || echo '$(srcdir)/'`main.cc LibTorrent_Test_Data-main.obj: main.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -MT LibTorrent_Test_Data-main.obj -MD -MP -MF $(DEPDIR)/LibTorrent_Test_Data-main.Tpo -c -o LibTorrent_Test_Data-main.obj `if test -f 'main.cc'; then $(CYGPATH_W) 'main.cc'; else $(CYGPATH_W) '$(srcdir)/main.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/LibTorrent_Test_Data-main.Tpo $(DEPDIR)/LibTorrent_Test_Data-main.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='main.cc' object='LibTorrent_Test_Data-main.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -c -o LibTorrent_Test_Data-main.obj `if test -f 'main.cc'; then $(CYGPATH_W) 'main.cc'; else $(CYGPATH_W) '$(srcdir)/main.cc'; fi` helpers/LibTorrent_Test_Data-mock_function.o: helpers/mock_function.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Data-mock_function.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Data-mock_function.Tpo -c -o helpers/LibTorrent_Test_Data-mock_function.o `test -f 'helpers/mock_function.cc' || echo '$(srcdir)/'`helpers/mock_function.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Data-mock_function.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Data-mock_function.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/mock_function.cc' object='helpers/LibTorrent_Test_Data-mock_function.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Data-mock_function.o `test -f 'helpers/mock_function.cc' || echo '$(srcdir)/'`helpers/mock_function.cc helpers/LibTorrent_Test_Data-mock_function.obj: helpers/mock_function.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Data-mock_function.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Data-mock_function.Tpo -c -o helpers/LibTorrent_Test_Data-mock_function.obj `if test -f 'helpers/mock_function.cc'; then $(CYGPATH_W) 'helpers/mock_function.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/mock_function.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Data-mock_function.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Data-mock_function.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/mock_function.cc' object='helpers/LibTorrent_Test_Data-mock_function.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Data-mock_function.obj `if test -f 'helpers/mock_function.cc'; then $(CYGPATH_W) 'helpers/mock_function.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/mock_function.cc'; fi` helpers/LibTorrent_Test_Data-network.o: helpers/network.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Data-network.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Data-network.Tpo -c -o helpers/LibTorrent_Test_Data-network.o `test -f 'helpers/network.cc' || echo '$(srcdir)/'`helpers/network.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Data-network.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Data-network.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/network.cc' object='helpers/LibTorrent_Test_Data-network.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Data-network.o `test -f 'helpers/network.cc' || echo '$(srcdir)/'`helpers/network.cc helpers/LibTorrent_Test_Data-network.obj: helpers/network.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Data-network.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Data-network.Tpo -c -o helpers/LibTorrent_Test_Data-network.obj `if test -f 'helpers/network.cc'; then $(CYGPATH_W) 'helpers/network.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/network.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Data-network.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Data-network.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/network.cc' object='helpers/LibTorrent_Test_Data-network.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Data-network.obj `if test -f 'helpers/network.cc'; then $(CYGPATH_W) 'helpers/network.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/network.cc'; fi` helpers/LibTorrent_Test_Data-progress_listener.o: helpers/progress_listener.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Data-progress_listener.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Data-progress_listener.Tpo -c -o helpers/LibTorrent_Test_Data-progress_listener.o `test -f 'helpers/progress_listener.cc' || echo '$(srcdir)/'`helpers/progress_listener.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Data-progress_listener.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Data-progress_listener.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/progress_listener.cc' object='helpers/LibTorrent_Test_Data-progress_listener.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Data-progress_listener.o `test -f 'helpers/progress_listener.cc' || echo '$(srcdir)/'`helpers/progress_listener.cc helpers/LibTorrent_Test_Data-progress_listener.obj: helpers/progress_listener.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Data-progress_listener.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Data-progress_listener.Tpo -c -o helpers/LibTorrent_Test_Data-progress_listener.obj `if test -f 'helpers/progress_listener.cc'; then $(CYGPATH_W) 'helpers/progress_listener.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/progress_listener.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Data-progress_listener.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Data-progress_listener.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/progress_listener.cc' object='helpers/LibTorrent_Test_Data-progress_listener.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Data-progress_listener.obj `if test -f 'helpers/progress_listener.cc'; then $(CYGPATH_W) 'helpers/progress_listener.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/progress_listener.cc'; fi` helpers/LibTorrent_Test_Data-protectors.o: helpers/protectors.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Data-protectors.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Data-protectors.Tpo -c -o helpers/LibTorrent_Test_Data-protectors.o `test -f 'helpers/protectors.cc' || echo '$(srcdir)/'`helpers/protectors.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Data-protectors.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Data-protectors.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/protectors.cc' object='helpers/LibTorrent_Test_Data-protectors.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Data-protectors.o `test -f 'helpers/protectors.cc' || echo '$(srcdir)/'`helpers/protectors.cc helpers/LibTorrent_Test_Data-protectors.obj: helpers/protectors.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Data-protectors.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Data-protectors.Tpo -c -o helpers/LibTorrent_Test_Data-protectors.obj `if test -f 'helpers/protectors.cc'; then $(CYGPATH_W) 'helpers/protectors.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/protectors.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Data-protectors.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Data-protectors.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/protectors.cc' object='helpers/LibTorrent_Test_Data-protectors.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Data-protectors.obj `if test -f 'helpers/protectors.cc'; then $(CYGPATH_W) 'helpers/protectors.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/protectors.cc'; fi` helpers/LibTorrent_Test_Data-test_fixture.o: helpers/test_fixture.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Data-test_fixture.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Data-test_fixture.Tpo -c -o helpers/LibTorrent_Test_Data-test_fixture.o `test -f 'helpers/test_fixture.cc' || echo '$(srcdir)/'`helpers/test_fixture.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Data-test_fixture.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Data-test_fixture.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/test_fixture.cc' object='helpers/LibTorrent_Test_Data-test_fixture.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Data-test_fixture.o `test -f 'helpers/test_fixture.cc' || echo '$(srcdir)/'`helpers/test_fixture.cc helpers/LibTorrent_Test_Data-test_fixture.obj: helpers/test_fixture.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Data-test_fixture.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Data-test_fixture.Tpo -c -o helpers/LibTorrent_Test_Data-test_fixture.obj `if test -f 'helpers/test_fixture.cc'; then $(CYGPATH_W) 'helpers/test_fixture.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/test_fixture.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Data-test_fixture.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Data-test_fixture.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/test_fixture.cc' object='helpers/LibTorrent_Test_Data-test_fixture.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Data-test_fixture.obj `if test -f 'helpers/test_fixture.cc'; then $(CYGPATH_W) 'helpers/test_fixture.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/test_fixture.cc'; fi` helpers/LibTorrent_Test_Data-test_main_thread.o: helpers/test_main_thread.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Data-test_main_thread.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Data-test_main_thread.Tpo -c -o helpers/LibTorrent_Test_Data-test_main_thread.o `test -f 'helpers/test_main_thread.cc' || echo '$(srcdir)/'`helpers/test_main_thread.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Data-test_main_thread.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Data-test_main_thread.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/test_main_thread.cc' object='helpers/LibTorrent_Test_Data-test_main_thread.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Data-test_main_thread.o `test -f 'helpers/test_main_thread.cc' || echo '$(srcdir)/'`helpers/test_main_thread.cc helpers/LibTorrent_Test_Data-test_main_thread.obj: helpers/test_main_thread.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Data-test_main_thread.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Data-test_main_thread.Tpo -c -o helpers/LibTorrent_Test_Data-test_main_thread.obj `if test -f 'helpers/test_main_thread.cc'; then $(CYGPATH_W) 'helpers/test_main_thread.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/test_main_thread.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Data-test_main_thread.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Data-test_main_thread.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/test_main_thread.cc' object='helpers/LibTorrent_Test_Data-test_main_thread.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Data-test_main_thread.obj `if test -f 'helpers/test_main_thread.cc'; then $(CYGPATH_W) 'helpers/test_main_thread.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/test_main_thread.cc'; fi` helpers/LibTorrent_Test_Data-test_thread.o: helpers/test_thread.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Data-test_thread.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Data-test_thread.Tpo -c -o helpers/LibTorrent_Test_Data-test_thread.o `test -f 'helpers/test_thread.cc' || echo '$(srcdir)/'`helpers/test_thread.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Data-test_thread.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Data-test_thread.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/test_thread.cc' object='helpers/LibTorrent_Test_Data-test_thread.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Data-test_thread.o `test -f 'helpers/test_thread.cc' || echo '$(srcdir)/'`helpers/test_thread.cc helpers/LibTorrent_Test_Data-test_thread.obj: helpers/test_thread.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Data-test_thread.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Data-test_thread.Tpo -c -o helpers/LibTorrent_Test_Data-test_thread.obj `if test -f 'helpers/test_thread.cc'; then $(CYGPATH_W) 'helpers/test_thread.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/test_thread.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Data-test_thread.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Data-test_thread.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/test_thread.cc' object='helpers/LibTorrent_Test_Data-test_thread.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Data-test_thread.obj `if test -f 'helpers/test_thread.cc'; then $(CYGPATH_W) 'helpers/test_thread.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/test_thread.cc'; fi` helpers/LibTorrent_Test_Data-tracker_test.o: helpers/tracker_test.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Data-tracker_test.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Data-tracker_test.Tpo -c -o helpers/LibTorrent_Test_Data-tracker_test.o `test -f 'helpers/tracker_test.cc' || echo '$(srcdir)/'`helpers/tracker_test.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Data-tracker_test.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Data-tracker_test.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/tracker_test.cc' object='helpers/LibTorrent_Test_Data-tracker_test.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Data-tracker_test.o `test -f 'helpers/tracker_test.cc' || echo '$(srcdir)/'`helpers/tracker_test.cc helpers/LibTorrent_Test_Data-tracker_test.obj: helpers/tracker_test.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Data-tracker_test.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Data-tracker_test.Tpo -c -o helpers/LibTorrent_Test_Data-tracker_test.obj `if test -f 'helpers/tracker_test.cc'; then $(CYGPATH_W) 'helpers/tracker_test.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/tracker_test.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Data-tracker_test.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Data-tracker_test.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/tracker_test.cc' object='helpers/LibTorrent_Test_Data-tracker_test.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Data-tracker_test.obj `if test -f 'helpers/tracker_test.cc'; then $(CYGPATH_W) 'helpers/tracker_test.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/tracker_test.cc'; fi` data/LibTorrent_Test_Data-test_chunk_list.o: data/test_chunk_list.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -MT data/LibTorrent_Test_Data-test_chunk_list.o -MD -MP -MF data/$(DEPDIR)/LibTorrent_Test_Data-test_chunk_list.Tpo -c -o data/LibTorrent_Test_Data-test_chunk_list.o `test -f 'data/test_chunk_list.cc' || echo '$(srcdir)/'`data/test_chunk_list.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) data/$(DEPDIR)/LibTorrent_Test_Data-test_chunk_list.Tpo data/$(DEPDIR)/LibTorrent_Test_Data-test_chunk_list.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='data/test_chunk_list.cc' object='data/LibTorrent_Test_Data-test_chunk_list.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -c -o data/LibTorrent_Test_Data-test_chunk_list.o `test -f 'data/test_chunk_list.cc' || echo '$(srcdir)/'`data/test_chunk_list.cc data/LibTorrent_Test_Data-test_chunk_list.obj: data/test_chunk_list.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -MT data/LibTorrent_Test_Data-test_chunk_list.obj -MD -MP -MF data/$(DEPDIR)/LibTorrent_Test_Data-test_chunk_list.Tpo -c -o data/LibTorrent_Test_Data-test_chunk_list.obj `if test -f 'data/test_chunk_list.cc'; then $(CYGPATH_W) 'data/test_chunk_list.cc'; else $(CYGPATH_W) '$(srcdir)/data/test_chunk_list.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) data/$(DEPDIR)/LibTorrent_Test_Data-test_chunk_list.Tpo data/$(DEPDIR)/LibTorrent_Test_Data-test_chunk_list.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='data/test_chunk_list.cc' object='data/LibTorrent_Test_Data-test_chunk_list.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -c -o data/LibTorrent_Test_Data-test_chunk_list.obj `if test -f 'data/test_chunk_list.cc'; then $(CYGPATH_W) 'data/test_chunk_list.cc'; else $(CYGPATH_W) '$(srcdir)/data/test_chunk_list.cc'; fi` data/LibTorrent_Test_Data-test_hash_check_queue.o: data/test_hash_check_queue.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -MT data/LibTorrent_Test_Data-test_hash_check_queue.o -MD -MP -MF data/$(DEPDIR)/LibTorrent_Test_Data-test_hash_check_queue.Tpo -c -o data/LibTorrent_Test_Data-test_hash_check_queue.o `test -f 'data/test_hash_check_queue.cc' || echo '$(srcdir)/'`data/test_hash_check_queue.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) data/$(DEPDIR)/LibTorrent_Test_Data-test_hash_check_queue.Tpo data/$(DEPDIR)/LibTorrent_Test_Data-test_hash_check_queue.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='data/test_hash_check_queue.cc' object='data/LibTorrent_Test_Data-test_hash_check_queue.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -c -o data/LibTorrent_Test_Data-test_hash_check_queue.o `test -f 'data/test_hash_check_queue.cc' || echo '$(srcdir)/'`data/test_hash_check_queue.cc data/LibTorrent_Test_Data-test_hash_check_queue.obj: data/test_hash_check_queue.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -MT data/LibTorrent_Test_Data-test_hash_check_queue.obj -MD -MP -MF data/$(DEPDIR)/LibTorrent_Test_Data-test_hash_check_queue.Tpo -c -o data/LibTorrent_Test_Data-test_hash_check_queue.obj `if test -f 'data/test_hash_check_queue.cc'; then $(CYGPATH_W) 'data/test_hash_check_queue.cc'; else $(CYGPATH_W) '$(srcdir)/data/test_hash_check_queue.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) data/$(DEPDIR)/LibTorrent_Test_Data-test_hash_check_queue.Tpo data/$(DEPDIR)/LibTorrent_Test_Data-test_hash_check_queue.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='data/test_hash_check_queue.cc' object='data/LibTorrent_Test_Data-test_hash_check_queue.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -c -o data/LibTorrent_Test_Data-test_hash_check_queue.obj `if test -f 'data/test_hash_check_queue.cc'; then $(CYGPATH_W) 'data/test_hash_check_queue.cc'; else $(CYGPATH_W) '$(srcdir)/data/test_hash_check_queue.cc'; fi` data/LibTorrent_Test_Data-test_hash_queue.o: data/test_hash_queue.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -MT data/LibTorrent_Test_Data-test_hash_queue.o -MD -MP -MF data/$(DEPDIR)/LibTorrent_Test_Data-test_hash_queue.Tpo -c -o data/LibTorrent_Test_Data-test_hash_queue.o `test -f 'data/test_hash_queue.cc' || echo '$(srcdir)/'`data/test_hash_queue.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) data/$(DEPDIR)/LibTorrent_Test_Data-test_hash_queue.Tpo data/$(DEPDIR)/LibTorrent_Test_Data-test_hash_queue.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='data/test_hash_queue.cc' object='data/LibTorrent_Test_Data-test_hash_queue.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -c -o data/LibTorrent_Test_Data-test_hash_queue.o `test -f 'data/test_hash_queue.cc' || echo '$(srcdir)/'`data/test_hash_queue.cc data/LibTorrent_Test_Data-test_hash_queue.obj: data/test_hash_queue.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -MT data/LibTorrent_Test_Data-test_hash_queue.obj -MD -MP -MF data/$(DEPDIR)/LibTorrent_Test_Data-test_hash_queue.Tpo -c -o data/LibTorrent_Test_Data-test_hash_queue.obj `if test -f 'data/test_hash_queue.cc'; then $(CYGPATH_W) 'data/test_hash_queue.cc'; else $(CYGPATH_W) '$(srcdir)/data/test_hash_queue.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) data/$(DEPDIR)/LibTorrent_Test_Data-test_hash_queue.Tpo data/$(DEPDIR)/LibTorrent_Test_Data-test_hash_queue.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='data/test_hash_queue.cc' object='data/LibTorrent_Test_Data-test_hash_queue.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Data_CXXFLAGS) $(CXXFLAGS) -c -o data/LibTorrent_Test_Data-test_hash_queue.obj `if test -f 'data/test_hash_queue.cc'; then $(CYGPATH_W) 'data/test_hash_queue.cc'; else $(CYGPATH_W) '$(srcdir)/data/test_hash_queue.cc'; fi` LibTorrent_Test_Net-main.o: main.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Net_CXXFLAGS) $(CXXFLAGS) -MT LibTorrent_Test_Net-main.o -MD -MP -MF $(DEPDIR)/LibTorrent_Test_Net-main.Tpo -c -o LibTorrent_Test_Net-main.o `test -f 'main.cc' || echo '$(srcdir)/'`main.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/LibTorrent_Test_Net-main.Tpo $(DEPDIR)/LibTorrent_Test_Net-main.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='main.cc' object='LibTorrent_Test_Net-main.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Net_CXXFLAGS) $(CXXFLAGS) -c -o LibTorrent_Test_Net-main.o `test -f 'main.cc' || echo '$(srcdir)/'`main.cc LibTorrent_Test_Net-main.obj: main.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Net_CXXFLAGS) $(CXXFLAGS) -MT LibTorrent_Test_Net-main.obj -MD -MP -MF $(DEPDIR)/LibTorrent_Test_Net-main.Tpo -c -o LibTorrent_Test_Net-main.obj `if test -f 'main.cc'; then $(CYGPATH_W) 'main.cc'; else $(CYGPATH_W) '$(srcdir)/main.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/LibTorrent_Test_Net-main.Tpo $(DEPDIR)/LibTorrent_Test_Net-main.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='main.cc' object='LibTorrent_Test_Net-main.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Net_CXXFLAGS) $(CXXFLAGS) -c -o LibTorrent_Test_Net-main.obj `if test -f 'main.cc'; then $(CYGPATH_W) 'main.cc'; else $(CYGPATH_W) '$(srcdir)/main.cc'; fi` helpers/LibTorrent_Test_Net-mock_function.o: helpers/mock_function.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Net_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Net-mock_function.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Net-mock_function.Tpo -c -o helpers/LibTorrent_Test_Net-mock_function.o `test -f 'helpers/mock_function.cc' || echo '$(srcdir)/'`helpers/mock_function.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Net-mock_function.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Net-mock_function.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/mock_function.cc' object='helpers/LibTorrent_Test_Net-mock_function.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Net_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Net-mock_function.o `test -f 'helpers/mock_function.cc' || echo '$(srcdir)/'`helpers/mock_function.cc helpers/LibTorrent_Test_Net-mock_function.obj: helpers/mock_function.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Net_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Net-mock_function.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Net-mock_function.Tpo -c -o helpers/LibTorrent_Test_Net-mock_function.obj `if test -f 'helpers/mock_function.cc'; then $(CYGPATH_W) 'helpers/mock_function.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/mock_function.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Net-mock_function.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Net-mock_function.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/mock_function.cc' object='helpers/LibTorrent_Test_Net-mock_function.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Net_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Net-mock_function.obj `if test -f 'helpers/mock_function.cc'; then $(CYGPATH_W) 'helpers/mock_function.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/mock_function.cc'; fi` helpers/LibTorrent_Test_Net-network.o: helpers/network.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Net_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Net-network.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Net-network.Tpo -c -o helpers/LibTorrent_Test_Net-network.o `test -f 'helpers/network.cc' || echo '$(srcdir)/'`helpers/network.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Net-network.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Net-network.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/network.cc' object='helpers/LibTorrent_Test_Net-network.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Net_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Net-network.o `test -f 'helpers/network.cc' || echo '$(srcdir)/'`helpers/network.cc helpers/LibTorrent_Test_Net-network.obj: helpers/network.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Net_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Net-network.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Net-network.Tpo -c -o helpers/LibTorrent_Test_Net-network.obj `if test -f 'helpers/network.cc'; then $(CYGPATH_W) 'helpers/network.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/network.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Net-network.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Net-network.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/network.cc' object='helpers/LibTorrent_Test_Net-network.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Net_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Net-network.obj `if test -f 'helpers/network.cc'; then $(CYGPATH_W) 'helpers/network.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/network.cc'; fi` helpers/LibTorrent_Test_Net-progress_listener.o: helpers/progress_listener.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Net_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Net-progress_listener.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Net-progress_listener.Tpo -c -o helpers/LibTorrent_Test_Net-progress_listener.o `test -f 'helpers/progress_listener.cc' || echo '$(srcdir)/'`helpers/progress_listener.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Net-progress_listener.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Net-progress_listener.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/progress_listener.cc' object='helpers/LibTorrent_Test_Net-progress_listener.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Net_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Net-progress_listener.o `test -f 'helpers/progress_listener.cc' || echo '$(srcdir)/'`helpers/progress_listener.cc helpers/LibTorrent_Test_Net-progress_listener.obj: helpers/progress_listener.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Net_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Net-progress_listener.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Net-progress_listener.Tpo -c -o helpers/LibTorrent_Test_Net-progress_listener.obj `if test -f 'helpers/progress_listener.cc'; then $(CYGPATH_W) 'helpers/progress_listener.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/progress_listener.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Net-progress_listener.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Net-progress_listener.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/progress_listener.cc' object='helpers/LibTorrent_Test_Net-progress_listener.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Net_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Net-progress_listener.obj `if test -f 'helpers/progress_listener.cc'; then $(CYGPATH_W) 'helpers/progress_listener.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/progress_listener.cc'; fi` helpers/LibTorrent_Test_Net-protectors.o: helpers/protectors.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Net_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Net-protectors.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Net-protectors.Tpo -c -o helpers/LibTorrent_Test_Net-protectors.o `test -f 'helpers/protectors.cc' || echo '$(srcdir)/'`helpers/protectors.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Net-protectors.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Net-protectors.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/protectors.cc' object='helpers/LibTorrent_Test_Net-protectors.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Net_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Net-protectors.o `test -f 'helpers/protectors.cc' || echo '$(srcdir)/'`helpers/protectors.cc helpers/LibTorrent_Test_Net-protectors.obj: helpers/protectors.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Net_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Net-protectors.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Net-protectors.Tpo -c -o helpers/LibTorrent_Test_Net-protectors.obj `if test -f 'helpers/protectors.cc'; then $(CYGPATH_W) 'helpers/protectors.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/protectors.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Net-protectors.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Net-protectors.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/protectors.cc' object='helpers/LibTorrent_Test_Net-protectors.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Net_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Net-protectors.obj `if test -f 'helpers/protectors.cc'; then $(CYGPATH_W) 'helpers/protectors.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/protectors.cc'; fi` helpers/LibTorrent_Test_Net-test_fixture.o: helpers/test_fixture.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Net_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Net-test_fixture.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Net-test_fixture.Tpo -c -o helpers/LibTorrent_Test_Net-test_fixture.o `test -f 'helpers/test_fixture.cc' || echo '$(srcdir)/'`helpers/test_fixture.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Net-test_fixture.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Net-test_fixture.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/test_fixture.cc' object='helpers/LibTorrent_Test_Net-test_fixture.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Net_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Net-test_fixture.o `test -f 'helpers/test_fixture.cc' || echo '$(srcdir)/'`helpers/test_fixture.cc helpers/LibTorrent_Test_Net-test_fixture.obj: helpers/test_fixture.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Net_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Net-test_fixture.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Net-test_fixture.Tpo -c -o helpers/LibTorrent_Test_Net-test_fixture.obj `if test -f 'helpers/test_fixture.cc'; then $(CYGPATH_W) 'helpers/test_fixture.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/test_fixture.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Net-test_fixture.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Net-test_fixture.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/test_fixture.cc' object='helpers/LibTorrent_Test_Net-test_fixture.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Net_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Net-test_fixture.obj `if test -f 'helpers/test_fixture.cc'; then $(CYGPATH_W) 'helpers/test_fixture.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/test_fixture.cc'; fi` helpers/LibTorrent_Test_Net-test_main_thread.o: helpers/test_main_thread.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Net_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Net-test_main_thread.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Net-test_main_thread.Tpo -c -o helpers/LibTorrent_Test_Net-test_main_thread.o `test -f 'helpers/test_main_thread.cc' || echo '$(srcdir)/'`helpers/test_main_thread.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Net-test_main_thread.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Net-test_main_thread.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/test_main_thread.cc' object='helpers/LibTorrent_Test_Net-test_main_thread.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Net_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Net-test_main_thread.o `test -f 'helpers/test_main_thread.cc' || echo '$(srcdir)/'`helpers/test_main_thread.cc helpers/LibTorrent_Test_Net-test_main_thread.obj: helpers/test_main_thread.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Net_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Net-test_main_thread.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Net-test_main_thread.Tpo -c -o helpers/LibTorrent_Test_Net-test_main_thread.obj `if test -f 'helpers/test_main_thread.cc'; then $(CYGPATH_W) 'helpers/test_main_thread.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/test_main_thread.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Net-test_main_thread.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Net-test_main_thread.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/test_main_thread.cc' object='helpers/LibTorrent_Test_Net-test_main_thread.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Net_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Net-test_main_thread.obj `if test -f 'helpers/test_main_thread.cc'; then $(CYGPATH_W) 'helpers/test_main_thread.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/test_main_thread.cc'; fi` helpers/LibTorrent_Test_Net-test_thread.o: helpers/test_thread.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Net_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Net-test_thread.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Net-test_thread.Tpo -c -o helpers/LibTorrent_Test_Net-test_thread.o `test -f 'helpers/test_thread.cc' || echo '$(srcdir)/'`helpers/test_thread.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Net-test_thread.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Net-test_thread.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/test_thread.cc' object='helpers/LibTorrent_Test_Net-test_thread.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Net_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Net-test_thread.o `test -f 'helpers/test_thread.cc' || echo '$(srcdir)/'`helpers/test_thread.cc helpers/LibTorrent_Test_Net-test_thread.obj: helpers/test_thread.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Net_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Net-test_thread.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Net-test_thread.Tpo -c -o helpers/LibTorrent_Test_Net-test_thread.obj `if test -f 'helpers/test_thread.cc'; then $(CYGPATH_W) 'helpers/test_thread.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/test_thread.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Net-test_thread.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Net-test_thread.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/test_thread.cc' object='helpers/LibTorrent_Test_Net-test_thread.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Net_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Net-test_thread.obj `if test -f 'helpers/test_thread.cc'; then $(CYGPATH_W) 'helpers/test_thread.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/test_thread.cc'; fi` helpers/LibTorrent_Test_Net-tracker_test.o: helpers/tracker_test.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Net_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Net-tracker_test.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Net-tracker_test.Tpo -c -o helpers/LibTorrent_Test_Net-tracker_test.o `test -f 'helpers/tracker_test.cc' || echo '$(srcdir)/'`helpers/tracker_test.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Net-tracker_test.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Net-tracker_test.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/tracker_test.cc' object='helpers/LibTorrent_Test_Net-tracker_test.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Net_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Net-tracker_test.o `test -f 'helpers/tracker_test.cc' || echo '$(srcdir)/'`helpers/tracker_test.cc helpers/LibTorrent_Test_Net-tracker_test.obj: helpers/tracker_test.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Net_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Net-tracker_test.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Net-tracker_test.Tpo -c -o helpers/LibTorrent_Test_Net-tracker_test.obj `if test -f 'helpers/tracker_test.cc'; then $(CYGPATH_W) 'helpers/tracker_test.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/tracker_test.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Net-tracker_test.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Net-tracker_test.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/tracker_test.cc' object='helpers/LibTorrent_Test_Net-tracker_test.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Net_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Net-tracker_test.obj `if test -f 'helpers/tracker_test.cc'; then $(CYGPATH_W) 'helpers/tracker_test.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/tracker_test.cc'; fi` LibTorrent_Test_Torrent-main.o: main.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -MT LibTorrent_Test_Torrent-main.o -MD -MP -MF $(DEPDIR)/LibTorrent_Test_Torrent-main.Tpo -c -o LibTorrent_Test_Torrent-main.o `test -f 'main.cc' || echo '$(srcdir)/'`main.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/LibTorrent_Test_Torrent-main.Tpo $(DEPDIR)/LibTorrent_Test_Torrent-main.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='main.cc' object='LibTorrent_Test_Torrent-main.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -c -o LibTorrent_Test_Torrent-main.o `test -f 'main.cc' || echo '$(srcdir)/'`main.cc LibTorrent_Test_Torrent-main.obj: main.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -MT LibTorrent_Test_Torrent-main.obj -MD -MP -MF $(DEPDIR)/LibTorrent_Test_Torrent-main.Tpo -c -o LibTorrent_Test_Torrent-main.obj `if test -f 'main.cc'; then $(CYGPATH_W) 'main.cc'; else $(CYGPATH_W) '$(srcdir)/main.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/LibTorrent_Test_Torrent-main.Tpo $(DEPDIR)/LibTorrent_Test_Torrent-main.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='main.cc' object='LibTorrent_Test_Torrent-main.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -c -o LibTorrent_Test_Torrent-main.obj `if test -f 'main.cc'; then $(CYGPATH_W) 'main.cc'; else $(CYGPATH_W) '$(srcdir)/main.cc'; fi` helpers/LibTorrent_Test_Torrent-mock_function.o: helpers/mock_function.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent-mock_function.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent-mock_function.Tpo -c -o helpers/LibTorrent_Test_Torrent-mock_function.o `test -f 'helpers/mock_function.cc' || echo '$(srcdir)/'`helpers/mock_function.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent-mock_function.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent-mock_function.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/mock_function.cc' object='helpers/LibTorrent_Test_Torrent-mock_function.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent-mock_function.o `test -f 'helpers/mock_function.cc' || echo '$(srcdir)/'`helpers/mock_function.cc helpers/LibTorrent_Test_Torrent-mock_function.obj: helpers/mock_function.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent-mock_function.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent-mock_function.Tpo -c -o helpers/LibTorrent_Test_Torrent-mock_function.obj `if test -f 'helpers/mock_function.cc'; then $(CYGPATH_W) 'helpers/mock_function.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/mock_function.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent-mock_function.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent-mock_function.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/mock_function.cc' object='helpers/LibTorrent_Test_Torrent-mock_function.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent-mock_function.obj `if test -f 'helpers/mock_function.cc'; then $(CYGPATH_W) 'helpers/mock_function.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/mock_function.cc'; fi` helpers/LibTorrent_Test_Torrent-network.o: helpers/network.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent-network.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent-network.Tpo -c -o helpers/LibTorrent_Test_Torrent-network.o `test -f 'helpers/network.cc' || echo '$(srcdir)/'`helpers/network.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent-network.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent-network.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/network.cc' object='helpers/LibTorrent_Test_Torrent-network.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent-network.o `test -f 'helpers/network.cc' || echo '$(srcdir)/'`helpers/network.cc helpers/LibTorrent_Test_Torrent-network.obj: helpers/network.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent-network.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent-network.Tpo -c -o helpers/LibTorrent_Test_Torrent-network.obj `if test -f 'helpers/network.cc'; then $(CYGPATH_W) 'helpers/network.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/network.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent-network.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent-network.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/network.cc' object='helpers/LibTorrent_Test_Torrent-network.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent-network.obj `if test -f 'helpers/network.cc'; then $(CYGPATH_W) 'helpers/network.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/network.cc'; fi` helpers/LibTorrent_Test_Torrent-progress_listener.o: helpers/progress_listener.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent-progress_listener.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent-progress_listener.Tpo -c -o helpers/LibTorrent_Test_Torrent-progress_listener.o `test -f 'helpers/progress_listener.cc' || echo '$(srcdir)/'`helpers/progress_listener.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent-progress_listener.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent-progress_listener.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/progress_listener.cc' object='helpers/LibTorrent_Test_Torrent-progress_listener.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent-progress_listener.o `test -f 'helpers/progress_listener.cc' || echo '$(srcdir)/'`helpers/progress_listener.cc helpers/LibTorrent_Test_Torrent-progress_listener.obj: helpers/progress_listener.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent-progress_listener.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent-progress_listener.Tpo -c -o helpers/LibTorrent_Test_Torrent-progress_listener.obj `if test -f 'helpers/progress_listener.cc'; then $(CYGPATH_W) 'helpers/progress_listener.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/progress_listener.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent-progress_listener.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent-progress_listener.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/progress_listener.cc' object='helpers/LibTorrent_Test_Torrent-progress_listener.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent-progress_listener.obj `if test -f 'helpers/progress_listener.cc'; then $(CYGPATH_W) 'helpers/progress_listener.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/progress_listener.cc'; fi` helpers/LibTorrent_Test_Torrent-protectors.o: helpers/protectors.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent-protectors.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent-protectors.Tpo -c -o helpers/LibTorrent_Test_Torrent-protectors.o `test -f 'helpers/protectors.cc' || echo '$(srcdir)/'`helpers/protectors.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent-protectors.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent-protectors.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/protectors.cc' object='helpers/LibTorrent_Test_Torrent-protectors.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent-protectors.o `test -f 'helpers/protectors.cc' || echo '$(srcdir)/'`helpers/protectors.cc helpers/LibTorrent_Test_Torrent-protectors.obj: helpers/protectors.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent-protectors.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent-protectors.Tpo -c -o helpers/LibTorrent_Test_Torrent-protectors.obj `if test -f 'helpers/protectors.cc'; then $(CYGPATH_W) 'helpers/protectors.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/protectors.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent-protectors.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent-protectors.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/protectors.cc' object='helpers/LibTorrent_Test_Torrent-protectors.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent-protectors.obj `if test -f 'helpers/protectors.cc'; then $(CYGPATH_W) 'helpers/protectors.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/protectors.cc'; fi` helpers/LibTorrent_Test_Torrent-test_fixture.o: helpers/test_fixture.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent-test_fixture.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent-test_fixture.Tpo -c -o helpers/LibTorrent_Test_Torrent-test_fixture.o `test -f 'helpers/test_fixture.cc' || echo '$(srcdir)/'`helpers/test_fixture.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent-test_fixture.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent-test_fixture.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/test_fixture.cc' object='helpers/LibTorrent_Test_Torrent-test_fixture.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent-test_fixture.o `test -f 'helpers/test_fixture.cc' || echo '$(srcdir)/'`helpers/test_fixture.cc helpers/LibTorrent_Test_Torrent-test_fixture.obj: helpers/test_fixture.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent-test_fixture.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent-test_fixture.Tpo -c -o helpers/LibTorrent_Test_Torrent-test_fixture.obj `if test -f 'helpers/test_fixture.cc'; then $(CYGPATH_W) 'helpers/test_fixture.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/test_fixture.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent-test_fixture.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent-test_fixture.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/test_fixture.cc' object='helpers/LibTorrent_Test_Torrent-test_fixture.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent-test_fixture.obj `if test -f 'helpers/test_fixture.cc'; then $(CYGPATH_W) 'helpers/test_fixture.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/test_fixture.cc'; fi` helpers/LibTorrent_Test_Torrent-test_main_thread.o: helpers/test_main_thread.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent-test_main_thread.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent-test_main_thread.Tpo -c -o helpers/LibTorrent_Test_Torrent-test_main_thread.o `test -f 'helpers/test_main_thread.cc' || echo '$(srcdir)/'`helpers/test_main_thread.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent-test_main_thread.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent-test_main_thread.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/test_main_thread.cc' object='helpers/LibTorrent_Test_Torrent-test_main_thread.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent-test_main_thread.o `test -f 'helpers/test_main_thread.cc' || echo '$(srcdir)/'`helpers/test_main_thread.cc helpers/LibTorrent_Test_Torrent-test_main_thread.obj: helpers/test_main_thread.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent-test_main_thread.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent-test_main_thread.Tpo -c -o helpers/LibTorrent_Test_Torrent-test_main_thread.obj `if test -f 'helpers/test_main_thread.cc'; then $(CYGPATH_W) 'helpers/test_main_thread.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/test_main_thread.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent-test_main_thread.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent-test_main_thread.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/test_main_thread.cc' object='helpers/LibTorrent_Test_Torrent-test_main_thread.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent-test_main_thread.obj `if test -f 'helpers/test_main_thread.cc'; then $(CYGPATH_W) 'helpers/test_main_thread.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/test_main_thread.cc'; fi` helpers/LibTorrent_Test_Torrent-test_thread.o: helpers/test_thread.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent-test_thread.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent-test_thread.Tpo -c -o helpers/LibTorrent_Test_Torrent-test_thread.o `test -f 'helpers/test_thread.cc' || echo '$(srcdir)/'`helpers/test_thread.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent-test_thread.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent-test_thread.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/test_thread.cc' object='helpers/LibTorrent_Test_Torrent-test_thread.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent-test_thread.o `test -f 'helpers/test_thread.cc' || echo '$(srcdir)/'`helpers/test_thread.cc helpers/LibTorrent_Test_Torrent-test_thread.obj: helpers/test_thread.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent-test_thread.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent-test_thread.Tpo -c -o helpers/LibTorrent_Test_Torrent-test_thread.obj `if test -f 'helpers/test_thread.cc'; then $(CYGPATH_W) 'helpers/test_thread.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/test_thread.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent-test_thread.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent-test_thread.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/test_thread.cc' object='helpers/LibTorrent_Test_Torrent-test_thread.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent-test_thread.obj `if test -f 'helpers/test_thread.cc'; then $(CYGPATH_W) 'helpers/test_thread.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/test_thread.cc'; fi` helpers/LibTorrent_Test_Torrent-tracker_test.o: helpers/tracker_test.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent-tracker_test.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent-tracker_test.Tpo -c -o helpers/LibTorrent_Test_Torrent-tracker_test.o `test -f 'helpers/tracker_test.cc' || echo '$(srcdir)/'`helpers/tracker_test.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent-tracker_test.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent-tracker_test.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/tracker_test.cc' object='helpers/LibTorrent_Test_Torrent-tracker_test.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent-tracker_test.o `test -f 'helpers/tracker_test.cc' || echo '$(srcdir)/'`helpers/tracker_test.cc helpers/LibTorrent_Test_Torrent-tracker_test.obj: helpers/tracker_test.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent-tracker_test.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent-tracker_test.Tpo -c -o helpers/LibTorrent_Test_Torrent-tracker_test.obj `if test -f 'helpers/tracker_test.cc'; then $(CYGPATH_W) 'helpers/tracker_test.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/tracker_test.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent-tracker_test.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent-tracker_test.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/tracker_test.cc' object='helpers/LibTorrent_Test_Torrent-tracker_test.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent-tracker_test.obj `if test -f 'helpers/tracker_test.cc'; then $(CYGPATH_W) 'helpers/tracker_test.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/tracker_test.cc'; fi` torrent/LibTorrent_Test_Torrent-object_test.o: torrent/object_test.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -MT torrent/LibTorrent_Test_Torrent-object_test.o -MD -MP -MF torrent/$(DEPDIR)/LibTorrent_Test_Torrent-object_test.Tpo -c -o torrent/LibTorrent_Test_Torrent-object_test.o `test -f 'torrent/object_test.cc' || echo '$(srcdir)/'`torrent/object_test.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/$(DEPDIR)/LibTorrent_Test_Torrent-object_test.Tpo torrent/$(DEPDIR)/LibTorrent_Test_Torrent-object_test.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/object_test.cc' object='torrent/LibTorrent_Test_Torrent-object_test.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -c -o torrent/LibTorrent_Test_Torrent-object_test.o `test -f 'torrent/object_test.cc' || echo '$(srcdir)/'`torrent/object_test.cc torrent/LibTorrent_Test_Torrent-object_test.obj: torrent/object_test.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -MT torrent/LibTorrent_Test_Torrent-object_test.obj -MD -MP -MF torrent/$(DEPDIR)/LibTorrent_Test_Torrent-object_test.Tpo -c -o torrent/LibTorrent_Test_Torrent-object_test.obj `if test -f 'torrent/object_test.cc'; then $(CYGPATH_W) 'torrent/object_test.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/object_test.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/$(DEPDIR)/LibTorrent_Test_Torrent-object_test.Tpo torrent/$(DEPDIR)/LibTorrent_Test_Torrent-object_test.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/object_test.cc' object='torrent/LibTorrent_Test_Torrent-object_test.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -c -o torrent/LibTorrent_Test_Torrent-object_test.obj `if test -f 'torrent/object_test.cc'; then $(CYGPATH_W) 'torrent/object_test.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/object_test.cc'; fi` torrent/LibTorrent_Test_Torrent-object_test_utils.o: torrent/object_test_utils.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -MT torrent/LibTorrent_Test_Torrent-object_test_utils.o -MD -MP -MF torrent/$(DEPDIR)/LibTorrent_Test_Torrent-object_test_utils.Tpo -c -o torrent/LibTorrent_Test_Torrent-object_test_utils.o `test -f 'torrent/object_test_utils.cc' || echo '$(srcdir)/'`torrent/object_test_utils.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/$(DEPDIR)/LibTorrent_Test_Torrent-object_test_utils.Tpo torrent/$(DEPDIR)/LibTorrent_Test_Torrent-object_test_utils.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/object_test_utils.cc' object='torrent/LibTorrent_Test_Torrent-object_test_utils.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -c -o torrent/LibTorrent_Test_Torrent-object_test_utils.o `test -f 'torrent/object_test_utils.cc' || echo '$(srcdir)/'`torrent/object_test_utils.cc torrent/LibTorrent_Test_Torrent-object_test_utils.obj: torrent/object_test_utils.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -MT torrent/LibTorrent_Test_Torrent-object_test_utils.obj -MD -MP -MF torrent/$(DEPDIR)/LibTorrent_Test_Torrent-object_test_utils.Tpo -c -o torrent/LibTorrent_Test_Torrent-object_test_utils.obj `if test -f 'torrent/object_test_utils.cc'; then $(CYGPATH_W) 'torrent/object_test_utils.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/object_test_utils.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/$(DEPDIR)/LibTorrent_Test_Torrent-object_test_utils.Tpo torrent/$(DEPDIR)/LibTorrent_Test_Torrent-object_test_utils.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/object_test_utils.cc' object='torrent/LibTorrent_Test_Torrent-object_test_utils.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -c -o torrent/LibTorrent_Test_Torrent-object_test_utils.obj `if test -f 'torrent/object_test_utils.cc'; then $(CYGPATH_W) 'torrent/object_test_utils.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/object_test_utils.cc'; fi` torrent/LibTorrent_Test_Torrent-object_static_map_test.o: torrent/object_static_map_test.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -MT torrent/LibTorrent_Test_Torrent-object_static_map_test.o -MD -MP -MF torrent/$(DEPDIR)/LibTorrent_Test_Torrent-object_static_map_test.Tpo -c -o torrent/LibTorrent_Test_Torrent-object_static_map_test.o `test -f 'torrent/object_static_map_test.cc' || echo '$(srcdir)/'`torrent/object_static_map_test.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/$(DEPDIR)/LibTorrent_Test_Torrent-object_static_map_test.Tpo torrent/$(DEPDIR)/LibTorrent_Test_Torrent-object_static_map_test.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/object_static_map_test.cc' object='torrent/LibTorrent_Test_Torrent-object_static_map_test.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -c -o torrent/LibTorrent_Test_Torrent-object_static_map_test.o `test -f 'torrent/object_static_map_test.cc' || echo '$(srcdir)/'`torrent/object_static_map_test.cc torrent/LibTorrent_Test_Torrent-object_static_map_test.obj: torrent/object_static_map_test.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -MT torrent/LibTorrent_Test_Torrent-object_static_map_test.obj -MD -MP -MF torrent/$(DEPDIR)/LibTorrent_Test_Torrent-object_static_map_test.Tpo -c -o torrent/LibTorrent_Test_Torrent-object_static_map_test.obj `if test -f 'torrent/object_static_map_test.cc'; then $(CYGPATH_W) 'torrent/object_static_map_test.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/object_static_map_test.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/$(DEPDIR)/LibTorrent_Test_Torrent-object_static_map_test.Tpo torrent/$(DEPDIR)/LibTorrent_Test_Torrent-object_static_map_test.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/object_static_map_test.cc' object='torrent/LibTorrent_Test_Torrent-object_static_map_test.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -c -o torrent/LibTorrent_Test_Torrent-object_static_map_test.obj `if test -f 'torrent/object_static_map_test.cc'; then $(CYGPATH_W) 'torrent/object_static_map_test.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/object_static_map_test.cc'; fi` torrent/LibTorrent_Test_Torrent-object_stream_test.o: torrent/object_stream_test.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -MT torrent/LibTorrent_Test_Torrent-object_stream_test.o -MD -MP -MF torrent/$(DEPDIR)/LibTorrent_Test_Torrent-object_stream_test.Tpo -c -o torrent/LibTorrent_Test_Torrent-object_stream_test.o `test -f 'torrent/object_stream_test.cc' || echo '$(srcdir)/'`torrent/object_stream_test.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/$(DEPDIR)/LibTorrent_Test_Torrent-object_stream_test.Tpo torrent/$(DEPDIR)/LibTorrent_Test_Torrent-object_stream_test.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/object_stream_test.cc' object='torrent/LibTorrent_Test_Torrent-object_stream_test.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -c -o torrent/LibTorrent_Test_Torrent-object_stream_test.o `test -f 'torrent/object_stream_test.cc' || echo '$(srcdir)/'`torrent/object_stream_test.cc torrent/LibTorrent_Test_Torrent-object_stream_test.obj: torrent/object_stream_test.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -MT torrent/LibTorrent_Test_Torrent-object_stream_test.obj -MD -MP -MF torrent/$(DEPDIR)/LibTorrent_Test_Torrent-object_stream_test.Tpo -c -o torrent/LibTorrent_Test_Torrent-object_stream_test.obj `if test -f 'torrent/object_stream_test.cc'; then $(CYGPATH_W) 'torrent/object_stream_test.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/object_stream_test.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/$(DEPDIR)/LibTorrent_Test_Torrent-object_stream_test.Tpo torrent/$(DEPDIR)/LibTorrent_Test_Torrent-object_stream_test.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/object_stream_test.cc' object='torrent/LibTorrent_Test_Torrent-object_stream_test.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -c -o torrent/LibTorrent_Test_Torrent-object_stream_test.obj `if test -f 'torrent/object_stream_test.cc'; then $(CYGPATH_W) 'torrent/object_stream_test.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/object_stream_test.cc'; fi` torrent/LibTorrent_Test_Torrent-test_tracker_controller.o: torrent/test_tracker_controller.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -MT torrent/LibTorrent_Test_Torrent-test_tracker_controller.o -MD -MP -MF torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_controller.Tpo -c -o torrent/LibTorrent_Test_Torrent-test_tracker_controller.o `test -f 'torrent/test_tracker_controller.cc' || echo '$(srcdir)/'`torrent/test_tracker_controller.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_controller.Tpo torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_controller.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/test_tracker_controller.cc' object='torrent/LibTorrent_Test_Torrent-test_tracker_controller.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -c -o torrent/LibTorrent_Test_Torrent-test_tracker_controller.o `test -f 'torrent/test_tracker_controller.cc' || echo '$(srcdir)/'`torrent/test_tracker_controller.cc torrent/LibTorrent_Test_Torrent-test_tracker_controller.obj: torrent/test_tracker_controller.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -MT torrent/LibTorrent_Test_Torrent-test_tracker_controller.obj -MD -MP -MF torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_controller.Tpo -c -o torrent/LibTorrent_Test_Torrent-test_tracker_controller.obj `if test -f 'torrent/test_tracker_controller.cc'; then $(CYGPATH_W) 'torrent/test_tracker_controller.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/test_tracker_controller.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_controller.Tpo torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_controller.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/test_tracker_controller.cc' object='torrent/LibTorrent_Test_Torrent-test_tracker_controller.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -c -o torrent/LibTorrent_Test_Torrent-test_tracker_controller.obj `if test -f 'torrent/test_tracker_controller.cc'; then $(CYGPATH_W) 'torrent/test_tracker_controller.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/test_tracker_controller.cc'; fi` torrent/LibTorrent_Test_Torrent-test_tracker_controller_features.o: torrent/test_tracker_controller_features.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -MT torrent/LibTorrent_Test_Torrent-test_tracker_controller_features.o -MD -MP -MF torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_controller_features.Tpo -c -o torrent/LibTorrent_Test_Torrent-test_tracker_controller_features.o `test -f 'torrent/test_tracker_controller_features.cc' || echo '$(srcdir)/'`torrent/test_tracker_controller_features.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_controller_features.Tpo torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_controller_features.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/test_tracker_controller_features.cc' object='torrent/LibTorrent_Test_Torrent-test_tracker_controller_features.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -c -o torrent/LibTorrent_Test_Torrent-test_tracker_controller_features.o `test -f 'torrent/test_tracker_controller_features.cc' || echo '$(srcdir)/'`torrent/test_tracker_controller_features.cc torrent/LibTorrent_Test_Torrent-test_tracker_controller_features.obj: torrent/test_tracker_controller_features.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -MT torrent/LibTorrent_Test_Torrent-test_tracker_controller_features.obj -MD -MP -MF torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_controller_features.Tpo -c -o torrent/LibTorrent_Test_Torrent-test_tracker_controller_features.obj `if test -f 'torrent/test_tracker_controller_features.cc'; then $(CYGPATH_W) 'torrent/test_tracker_controller_features.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/test_tracker_controller_features.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_controller_features.Tpo torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_controller_features.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/test_tracker_controller_features.cc' object='torrent/LibTorrent_Test_Torrent-test_tracker_controller_features.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -c -o torrent/LibTorrent_Test_Torrent-test_tracker_controller_features.obj `if test -f 'torrent/test_tracker_controller_features.cc'; then $(CYGPATH_W) 'torrent/test_tracker_controller_features.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/test_tracker_controller_features.cc'; fi` torrent/LibTorrent_Test_Torrent-test_tracker_controller_requesting.o: torrent/test_tracker_controller_requesting.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -MT torrent/LibTorrent_Test_Torrent-test_tracker_controller_requesting.o -MD -MP -MF torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_controller_requesting.Tpo -c -o torrent/LibTorrent_Test_Torrent-test_tracker_controller_requesting.o `test -f 'torrent/test_tracker_controller_requesting.cc' || echo '$(srcdir)/'`torrent/test_tracker_controller_requesting.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_controller_requesting.Tpo torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_controller_requesting.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/test_tracker_controller_requesting.cc' object='torrent/LibTorrent_Test_Torrent-test_tracker_controller_requesting.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -c -o torrent/LibTorrent_Test_Torrent-test_tracker_controller_requesting.o `test -f 'torrent/test_tracker_controller_requesting.cc' || echo '$(srcdir)/'`torrent/test_tracker_controller_requesting.cc torrent/LibTorrent_Test_Torrent-test_tracker_controller_requesting.obj: torrent/test_tracker_controller_requesting.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -MT torrent/LibTorrent_Test_Torrent-test_tracker_controller_requesting.obj -MD -MP -MF torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_controller_requesting.Tpo -c -o torrent/LibTorrent_Test_Torrent-test_tracker_controller_requesting.obj `if test -f 'torrent/test_tracker_controller_requesting.cc'; then $(CYGPATH_W) 'torrent/test_tracker_controller_requesting.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/test_tracker_controller_requesting.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_controller_requesting.Tpo torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_controller_requesting.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/test_tracker_controller_requesting.cc' object='torrent/LibTorrent_Test_Torrent-test_tracker_controller_requesting.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -c -o torrent/LibTorrent_Test_Torrent-test_tracker_controller_requesting.obj `if test -f 'torrent/test_tracker_controller_requesting.cc'; then $(CYGPATH_W) 'torrent/test_tracker_controller_requesting.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/test_tracker_controller_requesting.cc'; fi` torrent/LibTorrent_Test_Torrent-test_tracker_list.o: torrent/test_tracker_list.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -MT torrent/LibTorrent_Test_Torrent-test_tracker_list.o -MD -MP -MF torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_list.Tpo -c -o torrent/LibTorrent_Test_Torrent-test_tracker_list.o `test -f 'torrent/test_tracker_list.cc' || echo '$(srcdir)/'`torrent/test_tracker_list.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_list.Tpo torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_list.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/test_tracker_list.cc' object='torrent/LibTorrent_Test_Torrent-test_tracker_list.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -c -o torrent/LibTorrent_Test_Torrent-test_tracker_list.o `test -f 'torrent/test_tracker_list.cc' || echo '$(srcdir)/'`torrent/test_tracker_list.cc torrent/LibTorrent_Test_Torrent-test_tracker_list.obj: torrent/test_tracker_list.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -MT torrent/LibTorrent_Test_Torrent-test_tracker_list.obj -MD -MP -MF torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_list.Tpo -c -o torrent/LibTorrent_Test_Torrent-test_tracker_list.obj `if test -f 'torrent/test_tracker_list.cc'; then $(CYGPATH_W) 'torrent/test_tracker_list.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/test_tracker_list.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_list.Tpo torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_list.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/test_tracker_list.cc' object='torrent/LibTorrent_Test_Torrent-test_tracker_list.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -c -o torrent/LibTorrent_Test_Torrent-test_tracker_list.obj `if test -f 'torrent/test_tracker_list.cc'; then $(CYGPATH_W) 'torrent/test_tracker_list.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/test_tracker_list.cc'; fi` torrent/LibTorrent_Test_Torrent-test_tracker_list_features.o: torrent/test_tracker_list_features.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -MT torrent/LibTorrent_Test_Torrent-test_tracker_list_features.o -MD -MP -MF torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_list_features.Tpo -c -o torrent/LibTorrent_Test_Torrent-test_tracker_list_features.o `test -f 'torrent/test_tracker_list_features.cc' || echo '$(srcdir)/'`torrent/test_tracker_list_features.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_list_features.Tpo torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_list_features.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/test_tracker_list_features.cc' object='torrent/LibTorrent_Test_Torrent-test_tracker_list_features.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -c -o torrent/LibTorrent_Test_Torrent-test_tracker_list_features.o `test -f 'torrent/test_tracker_list_features.cc' || echo '$(srcdir)/'`torrent/test_tracker_list_features.cc torrent/LibTorrent_Test_Torrent-test_tracker_list_features.obj: torrent/test_tracker_list_features.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -MT torrent/LibTorrent_Test_Torrent-test_tracker_list_features.obj -MD -MP -MF torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_list_features.Tpo -c -o torrent/LibTorrent_Test_Torrent-test_tracker_list_features.obj `if test -f 'torrent/test_tracker_list_features.cc'; then $(CYGPATH_W) 'torrent/test_tracker_list_features.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/test_tracker_list_features.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_list_features.Tpo torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_list_features.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/test_tracker_list_features.cc' object='torrent/LibTorrent_Test_Torrent-test_tracker_list_features.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -c -o torrent/LibTorrent_Test_Torrent-test_tracker_list_features.obj `if test -f 'torrent/test_tracker_list_features.cc'; then $(CYGPATH_W) 'torrent/test_tracker_list_features.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/test_tracker_list_features.cc'; fi` torrent/LibTorrent_Test_Torrent-test_tracker_timeout.o: torrent/test_tracker_timeout.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -MT torrent/LibTorrent_Test_Torrent-test_tracker_timeout.o -MD -MP -MF torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_timeout.Tpo -c -o torrent/LibTorrent_Test_Torrent-test_tracker_timeout.o `test -f 'torrent/test_tracker_timeout.cc' || echo '$(srcdir)/'`torrent/test_tracker_timeout.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_timeout.Tpo torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_timeout.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/test_tracker_timeout.cc' object='torrent/LibTorrent_Test_Torrent-test_tracker_timeout.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -c -o torrent/LibTorrent_Test_Torrent-test_tracker_timeout.o `test -f 'torrent/test_tracker_timeout.cc' || echo '$(srcdir)/'`torrent/test_tracker_timeout.cc torrent/LibTorrent_Test_Torrent-test_tracker_timeout.obj: torrent/test_tracker_timeout.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -MT torrent/LibTorrent_Test_Torrent-test_tracker_timeout.obj -MD -MP -MF torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_timeout.Tpo -c -o torrent/LibTorrent_Test_Torrent-test_tracker_timeout.obj `if test -f 'torrent/test_tracker_timeout.cc'; then $(CYGPATH_W) 'torrent/test_tracker_timeout.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/test_tracker_timeout.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_timeout.Tpo torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_timeout.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/test_tracker_timeout.cc' object='torrent/LibTorrent_Test_Torrent-test_tracker_timeout.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_CXXFLAGS) $(CXXFLAGS) -c -o torrent/LibTorrent_Test_Torrent-test_tracker_timeout.obj `if test -f 'torrent/test_tracker_timeout.cc'; then $(CYGPATH_W) 'torrent/test_tracker_timeout.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/test_tracker_timeout.cc'; fi` LibTorrent_Test_Torrent_Net-main.o: main.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -MT LibTorrent_Test_Torrent_Net-main.o -MD -MP -MF $(DEPDIR)/LibTorrent_Test_Torrent_Net-main.Tpo -c -o LibTorrent_Test_Torrent_Net-main.o `test -f 'main.cc' || echo '$(srcdir)/'`main.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/LibTorrent_Test_Torrent_Net-main.Tpo $(DEPDIR)/LibTorrent_Test_Torrent_Net-main.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='main.cc' object='LibTorrent_Test_Torrent_Net-main.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -c -o LibTorrent_Test_Torrent_Net-main.o `test -f 'main.cc' || echo '$(srcdir)/'`main.cc LibTorrent_Test_Torrent_Net-main.obj: main.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -MT LibTorrent_Test_Torrent_Net-main.obj -MD -MP -MF $(DEPDIR)/LibTorrent_Test_Torrent_Net-main.Tpo -c -o LibTorrent_Test_Torrent_Net-main.obj `if test -f 'main.cc'; then $(CYGPATH_W) 'main.cc'; else $(CYGPATH_W) '$(srcdir)/main.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/LibTorrent_Test_Torrent_Net-main.Tpo $(DEPDIR)/LibTorrent_Test_Torrent_Net-main.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='main.cc' object='LibTorrent_Test_Torrent_Net-main.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -c -o LibTorrent_Test_Torrent_Net-main.obj `if test -f 'main.cc'; then $(CYGPATH_W) 'main.cc'; else $(CYGPATH_W) '$(srcdir)/main.cc'; fi` helpers/LibTorrent_Test_Torrent_Net-mock_function.o: helpers/mock_function.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent_Net-mock_function.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-mock_function.Tpo -c -o helpers/LibTorrent_Test_Torrent_Net-mock_function.o `test -f 'helpers/mock_function.cc' || echo '$(srcdir)/'`helpers/mock_function.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-mock_function.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-mock_function.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/mock_function.cc' object='helpers/LibTorrent_Test_Torrent_Net-mock_function.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent_Net-mock_function.o `test -f 'helpers/mock_function.cc' || echo '$(srcdir)/'`helpers/mock_function.cc helpers/LibTorrent_Test_Torrent_Net-mock_function.obj: helpers/mock_function.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent_Net-mock_function.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-mock_function.Tpo -c -o helpers/LibTorrent_Test_Torrent_Net-mock_function.obj `if test -f 'helpers/mock_function.cc'; then $(CYGPATH_W) 'helpers/mock_function.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/mock_function.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-mock_function.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-mock_function.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/mock_function.cc' object='helpers/LibTorrent_Test_Torrent_Net-mock_function.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent_Net-mock_function.obj `if test -f 'helpers/mock_function.cc'; then $(CYGPATH_W) 'helpers/mock_function.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/mock_function.cc'; fi` helpers/LibTorrent_Test_Torrent_Net-network.o: helpers/network.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent_Net-network.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-network.Tpo -c -o helpers/LibTorrent_Test_Torrent_Net-network.o `test -f 'helpers/network.cc' || echo '$(srcdir)/'`helpers/network.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-network.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-network.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/network.cc' object='helpers/LibTorrent_Test_Torrent_Net-network.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent_Net-network.o `test -f 'helpers/network.cc' || echo '$(srcdir)/'`helpers/network.cc helpers/LibTorrent_Test_Torrent_Net-network.obj: helpers/network.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent_Net-network.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-network.Tpo -c -o helpers/LibTorrent_Test_Torrent_Net-network.obj `if test -f 'helpers/network.cc'; then $(CYGPATH_W) 'helpers/network.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/network.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-network.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-network.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/network.cc' object='helpers/LibTorrent_Test_Torrent_Net-network.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent_Net-network.obj `if test -f 'helpers/network.cc'; then $(CYGPATH_W) 'helpers/network.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/network.cc'; fi` helpers/LibTorrent_Test_Torrent_Net-progress_listener.o: helpers/progress_listener.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent_Net-progress_listener.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-progress_listener.Tpo -c -o helpers/LibTorrent_Test_Torrent_Net-progress_listener.o `test -f 'helpers/progress_listener.cc' || echo '$(srcdir)/'`helpers/progress_listener.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-progress_listener.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-progress_listener.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/progress_listener.cc' object='helpers/LibTorrent_Test_Torrent_Net-progress_listener.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent_Net-progress_listener.o `test -f 'helpers/progress_listener.cc' || echo '$(srcdir)/'`helpers/progress_listener.cc helpers/LibTorrent_Test_Torrent_Net-progress_listener.obj: helpers/progress_listener.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent_Net-progress_listener.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-progress_listener.Tpo -c -o helpers/LibTorrent_Test_Torrent_Net-progress_listener.obj `if test -f 'helpers/progress_listener.cc'; then $(CYGPATH_W) 'helpers/progress_listener.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/progress_listener.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-progress_listener.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-progress_listener.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/progress_listener.cc' object='helpers/LibTorrent_Test_Torrent_Net-progress_listener.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent_Net-progress_listener.obj `if test -f 'helpers/progress_listener.cc'; then $(CYGPATH_W) 'helpers/progress_listener.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/progress_listener.cc'; fi` helpers/LibTorrent_Test_Torrent_Net-protectors.o: helpers/protectors.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent_Net-protectors.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-protectors.Tpo -c -o helpers/LibTorrent_Test_Torrent_Net-protectors.o `test -f 'helpers/protectors.cc' || echo '$(srcdir)/'`helpers/protectors.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-protectors.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-protectors.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/protectors.cc' object='helpers/LibTorrent_Test_Torrent_Net-protectors.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent_Net-protectors.o `test -f 'helpers/protectors.cc' || echo '$(srcdir)/'`helpers/protectors.cc helpers/LibTorrent_Test_Torrent_Net-protectors.obj: helpers/protectors.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent_Net-protectors.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-protectors.Tpo -c -o helpers/LibTorrent_Test_Torrent_Net-protectors.obj `if test -f 'helpers/protectors.cc'; then $(CYGPATH_W) 'helpers/protectors.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/protectors.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-protectors.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-protectors.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/protectors.cc' object='helpers/LibTorrent_Test_Torrent_Net-protectors.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent_Net-protectors.obj `if test -f 'helpers/protectors.cc'; then $(CYGPATH_W) 'helpers/protectors.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/protectors.cc'; fi` helpers/LibTorrent_Test_Torrent_Net-test_fixture.o: helpers/test_fixture.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent_Net-test_fixture.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_fixture.Tpo -c -o helpers/LibTorrent_Test_Torrent_Net-test_fixture.o `test -f 'helpers/test_fixture.cc' || echo '$(srcdir)/'`helpers/test_fixture.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_fixture.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_fixture.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/test_fixture.cc' object='helpers/LibTorrent_Test_Torrent_Net-test_fixture.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent_Net-test_fixture.o `test -f 'helpers/test_fixture.cc' || echo '$(srcdir)/'`helpers/test_fixture.cc helpers/LibTorrent_Test_Torrent_Net-test_fixture.obj: helpers/test_fixture.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent_Net-test_fixture.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_fixture.Tpo -c -o helpers/LibTorrent_Test_Torrent_Net-test_fixture.obj `if test -f 'helpers/test_fixture.cc'; then $(CYGPATH_W) 'helpers/test_fixture.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/test_fixture.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_fixture.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_fixture.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/test_fixture.cc' object='helpers/LibTorrent_Test_Torrent_Net-test_fixture.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent_Net-test_fixture.obj `if test -f 'helpers/test_fixture.cc'; then $(CYGPATH_W) 'helpers/test_fixture.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/test_fixture.cc'; fi` helpers/LibTorrent_Test_Torrent_Net-test_main_thread.o: helpers/test_main_thread.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent_Net-test_main_thread.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_main_thread.Tpo -c -o helpers/LibTorrent_Test_Torrent_Net-test_main_thread.o `test -f 'helpers/test_main_thread.cc' || echo '$(srcdir)/'`helpers/test_main_thread.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_main_thread.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_main_thread.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/test_main_thread.cc' object='helpers/LibTorrent_Test_Torrent_Net-test_main_thread.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent_Net-test_main_thread.o `test -f 'helpers/test_main_thread.cc' || echo '$(srcdir)/'`helpers/test_main_thread.cc helpers/LibTorrent_Test_Torrent_Net-test_main_thread.obj: helpers/test_main_thread.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent_Net-test_main_thread.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_main_thread.Tpo -c -o helpers/LibTorrent_Test_Torrent_Net-test_main_thread.obj `if test -f 'helpers/test_main_thread.cc'; then $(CYGPATH_W) 'helpers/test_main_thread.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/test_main_thread.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_main_thread.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_main_thread.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/test_main_thread.cc' object='helpers/LibTorrent_Test_Torrent_Net-test_main_thread.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent_Net-test_main_thread.obj `if test -f 'helpers/test_main_thread.cc'; then $(CYGPATH_W) 'helpers/test_main_thread.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/test_main_thread.cc'; fi` helpers/LibTorrent_Test_Torrent_Net-test_thread.o: helpers/test_thread.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent_Net-test_thread.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_thread.Tpo -c -o helpers/LibTorrent_Test_Torrent_Net-test_thread.o `test -f 'helpers/test_thread.cc' || echo '$(srcdir)/'`helpers/test_thread.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_thread.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_thread.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/test_thread.cc' object='helpers/LibTorrent_Test_Torrent_Net-test_thread.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent_Net-test_thread.o `test -f 'helpers/test_thread.cc' || echo '$(srcdir)/'`helpers/test_thread.cc helpers/LibTorrent_Test_Torrent_Net-test_thread.obj: helpers/test_thread.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent_Net-test_thread.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_thread.Tpo -c -o helpers/LibTorrent_Test_Torrent_Net-test_thread.obj `if test -f 'helpers/test_thread.cc'; then $(CYGPATH_W) 'helpers/test_thread.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/test_thread.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_thread.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_thread.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/test_thread.cc' object='helpers/LibTorrent_Test_Torrent_Net-test_thread.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent_Net-test_thread.obj `if test -f 'helpers/test_thread.cc'; then $(CYGPATH_W) 'helpers/test_thread.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/test_thread.cc'; fi` helpers/LibTorrent_Test_Torrent_Net-tracker_test.o: helpers/tracker_test.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent_Net-tracker_test.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-tracker_test.Tpo -c -o helpers/LibTorrent_Test_Torrent_Net-tracker_test.o `test -f 'helpers/tracker_test.cc' || echo '$(srcdir)/'`helpers/tracker_test.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-tracker_test.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-tracker_test.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/tracker_test.cc' object='helpers/LibTorrent_Test_Torrent_Net-tracker_test.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent_Net-tracker_test.o `test -f 'helpers/tracker_test.cc' || echo '$(srcdir)/'`helpers/tracker_test.cc helpers/LibTorrent_Test_Torrent_Net-tracker_test.obj: helpers/tracker_test.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent_Net-tracker_test.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-tracker_test.Tpo -c -o helpers/LibTorrent_Test_Torrent_Net-tracker_test.obj `if test -f 'helpers/tracker_test.cc'; then $(CYGPATH_W) 'helpers/tracker_test.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/tracker_test.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-tracker_test.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-tracker_test.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/tracker_test.cc' object='helpers/LibTorrent_Test_Torrent_Net-tracker_test.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent_Net-tracker_test.obj `if test -f 'helpers/tracker_test.cc'; then $(CYGPATH_W) 'helpers/tracker_test.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/tracker_test.cc'; fi` torrent/net/LibTorrent_Test_Torrent_Net-test_address_info.o: torrent/net/test_address_info.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -MT torrent/net/LibTorrent_Test_Torrent_Net-test_address_info.o -MD -MP -MF torrent/net/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_address_info.Tpo -c -o torrent/net/LibTorrent_Test_Torrent_Net-test_address_info.o `test -f 'torrent/net/test_address_info.cc' || echo '$(srcdir)/'`torrent/net/test_address_info.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/net/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_address_info.Tpo torrent/net/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_address_info.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/net/test_address_info.cc' object='torrent/net/LibTorrent_Test_Torrent_Net-test_address_info.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -c -o torrent/net/LibTorrent_Test_Torrent_Net-test_address_info.o `test -f 'torrent/net/test_address_info.cc' || echo '$(srcdir)/'`torrent/net/test_address_info.cc torrent/net/LibTorrent_Test_Torrent_Net-test_address_info.obj: torrent/net/test_address_info.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -MT torrent/net/LibTorrent_Test_Torrent_Net-test_address_info.obj -MD -MP -MF torrent/net/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_address_info.Tpo -c -o torrent/net/LibTorrent_Test_Torrent_Net-test_address_info.obj `if test -f 'torrent/net/test_address_info.cc'; then $(CYGPATH_W) 'torrent/net/test_address_info.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/net/test_address_info.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/net/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_address_info.Tpo torrent/net/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_address_info.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/net/test_address_info.cc' object='torrent/net/LibTorrent_Test_Torrent_Net-test_address_info.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -c -o torrent/net/LibTorrent_Test_Torrent_Net-test_address_info.obj `if test -f 'torrent/net/test_address_info.cc'; then $(CYGPATH_W) 'torrent/net/test_address_info.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/net/test_address_info.cc'; fi` torrent/net/LibTorrent_Test_Torrent_Net-test_fd.o: torrent/net/test_fd.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -MT torrent/net/LibTorrent_Test_Torrent_Net-test_fd.o -MD -MP -MF torrent/net/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_fd.Tpo -c -o torrent/net/LibTorrent_Test_Torrent_Net-test_fd.o `test -f 'torrent/net/test_fd.cc' || echo '$(srcdir)/'`torrent/net/test_fd.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/net/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_fd.Tpo torrent/net/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_fd.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/net/test_fd.cc' object='torrent/net/LibTorrent_Test_Torrent_Net-test_fd.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -c -o torrent/net/LibTorrent_Test_Torrent_Net-test_fd.o `test -f 'torrent/net/test_fd.cc' || echo '$(srcdir)/'`torrent/net/test_fd.cc torrent/net/LibTorrent_Test_Torrent_Net-test_fd.obj: torrent/net/test_fd.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -MT torrent/net/LibTorrent_Test_Torrent_Net-test_fd.obj -MD -MP -MF torrent/net/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_fd.Tpo -c -o torrent/net/LibTorrent_Test_Torrent_Net-test_fd.obj `if test -f 'torrent/net/test_fd.cc'; then $(CYGPATH_W) 'torrent/net/test_fd.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/net/test_fd.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/net/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_fd.Tpo torrent/net/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_fd.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/net/test_fd.cc' object='torrent/net/LibTorrent_Test_Torrent_Net-test_fd.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -c -o torrent/net/LibTorrent_Test_Torrent_Net-test_fd.obj `if test -f 'torrent/net/test_fd.cc'; then $(CYGPATH_W) 'torrent/net/test_fd.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/net/test_fd.cc'; fi` torrent/net/LibTorrent_Test_Torrent_Net-test_socket_address.o: torrent/net/test_socket_address.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -MT torrent/net/LibTorrent_Test_Torrent_Net-test_socket_address.o -MD -MP -MF torrent/net/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_socket_address.Tpo -c -o torrent/net/LibTorrent_Test_Torrent_Net-test_socket_address.o `test -f 'torrent/net/test_socket_address.cc' || echo '$(srcdir)/'`torrent/net/test_socket_address.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/net/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_socket_address.Tpo torrent/net/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_socket_address.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/net/test_socket_address.cc' object='torrent/net/LibTorrent_Test_Torrent_Net-test_socket_address.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -c -o torrent/net/LibTorrent_Test_Torrent_Net-test_socket_address.o `test -f 'torrent/net/test_socket_address.cc' || echo '$(srcdir)/'`torrent/net/test_socket_address.cc torrent/net/LibTorrent_Test_Torrent_Net-test_socket_address.obj: torrent/net/test_socket_address.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -MT torrent/net/LibTorrent_Test_Torrent_Net-test_socket_address.obj -MD -MP -MF torrent/net/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_socket_address.Tpo -c -o torrent/net/LibTorrent_Test_Torrent_Net-test_socket_address.obj `if test -f 'torrent/net/test_socket_address.cc'; then $(CYGPATH_W) 'torrent/net/test_socket_address.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/net/test_socket_address.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/net/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_socket_address.Tpo torrent/net/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_socket_address.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/net/test_socket_address.cc' object='torrent/net/LibTorrent_Test_Torrent_Net-test_socket_address.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Net_CXXFLAGS) $(CXXFLAGS) -c -o torrent/net/LibTorrent_Test_Torrent_Net-test_socket_address.obj `if test -f 'torrent/net/test_socket_address.cc'; then $(CYGPATH_W) 'torrent/net/test_socket_address.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/net/test_socket_address.cc'; fi` LibTorrent_Test_Torrent_Utils-main.o: main.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -MT LibTorrent_Test_Torrent_Utils-main.o -MD -MP -MF $(DEPDIR)/LibTorrent_Test_Torrent_Utils-main.Tpo -c -o LibTorrent_Test_Torrent_Utils-main.o `test -f 'main.cc' || echo '$(srcdir)/'`main.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/LibTorrent_Test_Torrent_Utils-main.Tpo $(DEPDIR)/LibTorrent_Test_Torrent_Utils-main.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='main.cc' object='LibTorrent_Test_Torrent_Utils-main.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -c -o LibTorrent_Test_Torrent_Utils-main.o `test -f 'main.cc' || echo '$(srcdir)/'`main.cc LibTorrent_Test_Torrent_Utils-main.obj: main.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -MT LibTorrent_Test_Torrent_Utils-main.obj -MD -MP -MF $(DEPDIR)/LibTorrent_Test_Torrent_Utils-main.Tpo -c -o LibTorrent_Test_Torrent_Utils-main.obj `if test -f 'main.cc'; then $(CYGPATH_W) 'main.cc'; else $(CYGPATH_W) '$(srcdir)/main.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/LibTorrent_Test_Torrent_Utils-main.Tpo $(DEPDIR)/LibTorrent_Test_Torrent_Utils-main.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='main.cc' object='LibTorrent_Test_Torrent_Utils-main.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -c -o LibTorrent_Test_Torrent_Utils-main.obj `if test -f 'main.cc'; then $(CYGPATH_W) 'main.cc'; else $(CYGPATH_W) '$(srcdir)/main.cc'; fi` helpers/LibTorrent_Test_Torrent_Utils-mock_function.o: helpers/mock_function.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent_Utils-mock_function.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-mock_function.Tpo -c -o helpers/LibTorrent_Test_Torrent_Utils-mock_function.o `test -f 'helpers/mock_function.cc' || echo '$(srcdir)/'`helpers/mock_function.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-mock_function.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-mock_function.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/mock_function.cc' object='helpers/LibTorrent_Test_Torrent_Utils-mock_function.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent_Utils-mock_function.o `test -f 'helpers/mock_function.cc' || echo '$(srcdir)/'`helpers/mock_function.cc helpers/LibTorrent_Test_Torrent_Utils-mock_function.obj: helpers/mock_function.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent_Utils-mock_function.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-mock_function.Tpo -c -o helpers/LibTorrent_Test_Torrent_Utils-mock_function.obj `if test -f 'helpers/mock_function.cc'; then $(CYGPATH_W) 'helpers/mock_function.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/mock_function.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-mock_function.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-mock_function.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/mock_function.cc' object='helpers/LibTorrent_Test_Torrent_Utils-mock_function.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent_Utils-mock_function.obj `if test -f 'helpers/mock_function.cc'; then $(CYGPATH_W) 'helpers/mock_function.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/mock_function.cc'; fi` helpers/LibTorrent_Test_Torrent_Utils-network.o: helpers/network.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent_Utils-network.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-network.Tpo -c -o helpers/LibTorrent_Test_Torrent_Utils-network.o `test -f 'helpers/network.cc' || echo '$(srcdir)/'`helpers/network.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-network.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-network.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/network.cc' object='helpers/LibTorrent_Test_Torrent_Utils-network.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent_Utils-network.o `test -f 'helpers/network.cc' || echo '$(srcdir)/'`helpers/network.cc helpers/LibTorrent_Test_Torrent_Utils-network.obj: helpers/network.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent_Utils-network.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-network.Tpo -c -o helpers/LibTorrent_Test_Torrent_Utils-network.obj `if test -f 'helpers/network.cc'; then $(CYGPATH_W) 'helpers/network.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/network.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-network.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-network.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/network.cc' object='helpers/LibTorrent_Test_Torrent_Utils-network.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent_Utils-network.obj `if test -f 'helpers/network.cc'; then $(CYGPATH_W) 'helpers/network.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/network.cc'; fi` helpers/LibTorrent_Test_Torrent_Utils-progress_listener.o: helpers/progress_listener.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent_Utils-progress_listener.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-progress_listener.Tpo -c -o helpers/LibTorrent_Test_Torrent_Utils-progress_listener.o `test -f 'helpers/progress_listener.cc' || echo '$(srcdir)/'`helpers/progress_listener.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-progress_listener.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-progress_listener.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/progress_listener.cc' object='helpers/LibTorrent_Test_Torrent_Utils-progress_listener.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent_Utils-progress_listener.o `test -f 'helpers/progress_listener.cc' || echo '$(srcdir)/'`helpers/progress_listener.cc helpers/LibTorrent_Test_Torrent_Utils-progress_listener.obj: helpers/progress_listener.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent_Utils-progress_listener.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-progress_listener.Tpo -c -o helpers/LibTorrent_Test_Torrent_Utils-progress_listener.obj `if test -f 'helpers/progress_listener.cc'; then $(CYGPATH_W) 'helpers/progress_listener.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/progress_listener.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-progress_listener.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-progress_listener.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/progress_listener.cc' object='helpers/LibTorrent_Test_Torrent_Utils-progress_listener.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent_Utils-progress_listener.obj `if test -f 'helpers/progress_listener.cc'; then $(CYGPATH_W) 'helpers/progress_listener.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/progress_listener.cc'; fi` helpers/LibTorrent_Test_Torrent_Utils-protectors.o: helpers/protectors.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent_Utils-protectors.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-protectors.Tpo -c -o helpers/LibTorrent_Test_Torrent_Utils-protectors.o `test -f 'helpers/protectors.cc' || echo '$(srcdir)/'`helpers/protectors.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-protectors.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-protectors.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/protectors.cc' object='helpers/LibTorrent_Test_Torrent_Utils-protectors.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent_Utils-protectors.o `test -f 'helpers/protectors.cc' || echo '$(srcdir)/'`helpers/protectors.cc helpers/LibTorrent_Test_Torrent_Utils-protectors.obj: helpers/protectors.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent_Utils-protectors.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-protectors.Tpo -c -o helpers/LibTorrent_Test_Torrent_Utils-protectors.obj `if test -f 'helpers/protectors.cc'; then $(CYGPATH_W) 'helpers/protectors.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/protectors.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-protectors.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-protectors.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/protectors.cc' object='helpers/LibTorrent_Test_Torrent_Utils-protectors.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent_Utils-protectors.obj `if test -f 'helpers/protectors.cc'; then $(CYGPATH_W) 'helpers/protectors.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/protectors.cc'; fi` helpers/LibTorrent_Test_Torrent_Utils-test_fixture.o: helpers/test_fixture.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent_Utils-test_fixture.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_fixture.Tpo -c -o helpers/LibTorrent_Test_Torrent_Utils-test_fixture.o `test -f 'helpers/test_fixture.cc' || echo '$(srcdir)/'`helpers/test_fixture.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_fixture.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_fixture.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/test_fixture.cc' object='helpers/LibTorrent_Test_Torrent_Utils-test_fixture.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent_Utils-test_fixture.o `test -f 'helpers/test_fixture.cc' || echo '$(srcdir)/'`helpers/test_fixture.cc helpers/LibTorrent_Test_Torrent_Utils-test_fixture.obj: helpers/test_fixture.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent_Utils-test_fixture.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_fixture.Tpo -c -o helpers/LibTorrent_Test_Torrent_Utils-test_fixture.obj `if test -f 'helpers/test_fixture.cc'; then $(CYGPATH_W) 'helpers/test_fixture.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/test_fixture.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_fixture.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_fixture.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/test_fixture.cc' object='helpers/LibTorrent_Test_Torrent_Utils-test_fixture.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent_Utils-test_fixture.obj `if test -f 'helpers/test_fixture.cc'; then $(CYGPATH_W) 'helpers/test_fixture.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/test_fixture.cc'; fi` helpers/LibTorrent_Test_Torrent_Utils-test_main_thread.o: helpers/test_main_thread.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent_Utils-test_main_thread.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_main_thread.Tpo -c -o helpers/LibTorrent_Test_Torrent_Utils-test_main_thread.o `test -f 'helpers/test_main_thread.cc' || echo '$(srcdir)/'`helpers/test_main_thread.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_main_thread.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_main_thread.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/test_main_thread.cc' object='helpers/LibTorrent_Test_Torrent_Utils-test_main_thread.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent_Utils-test_main_thread.o `test -f 'helpers/test_main_thread.cc' || echo '$(srcdir)/'`helpers/test_main_thread.cc helpers/LibTorrent_Test_Torrent_Utils-test_main_thread.obj: helpers/test_main_thread.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent_Utils-test_main_thread.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_main_thread.Tpo -c -o helpers/LibTorrent_Test_Torrent_Utils-test_main_thread.obj `if test -f 'helpers/test_main_thread.cc'; then $(CYGPATH_W) 'helpers/test_main_thread.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/test_main_thread.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_main_thread.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_main_thread.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/test_main_thread.cc' object='helpers/LibTorrent_Test_Torrent_Utils-test_main_thread.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent_Utils-test_main_thread.obj `if test -f 'helpers/test_main_thread.cc'; then $(CYGPATH_W) 'helpers/test_main_thread.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/test_main_thread.cc'; fi` helpers/LibTorrent_Test_Torrent_Utils-test_thread.o: helpers/test_thread.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent_Utils-test_thread.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_thread.Tpo -c -o helpers/LibTorrent_Test_Torrent_Utils-test_thread.o `test -f 'helpers/test_thread.cc' || echo '$(srcdir)/'`helpers/test_thread.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_thread.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_thread.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/test_thread.cc' object='helpers/LibTorrent_Test_Torrent_Utils-test_thread.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent_Utils-test_thread.o `test -f 'helpers/test_thread.cc' || echo '$(srcdir)/'`helpers/test_thread.cc helpers/LibTorrent_Test_Torrent_Utils-test_thread.obj: helpers/test_thread.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent_Utils-test_thread.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_thread.Tpo -c -o helpers/LibTorrent_Test_Torrent_Utils-test_thread.obj `if test -f 'helpers/test_thread.cc'; then $(CYGPATH_W) 'helpers/test_thread.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/test_thread.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_thread.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_thread.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/test_thread.cc' object='helpers/LibTorrent_Test_Torrent_Utils-test_thread.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent_Utils-test_thread.obj `if test -f 'helpers/test_thread.cc'; then $(CYGPATH_W) 'helpers/test_thread.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/test_thread.cc'; fi` helpers/LibTorrent_Test_Torrent_Utils-tracker_test.o: helpers/tracker_test.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent_Utils-tracker_test.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-tracker_test.Tpo -c -o helpers/LibTorrent_Test_Torrent_Utils-tracker_test.o `test -f 'helpers/tracker_test.cc' || echo '$(srcdir)/'`helpers/tracker_test.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-tracker_test.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-tracker_test.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/tracker_test.cc' object='helpers/LibTorrent_Test_Torrent_Utils-tracker_test.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent_Utils-tracker_test.o `test -f 'helpers/tracker_test.cc' || echo '$(srcdir)/'`helpers/tracker_test.cc helpers/LibTorrent_Test_Torrent_Utils-tracker_test.obj: helpers/tracker_test.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Torrent_Utils-tracker_test.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-tracker_test.Tpo -c -o helpers/LibTorrent_Test_Torrent_Utils-tracker_test.obj `if test -f 'helpers/tracker_test.cc'; then $(CYGPATH_W) 'helpers/tracker_test.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/tracker_test.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-tracker_test.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-tracker_test.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/tracker_test.cc' object='helpers/LibTorrent_Test_Torrent_Utils-tracker_test.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Torrent_Utils-tracker_test.obj `if test -f 'helpers/tracker_test.cc'; then $(CYGPATH_W) 'helpers/tracker_test.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/tracker_test.cc'; fi` torrent/utils/LibTorrent_Test_Torrent_Utils-test_extents.o: torrent/utils/test_extents.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -MT torrent/utils/LibTorrent_Test_Torrent_Utils-test_extents.o -MD -MP -MF torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_extents.Tpo -c -o torrent/utils/LibTorrent_Test_Torrent_Utils-test_extents.o `test -f 'torrent/utils/test_extents.cc' || echo '$(srcdir)/'`torrent/utils/test_extents.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_extents.Tpo torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_extents.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/utils/test_extents.cc' object='torrent/utils/LibTorrent_Test_Torrent_Utils-test_extents.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -c -o torrent/utils/LibTorrent_Test_Torrent_Utils-test_extents.o `test -f 'torrent/utils/test_extents.cc' || echo '$(srcdir)/'`torrent/utils/test_extents.cc torrent/utils/LibTorrent_Test_Torrent_Utils-test_extents.obj: torrent/utils/test_extents.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -MT torrent/utils/LibTorrent_Test_Torrent_Utils-test_extents.obj -MD -MP -MF torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_extents.Tpo -c -o torrent/utils/LibTorrent_Test_Torrent_Utils-test_extents.obj `if test -f 'torrent/utils/test_extents.cc'; then $(CYGPATH_W) 'torrent/utils/test_extents.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/utils/test_extents.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_extents.Tpo torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_extents.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/utils/test_extents.cc' object='torrent/utils/LibTorrent_Test_Torrent_Utils-test_extents.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -c -o torrent/utils/LibTorrent_Test_Torrent_Utils-test_extents.obj `if test -f 'torrent/utils/test_extents.cc'; then $(CYGPATH_W) 'torrent/utils/test_extents.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/utils/test_extents.cc'; fi` torrent/utils/LibTorrent_Test_Torrent_Utils-test_log.o: torrent/utils/test_log.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -MT torrent/utils/LibTorrent_Test_Torrent_Utils-test_log.o -MD -MP -MF torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_log.Tpo -c -o torrent/utils/LibTorrent_Test_Torrent_Utils-test_log.o `test -f 'torrent/utils/test_log.cc' || echo '$(srcdir)/'`torrent/utils/test_log.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_log.Tpo torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_log.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/utils/test_log.cc' object='torrent/utils/LibTorrent_Test_Torrent_Utils-test_log.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -c -o torrent/utils/LibTorrent_Test_Torrent_Utils-test_log.o `test -f 'torrent/utils/test_log.cc' || echo '$(srcdir)/'`torrent/utils/test_log.cc torrent/utils/LibTorrent_Test_Torrent_Utils-test_log.obj: torrent/utils/test_log.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -MT torrent/utils/LibTorrent_Test_Torrent_Utils-test_log.obj -MD -MP -MF torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_log.Tpo -c -o torrent/utils/LibTorrent_Test_Torrent_Utils-test_log.obj `if test -f 'torrent/utils/test_log.cc'; then $(CYGPATH_W) 'torrent/utils/test_log.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/utils/test_log.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_log.Tpo torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_log.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/utils/test_log.cc' object='torrent/utils/LibTorrent_Test_Torrent_Utils-test_log.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -c -o torrent/utils/LibTorrent_Test_Torrent_Utils-test_log.obj `if test -f 'torrent/utils/test_log.cc'; then $(CYGPATH_W) 'torrent/utils/test_log.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/utils/test_log.cc'; fi` torrent/utils/LibTorrent_Test_Torrent_Utils-test_log_buffer.o: torrent/utils/test_log_buffer.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -MT torrent/utils/LibTorrent_Test_Torrent_Utils-test_log_buffer.o -MD -MP -MF torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_log_buffer.Tpo -c -o torrent/utils/LibTorrent_Test_Torrent_Utils-test_log_buffer.o `test -f 'torrent/utils/test_log_buffer.cc' || echo '$(srcdir)/'`torrent/utils/test_log_buffer.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_log_buffer.Tpo torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_log_buffer.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/utils/test_log_buffer.cc' object='torrent/utils/LibTorrent_Test_Torrent_Utils-test_log_buffer.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -c -o torrent/utils/LibTorrent_Test_Torrent_Utils-test_log_buffer.o `test -f 'torrent/utils/test_log_buffer.cc' || echo '$(srcdir)/'`torrent/utils/test_log_buffer.cc torrent/utils/LibTorrent_Test_Torrent_Utils-test_log_buffer.obj: torrent/utils/test_log_buffer.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -MT torrent/utils/LibTorrent_Test_Torrent_Utils-test_log_buffer.obj -MD -MP -MF torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_log_buffer.Tpo -c -o torrent/utils/LibTorrent_Test_Torrent_Utils-test_log_buffer.obj `if test -f 'torrent/utils/test_log_buffer.cc'; then $(CYGPATH_W) 'torrent/utils/test_log_buffer.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/utils/test_log_buffer.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_log_buffer.Tpo torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_log_buffer.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/utils/test_log_buffer.cc' object='torrent/utils/LibTorrent_Test_Torrent_Utils-test_log_buffer.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -c -o torrent/utils/LibTorrent_Test_Torrent_Utils-test_log_buffer.obj `if test -f 'torrent/utils/test_log_buffer.cc'; then $(CYGPATH_W) 'torrent/utils/test_log_buffer.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/utils/test_log_buffer.cc'; fi` torrent/utils/LibTorrent_Test_Torrent_Utils-test_option_strings.o: torrent/utils/test_option_strings.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -MT torrent/utils/LibTorrent_Test_Torrent_Utils-test_option_strings.o -MD -MP -MF torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_option_strings.Tpo -c -o torrent/utils/LibTorrent_Test_Torrent_Utils-test_option_strings.o `test -f 'torrent/utils/test_option_strings.cc' || echo '$(srcdir)/'`torrent/utils/test_option_strings.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_option_strings.Tpo torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_option_strings.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/utils/test_option_strings.cc' object='torrent/utils/LibTorrent_Test_Torrent_Utils-test_option_strings.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -c -o torrent/utils/LibTorrent_Test_Torrent_Utils-test_option_strings.o `test -f 'torrent/utils/test_option_strings.cc' || echo '$(srcdir)/'`torrent/utils/test_option_strings.cc torrent/utils/LibTorrent_Test_Torrent_Utils-test_option_strings.obj: torrent/utils/test_option_strings.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -MT torrent/utils/LibTorrent_Test_Torrent_Utils-test_option_strings.obj -MD -MP -MF torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_option_strings.Tpo -c -o torrent/utils/LibTorrent_Test_Torrent_Utils-test_option_strings.obj `if test -f 'torrent/utils/test_option_strings.cc'; then $(CYGPATH_W) 'torrent/utils/test_option_strings.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/utils/test_option_strings.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_option_strings.Tpo torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_option_strings.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/utils/test_option_strings.cc' object='torrent/utils/LibTorrent_Test_Torrent_Utils-test_option_strings.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -c -o torrent/utils/LibTorrent_Test_Torrent_Utils-test_option_strings.obj `if test -f 'torrent/utils/test_option_strings.cc'; then $(CYGPATH_W) 'torrent/utils/test_option_strings.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/utils/test_option_strings.cc'; fi` torrent/utils/LibTorrent_Test_Torrent_Utils-test_queue_buckets.o: torrent/utils/test_queue_buckets.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -MT torrent/utils/LibTorrent_Test_Torrent_Utils-test_queue_buckets.o -MD -MP -MF torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_queue_buckets.Tpo -c -o torrent/utils/LibTorrent_Test_Torrent_Utils-test_queue_buckets.o `test -f 'torrent/utils/test_queue_buckets.cc' || echo '$(srcdir)/'`torrent/utils/test_queue_buckets.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_queue_buckets.Tpo torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_queue_buckets.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/utils/test_queue_buckets.cc' object='torrent/utils/LibTorrent_Test_Torrent_Utils-test_queue_buckets.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -c -o torrent/utils/LibTorrent_Test_Torrent_Utils-test_queue_buckets.o `test -f 'torrent/utils/test_queue_buckets.cc' || echo '$(srcdir)/'`torrent/utils/test_queue_buckets.cc torrent/utils/LibTorrent_Test_Torrent_Utils-test_queue_buckets.obj: torrent/utils/test_queue_buckets.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -MT torrent/utils/LibTorrent_Test_Torrent_Utils-test_queue_buckets.obj -MD -MP -MF torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_queue_buckets.Tpo -c -o torrent/utils/LibTorrent_Test_Torrent_Utils-test_queue_buckets.obj `if test -f 'torrent/utils/test_queue_buckets.cc'; then $(CYGPATH_W) 'torrent/utils/test_queue_buckets.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/utils/test_queue_buckets.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_queue_buckets.Tpo torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_queue_buckets.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/utils/test_queue_buckets.cc' object='torrent/utils/LibTorrent_Test_Torrent_Utils-test_queue_buckets.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -c -o torrent/utils/LibTorrent_Test_Torrent_Utils-test_queue_buckets.obj `if test -f 'torrent/utils/test_queue_buckets.cc'; then $(CYGPATH_W) 'torrent/utils/test_queue_buckets.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/utils/test_queue_buckets.cc'; fi` torrent/utils/LibTorrent_Test_Torrent_Utils-test_signal_bitfield.o: torrent/utils/test_signal_bitfield.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -MT torrent/utils/LibTorrent_Test_Torrent_Utils-test_signal_bitfield.o -MD -MP -MF torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_signal_bitfield.Tpo -c -o torrent/utils/LibTorrent_Test_Torrent_Utils-test_signal_bitfield.o `test -f 'torrent/utils/test_signal_bitfield.cc' || echo '$(srcdir)/'`torrent/utils/test_signal_bitfield.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_signal_bitfield.Tpo torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_signal_bitfield.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/utils/test_signal_bitfield.cc' object='torrent/utils/LibTorrent_Test_Torrent_Utils-test_signal_bitfield.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -c -o torrent/utils/LibTorrent_Test_Torrent_Utils-test_signal_bitfield.o `test -f 'torrent/utils/test_signal_bitfield.cc' || echo '$(srcdir)/'`torrent/utils/test_signal_bitfield.cc torrent/utils/LibTorrent_Test_Torrent_Utils-test_signal_bitfield.obj: torrent/utils/test_signal_bitfield.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -MT torrent/utils/LibTorrent_Test_Torrent_Utils-test_signal_bitfield.obj -MD -MP -MF torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_signal_bitfield.Tpo -c -o torrent/utils/LibTorrent_Test_Torrent_Utils-test_signal_bitfield.obj `if test -f 'torrent/utils/test_signal_bitfield.cc'; then $(CYGPATH_W) 'torrent/utils/test_signal_bitfield.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/utils/test_signal_bitfield.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_signal_bitfield.Tpo torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_signal_bitfield.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/utils/test_signal_bitfield.cc' object='torrent/utils/LibTorrent_Test_Torrent_Utils-test_signal_bitfield.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -c -o torrent/utils/LibTorrent_Test_Torrent_Utils-test_signal_bitfield.obj `if test -f 'torrent/utils/test_signal_bitfield.cc'; then $(CYGPATH_W) 'torrent/utils/test_signal_bitfield.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/utils/test_signal_bitfield.cc'; fi` torrent/utils/LibTorrent_Test_Torrent_Utils-test_signal_interrupt.o: torrent/utils/test_signal_interrupt.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -MT torrent/utils/LibTorrent_Test_Torrent_Utils-test_signal_interrupt.o -MD -MP -MF torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_signal_interrupt.Tpo -c -o torrent/utils/LibTorrent_Test_Torrent_Utils-test_signal_interrupt.o `test -f 'torrent/utils/test_signal_interrupt.cc' || echo '$(srcdir)/'`torrent/utils/test_signal_interrupt.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_signal_interrupt.Tpo torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_signal_interrupt.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/utils/test_signal_interrupt.cc' object='torrent/utils/LibTorrent_Test_Torrent_Utils-test_signal_interrupt.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -c -o torrent/utils/LibTorrent_Test_Torrent_Utils-test_signal_interrupt.o `test -f 'torrent/utils/test_signal_interrupt.cc' || echo '$(srcdir)/'`torrent/utils/test_signal_interrupt.cc torrent/utils/LibTorrent_Test_Torrent_Utils-test_signal_interrupt.obj: torrent/utils/test_signal_interrupt.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -MT torrent/utils/LibTorrent_Test_Torrent_Utils-test_signal_interrupt.obj -MD -MP -MF torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_signal_interrupt.Tpo -c -o torrent/utils/LibTorrent_Test_Torrent_Utils-test_signal_interrupt.obj `if test -f 'torrent/utils/test_signal_interrupt.cc'; then $(CYGPATH_W) 'torrent/utils/test_signal_interrupt.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/utils/test_signal_interrupt.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_signal_interrupt.Tpo torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_signal_interrupt.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/utils/test_signal_interrupt.cc' object='torrent/utils/LibTorrent_Test_Torrent_Utils-test_signal_interrupt.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -c -o torrent/utils/LibTorrent_Test_Torrent_Utils-test_signal_interrupt.obj `if test -f 'torrent/utils/test_signal_interrupt.cc'; then $(CYGPATH_W) 'torrent/utils/test_signal_interrupt.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/utils/test_signal_interrupt.cc'; fi` torrent/utils/LibTorrent_Test_Torrent_Utils-test_thread_base.o: torrent/utils/test_thread_base.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -MT torrent/utils/LibTorrent_Test_Torrent_Utils-test_thread_base.o -MD -MP -MF torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_thread_base.Tpo -c -o torrent/utils/LibTorrent_Test_Torrent_Utils-test_thread_base.o `test -f 'torrent/utils/test_thread_base.cc' || echo '$(srcdir)/'`torrent/utils/test_thread_base.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_thread_base.Tpo torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_thread_base.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/utils/test_thread_base.cc' object='torrent/utils/LibTorrent_Test_Torrent_Utils-test_thread_base.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -c -o torrent/utils/LibTorrent_Test_Torrent_Utils-test_thread_base.o `test -f 'torrent/utils/test_thread_base.cc' || echo '$(srcdir)/'`torrent/utils/test_thread_base.cc torrent/utils/LibTorrent_Test_Torrent_Utils-test_thread_base.obj: torrent/utils/test_thread_base.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -MT torrent/utils/LibTorrent_Test_Torrent_Utils-test_thread_base.obj -MD -MP -MF torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_thread_base.Tpo -c -o torrent/utils/LibTorrent_Test_Torrent_Utils-test_thread_base.obj `if test -f 'torrent/utils/test_thread_base.cc'; then $(CYGPATH_W) 'torrent/utils/test_thread_base.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/utils/test_thread_base.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_thread_base.Tpo torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_thread_base.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/utils/test_thread_base.cc' object='torrent/utils/LibTorrent_Test_Torrent_Utils-test_thread_base.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -c -o torrent/utils/LibTorrent_Test_Torrent_Utils-test_thread_base.obj `if test -f 'torrent/utils/test_thread_base.cc'; then $(CYGPATH_W) 'torrent/utils/test_thread_base.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/utils/test_thread_base.cc'; fi` torrent/utils/LibTorrent_Test_Torrent_Utils-test_uri_parser.o: torrent/utils/test_uri_parser.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -MT torrent/utils/LibTorrent_Test_Torrent_Utils-test_uri_parser.o -MD -MP -MF torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_uri_parser.Tpo -c -o torrent/utils/LibTorrent_Test_Torrent_Utils-test_uri_parser.o `test -f 'torrent/utils/test_uri_parser.cc' || echo '$(srcdir)/'`torrent/utils/test_uri_parser.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_uri_parser.Tpo torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_uri_parser.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/utils/test_uri_parser.cc' object='torrent/utils/LibTorrent_Test_Torrent_Utils-test_uri_parser.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -c -o torrent/utils/LibTorrent_Test_Torrent_Utils-test_uri_parser.o `test -f 'torrent/utils/test_uri_parser.cc' || echo '$(srcdir)/'`torrent/utils/test_uri_parser.cc torrent/utils/LibTorrent_Test_Torrent_Utils-test_uri_parser.obj: torrent/utils/test_uri_parser.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -MT torrent/utils/LibTorrent_Test_Torrent_Utils-test_uri_parser.obj -MD -MP -MF torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_uri_parser.Tpo -c -o torrent/utils/LibTorrent_Test_Torrent_Utils-test_uri_parser.obj `if test -f 'torrent/utils/test_uri_parser.cc'; then $(CYGPATH_W) 'torrent/utils/test_uri_parser.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/utils/test_uri_parser.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_uri_parser.Tpo torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_uri_parser.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='torrent/utils/test_uri_parser.cc' object='torrent/utils/LibTorrent_Test_Torrent_Utils-test_uri_parser.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Torrent_Utils_CXXFLAGS) $(CXXFLAGS) -c -o torrent/utils/LibTorrent_Test_Torrent_Utils-test_uri_parser.obj `if test -f 'torrent/utils/test_uri_parser.cc'; then $(CYGPATH_W) 'torrent/utils/test_uri_parser.cc'; else $(CYGPATH_W) '$(srcdir)/torrent/utils/test_uri_parser.cc'; fi` LibTorrent_Test_Tracker-main.o: main.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Tracker_CXXFLAGS) $(CXXFLAGS) -MT LibTorrent_Test_Tracker-main.o -MD -MP -MF $(DEPDIR)/LibTorrent_Test_Tracker-main.Tpo -c -o LibTorrent_Test_Tracker-main.o `test -f 'main.cc' || echo '$(srcdir)/'`main.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/LibTorrent_Test_Tracker-main.Tpo $(DEPDIR)/LibTorrent_Test_Tracker-main.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='main.cc' object='LibTorrent_Test_Tracker-main.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Tracker_CXXFLAGS) $(CXXFLAGS) -c -o LibTorrent_Test_Tracker-main.o `test -f 'main.cc' || echo '$(srcdir)/'`main.cc LibTorrent_Test_Tracker-main.obj: main.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Tracker_CXXFLAGS) $(CXXFLAGS) -MT LibTorrent_Test_Tracker-main.obj -MD -MP -MF $(DEPDIR)/LibTorrent_Test_Tracker-main.Tpo -c -o LibTorrent_Test_Tracker-main.obj `if test -f 'main.cc'; then $(CYGPATH_W) 'main.cc'; else $(CYGPATH_W) '$(srcdir)/main.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/LibTorrent_Test_Tracker-main.Tpo $(DEPDIR)/LibTorrent_Test_Tracker-main.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='main.cc' object='LibTorrent_Test_Tracker-main.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Tracker_CXXFLAGS) $(CXXFLAGS) -c -o LibTorrent_Test_Tracker-main.obj `if test -f 'main.cc'; then $(CYGPATH_W) 'main.cc'; else $(CYGPATH_W) '$(srcdir)/main.cc'; fi` helpers/LibTorrent_Test_Tracker-mock_function.o: helpers/mock_function.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Tracker_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Tracker-mock_function.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Tracker-mock_function.Tpo -c -o helpers/LibTorrent_Test_Tracker-mock_function.o `test -f 'helpers/mock_function.cc' || echo '$(srcdir)/'`helpers/mock_function.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Tracker-mock_function.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Tracker-mock_function.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/mock_function.cc' object='helpers/LibTorrent_Test_Tracker-mock_function.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Tracker_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Tracker-mock_function.o `test -f 'helpers/mock_function.cc' || echo '$(srcdir)/'`helpers/mock_function.cc helpers/LibTorrent_Test_Tracker-mock_function.obj: helpers/mock_function.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Tracker_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Tracker-mock_function.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Tracker-mock_function.Tpo -c -o helpers/LibTorrent_Test_Tracker-mock_function.obj `if test -f 'helpers/mock_function.cc'; then $(CYGPATH_W) 'helpers/mock_function.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/mock_function.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Tracker-mock_function.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Tracker-mock_function.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/mock_function.cc' object='helpers/LibTorrent_Test_Tracker-mock_function.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Tracker_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Tracker-mock_function.obj `if test -f 'helpers/mock_function.cc'; then $(CYGPATH_W) 'helpers/mock_function.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/mock_function.cc'; fi` helpers/LibTorrent_Test_Tracker-network.o: helpers/network.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Tracker_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Tracker-network.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Tracker-network.Tpo -c -o helpers/LibTorrent_Test_Tracker-network.o `test -f 'helpers/network.cc' || echo '$(srcdir)/'`helpers/network.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Tracker-network.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Tracker-network.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/network.cc' object='helpers/LibTorrent_Test_Tracker-network.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Tracker_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Tracker-network.o `test -f 'helpers/network.cc' || echo '$(srcdir)/'`helpers/network.cc helpers/LibTorrent_Test_Tracker-network.obj: helpers/network.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Tracker_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Tracker-network.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Tracker-network.Tpo -c -o helpers/LibTorrent_Test_Tracker-network.obj `if test -f 'helpers/network.cc'; then $(CYGPATH_W) 'helpers/network.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/network.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Tracker-network.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Tracker-network.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/network.cc' object='helpers/LibTorrent_Test_Tracker-network.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Tracker_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Tracker-network.obj `if test -f 'helpers/network.cc'; then $(CYGPATH_W) 'helpers/network.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/network.cc'; fi` helpers/LibTorrent_Test_Tracker-progress_listener.o: helpers/progress_listener.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Tracker_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Tracker-progress_listener.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Tracker-progress_listener.Tpo -c -o helpers/LibTorrent_Test_Tracker-progress_listener.o `test -f 'helpers/progress_listener.cc' || echo '$(srcdir)/'`helpers/progress_listener.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Tracker-progress_listener.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Tracker-progress_listener.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/progress_listener.cc' object='helpers/LibTorrent_Test_Tracker-progress_listener.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Tracker_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Tracker-progress_listener.o `test -f 'helpers/progress_listener.cc' || echo '$(srcdir)/'`helpers/progress_listener.cc helpers/LibTorrent_Test_Tracker-progress_listener.obj: helpers/progress_listener.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Tracker_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Tracker-progress_listener.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Tracker-progress_listener.Tpo -c -o helpers/LibTorrent_Test_Tracker-progress_listener.obj `if test -f 'helpers/progress_listener.cc'; then $(CYGPATH_W) 'helpers/progress_listener.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/progress_listener.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Tracker-progress_listener.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Tracker-progress_listener.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/progress_listener.cc' object='helpers/LibTorrent_Test_Tracker-progress_listener.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Tracker_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Tracker-progress_listener.obj `if test -f 'helpers/progress_listener.cc'; then $(CYGPATH_W) 'helpers/progress_listener.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/progress_listener.cc'; fi` helpers/LibTorrent_Test_Tracker-protectors.o: helpers/protectors.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Tracker_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Tracker-protectors.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Tracker-protectors.Tpo -c -o helpers/LibTorrent_Test_Tracker-protectors.o `test -f 'helpers/protectors.cc' || echo '$(srcdir)/'`helpers/protectors.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Tracker-protectors.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Tracker-protectors.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/protectors.cc' object='helpers/LibTorrent_Test_Tracker-protectors.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Tracker_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Tracker-protectors.o `test -f 'helpers/protectors.cc' || echo '$(srcdir)/'`helpers/protectors.cc helpers/LibTorrent_Test_Tracker-protectors.obj: helpers/protectors.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Tracker_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Tracker-protectors.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Tracker-protectors.Tpo -c -o helpers/LibTorrent_Test_Tracker-protectors.obj `if test -f 'helpers/protectors.cc'; then $(CYGPATH_W) 'helpers/protectors.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/protectors.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Tracker-protectors.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Tracker-protectors.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/protectors.cc' object='helpers/LibTorrent_Test_Tracker-protectors.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Tracker_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Tracker-protectors.obj `if test -f 'helpers/protectors.cc'; then $(CYGPATH_W) 'helpers/protectors.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/protectors.cc'; fi` helpers/LibTorrent_Test_Tracker-test_fixture.o: helpers/test_fixture.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Tracker_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Tracker-test_fixture.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Tracker-test_fixture.Tpo -c -o helpers/LibTorrent_Test_Tracker-test_fixture.o `test -f 'helpers/test_fixture.cc' || echo '$(srcdir)/'`helpers/test_fixture.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Tracker-test_fixture.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Tracker-test_fixture.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/test_fixture.cc' object='helpers/LibTorrent_Test_Tracker-test_fixture.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Tracker_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Tracker-test_fixture.o `test -f 'helpers/test_fixture.cc' || echo '$(srcdir)/'`helpers/test_fixture.cc helpers/LibTorrent_Test_Tracker-test_fixture.obj: helpers/test_fixture.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Tracker_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Tracker-test_fixture.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Tracker-test_fixture.Tpo -c -o helpers/LibTorrent_Test_Tracker-test_fixture.obj `if test -f 'helpers/test_fixture.cc'; then $(CYGPATH_W) 'helpers/test_fixture.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/test_fixture.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Tracker-test_fixture.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Tracker-test_fixture.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/test_fixture.cc' object='helpers/LibTorrent_Test_Tracker-test_fixture.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Tracker_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Tracker-test_fixture.obj `if test -f 'helpers/test_fixture.cc'; then $(CYGPATH_W) 'helpers/test_fixture.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/test_fixture.cc'; fi` helpers/LibTorrent_Test_Tracker-test_main_thread.o: helpers/test_main_thread.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Tracker_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Tracker-test_main_thread.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Tracker-test_main_thread.Tpo -c -o helpers/LibTorrent_Test_Tracker-test_main_thread.o `test -f 'helpers/test_main_thread.cc' || echo '$(srcdir)/'`helpers/test_main_thread.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Tracker-test_main_thread.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Tracker-test_main_thread.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/test_main_thread.cc' object='helpers/LibTorrent_Test_Tracker-test_main_thread.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Tracker_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Tracker-test_main_thread.o `test -f 'helpers/test_main_thread.cc' || echo '$(srcdir)/'`helpers/test_main_thread.cc helpers/LibTorrent_Test_Tracker-test_main_thread.obj: helpers/test_main_thread.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Tracker_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Tracker-test_main_thread.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Tracker-test_main_thread.Tpo -c -o helpers/LibTorrent_Test_Tracker-test_main_thread.obj `if test -f 'helpers/test_main_thread.cc'; then $(CYGPATH_W) 'helpers/test_main_thread.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/test_main_thread.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Tracker-test_main_thread.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Tracker-test_main_thread.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/test_main_thread.cc' object='helpers/LibTorrent_Test_Tracker-test_main_thread.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Tracker_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Tracker-test_main_thread.obj `if test -f 'helpers/test_main_thread.cc'; then $(CYGPATH_W) 'helpers/test_main_thread.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/test_main_thread.cc'; fi` helpers/LibTorrent_Test_Tracker-test_thread.o: helpers/test_thread.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Tracker_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Tracker-test_thread.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Tracker-test_thread.Tpo -c -o helpers/LibTorrent_Test_Tracker-test_thread.o `test -f 'helpers/test_thread.cc' || echo '$(srcdir)/'`helpers/test_thread.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Tracker-test_thread.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Tracker-test_thread.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/test_thread.cc' object='helpers/LibTorrent_Test_Tracker-test_thread.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Tracker_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Tracker-test_thread.o `test -f 'helpers/test_thread.cc' || echo '$(srcdir)/'`helpers/test_thread.cc helpers/LibTorrent_Test_Tracker-test_thread.obj: helpers/test_thread.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Tracker_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Tracker-test_thread.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Tracker-test_thread.Tpo -c -o helpers/LibTorrent_Test_Tracker-test_thread.obj `if test -f 'helpers/test_thread.cc'; then $(CYGPATH_W) 'helpers/test_thread.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/test_thread.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Tracker-test_thread.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Tracker-test_thread.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/test_thread.cc' object='helpers/LibTorrent_Test_Tracker-test_thread.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Tracker_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Tracker-test_thread.obj `if test -f 'helpers/test_thread.cc'; then $(CYGPATH_W) 'helpers/test_thread.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/test_thread.cc'; fi` helpers/LibTorrent_Test_Tracker-tracker_test.o: helpers/tracker_test.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Tracker_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Tracker-tracker_test.o -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Tracker-tracker_test.Tpo -c -o helpers/LibTorrent_Test_Tracker-tracker_test.o `test -f 'helpers/tracker_test.cc' || echo '$(srcdir)/'`helpers/tracker_test.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Tracker-tracker_test.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Tracker-tracker_test.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/tracker_test.cc' object='helpers/LibTorrent_Test_Tracker-tracker_test.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Tracker_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Tracker-tracker_test.o `test -f 'helpers/tracker_test.cc' || echo '$(srcdir)/'`helpers/tracker_test.cc helpers/LibTorrent_Test_Tracker-tracker_test.obj: helpers/tracker_test.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Tracker_CXXFLAGS) $(CXXFLAGS) -MT helpers/LibTorrent_Test_Tracker-tracker_test.obj -MD -MP -MF helpers/$(DEPDIR)/LibTorrent_Test_Tracker-tracker_test.Tpo -c -o helpers/LibTorrent_Test_Tracker-tracker_test.obj `if test -f 'helpers/tracker_test.cc'; then $(CYGPATH_W) 'helpers/tracker_test.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/tracker_test.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) helpers/$(DEPDIR)/LibTorrent_Test_Tracker-tracker_test.Tpo helpers/$(DEPDIR)/LibTorrent_Test_Tracker-tracker_test.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='helpers/tracker_test.cc' object='helpers/LibTorrent_Test_Tracker-tracker_test.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Tracker_CXXFLAGS) $(CXXFLAGS) -c -o helpers/LibTorrent_Test_Tracker-tracker_test.obj `if test -f 'helpers/tracker_test.cc'; then $(CYGPATH_W) 'helpers/tracker_test.cc'; else $(CYGPATH_W) '$(srcdir)/helpers/tracker_test.cc'; fi` tracker/LibTorrent_Test_Tracker-test_tracker_http.o: tracker/test_tracker_http.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Tracker_CXXFLAGS) $(CXXFLAGS) -MT tracker/LibTorrent_Test_Tracker-test_tracker_http.o -MD -MP -MF tracker/$(DEPDIR)/LibTorrent_Test_Tracker-test_tracker_http.Tpo -c -o tracker/LibTorrent_Test_Tracker-test_tracker_http.o `test -f 'tracker/test_tracker_http.cc' || echo '$(srcdir)/'`tracker/test_tracker_http.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) tracker/$(DEPDIR)/LibTorrent_Test_Tracker-test_tracker_http.Tpo tracker/$(DEPDIR)/LibTorrent_Test_Tracker-test_tracker_http.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tracker/test_tracker_http.cc' object='tracker/LibTorrent_Test_Tracker-test_tracker_http.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Tracker_CXXFLAGS) $(CXXFLAGS) -c -o tracker/LibTorrent_Test_Tracker-test_tracker_http.o `test -f 'tracker/test_tracker_http.cc' || echo '$(srcdir)/'`tracker/test_tracker_http.cc tracker/LibTorrent_Test_Tracker-test_tracker_http.obj: tracker/test_tracker_http.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Tracker_CXXFLAGS) $(CXXFLAGS) -MT tracker/LibTorrent_Test_Tracker-test_tracker_http.obj -MD -MP -MF tracker/$(DEPDIR)/LibTorrent_Test_Tracker-test_tracker_http.Tpo -c -o tracker/LibTorrent_Test_Tracker-test_tracker_http.obj `if test -f 'tracker/test_tracker_http.cc'; then $(CYGPATH_W) 'tracker/test_tracker_http.cc'; else $(CYGPATH_W) '$(srcdir)/tracker/test_tracker_http.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) tracker/$(DEPDIR)/LibTorrent_Test_Tracker-test_tracker_http.Tpo tracker/$(DEPDIR)/LibTorrent_Test_Tracker-test_tracker_http.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tracker/test_tracker_http.cc' object='tracker/LibTorrent_Test_Tracker-test_tracker_http.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(LibTorrent_Test_Tracker_CXXFLAGS) $(CXXFLAGS) -c -o tracker/LibTorrent_Test_Tracker-test_tracker_http.obj `if test -f 'tracker/test_tracker_http.cc'; then $(CYGPATH_W) 'tracker/test_tracker_http.cc'; else $(CYGPATH_W) '$(srcdir)/tracker/test_tracker_http.cc'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags check-TESTS: $(TESTS) @failed=0; all=0; xfail=0; xpass=0; skip=0; \ srcdir=$(srcdir); export srcdir; \ list=' $(TESTS) '; \ $(am__tty_colors); \ if test -n "$$list"; then \ for tst in $$list; do \ if test -f ./$$tst; then dir=./; \ elif test -f $$tst; then dir=; \ else dir="$(srcdir)/"; fi; \ if $(TESTS_ENVIRONMENT) $${dir}$$tst $(AM_TESTS_FD_REDIRECT); then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$tst[\ \ ]*) \ xpass=`expr $$xpass + 1`; \ failed=`expr $$failed + 1`; \ col=$$red; res=XPASS; \ ;; \ *) \ col=$$grn; res=PASS; \ ;; \ esac; \ elif test $$? -ne 77; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$tst[\ \ ]*) \ xfail=`expr $$xfail + 1`; \ col=$$lgn; res=XFAIL; \ ;; \ *) \ failed=`expr $$failed + 1`; \ col=$$red; res=FAIL; \ ;; \ esac; \ else \ skip=`expr $$skip + 1`; \ col=$$blu; res=SKIP; \ fi; \ echo "$${col}$$res$${std}: $$tst"; \ done; \ if test "$$all" -eq 1; then \ tests="test"; \ All=""; \ else \ tests="tests"; \ All="All "; \ fi; \ if test "$$failed" -eq 0; then \ if test "$$xfail" -eq 0; then \ banner="$$All$$all $$tests passed"; \ else \ if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ fi; \ else \ if test "$$xpass" -eq 0; then \ banner="$$failed of $$all $$tests failed"; \ else \ if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ fi; \ fi; \ dashes="$$banner"; \ skipped=""; \ if test "$$skip" -ne 0; then \ if test "$$skip" -eq 1; then \ skipped="($$skip test was not run)"; \ else \ skipped="($$skip tests were not run)"; \ fi; \ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$skipped"; \ fi; \ report=""; \ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ report="Please report to $(PACKAGE_BUGREPORT)"; \ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$report"; \ fi; \ dashes=`echo "$$dashes" | sed s/./=/g`; \ if test "$$failed" -eq 0; then \ col="$$grn"; \ else \ col="$$red"; \ fi; \ echo "$${col}$$dashes$${std}"; \ echo "$${col}$$banner$${std}"; \ test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \ test -z "$$report" || echo "$${col}$$report$${std}"; \ echo "$${col}$$dashes$${std}"; \ test "$$failed" -eq 0; \ else :; fi distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -$(am__rm_f) $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || $(am__rm_f) $(CONFIG_CLEAN_VPATH_FILES) -$(am__rm_f) data/$(DEPDIR)/$(am__dirstamp) -$(am__rm_f) data/$(am__dirstamp) -$(am__rm_f) helpers/$(DEPDIR)/$(am__dirstamp) -$(am__rm_f) helpers/$(am__dirstamp) -$(am__rm_f) protocol/$(DEPDIR)/$(am__dirstamp) -$(am__rm_f) protocol/$(am__dirstamp) -$(am__rm_f) rak/$(DEPDIR)/$(am__dirstamp) -$(am__rm_f) rak/$(am__dirstamp) -$(am__rm_f) torrent/$(DEPDIR)/$(am__dirstamp) -$(am__rm_f) torrent/$(am__dirstamp) -$(am__rm_f) torrent/net/$(DEPDIR)/$(am__dirstamp) -$(am__rm_f) torrent/net/$(am__dirstamp) -$(am__rm_f) torrent/utils/$(DEPDIR)/$(am__dirstamp) -$(am__rm_f) torrent/utils/$(am__dirstamp) -$(am__rm_f) tracker/$(DEPDIR)/$(am__dirstamp) -$(am__rm_f) tracker/$(am__dirstamp) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libtool \ mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/LibTorrent_Test-main.Po -rm -f ./$(DEPDIR)/LibTorrent_Test_Data-main.Po -rm -f ./$(DEPDIR)/LibTorrent_Test_Net-main.Po -rm -f ./$(DEPDIR)/LibTorrent_Test_Torrent-main.Po -rm -f ./$(DEPDIR)/LibTorrent_Test_Torrent_Net-main.Po -rm -f ./$(DEPDIR)/LibTorrent_Test_Torrent_Utils-main.Po -rm -f ./$(DEPDIR)/LibTorrent_Test_Tracker-main.Po -rm -f data/$(DEPDIR)/LibTorrent_Test_Data-test_chunk_list.Po -rm -f data/$(DEPDIR)/LibTorrent_Test_Data-test_hash_check_queue.Po -rm -f data/$(DEPDIR)/LibTorrent_Test_Data-test_hash_queue.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test-mock_function.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test-network.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test-progress_listener.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test-protectors.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test-test_fixture.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test-test_main_thread.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test-test_thread.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test-tracker_test.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Data-mock_function.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Data-network.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Data-progress_listener.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Data-protectors.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Data-test_fixture.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Data-test_main_thread.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Data-test_thread.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Data-tracker_test.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Net-mock_function.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Net-network.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Net-progress_listener.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Net-protectors.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Net-test_fixture.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Net-test_main_thread.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Net-test_thread.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Net-tracker_test.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent-mock_function.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent-network.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent-progress_listener.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent-protectors.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent-test_fixture.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent-test_main_thread.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent-test_thread.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent-tracker_test.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-mock_function.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-network.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-progress_listener.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-protectors.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_fixture.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_main_thread.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_thread.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-tracker_test.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-mock_function.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-network.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-progress_listener.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-protectors.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_fixture.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_main_thread.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_thread.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-tracker_test.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Tracker-mock_function.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Tracker-network.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Tracker-progress_listener.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Tracker-protectors.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Tracker-test_fixture.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Tracker-test_main_thread.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Tracker-test_thread.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Tracker-tracker_test.Po -rm -f protocol/$(DEPDIR)/LibTorrent_Test-test_request_list.Po -rm -f rak/$(DEPDIR)/LibTorrent_Test-ranges_test.Po -rm -f torrent/$(DEPDIR)/LibTorrent_Test_Torrent-object_static_map_test.Po -rm -f torrent/$(DEPDIR)/LibTorrent_Test_Torrent-object_stream_test.Po -rm -f torrent/$(DEPDIR)/LibTorrent_Test_Torrent-object_test.Po -rm -f torrent/$(DEPDIR)/LibTorrent_Test_Torrent-object_test_utils.Po -rm -f torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_controller.Po -rm -f torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_controller_features.Po -rm -f torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_controller_requesting.Po -rm -f torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_list.Po -rm -f torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_list_features.Po -rm -f torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_timeout.Po -rm -f torrent/net/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_address_info.Po -rm -f torrent/net/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_fd.Po -rm -f torrent/net/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_socket_address.Po -rm -f torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_extents.Po -rm -f torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_log.Po -rm -f torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_log_buffer.Po -rm -f torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_option_strings.Po -rm -f torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_queue_buckets.Po -rm -f torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_signal_bitfield.Po -rm -f torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_signal_interrupt.Po -rm -f torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_thread_base.Po -rm -f torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_uri_parser.Po -rm -f tracker/$(DEPDIR)/LibTorrent_Test_Tracker-test_tracker_http.Po -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/LibTorrent_Test-main.Po -rm -f ./$(DEPDIR)/LibTorrent_Test_Data-main.Po -rm -f ./$(DEPDIR)/LibTorrent_Test_Net-main.Po -rm -f ./$(DEPDIR)/LibTorrent_Test_Torrent-main.Po -rm -f ./$(DEPDIR)/LibTorrent_Test_Torrent_Net-main.Po -rm -f ./$(DEPDIR)/LibTorrent_Test_Torrent_Utils-main.Po -rm -f ./$(DEPDIR)/LibTorrent_Test_Tracker-main.Po -rm -f data/$(DEPDIR)/LibTorrent_Test_Data-test_chunk_list.Po -rm -f data/$(DEPDIR)/LibTorrent_Test_Data-test_hash_check_queue.Po -rm -f data/$(DEPDIR)/LibTorrent_Test_Data-test_hash_queue.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test-mock_function.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test-network.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test-progress_listener.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test-protectors.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test-test_fixture.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test-test_main_thread.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test-test_thread.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test-tracker_test.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Data-mock_function.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Data-network.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Data-progress_listener.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Data-protectors.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Data-test_fixture.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Data-test_main_thread.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Data-test_thread.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Data-tracker_test.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Net-mock_function.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Net-network.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Net-progress_listener.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Net-protectors.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Net-test_fixture.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Net-test_main_thread.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Net-test_thread.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Net-tracker_test.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent-mock_function.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent-network.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent-progress_listener.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent-protectors.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent-test_fixture.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent-test_main_thread.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent-test_thread.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent-tracker_test.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-mock_function.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-network.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-progress_listener.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-protectors.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_fixture.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_main_thread.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_thread.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Net-tracker_test.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-mock_function.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-network.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-progress_listener.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-protectors.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_fixture.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_main_thread.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_thread.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-tracker_test.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Tracker-mock_function.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Tracker-network.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Tracker-progress_listener.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Tracker-protectors.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Tracker-test_fixture.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Tracker-test_main_thread.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Tracker-test_thread.Po -rm -f helpers/$(DEPDIR)/LibTorrent_Test_Tracker-tracker_test.Po -rm -f protocol/$(DEPDIR)/LibTorrent_Test-test_request_list.Po -rm -f rak/$(DEPDIR)/LibTorrent_Test-ranges_test.Po -rm -f torrent/$(DEPDIR)/LibTorrent_Test_Torrent-object_static_map_test.Po -rm -f torrent/$(DEPDIR)/LibTorrent_Test_Torrent-object_stream_test.Po -rm -f torrent/$(DEPDIR)/LibTorrent_Test_Torrent-object_test.Po -rm -f torrent/$(DEPDIR)/LibTorrent_Test_Torrent-object_test_utils.Po -rm -f torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_controller.Po -rm -f torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_controller_features.Po -rm -f torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_controller_requesting.Po -rm -f torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_list.Po -rm -f torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_list_features.Po -rm -f torrent/$(DEPDIR)/LibTorrent_Test_Torrent-test_tracker_timeout.Po -rm -f torrent/net/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_address_info.Po -rm -f torrent/net/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_fd.Po -rm -f torrent/net/$(DEPDIR)/LibTorrent_Test_Torrent_Net-test_socket_address.Po -rm -f torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_extents.Po -rm -f torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_log.Po -rm -f torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_log_buffer.Po -rm -f torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_option_strings.Po -rm -f torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_queue_buckets.Po -rm -f torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_signal_bitfield.Po -rm -f torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_signal_interrupt.Po -rm -f torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_thread_base.Po -rm -f torrent/utils/$(DEPDIR)/LibTorrent_Test_Torrent_Utils-test_uri_parser.Po -rm -f tracker/$(DEPDIR)/LibTorrent_Test_Tracker-test_tracker_http.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-TESTS \ check-am clean clean-checkPROGRAMS clean-generic clean-libtool \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: # Tell GNU make to disable its built-in pattern rules. %:: %,v %:: RCS/%,v %:: RCS/% %:: s.% %:: SCCS/s.% libtorrent-0.16.11/test/tracker/0000755000000000000000000000000015175073435012177 5libtorrent-0.16.11/test/tracker/test_tracker_http.h0000644000000000000000000000037115175073411016014 #include "helpers/test_fixture.h" #include "torrent/system/thread.h" class test_tracker_http : public test_fixture { CPPUNIT_TEST_SUITE(test_tracker_http); CPPUNIT_TEST(test_basic); CPPUNIT_TEST_SUITE_END(); public: void test_basic(); }; libtorrent-0.16.11/test/tracker/test_tracker_http.cc0000644000000000000000000000030715175073411016151 #include "config.h" #include "test_tracker_http.h" #include "tracker/tracker_http.h" CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(test_tracker_http, "tracker"); void test_tracker_http::test_basic() { } libtorrent-0.16.11/test/main.cc0000644000000000000000000000513115175073411011711 #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_BACKTRACE #include #endif #include "helpers/progress_listener.h" #include "helpers/protectors.h" #include "helpers/utils.h" CPPUNIT_REGISTRY_ADD_TO_DEFAULT("torrent/net"); CPPUNIT_REGISTRY_ADD_TO_DEFAULT("torrent/utils"); CPPUNIT_REGISTRY_ADD_TO_DEFAULT("torrent"); CPPUNIT_REGISTRY_ADD_TO_DEFAULT("data"); CPPUNIT_REGISTRY_ADD_TO_DEFAULT("net"); CPPUNIT_REGISTRY_ADD_TO_DEFAULT("tracker"); namespace { void do_test_panic(int signum) { signal(signum, SIG_DFL); std::cout << std::endl << std::endl << "Caught " << strsignal(signum) << ", dumping stack:" << std::endl << std::endl; #ifdef HAVE_BACKTRACE void* stackPtrs[20]; // Print the stack and exit. int stackSize = backtrace(stackPtrs, 20); char** stackStrings = backtrace_symbols(stackPtrs, stackSize); for (int i = 0; i < stackSize; ++i) std::cout << stackStrings[i] << std::endl; #else std::cout << "Stack dump not enabled." << std::endl; #endif std::cout << std::endl; torrent::log_cleanup(); std::abort(); } void register_signal_handlers() { struct sigaction sa; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; sa.sa_handler = &do_test_panic; if (sigaction(SIGSEGV, &sa, NULL) == -1) { std::cout << "Could not register signal handlers." << std::endl; exit(-1); } } } // namespace int main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[]) { register_signal_handlers(); CppUnit::TestResult controller; CppUnit::TestResultCollector result; progress_listener progress; controller.addListener(&result); controller.addListener(&progress); controller.popProtector(); controller.pushProtector(new ExceptionProtector()); CppUnit::TextUi::TestRunner runner; add_tests(runner, std::getenv("TEST_NAME")); try { std::cout << "Running "; runner.run( controller ); // TODO: Make outputter. dump_failures(progress.failures()); // Print test in a compiler compatible format. CppUnit::CompilerOutputter outputter( &result, std::cerr ); outputter.write(); } catch (const std::invalid_argument& e) { // Test path not resolved std::cerr << std::endl << "ERROR: " << e.what() << std::endl; return 1; } return result.wasSuccessful() ? 0 : 1; } libtorrent-0.16.11/test/data/0000755000000000000000000000000015175073435011455 5libtorrent-0.16.11/test/data/test_hash_queue.cc0000644000000000000000000001124615175073411015070 #include "config.h" #include "test_hash_queue.h" #include #include "data/hash_queue.h" #include "data/hash_queue_node.h" #include "torrent/chunk_manager.h" #include "torrent/exceptions.h" #include "torrent/hash_string.h" #include "data/thread_disk.h" #include "test_chunk_list.h" #include "test_hash_check_queue.h" #include "helpers/test_thread.h" #include "helpers/test_utils.h" CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(test_hash_queue, "data"); typedef std::map done_chunks_type; namespace { void chunk_done(torrent::ChunkList* chunk_list, done_chunks_type* done_chunks, torrent::ChunkHandle handle, const char* hash_value) { if (hash_value != NULL) (*done_chunks)[handle.index()] = *torrent::HashString::cast_from(hash_value); chunk_list->release(&handle, torrent::ChunkList::release_default); } bool check_for_chunk_done(torrent::HashQueue* hash_queue, done_chunks_type* done_chunks, int index) { hash_queue->work(); return done_chunks->find(index) != done_chunks->end(); } void fill_queue() { } } // namespace #define SETUP_HASH_QUEUE() \ done_chunks_type done_chunks; \ auto hash_queue = new torrent::HashQueue(); \ hash_queue->slot_has_work() = std::bind(&fill_queue); \ \ torrent::thread_disk()->hash_check_queue()->slot_chunk_done() = [&](auto hc, const auto& hv) { \ hash_queue->chunk_done(hc, hv); \ }; void test_hash_queue::test_single() { SETUP_CHUNK_LIST(); SETUP_HASH_QUEUE(); torrent::ChunkHandle handle_0 = chunk_list->get(0, torrent::ChunkList::get_not_hashing | torrent::ChunkList::get_blocking); hash_queue->push_back(handle_0, NULL, std::bind(&chunk_done, chunk_list, &done_chunks, std::placeholders::_1, std::placeholders::_2)); CPPUNIT_ASSERT(hash_queue->size() == 1); CPPUNIT_ASSERT(hash_queue->front().handle().is_blocking()); CPPUNIT_ASSERT(hash_queue->front().handle().object() == &((*chunk_list)[0])); hash_queue->work(); CPPUNIT_ASSERT(wait_for_true(std::bind(&check_for_chunk_done, hash_queue, &done_chunks, 0))); CPPUNIT_ASSERT(done_chunks[0] == hash_for_index(0)); // chunk_list->release(&handle_0); CPPUNIT_ASSERT(torrent::thread_disk()->hash_check_queue()->empty()); delete hash_queue; CLEANUP_CHUNK_LIST(); } void test_hash_queue::test_multiple() { SETUP_CHUNK_LIST(); SETUP_HASH_QUEUE(); for (unsigned int i = 0; i < 20; i++) { hash_queue->push_back(chunk_list->get(i, torrent::ChunkList::get_not_hashing | torrent::ChunkList::get_blocking), NULL, std::bind(&chunk_done, chunk_list, &done_chunks, std::placeholders::_1, std::placeholders::_2)); CPPUNIT_ASSERT(hash_queue->size() == i + 1); CPPUNIT_ASSERT(hash_queue->back().handle().is_blocking()); CPPUNIT_ASSERT(hash_queue->back().handle().object() == &((*chunk_list)[i])); } for (unsigned int i = 0; i < 20; i++) { CPPUNIT_ASSERT(wait_for_true(std::bind(&check_for_chunk_done, hash_queue, &done_chunks, i))); CPPUNIT_ASSERT(done_chunks[i] == hash_for_index(i)); } CPPUNIT_ASSERT(torrent::thread_disk()->hash_check_queue()->empty()); delete hash_queue; CLEANUP_CHUNK_LIST(); } void test_hash_queue::test_erase() { SETUP_CHUNK_LIST(); SETUP_HASH_QUEUE(); for (unsigned int i = 0; i < 20; i++) { hash_queue->push_back(chunk_list->get(i, torrent::ChunkList::get_not_hashing | torrent::ChunkList::get_blocking), NULL, std::bind(&chunk_done, chunk_list, &done_chunks, std::placeholders::_1, std::placeholders::_2)); CPPUNIT_ASSERT(hash_queue->size() == i + 1); } hash_queue->remove(NULL); CPPUNIT_ASSERT(hash_queue->empty()); CPPUNIT_ASSERT(torrent::thread_disk()->hash_check_queue()->empty()); delete hash_queue; CLEANUP_CHUNK_LIST(); } void test_hash_queue::test_erase_stress() { SETUP_CHUNK_LIST(); SETUP_HASH_QUEUE(); for (unsigned int i = 0; i < 1000; i++) { for (unsigned int i = 0; i < 20; i++) { hash_queue->push_back(chunk_list->get(i, torrent::ChunkList::get_not_hashing | torrent::ChunkList::get_blocking), NULL, std::bind(&chunk_done, chunk_list, &done_chunks, std::placeholders::_1, std::placeholders::_2)); CPPUNIT_ASSERT(hash_queue->size() == i + 1); } hash_queue->remove(NULL); CPPUNIT_ASSERT(hash_queue->empty()); } CPPUNIT_ASSERT(torrent::thread_disk()->hash_check_queue()->empty()); delete hash_queue; CLEANUP_CHUNK_LIST(); } // Test erase of different id's. // Current code doesn't work well if we remove a hash... libtorrent-0.16.11/test/data/test_hash_check_queue.cc0000644000000000000000000001311115175073411016216 #include "config.h" #include "test_hash_check_queue.h" #include "helpers/test_thread.h" #include "helpers/test_utils.h" #include #include #include "data/chunk_handle.h" #include "data/thread_disk.h" #include "utils/sha1.h" #include "torrent/chunk_manager.h" #include "torrent/exceptions.h" #include "test_chunk_list.h" CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(test_hash_check_queue, "data"); namespace { pthread_mutex_t done_chunks_lock = PTHREAD_MUTEX_INITIALIZER; void chunk_done(done_chunks_type* done_chunks, torrent::HashChunk* hash_chunk, const torrent::HashString& hash_value) { pthread_mutex_lock(&done_chunks_lock); (*done_chunks)[hash_chunk->handle().index()] = hash_value; pthread_mutex_unlock(&done_chunks_lock); } } // namespace torrent::HashString hash_for_index(uint32_t index) { char buffer[10]; std::memset(buffer, index, 10); torrent::Sha1 sha1; torrent::HashString hash; sha1.init(); sha1.update(buffer, 10); sha1.final_c(hash.data()); return hash; } bool verify_hash(const done_chunks_type* done_chunks, int index, const torrent::HashString& hash) { pthread_mutex_lock(&done_chunks_lock); done_chunks_type::const_iterator itr = done_chunks->find(index); if (itr == done_chunks->end()) { pthread_mutex_unlock(&done_chunks_lock); return false; } bool matches = itr->second == hash; pthread_mutex_unlock(&done_chunks_lock); if (!matches) { // std::cout << "chunk compare: " << index << " " // << torrent::hash_string_to_hex_str(itr->second) << ' ' << torrent::hash_string_to_hex_str(hash) << ' ' // << (itr != done_chunks->end() && itr->second == hash) // << std::endl; throw torrent::internal_error("Could not verify hash..."); } return true; } void test_hash_check_queue::test_single() { SETUP_CHUNK_LIST(); torrent::HashCheckQueue hash_queue; done_chunks_type done_chunks; hash_queue.slot_chunk_done() = std::bind(&chunk_done, &done_chunks, std::placeholders::_1, std::placeholders::_2); torrent::ChunkHandle handle_0 = chunk_list->get(0, torrent::ChunkList::get_not_hashing | torrent::ChunkList::get_blocking); hash_queue.push_back(new torrent::HashChunk(handle_0)); CPPUNIT_ASSERT(hash_queue.size() == 1); CPPUNIT_ASSERT(hash_queue.front()->handle().is_blocking()); CPPUNIT_ASSERT(hash_queue.front()->handle().object() == &((*chunk_list)[0])); hash_queue.perform(); CPPUNIT_ASSERT(done_chunks.find(0) != done_chunks.end()); CPPUNIT_ASSERT(done_chunks[0] == hash_for_index(0)); // Should not be needed... Also verify that HashChunk gets deleted. chunk_list->release(&handle_0, torrent::ChunkList::release_default); CLEANUP_CHUNK_LIST(); } void test_hash_check_queue::test_multiple() { SETUP_CHUNK_LIST(); torrent::HashCheckQueue hash_queue; done_chunks_type done_chunks; hash_queue.slot_chunk_done() = std::bind(&chunk_done, &done_chunks, std::placeholders::_1, std::placeholders::_2); handle_list handles; for (unsigned int i = 0; i < 20; i++) { handles.push_back(chunk_list->get(i, torrent::ChunkList::get_not_hashing | torrent::ChunkList::get_blocking)); hash_queue.push_back(new torrent::HashChunk(handles.back())); CPPUNIT_ASSERT(hash_queue.size() == i + 1); CPPUNIT_ASSERT(hash_queue.back()->handle().is_blocking()); CPPUNIT_ASSERT(hash_queue.back()->handle().object() == &((*chunk_list)[i])); } hash_queue.perform(); for (unsigned int i = 0; i < 20; i++) { CPPUNIT_ASSERT(done_chunks.find(i) != done_chunks.end()); CPPUNIT_ASSERT(done_chunks[i] == hash_for_index(i)); // Should not be needed... chunk_list->release(&handles[i], torrent::ChunkList::release_default); } CLEANUP_CHUNK_LIST(); } void test_hash_check_queue::test_erase() { // SETUP_CHUNK_LIST(); // torrent::HashCheckQueue hash_queue; // done_chunks_type done_chunks; // hash_queue.slot_chunk_done() = std::bind(&chunk_done, &done_chunks, std::placeholders::_1, std::placeholders::_2); // handle_list handles; // for (unsigned int i = 0; i < 20; i++) { // handles.push_back(chunk_list->get(i, torrent::ChunkList::get_not_hashing | torrent::ChunkList::get_blocking)); // hash_queue.push_back(new torrent::HashChunk(handles.back())); // CPPUNIT_ASSERT(hash_queue.size() == i + 1); // CPPUNIT_ASSERT(hash_queue.back()->handle().is_blocking()); // CPPUNIT_ASSERT(hash_queue.back()->handle().object() == &((*chunk_list)[i])); // } // hash_queue.perform(); // for (unsigned int i = 0; i < 20; i++) { // CPPUNIT_ASSERT(done_chunks.find(i) != done_chunks.end()); // CPPUNIT_ASSERT(done_chunks[i] == hash_for_index(i)); // // Should not be needed... // chunk_list->release(&handles[i]); // } // CLEANUP_CHUNK_LIST(); } void test_hash_check_queue::test_thread_interrupt() { SETUP_CHUNK_LIST(); torrent::HashCheckQueue* hash_queue = torrent::thread_disk()->hash_check_queue(); done_chunks_type done_chunks; hash_queue->slot_chunk_done() = std::bind(&chunk_done, &done_chunks, std::placeholders::_1, std::placeholders::_2); for (int i = 0; i < 1000; i++) { pthread_mutex_lock(&done_chunks_lock); done_chunks.erase(0); pthread_mutex_unlock(&done_chunks_lock); torrent::ChunkHandle handle_0 = chunk_list->get(0, torrent::ChunkList::get_not_hashing | torrent::ChunkList::get_blocking); hash_queue->push_back(new torrent::HashChunk(handle_0)); torrent::thread_disk()->interrupt(); CPPUNIT_ASSERT(wait_for_true(std::bind(&verify_hash, &done_chunks, 0, hash_for_index(0)))); chunk_list->release(&handle_0, torrent::ChunkList::release_default); } CLEANUP_CHUNK_LIST(); } libtorrent-0.16.11/test/data/test_chunk_list.cc0000644000000000000000000001123215175073411015077 #include "config.h" #include "test_chunk_list.h" #include "torrent/chunk_manager.h" #include "torrent/exceptions.h" CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(test_chunk_list, "data"); torrent::Chunk* func_create_chunk(uint32_t index, [[maybe_unused]] int prot_flags) { // Do proper handling of prot_flags... char* memory_part1 = (char*)mmap(NULL, 10, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); if (memory_part1 == MAP_FAILED) throw torrent::internal_error("func_create_chunk() failed: " + std::string(strerror(errno))); std::memset(memory_part1, index, 10); torrent::Chunk* chunk = new torrent::Chunk(); chunk->push_back(torrent::ChunkPart::MAPPED_MMAP, torrent::MemoryChunk(memory_part1, memory_part1, memory_part1 + 10, torrent::MemoryChunk::prot_read, 0)); if (chunk == NULL) throw torrent::internal_error("func_create_chunk() failed: chunk == NULL."); return chunk; } uint64_t func_free_diskspace([[maybe_unused]] torrent::ChunkList* chunk_list) { return 0; } void func_storage_error([[maybe_unused]] torrent::ChunkList* chunk_list, [[maybe_unused]] const std::string& message) { } void test_chunk_list::test_basic() { torrent::ChunkManager chunk_manager; torrent::ChunkList chunk_list; CPPUNIT_ASSERT(chunk_list.flags() == 0); CPPUNIT_ASSERT(chunk_list.chunk_size() == 0); chunk_list.set_chunk_size(1 << 16); chunk_list.set_manager(&chunk_manager); chunk_list.resize(32); CPPUNIT_ASSERT(chunk_list.size() == 32); CPPUNIT_ASSERT(chunk_list.chunk_size() == (1 << 16)); for (unsigned int i = 0; i < 32; i++) CPPUNIT_ASSERT(chunk_list[i].index() == i); } void test_chunk_list::test_get_release() { SETUP_CHUNK_LIST(); CPPUNIT_ASSERT(!(*chunk_list)[0].is_valid()); torrent::ChunkHandle handle_0 = chunk_list->get(0, torrent::ChunkList::get_not_hashing); CPPUNIT_ASSERT(handle_0.object() != NULL); CPPUNIT_ASSERT(handle_0.object()->index() == 0); CPPUNIT_ASSERT(handle_0.index() == 0); CPPUNIT_ASSERT(!handle_0.is_writable()); CPPUNIT_ASSERT(!handle_0.is_blocking()); CPPUNIT_ASSERT((*chunk_list)[0].is_valid()); CPPUNIT_ASSERT((*chunk_list)[0].references() == 1); CPPUNIT_ASSERT((*chunk_list)[0].writable() == 0); CPPUNIT_ASSERT((*chunk_list)[0].blocking() == 0); chunk_list->release(&handle_0, torrent::ChunkList::release_default); torrent::ChunkHandle handle_1 = chunk_list->get(1, torrent::ChunkList::get_not_hashing | torrent::ChunkList::get_writable); CPPUNIT_ASSERT(handle_1.object() != NULL); CPPUNIT_ASSERT(handle_1.object()->index() == 1); CPPUNIT_ASSERT(handle_1.index() == 1); CPPUNIT_ASSERT(handle_1.is_writable()); CPPUNIT_ASSERT(!handle_1.is_blocking()); CPPUNIT_ASSERT((*chunk_list)[1].is_valid()); CPPUNIT_ASSERT((*chunk_list)[1].references() == 1); CPPUNIT_ASSERT((*chunk_list)[1].writable() == 1); CPPUNIT_ASSERT((*chunk_list)[1].blocking() == 0); chunk_list->release(&handle_1, torrent::ChunkList::release_default); torrent::ChunkHandle handle_2 = chunk_list->get(2, torrent::ChunkList::get_not_hashing | torrent::ChunkList::get_blocking); CPPUNIT_ASSERT(handle_2.object() != NULL); CPPUNIT_ASSERT(handle_2.object()->index() == 2); CPPUNIT_ASSERT(handle_2.index() == 2); CPPUNIT_ASSERT(!handle_2.is_writable()); CPPUNIT_ASSERT(handle_2.is_blocking()); CPPUNIT_ASSERT((*chunk_list)[2].is_valid()); CPPUNIT_ASSERT((*chunk_list)[2].references() == 1); CPPUNIT_ASSERT((*chunk_list)[2].writable() == 0); CPPUNIT_ASSERT((*chunk_list)[2].blocking() == 1); chunk_list->release(&handle_2, torrent::ChunkList::release_default); // Test ro->wr, etc. CLEANUP_CHUNK_LIST(); } // Make sure we can't go into writable when blocking, etc. void test_chunk_list::test_blocking() { SETUP_CHUNK_LIST(); torrent::ChunkHandle handle_0_ro = chunk_list->get(0, torrent::ChunkList::get_not_hashing | torrent::ChunkList::get_blocking); CPPUNIT_ASSERT(handle_0_ro.is_valid()); // Test writable, etc, on blocking without get_nonblock using a // timer on other thread. // torrent::ChunkHandle handle_1 = chunk_list->get(0, torrent::ChunkList::get_writable); torrent::ChunkHandle handle_0_rw = chunk_list->get(0, torrent::ChunkList::get_not_hashing | torrent::ChunkList::get_writable | torrent::ChunkList::get_nonblock); CPPUNIT_ASSERT(!handle_0_rw.is_valid()); CPPUNIT_ASSERT(handle_0_rw.error_number() == EAGAIN); chunk_list->release(&handle_0_ro, torrent::ChunkList::release_default); handle_0_rw = chunk_list->get(0, torrent::ChunkList::get_not_hashing | torrent::ChunkList::get_writable); CPPUNIT_ASSERT(handle_0_rw.is_valid()); chunk_list->release(&handle_0_rw, torrent::ChunkList::release_default); CLEANUP_CHUNK_LIST(); } // TODO: Add tests for get_hashing, etc. libtorrent-0.16.11/test/data/test_hash_queue.h0000644000000000000000000000062515175073411014731 #include "helpers/test_main_thread.h" class test_hash_queue : public TestFixtureWithMainAndDiskThread { CPPUNIT_TEST_SUITE(test_hash_queue); CPPUNIT_TEST(test_single); CPPUNIT_TEST(test_multiple); CPPUNIT_TEST(test_erase); CPPUNIT_TEST(test_erase_stress); CPPUNIT_TEST_SUITE_END(); public: void test_single(); void test_multiple(); void test_erase(); void test_erase_stress(); }; libtorrent-0.16.11/test/data/test_hash_check_queue.h0000644000000000000000000000166315175073411016071 #ifndef TEST_DATA_HASH_CHECK_QUEUE_H #define TEST_DATA_HASH_CHECK_QUEUE_H #include #include #include "data/hash_queue_node.h" #include "data/hash_check_queue.h" #include "helpers/test_main_thread.h" #include "torrent/hash_string.h" class test_hash_check_queue : public TestFixtureWithMainAndDiskThread { CPPUNIT_TEST_SUITE(test_hash_check_queue); CPPUNIT_TEST(test_single); CPPUNIT_TEST(test_multiple); CPPUNIT_TEST(test_erase); CPPUNIT_TEST(test_thread_interrupt); CPPUNIT_TEST_SUITE_END(); public: void test_single(); void test_multiple(); void test_erase(); void test_thread_interrupt(); }; typedef std::map done_chunks_type; typedef std::vector handle_list; torrent::HashString hash_for_index(uint32_t index); bool verify_hash(const done_chunks_type* done_chunks, int index, const torrent::HashString& hash); #endif // TEST_DATA_HASH_CHECK_QUEUE_H libtorrent-0.16.11/test/data/test_chunk_list.h0000644000000000000000000000261215175073411014743 #include "helpers/test_fixture.h" class test_chunk_list : public test_fixture { CPPUNIT_TEST_SUITE(test_chunk_list); CPPUNIT_TEST(test_basic); CPPUNIT_TEST(test_get_release); CPPUNIT_TEST(test_blocking); CPPUNIT_TEST_SUITE_END(); public: void test_basic(); void test_get_release(); void test_blocking(); }; #include "data/chunk_list.h" torrent::Chunk* func_create_chunk(uint32_t index, int prot_flags); uint64_t func_free_diskspace(torrent::ChunkList* chunk_list); void func_storage_error(torrent::ChunkList* chunk_list, const std::string& message); #define SETUP_CHUNK_LIST() \ torrent::ChunkManager* chunk_manager = new torrent::ChunkManager; \ torrent::ChunkList* chunk_list = new torrent::ChunkList; \ chunk_list->set_manager(chunk_manager); \ chunk_list->slot_create_chunk() = std::bind(&func_create_chunk, std::placeholders::_1, std::placeholders::_2); \ chunk_list->slot_free_diskspace() = std::bind(&func_free_diskspace, chunk_list); \ chunk_list->slot_storage_error() = std::bind(&func_storage_error, chunk_list, std::placeholders::_1); \ chunk_list->set_chunk_size(1 << 16); \ chunk_list->resize(32); #define CLEANUP_CHUNK_LIST() \ delete chunk_list; \ delete chunk_manager; libtorrent-0.16.11/ltmain.sh0000644000000000000000000121271715175073420011332 #! /usr/bin/env sh ## DO NOT EDIT - This file generated from ./build-aux/ltmain.in ## by inline-source v2019-02-19.15 # libtool (GNU libtool) 2.4.7 # Provide generalized library-building support services. # Written by Gordon Matzigkeit , 1996 # Copyright (C) 1996-2019, 2021-2022 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . PROGRAM=libtool PACKAGE=libtool VERSION=2.4.7 package_revision=2.4.7 ## ------ ## ## Usage. ## ## ------ ## # Run './libtool --help' for help with using this script from the # command line. ## ------------------------------- ## ## User overridable command paths. ## ## ------------------------------- ## # After configure completes, it has a better idea of some of the # shell tools we need than the defaults used by the functions shared # with bootstrap, so set those here where they can still be over- # ridden by the user, but otherwise take precedence. : ${AUTOCONF="autoconf"} : ${AUTOMAKE="automake"} ## -------------------------- ## ## Source external libraries. ## ## -------------------------- ## # Much of our low-level functionality needs to be sourced from external # libraries, which are installed to $pkgauxdir. # Set a version string for this script. scriptversion=2019-02-19.15; # UTC # General shell script boiler plate, and helper functions. # Written by Gary V. Vaughan, 2004 # This is free software. There is NO warranty; not even for # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # # Copyright (C) 2004-2019, 2021 Bootstrap Authors # # This file is dual licensed under the terms of the MIT license # , and GPL version 2 or later # . You must apply one of # these licenses when using or redistributing this software or any of # the files within it. See the URLs above, or the file `LICENSE` # included in the Bootstrap distribution for the full license texts. # Please report bugs or propose patches to: # ## ------ ## ## Usage. ## ## ------ ## # Evaluate this file near the top of your script to gain access to # the functions and variables defined here: # # . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh # # If you need to override any of the default environment variable # settings, do that before evaluating this file. ## -------------------- ## ## Shell normalisation. ## ## -------------------- ## # Some shells need a little help to be as Bourne compatible as possible. # Before doing anything else, make sure all that help has been provided! DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi # NLS nuisances: We save the old values in case they are required later. _G_user_locale= _G_safe_locale= for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test set = \"\${$_G_var+set}\"; then save_$_G_var=\$$_G_var $_G_var=C export $_G_var _G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\" _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\" fi" done # These NLS vars are set unconditionally (bootstrap issue #24). Unset those # in case the environment reset is needed later and the $save_* variant is not # defined (see the code above). LC_ALL=C LANGUAGE=C export LANGUAGE LC_ALL # Make sure IFS has a sensible default sp=' ' nl=' ' IFS="$sp $nl" # There are apparently some retarded systems that use ';' as a PATH separator! if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # func_unset VAR # -------------- # Portably unset VAR. # In some shells, an 'unset VAR' statement leaves a non-zero return # status if VAR is already unset, which might be problematic if the # statement is used at the end of a function (thus poisoning its return # value) or when 'set -e' is active (causing even a spurious abort of # the script in this case). func_unset () { { eval $1=; (eval unset $1) >/dev/null 2>&1 && eval unset $1 || : ; } } # Make sure CDPATH doesn't cause `cd` commands to output the target dir. func_unset CDPATH # Make sure ${,E,F}GREP behave sanely. func_unset GREP_OPTIONS ## ------------------------- ## ## Locate command utilities. ## ## ------------------------- ## # func_executable_p FILE # ---------------------- # Check that FILE is an executable regular file. func_executable_p () { test -f "$1" && test -x "$1" } # func_path_progs PROGS_LIST CHECK_FUNC [PATH] # -------------------------------------------- # Search for either a program that responds to --version with output # containing "GNU", or else returned by CHECK_FUNC otherwise, by # trying all the directories in PATH with each of the elements of # PROGS_LIST. # # CHECK_FUNC should accept the path to a candidate program, and # set $func_check_prog_result if it truncates its output less than # $_G_path_prog_max characters. func_path_progs () { _G_progs_list=$1 _G_check_func=$2 _G_PATH=${3-"$PATH"} _G_path_prog_max=0 _G_path_prog_found=false _G_save_IFS=$IFS; IFS=${PATH_SEPARATOR-:} for _G_dir in $_G_PATH; do IFS=$_G_save_IFS test -z "$_G_dir" && _G_dir=. for _G_prog_name in $_G_progs_list; do for _exeext in '' .EXE; do _G_path_prog=$_G_dir/$_G_prog_name$_exeext func_executable_p "$_G_path_prog" || continue case `"$_G_path_prog" --version 2>&1` in *GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;; *) $_G_check_func $_G_path_prog func_path_progs_result=$func_check_prog_result ;; esac $_G_path_prog_found && break 3 done done done IFS=$_G_save_IFS test -z "$func_path_progs_result" && { echo "no acceptable sed could be found in \$PATH" >&2 exit 1 } } # We want to be able to use the functions in this file before configure # has figured out where the best binaries are kept, which means we have # to search for them ourselves - except when the results are already set # where we skip the searches. # Unless the user overrides by setting SED, search the path for either GNU # sed, or the sed that truncates its output the least. test -z "$SED" && { _G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ for _G_i in 1 2 3 4 5 6 7; do _G_sed_script=$_G_sed_script$nl$_G_sed_script done echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed _G_sed_script= func_check_prog_sed () { _G_path_prog=$1 _G_count=0 printf 0123456789 >conftest.in while : do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo '' >> conftest.nl "$_G_path_prog" -f conftest.sed conftest.out 2>/dev/null || break diff conftest.out conftest.nl >/dev/null 2>&1 || break _G_count=`expr $_G_count + 1` if test "$_G_count" -gt "$_G_path_prog_max"; then # Best one so far, save it but keep looking for a better one func_check_prog_result=$_G_path_prog _G_path_prog_max=$_G_count fi # 10*(2^10) chars as input seems more than enough test 10 -lt "$_G_count" && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out } func_path_progs "sed gsed" func_check_prog_sed "$PATH:/usr/xpg4/bin" rm -f conftest.sed SED=$func_path_progs_result } # Unless the user overrides by setting GREP, search the path for either GNU # grep, or the grep that truncates its output the least. test -z "$GREP" && { func_check_prog_grep () { _G_path_prog=$1 _G_count=0 _G_path_prog_max=0 printf 0123456789 >conftest.in while : do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo 'GREP' >> conftest.nl "$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' conftest.out 2>/dev/null || break diff conftest.out conftest.nl >/dev/null 2>&1 || break _G_count=`expr $_G_count + 1` if test "$_G_count" -gt "$_G_path_prog_max"; then # Best one so far, save it but keep looking for a better one func_check_prog_result=$_G_path_prog _G_path_prog_max=$_G_count fi # 10*(2^10) chars as input seems more than enough test 10 -lt "$_G_count" && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out } func_path_progs "grep ggrep" func_check_prog_grep "$PATH:/usr/xpg4/bin" GREP=$func_path_progs_result } ## ------------------------------- ## ## User overridable command paths. ## ## ------------------------------- ## # All uppercase variable names are used for environment variables. These # variables can be overridden by the user before calling a script that # uses them if a suitable command of that name is not already available # in the command search PATH. : ${CP="cp -f"} : ${ECHO="printf %s\n"} : ${EGREP="$GREP -E"} : ${FGREP="$GREP -F"} : ${LN_S="ln -s"} : ${MAKE="make"} : ${MKDIR="mkdir"} : ${MV="mv -f"} : ${RM="rm -f"} : ${SHELL="${CONFIG_SHELL-/bin/sh}"} ## -------------------- ## ## Useful sed snippets. ## ## -------------------- ## sed_dirname='s|/[^/]*$||' sed_basename='s|^.*/||' # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. sed_quote_subst='s|\([`"$\\]\)|\\\1|g' # Same as above, but do not quote variable references. sed_double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution that turns a string into a regex matching for the # string literally. sed_make_literal_regex='s|[].[^$\\*\/]|\\&|g' # Sed substitution that converts a w32 file name or path # that contains forward slashes, into one that contains # (escaped) backslashes. A very naive implementation. sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' # Re-'\' parameter expansions in output of sed_double_quote_subst that # were '\'-ed in input to the same. If an odd number of '\' preceded a # '$' in input to sed_double_quote_subst, that '$' was protected from # expansion. Since each input '\' is now two '\'s, look for any number # of runs of four '\'s followed by two '\'s and then a '$'. '\' that '$'. _G_bs='\\' _G_bs2='\\\\' _G_bs4='\\\\\\\\' _G_dollar='\$' sed_double_backslash="\ s/$_G_bs4/&\\ /g s/^$_G_bs2$_G_dollar/$_G_bs&/ s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g s/\n//g" # require_check_ifs_backslash # --------------------------- # Check if we can use backslash as IFS='\' separator, and set # $check_ifs_backshlash_broken to ':' or 'false'. require_check_ifs_backslash=func_require_check_ifs_backslash func_require_check_ifs_backslash () { _G_save_IFS=$IFS IFS='\' _G_check_ifs_backshlash='a\\b' for _G_i in $_G_check_ifs_backshlash do case $_G_i in a) check_ifs_backshlash_broken=false ;; '') break ;; *) check_ifs_backshlash_broken=: break ;; esac done IFS=$_G_save_IFS require_check_ifs_backslash=: } ## ----------------- ## ## Global variables. ## ## ----------------- ## # Except for the global variables explicitly listed below, the following # functions in the '^func_' namespace, and the '^require_' namespace # variables initialised in the 'Resource management' section, sourcing # this file will not pollute your global namespace with anything # else. There's no portable way to scope variables in Bourne shell # though, so actually running these functions will sometimes place # results into a variable named after the function, and often use # temporary variables in the '^_G_' namespace. If you are careful to # avoid using those namespaces casually in your sourcing script, things # should continue to work as you expect. And, of course, you can freely # overwrite any of the functions or variables defined here before # calling anything to customize them. EXIT_SUCCESS=0 EXIT_FAILURE=1 EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. # Allow overriding, eg assuming that you follow the convention of # putting '$debug_cmd' at the start of all your functions, you can get # bash to show function call trace with: # # debug_cmd='eval echo "${FUNCNAME[0]} $*" >&2' bash your-script-name debug_cmd=${debug_cmd-":"} exit_cmd=: # By convention, finish your script with: # # exit $exit_status # # so that you can set exit_status to non-zero if you want to indicate # something went wrong during execution without actually bailing out at # the point of failure. exit_status=$EXIT_SUCCESS # Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh # is ksh but when the shell is invoked as "sh" and the current value of # the _XPG environment variable is not equal to 1 (one), the special # positional parameter $0, within a function call, is the name of the # function. progpath=$0 # The name of this program. progname=`$ECHO "$progpath" |$SED "$sed_basename"` # Make sure we have an absolute progpath for reexecution: case $progpath in [\\/]*|[A-Za-z]:\\*) ;; *[\\/]*) progdir=`$ECHO "$progpath" |$SED "$sed_dirname"` progdir=`cd "$progdir" && pwd` progpath=$progdir/$progname ;; *) _G_IFS=$IFS IFS=${PATH_SEPARATOR-:} for progdir in $PATH; do IFS=$_G_IFS test -x "$progdir/$progname" && break done IFS=$_G_IFS test -n "$progdir" || progdir=`pwd` progpath=$progdir/$progname ;; esac ## ----------------- ## ## Standard options. ## ## ----------------- ## # The following options affect the operation of the functions defined # below, and should be set appropriately depending on run-time para- # meters passed on the command line. opt_dry_run=false opt_quiet=false opt_verbose=false # Categories 'all' and 'none' are always available. Append any others # you will pass as the first argument to func_warning from your own # code. warning_categories= # By default, display warnings according to 'opt_warning_types'. Set # 'warning_func' to ':' to elide all warnings, or func_fatal_error to # treat the next displayed warning as a fatal error. warning_func=func_warn_and_continue # Set to 'all' to display all warnings, 'none' to suppress all # warnings, or a space delimited list of some subset of # 'warning_categories' to display only the listed warnings. opt_warning_types=all ## -------------------- ## ## Resource management. ## ## -------------------- ## # This section contains definitions for functions that each ensure a # particular resource (a file, or a non-empty configuration variable for # example) is available, and if appropriate to extract default values # from pertinent package files. Call them using their associated # 'require_*' variable to ensure that they are executed, at most, once. # # It's entirely deliberate that calling these functions can set # variables that don't obey the namespace limitations obeyed by the rest # of this file, in order that that they be as useful as possible to # callers. # require_term_colors # ------------------- # Allow display of bold text on terminals that support it. require_term_colors=func_require_term_colors func_require_term_colors () { $debug_cmd test -t 1 && { # COLORTERM and USE_ANSI_COLORS environment variables take # precedence, because most terminfo databases neglect to describe # whether color sequences are supported. test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"} if test 1 = "$USE_ANSI_COLORS"; then # Standard ANSI escape sequences tc_reset='' tc_bold=''; tc_standout='' tc_red=''; tc_green='' tc_blue=''; tc_cyan='' else # Otherwise trust the terminfo database after all. test -n "`tput sgr0 2>/dev/null`" && { tc_reset=`tput sgr0` test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold` tc_standout=$tc_bold test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso` test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1` test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2` test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4` test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5` } fi } require_term_colors=: } ## ----------------- ## ## Function library. ## ## ----------------- ## # This section contains a variety of useful functions to call in your # scripts. Take note of the portable wrappers for features provided by # some modern shells, which will fall back to slower equivalents on # less featureful shells. # func_append VAR VALUE # --------------------- # Append VALUE onto the existing contents of VAR. # We should try to minimise forks, especially on Windows where they are # unreasonably slow, so skip the feature probes when bash or zsh are # being used: if test set = "${BASH_VERSION+set}${ZSH_VERSION+set}"; then : ${_G_HAVE_ARITH_OP="yes"} : ${_G_HAVE_XSI_OPS="yes"} # The += operator was introduced in bash 3.1 case $BASH_VERSION in [12].* | 3.0 | 3.0*) ;; *) : ${_G_HAVE_PLUSEQ_OP="yes"} ;; esac fi # _G_HAVE_PLUSEQ_OP # Can be empty, in which case the shell is probed, "yes" if += is # useable or anything else if it does not work. test -z "$_G_HAVE_PLUSEQ_OP" \ && (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \ && _G_HAVE_PLUSEQ_OP=yes if test yes = "$_G_HAVE_PLUSEQ_OP" then # This is an XSI compatible shell, allowing a faster implementation... eval 'func_append () { $debug_cmd eval "$1+=\$2" }' else # ...otherwise fall back to using expr, which is often a shell builtin. func_append () { $debug_cmd eval "$1=\$$1\$2" } fi # func_append_quoted VAR VALUE # ---------------------------- # Quote VALUE and append to the end of shell variable VAR, separated # by a space. if test yes = "$_G_HAVE_PLUSEQ_OP"; then eval 'func_append_quoted () { $debug_cmd func_quote_arg pretty "$2" eval "$1+=\\ \$func_quote_arg_result" }' else func_append_quoted () { $debug_cmd func_quote_arg pretty "$2" eval "$1=\$$1\\ \$func_quote_arg_result" } fi # func_append_uniq VAR VALUE # -------------------------- # Append unique VALUE onto the existing contents of VAR, assuming # entries are delimited by the first character of VALUE. For example: # # func_append_uniq options " --another-option option-argument" # # will only append to $options if " --another-option option-argument " # is not already present somewhere in $options already (note spaces at # each end implied by leading space in second argument). func_append_uniq () { $debug_cmd eval _G_current_value='`$ECHO $'$1'`' _G_delim=`expr "$2" : '\(.\)'` case $_G_delim$_G_current_value$_G_delim in *"$2$_G_delim"*) ;; *) func_append "$@" ;; esac } # func_arith TERM... # ------------------ # Set func_arith_result to the result of evaluating TERMs. test -z "$_G_HAVE_ARITH_OP" \ && (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \ && _G_HAVE_ARITH_OP=yes if test yes = "$_G_HAVE_ARITH_OP"; then eval 'func_arith () { $debug_cmd func_arith_result=$(( $* )) }' else func_arith () { $debug_cmd func_arith_result=`expr "$@"` } fi # func_basename FILE # ------------------ # Set func_basename_result to FILE with everything up to and including # the last / stripped. if test yes = "$_G_HAVE_XSI_OPS"; then # If this shell supports suffix pattern removal, then use it to avoid # forking. Hide the definitions single quotes in case the shell chokes # on unsupported syntax... _b='func_basename_result=${1##*/}' _d='case $1 in */*) func_dirname_result=${1%/*}$2 ;; * ) func_dirname_result=$3 ;; esac' else # ...otherwise fall back to using sed. _b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`' _d='func_dirname_result=`$ECHO "$1" |$SED "$sed_dirname"` if test "X$func_dirname_result" = "X$1"; then func_dirname_result=$3 else func_append func_dirname_result "$2" fi' fi eval 'func_basename () { $debug_cmd '"$_b"' }' # func_dirname FILE APPEND NONDIR_REPLACEMENT # ------------------------------------------- # Compute the dirname of FILE. If nonempty, add APPEND to the result, # otherwise set result to NONDIR_REPLACEMENT. eval 'func_dirname () { $debug_cmd '"$_d"' }' # func_dirname_and_basename FILE APPEND NONDIR_REPLACEMENT # -------------------------------------------------------- # Perform func_basename and func_dirname in a single function # call: # dirname: Compute the dirname of FILE. If nonempty, # add APPEND to the result, otherwise set result # to NONDIR_REPLACEMENT. # value returned in "$func_dirname_result" # basename: Compute filename of FILE. # value retuned in "$func_basename_result" # For efficiency, we do not delegate to the functions above but instead # duplicate the functionality here. eval 'func_dirname_and_basename () { $debug_cmd '"$_b"' '"$_d"' }' # func_echo ARG... # ---------------- # Echo program name prefixed message. func_echo () { $debug_cmd _G_message=$* func_echo_IFS=$IFS IFS=$nl for _G_line in $_G_message; do IFS=$func_echo_IFS $ECHO "$progname: $_G_line" done IFS=$func_echo_IFS } # func_echo_all ARG... # -------------------- # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } # func_echo_infix_1 INFIX ARG... # ------------------------------ # Echo program name, followed by INFIX on the first line, with any # additional lines not showing INFIX. func_echo_infix_1 () { $debug_cmd $require_term_colors _G_infix=$1; shift _G_indent=$_G_infix _G_prefix="$progname: $_G_infix: " _G_message=$* # Strip color escape sequences before counting printable length for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan" do test -n "$_G_tc" && { _G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"` _G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"` } done _G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`" " ## exclude from sc_prohibit_nested_quotes func_echo_infix_1_IFS=$IFS IFS=$nl for _G_line in $_G_message; do IFS=$func_echo_infix_1_IFS $ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2 _G_prefix=$_G_indent done IFS=$func_echo_infix_1_IFS } # func_error ARG... # ----------------- # Echo program name prefixed message to standard error. func_error () { $debug_cmd $require_term_colors func_echo_infix_1 " $tc_standout${tc_red}error$tc_reset" "$*" >&2 } # func_fatal_error ARG... # ----------------------- # Echo program name prefixed message to standard error, and exit. func_fatal_error () { $debug_cmd func_error "$*" exit $EXIT_FAILURE } # func_grep EXPRESSION FILENAME # ----------------------------- # Check whether EXPRESSION matches any line of FILENAME, without output. func_grep () { $debug_cmd $GREP "$1" "$2" >/dev/null 2>&1 } # func_len STRING # --------------- # Set func_len_result to the length of STRING. STRING may not # start with a hyphen. test -z "$_G_HAVE_XSI_OPS" \ && (eval 'x=a/b/c; test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ && _G_HAVE_XSI_OPS=yes if test yes = "$_G_HAVE_XSI_OPS"; then eval 'func_len () { $debug_cmd func_len_result=${#1} }' else func_len () { $debug_cmd func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` } fi # func_mkdir_p DIRECTORY-PATH # --------------------------- # Make sure the entire path to DIRECTORY-PATH is available. func_mkdir_p () { $debug_cmd _G_directory_path=$1 _G_dir_list= if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then # Protect directory names starting with '-' case $_G_directory_path in -*) _G_directory_path=./$_G_directory_path ;; esac # While some portion of DIR does not yet exist... while test ! -d "$_G_directory_path"; do # ...make a list in topmost first order. Use a colon delimited # list incase some portion of path contains whitespace. _G_dir_list=$_G_directory_path:$_G_dir_list # If the last portion added has no slash in it, the list is done case $_G_directory_path in */*) ;; *) break ;; esac # ...otherwise throw away the child directory and loop _G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"` done _G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'` func_mkdir_p_IFS=$IFS; IFS=: for _G_dir in $_G_dir_list; do IFS=$func_mkdir_p_IFS # mkdir can fail with a 'File exist' error if two processes # try to create one of the directories concurrently. Don't # stop in that case! $MKDIR "$_G_dir" 2>/dev/null || : done IFS=$func_mkdir_p_IFS # Bail out if we (or some other process) failed to create a directory. test -d "$_G_directory_path" || \ func_fatal_error "Failed to create '$1'" fi } # func_mktempdir [BASENAME] # ------------------------- # Make a temporary directory that won't clash with other running # libtool processes, and avoids race conditions if possible. If # given, BASENAME is the basename for that directory. func_mktempdir () { $debug_cmd _G_template=${TMPDIR-/tmp}/${1-$progname} if test : = "$opt_dry_run"; then # Return a directory name, but don't create it in dry-run mode _G_tmpdir=$_G_template-$$ else # If mktemp works, use that first and foremost _G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null` if test ! -d "$_G_tmpdir"; then # Failing that, at least try and use $RANDOM to avoid a race _G_tmpdir=$_G_template-${RANDOM-0}$$ func_mktempdir_umask=`umask` umask 0077 $MKDIR "$_G_tmpdir" umask $func_mktempdir_umask fi # If we're not in dry-run mode, bomb out on failure test -d "$_G_tmpdir" || \ func_fatal_error "cannot create temporary directory '$_G_tmpdir'" fi $ECHO "$_G_tmpdir" } # func_normal_abspath PATH # ------------------------ # Remove doubled-up and trailing slashes, "." path components, # and cancel out any ".." path components in PATH after making # it an absolute path. func_normal_abspath () { $debug_cmd # These SED scripts presuppose an absolute path with a trailing slash. _G_pathcar='s|^/\([^/]*\).*$|\1|' _G_pathcdr='s|^/[^/]*||' _G_removedotparts=':dotsl s|/\./|/|g t dotsl s|/\.$|/|' _G_collapseslashes='s|/\{1,\}|/|g' _G_finalslash='s|/*$|/|' # Start from root dir and reassemble the path. func_normal_abspath_result= func_normal_abspath_tpath=$1 func_normal_abspath_altnamespace= case $func_normal_abspath_tpath in "") # Empty path, that just means $cwd. func_stripname '' '/' "`pwd`" func_normal_abspath_result=$func_stripname_result return ;; # The next three entries are used to spot a run of precisely # two leading slashes without using negated character classes; # we take advantage of case's first-match behaviour. ///*) # Unusual form of absolute path, do nothing. ;; //*) # Not necessarily an ordinary path; POSIX reserves leading '//' # and for example Cygwin uses it to access remote file shares # over CIFS/SMB, so we conserve a leading double slash if found. func_normal_abspath_altnamespace=/ ;; /*) # Absolute path, do nothing. ;; *) # Relative path, prepend $cwd. func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath ;; esac # Cancel out all the simple stuff to save iterations. We also want # the path to end with a slash for ease of parsing, so make sure # there is one (and only one) here. func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_finalslash"` while :; do # Processed it all yet? if test / = "$func_normal_abspath_tpath"; then # If we ascended to the root using ".." the result may be empty now. if test -z "$func_normal_abspath_result"; then func_normal_abspath_result=/ fi break fi func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$_G_pathcar"` func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$_G_pathcdr"` # Figure out what to do with it case $func_normal_abspath_tcomponent in "") # Trailing empty path component, ignore it. ;; ..) # Parent dir; strip last assembled component from result. func_dirname "$func_normal_abspath_result" func_normal_abspath_result=$func_dirname_result ;; *) # Actual path component, append it. func_append func_normal_abspath_result "/$func_normal_abspath_tcomponent" ;; esac done # Restore leading double-slash if one was found on entry. func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result } # func_notquiet ARG... # -------------------- # Echo program name prefixed message only when not in quiet mode. func_notquiet () { $debug_cmd $opt_quiet || func_echo ${1+"$@"} # A bug in bash halts the script if the last line of a function # fails when set -e is in force, so we need another command to # work around that: : } # func_relative_path SRCDIR DSTDIR # -------------------------------- # Set func_relative_path_result to the relative path from SRCDIR to DSTDIR. func_relative_path () { $debug_cmd func_relative_path_result= func_normal_abspath "$1" func_relative_path_tlibdir=$func_normal_abspath_result func_normal_abspath "$2" func_relative_path_tbindir=$func_normal_abspath_result # Ascend the tree starting from libdir while :; do # check if we have found a prefix of bindir case $func_relative_path_tbindir in $func_relative_path_tlibdir) # found an exact match func_relative_path_tcancelled= break ;; $func_relative_path_tlibdir*) # found a matching prefix func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" func_relative_path_tcancelled=$func_stripname_result if test -z "$func_relative_path_result"; then func_relative_path_result=. fi break ;; *) func_dirname $func_relative_path_tlibdir func_relative_path_tlibdir=$func_dirname_result if test -z "$func_relative_path_tlibdir"; then # Have to descend all the way to the root! func_relative_path_result=../$func_relative_path_result func_relative_path_tcancelled=$func_relative_path_tbindir break fi func_relative_path_result=../$func_relative_path_result ;; esac done # Now calculate path; take care to avoid doubling-up slashes. func_stripname '' '/' "$func_relative_path_result" func_relative_path_result=$func_stripname_result func_stripname '/' '/' "$func_relative_path_tcancelled" if test -n "$func_stripname_result"; then func_append func_relative_path_result "/$func_stripname_result" fi # Normalisation. If bindir is libdir, return '.' else relative path. if test -n "$func_relative_path_result"; then func_stripname './' '' "$func_relative_path_result" func_relative_path_result=$func_stripname_result fi test -n "$func_relative_path_result" || func_relative_path_result=. : } # func_quote_portable EVAL ARG # ---------------------------- # Internal function to portably implement func_quote_arg. Note that we still # keep attention to performance here so we as much as possible try to avoid # calling sed binary (so far O(N) complexity as long as func_append is O(1)). func_quote_portable () { $debug_cmd $require_check_ifs_backslash func_quote_portable_result=$2 # one-time-loop (easy break) while true do if $1; then func_quote_portable_result=`$ECHO "$2" | $SED \ -e "$sed_double_quote_subst" -e "$sed_double_backslash"` break fi # Quote for eval. case $func_quote_portable_result in *[\\\`\"\$]*) # Fallback to sed for $func_check_bs_ifs_broken=:, or when the string # contains the shell wildcard characters. case $check_ifs_backshlash_broken$func_quote_portable_result in :*|*[\[\*\?]*) func_quote_portable_result=`$ECHO "$func_quote_portable_result" \ | $SED "$sed_quote_subst"` break ;; esac func_quote_portable_old_IFS=$IFS for _G_char in '\' '`' '"' '$' do # STATE($1) PREV($2) SEPARATOR($3) set start "" "" func_quote_portable_result=dummy"$_G_char$func_quote_portable_result$_G_char"dummy IFS=$_G_char for _G_part in $func_quote_portable_result do case $1 in quote) func_append func_quote_portable_result "$3$2" set quote "$_G_part" "\\$_G_char" ;; start) set first "" "" func_quote_portable_result= ;; first) set quote "$_G_part" "" ;; esac done done IFS=$func_quote_portable_old_IFS ;; *) ;; esac break done func_quote_portable_unquoted_result=$func_quote_portable_result case $func_quote_portable_result in # double-quote args containing shell metacharacters to delay # word splitting, command substitution and variable expansion # for a subsequent eval. # many bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") func_quote_portable_result=\"$func_quote_portable_result\" ;; esac } # func_quotefast_eval ARG # ----------------------- # Quote one ARG (internal). This is equivalent to 'func_quote_arg eval ARG', # but optimized for speed. Result is stored in $func_quotefast_eval. if test xyes = `(x=; printf -v x %q yes; echo x"$x") 2>/dev/null`; then printf -v _GL_test_printf_tilde %q '~' if test '\~' = "$_GL_test_printf_tilde"; then func_quotefast_eval () { printf -v func_quotefast_eval_result %q "$1" } else # Broken older Bash implementations. Make those faster too if possible. func_quotefast_eval () { case $1 in '~'*) func_quote_portable false "$1" func_quotefast_eval_result=$func_quote_portable_result ;; *) printf -v func_quotefast_eval_result %q "$1" ;; esac } fi else func_quotefast_eval () { func_quote_portable false "$1" func_quotefast_eval_result=$func_quote_portable_result } fi # func_quote_arg MODEs ARG # ------------------------ # Quote one ARG to be evaled later. MODEs argument may contain zero or more # specifiers listed below separated by ',' character. This function returns two # values: # i) func_quote_arg_result # double-quoted (when needed), suitable for a subsequent eval # ii) func_quote_arg_unquoted_result # has all characters that are still active within double # quotes backslashified. Available only if 'unquoted' is specified. # # Available modes: # ---------------- # 'eval' (default) # - escape shell special characters # 'expand' # - the same as 'eval'; but do not quote variable references # 'pretty' # - request aesthetic output, i.e. '"a b"' instead of 'a\ b'. This might # be used later in func_quote to get output like: 'echo "a b"' instead # of 'echo a\ b'. This is slower than default on some shells. # 'unquoted' # - produce also $func_quote_arg_unquoted_result which does not contain # wrapping double-quotes. # # Examples for 'func_quote_arg pretty,unquoted string': # # string | *_result | *_unquoted_result # ------------+-----------------------+------------------- # " | \" | \" # a b | "a b" | a b # "a b" | "\"a b\"" | \"a b\" # * | "*" | * # z="${x-$y}" | "z=\"\${x-\$y}\"" | z=\"\${x-\$y}\" # # Examples for 'func_quote_arg pretty,unquoted,expand string': # # string | *_result | *_unquoted_result # --------------+---------------------+-------------------- # z="${x-$y}" | "z=\"${x-$y}\"" | z=\"${x-$y}\" func_quote_arg () { _G_quote_expand=false case ,$1, in *,expand,*) _G_quote_expand=: ;; esac case ,$1, in *,pretty,*|*,expand,*|*,unquoted,*) func_quote_portable $_G_quote_expand "$2" func_quote_arg_result=$func_quote_portable_result func_quote_arg_unquoted_result=$func_quote_portable_unquoted_result ;; *) # Faster quote-for-eval for some shells. func_quotefast_eval "$2" func_quote_arg_result=$func_quotefast_eval_result ;; esac } # func_quote MODEs ARGs... # ------------------------ # Quote all ARGs to be evaled later and join them into single command. See # func_quote_arg's description for more info. func_quote () { $debug_cmd _G_func_quote_mode=$1 ; shift func_quote_result= while test 0 -lt $#; do func_quote_arg "$_G_func_quote_mode" "$1" if test -n "$func_quote_result"; then func_append func_quote_result " $func_quote_arg_result" else func_append func_quote_result "$func_quote_arg_result" fi shift done } # func_stripname PREFIX SUFFIX NAME # --------------------------------- # strip PREFIX and SUFFIX from NAME, and store in func_stripname_result. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). if test yes = "$_G_HAVE_XSI_OPS"; then eval 'func_stripname () { $debug_cmd # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are # positional parameters, so assign one to ordinary variable first. func_stripname_result=$3 func_stripname_result=${func_stripname_result#"$1"} func_stripname_result=${func_stripname_result%"$2"} }' else func_stripname () { $debug_cmd case $2 in .*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;; *) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;; esac } fi # func_show_eval CMD [FAIL_EXP] # ----------------------------- # Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. func_show_eval () { $debug_cmd _G_cmd=$1 _G_fail_exp=${2-':'} func_quote_arg pretty,expand "$_G_cmd" eval "func_notquiet $func_quote_arg_result" $opt_dry_run || { eval "$_G_cmd" _G_status=$? if test 0 -ne "$_G_status"; then eval "(exit $_G_status); $_G_fail_exp" fi } } # func_show_eval_locale CMD [FAIL_EXP] # ------------------------------------ # Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. Use the saved locale for evaluation. func_show_eval_locale () { $debug_cmd _G_cmd=$1 _G_fail_exp=${2-':'} $opt_quiet || { func_quote_arg expand,pretty "$_G_cmd" eval "func_echo $func_quote_arg_result" } $opt_dry_run || { eval "$_G_user_locale $_G_cmd" _G_status=$? eval "$_G_safe_locale" if test 0 -ne "$_G_status"; then eval "(exit $_G_status); $_G_fail_exp" fi } } # func_tr_sh # ---------- # Turn $1 into a string suitable for a shell variable name. # Result is stored in $func_tr_sh_result. All characters # not in the set a-zA-Z0-9_ are replaced with '_'. Further, # if $1 begins with a digit, a '_' is prepended as well. func_tr_sh () { $debug_cmd case $1 in [0-9]* | *[!a-zA-Z0-9_]*) func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'` ;; * ) func_tr_sh_result=$1 ;; esac } # func_verbose ARG... # ------------------- # Echo program name prefixed message in verbose mode only. func_verbose () { $debug_cmd $opt_verbose && func_echo "$*" : } # func_warn_and_continue ARG... # ----------------------------- # Echo program name prefixed warning message to standard error. func_warn_and_continue () { $debug_cmd $require_term_colors func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2 } # func_warning CATEGORY ARG... # ---------------------------- # Echo program name prefixed warning message to standard error. Warning # messages can be filtered according to CATEGORY, where this function # elides messages where CATEGORY is not listed in the global variable # 'opt_warning_types'. func_warning () { $debug_cmd # CATEGORY must be in the warning_categories list! case " $warning_categories " in *" $1 "*) ;; *) func_internal_error "invalid warning category '$1'" ;; esac _G_category=$1 shift case " $opt_warning_types " in *" $_G_category "*) $warning_func ${1+"$@"} ;; esac } # func_sort_ver VER1 VER2 # ----------------------- # 'sort -V' is not generally available. # Note this deviates from the version comparison in automake # in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a # but this should suffice as we won't be specifying old # version formats or redundant trailing .0 in bootstrap.conf. # If we did want full compatibility then we should probably # use m4_version_compare from autoconf. func_sort_ver () { $debug_cmd printf '%s\n%s\n' "$1" "$2" \ | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n } # func_lt_ver PREV CURR # --------------------- # Return true if PREV and CURR are in the correct order according to # func_sort_ver, otherwise false. Use it like this: # # func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..." func_lt_ver () { $debug_cmd test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q` } # Local variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" # time-stamp-time-zone: "UTC" # End: #! /bin/sh # A portable, pluggable option parser for Bourne shell. # Written by Gary V. Vaughan, 2010 # This is free software. There is NO warranty; not even for # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # # Copyright (C) 2010-2019, 2021 Bootstrap Authors # # This file is dual licensed under the terms of the MIT license # , and GPL version 2 or later # . You must apply one of # these licenses when using or redistributing this software or any of # the files within it. See the URLs above, or the file `LICENSE` # included in the Bootstrap distribution for the full license texts. # Please report bugs or propose patches to: # # Set a version string for this script. scriptversion=2019-02-19.15; # UTC ## ------ ## ## Usage. ## ## ------ ## # This file is a library for parsing options in your shell scripts along # with assorted other useful supporting features that you can make use # of too. # # For the simplest scripts you might need only: # # #!/bin/sh # . relative/path/to/funclib.sh # . relative/path/to/options-parser # scriptversion=1.0 # func_options ${1+"$@"} # eval set dummy "$func_options_result"; shift # ...rest of your script... # # In order for the '--version' option to work, you will need to have a # suitably formatted comment like the one at the top of this file # starting with '# Written by ' and ending with '# Copyright'. # # For '-h' and '--help' to work, you will also need a one line # description of your script's purpose in a comment directly above the # '# Written by ' line, like the one at the top of this file. # # The default options also support '--debug', which will turn on shell # execution tracing (see the comment above debug_cmd below for another # use), and '--verbose' and the func_verbose function to allow your script # to display verbose messages only when your user has specified # '--verbose'. # # After sourcing this file, you can plug in processing for additional # options by amending the variables from the 'Configuration' section # below, and following the instructions in the 'Option parsing' # section further down. ## -------------- ## ## Configuration. ## ## -------------- ## # You should override these variables in your script after sourcing this # file so that they reflect the customisations you have added to the # option parser. # The usage line for option parsing errors and the start of '-h' and # '--help' output messages. You can embed shell variables for delayed # expansion at the time the message is displayed, but you will need to # quote other shell meta-characters carefully to prevent them being # expanded when the contents are evaled. usage='$progpath [OPTION]...' # Short help message in response to '-h' and '--help'. Add to this or # override it after sourcing this library to reflect the full set of # options your script accepts. usage_message="\ --debug enable verbose shell tracing -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] -v, --verbose verbosely report processing --version print version information and exit -h, --help print short or long help message and exit " # Additional text appended to 'usage_message' in response to '--help'. long_help_message=" Warning categories include: 'all' show all warnings 'none' turn off all the warnings 'error' warnings are treated as fatal errors" # Help message printed before fatal option parsing errors. fatal_help="Try '\$progname --help' for more information." ## ------------------------- ## ## Hook function management. ## ## ------------------------- ## # This section contains functions for adding, removing, and running hooks # in the main code. A hook is just a list of function names that can be # run in order later on. # func_hookable FUNC_NAME # ----------------------- # Declare that FUNC_NAME will run hooks added with # 'func_add_hook FUNC_NAME ...'. func_hookable () { $debug_cmd func_append hookable_fns " $1" } # func_add_hook FUNC_NAME HOOK_FUNC # --------------------------------- # Request that FUNC_NAME call HOOK_FUNC before it returns. FUNC_NAME must # first have been declared "hookable" by a call to 'func_hookable'. func_add_hook () { $debug_cmd case " $hookable_fns " in *" $1 "*) ;; *) func_fatal_error "'$1' does not accept hook functions." ;; esac eval func_append ${1}_hooks '" $2"' } # func_remove_hook FUNC_NAME HOOK_FUNC # ------------------------------------ # Remove HOOK_FUNC from the list of hook functions to be called by # FUNC_NAME. func_remove_hook () { $debug_cmd eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`' } # func_propagate_result FUNC_NAME_A FUNC_NAME_B # --------------------------------------------- # If the *_result variable of FUNC_NAME_A _is set_, assign its value to # *_result variable of FUNC_NAME_B. func_propagate_result () { $debug_cmd func_propagate_result_result=: if eval "test \"\${${1}_result+set}\" = set" then eval "${2}_result=\$${1}_result" else func_propagate_result_result=false fi } # func_run_hooks FUNC_NAME [ARG]... # --------------------------------- # Run all hook functions registered to FUNC_NAME. # It's assumed that the list of hook functions contains nothing more # than a whitespace-delimited list of legal shell function names, and # no effort is wasted trying to catch shell meta-characters or preserve # whitespace. func_run_hooks () { $debug_cmd case " $hookable_fns " in *" $1 "*) ;; *) func_fatal_error "'$1' does not support hook functions." ;; esac eval _G_hook_fns=\$$1_hooks; shift for _G_hook in $_G_hook_fns; do func_unset "${_G_hook}_result" eval $_G_hook '${1+"$@"}' func_propagate_result $_G_hook func_run_hooks if $func_propagate_result_result; then eval set dummy "$func_run_hooks_result"; shift fi done } ## --------------- ## ## Option parsing. ## ## --------------- ## # In order to add your own option parsing hooks, you must accept the # full positional parameter list from your hook function. You may remove # or edit any options that you action, and then pass back the remaining # unprocessed options in '_result', escaped # suitably for 'eval'. # # The '_result' variable is automatically unset # before your hook gets called; for best performance, only set the # *_result variable when necessary (i.e. don't call the 'func_quote' # function unnecessarily because it can be an expensive operation on some # machines). # # Like this: # # my_options_prep () # { # $debug_cmd # # # Extend the existing usage message. # usage_message=$usage_message' # -s, --silent don'\''t print informational messages # ' # # No change in '$@' (ignored completely by this hook). Leave # # my_options_prep_result variable intact. # } # func_add_hook func_options_prep my_options_prep # # # my_silent_option () # { # $debug_cmd # # args_changed=false # # # Note that, for efficiency, we parse as many options as we can # # recognise in a loop before passing the remainder back to the # # caller on the first unrecognised argument we encounter. # while test $# -gt 0; do # opt=$1; shift # case $opt in # --silent|-s) opt_silent=: # args_changed=: # ;; # # Separate non-argument short options: # -s*) func_split_short_opt "$_G_opt" # set dummy "$func_split_short_opt_name" \ # "-$func_split_short_opt_arg" ${1+"$@"} # shift # args_changed=: # ;; # *) # Make sure the first unrecognised option "$_G_opt" # # is added back to "$@" in case we need it later, # # if $args_changed was set to 'true'. # set dummy "$_G_opt" ${1+"$@"}; shift; break ;; # esac # done # # # Only call 'func_quote' here if we processed at least one argument. # if $args_changed; then # func_quote eval ${1+"$@"} # my_silent_option_result=$func_quote_result # fi # } # func_add_hook func_parse_options my_silent_option # # # my_option_validation () # { # $debug_cmd # # $opt_silent && $opt_verbose && func_fatal_help "\ # '--silent' and '--verbose' options are mutually exclusive." # } # func_add_hook func_validate_options my_option_validation # # You'll also need to manually amend $usage_message to reflect the extra # options you parse. It's preferable to append if you can, so that # multiple option parsing hooks can be added safely. # func_options_finish [ARG]... # ---------------------------- # Finishing the option parse loop (call 'func_options' hooks ATM). func_options_finish () { $debug_cmd func_run_hooks func_options ${1+"$@"} func_propagate_result func_run_hooks func_options_finish } # func_options [ARG]... # --------------------- # All the functions called inside func_options are hookable. See the # individual implementations for details. func_hookable func_options func_options () { $debug_cmd _G_options_quoted=false for my_func in options_prep parse_options validate_options options_finish do func_unset func_${my_func}_result func_unset func_run_hooks_result eval func_$my_func '${1+"$@"}' func_propagate_result func_$my_func func_options if $func_propagate_result_result; then eval set dummy "$func_options_result"; shift _G_options_quoted=: fi done $_G_options_quoted || { # As we (func_options) are top-level options-parser function and # nobody quoted "$@" for us yet, we need to do it explicitly for # caller. func_quote eval ${1+"$@"} func_options_result=$func_quote_result } } # func_options_prep [ARG]... # -------------------------- # All initialisations required before starting the option parse loop. # Note that when calling hook functions, we pass through the list of # positional parameters. If a hook function modifies that list, and # needs to propagate that back to rest of this script, then the complete # modified list must be put in 'func_run_hooks_result' before returning. func_hookable func_options_prep func_options_prep () { $debug_cmd # Option defaults: opt_verbose=false opt_warning_types= func_run_hooks func_options_prep ${1+"$@"} func_propagate_result func_run_hooks func_options_prep } # func_parse_options [ARG]... # --------------------------- # The main option parsing loop. func_hookable func_parse_options func_parse_options () { $debug_cmd _G_parse_options_requote=false # this just eases exit handling while test $# -gt 0; do # Defer to hook functions for initial option parsing, so they # get priority in the event of reusing an option name. func_run_hooks func_parse_options ${1+"$@"} func_propagate_result func_run_hooks func_parse_options if $func_propagate_result_result; then eval set dummy "$func_parse_options_result"; shift # Even though we may have changed "$@", we passed the "$@" array # down into the hook and it quoted it for us (because we are in # this if-branch). No need to quote it again. _G_parse_options_requote=false fi # Break out of the loop if we already parsed every option. test $# -gt 0 || break # We expect that one of the options parsed in this function matches # and thus we remove _G_opt from "$@" and need to re-quote. _G_match_parse_options=: _G_opt=$1 shift case $_G_opt in --debug|-x) debug_cmd='set -x' func_echo "enabling shell trace mode" >&2 $debug_cmd ;; --no-warnings|--no-warning|--no-warn) set dummy --warnings none ${1+"$@"} shift ;; --warnings|--warning|-W) if test $# = 0 && func_missing_arg $_G_opt; then _G_parse_options_requote=: break fi case " $warning_categories $1" in *" $1 "*) # trailing space prevents matching last $1 above func_append_uniq opt_warning_types " $1" ;; *all) opt_warning_types=$warning_categories ;; *none) opt_warning_types=none warning_func=: ;; *error) opt_warning_types=$warning_categories warning_func=func_fatal_error ;; *) func_fatal_error \ "unsupported warning category: '$1'" ;; esac shift ;; --verbose|-v) opt_verbose=: ;; --version) func_version ;; -\?|-h) func_usage ;; --help) func_help ;; # Separate optargs to long options (plugins may need this): --*=*) func_split_equals "$_G_opt" set dummy "$func_split_equals_lhs" \ "$func_split_equals_rhs" ${1+"$@"} shift ;; # Separate optargs to short options: -W*) func_split_short_opt "$_G_opt" set dummy "$func_split_short_opt_name" \ "$func_split_short_opt_arg" ${1+"$@"} shift ;; # Separate non-argument short options: -\?*|-h*|-v*|-x*) func_split_short_opt "$_G_opt" set dummy "$func_split_short_opt_name" \ "-$func_split_short_opt_arg" ${1+"$@"} shift ;; --) _G_parse_options_requote=: ; break ;; -*) func_fatal_help "unrecognised option: '$_G_opt'" ;; *) set dummy "$_G_opt" ${1+"$@"}; shift _G_match_parse_options=false break ;; esac if $_G_match_parse_options; then _G_parse_options_requote=: fi done if $_G_parse_options_requote; then # save modified positional parameters for caller func_quote eval ${1+"$@"} func_parse_options_result=$func_quote_result fi } # func_validate_options [ARG]... # ------------------------------ # Perform any sanity checks on option settings and/or unconsumed # arguments. func_hookable func_validate_options func_validate_options () { $debug_cmd # Display all warnings if -W was not given. test -n "$opt_warning_types" || opt_warning_types=" $warning_categories" func_run_hooks func_validate_options ${1+"$@"} func_propagate_result func_run_hooks func_validate_options # Bail if the options were screwed! $exit_cmd $EXIT_FAILURE } ## ----------------- ## ## Helper functions. ## ## ----------------- ## # This section contains the helper functions used by the rest of the # hookable option parser framework in ascii-betical order. # func_fatal_help ARG... # ---------------------- # Echo program name prefixed message to standard error, followed by # a help hint, and exit. func_fatal_help () { $debug_cmd eval \$ECHO \""Usage: $usage"\" eval \$ECHO \""$fatal_help"\" func_error ${1+"$@"} exit $EXIT_FAILURE } # func_help # --------- # Echo long help message to standard output and exit. func_help () { $debug_cmd func_usage_message $ECHO "$long_help_message" exit 0 } # func_missing_arg ARGNAME # ------------------------ # Echo program name prefixed message to standard error and set global # exit_cmd. func_missing_arg () { $debug_cmd func_error "Missing argument for '$1'." exit_cmd=exit } # func_split_equals STRING # ------------------------ # Set func_split_equals_lhs and func_split_equals_rhs shell variables # after splitting STRING at the '=' sign. test -z "$_G_HAVE_XSI_OPS" \ && (eval 'x=a/b/c; test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ && _G_HAVE_XSI_OPS=yes if test yes = "$_G_HAVE_XSI_OPS" then # This is an XSI compatible shell, allowing a faster implementation... eval 'func_split_equals () { $debug_cmd func_split_equals_lhs=${1%%=*} func_split_equals_rhs=${1#*=} if test "x$func_split_equals_lhs" = "x$1"; then func_split_equals_rhs= fi }' else # ...otherwise fall back to using expr, which is often a shell builtin. func_split_equals () { $debug_cmd func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'` func_split_equals_rhs= test "x$func_split_equals_lhs=" = "x$1" \ || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'` } fi #func_split_equals # func_split_short_opt SHORTOPT # ----------------------------- # Set func_split_short_opt_name and func_split_short_opt_arg shell # variables after splitting SHORTOPT after the 2nd character. if test yes = "$_G_HAVE_XSI_OPS" then # This is an XSI compatible shell, allowing a faster implementation... eval 'func_split_short_opt () { $debug_cmd func_split_short_opt_arg=${1#??} func_split_short_opt_name=${1%"$func_split_short_opt_arg"} }' else # ...otherwise fall back to using expr, which is often a shell builtin. func_split_short_opt () { $debug_cmd func_split_short_opt_name=`expr "x$1" : 'x\(-.\)'` func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'` } fi #func_split_short_opt # func_usage # ---------- # Echo short help message to standard output and exit. func_usage () { $debug_cmd func_usage_message $ECHO "Run '$progname --help |${PAGER-more}' for full usage" exit 0 } # func_usage_message # ------------------ # Echo short help message to standard output. func_usage_message () { $debug_cmd eval \$ECHO \""Usage: $usage"\" echo $SED -n 's|^# || /^Written by/{ x;p;x } h /^Written by/q' < "$progpath" echo eval \$ECHO \""$usage_message"\" } # func_version # ------------ # Echo version message to standard output and exit. # The version message is extracted from the calling file's header # comments, with leading '# ' stripped: # 1. First display the progname and version # 2. Followed by the header comment line matching /^# Written by / # 3. Then a blank line followed by the first following line matching # /^# Copyright / # 4. Immediately followed by any lines between the previous matches, # except lines preceding the intervening completely blank line. # For example, see the header comments of this file. func_version () { $debug_cmd printf '%s\n' "$progname $scriptversion" $SED -n ' /^# Written by /!b s|^# ||; p; n :fwd2blnk /./ { n b fwd2blnk } p; n :holdwrnt s|^# || s|^# *$|| /^Copyright /!{ /./H n b holdwrnt } s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2| G s|\(\n\)\n*|\1|g p; q' < "$progpath" exit $? } # Local variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-pattern: "30/scriptversion=%:y-%02m-%02d.%02H; # UTC" # time-stamp-time-zone: "UTC" # End: # Set a version string. scriptversion='(GNU libtool) 2.4.7' # func_echo ARG... # ---------------- # Libtool also displays the current mode in messages, so override # funclib.sh func_echo with this custom definition. func_echo () { $debug_cmd _G_message=$* func_echo_IFS=$IFS IFS=$nl for _G_line in $_G_message; do IFS=$func_echo_IFS $ECHO "$progname${opt_mode+: $opt_mode}: $_G_line" done IFS=$func_echo_IFS } # func_warning ARG... # ------------------- # Libtool warnings are not categorized, so override funclib.sh # func_warning with this simpler definition. func_warning () { $debug_cmd $warning_func ${1+"$@"} } ## ---------------- ## ## Options parsing. ## ## ---------------- ## # Hook in the functions to make sure our own options are parsed during # the option parsing loop. usage='$progpath [OPTION]... [MODE-ARG]...' # Short help message in response to '-h'. usage_message="Options: --config show all configuration variables --debug enable verbose shell tracing -n, --dry-run display commands without modifying any files --features display basic configuration information and exit --mode=MODE use operation mode MODE --no-warnings equivalent to '-Wnone' --preserve-dup-deps don't remove duplicate dependency libraries --quiet, --silent don't print informational messages --tag=TAG use configuration variables from tag TAG -v, --verbose print more informational messages than default --version print version information -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] -h, --help, --help-all print short, long, or detailed help message " # Additional text appended to 'usage_message' in response to '--help'. func_help () { $debug_cmd func_usage_message $ECHO "$long_help_message MODE must be one of the following: clean remove files from the build directory compile compile a source file into a libtool object execute automatically set library path, then run a program finish complete the installation of libtool libraries install install libraries or executables link create a library or an executable uninstall remove libraries from an installed directory MODE-ARGS vary depending on the MODE. When passed as first option, '--mode=MODE' may be abbreviated as 'MODE' or a unique abbreviation of that. Try '$progname --help --mode=MODE' for a more detailed description of MODE. When reporting a bug, please describe a test case to reproduce it and include the following information: host-triplet: $host shell: $SHELL compiler: $LTCC compiler flags: $LTCFLAGS linker: $LD (gnu? $with_gnu_ld) version: $progname (GNU libtool) 2.4.7 automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q` autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q` Report bugs to . GNU libtool home page: . General help using GNU software: ." exit 0 } # func_lo2o OBJECT-NAME # --------------------- # Transform OBJECT-NAME from a '.lo' suffix to the platform specific # object suffix. lo2o=s/\\.lo\$/.$objext/ o2lo=s/\\.$objext\$/.lo/ if test yes = "$_G_HAVE_XSI_OPS"; then eval 'func_lo2o () { case $1 in *.lo) func_lo2o_result=${1%.lo}.$objext ;; * ) func_lo2o_result=$1 ;; esac }' # func_xform LIBOBJ-OR-SOURCE # --------------------------- # Transform LIBOBJ-OR-SOURCE from a '.o' or '.c' (or otherwise) # suffix to a '.lo' libtool-object suffix. eval 'func_xform () { func_xform_result=${1%.*}.lo }' else # ...otherwise fall back to using sed. func_lo2o () { func_lo2o_result=`$ECHO "$1" | $SED "$lo2o"` } func_xform () { func_xform_result=`$ECHO "$1" | $SED 's|\.[^.]*$|.lo|'` } fi # func_fatal_configuration ARG... # ------------------------------- # Echo program name prefixed message to standard error, followed by # a configuration failure hint, and exit. func_fatal_configuration () { func_fatal_error ${1+"$@"} \ "See the $PACKAGE documentation for more information." \ "Fatal configuration error." } # func_config # ----------- # Display the configuration for all the tags in this script. func_config () { re_begincf='^# ### BEGIN LIBTOOL' re_endcf='^# ### END LIBTOOL' # Default configuration. $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" # Now print the configurations for the tags. for tagname in $taglist; do $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" done exit $? } # func_features # ------------- # Display the features supported by this script. func_features () { echo "host: $host" if test yes = "$build_libtool_libs"; then echo "enable shared libraries" else echo "disable shared libraries" fi if test yes = "$build_old_libs"; then echo "enable static libraries" else echo "disable static libraries" fi exit $? } # func_enable_tag TAGNAME # ----------------------- # Verify that TAGNAME is valid, and either flag an error and exit, or # enable the TAGNAME tag. We also add TAGNAME to the global $taglist # variable here. func_enable_tag () { # Global variable: tagname=$1 re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" sed_extractcf=/$re_begincf/,/$re_endcf/p # Validate tagname. case $tagname in *[!-_A-Za-z0-9,/]*) func_fatal_error "invalid tag name: $tagname" ;; esac # Don't test for the "default" C tag, as we know it's # there but not specially marked. case $tagname in CC) ;; *) if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then taglist="$taglist $tagname" # Evaluate the configuration. Be careful to quote the path # and the sed script, to avoid splitting on whitespace, but # also don't use non-portable quotes within backquotes within # quotes we have to do it in 2 steps: extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` eval "$extractedcf" else func_error "ignoring unknown tag $tagname" fi ;; esac } # func_check_version_match # ------------------------ # Ensure that we are using m4 macros, and libtool script from the same # release of libtool. func_check_version_match () { if test "$package_revision" != "$macro_revision"; then if test "$VERSION" != "$macro_version"; then if test -z "$macro_version"; then cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from an older release. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from $PACKAGE $macro_version. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF fi else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, $progname: but the definition of this LT_INIT comes from revision $macro_revision. $progname: You should recreate aclocal.m4 with macros from revision $package_revision $progname: of $PACKAGE $VERSION and run autoconf again. _LT_EOF fi exit $EXIT_MISMATCH fi } # libtool_options_prep [ARG]... # ----------------------------- # Preparation for options parsed by libtool. libtool_options_prep () { $debug_mode # Option defaults: opt_config=false opt_dlopen= opt_dry_run=false opt_help=false opt_mode= opt_preserve_dup_deps=false opt_quiet=false nonopt= preserve_args= _G_rc_lt_options_prep=: # Shorthand for --mode=foo, only valid as the first argument case $1 in clean|clea|cle|cl) shift; set dummy --mode clean ${1+"$@"}; shift ;; compile|compil|compi|comp|com|co|c) shift; set dummy --mode compile ${1+"$@"}; shift ;; execute|execut|execu|exec|exe|ex|e) shift; set dummy --mode execute ${1+"$@"}; shift ;; finish|finis|fini|fin|fi|f) shift; set dummy --mode finish ${1+"$@"}; shift ;; install|instal|insta|inst|ins|in|i) shift; set dummy --mode install ${1+"$@"}; shift ;; link|lin|li|l) shift; set dummy --mode link ${1+"$@"}; shift ;; uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) shift; set dummy --mode uninstall ${1+"$@"}; shift ;; *) _G_rc_lt_options_prep=false ;; esac if $_G_rc_lt_options_prep; then # Pass back the list of options. func_quote eval ${1+"$@"} libtool_options_prep_result=$func_quote_result fi } func_add_hook func_options_prep libtool_options_prep # libtool_parse_options [ARG]... # --------------------------------- # Provide handling for libtool specific options. libtool_parse_options () { $debug_cmd _G_rc_lt_parse_options=false # Perform our own loop to consume as many options as possible in # each iteration. while test $# -gt 0; do _G_match_lt_parse_options=: _G_opt=$1 shift case $_G_opt in --dry-run|--dryrun|-n) opt_dry_run=: ;; --config) func_config ;; --dlopen|-dlopen) opt_dlopen="${opt_dlopen+$opt_dlopen }$1" shift ;; --preserve-dup-deps) opt_preserve_dup_deps=: ;; --features) func_features ;; --finish) set dummy --mode finish ${1+"$@"}; shift ;; --help) opt_help=: ;; --help-all) opt_help=': help-all' ;; --mode) test $# = 0 && func_missing_arg $_G_opt && break opt_mode=$1 case $1 in # Valid mode arguments: clean|compile|execute|finish|install|link|relink|uninstall) ;; # Catch anything else as an error *) func_error "invalid argument for $_G_opt" exit_cmd=exit break ;; esac shift ;; --no-silent|--no-quiet) opt_quiet=false func_append preserve_args " $_G_opt" ;; --no-warnings|--no-warning|--no-warn) opt_warning=false func_append preserve_args " $_G_opt" ;; --no-verbose) opt_verbose=false func_append preserve_args " $_G_opt" ;; --silent|--quiet) opt_quiet=: opt_verbose=false func_append preserve_args " $_G_opt" ;; --tag) test $# = 0 && func_missing_arg $_G_opt && break opt_tag=$1 func_append preserve_args " $_G_opt $1" func_enable_tag "$1" shift ;; --verbose|-v) opt_quiet=false opt_verbose=: func_append preserve_args " $_G_opt" ;; # An option not handled by this hook function: *) set dummy "$_G_opt" ${1+"$@"} ; shift _G_match_lt_parse_options=false break ;; esac $_G_match_lt_parse_options && _G_rc_lt_parse_options=: done if $_G_rc_lt_parse_options; then # save modified positional parameters for caller func_quote eval ${1+"$@"} libtool_parse_options_result=$func_quote_result fi } func_add_hook func_parse_options libtool_parse_options # libtool_validate_options [ARG]... # --------------------------------- # Perform any sanity checks on option settings and/or unconsumed # arguments. libtool_validate_options () { # save first non-option argument if test 0 -lt $#; then nonopt=$1 shift fi # preserve --debug test : = "$debug_cmd" || func_append preserve_args " --debug" case $host in # Solaris2 added to fix http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16452 # see also: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59788 *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* | *os2*) # don't eliminate duplications in $postdeps and $predeps opt_duplicate_compiler_generated_deps=: ;; *) opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps ;; esac $opt_help || { # Sanity checks first: func_check_version_match test yes != "$build_libtool_libs" \ && test yes != "$build_old_libs" \ && func_fatal_configuration "not configured to build any kind of library" # Darwin sucks eval std_shrext=\"$shrext_cmds\" # Only execute mode is allowed to have -dlopen flags. if test -n "$opt_dlopen" && test execute != "$opt_mode"; then func_error "unrecognized option '-dlopen'" $ECHO "$help" 1>&2 exit $EXIT_FAILURE fi # Change the help message to a mode-specific one. generic_help=$help help="Try '$progname --help --mode=$opt_mode' for more information." } # Pass back the unparsed argument list func_quote eval ${1+"$@"} libtool_validate_options_result=$func_quote_result } func_add_hook func_validate_options libtool_validate_options # Process options as early as possible so that --help and --version # can return quickly. func_options ${1+"$@"} eval set dummy "$func_options_result"; shift ## ----------- ## ## Main. ## ## ----------- ## magic='%%%MAGIC variable%%%' magic_exe='%%%MAGIC EXE variable%%%' # Global variables. extracted_archives= extracted_serial=0 # If this variable is set in any of the actions, the command in it # will be execed at the end. This prevents here-documents from being # left over by shells. exec_cmd= # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } # func_generated_by_libtool # True iff stdin has been generated by Libtool. This function is only # a basic sanity check; it will hardly flush out determined imposters. func_generated_by_libtool_p () { $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 } # func_lalib_p file # True iff FILE is a libtool '.la' library or '.lo' object file. # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_lalib_p () { test -f "$1" && $SED -e 4q "$1" 2>/dev/null | func_generated_by_libtool_p } # func_lalib_unsafe_p file # True iff FILE is a libtool '.la' library or '.lo' object file. # This function implements the same check as func_lalib_p without # resorting to external programs. To this end, it redirects stdin and # closes it afterwards, without saving the original file descriptor. # As a safety measure, use it only where a negative result would be # fatal anyway. Works if 'file' does not exist. func_lalib_unsafe_p () { lalib_p=no if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then for lalib_p_l in 1 2 3 4 do read lalib_p_line case $lalib_p_line in \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; esac done exec 0<&5 5<&- fi test yes = "$lalib_p" } # func_ltwrapper_script_p file # True iff FILE is a libtool wrapper script # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_script_p () { test -f "$1" && $lt_truncate_bin < "$1" 2>/dev/null | func_generated_by_libtool_p } # func_ltwrapper_executable_p file # True iff FILE is a libtool wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_executable_p () { func_ltwrapper_exec_suffix= case $1 in *.exe) ;; *) func_ltwrapper_exec_suffix=.exe ;; esac $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 } # func_ltwrapper_scriptname file # Assumes file is an ltwrapper_executable # uses $file to determine the appropriate filename for a # temporary ltwrapper_script. func_ltwrapper_scriptname () { func_dirname_and_basename "$1" "" "." func_stripname '' '.exe' "$func_basename_result" func_ltwrapper_scriptname_result=$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper } # func_ltwrapper_p file # True iff FILE is a libtool wrapper script or wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_p () { func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" } # func_execute_cmds commands fail_cmd # Execute tilde-delimited COMMANDS. # If FAIL_CMD is given, eval that upon failure. # FAIL_CMD may read-access the current command in variable CMD! func_execute_cmds () { $debug_cmd save_ifs=$IFS; IFS='~' for cmd in $1; do IFS=$sp$nl eval cmd=\"$cmd\" IFS=$save_ifs func_show_eval "$cmd" "${2-:}" done IFS=$save_ifs } # func_source file # Source FILE, adding directory component if necessary. # Note that it is not necessary on cygwin/mingw to append a dot to # FILE even if both FILE and FILE.exe exist: automatic-append-.exe # behavior happens only for exec(3), not for open(2)! Also, sourcing # 'FILE.' does not work on cygwin managed mounts. func_source () { $debug_cmd case $1 in */* | *\\*) . "$1" ;; *) . "./$1" ;; esac } # func_resolve_sysroot PATH # Replace a leading = in PATH with a sysroot. Store the result into # func_resolve_sysroot_result func_resolve_sysroot () { func_resolve_sysroot_result=$1 case $func_resolve_sysroot_result in =*) func_stripname '=' '' "$func_resolve_sysroot_result" func_resolve_sysroot_result=$lt_sysroot$func_stripname_result ;; esac } # func_replace_sysroot PATH # If PATH begins with the sysroot, replace it with = and # store the result into func_replace_sysroot_result. func_replace_sysroot () { case $lt_sysroot:$1 in ?*:"$lt_sysroot"*) func_stripname "$lt_sysroot" '' "$1" func_replace_sysroot_result='='$func_stripname_result ;; *) # Including no sysroot. func_replace_sysroot_result=$1 ;; esac } # func_infer_tag arg # Infer tagged configuration to use if any are available and # if one wasn't chosen via the "--tag" command line option. # Only attempt this if the compiler in the base compile # command doesn't match the default compiler. # arg is usually of the form 'gcc ...' func_infer_tag () { $debug_cmd if test -n "$available_tags" && test -z "$tagname"; then CC_quoted= for arg in $CC; do func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case $@ in # Blanks in the command may have been stripped by the calling shell, # but not from the CC environment variable when configure was run. " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; # Blanks at the start of $base_compile will cause this to fail # if we don't check for them as well. *) for z in $available_tags; do if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then # Evaluate the configuration. eval "`$SED -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" CC_quoted= for arg in $CC; do # Double-quote args containing other shell metacharacters. func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case "$@ " in " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) # The compiler in the base compile command matches # the one in the tagged configuration. # Assume this is the tagged configuration we want. tagname=$z break ;; esac fi done # If $tagname still isn't set, then no tagged configuration # was found and let the user know that the "--tag" command # line option must be used. if test -z "$tagname"; then func_echo "unable to infer tagged configuration" func_fatal_error "specify a tag with '--tag'" # else # func_verbose "using $tagname tagged configuration" fi ;; esac fi } # func_write_libtool_object output_name pic_name nonpic_name # Create a libtool object file (analogous to a ".la" file), # but don't create it if we're doing a dry run. func_write_libtool_object () { write_libobj=$1 if test yes = "$build_libtool_libs"; then write_lobj=\'$2\' else write_lobj=none fi if test yes = "$build_old_libs"; then write_oldobj=\'$3\' else write_oldobj=none fi $opt_dry_run || { cat >${write_libobj}T </dev/null` if test "$?" -eq 0 && test -n "$func_convert_core_file_wine_to_w32_tmp"; then func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | $SED -e "$sed_naive_backslashify"` else func_convert_core_file_wine_to_w32_result= fi fi } # end: func_convert_core_file_wine_to_w32 # func_convert_core_path_wine_to_w32 ARG # Helper function used by path conversion functions when $build is *nix, and # $host is mingw, cygwin, or some other w32 environment. Relies on a correctly # configured wine environment available, with the winepath program in $build's # $PATH. Assumes ARG has no leading or trailing path separator characters. # # ARG is path to be converted from $build format to win32. # Result is available in $func_convert_core_path_wine_to_w32_result. # Unconvertible file (directory) names in ARG are skipped; if no directory names # are convertible, then the result may be empty. func_convert_core_path_wine_to_w32 () { $debug_cmd # unfortunately, winepath doesn't convert paths, only file names func_convert_core_path_wine_to_w32_result= if test -n "$1"; then oldIFS=$IFS IFS=: for func_convert_core_path_wine_to_w32_f in $1; do IFS=$oldIFS func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" if test -n "$func_convert_core_file_wine_to_w32_result"; then if test -z "$func_convert_core_path_wine_to_w32_result"; then func_convert_core_path_wine_to_w32_result=$func_convert_core_file_wine_to_w32_result else func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" fi fi done IFS=$oldIFS fi } # end: func_convert_core_path_wine_to_w32 # func_cygpath ARGS... # Wrapper around calling the cygpath program via LT_CYGPATH. This is used when # when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) # $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or # (2), returns the Cygwin file name or path in func_cygpath_result (input # file name or path is assumed to be in w32 format, as previously converted # from $build's *nix or MSYS format). In case (3), returns the w32 file name # or path in func_cygpath_result (input file name or path is assumed to be in # Cygwin format). Returns an empty string on error. # # ARGS are passed to cygpath, with the last one being the file name or path to # be converted. # # Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH # environment variable; do not put it in $PATH. func_cygpath () { $debug_cmd if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` if test "$?" -ne 0; then # on failure, ensure result is empty func_cygpath_result= fi else func_cygpath_result= func_error "LT_CYGPATH is empty or specifies non-existent file: '$LT_CYGPATH'" fi } #end: func_cygpath # func_convert_core_msys_to_w32 ARG # Convert file name or path ARG from MSYS format to w32 format. Return # result in func_convert_core_msys_to_w32_result. func_convert_core_msys_to_w32 () { $debug_cmd # awkward: cmd appends spaces to result func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | $SED -e 's/[ ]*$//' -e "$sed_naive_backslashify"` } #end: func_convert_core_msys_to_w32 # func_convert_file_check ARG1 ARG2 # Verify that ARG1 (a file name in $build format) was converted to $host # format in ARG2. Otherwise, emit an error message, but continue (resetting # func_to_host_file_result to ARG1). func_convert_file_check () { $debug_cmd if test -z "$2" && test -n "$1"; then func_error "Could not determine host file name corresponding to" func_error " '$1'" func_error "Continuing, but uninstalled executables may not work." # Fallback: func_to_host_file_result=$1 fi } # end func_convert_file_check # func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH # Verify that FROM_PATH (a path in $build format) was converted to $host # format in TO_PATH. Otherwise, emit an error message, but continue, resetting # func_to_host_file_result to a simplistic fallback value (see below). func_convert_path_check () { $debug_cmd if test -z "$4" && test -n "$3"; then func_error "Could not determine the host path corresponding to" func_error " '$3'" func_error "Continuing, but uninstalled executables may not work." # Fallback. This is a deliberately simplistic "conversion" and # should not be "improved". See libtool.info. if test "x$1" != "x$2"; then lt_replace_pathsep_chars="s|$1|$2|g" func_to_host_path_result=`echo "$3" | $SED -e "$lt_replace_pathsep_chars"` else func_to_host_path_result=$3 fi fi } # end func_convert_path_check # func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG # Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT # and appending REPL if ORIG matches BACKPAT. func_convert_path_front_back_pathsep () { $debug_cmd case $4 in $1 ) func_to_host_path_result=$3$func_to_host_path_result ;; esac case $4 in $2 ) func_append func_to_host_path_result "$3" ;; esac } # end func_convert_path_front_back_pathsep ################################################## # $build to $host FILE NAME CONVERSION FUNCTIONS # ################################################## # invoked via '$to_host_file_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # Result will be available in $func_to_host_file_result. # func_to_host_file ARG # Converts the file name ARG from $build format to $host format. Return result # in func_to_host_file_result. func_to_host_file () { $debug_cmd $to_host_file_cmd "$1" } # end func_to_host_file # func_to_tool_file ARG LAZY # converts the file name ARG from $build format to toolchain format. Return # result in func_to_tool_file_result. If the conversion in use is listed # in (the comma separated) LAZY, no conversion takes place. func_to_tool_file () { $debug_cmd case ,$2, in *,"$to_tool_file_cmd",*) func_to_tool_file_result=$1 ;; *) $to_tool_file_cmd "$1" func_to_tool_file_result=$func_to_host_file_result ;; esac } # end func_to_tool_file # func_convert_file_noop ARG # Copy ARG to func_to_host_file_result. func_convert_file_noop () { func_to_host_file_result=$1 } # end func_convert_file_noop # func_convert_file_msys_to_w32 ARG # Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_file_result. func_convert_file_msys_to_w32 () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_to_host_file_result=$func_convert_core_msys_to_w32_result fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_w32 # func_convert_file_cygwin_to_w32 ARG # Convert file name ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_file_cygwin_to_w32 () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then # because $build is cygwin, we call "the" cygpath in $PATH; no need to use # LT_CYGPATH in this case. func_to_host_file_result=`cygpath -m "$1"` fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_cygwin_to_w32 # func_convert_file_nix_to_w32 ARG # Convert file name ARG from *nix to w32 format. Requires a wine environment # and a working winepath. Returns result in func_to_host_file_result. func_convert_file_nix_to_w32 () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then func_convert_core_file_wine_to_w32 "$1" func_to_host_file_result=$func_convert_core_file_wine_to_w32_result fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_w32 # func_convert_file_msys_to_cygwin ARG # Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_file_msys_to_cygwin () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_cygpath -u "$func_convert_core_msys_to_w32_result" func_to_host_file_result=$func_cygpath_result fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_cygwin # func_convert_file_nix_to_cygwin ARG # Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed # in a wine environment, working winepath, and LT_CYGPATH set. Returns result # in func_to_host_file_result. func_convert_file_nix_to_cygwin () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. func_convert_core_file_wine_to_w32 "$1" func_cygpath -u "$func_convert_core_file_wine_to_w32_result" func_to_host_file_result=$func_cygpath_result fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_cygwin ############################################# # $build to $host PATH CONVERSION FUNCTIONS # ############################################# # invoked via '$to_host_path_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # The result will be available in $func_to_host_path_result. # # Path separators are also converted from $build format to $host format. If # ARG begins or ends with a path separator character, it is preserved (but # converted to $host format) on output. # # All path conversion functions are named using the following convention: # file name conversion function : func_convert_file_X_to_Y () # path conversion function : func_convert_path_X_to_Y () # where, for any given $build/$host combination the 'X_to_Y' value is the # same. If conversion functions are added for new $build/$host combinations, # the two new functions must follow this pattern, or func_init_to_host_path_cmd # will break. # func_init_to_host_path_cmd # Ensures that function "pointer" variable $to_host_path_cmd is set to the # appropriate value, based on the value of $to_host_file_cmd. to_host_path_cmd= func_init_to_host_path_cmd () { $debug_cmd if test -z "$to_host_path_cmd"; then func_stripname 'func_convert_file_' '' "$to_host_file_cmd" to_host_path_cmd=func_convert_path_$func_stripname_result fi } # func_to_host_path ARG # Converts the path ARG from $build format to $host format. Return result # in func_to_host_path_result. func_to_host_path () { $debug_cmd func_init_to_host_path_cmd $to_host_path_cmd "$1" } # end func_to_host_path # func_convert_path_noop ARG # Copy ARG to func_to_host_path_result. func_convert_path_noop () { func_to_host_path_result=$1 } # end func_convert_path_noop # func_convert_path_msys_to_w32 ARG # Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_path_result. func_convert_path_msys_to_w32 () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # Remove leading and trailing path separator characters from ARG. MSYS # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; # and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result=$func_convert_core_msys_to_w32_result func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_msys_to_w32 # func_convert_path_cygwin_to_w32 ARG # Convert path ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_path_cygwin_to_w32 () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_cygwin_to_w32 # func_convert_path_nix_to_w32 ARG # Convert path ARG from *nix to w32 format. Requires a wine environment and # a working winepath. Returns result in func_to_host_file_result. func_convert_path_nix_to_w32 () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result=$func_convert_core_path_wine_to_w32_result func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_nix_to_w32 # func_convert_path_msys_to_cygwin ARG # Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_path_msys_to_cygwin () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_msys_to_w32_result" func_to_host_path_result=$func_cygpath_result func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_msys_to_cygwin # func_convert_path_nix_to_cygwin ARG # Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a # a wine environment, working winepath, and LT_CYGPATH set. Returns result in # func_to_host_file_result. func_convert_path_nix_to_cygwin () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # Remove leading and trailing path separator characters from # ARG. msys behavior is inconsistent here, cygpath turns them # into '.;' and ';.', and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" func_to_host_path_result=$func_cygpath_result func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_nix_to_cygwin # func_dll_def_p FILE # True iff FILE is a Windows DLL '.def' file. # Keep in sync with _LT_DLL_DEF_P in libtool.m4 func_dll_def_p () { $debug_cmd func_dll_def_p_tmp=`$SED -n \ -e 's/^[ ]*//' \ -e '/^\(;.*\)*$/d' \ -e 's/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p' \ -e q \ "$1"` test DEF = "$func_dll_def_p_tmp" } # func_mode_compile arg... func_mode_compile () { $debug_cmd # Get the compilation command and the source file. base_compile= srcfile=$nonopt # always keep a non-empty value in "srcfile" suppress_opt=yes suppress_output= arg_mode=normal libobj= later= pie_flag= for arg do case $arg_mode in arg ) # do not "continue". Instead, add this to base_compile lastarg=$arg arg_mode=normal ;; target ) libobj=$arg arg_mode=normal continue ;; normal ) # Accept any command-line options. case $arg in -o) test -n "$libobj" && \ func_fatal_error "you cannot specify '-o' more than once" arg_mode=target continue ;; -pie | -fpie | -fPIE) func_append pie_flag " $arg" continue ;; -shared | -static | -prefer-pic | -prefer-non-pic) func_append later " $arg" continue ;; -no-suppress) suppress_opt=no continue ;; -Xcompiler) arg_mode=arg # the next one goes into the "base_compile" arg list continue # The current "srcfile" will either be retained or ;; # replaced later. I would guess that would be a bug. -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result lastarg= save_ifs=$IFS; IFS=, for arg in $args; do IFS=$save_ifs func_append_quoted lastarg "$arg" done IFS=$save_ifs func_stripname ' ' '' "$lastarg" lastarg=$func_stripname_result # Add the arguments to base_compile. func_append base_compile " $lastarg" continue ;; *) # Accept the current argument as the source file. # The previous "srcfile" becomes the current argument. # lastarg=$srcfile srcfile=$arg ;; esac # case $arg ;; esac # case $arg_mode # Aesthetically quote the previous argument. func_append_quoted base_compile "$lastarg" done # for arg case $arg_mode in arg) func_fatal_error "you must specify an argument for -Xcompile" ;; target) func_fatal_error "you must specify a target with '-o'" ;; *) # Get the name of the library object. test -z "$libobj" && { func_basename "$srcfile" libobj=$func_basename_result } ;; esac # Recognize several different file suffixes. # If the user specifies -o file.o, it is replaced with file.lo case $libobj in *.[cCFSifmso] | \ *.ada | *.adb | *.ads | *.asm | \ *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) func_xform "$libobj" libobj=$func_xform_result ;; esac case $libobj in *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; *) func_fatal_error "cannot determine name of library object from '$libobj'" ;; esac func_infer_tag $base_compile for arg in $later; do case $arg in -shared) test yes = "$build_libtool_libs" \ || func_fatal_configuration "cannot build a shared library" build_old_libs=no continue ;; -static) build_libtool_libs=no build_old_libs=yes continue ;; -prefer-pic) pic_mode=yes continue ;; -prefer-non-pic) pic_mode=no continue ;; esac done func_quote_arg pretty "$libobj" test "X$libobj" != "X$func_quote_arg_result" \ && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ && func_warning "libobj name '$libobj' may not contain shell special characters." func_dirname_and_basename "$obj" "/" "" objname=$func_basename_result xdir=$func_dirname_result lobj=$xdir$objdir/$objname test -z "$base_compile" && \ func_fatal_help "you must specify a compilation command" # Delete any leftover library objects. if test yes = "$build_old_libs"; then removelist="$obj $lobj $libobj ${libobj}T" else removelist="$lobj $libobj ${libobj}T" fi # On Cygwin there's no "real" PIC flag so we must build both object types case $host_os in cygwin* | mingw* | pw32* | os2* | cegcc*) pic_mode=default ;; esac if test no = "$pic_mode" && test pass_all != "$deplibs_check_method"; then # non-PIC code in shared libraries is not supported pic_mode=default fi # Calculate the filename of the output object if compiler does # not support -o with -c if test no = "$compiler_c_o"; then output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.$objext lockfile=$output_obj.lock else output_obj= need_locks=no lockfile= fi # Lock this critical section if it is needed # We use this script file to make the link, it avoids creating a new file if test yes = "$need_locks"; then until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done elif test warn = "$need_locks"; then if test -f "$lockfile"; then $ECHO "\ *** ERROR, $lockfile exists and contains: `cat $lockfile 2>/dev/null` This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support '-c' and '-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi func_append removelist " $output_obj" $ECHO "$srcfile" > "$lockfile" fi $opt_dry_run || $RM $removelist func_append removelist " $lockfile" trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 srcfile=$func_to_tool_file_result func_quote_arg pretty "$srcfile" qsrcfile=$func_quote_arg_result # Only build a PIC object if we are building libtool libraries. if test yes = "$build_libtool_libs"; then # Without this assignment, base_compile gets emptied. fbsd_hideous_sh_bug=$base_compile if test no != "$pic_mode"; then command="$base_compile $qsrcfile $pic_flag" else # Don't build PIC code command="$base_compile $qsrcfile" fi func_mkdir_p "$xdir$objdir" if test -z "$output_obj"; then # Place PIC objects in $objdir func_append command " -o $lobj" fi func_show_eval_locale "$command" \ 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' if test warn = "$need_locks" && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support '-c' and '-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed, then go on to compile the next one if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then func_show_eval '$MV "$output_obj" "$lobj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi # Allow error messages only from the first compilation. if test yes = "$suppress_opt"; then suppress_output=' >/dev/null 2>&1' fi fi # Only build a position-dependent object if we build old libraries. if test yes = "$build_old_libs"; then if test yes != "$pic_mode"; then # Don't build PIC code command="$base_compile $qsrcfile$pie_flag" else command="$base_compile $qsrcfile $pic_flag" fi if test yes = "$compiler_c_o"; then func_append command " -o $obj" fi # Suppress compiler output if we already did a PIC compilation. func_append command "$suppress_output" func_show_eval_locale "$command" \ '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' if test warn = "$need_locks" && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support '-c' and '-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then func_show_eval '$MV "$output_obj" "$obj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi fi $opt_dry_run || { func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" # Unlock the critical section if it was locked if test no != "$need_locks"; then removelist=$lockfile $RM "$lockfile" fi } exit $EXIT_SUCCESS } $opt_help || { test compile = "$opt_mode" && func_mode_compile ${1+"$@"} } func_mode_help () { # We need to display help for each of the modes. case $opt_mode in "") # Generic help is extracted from the usage comments # at the start of this file. func_help ;; clean) $ECHO \ "Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... Remove files from the build directory. RM is the name of the program to use to delete files associated with each FILE (typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed to RM. If FILE is a libtool library, object or program, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; compile) $ECHO \ "Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE Compile a source file into a libtool library object. This mode accepts the following additional options: -o OUTPUT-FILE set the output file name to OUTPUT-FILE -no-suppress do not suppress compiler output for multiple passes -prefer-pic try to build PIC objects only -prefer-non-pic try to build non-PIC objects only -shared do not build a '.o' file suitable for static linking -static only build a '.o' file suitable for static linking -Wc,FLAG -Xcompiler FLAG pass FLAG directly to the compiler COMPILE-COMMAND is a command to be used in creating a 'standard' object file from the given SOURCEFILE. The output file name is determined by removing the directory component from SOURCEFILE, then substituting the C source code suffix '.c' with the library object suffix, '.lo'." ;; execute) $ECHO \ "Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... Automatically set library path, then run a program. This mode accepts the following additional options: -dlopen FILE add the directory containing FILE to the library path This mode sets the library path environment variable according to '-dlopen' flags. If any of the ARGS are libtool executable wrappers, then they are translated into their corresponding uninstalled binary, and any of their required library directories are added to the library path. Then, COMMAND is executed, with ARGS as arguments." ;; finish) $ECHO \ "Usage: $progname [OPTION]... --mode=finish [LIBDIR]... Complete the installation of libtool libraries. Each LIBDIR is a directory that contains libtool libraries. The commands that this mode executes may require superuser privileges. Use the '--dry-run' option if you just want to see what would be executed." ;; install) $ECHO \ "Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... Install executables or libraries. INSTALL-COMMAND is the installation command. The first component should be either the 'install' or 'cp' program. The following components of INSTALL-COMMAND are treated specially: -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation The rest of the components are interpreted as arguments to that command (only BSD-compatible install options are recognized)." ;; link) $ECHO \ "Usage: $progname [OPTION]... --mode=link LINK-COMMAND... Link object files or libraries together to form another library, or to create an executable program. LINK-COMMAND is a command using the C compiler that you would use to create a program from several object files. The following components of LINK-COMMAND are treated specially: -all-static do not do any dynamic linking at all -avoid-version do not add a version suffix if possible -bindir BINDIR specify path to binaries directory (for systems where libraries must be found in the PATH setting at runtime) -dlopen FILE '-dlpreopen' FILE if it cannot be dlopened at runtime -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) -export-symbols SYMFILE try to export only the symbols listed in SYMFILE -export-symbols-regex REGEX try to export only the symbols matching REGEX -LLIBDIR search LIBDIR for required installed libraries -lNAME OUTPUT-FILE requires the installed library libNAME -module build a library that can dlopened -no-fast-install disable the fast-install mode -no-install link a not-installable executable -no-undefined declare that a library does not refer to external symbols -o OUTPUT-FILE create OUTPUT-FILE from the specified objects -objectlist FILE use a list of object files found in FILE to specify objects -os2dllname NAME force a short DLL name on OS/2 (no effect on other OSes) -precious-files-regex REGEX don't remove output files matching REGEX -release RELEASE specify package release information -rpath LIBDIR the created library will eventually be installed in LIBDIR -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries -shared only do dynamic linking of libtool libraries -shrext SUFFIX override the standard shared library file extension -static do not do any dynamic linking of uninstalled libtool libraries -static-libtool-libs do not do any dynamic linking of libtool libraries -version-info CURRENT[:REVISION[:AGE]] specify library version info [each variable defaults to 0] -weak LIBNAME declare that the target provides the LIBNAME interface -Wc,FLAG -Xcompiler FLAG pass linker-specific FLAG directly to the compiler -Wa,FLAG -Xassembler FLAG pass linker-specific FLAG directly to the assembler -Wl,FLAG -Xlinker FLAG pass linker-specific FLAG directly to the linker -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) All other options (arguments beginning with '-') are ignored. Every other argument is treated as a filename. Files ending in '.la' are treated as uninstalled libtool libraries, other files are standard or library object files. If the OUTPUT-FILE ends in '.la', then a libtool library is created, only library objects ('.lo' files) may be specified, and '-rpath' is required, except when creating a convenience library. If OUTPUT-FILE ends in '.a' or '.lib', then a standard library is created using 'ar' and 'ranlib', or on Windows using 'lib'. If OUTPUT-FILE ends in '.lo' or '.$objext', then a reloadable object file is created, otherwise an executable program is created." ;; uninstall) $ECHO \ "Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... Remove libraries from an installation directory. RM is the name of the program to use to delete files associated with each FILE (typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed to RM. If FILE is a libtool library, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; *) func_fatal_help "invalid operation mode '$opt_mode'" ;; esac echo $ECHO "Try '$progname --help' for more information about other modes." } # Now that we've collected a possible --mode arg, show help if necessary if $opt_help; then if test : = "$opt_help"; then func_mode_help else { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do func_mode_help done } | $SED -n '1p; 2,$s/^Usage:/ or: /p' { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do echo func_mode_help done } | $SED '1d /^When reporting/,/^Report/{ H d } $x /information about other modes/d /more detailed .*MODE/d s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' fi exit $? fi # func_mode_execute arg... func_mode_execute () { $debug_cmd # The first argument is the command name. cmd=$nonopt test -z "$cmd" && \ func_fatal_help "you must specify a COMMAND" # Handle -dlopen flags immediately. for file in $opt_dlopen; do test -f "$file" \ || func_fatal_help "'$file' is not a file" dir= case $file in *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "'$lib' is not a valid libtool archive" # Read the libtool library. dlname= library_names= func_source "$file" # Skip this library if it cannot be dlopened. if test -z "$dlname"; then # Warn if it was a shared library. test -n "$library_names" && \ func_warning "'$file' was not linked with '-export-dynamic'" continue fi func_dirname "$file" "" "." dir=$func_dirname_result if test -f "$dir/$objdir/$dlname"; then func_append dir "/$objdir" else if test ! -f "$dir/$dlname"; then func_fatal_error "cannot find '$dlname' in '$dir' or '$dir/$objdir'" fi fi ;; *.lo) # Just add the directory containing the .lo file. func_dirname "$file" "" "." dir=$func_dirname_result ;; *) func_warning "'-dlopen' is ignored for non-libtool libraries and objects" continue ;; esac # Get the absolute pathname. absdir=`cd "$dir" && pwd` test -n "$absdir" && dir=$absdir # Now add the directory to shlibpath_var. if eval "test -z \"\$$shlibpath_var\""; then eval "$shlibpath_var=\"\$dir\"" else eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" fi done # This variable tells wrapper scripts just to set shlibpath_var # rather than running their programs. libtool_execute_magic=$magic # Check if any of the arguments is a wrapper script. args= for file do case $file in -* | *.la | *.lo ) ;; *) # Do a test to see if this is really a libtool program. if func_ltwrapper_script_p "$file"; then func_source "$file" # Transform arg to wrapped name. file=$progdir/$program elif func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" func_source "$func_ltwrapper_scriptname_result" # Transform arg to wrapped name. file=$progdir/$program fi ;; esac # Quote arguments (to preserve shell metacharacters). func_append_quoted args "$file" done if $opt_dry_run; then # Display what would be done. if test -n "$shlibpath_var"; then eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" echo "export $shlibpath_var" fi $ECHO "$cmd$args" exit $EXIT_SUCCESS else if test -n "$shlibpath_var"; then # Export the shlibpath_var. eval "export $shlibpath_var" fi # Restore saved environment variables for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${save_$lt_var+set}\" = set; then $lt_var=\$save_$lt_var; export $lt_var else $lt_unset $lt_var fi" done # Now prepare to actually exec the command. exec_cmd=\$cmd$args fi } test execute = "$opt_mode" && func_mode_execute ${1+"$@"} # func_mode_finish arg... func_mode_finish () { $debug_cmd libs= libdirs= admincmds= for opt in "$nonopt" ${1+"$@"} do if test -d "$opt"; then func_append libdirs " $opt" elif test -f "$opt"; then if func_lalib_unsafe_p "$opt"; then func_append libs " $opt" else func_warning "'$opt' is not a valid libtool archive" fi else func_fatal_error "invalid argument '$opt'" fi done if test -n "$libs"; then if test -n "$lt_sysroot"; then sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" else sysroot_cmd= fi # Remove sysroot references if $opt_dry_run; then for lib in $libs; do echo "removing references to $lt_sysroot and '=' prefixes from $lib" done else tmpdir=`func_mktempdir` for lib in $libs; do $SED -e "$sysroot_cmd s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ > $tmpdir/tmp-la mv -f $tmpdir/tmp-la $lib done ${RM}r "$tmpdir" fi fi if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then for libdir in $libdirs; do if test -n "$finish_cmds"; then # Do each command in the finish commands. func_execute_cmds "$finish_cmds" 'admincmds="$admincmds '"$cmd"'"' fi if test -n "$finish_eval"; then # Do the single finish_eval. eval cmds=\"$finish_eval\" $opt_dry_run || eval "$cmds" || func_append admincmds " $cmds" fi done fi # Exit here if they wanted silent mode. $opt_quiet && exit $EXIT_SUCCESS if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then echo "----------------------------------------------------------------------" echo "Libraries have been installed in:" for libdir in $libdirs; do $ECHO " $libdir" done echo echo "If you ever happen to want to link against installed libraries" echo "in a given directory, LIBDIR, you must either use libtool, and" echo "specify the full pathname of the library, or use the '-LLIBDIR'" echo "flag during linking and do at least one of the following:" if test -n "$shlibpath_var"; then echo " - add LIBDIR to the '$shlibpath_var' environment variable" echo " during execution" fi if test -n "$runpath_var"; then echo " - add LIBDIR to the '$runpath_var' environment variable" echo " during linking" fi if test -n "$hardcode_libdir_flag_spec"; then libdir=LIBDIR eval flag=\"$hardcode_libdir_flag_spec\" $ECHO " - use the '$flag' linker flag" fi if test -n "$admincmds"; then $ECHO " - have your system administrator run these commands:$admincmds" fi if test -f /etc/ld.so.conf; then echo " - have your system administrator add LIBDIR to '/etc/ld.so.conf'" fi echo echo "See any operating system documentation about shared libraries for" case $host in solaris2.[6789]|solaris2.1[0-9]) echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" echo "pages." ;; *) echo "more information, such as the ld(1) and ld.so(8) manual pages." ;; esac echo "----------------------------------------------------------------------" fi exit $EXIT_SUCCESS } test finish = "$opt_mode" && func_mode_finish ${1+"$@"} # func_mode_install arg... func_mode_install () { $debug_cmd # There may be an optional sh(1) argument at the beginning of # install_prog (especially on Windows NT). if test "$SHELL" = "$nonopt" || test /bin/sh = "$nonopt" || # Allow the use of GNU shtool's install command. case $nonopt in *shtool*) :;; *) false;; esac then # Aesthetically quote it. func_quote_arg pretty "$nonopt" install_prog="$func_quote_arg_result " arg=$1 shift else install_prog= arg=$nonopt fi # The real first argument should be the name of the installation program. # Aesthetically quote it. func_quote_arg pretty "$arg" func_append install_prog "$func_quote_arg_result" install_shared_prog=$install_prog case " $install_prog " in *[\\\ /]cp\ *) install_cp=: ;; *) install_cp=false ;; esac # We need to accept at least all the BSD install flags. dest= files= opts= prev= install_type= isdir=false stripme= no_mode=: for arg do arg2= if test -n "$dest"; then func_append files " $dest" dest=$arg continue fi case $arg in -d) isdir=: ;; -f) if $install_cp; then :; else prev=$arg fi ;; -g | -m | -o) prev=$arg ;; -s) stripme=" -s" continue ;; -*) ;; *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then if test X-m = "X$prev" && test -n "$install_override_mode"; then arg2=$install_override_mode no_mode=false fi prev= else dest=$arg continue fi ;; esac # Aesthetically quote the argument. func_quote_arg pretty "$arg" func_append install_prog " $func_quote_arg_result" if test -n "$arg2"; then func_quote_arg pretty "$arg2" fi func_append install_shared_prog " $func_quote_arg_result" done test -z "$install_prog" && \ func_fatal_help "you must specify an install program" test -n "$prev" && \ func_fatal_help "the '$prev' option requires an argument" if test -n "$install_override_mode" && $no_mode; then if $install_cp; then :; else func_quote_arg pretty "$install_override_mode" func_append install_shared_prog " -m $func_quote_arg_result" fi fi if test -z "$files"; then if test -z "$dest"; then func_fatal_help "no file or destination specified" else func_fatal_help "you must specify a destination" fi fi # Strip any trailing slash from the destination. func_stripname '' '/' "$dest" dest=$func_stripname_result # Check to see that the destination is a directory. test -d "$dest" && isdir=: if $isdir; then destdir=$dest destname= else func_dirname_and_basename "$dest" "" "." destdir=$func_dirname_result destname=$func_basename_result # Not a directory, so check to see that there is only one file specified. set dummy $files; shift test "$#" -gt 1 && \ func_fatal_help "'$dest' is not a directory" fi case $destdir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) for file in $files; do case $file in *.lo) ;; *) func_fatal_help "'$destdir' must be an absolute directory name" ;; esac done ;; esac # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic=$magic staticlibs= future_libdirs= current_libdirs= for file in $files; do # Do each installation. case $file in *.$libext) # Do the static libraries later. func_append staticlibs " $file" ;; *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "'$file' is not a valid libtool archive" library_names= old_library= relink_command= func_source "$file" # Add the libdir to current_libdirs if it is the destination. if test "X$destdir" = "X$libdir"; then case "$current_libdirs " in *" $libdir "*) ;; *) func_append current_libdirs " $libdir" ;; esac else # Note the libdir as a future libdir. case "$future_libdirs " in *" $libdir "*) ;; *) func_append future_libdirs " $libdir" ;; esac fi func_dirname "$file" "/" "" dir=$func_dirname_result func_append dir "$objdir" if test -n "$relink_command"; then # Determine the prefix the user has applied to our future dir. inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` # Don't allow the user to place us outside of our expected # location b/c this prevents finding dependent libraries that # are installed to the same prefix. # At present, this check doesn't affect windows .dll's that # are installed into $libdir/../bin (currently, that works fine) # but it's something to keep an eye on. test "$inst_prefix_dir" = "$destdir" && \ func_fatal_error "error: cannot install '$file' to a directory not ending in $libdir" if test -n "$inst_prefix_dir"; then # Stick the inst_prefix_dir data into the link command. relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` else relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` fi func_warning "relinking '$file'" func_show_eval "$relink_command" \ 'func_fatal_error "error: relink '\''$file'\'' with the above command before installing it"' fi # See the names of the shared library. set dummy $library_names; shift if test -n "$1"; then realname=$1 shift srcname=$realname test -n "$relink_command" && srcname=${realname}T # Install the shared library and build the symlinks. func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ 'exit $?' tstripme=$stripme case $host_os in cygwin* | mingw* | pw32* | cegcc*) case $realname in *.dll.a) tstripme= ;; esac ;; os2*) case $realname in *_dll.a) tstripme= ;; esac ;; esac if test -n "$tstripme" && test -n "$striplib"; then func_show_eval "$striplib $destdir/$realname" 'exit $?' fi if test "$#" -gt 0; then # Delete the old symlinks, and create new ones. # Try 'ln -sf' first, because the 'ln' binary might depend on # the symlink we replace! Solaris /bin/ln does not understand -f, # so we also need to try rm && ln -s. for linkname do test "$linkname" != "$realname" \ && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" done fi # Do each command in the postinstall commands. lib=$destdir/$realname func_execute_cmds "$postinstall_cmds" 'exit $?' fi # Install the pseudo-library for information purposes. func_basename "$file" name=$func_basename_result instname=$dir/${name}i func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' # Maybe install the static library, too. test -n "$old_library" && func_append staticlibs " $dir/$old_library" ;; *.lo) # Install (i.e. copy) a libtool object. # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile=$destdir/$destname else func_basename "$file" destfile=$func_basename_result destfile=$destdir/$destfile fi # Deduce the name of the destination old-style object file. case $destfile in *.lo) func_lo2o "$destfile" staticdest=$func_lo2o_result ;; *.$objext) staticdest=$destfile destfile= ;; *) func_fatal_help "cannot copy a libtool object to '$destfile'" ;; esac # Install the libtool object if requested. test -n "$destfile" && \ func_show_eval "$install_prog $file $destfile" 'exit $?' # Install the old object if enabled. if test yes = "$build_old_libs"; then # Deduce the name of the old-style object file. func_lo2o "$file" staticobj=$func_lo2o_result func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' fi exit $EXIT_SUCCESS ;; *) # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile=$destdir/$destname else func_basename "$file" destfile=$func_basename_result destfile=$destdir/$destfile fi # If the file is missing, and there is a .exe on the end, strip it # because it is most likely a libtool script we actually want to # install stripped_ext= case $file in *.exe) if test ! -f "$file"; then func_stripname '' '.exe' "$file" file=$func_stripname_result stripped_ext=.exe fi ;; esac # Do a test to see if this is really a libtool program. case $host in *cygwin* | *mingw*) if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" wrapper=$func_ltwrapper_scriptname_result else func_stripname '' '.exe' "$file" wrapper=$func_stripname_result fi ;; *) wrapper=$file ;; esac if func_ltwrapper_script_p "$wrapper"; then notinst_deplibs= relink_command= func_source "$wrapper" # Check the variables that should have been set. test -z "$generated_by_libtool_version" && \ func_fatal_error "invalid libtool wrapper script '$wrapper'" finalize=: for lib in $notinst_deplibs; do # Check to see that each library is installed. libdir= if test -f "$lib"; then func_source "$lib" fi libfile=$libdir/`$ECHO "$lib" | $SED 's%^.*/%%g'` if test -n "$libdir" && test ! -f "$libfile"; then func_warning "'$lib' has not been installed in '$libdir'" finalize=false fi done relink_command= func_source "$wrapper" outputname= if test no = "$fast_install" && test -n "$relink_command"; then $opt_dry_run || { if $finalize; then tmpdir=`func_mktempdir` func_basename "$file$stripped_ext" file=$func_basename_result outputname=$tmpdir/$file # Replace the output file specification. relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` $opt_quiet || { func_quote_arg expand,pretty "$relink_command" eval "func_echo $func_quote_arg_result" } if eval "$relink_command"; then : else func_error "error: relink '$file' with the above command before installing it" $opt_dry_run || ${RM}r "$tmpdir" continue fi file=$outputname else func_warning "cannot relink '$file'" fi } else # Install the binary that we compiled earlier. file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` fi fi # remove .exe since cygwin /usr/bin/install will append another # one anyway case $install_prog,$host in */usr/bin/install*,*cygwin*) case $file:$destfile in *.exe:*.exe) # this is ok ;; *.exe:*) destfile=$destfile.exe ;; *:*.exe) func_stripname '' '.exe' "$destfile" destfile=$func_stripname_result ;; esac ;; esac func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' $opt_dry_run || if test -n "$outputname"; then ${RM}r "$tmpdir" fi ;; esac done for file in $staticlibs; do func_basename "$file" name=$func_basename_result # Set up the ranlib parameters. oldlib=$destdir/$name func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result func_show_eval "$install_prog \$file \$oldlib" 'exit $?' if test -n "$stripme" && test -n "$old_striplib"; then func_show_eval "$old_striplib $tool_oldlib" 'exit $?' fi # Do each command in the postinstall commands. func_execute_cmds "$old_postinstall_cmds" 'exit $?' done test -n "$future_libdirs" && \ func_warning "remember to run '$progname --finish$future_libdirs'" if test -n "$current_libdirs"; then # Maybe just do a dry run. $opt_dry_run && current_libdirs=" -n$current_libdirs" exec_cmd='$SHELL "$progpath" $preserve_args --finish$current_libdirs' else exit $EXIT_SUCCESS fi } test install = "$opt_mode" && func_mode_install ${1+"$@"} # func_generate_dlsyms outputname originator pic_p # Extract symbols from dlprefiles and create ${outputname}S.o with # a dlpreopen symbol table. func_generate_dlsyms () { $debug_cmd my_outputname=$1 my_originator=$2 my_pic_p=${3-false} my_prefix=`$ECHO "$my_originator" | $SED 's%[^a-zA-Z0-9]%_%g'` my_dlsyms= if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then if test -n "$NM" && test -n "$global_symbol_pipe"; then my_dlsyms=${my_outputname}S.c else func_error "not configured to extract global symbols from dlpreopened files" fi fi if test -n "$my_dlsyms"; then case $my_dlsyms in "") ;; *.c) # Discover the nlist of each of the dlfiles. nlist=$output_objdir/$my_outputname.nm func_show_eval "$RM $nlist ${nlist}S ${nlist}T" # Parse the name list into a source file. func_verbose "creating $output_objdir/$my_dlsyms" $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ /* $my_dlsyms - symbol resolution table for '$my_outputname' dlsym emulation. */ /* Generated by $PROGRAM (GNU $PACKAGE) $VERSION */ #ifdef __cplusplus extern \"C\" { #endif #if defined __GNUC__ && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) #pragma GCC diagnostic ignored \"-Wstrict-prototypes\" #endif /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE /* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif #define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) /* External symbol declarations for the compiler. */\ " if test yes = "$dlself"; then func_verbose "generating symbol list for '$output'" $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" # Add our own program objects to the symbol list. progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` for progfile in $progfiles; do func_to_tool_file "$progfile" func_convert_file_msys_to_w32 func_verbose "extracting global C symbols from '$func_to_tool_file_result'" $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" done if test -n "$exclude_expsyms"; then $opt_dry_run || { eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi if test -n "$export_symbols_regex"; then $opt_dry_run || { eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi # Prepare the list of exported symbols if test -z "$export_symbols"; then export_symbols=$output_objdir/$outputname.exp $opt_dry_run || { $RM $export_symbols eval "$SED -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' ;; esac } else $opt_dry_run || { eval "$SED -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' ;; esac } fi fi for dlprefile in $dlprefiles; do func_verbose "extracting global C symbols from '$dlprefile'" func_basename "$dlprefile" name=$func_basename_result case $host in *cygwin* | *mingw* | *cegcc* ) # if an import library, we need to obtain dlname if func_win32_import_lib_p "$dlprefile"; then func_tr_sh "$dlprefile" eval "curr_lafile=\$libfile_$func_tr_sh_result" dlprefile_dlbasename= if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then # Use subshell, to avoid clobbering current variable values dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` if test -n "$dlprefile_dlname"; then func_basename "$dlprefile_dlname" dlprefile_dlbasename=$func_basename_result else # no lafile. user explicitly requested -dlpreopen . $sharedlib_from_linklib_cmd "$dlprefile" dlprefile_dlbasename=$sharedlib_from_linklib_result fi fi $opt_dry_run || { if test -n "$dlprefile_dlbasename"; then eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' else func_warning "Could not compute DLL name from $name" eval '$ECHO ": $name " >> "$nlist"' fi func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" } else # not an import lib $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } fi ;; *) $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } ;; esac done $opt_dry_run || { # Make sure we have at least an empty file. test -f "$nlist" || : > "$nlist" if test -n "$exclude_expsyms"; then $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T $MV "$nlist"T "$nlist" fi # Try sorting and uniquifying the output. if $GREP -v "^: " < "$nlist" | if sort -k 3 /dev/null 2>&1; then sort -k 3 else sort +2 fi | uniq > "$nlist"S; then : else $GREP -v "^: " < "$nlist" > "$nlist"S fi if test -f "$nlist"S; then eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' else echo '/* NONE */' >> "$output_objdir/$my_dlsyms" fi func_show_eval '$RM "${nlist}I"' if test -n "$global_symbol_to_import"; then eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I' fi echo >> "$output_objdir/$my_dlsyms" "\ /* The mapping between symbol names and symbols. */ typedef struct { const char *name; void *address; } lt_dlsymlist; extern LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[];\ " if test -s "$nlist"I; then echo >> "$output_objdir/$my_dlsyms" "\ static void lt_syminit(void) { LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols; for (; symbol->name; ++symbol) {" $SED 's/.*/ if (STREQ (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms" echo >> "$output_objdir/$my_dlsyms" "\ } }" fi echo >> "$output_objdir/$my_dlsyms" "\ LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[] = { {\"$my_originator\", (void *) 0}," if test -s "$nlist"I; then echo >> "$output_objdir/$my_dlsyms" "\ {\"@INIT@\", (void *) <_syminit}," fi case $need_lib_prefix in no) eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; *) eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; esac echo >> "$output_objdir/$my_dlsyms" "\ {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt_${my_prefix}_LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif\ " } # !$opt_dry_run pic_flag_for_symtable= case "$compile_command " in *" -static "*) ;; *) case $host in # compiling the symbol table file with pic_flag works around # a FreeBSD bug that causes programs to crash when -lm is # linked before any other PIC object. But we must not use # pic_flag when linking with -static. The problem exists in # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; *-*-hpux*) pic_flag_for_symtable=" $pic_flag" ;; *) $my_pic_p && pic_flag_for_symtable=" $pic_flag" ;; esac ;; esac symtab_cflags= for arg in $LTCFLAGS; do case $arg in -pie | -fpie | -fPIE) ;; *) func_append symtab_cflags " $arg" ;; esac done # Now compile the dynamic symbol file. func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' # Clean up the generated files. func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" "${nlist}I"' # Transform the symbol file into the correct name. symfileobj=$output_objdir/${my_outputname}S.$objext case $host in *cygwin* | *mingw* | *cegcc* ) if test -f "$output_objdir/$my_outputname.def"; then compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` else compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` fi ;; *) compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` ;; esac ;; *) func_fatal_error "unknown suffix for '$my_dlsyms'" ;; esac else # We keep going just in case the user didn't refer to # lt_preloaded_symbols. The linker will fail if global_symbol_pipe # really was required. # Nullify the symbol file. compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` fi } # func_cygming_gnu_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is a GNU/binutils-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_gnu_implib_p () { $debug_cmd func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` test -n "$func_cygming_gnu_implib_tmp" } # func_cygming_ms_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is an MS-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_ms_implib_p () { $debug_cmd func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` test -n "$func_cygming_ms_implib_tmp" } # func_win32_libid arg # return the library type of file 'arg' # # Need a lot of goo to handle *both* DLLs and import libs # Has to be a shell function in order to 'eat' the argument # that is supplied when $file_magic_command is called. # Despite the name, also deal with 64 bit binaries. func_win32_libid () { $debug_cmd win32_libid_type=unknown win32_fileres=`file -L $1 2>/dev/null` case $win32_fileres in *ar\ archive\ import\ library*) # definitely import win32_libid_type="x86 archive import" ;; *ar\ archive*) # could be an import, or static # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then case $nm_interface in "MS dumpbin") if func_cygming_ms_implib_p "$1" || func_cygming_gnu_implib_p "$1" then win32_nmres=import else win32_nmres= fi ;; *) func_to_tool_file "$1" func_convert_file_msys_to_w32 win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | $SED -n -e ' 1,100{ / I /{ s|.*|import| p q } }'` ;; esac case $win32_nmres in import*) win32_libid_type="x86 archive import";; *) win32_libid_type="x86 archive static";; esac fi ;; *DLL*) win32_libid_type="x86 DLL" ;; *executable*) # but shell scripts are "executable" too... case $win32_fileres in *MS\ Windows\ PE\ Intel*) win32_libid_type="x86 DLL" ;; esac ;; esac $ECHO "$win32_libid_type" } # func_cygming_dll_for_implib ARG # # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib () { $debug_cmd sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` } # func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs # # The is the core of a fallback implementation of a # platform-specific function to extract the name of the # DLL associated with the specified import library LIBNAME. # # SECTION_NAME is either .idata$6 or .idata$7, depending # on the platform and compiler that created the implib. # # Echos the name of the DLL associated with the # specified import library. func_cygming_dll_for_implib_fallback_core () { $debug_cmd match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` $OBJDUMP -s --section "$1" "$2" 2>/dev/null | $SED '/^Contents of section '"$match_literal"':/{ # Place marker at beginning of archive member dllname section s/.*/====MARK====/ p d } # These lines can sometimes be longer than 43 characters, but # are always uninteresting /:[ ]*file format pe[i]\{,1\}-/d /^In archive [^:]*:/d # Ensure marker is printed /^====MARK====/p # Remove all lines with less than 43 characters /^.\{43\}/!d # From remaining lines, remove first 43 characters s/^.\{43\}//' | $SED -n ' # Join marker and all lines until next marker into a single line /^====MARK====/ b para H $ b para b :para x s/\n//g # Remove the marker s/^====MARK====// # Remove trailing dots and whitespace s/[\. \t]*$// # Print /./p' | # we now have a list, one entry per line, of the stringified # contents of the appropriate section of all members of the # archive that possess that section. Heuristic: eliminate # all those that have a first or second character that is # a '.' (that is, objdump's representation of an unprintable # character.) This should work for all archives with less than # 0x302f exports -- but will fail for DLLs whose name actually # begins with a literal '.' or a single character followed by # a '.'. # # Of those that remain, print the first one. $SED -e '/^\./d;/^.\./d;q' } # func_cygming_dll_for_implib_fallback ARG # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # # This fallback implementation is for use when $DLLTOOL # does not support the --identify-strict option. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib_fallback () { $debug_cmd if func_cygming_gnu_implib_p "$1"; then # binutils import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` elif func_cygming_ms_implib_p "$1"; then # ms-generated import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` else # unknown sharedlib_from_linklib_result= fi } # func_extract_an_archive dir oldlib func_extract_an_archive () { $debug_cmd f_ex_an_ar_dir=$1; shift f_ex_an_ar_oldlib=$1 if test yes = "$lock_old_archive_extraction"; then lockfile=$f_ex_an_ar_oldlib.lock until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done fi func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ 'stat=$?; rm -f "$lockfile"; exit $stat' if test yes = "$lock_old_archive_extraction"; then $opt_dry_run || rm -f "$lockfile" fi if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then : else func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" fi } # func_extract_archives gentop oldlib ... func_extract_archives () { $debug_cmd my_gentop=$1; shift my_oldlibs=${1+"$@"} my_oldobjs= my_xlib= my_xabs= my_xdir= for my_xlib in $my_oldlibs; do # Extract the objects. case $my_xlib in [\\/]* | [A-Za-z]:[\\/]*) my_xabs=$my_xlib ;; *) my_xabs=`pwd`"/$my_xlib" ;; esac func_basename "$my_xlib" my_xlib=$func_basename_result my_xlib_u=$my_xlib while :; do case " $extracted_archives " in *" $my_xlib_u "*) func_arith $extracted_serial + 1 extracted_serial=$func_arith_result my_xlib_u=lt$extracted_serial-$my_xlib ;; *) break ;; esac done extracted_archives="$extracted_archives $my_xlib_u" my_xdir=$my_gentop/$my_xlib_u func_mkdir_p "$my_xdir" case $host in *-darwin*) func_verbose "Extracting $my_xabs" # Do not bother doing anything if just a dry run $opt_dry_run || { darwin_orig_dir=`pwd` cd $my_xdir || exit $? darwin_archive=$my_xabs darwin_curdir=`pwd` func_basename "$darwin_archive" darwin_base_archive=$func_basename_result darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` if test -n "$darwin_arches"; then darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` darwin_arch= func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" for darwin_arch in $darwin_arches; do func_mkdir_p "unfat-$$/$darwin_base_archive-$darwin_arch" $LIPO -thin $darwin_arch -output "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" "$darwin_archive" cd "unfat-$$/$darwin_base_archive-$darwin_arch" func_extract_an_archive "`pwd`" "$darwin_base_archive" cd "$darwin_curdir" $RM "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" done # $darwin_arches ## Okay now we've a bunch of thin objects, gotta fatten them up :) darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$sed_basename" | sort -u` darwin_file= darwin_files= for darwin_file in $darwin_filelist; do darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` $LIPO -create -output "$darwin_file" $darwin_files done # $darwin_filelist $RM -rf unfat-$$ cd "$darwin_orig_dir" else cd $darwin_orig_dir func_extract_an_archive "$my_xdir" "$my_xabs" fi # $darwin_arches } # !$opt_dry_run ;; *) func_extract_an_archive "$my_xdir" "$my_xabs" ;; esac my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` done func_extract_archives_result=$my_oldobjs } # func_emit_wrapper [arg=no] # # Emit a libtool wrapper script on stdout. # Don't directly open a file because we may want to # incorporate the script contents within a cygwin/mingw # wrapper executable. Must ONLY be called from within # func_mode_link because it depends on a number of variables # set therein. # # ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR # variable will take. If 'yes', then the emitted script # will assume that the directory where it is stored is # the $objdir directory. This is a cygwin/mingw-specific # behavior. func_emit_wrapper () { func_emit_wrapper_arg1=${1-no} $ECHO "\ #! $SHELL # $output - temporary wrapper script for $objdir/$outputname # Generated by $PROGRAM (GNU $PACKAGE) $VERSION # # The $output program cannot be directly executed until all the libtool # libraries that it depends on are installed. # # This wrapper script should never be moved out of the build directory. # If it is, it will not operate correctly. # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. sed_quote_subst='$sed_quote_subst' # Be Bourne compatible if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH relink_command=\"$relink_command\" # This environment variable determines our operation mode. if test \"\$libtool_install_magic\" = \"$magic\"; then # install mode needs the following variables: generated_by_libtool_version='$macro_version' notinst_deplibs='$notinst_deplibs' else # When we are sourced in execute mode, \$file and \$ECHO are already set. if test \"\$libtool_execute_magic\" != \"$magic\"; then file=\"\$0\"" func_quote_arg pretty "$ECHO" qECHO=$func_quote_arg_result $ECHO "\ # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } ECHO=$qECHO fi # Very basic option parsing. These options are (a) specific to # the libtool wrapper, (b) are identical between the wrapper # /script/ and the wrapper /executable/ that is used only on # windows platforms, and (c) all begin with the string "--lt-" # (application programs are unlikely to have options that match # this pattern). # # There are only two supported options: --lt-debug and # --lt-dump-script. There is, deliberately, no --lt-help. # # The first argument to this parsing function should be the # script's $0 value, followed by "$@". lt_option_debug= func_parse_lt_options () { lt_script_arg0=\$0 shift for lt_opt do case \"\$lt_opt\" in --lt-debug) lt_option_debug=1 ;; --lt-dump-script) lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` cat \"\$lt_dump_D/\$lt_dump_F\" exit 0 ;; --lt-*) \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 exit 1 ;; esac done # Print the debug banner immediately: if test -n \"\$lt_option_debug\"; then echo \"$outputname:$output:\$LINENO: libtool wrapper (GNU $PACKAGE) $VERSION\" 1>&2 fi } # Used when --lt-debug. Prints its arguments to stdout # (redirection is the responsibility of the caller) func_lt_dump_args () { lt_dump_args_N=1; for lt_arg do \$ECHO \"$outputname:$output:\$LINENO: newargv[\$lt_dump_args_N]: \$lt_arg\" lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` done } # Core function for launching the target application func_exec_program_core () { " case $host in # Backslashes separate directories on plain windows *-*-mingw | *-*-os2* | *-cegcc*) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir\\\\\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} " ;; *) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir/\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir/\$program\" \${1+\"\$@\"} " ;; esac $ECHO "\ \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 exit 1 } # A function to encapsulate launching the target application # Strips options in the --lt-* namespace from \$@ and # launches target application with the remaining arguments. func_exec_program () { case \" \$* \" in *\\ --lt-*) for lt_wr_arg do case \$lt_wr_arg in --lt-*) ;; *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; esac shift done ;; esac func_exec_program_core \${1+\"\$@\"} } # Parse options func_parse_lt_options \"\$0\" \${1+\"\$@\"} # Find the directory that this script lives in. thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` test \"x\$thisdir\" = \"x\$file\" && thisdir=. # Follow symbolic links until we get to the real thisdir. file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` while test -n \"\$file\"; do destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` # If there was a directory component, then change thisdir. if test \"x\$destdir\" != \"x\$file\"; then case \"\$destdir\" in [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; *) thisdir=\"\$thisdir/\$destdir\" ;; esac fi file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` done # Usually 'no', except on cygwin/mingw when embedded into # the cwrapper. WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then # special case for '.' if test \"\$thisdir\" = \".\"; then thisdir=\`pwd\` fi # remove .libs from thisdir case \"\$thisdir\" in *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; $objdir ) thisdir=. ;; esac fi # Try to get the absolute directory name. absdir=\`cd \"\$thisdir\" && pwd\` test -n \"\$absdir\" && thisdir=\"\$absdir\" " if test yes = "$fast_install"; then $ECHO "\ program=lt-'$outputname'$exeext progdir=\"\$thisdir/$objdir\" if test ! -f \"\$progdir/\$program\" || { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | $SED 1q\`; \\ test \"X\$file\" != \"X\$progdir/\$program\"; }; then file=\"\$\$-\$program\" if test ! -d \"\$progdir\"; then $MKDIR \"\$progdir\" else $RM \"\$progdir/\$file\" fi" $ECHO "\ # relink executable if necessary if test -n \"\$relink_command\"; then if relink_command_output=\`eval \$relink_command 2>&1\`; then : else \$ECHO \"\$relink_command_output\" >&2 $RM \"\$progdir/\$file\" exit 1 fi fi $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || { $RM \"\$progdir/\$program\"; $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } $RM \"\$progdir/\$file\" fi" else $ECHO "\ program='$outputname' progdir=\"\$thisdir/$objdir\" " fi $ECHO "\ if test -f \"\$progdir/\$program\"; then" # fixup the dll searchpath if we need to. # # Fix the DLL searchpath if we need to. Do this before prepending # to shlibpath, because on Windows, both are PATH and uninstalled # libraries must come first. if test -n "$dllsearchpath"; then $ECHO "\ # Add the dll search path components to the executable PATH PATH=$dllsearchpath:\$PATH " fi # Export our shlibpath_var if we have one. if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then $ECHO "\ # Add our own library path to $shlibpath_var $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" # Some systems cannot cope with colon-terminated $shlibpath_var # The second colon is a workaround for a bug in BeOS R4 sed $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` export $shlibpath_var " fi $ECHO "\ if test \"\$libtool_execute_magic\" != \"$magic\"; then # Run the actual program with our arguments. func_exec_program \${1+\"\$@\"} fi else # The program doesn't exist. \$ECHO \"\$0: error: '\$progdir/\$program' does not exist\" 1>&2 \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 exit 1 fi fi\ " } # func_emit_cwrapperexe_src # emit the source code for a wrapper executable on stdout # Must ONLY be called from within func_mode_link because # it depends on a number of variable set therein. func_emit_cwrapperexe_src () { cat < #include #ifdef _MSC_VER # include # include # include #else # include # include # ifdef __CYGWIN__ # include # endif #endif #include #include #include #include #include #include #include #include #define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) /* declarations of non-ANSI functions */ #if defined __MINGW32__ # ifdef __STRICT_ANSI__ int _putenv (const char *); # endif #elif defined __CYGWIN__ # ifdef __STRICT_ANSI__ char *realpath (const char *, char *); int putenv (char *); int setenv (const char *, const char *, int); # endif /* #elif defined other_platform || defined ... */ #endif /* portability defines, excluding path handling macros */ #if defined _MSC_VER # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv # define S_IXUSR _S_IEXEC #elif defined __MINGW32__ # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv #elif defined __CYGWIN__ # define HAVE_SETENV # define FOPEN_WB "wb" /* #elif defined other platforms ... */ #endif #if defined PATH_MAX # define LT_PATHMAX PATH_MAX #elif defined MAXPATHLEN # define LT_PATHMAX MAXPATHLEN #else # define LT_PATHMAX 1024 #endif #ifndef S_IXOTH # define S_IXOTH 0 #endif #ifndef S_IXGRP # define S_IXGRP 0 #endif /* path handling portability macros */ #ifndef DIR_SEPARATOR # define DIR_SEPARATOR '/' # define PATH_SEPARATOR ':' #endif #if defined _WIN32 || defined __MSDOS__ || defined __DJGPP__ || \ defined __OS2__ # define HAVE_DOS_BASED_FILE_SYSTEM # define FOPEN_WB "wb" # ifndef DIR_SEPARATOR_2 # define DIR_SEPARATOR_2 '\\' # endif # ifndef PATH_SEPARATOR_2 # define PATH_SEPARATOR_2 ';' # endif #endif #ifndef DIR_SEPARATOR_2 # define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) #else /* DIR_SEPARATOR_2 */ # define IS_DIR_SEPARATOR(ch) \ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) #endif /* DIR_SEPARATOR_2 */ #ifndef PATH_SEPARATOR_2 # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) #else /* PATH_SEPARATOR_2 */ # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) #endif /* PATH_SEPARATOR_2 */ #ifndef FOPEN_WB # define FOPEN_WB "w" #endif #ifndef _O_BINARY # define _O_BINARY 0 #endif #define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) #define XFREE(stale) do { \ if (stale) { free (stale); stale = 0; } \ } while (0) #if defined LT_DEBUGWRAPPER static int lt_debug = 1; #else static int lt_debug = 0; #endif const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ void *xmalloc (size_t num); char *xstrdup (const char *string); const char *base_name (const char *name); char *find_executable (const char *wrapper); char *chase_symlinks (const char *pathspec); int make_executable (const char *path); int check_executable (const char *path); char *strendzap (char *str, const char *pat); void lt_debugprintf (const char *file, int line, const char *fmt, ...); void lt_fatal (const char *file, int line, const char *message, ...); static const char *nonnull (const char *s); static const char *nonempty (const char *s); void lt_setenv (const char *name, const char *value); char *lt_extend_str (const char *orig_value, const char *add, int to_end); void lt_update_exe_path (const char *name, const char *value); void lt_update_lib_path (const char *name, const char *value); char **prepare_spawn (char **argv); void lt_dump_script (FILE *f); EOF cat <= 0) && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) return 1; else return 0; } int make_executable (const char *path) { int rval = 0; struct stat st; lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", nonempty (path)); if ((!path) || (!*path)) return 0; if (stat (path, &st) >= 0) { rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); } return rval; } /* Searches for the full path of the wrapper. Returns newly allocated full path name if found, NULL otherwise Does not chase symlinks, even on platforms that support them. */ char * find_executable (const char *wrapper) { int has_slash = 0; const char *p; const char *p_next; /* static buffer for getcwd */ char tmp[LT_PATHMAX + 1]; size_t tmp_len; char *concat_name; lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", nonempty (wrapper)); if ((wrapper == NULL) || (*wrapper == '\0')) return NULL; /* Absolute path? */ #if defined HAVE_DOS_BASED_FILE_SYSTEM if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } else { #endif if (IS_DIR_SEPARATOR (wrapper[0])) { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } #if defined HAVE_DOS_BASED_FILE_SYSTEM } #endif for (p = wrapper; *p; p++) if (*p == '/') { has_slash = 1; break; } if (!has_slash) { /* no slashes; search PATH */ const char *path = getenv ("PATH"); if (path != NULL) { for (p = path; *p; p = p_next) { const char *q; size_t p_len; for (q = p; *q; q++) if (IS_PATH_SEPARATOR (*q)) break; p_len = (size_t) (q - p); p_next = (*q == '\0' ? q : q + 1); if (p_len == 0) { /* empty path: current directory */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); } else { concat_name = XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, p, p_len); concat_name[p_len] = '/'; strcpy (concat_name + p_len + 1, wrapper); } if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } } /* not found in PATH; assume curdir */ } /* Relative path | not found in path: prepend cwd */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); return NULL; } char * chase_symlinks (const char *pathspec) { #ifndef S_ISLNK return xstrdup (pathspec); #else char buf[LT_PATHMAX]; struct stat s; char *tmp_pathspec = xstrdup (pathspec); char *p; int has_symlinks = 0; while (strlen (tmp_pathspec) && !has_symlinks) { lt_debugprintf (__FILE__, __LINE__, "checking path component for symlinks: %s\n", tmp_pathspec); if (lstat (tmp_pathspec, &s) == 0) { if (S_ISLNK (s.st_mode) != 0) { has_symlinks = 1; break; } /* search backwards for last DIR_SEPARATOR */ p = tmp_pathspec + strlen (tmp_pathspec) - 1; while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) p--; if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) { /* no more DIR_SEPARATORS left */ break; } *p = '\0'; } else { lt_fatal (__FILE__, __LINE__, "error accessing file \"%s\": %s", tmp_pathspec, nonnull (strerror (errno))); } } XFREE (tmp_pathspec); if (!has_symlinks) { return xstrdup (pathspec); } tmp_pathspec = realpath (pathspec, buf); if (tmp_pathspec == 0) { lt_fatal (__FILE__, __LINE__, "could not follow symlinks for %s", pathspec); } return xstrdup (tmp_pathspec); #endif } char * strendzap (char *str, const char *pat) { size_t len, patlen; assert (str != NULL); assert (pat != NULL); len = strlen (str); patlen = strlen (pat); if (patlen <= len) { str += len - patlen; if (STREQ (str, pat)) *str = '\0'; } return str; } void lt_debugprintf (const char *file, int line, const char *fmt, ...) { va_list args; if (lt_debug) { (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); va_start (args, fmt); (void) vfprintf (stderr, fmt, args); va_end (args); } } static void lt_error_core (int exit_status, const char *file, int line, const char *mode, const char *message, va_list ap) { fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); vfprintf (stderr, message, ap); fprintf (stderr, ".\n"); if (exit_status >= 0) exit (exit_status); } void lt_fatal (const char *file, int line, const char *message, ...) { va_list ap; va_start (ap, message); lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); va_end (ap); } static const char * nonnull (const char *s) { return s ? s : "(null)"; } static const char * nonempty (const char *s) { return (s && !*s) ? "(empty)" : nonnull (s); } void lt_setenv (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_setenv) setting '%s' to '%s'\n", nonnull (name), nonnull (value)); { #ifdef HAVE_SETENV /* always make a copy, for consistency with !HAVE_SETENV */ char *str = xstrdup (value); setenv (name, str, 1); #else size_t len = strlen (name) + 1 + strlen (value) + 1; char *str = XMALLOC (char, len); sprintf (str, "%s=%s", name, value); if (putenv (str) != EXIT_SUCCESS) { XFREE (str); } #endif } } char * lt_extend_str (const char *orig_value, const char *add, int to_end) { char *new_value; if (orig_value && *orig_value) { size_t orig_value_len = strlen (orig_value); size_t add_len = strlen (add); new_value = XMALLOC (char, add_len + orig_value_len + 1); if (to_end) { strcpy (new_value, orig_value); strcpy (new_value + orig_value_len, add); } else { strcpy (new_value, add); strcpy (new_value + add_len, orig_value); } } else { new_value = xstrdup (add); } return new_value; } void lt_update_exe_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); /* some systems can't cope with a ':'-terminated path #' */ size_t len = strlen (new_value); while ((len > 0) && IS_PATH_SEPARATOR (new_value[len-1])) { new_value[--len] = '\0'; } lt_setenv (name, new_value); XFREE (new_value); } } void lt_update_lib_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); lt_setenv (name, new_value); XFREE (new_value); } } EOF case $host_os in mingw*) cat <<"EOF" /* Prepares an argument vector before calling spawn(). Note that spawn() does not by itself call the command interpreter (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&v); v.dwPlatformId == VER_PLATFORM_WIN32_NT; }) ? "cmd.exe" : "command.com"). Instead it simply concatenates the arguments, separated by ' ', and calls CreateProcess(). We must quote the arguments since Win32 CreateProcess() interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a special way: - Space and tab are interpreted as delimiters. They are not treated as delimiters if they are surrounded by double quotes: "...". - Unescaped double quotes are removed from the input. Their only effect is that within double quotes, space and tab are treated like normal characters. - Backslashes not followed by double quotes are not special. - But 2*n+1 backslashes followed by a double quote become n backslashes followed by a double quote (n >= 0): \" -> " \\\" -> \" \\\\\" -> \\" */ #define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" #define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" char ** prepare_spawn (char **argv) { size_t argc; char **new_argv; size_t i; /* Count number of arguments. */ for (argc = 0; argv[argc] != NULL; argc++) ; /* Allocate new argument vector. */ new_argv = XMALLOC (char *, argc + 1); /* Put quoted arguments into the new argument vector. */ for (i = 0; i < argc; i++) { const char *string = argv[i]; if (string[0] == '\0') new_argv[i] = xstrdup ("\"\""); else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) { int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); size_t length; unsigned int backslashes; const char *s; char *quoted_string; char *p; length = 0; backslashes = 0; if (quote_around) length++; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') length += backslashes + 1; length++; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) length += backslashes + 1; quoted_string = XMALLOC (char, length + 1); p = quoted_string; backslashes = 0; if (quote_around) *p++ = '"'; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') { unsigned int j; for (j = backslashes + 1; j > 0; j--) *p++ = '\\'; } *p++ = c; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) { unsigned int j; for (j = backslashes; j > 0; j--) *p++ = '\\'; *p++ = '"'; } *p = '\0'; new_argv[i] = quoted_string; } else new_argv[i] = (char *) string; } new_argv[argc] = NULL; return new_argv; } EOF ;; esac cat <<"EOF" void lt_dump_script (FILE* f) { EOF func_emit_wrapper yes | $SED -n -e ' s/^\(.\{79\}\)\(..*\)/\1\ \2/ h s/\([\\"]\)/\\\1/g s/$/\\n/ s/\([^\n]*\).*/ fputs ("\1", f);/p g D' cat <<"EOF" } EOF } # end: func_emit_cwrapperexe_src # func_win32_import_lib_p ARG # True if ARG is an import lib, as indicated by $file_magic_cmd func_win32_import_lib_p () { $debug_cmd case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in *import*) : ;; *) false ;; esac } # func_suncc_cstd_abi # !!ONLY CALL THIS FOR SUN CC AFTER $compile_command IS FULLY EXPANDED!! # Several compiler flags select an ABI that is incompatible with the # Cstd library. Avoid specifying it if any are in CXXFLAGS. func_suncc_cstd_abi () { $debug_cmd case " $compile_command " in *" -compat=g "*|*\ -std=c++[0-9][0-9]\ *|*" -library=stdcxx4 "*|*" -library=stlport4 "*) suncc_use_cstd_abi=no ;; *) suncc_use_cstd_abi=yes ;; esac } # func_mode_link arg... func_mode_link () { $debug_cmd case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) # It is impossible to link a dll without this setting, and # we shouldn't force the makefile maintainer to figure out # what system we are compiling for in order to pass an extra # flag for every libtool invocation. # allow_undefined=no # FIXME: Unfortunately, there are problems with the above when trying # to make a dll that has undefined symbols, in which case not # even a static library is built. For now, we need to specify # -no-undefined on the libtool link line when we can be certain # that all symbols are satisfied, otherwise we get a static library. allow_undefined=yes ;; *) allow_undefined=yes ;; esac libtool_args=$nonopt base_compile="$nonopt $@" compile_command=$nonopt finalize_command=$nonopt compile_rpath= finalize_rpath= compile_shlibpath= finalize_shlibpath= convenience= old_convenience= deplibs= old_deplibs= compiler_flags= linker_flags= dllsearchpath= lib_search_path=`pwd` inst_prefix_dir= new_inherited_linker_flags= avoid_version=no bindir= dlfiles= dlprefiles= dlself=no export_dynamic=no export_symbols= export_symbols_regex= generated= libobjs= ltlibs= module=no no_install=no objs= os2dllname= non_pic_objects= precious_files_regex= prefer_static_libs=no preload=false prev= prevarg= release= rpath= xrpath= perm_rpath= temp_rpath= thread_safe=no vinfo= vinfo_number=no weak_libs= single_module=$wl-single_module func_infer_tag $base_compile # We need to know -static, to get the right output filenames. for arg do case $arg in -shared) test yes != "$build_libtool_libs" \ && func_fatal_configuration "cannot build a shared library" build_old_libs=no break ;; -all-static | -static | -static-libtool-libs) case $arg in -all-static) if test yes = "$build_libtool_libs" && test -z "$link_static_flag"; then func_warning "complete static linking is impossible in this configuration" fi if test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; -static) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=built ;; -static-libtool-libs) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; esac build_libtool_libs=no build_old_libs=yes break ;; esac done # See if our shared archives depend on static archives. test -n "$old_archive_from_new_cmds" && build_old_libs=yes # Go through the arguments, transforming them on the way. while test "$#" -gt 0; do arg=$1 shift func_quote_arg pretty,unquoted "$arg" qarg=$func_quote_arg_unquoted_result func_append libtool_args " $func_quote_arg_result" # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in output) func_append compile_command " @OUTPUT@" func_append finalize_command " @OUTPUT@" ;; esac case $prev in bindir) bindir=$arg prev= continue ;; dlfiles|dlprefiles) $preload || { # Add the symbol object into the linking commands. func_append compile_command " @SYMFILE@" func_append finalize_command " @SYMFILE@" preload=: } case $arg in *.la | *.lo) ;; # We handle these cases below. force) if test no = "$dlself"; then dlself=needless export_dynamic=yes fi prev= continue ;; self) if test dlprefiles = "$prev"; then dlself=yes elif test dlfiles = "$prev" && test yes != "$dlopen_self"; then dlself=yes else dlself=needless export_dynamic=yes fi prev= continue ;; *) if test dlfiles = "$prev"; then func_append dlfiles " $arg" else func_append dlprefiles " $arg" fi prev= continue ;; esac ;; expsyms) export_symbols=$arg test -f "$arg" \ || func_fatal_error "symbol file '$arg' does not exist" prev= continue ;; expsyms_regex) export_symbols_regex=$arg prev= continue ;; framework) case $host in *-*-darwin*) case "$deplibs " in *" $qarg.ltframework "*) ;; *) func_append deplibs " $qarg.ltframework" # this is fixed later ;; esac ;; esac prev= continue ;; inst_prefix) inst_prefix_dir=$arg prev= continue ;; mllvm) # Clang does not use LLVM to link, so we can simply discard any # '-mllvm $arg' options when doing the link step. prev= continue ;; objectlist) if test -f "$arg"; then save_arg=$arg moreargs= for fil in `cat "$save_arg"` do # func_append moreargs " $fil" arg=$fil # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test none = "$pic_object" && test none = "$non_pic_object"; then func_fatal_error "cannot find name of object for '$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result if test none != "$pic_object"; then # Prepend the subdirectory the object is found in. pic_object=$xdir$pic_object if test dlfiles = "$prev"; then if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test dlprefiles = "$prev"; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg=$pic_object fi # Non-PIC object. if test none != "$non_pic_object"; then # Prepend the subdirectory the object is found in. non_pic_object=$xdir$non_pic_object # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test none = "$pic_object"; then arg=$non_pic_object fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object=$pic_object func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "'$arg' is not a valid libtool object" fi fi done else func_fatal_error "link input file '$arg' does not exist" fi arg=$save_arg prev= continue ;; os2dllname) os2dllname=$arg prev= continue ;; precious_regex) precious_files_regex=$arg prev= continue ;; release) release=-$arg prev= continue ;; rpath | xrpath) # We need an absolute path. case $arg in [\\/]* | [A-Za-z]:[\\/]*) ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac if test rpath = "$prev"; then case "$rpath " in *" $arg "*) ;; *) func_append rpath " $arg" ;; esac else case "$xrpath " in *" $arg "*) ;; *) func_append xrpath " $arg" ;; esac fi prev= continue ;; shrext) shrext_cmds=$arg prev= continue ;; weak) func_append weak_libs " $arg" prev= continue ;; xassembler) func_append compiler_flags " -Xassembler $qarg" prev= func_append compile_command " -Xassembler $qarg" func_append finalize_command " -Xassembler $qarg" continue ;; xcclinker) func_append linker_flags " $qarg" func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xcompiler) func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xlinker) func_append linker_flags " $qarg" func_append compiler_flags " $wl$qarg" prev= func_append compile_command " $wl$qarg" func_append finalize_command " $wl$qarg" continue ;; *) eval "$prev=\"\$arg\"" prev= continue ;; esac fi # test -n "$prev" prevarg=$arg case $arg in -all-static) if test -n "$link_static_flag"; then # See comment for -static flag below, for more details. func_append compile_command " $link_static_flag" func_append finalize_command " $link_static_flag" fi continue ;; -allow-undefined) # FIXME: remove this flag sometime in the future. func_fatal_error "'-allow-undefined' must not be used because it is the default" ;; -avoid-version) avoid_version=yes continue ;; -bindir) prev=bindir continue ;; -dlopen) prev=dlfiles continue ;; -dlpreopen) prev=dlprefiles continue ;; -export-dynamic) export_dynamic=yes continue ;; -export-symbols | -export-symbols-regex) if test -n "$export_symbols" || test -n "$export_symbols_regex"; then func_fatal_error "more than one -exported-symbols argument is not allowed" fi if test X-export-symbols = "X$arg"; then prev=expsyms else prev=expsyms_regex fi continue ;; -framework) prev=framework continue ;; -inst-prefix-dir) prev=inst_prefix continue ;; # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* # so, if we see these flags be careful not to treat them like -L -L[A-Z][A-Z]*:*) case $with_gcc/$host in no/*-*-irix* | /*-*-irix*) func_append compile_command " $arg" func_append finalize_command " $arg" ;; esac continue ;; -L*) func_stripname "-L" '' "$arg" if test -z "$func_stripname_result"; then if test "$#" -gt 0; then func_fatal_error "require no space between '-L' and '$1'" else func_fatal_error "need path for '-L' option" fi fi func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) absdir=`cd "$dir" && pwd` test -z "$absdir" && \ func_fatal_error "cannot determine absolute directory name of '$dir'" dir=$absdir ;; esac case "$deplibs " in *" -L$dir "* | *" $arg "*) # Will only happen for absolute or sysroot arguments ;; *) # Preserve sysroot, but never include relative directories case $dir in [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; *) func_append deplibs " -L$dir" ;; esac func_append lib_search_path " $dir" ;; esac case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` case :$dllsearchpath: in *":$dir:"*) ;; ::) dllsearchpath=$dir;; *) func_append dllsearchpath ":$dir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac continue ;; -l*) if test X-lc = "X$arg" || test X-lm = "X$arg"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) # These systems don't actually have a C or math library (as such) continue ;; *-*-os2*) # These systems don't actually have a C library (as such) test X-lc = "X$arg" && continue ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig* | *-*-midnightbsd*) # Do not include libc due to us having libc/libc_r. test X-lc = "X$arg" && continue ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C and math libraries are in the System framework func_append deplibs " System.ltframework" continue ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype test X-lc = "X$arg" && continue ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work test X-lc = "X$arg" && continue ;; esac elif test X-lc_r = "X$arg"; then case $host in *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig* | *-*-midnightbsd*) # Do not include libc_r directly, use -pthread flag. continue ;; esac fi func_append deplibs " $arg" continue ;; -mllvm) prev=mllvm continue ;; -module) module=yes continue ;; # Tru64 UNIX uses -model [arg] to determine the layout of C++ # classes, name mangling, and exception handling. # Darwin uses the -arch flag to determine output architecture. -model|-arch|-isysroot|--sysroot) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" prev=xcompiler continue ;; # Solaris ld rejects as of 11.4. Refer to Oracle bug 22985199. -pthread) case $host in *solaris2*) ;; *) case "$new_inherited_linker_flags " in *" $arg "*) ;; * ) func_append new_inherited_linker_flags " $arg" ;; esac ;; esac continue ;; -mt|-mthreads|-kthread|-Kthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" case "$new_inherited_linker_flags " in *" $arg "*) ;; * ) func_append new_inherited_linker_flags " $arg" ;; esac continue ;; -multi_module) single_module=$wl-multi_module continue ;; -no-fast-install) fast_install=no continue ;; -no-install) case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) # The PATH hackery in wrapper scripts is required on Windows # and Darwin in order for the loader to find any dlls it needs. func_warning "'-no-install' is ignored for $host" func_warning "assuming '-no-fast-install' instead" fast_install=no ;; *) no_install=yes ;; esac continue ;; -no-undefined) allow_undefined=no continue ;; -objectlist) prev=objectlist continue ;; -os2dllname) prev=os2dllname continue ;; -o) prev=output ;; -precious-files-regex) prev=precious_regex continue ;; -release) prev=release continue ;; -rpath) prev=rpath continue ;; -R) prev=xrpath continue ;; -R*) func_stripname '-R' '' "$arg" dir=$func_stripname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; =*) func_stripname '=' '' "$dir" dir=$lt_sysroot$func_stripname_result ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac continue ;; -shared) # The effects of -shared are defined in a previous loop. continue ;; -shrext) prev=shrext continue ;; -static | -static-libtool-libs) # The effects of -static are defined in a previous loop. # We used to do the same as -all-static on platforms that # didn't have a PIC flag, but the assumption that the effects # would be equivalent was wrong. It would break on at least # Digital Unix and AIX. continue ;; -thread-safe) thread_safe=yes continue ;; -version-info) prev=vinfo continue ;; -version-number) prev=vinfo vinfo_number=yes continue ;; -weak) prev=weak continue ;; -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result arg= save_ifs=$IFS; IFS=, for flag in $args; do IFS=$save_ifs func_quote_arg pretty "$flag" func_append arg " $func_quote_arg_result" func_append compiler_flags " $func_quote_arg_result" done IFS=$save_ifs func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Wl,*) func_stripname '-Wl,' '' "$arg" args=$func_stripname_result arg= save_ifs=$IFS; IFS=, for flag in $args; do IFS=$save_ifs func_quote_arg pretty "$flag" func_append arg " $wl$func_quote_arg_result" func_append compiler_flags " $wl$func_quote_arg_result" func_append linker_flags " $func_quote_arg_result" done IFS=$save_ifs func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Xassembler) prev=xassembler continue ;; -Xcompiler) prev=xcompiler continue ;; -Xlinker) prev=xlinker continue ;; -XCClinker) prev=xcclinker continue ;; # -msg_* for osf cc -msg_*) func_quote_arg pretty "$arg" arg=$func_quote_arg_result ;; # Flags to be passed through unchanged, with rationale: # -64, -mips[0-9] enable 64-bit mode for the SGI compiler # -r[0-9][0-9]* specify processor for the SGI compiler # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler # +DA*, +DD* enable 64-bit mode for the HP compiler # -q* compiler args for the IBM compiler # -m*, -t[45]*, -txscale* architecture-specific flags for GCC # -F/path path to uninstalled frameworks, gcc on darwin # -p, -pg, --coverage, -fprofile-* profiling flags for GCC # -fstack-protector* stack protector flags for GCC # @file GCC response files # -tp=* Portland pgcc target processor selection # --sysroot=* for sysroot support # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization # -specs=* GCC specs files # -stdlib=* select c++ std lib with clang # -fsanitize=* Clang/GCC memory and address sanitizer # -fuse-ld=* Linker select flags for GCC # -Wa,* Pass flags directly to the assembler -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \ -specs=*|-fsanitize=*|-fuse-ld=*|-Wa,*) func_quote_arg pretty "$arg" arg=$func_quote_arg_result func_append compile_command " $arg" func_append finalize_command " $arg" func_append compiler_flags " $arg" continue ;; -Z*) if test os2 = "`expr $host : '.*\(os2\)'`"; then # OS/2 uses -Zxxx to specify OS/2-specific options compiler_flags="$compiler_flags $arg" func_append compile_command " $arg" func_append finalize_command " $arg" case $arg in -Zlinker | -Zstack) prev=xcompiler ;; esac continue else # Otherwise treat like 'Some other compiler flag' below func_quote_arg pretty "$arg" arg=$func_quote_arg_result fi ;; # Some other compiler flag. -* | +*) func_quote_arg pretty "$arg" arg=$func_quote_arg_result ;; *.$objext) # A standard object. func_append objs " $arg" ;; *.lo) # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test none = "$pic_object" && test none = "$non_pic_object"; then func_fatal_error "cannot find name of object for '$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result test none = "$pic_object" || { # Prepend the subdirectory the object is found in. pic_object=$xdir$pic_object if test dlfiles = "$prev"; then if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test dlprefiles = "$prev"; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg=$pic_object } # Non-PIC object. if test none != "$non_pic_object"; then # Prepend the subdirectory the object is found in. non_pic_object=$xdir$non_pic_object # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test none = "$pic_object"; then arg=$non_pic_object fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object=$pic_object func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "'$arg' is not a valid libtool object" fi fi ;; *.$libext) # An archive. func_append deplibs " $arg" func_append old_deplibs " $arg" continue ;; *.la) # A libtool-controlled library. func_resolve_sysroot "$arg" if test dlfiles = "$prev"; then # This library was specified with -dlopen. func_append dlfiles " $func_resolve_sysroot_result" prev= elif test dlprefiles = "$prev"; then # The library was specified with -dlpreopen. func_append dlprefiles " $func_resolve_sysroot_result" prev= else func_append deplibs " $func_resolve_sysroot_result" fi continue ;; # Some other compiler argument. *) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. func_quote_arg pretty "$arg" arg=$func_quote_arg_result ;; esac # arg # Now actually substitute the argument into the commands. if test -n "$arg"; then func_append compile_command " $arg" func_append finalize_command " $arg" fi done # argument parsing loop test -n "$prev" && \ func_fatal_help "the '$prevarg' option requires an argument" if test yes = "$export_dynamic" && test -n "$export_dynamic_flag_spec"; then eval arg=\"$export_dynamic_flag_spec\" func_append compile_command " $arg" func_append finalize_command " $arg" fi oldlibs= # calculate the name of the file, without its directory func_basename "$output" outputname=$func_basename_result libobjs_save=$libobjs if test -n "$shlibpath_var"; then # get the directories listed in $shlibpath_var eval shlib_search_path=\`\$ECHO \"\$$shlibpath_var\" \| \$SED \'s/:/ /g\'\` else shlib_search_path= fi eval sys_lib_search_path=\"$sys_lib_search_path_spec\" eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" # Definition is injected by LT_CONFIG during libtool generation. func_munge_path_list sys_lib_dlsearch_path "$LT_SYS_LIBRARY_PATH" func_dirname "$output" "/" "" output_objdir=$func_dirname_result$objdir func_to_tool_file "$output_objdir/" tool_output_objdir=$func_to_tool_file_result # Create the object directory. func_mkdir_p "$output_objdir" # Determine the type of output case $output in "") func_fatal_help "you must specify an output file" ;; *.$libext) linkmode=oldlib ;; *.lo | *.$objext) linkmode=obj ;; *.la) linkmode=lib ;; *) linkmode=prog ;; # Anything else should be a program. esac specialdeplibs= libs= # Find all interdependent deplibs by searching for libraries # that are linked more than once (e.g. -la -lb -la) for deplib in $deplibs; do if $opt_preserve_dup_deps; then case "$libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append libs " $deplib" done if test lib = "$linkmode"; then libs="$predeps $libs $compiler_lib_search_path $postdeps" # Compute libraries that are listed more than once in $predeps # $postdeps and mark them as special (i.e., whose duplicates are # not to be eliminated). pre_post_deps= if $opt_duplicate_compiler_generated_deps; then for pre_post_dep in $predeps $postdeps; do case "$pre_post_deps " in *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; esac func_append pre_post_deps " $pre_post_dep" done fi pre_post_deps= fi deplibs= newdependency_libs= newlib_search_path= need_relink=no # whether we're linking any uninstalled libtool libraries notinst_deplibs= # not-installed libtool libraries notinst_path= # paths that contain not-installed libtool libraries case $linkmode in lib) passes="conv dlpreopen link" for file in $dlfiles $dlprefiles; do case $file in *.la) ;; *) func_fatal_help "libraries can '-dlopen' only libtool libraries: $file" ;; esac done ;; prog) compile_deplibs= finalize_deplibs= alldeplibs=false newdlfiles= newdlprefiles= passes="conv scan dlopen dlpreopen link" ;; *) passes="conv" ;; esac for pass in $passes; do # The preopen pass in lib mode reverses $deplibs; put it back here # so that -L comes before libs that need it for instance... if test lib,link = "$linkmode,$pass"; then ## FIXME: Find the place where the list is rebuilt in the wrong ## order, and fix it there properly tmp_deplibs= for deplib in $deplibs; do tmp_deplibs="$deplib $tmp_deplibs" done deplibs=$tmp_deplibs fi if test lib,link = "$linkmode,$pass" || test prog,scan = "$linkmode,$pass"; then libs=$deplibs deplibs= fi if test prog = "$linkmode"; then case $pass in dlopen) libs=$dlfiles ;; dlpreopen) libs=$dlprefiles ;; link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; esac fi if test lib,dlpreopen = "$linkmode,$pass"; then # Collect and forward deplibs of preopened libtool libs for lib in $dlprefiles; do # Ignore non-libtool-libs dependency_libs= func_resolve_sysroot "$lib" case $lib in *.la) func_source "$func_resolve_sysroot_result" ;; esac # Collect preopened libtool deplibs, except any this library # has declared as weak libs for deplib in $dependency_libs; do func_basename "$deplib" deplib_base=$func_basename_result case " $weak_libs " in *" $deplib_base "*) ;; *) func_append deplibs " $deplib" ;; esac done done libs=$dlprefiles fi if test dlopen = "$pass"; then # Collect dlpreopened libraries save_deplibs=$deplibs deplibs= fi for deplib in $libs; do lib= found=false case $deplib in -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append compiler_flags " $deplib" if test lib = "$linkmode"; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -l*) if test lib != "$linkmode" && test prog != "$linkmode"; then func_warning "'-l' is ignored for archives/objects" continue fi func_stripname '-l' '' "$deplib" name=$func_stripname_result if test lib = "$linkmode"; then searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" else searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" fi for searchdir in $searchdirs; do for search_ext in .la $std_shrext .so .a; do # Search the libtool library lib=$searchdir/lib$name$search_ext if test -f "$lib"; then if test .la = "$search_ext"; then found=: else found=false fi break 2 fi done done if $found; then # deplib is a libtool library # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, # We need to do some special things here, and not later. if test yes = "$allow_libtool_libs_with_static_runtimes"; then case " $predeps $postdeps " in *" $deplib "*) if func_lalib_p "$lib"; then library_names= old_library= func_source "$lib" for l in $old_library $library_names; do ll=$l done if test "X$ll" = "X$old_library"; then # only static version available found=false func_dirname "$lib" "" "." ladir=$func_dirname_result lib=$ladir/$old_library if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" fi continue fi fi ;; *) ;; esac fi else # deplib doesn't seem to be a libtool library if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" fi continue fi ;; # -l *.ltframework) if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" if test lib = "$linkmode"; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -L*) case $linkmode in lib) deplibs="$deplib $deplibs" test conv = "$pass" && continue newdependency_libs="$deplib $newdependency_libs" func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; prog) if test conv = "$pass"; then deplibs="$deplib $deplibs" continue fi if test scan = "$pass"; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; *) func_warning "'-L' is ignored for archives/objects" ;; esac # linkmode continue ;; # -L -R*) if test link = "$pass"; then func_stripname '-R' '' "$deplib" func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # Make sure the xrpath contains only unique directories. case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac fi deplibs="$deplib $deplibs" continue ;; *.la) func_resolve_sysroot "$deplib" lib=$func_resolve_sysroot_result ;; *.$libext) if test conv = "$pass"; then deplibs="$deplib $deplibs" continue fi case $linkmode in lib) # Linking convenience modules into shared libraries is allowed, # but linking other static libraries is non-portable. case " $dlpreconveniencelibs " in *" $deplib "*) ;; *) valid_a_lib=false case $deplibs_check_method in match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ | $EGREP "$match_pattern_regex" > /dev/null; then valid_a_lib=: fi ;; pass_all) valid_a_lib=: ;; esac if $valid_a_lib; then echo $ECHO "*** Warning: Linking the shared library $output against the" $ECHO "*** static library $deplib is not portable!" deplibs="$deplib $deplibs" else echo $ECHO "*** Warning: Trying to link with static lib archive $deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because the file extensions .$libext of this argument makes me believe" echo "*** that it is just a static archive that I should not use here." fi ;; esac continue ;; prog) if test link != "$pass"; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi continue ;; esac # linkmode ;; # *.$libext *.lo | *.$objext) if test conv = "$pass"; then deplibs="$deplib $deplibs" elif test prog = "$linkmode"; then if test dlpreopen = "$pass" || test yes != "$dlopen_support" || test no = "$build_libtool_libs"; then # If there is no dlopen support or we're linking statically, # we need to preload. func_append newdlprefiles " $deplib" compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append newdlfiles " $deplib" fi fi continue ;; %DEPLIBS%) alldeplibs=: continue ;; esac # case $deplib $found || test -f "$lib" \ || func_fatal_error "cannot find the library '$lib' or unhandled argument '$deplib'" # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$lib" \ || func_fatal_error "'$lib' is not a valid libtool archive" func_dirname "$lib" "" "." ladir=$func_dirname_result dlname= dlopen= dlpreopen= libdir= library_names= old_library= inherited_linker_flags= # If the library was installed with an old release of libtool, # it will not redefine variables installed, or shouldnotlink installed=yes shouldnotlink=no avoidtemprpath= # Read the .la file func_source "$lib" # Convert "-framework foo" to "foo.ltframework" if test -n "$inherited_linker_flags"; then tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do case " $new_inherited_linker_flags " in *" $tmp_inherited_linker_flag "*) ;; *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; esac done fi dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` if test lib,link = "$linkmode,$pass" || test prog,scan = "$linkmode,$pass" || { test prog != "$linkmode" && test lib != "$linkmode"; }; then test -n "$dlopen" && func_append dlfiles " $dlopen" test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" fi if test conv = "$pass"; then # Only check for convenience libraries deplibs="$lib $deplibs" if test -z "$libdir"; then if test -z "$old_library"; then func_fatal_error "cannot find name of link library for '$lib'" fi # It is a libtool convenience library, so add in its objects. func_append convenience " $ladir/$objdir/$old_library" func_append old_convenience " $ladir/$objdir/$old_library" elif test prog != "$linkmode" && test lib != "$linkmode"; then func_fatal_error "'$lib' is not a convenience library" fi tmp_libs= for deplib in $dependency_libs; do deplibs="$deplib $deplibs" if $opt_preserve_dup_deps; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done continue fi # $pass = conv # Get the name of the library we link against. linklib= if test -n "$old_library" && { test yes = "$prefer_static_libs" || test built,no = "$prefer_static_libs,$installed"; }; then linklib=$old_library else for l in $old_library $library_names; do linklib=$l done fi if test -z "$linklib"; then func_fatal_error "cannot find name of link library for '$lib'" fi # This library was specified with -dlopen. if test dlopen = "$pass"; then test -z "$libdir" \ && func_fatal_error "cannot -dlopen a convenience library: '$lib'" if test -z "$dlname" || test yes != "$dlopen_support" || test no = "$build_libtool_libs" then # If there is no dlname, no dlopen support or we're linking # statically, we need to preload. We also need to preload any # dependent libraries so libltdl's deplib preloader doesn't # bomb out in the load deplibs phase. func_append dlprefiles " $lib $dependency_libs" else func_append newdlfiles " $lib" fi continue fi # $pass = dlopen # We need an absolute path. case $ladir in [\\/]* | [A-Za-z]:[\\/]*) abs_ladir=$ladir ;; *) abs_ladir=`cd "$ladir" && pwd` if test -z "$abs_ladir"; then func_warning "cannot determine absolute directory name of '$ladir'" func_warning "passing it literally to the linker, although it might fail" abs_ladir=$ladir fi ;; esac func_basename "$lib" laname=$func_basename_result # Find the relevant object directory and library name. if test yes = "$installed"; then if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then func_warning "library '$lib' was moved." dir=$ladir absdir=$abs_ladir libdir=$abs_ladir else dir=$lt_sysroot$libdir absdir=$lt_sysroot$libdir fi test yes = "$hardcode_automatic" && avoidtemprpath=yes else if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then dir=$ladir absdir=$abs_ladir # Remove this search path later func_append notinst_path " $abs_ladir" else dir=$ladir/$objdir absdir=$abs_ladir/$objdir # Remove this search path later func_append notinst_path " $abs_ladir" fi fi # $installed = yes func_stripname 'lib' '.la' "$laname" name=$func_stripname_result # This library was specified with -dlpreopen. if test dlpreopen = "$pass"; then if test -z "$libdir" && test prog = "$linkmode"; then func_fatal_error "only libraries may -dlpreopen a convenience library: '$lib'" fi case $host in # special handling for platforms with PE-DLLs. *cygwin* | *mingw* | *cegcc* ) # Linker will automatically link against shared library if both # static and shared are present. Therefore, ensure we extract # symbols from the import library if a shared library is present # (otherwise, the dlopen module name will be incorrect). We do # this by putting the import library name into $newdlprefiles. # We recover the dlopen module name by 'saving' the la file # name in a special purpose variable, and (later) extracting the # dlname from the la file. if test -n "$dlname"; then func_tr_sh "$dir/$linklib" eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" func_append newdlprefiles " $dir/$linklib" else func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" fi ;; * ) # Prefer using a static library (so that no silly _DYNAMIC symbols # are required to link). if test -n "$old_library"; then func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" # Otherwise, use the dlname, so that lt_dlopen finds it. elif test -n "$dlname"; then func_append newdlprefiles " $dir/$dlname" else func_append newdlprefiles " $dir/$linklib" fi ;; esac fi # $pass = dlpreopen if test -z "$libdir"; then # Link the convenience library if test lib = "$linkmode"; then deplibs="$dir/$old_library $deplibs" elif test prog,link = "$linkmode,$pass"; then compile_deplibs="$dir/$old_library $compile_deplibs" finalize_deplibs="$dir/$old_library $finalize_deplibs" else deplibs="$lib $deplibs" # used for prog,scan pass fi continue fi if test prog = "$linkmode" && test link != "$pass"; then func_append newlib_search_path " $ladir" deplibs="$lib $deplibs" linkalldeplibs=false if test no != "$link_all_deplibs" || test -z "$library_names" || test no = "$build_libtool_libs"; then linkalldeplibs=: fi tmp_libs= for deplib in $dependency_libs; do case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; esac # Need to link against all dependency_libs? if $linkalldeplibs; then deplibs="$deplib $deplibs" else # Need to hardcode shared library paths # or/and link against static libraries newdependency_libs="$deplib $newdependency_libs" fi if $opt_preserve_dup_deps; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done # for deplib continue fi # $linkmode = prog... if test prog,link = "$linkmode,$pass"; then if test -n "$library_names" && { { test no = "$prefer_static_libs" || test built,yes = "$prefer_static_libs,$installed"; } || test -z "$old_library"; }; then # We need to hardcode the library path if test -n "$shlibpath_var" && test -z "$avoidtemprpath"; then # Make sure the rpath contains only unique directories. case $temp_rpath: in *"$absdir:"*) ;; *) func_append temp_rpath "$absdir:" ;; esac fi # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi # $linkmode,$pass = prog,link... if $alldeplibs && { test pass_all = "$deplibs_check_method" || { test yes = "$build_libtool_libs" && test -n "$library_names"; }; }; then # We only need to search for static libraries continue fi fi link_static=no # Whether the deplib will be linked statically use_static_libs=$prefer_static_libs if test built = "$use_static_libs" && test yes = "$installed"; then use_static_libs=no fi if test -n "$library_names" && { test no = "$use_static_libs" || test -z "$old_library"; }; then case $host in *cygwin* | *mingw* | *cegcc* | *os2*) # No point in relinking DLLs because paths are not encoded func_append notinst_deplibs " $lib" need_relink=no ;; *) if test no = "$installed"; then func_append notinst_deplibs " $lib" need_relink=yes fi ;; esac # This is a shared library # Warn about portability, can't link against -module's on some # systems (darwin). Don't bleat about dlopened modules though! dlopenmodule= for dlpremoduletest in $dlprefiles; do if test "X$dlpremoduletest" = "X$lib"; then dlopenmodule=$dlpremoduletest break fi done if test -z "$dlopenmodule" && test yes = "$shouldnotlink" && test link = "$pass"; then echo if test prog = "$linkmode"; then $ECHO "*** Warning: Linking the executable $output against the loadable module" else $ECHO "*** Warning: Linking the shared library $output against the loadable module" fi $ECHO "*** $linklib is not portable!" fi if test lib = "$linkmode" && test yes = "$hardcode_into_libs"; then # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi if test -n "$old_archive_from_expsyms_cmds"; then # figure out the soname set dummy $library_names shift realname=$1 shift libname=`eval "\\$ECHO \"$libname_spec\""` # use dlname if we got it. it's perfectly good, no? if test -n "$dlname"; then soname=$dlname elif test -n "$soname_spec"; then # bleh windows case $host in *cygwin* | mingw* | *cegcc* | *os2*) func_arith $current - $age major=$func_arith_result versuffix=-$major ;; esac eval soname=\"$soname_spec\" else soname=$realname fi # Make a new name for the extract_expsyms_cmds to use soroot=$soname func_basename "$soroot" soname=$func_basename_result func_stripname 'lib' '.dll' "$soname" newlib=libimp-$func_stripname_result.a # If the library has no export list, then create one now if test -f "$output_objdir/$soname-def"; then : else func_verbose "extracting exported symbol list from '$soname'" func_execute_cmds "$extract_expsyms_cmds" 'exit $?' fi # Create $newlib if test -f "$output_objdir/$newlib"; then :; else func_verbose "generating import library for '$soname'" func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' fi # make sure the library variables are pointing to the new library dir=$output_objdir linklib=$newlib fi # test -n "$old_archive_from_expsyms_cmds" if test prog = "$linkmode" || test relink != "$opt_mode"; then add_shlibpath= add_dir= add= lib_linked=yes case $hardcode_action in immediate | unsupported) if test no = "$hardcode_direct"; then add=$dir/$linklib case $host in *-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;; *-*-sysv4*uw2*) add_dir=-L$dir ;; *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ *-*-unixware7*) add_dir=-L$dir ;; *-*-darwin* ) # if the lib is a (non-dlopened) module then we cannot # link against it, someone is ignoring the earlier warnings if /usr/bin/file -L $add 2> /dev/null | $GREP ": [^:]* bundle" >/dev/null; then if test "X$dlopenmodule" != "X$lib"; then $ECHO "*** Warning: lib $linklib is a module, not a shared library" if test -z "$old_library"; then echo echo "*** And there doesn't seem to be a static archive available" echo "*** The link will probably fail, sorry" else add=$dir/$old_library fi elif test -n "$old_library"; then add=$dir/$old_library fi fi esac elif test no = "$hardcode_minus_L"; then case $host in *-*-sunos*) add_shlibpath=$dir ;; esac add_dir=-L$dir add=-l$name elif test no = "$hardcode_shlibpath_var"; then add_shlibpath=$dir add=-l$name else lib_linked=no fi ;; relink) if test yes = "$hardcode_direct" && test no = "$hardcode_direct_absolute"; then add=$dir/$linklib elif test yes = "$hardcode_minus_L"; then add_dir=-L$absdir # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add=-l$name elif test yes = "$hardcode_shlibpath_var"; then add_shlibpath=$dir add=-l$name else lib_linked=no fi ;; *) lib_linked=no ;; esac if test yes != "$lib_linked"; then func_fatal_configuration "unsupported hardcode properties" fi if test -n "$add_shlibpath"; then case :$compile_shlibpath: in *":$add_shlibpath:"*) ;; *) func_append compile_shlibpath "$add_shlibpath:" ;; esac fi if test prog = "$linkmode"; then test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" test -n "$add" && compile_deplibs="$add $compile_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" if test yes != "$hardcode_direct" && test yes != "$hardcode_minus_L" && test yes = "$hardcode_shlibpath_var"; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac fi fi fi if test prog = "$linkmode" || test relink = "$opt_mode"; then add_shlibpath= add_dir= add= # Finalize command for both is simple: just hardcode it. if test yes = "$hardcode_direct" && test no = "$hardcode_direct_absolute"; then add=$libdir/$linklib elif test yes = "$hardcode_minus_L"; then add_dir=-L$libdir add=-l$name elif test yes = "$hardcode_shlibpath_var"; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac add=-l$name elif test yes = "$hardcode_automatic"; then if test -n "$inst_prefix_dir" && test -f "$inst_prefix_dir$libdir/$linklib"; then add=$inst_prefix_dir$libdir/$linklib else add=$libdir/$linklib fi else # We cannot seem to hardcode it, guess we'll fake it. add_dir="-L$lt_sysroot$libdir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add=-l$name fi if test prog = "$linkmode"; then test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" test -n "$add" && finalize_deplibs="$add $finalize_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" fi fi elif test prog = "$linkmode"; then # Here we assume that one of hardcode_direct or hardcode_minus_L # is not unsupported. This is valid on all known static and # shared platforms. if test unsupported != "$hardcode_direct"; then test -n "$old_library" && linklib=$old_library compile_deplibs="$dir/$linklib $compile_deplibs" finalize_deplibs="$dir/$linklib $finalize_deplibs" else compile_deplibs="-l$name -L$dir $compile_deplibs" finalize_deplibs="-l$name -L$dir $finalize_deplibs" fi elif test yes = "$build_libtool_libs"; then # Not a shared library if test pass_all != "$deplibs_check_method"; then # We're trying link a shared library against a static one # but the system doesn't support it. # Just print a warning and add the library to dependency_libs so # that the program can be linked against the static library. echo $ECHO "*** Warning: This system cannot link to static lib archive $lib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have." if test yes = "$module"; then echo "*** But as you try to build a module library, libtool will still create " echo "*** a static module, that should work as long as the dlopening application" echo "*** is linked with the -dlopen flag to resolve symbols at runtime." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using 'nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** 'nm' from GNU binutils and a full rebuild may help." fi if test no = "$build_old_libs"; then build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi else deplibs="$dir/$old_library $deplibs" link_static=yes fi fi # link shared/static library? if test lib = "$linkmode"; then if test -n "$dependency_libs" && { test yes != "$hardcode_into_libs" || test yes = "$build_old_libs" || test yes = "$link_static"; }; then # Extract -R from dependency_libs temp_deplibs= for libdir in $dependency_libs; do case $libdir in -R*) func_stripname '-R' '' "$libdir" temp_xrpath=$func_stripname_result case " $xrpath " in *" $temp_xrpath "*) ;; *) func_append xrpath " $temp_xrpath";; esac;; *) func_append temp_deplibs " $libdir";; esac done dependency_libs=$temp_deplibs fi func_append newlib_search_path " $absdir" # Link against this library test no = "$link_static" && newdependency_libs="$abs_ladir/$laname $newdependency_libs" # ... and its dependency_libs tmp_libs= for deplib in $dependency_libs; do newdependency_libs="$deplib $newdependency_libs" case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result";; *) func_resolve_sysroot "$deplib" ;; esac if $opt_preserve_dup_deps; then case "$tmp_libs " in *" $func_resolve_sysroot_result "*) func_append specialdeplibs " $func_resolve_sysroot_result" ;; esac fi func_append tmp_libs " $func_resolve_sysroot_result" done if test no != "$link_all_deplibs"; then # Add the search paths of all dependency libraries for deplib in $dependency_libs; do path= case $deplib in -L*) path=$deplib ;; *.la) func_resolve_sysroot "$deplib" deplib=$func_resolve_sysroot_result func_dirname "$deplib" "" "." dir=$func_dirname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) absdir=$dir ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then func_warning "cannot determine absolute directory name of '$dir'" absdir=$dir fi ;; esac if $GREP "^installed=no" $deplib > /dev/null; then case $host in *-*-darwin*) depdepl= eval deplibrary_names=`$SED -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` if test -n "$deplibrary_names"; then for tmp in $deplibrary_names; do depdepl=$tmp done if test -f "$absdir/$objdir/$depdepl"; then depdepl=$absdir/$objdir/$depdepl darwin_install_name=`$OTOOL -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` if test -z "$darwin_install_name"; then darwin_install_name=`$OTOOL64 -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` fi func_append compiler_flags " $wl-dylib_file $wl$darwin_install_name:$depdepl" func_append linker_flags " -dylib_file $darwin_install_name:$depdepl" path= fi fi ;; *) path=-L$absdir/$objdir ;; esac else eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` test -z "$libdir" && \ func_fatal_error "'$deplib' is not a valid libtool archive" test "$absdir" != "$libdir" && \ func_warning "'$deplib' seems to be moved" path=-L$absdir fi ;; esac case " $deplibs " in *" $path "*) ;; *) deplibs="$path $deplibs" ;; esac done fi # link_all_deplibs != no fi # linkmode = lib done # for deplib in $libs if test link = "$pass"; then if test prog = "$linkmode"; then compile_deplibs="$new_inherited_linker_flags $compile_deplibs" finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" else compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` fi fi dependency_libs=$newdependency_libs if test dlpreopen = "$pass"; then # Link the dlpreopened libraries before other libraries for deplib in $save_deplibs; do deplibs="$deplib $deplibs" done fi if test dlopen != "$pass"; then test conv = "$pass" || { # Make sure lib_search_path contains only unique directories. lib_search_path= for dir in $newlib_search_path; do case "$lib_search_path " in *" $dir "*) ;; *) func_append lib_search_path " $dir" ;; esac done newlib_search_path= } if test prog,link = "$linkmode,$pass"; then vars="compile_deplibs finalize_deplibs" else vars=deplibs fi for var in $vars dependency_libs; do # Add libraries to $var in reverse order eval tmp_libs=\"\$$var\" new_libs= for deplib in $tmp_libs; do # FIXME: Pedantically, this is the right thing to do, so # that some nasty dependency loop isn't accidentally # broken: #new_libs="$deplib $new_libs" # Pragmatically, this seems to cause very few problems in # practice: case $deplib in -L*) new_libs="$deplib $new_libs" ;; -R*) ;; *) # And here is the reason: when a library appears more # than once as an explicit dependence of a library, or # is implicitly linked in more than once by the # compiler, it is considered special, and multiple # occurrences thereof are not removed. Compare this # with having the same library being listed as a # dependency of multiple other libraries: in this case, # we know (pedantically, we assume) the library does not # need to be listed more than once, so we keep only the # last copy. This is not always right, but it is rare # enough that we require users that really mean to play # such unportable linking tricks to link the library # using -Wl,-lname, so that libtool does not consider it # for duplicate removal. case " $specialdeplibs " in *" $deplib "*) new_libs="$deplib $new_libs" ;; *) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$deplib $new_libs" ;; esac ;; esac ;; esac done tmp_libs= for deplib in $new_libs; do case $deplib in -L*) case " $tmp_libs " in *" $deplib "*) ;; *) func_append tmp_libs " $deplib" ;; esac ;; *) func_append tmp_libs " $deplib" ;; esac done eval $var=\"$tmp_libs\" done # for var fi # Add Sun CC postdeps if required: test CXX = "$tagname" && { case $host_os in linux*) case `$CC -V 2>&1 | $SED 5q` in *Sun\ C*) # Sun C++ 5.9 func_suncc_cstd_abi if test no != "$suncc_use_cstd_abi"; then func_append postdeps ' -library=Cstd -library=Crun' fi ;; esac ;; solaris*) func_cc_basename "$CC" case $func_cc_basename_result in CC* | sunCC*) func_suncc_cstd_abi if test no != "$suncc_use_cstd_abi"; then func_append postdeps ' -library=Cstd -library=Crun' fi ;; esac ;; esac } # Last step: remove runtime libs from dependency_libs # (they stay in deplibs) tmp_libs= for i in $dependency_libs; do case " $predeps $postdeps $compiler_lib_search_path " in *" $i "*) i= ;; esac if test -n "$i"; then func_append tmp_libs " $i" fi done dependency_libs=$tmp_libs done # for pass if test prog = "$linkmode"; then dlfiles=$newdlfiles fi if test prog = "$linkmode" || test lib = "$linkmode"; then dlprefiles=$newdlprefiles fi case $linkmode in oldlib) if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then func_warning "'-dlopen' is ignored for archives" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "'-l' and '-L' are ignored for archives" ;; esac test -n "$rpath" && \ func_warning "'-rpath' is ignored for archives" test -n "$xrpath" && \ func_warning "'-R' is ignored for archives" test -n "$vinfo" && \ func_warning "'-version-info/-version-number' is ignored for archives" test -n "$release" && \ func_warning "'-release' is ignored for archives" test -n "$export_symbols$export_symbols_regex" && \ func_warning "'-export-symbols' is ignored for archives" # Now set the variables for building old libraries. build_libtool_libs=no oldlibs=$output func_append objs "$old_deplibs" ;; lib) # Make sure we only generate libraries of the form 'libNAME.la'. case $outputname in lib*) func_stripname 'lib' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" ;; *) test no = "$module" \ && func_fatal_help "libtool library '$output' must begin with 'lib'" if test no != "$need_lib_prefix"; then # Add the "lib" prefix for modules if required func_stripname '' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" else func_stripname '' '.la' "$outputname" libname=$func_stripname_result fi ;; esac if test -n "$objs"; then if test pass_all != "$deplibs_check_method"; then func_fatal_error "cannot build libtool library '$output' from non-libtool objects on this host:$objs" else echo $ECHO "*** Warning: Linking the shared library $output against the non-libtool" $ECHO "*** objects $objs is not portable!" func_append libobjs " $objs" fi fi test no = "$dlself" \ || func_warning "'-dlopen self' is ignored for libtool libraries" set dummy $rpath shift test 1 -lt "$#" \ && func_warning "ignoring multiple '-rpath's for a libtool library" install_libdir=$1 oldlibs= if test -z "$rpath"; then if test yes = "$build_libtool_libs"; then # Building a libtool convenience library. # Some compilers have problems with a '.al' extension so # convenience libraries should have the same extension an # archive normally would. oldlibs="$output_objdir/$libname.$libext $oldlibs" build_libtool_libs=convenience build_old_libs=yes fi test -n "$vinfo" && \ func_warning "'-version-info/-version-number' is ignored for convenience libraries" test -n "$release" && \ func_warning "'-release' is ignored for convenience libraries" else # Parse the version information argument. save_ifs=$IFS; IFS=: set dummy $vinfo 0 0 0 shift IFS=$save_ifs test -n "$7" && \ func_fatal_help "too many parameters to '-version-info'" # convert absolute version numbers to libtool ages # this retains compatibility with .la files and attempts # to make the code below a bit more comprehensible case $vinfo_number in yes) number_major=$1 number_minor=$2 number_revision=$3 # # There are really only two kinds -- those that # use the current revision as the major version # and those that subtract age and use age as # a minor version. But, then there is irix # that has an extra 1 added just for fun # case $version_type in # correct linux to gnu/linux during the next big refactor darwin|freebsd-elf|linux|midnightbsd-elf|osf|windows|none) func_arith $number_major + $number_minor current=$func_arith_result age=$number_minor revision=$number_revision ;; freebsd-aout|qnx|sunos) current=$number_major revision=$number_minor age=0 ;; irix|nonstopux) func_arith $number_major + $number_minor current=$func_arith_result age=$number_minor revision=$number_minor lt_irix_increment=no ;; esac ;; no) current=$1 revision=$2 age=$3 ;; esac # Check that each of the things are valid numbers. case $current in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "CURRENT '$current' must be a nonnegative integer" func_fatal_error "'$vinfo' is not valid version information" ;; esac case $revision in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "REVISION '$revision' must be a nonnegative integer" func_fatal_error "'$vinfo' is not valid version information" ;; esac case $age in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "AGE '$age' must be a nonnegative integer" func_fatal_error "'$vinfo' is not valid version information" ;; esac if test "$age" -gt "$current"; then func_error "AGE '$age' is greater than the current interface number '$current'" func_fatal_error "'$vinfo' is not valid version information" fi # Calculate the version variables. major= versuffix= verstring= case $version_type in none) ;; darwin) # Like Linux, but with the current version available in # verstring for coding it into the library header func_arith $current - $age major=.$func_arith_result versuffix=$major.$age.$revision # Darwin ld doesn't like 0 for these options... func_arith $current + 1 minor_current=$func_arith_result xlcverstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" # On Darwin other compilers case $CC in nagfor*) verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" ;; *) verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" ;; esac ;; freebsd-aout) major=.$current versuffix=.$current.$revision ;; freebsd-elf | midnightbsd-elf) func_arith $current - $age major=.$func_arith_result versuffix=$major.$age.$revision ;; irix | nonstopux) if test no = "$lt_irix_increment"; then func_arith $current - $age else func_arith $current - $age + 1 fi major=$func_arith_result case $version_type in nonstopux) verstring_prefix=nonstopux ;; *) verstring_prefix=sgi ;; esac verstring=$verstring_prefix$major.$revision # Add in all the interfaces that we are compatible with. loop=$revision while test 0 -ne "$loop"; do func_arith $revision - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring=$verstring_prefix$major.$iface:$verstring done # Before this point, $major must not contain '.'. major=.$major versuffix=$major.$revision ;; linux) # correct to gnu/linux during the next big refactor func_arith $current - $age major=.$func_arith_result versuffix=$major.$age.$revision ;; osf) func_arith $current - $age major=.$func_arith_result versuffix=.$current.$age.$revision verstring=$current.$age.$revision # Add in all the interfaces that we are compatible with. loop=$age while test 0 -ne "$loop"; do func_arith $current - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring=$verstring:$iface.0 done # Make executables depend on our current version. func_append verstring ":$current.0" ;; qnx) major=.$current versuffix=.$current ;; sco) major=.$current versuffix=.$current ;; sunos) major=.$current versuffix=.$current.$revision ;; windows) # Use '-' rather than '.', since we only want one # extension on DOS 8.3 file systems. func_arith $current - $age major=$func_arith_result versuffix=-$major ;; *) func_fatal_configuration "unknown library version type '$version_type'" ;; esac # Clear the version info if we defaulted, and they specified a release. if test -z "$vinfo" && test -n "$release"; then major= case $version_type in darwin) # we can't check for "0.0" in archive_cmds due to quoting # problems, so we reset it completely verstring= ;; *) verstring=0.0 ;; esac if test no = "$need_version"; then versuffix= else versuffix=.0.0 fi fi # Remove version info from name if versioning should be avoided if test yes,no = "$avoid_version,$need_version"; then major= versuffix= verstring= fi # Check to see if the archive will have undefined symbols. if test yes = "$allow_undefined"; then if test unsupported = "$allow_undefined_flag"; then if test yes = "$build_old_libs"; then func_warning "undefined symbols not allowed in $host shared libraries; building static only" build_libtool_libs=no else func_fatal_error "can't build $host shared library unless -no-undefined is specified" fi fi else # Don't allow undefined symbols. allow_undefined_flag=$no_undefined_flag fi fi func_generate_dlsyms "$libname" "$libname" : func_append libobjs " $symfileobj" test " " = "$libobjs" && libobjs= if test relink != "$opt_mode"; then # Remove our outputs, but don't remove object files since they # may have been created when compiling PIC objects. removelist= tempremovelist=`$ECHO "$output_objdir/*"` for p in $tempremovelist; do case $p in *.$objext | *.gcno) ;; $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/$libname$release.*) if test -n "$precious_files_regex"; then if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 then continue fi fi func_append removelist " $p" ;; *) ;; esac done test -n "$removelist" && \ func_show_eval "${RM}r \$removelist" fi # Now set the variables for building old libraries. if test yes = "$build_old_libs" && test convenience != "$build_libtool_libs"; then func_append oldlibs " $output_objdir/$libname.$libext" # Transform .lo files to .o files. oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; $lo2o" | $NL2SP` fi # Eliminate all temporary directories. #for path in $notinst_path; do # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` #done if test -n "$xrpath"; then # If the user specified any rpath flags, then add them. temp_xrpath= for libdir in $xrpath; do func_replace_sysroot "$libdir" func_append temp_xrpath " -R$func_replace_sysroot_result" case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done if test yes != "$hardcode_into_libs" || test yes = "$build_old_libs"; then dependency_libs="$temp_xrpath $dependency_libs" fi fi # Make sure dlfiles contains only unique files that won't be dlpreopened old_dlfiles=$dlfiles dlfiles= for lib in $old_dlfiles; do case " $dlprefiles $dlfiles " in *" $lib "*) ;; *) func_append dlfiles " $lib" ;; esac done # Make sure dlprefiles contains only unique files old_dlprefiles=$dlprefiles dlprefiles= for lib in $old_dlprefiles; do case "$dlprefiles " in *" $lib "*) ;; *) func_append dlprefiles " $lib" ;; esac done if test yes = "$build_libtool_libs"; then if test -n "$rpath"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) # these systems don't actually have a c library (as such)! ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C library is in the System framework func_append deplibs " System.ltframework" ;; *-*-netbsd*) # Don't link with libc until the a.out ld.so is fixed. ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-midnightbsd*) # Do not include libc due to us having libc/libc_r. ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work ;; *) # Add libc to deplibs on all other systems if necessary. if test yes = "$build_libtool_need_lc"; then func_append deplibs " -lc" fi ;; esac fi # Transform deplibs into only deplibs that can be linked in shared. name_save=$name libname_save=$libname release_save=$release versuffix_save=$versuffix major_save=$major # I'm not sure if I'm treating the release correctly. I think # release should show up in the -l (ie -lgmp5) so we don't want to # add it in twice. Is that correct? release= versuffix= major= newdeplibs= droppeddeps=no case $deplibs_check_method in pass_all) # Don't check for shared/static. Everything works. # This might be a little naive. We might want to check # whether the library exists or not. But this is on # osf3 & osf4 and I'm not really sure... Just # implementing what was already the behavior. newdeplibs=$deplibs ;; test_compile) # This code stresses the "libraries are programs" paradigm to its # limits. Maybe even breaks it. We compile a program, linking it # against the deplibs as a proxy for the library. Then we can check # whether they linked in statically or dynamically with ldd. $opt_dry_run || $RM conftest.c cat > conftest.c </dev/null` $nocaseglob else potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` fi for potent_lib in $potential_libs; do # Follow soft links. if ls -lLd "$potent_lib" 2>/dev/null | $GREP " -> " >/dev/null; then continue fi # The statement above tries to avoid entering an # endless loop below, in case of cyclic links. # We might still enter an endless loop, since a link # loop can be closed while we follow links, # but so what? potlib=$potent_lib while test -h "$potlib" 2>/dev/null; do potliblink=`ls -ld $potlib | $SED 's/.* -> //'` case $potliblink in [\\/]* | [A-Za-z]:[\\/]*) potlib=$potliblink;; *) potlib=`$ECHO "$potlib" | $SED 's|[^/]*$||'`"$potliblink";; esac done if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | $SED -e 10q | $EGREP "$file_magic_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib= break 2 fi done done fi if test -n "$a_deplib"; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib"; then $ECHO "*** with $libname but no candidates were found. (...for file magic test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a file magic. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` for a_deplib in $deplibs; do case $a_deplib in -l*) func_stripname -l '' "$a_deplib" name=$func_stripname_result if test yes = "$allow_libtool_libs_with_static_runtimes"; then case " $predeps $postdeps " in *" $a_deplib "*) func_append newdeplibs " $a_deplib" a_deplib= ;; esac fi if test -n "$a_deplib"; then libname=`eval "\\$ECHO \"$libname_spec\""` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do potential_libs=`ls $i/$libname[.-]* 2>/dev/null` for potent_lib in $potential_libs; do potlib=$potent_lib # see symlink-check above in file_magic test if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ $EGREP "$match_pattern_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib= break 2 fi done done fi if test -n "$a_deplib"; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib"; then $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a regex pattern. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; none | unknown | *) newdeplibs= tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` if test yes = "$allow_libtool_libs_with_static_runtimes"; then for i in $predeps $postdeps; do # can't use Xsed below, because $i might contain '/' tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s|$i||"` done fi case $tmp_deplibs in *[!\ \ ]*) echo if test none = "$deplibs_check_method"; then echo "*** Warning: inter-library dependencies are not supported in this platform." else echo "*** Warning: inter-library dependencies are not known to be supported." fi echo "*** All declared inter-library dependencies are being dropped." droppeddeps=yes ;; esac ;; esac versuffix=$versuffix_save major=$major_save release=$release_save libname=$libname_save name=$name_save case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library with the System framework newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac if test yes = "$droppeddeps"; then if test yes = "$module"; then echo echo "*** Warning: libtool could not satisfy all declared inter-library" $ECHO "*** dependencies of module $libname. Therefore, libtool will create" echo "*** a static module, that should work as long as the dlopening" echo "*** application is linked with the -dlopen flag." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using 'nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** 'nm' from GNU binutils and a full rebuild may help." fi if test no = "$build_old_libs"; then oldlibs=$output_objdir/$libname.$libext build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi else echo "*** The inter-library dependencies that have been dropped here will be" echo "*** automatically added whenever a program is linked with this library" echo "*** or is declared to -dlopen it." if test no = "$allow_undefined"; then echo echo "*** Since this library must not contain undefined symbols," echo "*** because either the platform does not support them or" echo "*** it was explicitly requested with -no-undefined," echo "*** libtool will only create a static version of it." if test no = "$build_old_libs"; then oldlibs=$output_objdir/$libname.$libext build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi fi fi # Done checking deplibs! deplibs=$newdeplibs fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" case $host in *-*-darwin*) newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done deplibs=$new_libs # All the library-specific variables (install_libdir is set above). library_names= old_library= dlname= # Test again, we may have decided not to build it any more if test yes = "$build_libtool_libs"; then # Remove $wl instances when linking with ld. # FIXME: should test the right _cmds variable. case $archive_cmds in *\$LD\ *) wl= ;; esac if test yes = "$hardcode_into_libs"; then # Hardcode the library paths hardcode_libdirs= dep_rpath= rpath=$finalize_rpath test relink = "$opt_mode" || rpath=$compile_rpath$rpath for libdir in $rpath; do if test -n "$hardcode_libdir_flag_spec"; then func_replace_sysroot "$libdir" libdir=$func_replace_sysroot_result func_stripname '=' '' "$libdir" libdir=$func_stripname_result if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs=$libdir else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append dep_rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir=$hardcode_libdirs eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" fi if test -n "$runpath_var" && test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" fi test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" fi shlibpath=$finalize_shlibpath test relink = "$opt_mode" || shlibpath=$compile_shlibpath$shlibpath if test -n "$shlibpath"; then eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" fi # Get the real and link names of the library. eval shared_ext=\"$shrext_cmds\" eval library_names=\"$library_names_spec\" set dummy $library_names shift realname=$1 shift if test -n "$soname_spec"; then eval soname=\"$soname_spec\" else soname=$realname fi if test -z "$dlname"; then dlname=$soname fi lib=$output_objdir/$realname linknames= for link do func_append linknames " $link" done # Use standard objects if they are pic test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` test "X$libobjs" = "X " && libobjs= delfiles= if test -n "$export_symbols" && test -n "$include_expsyms"; then $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" export_symbols=$output_objdir/$libname.uexp func_append delfiles " $export_symbols" fi orig_export_symbols= case $host_os in cygwin* | mingw* | cegcc*) if test -n "$export_symbols" && test -z "$export_symbols_regex"; then # exporting using user supplied symfile func_dll_def_p "$export_symbols" || { # and it's NOT already a .def file. Must figure out # which of the given symbols are data symbols and tag # them as such. So, trigger use of export_symbols_cmds. # export_symbols gets reassigned inside the "prepare # the list of exported symbols" if statement, so the # include_expsyms logic still works. orig_export_symbols=$export_symbols export_symbols= always_export_symbols=yes } fi ;; esac # Prepare the list of exported symbols if test -z "$export_symbols"; then if test yes = "$always_export_symbols" || test -n "$export_symbols_regex"; then func_verbose "generating symbol list for '$libname.la'" export_symbols=$output_objdir/$libname.exp $opt_dry_run || $RM $export_symbols cmds=$export_symbols_cmds save_ifs=$IFS; IFS='~' for cmd1 in $cmds; do IFS=$save_ifs # Take the normal branch if the nm_file_list_spec branch # doesn't work or if tool conversion is not needed. case $nm_file_list_spec~$to_tool_file_cmd in *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) try_normal_branch=yes eval cmd=\"$cmd1\" func_len " $cmd" len=$func_len_result ;; *) try_normal_branch=no ;; esac if test yes = "$try_normal_branch" \ && { test "$len" -lt "$max_cmd_len" \ || test "$max_cmd_len" -le -1; } then func_show_eval "$cmd" 'exit $?' skipped_export=false elif test -n "$nm_file_list_spec"; then func_basename "$output" output_la=$func_basename_result save_libobjs=$libobjs save_output=$output output=$output_objdir/$output_la.nm func_to_tool_file "$output" libobjs=$nm_file_list_spec$func_to_tool_file_result func_append delfiles " $output" func_verbose "creating $NM input file list: $output" for obj in $save_libobjs; do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > "$output" eval cmd=\"$cmd1\" func_show_eval "$cmd" 'exit $?' output=$save_output libobjs=$save_libobjs skipped_export=false else # The command line is too long to execute in one step. func_verbose "using reloadable object file for export list..." skipped_export=: # Break out early, otherwise skipped_export may be # set to false by a later but shorter cmd. break fi done IFS=$save_ifs if test -n "$export_symbols_regex" && test : != "$skipped_export"; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi fi if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols=$export_symbols test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test : != "$skipped_export" && test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for '$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands, which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi tmp_deplibs= for test_deplib in $deplibs; do case " $convenience " in *" $test_deplib "*) ;; *) func_append tmp_deplibs " $test_deplib" ;; esac done deplibs=$tmp_deplibs if test -n "$convenience"; then if test -n "$whole_archive_flag_spec" && test yes = "$compiler_needs_object" && test -z "$libobjs"; then # extract the archives, so we have objects to list. # TODO: could optimize this to just extract one archive. whole_archive_flag_spec= fi if test -n "$whole_archive_flag_spec"; then save_libobjs=$libobjs eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= else gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $convenience func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi fi if test yes = "$thread_safe" && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" func_append linker_flags " $flag" fi # Make a backup of the uninstalled library when relinking if test relink = "$opt_mode"; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? fi # Do each of the archive commands. if test yes = "$module" && test -n "$module_cmds"; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then eval test_cmds=\"$module_expsym_cmds\" cmds=$module_expsym_cmds else eval test_cmds=\"$module_cmds\" cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then eval test_cmds=\"$archive_expsym_cmds\" cmds=$archive_expsym_cmds else eval test_cmds=\"$archive_cmds\" cmds=$archive_cmds fi fi if test : != "$skipped_export" && func_len " $test_cmds" && len=$func_len_result && test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then : else # The command line is too long to link in one step, link piecewise # or, if using GNU ld and skipped_export is not :, use a linker # script. # Save the value of $output and $libobjs because we want to # use them later. If we have whole_archive_flag_spec, we # want to use save_libobjs as it was before # whole_archive_flag_spec was expanded, because we can't # assume the linker understands whole_archive_flag_spec. # This may have to be revisited, in case too many # convenience libraries get linked in and end up exceeding # the spec. if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then save_libobjs=$libobjs fi save_output=$output func_basename "$output" output_la=$func_basename_result # Clear the reloadable object creation command queue and # initialize k to one. test_cmds= concat_cmds= objlist= last_robj= k=1 if test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then output=$output_objdir/$output_la.lnkscript func_verbose "creating GNU ld script: $output" echo 'INPUT (' > $output for obj in $save_libobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done echo ')' >> $output func_append delfiles " $output" func_to_tool_file "$output" output=$func_to_tool_file_result elif test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then output=$output_objdir/$output_la.lnk func_verbose "creating linker input file list: $output" : > $output set x $save_libobjs shift firstobj= if test yes = "$compiler_needs_object"; then firstobj="$1 " shift fi for obj do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done func_append delfiles " $output" func_to_tool_file "$output" output=$firstobj\"$file_list_spec$func_to_tool_file_result\" else if test -n "$save_libobjs"; then func_verbose "creating reloadable object files..." output=$output_objdir/$output_la-$k.$objext eval test_cmds=\"$reload_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 # Loop over the list of objects to be linked. for obj in $save_libobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result if test -z "$objlist" || test "$len" -lt "$max_cmd_len"; then func_append objlist " $obj" else # The command $test_cmds is almost too long, add a # command to the queue. if test 1 -eq "$k"; then # The first file doesn't have a previous command to add. reload_objs=$objlist eval concat_cmds=\"$reload_cmds\" else # All subsequent reloadable object files will link in # the last one created. reload_objs="$objlist $last_robj" eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" fi last_robj=$output_objdir/$output_la-$k.$objext func_arith $k + 1 k=$func_arith_result output=$output_objdir/$output_la-$k.$objext objlist=" $obj" func_len " $last_robj" func_arith $len0 + $func_len_result len=$func_arith_result fi done # Handle the remaining objects by creating one last # reloadable object file. All subsequent reloadable object # files will link in the last one created. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ reload_objs="$objlist $last_robj" eval concat_cmds=\"\$concat_cmds$reload_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi func_append delfiles " $output" else output= fi ${skipped_export-false} && { func_verbose "generating symbol list for '$libname.la'" export_symbols=$output_objdir/$libname.exp $opt_dry_run || $RM $export_symbols libobjs=$output # Append the command to create the export file. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi } test -n "$save_libobjs" && func_verbose "creating a temporary reloadable object file: $output" # Loop through the commands generated above and execute them. save_ifs=$IFS; IFS='~' for cmd in $concat_cmds; do IFS=$save_ifs $opt_quiet || { func_quote_arg expand,pretty "$cmd" eval "func_echo $func_quote_arg_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test relink = "$opt_mode"; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS=$save_ifs if test -n "$export_symbols_regex" && ${skipped_export-false}; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi ${skipped_export-false} && { if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols=$export_symbols test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for '$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands, which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi } libobjs=$output # Restore the value of output. output=$save_output if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= fi # Expand the library linking commands again to reset the # value of $libobjs for piecewise linking. # Do each of the archive commands. if test yes = "$module" && test -n "$module_cmds"; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then cmds=$module_expsym_cmds else cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then cmds=$archive_expsym_cmds else cmds=$archive_cmds fi fi fi if test -n "$delfiles"; then # Append the command to remove temporary files to $cmds. eval cmds=\"\$cmds~\$RM $delfiles\" fi # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi save_ifs=$IFS; IFS='~' for cmd in $cmds; do IFS=$sp$nl eval cmd=\"$cmd\" IFS=$save_ifs $opt_quiet || { func_quote_arg expand,pretty "$cmd" eval "func_echo $func_quote_arg_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test relink = "$opt_mode"; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS=$save_ifs # Restore the uninstalled library and exit if test relink = "$opt_mode"; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? if test -n "$convenience"; then if test -z "$whole_archive_flag_spec"; then func_show_eval '${RM}r "$gentop"' fi fi exit $EXIT_SUCCESS fi # Create links to the real library. for linkname in $linknames; do if test "$realname" != "$linkname"; then func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' fi done # If -module or -export-dynamic was specified, set the dlname. if test yes = "$module" || test yes = "$export_dynamic"; then # On all known operating systems, these are identical. dlname=$soname fi fi ;; obj) if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then func_warning "'-dlopen' is ignored for objects" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "'-l' and '-L' are ignored for objects" ;; esac test -n "$rpath" && \ func_warning "'-rpath' is ignored for objects" test -n "$xrpath" && \ func_warning "'-R' is ignored for objects" test -n "$vinfo" && \ func_warning "'-version-info' is ignored for objects" test -n "$release" && \ func_warning "'-release' is ignored for objects" case $output in *.lo) test -n "$objs$old_deplibs" && \ func_fatal_error "cannot build library object '$output' from non-libtool objects" libobj=$output func_lo2o "$libobj" obj=$func_lo2o_result ;; *) libobj= obj=$output ;; esac # Delete the old objects. $opt_dry_run || $RM $obj $libobj # Objects from convenience libraries. This assumes # single-version convenience libraries. Whenever we create # different ones for PIC/non-PIC, this we'll have to duplicate # the extraction. reload_conv_objs= gentop= # if reload_cmds runs $LD directly, get rid of -Wl from # whole_archive_flag_spec and hope we can get by with turning comma # into space. case $reload_cmds in *\$LD[\ \$]*) wl= ;; esac if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" test -n "$wl" || tmp_whole_archive_flags=`$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` reload_conv_objs=$reload_objs\ $tmp_whole_archive_flags else gentop=$output_objdir/${obj}x func_append generated " $gentop" func_extract_archives $gentop $convenience reload_conv_objs="$reload_objs $func_extract_archives_result" fi fi # If we're not building shared, we need to use non_pic_objs test yes = "$build_libtool_libs" || libobjs=$non_pic_objects # Create the old-style object. reload_objs=$objs$old_deplibs' '`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; /\.lib$/d; $lo2o" | $NL2SP`' '$reload_conv_objs output=$obj func_execute_cmds "$reload_cmds" 'exit $?' # Exit if we aren't doing a library object file. if test -z "$libobj"; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS fi test yes = "$build_libtool_libs" || { if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi # Create an invalid libtool object if no PIC, so that we don't # accidentally link it into a program. # $show "echo timestamp > $libobj" # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? exit $EXIT_SUCCESS } if test -n "$pic_flag" || test default != "$pic_mode"; then # Only do commands if we really have different PIC objects. reload_objs="$libobjs $reload_conv_objs" output=$libobj func_execute_cmds "$reload_cmds" 'exit $?' fi if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS ;; prog) case $host in *cygwin*) func_stripname '' '.exe' "$output" output=$func_stripname_result.exe;; esac test -n "$vinfo" && \ func_warning "'-version-info' is ignored for programs" test -n "$release" && \ func_warning "'-release' is ignored for programs" $preload \ && test unknown,unknown,unknown = "$dlopen_support,$dlopen_self,$dlopen_self_static" \ && func_warning "'LT_INIT([dlopen])' not used. Assuming no dlopen support." case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac case $host in *-*-darwin*) # Don't allow lazy linking, it breaks C++ global constructors # But is supposedly fixed on 10.4 or later (yay!). if test CXX = "$tagname"; then case ${MACOSX_DEPLOYMENT_TARGET-10.0} in 10.[0123]) func_append compile_command " $wl-bind_at_load" func_append finalize_command " $wl-bind_at_load" ;; esac fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $compile_deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $compile_deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done compile_deplibs=$new_libs func_append compile_command " $compile_deplibs" func_append finalize_command " $finalize_deplibs" if test -n "$rpath$xrpath"; then # If the user specified any rpath flags, then add them. for libdir in $rpath $xrpath; do # This is the magic to use -rpath. case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done fi # Now hardcode the library paths rpath= hardcode_libdirs= for libdir in $compile_rpath $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then func_replace_sysroot "$libdir" libdir=$func_replace_sysroot_result func_stripname '=' '' "$libdir" libdir=$func_stripname_result if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs=$libdir else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append perm_rpath " $libdir" ;; esac fi case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`$ECHO "$libdir" | $SED -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$libdir:"*) ;; ::) dllsearchpath=$libdir;; *) func_append dllsearchpath ":$libdir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir=$hardcode_libdirs eval rpath=\" $hardcode_libdir_flag_spec\" fi compile_rpath=$rpath rpath= hardcode_libdirs= for libdir in $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs=$libdir else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$finalize_perm_rpath " in *" $libdir "*) ;; *) func_append finalize_perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir=$hardcode_libdirs eval rpath=\" $hardcode_libdir_flag_spec\" fi finalize_rpath=$rpath if test -n "$libobjs" && test yes = "$build_old_libs"; then # Transform all the library objects into standard objects. compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` fi func_generate_dlsyms "$outputname" "@PROGRAM@" false # template prelinking step if test -n "$prelink_cmds"; then func_execute_cmds "$prelink_cmds" 'exit $?' fi wrappers_required=: case $host in *cegcc* | *mingw32ce*) # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. wrappers_required=false ;; *cygwin* | *mingw* ) test yes = "$build_libtool_libs" || wrappers_required=false ;; *) if test no = "$need_relink" || test yes != "$build_libtool_libs"; then wrappers_required=false fi ;; esac $wrappers_required || { # Replace the output file specification. compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` link_command=$compile_command$compile_rpath # We have no uninstalled library dependencies, so finalize right now. exit_status=0 func_show_eval "$link_command" 'exit_status=$?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Delete the generated files. if test -f "$output_objdir/${outputname}S.$objext"; then func_show_eval '$RM "$output_objdir/${outputname}S.$objext"' fi exit $exit_status } if test -n "$compile_shlibpath$finalize_shlibpath"; then compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" fi if test -n "$finalize_shlibpath"; then finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" fi compile_var= finalize_var= if test -n "$runpath_var"; then if test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done compile_var="$runpath_var=\"$rpath\$$runpath_var\" " fi if test -n "$finalize_perm_rpath"; then # We should set the runpath_var. rpath= for dir in $finalize_perm_rpath; do func_append rpath "$dir:" done finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " fi fi if test yes = "$no_install"; then # We don't need to create a wrapper script. link_command=$compile_var$compile_command$compile_rpath # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` # Delete the old output file. $opt_dry_run || $RM $output # Link the executable and exit func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi exit $EXIT_SUCCESS fi case $hardcode_action,$fast_install in relink,*) # Fast installation is not supported link_command=$compile_var$compile_command$compile_rpath relink_command=$finalize_var$finalize_command$finalize_rpath func_warning "this platform does not like uninstalled shared libraries" func_warning "'$output' will be relinked during installation" ;; *,yes) link_command=$finalize_var$compile_command$finalize_rpath relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` ;; *,no) link_command=$compile_var$compile_command$compile_rpath relink_command=$finalize_var$finalize_command$finalize_rpath ;; *,needless) link_command=$finalize_var$compile_command$finalize_rpath relink_command= ;; esac # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` # Delete the old output files. $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output_objdir/$outputname" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Now create the wrapper script. func_verbose "creating $output" # Quote the relink command for shipping. if test -n "$relink_command"; then # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_arg pretty "$var_value" relink_command="$var=$func_quote_arg_result; export $var; $relink_command" fi done func_quote eval cd "`pwd`" func_quote_arg pretty,unquoted "($func_quote_result; $relink_command)" relink_command=$func_quote_arg_unquoted_result fi # Only actually do things if not in dry run mode. $opt_dry_run || { # win32 will think the script is a binary if it has # a .exe suffix, so we strip it off here. case $output in *.exe) func_stripname '' '.exe' "$output" output=$func_stripname_result ;; esac # test for cygwin because mv fails w/o .exe extensions case $host in *cygwin*) exeext=.exe func_stripname '' '.exe' "$outputname" outputname=$func_stripname_result ;; *) exeext= ;; esac case $host in *cygwin* | *mingw* ) func_dirname_and_basename "$output" "" "." output_name=$func_basename_result output_path=$func_dirname_result cwrappersource=$output_path/$objdir/lt-$output_name.c cwrapper=$output_path/$output_name.exe $RM $cwrappersource $cwrapper trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 func_emit_cwrapperexe_src > $cwrappersource # The wrapper executable is built using the $host compiler, # because it contains $host paths and files. If cross- # compiling, it, like the target executable, must be # executed on the $host or under an emulation environment. $opt_dry_run || { $LTCC $LTCFLAGS -o $cwrapper $cwrappersource $STRIP $cwrapper } # Now, create the wrapper script for func_source use: func_ltwrapper_scriptname $cwrapper $RM $func_ltwrapper_scriptname_result trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 $opt_dry_run || { # note: this script will not be executed, so do not chmod. if test "x$build" = "x$host"; then $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result else func_emit_wrapper no > $func_ltwrapper_scriptname_result fi } ;; * ) $RM $output trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 func_emit_wrapper no > $output chmod +x $output ;; esac } exit $EXIT_SUCCESS ;; esac # See if we need to build an old-fashioned archive. for oldlib in $oldlibs; do case $build_libtool_libs in convenience) oldobjs="$libobjs_save $symfileobj" addlibs=$convenience build_libtool_libs=no ;; module) oldobjs=$libobjs_save addlibs=$old_convenience build_libtool_libs=no ;; *) oldobjs="$old_deplibs $non_pic_objects" $preload && test -f "$symfileobj" \ && func_append oldobjs " $symfileobj" addlibs=$old_convenience ;; esac if test -n "$addlibs"; then gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $addlibs func_append oldobjs " $func_extract_archives_result" fi # Do each command in the archive commands. if test -n "$old_archive_from_new_cmds" && test yes = "$build_libtool_libs"; then cmds=$old_archive_from_new_cmds else # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append oldobjs " $func_extract_archives_result" fi # POSIX demands no paths to be encoded in archives. We have # to avoid creating archives with duplicate basenames if we # might have to extract them afterwards, e.g., when creating a # static archive out of a convenience library, or when linking # the entirety of a libtool archive into another (currently # not supported by libtool). if (for obj in $oldobjs do func_basename "$obj" $ECHO "$func_basename_result" done | sort | sort -uc >/dev/null 2>&1); then : else echo "copying selected object files to avoid basename conflicts..." gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_mkdir_p "$gentop" save_oldobjs=$oldobjs oldobjs= counter=1 for obj in $save_oldobjs do func_basename "$obj" objbase=$func_basename_result case " $oldobjs " in " ") oldobjs=$obj ;; *[\ /]"$objbase "*) while :; do # Make sure we don't pick an alternate name that also # overlaps. newobj=lt$counter-$objbase func_arith $counter + 1 counter=$func_arith_result case " $oldobjs " in *[\ /]"$newobj "*) ;; *) if test ! -f "$gentop/$newobj"; then break; fi ;; esac done func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" func_append oldobjs " $gentop/$newobj" ;; *) func_append oldobjs " $obj" ;; esac done fi func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result eval cmds=\"$old_archive_cmds\" func_len " $cmds" len=$func_len_result if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then cmds=$old_archive_cmds elif test -n "$archiver_list_spec"; then func_verbose "using command file archive linking..." for obj in $oldobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > $output_objdir/$libname.libcmd func_to_tool_file "$output_objdir/$libname.libcmd" oldobjs=" $archiver_list_spec$func_to_tool_file_result" cmds=$old_archive_cmds else # the command line is too long to link in one step, link in parts func_verbose "using piecewise archive linking..." save_RANLIB=$RANLIB RANLIB=: objlist= concat_cmds= save_oldobjs=$oldobjs oldobjs= # Is there a better way of finding the last object in the list? for obj in $save_oldobjs do last_oldobj=$obj done eval test_cmds=\"$old_archive_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 for obj in $save_oldobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result func_append objlist " $obj" if test "$len" -lt "$max_cmd_len"; then : else # the above command should be used before it gets too long oldobjs=$objlist if test "$obj" = "$last_oldobj"; then RANLIB=$save_RANLIB fi test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\$concat_cmds$old_archive_cmds\" objlist= len=$len0 fi done RANLIB=$save_RANLIB oldobjs=$objlist if test -z "$oldobjs"; then eval cmds=\"\$concat_cmds\" else eval cmds=\"\$concat_cmds~\$old_archive_cmds\" fi fi fi func_execute_cmds "$cmds" 'exit $?' done test -n "$generated" && \ func_show_eval "${RM}r$generated" # Now create the libtool archive. case $output in *.la) old_library= test yes = "$build_old_libs" && old_library=$libname.$libext func_verbose "creating $output" # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_arg pretty,unquoted "$var_value" relink_command="$var=$func_quote_arg_unquoted_result; export $var; $relink_command" fi done # Quote the link command for shipping. func_quote eval cd "`pwd`" relink_command="($func_quote_result; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" func_quote_arg pretty,unquoted "$relink_command" relink_command=$func_quote_arg_unquoted_result if test yes = "$hardcode_automatic"; then relink_command= fi # Only create the output if not a dry run. $opt_dry_run || { for installed in no yes; do if test yes = "$installed"; then if test -z "$install_libdir"; then break fi output=$output_objdir/${outputname}i # Replace all uninstalled libtool libraries with the installed ones newdependency_libs= for deplib in $dependency_libs; do case $deplib in *.la) func_basename "$deplib" name=$func_basename_result func_resolve_sysroot "$deplib" eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` test -z "$libdir" && \ func_fatal_error "'$deplib' is not a valid libtool archive" func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" ;; -L*) func_stripname -L '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -L$func_replace_sysroot_result" ;; -R*) func_stripname -R '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -R$func_replace_sysroot_result" ;; *) func_append newdependency_libs " $deplib" ;; esac done dependency_libs=$newdependency_libs newdlfiles= for lib in $dlfiles; do case $lib in *.la) func_basename "$lib" name=$func_basename_result eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "'$lib' is not a valid libtool archive" func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" ;; *) func_append newdlfiles " $lib" ;; esac done dlfiles=$newdlfiles newdlprefiles= for lib in $dlprefiles; do case $lib in *.la) # Only pass preopened files to the pseudo-archive (for # eventual linking with the app. that links it) if we # didn't already link the preopened objects directly into # the library: func_basename "$lib" name=$func_basename_result eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "'$lib' is not a valid libtool archive" func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" ;; esac done dlprefiles=$newdlprefiles else newdlfiles= for lib in $dlfiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlfiles " $abs" done dlfiles=$newdlfiles newdlprefiles= for lib in $dlprefiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlprefiles " $abs" done dlprefiles=$newdlprefiles fi $RM $output # place dlname in correct position for cygwin # In fact, it would be nice if we could use this code for all target # systems that can't hard-code library paths into their executables # and that have no shared library path variable independent of PATH, # but it turns out we can't easily determine that from inspecting # libtool variables, so we have to hard-code the OSs to which it # applies here; at the moment, that means platforms that use the PE # object format with DLL files. See the long comment at the top of # tests/bindir.at for full details. tdlname=$dlname case $host,$output,$installed,$module,$dlname in *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) # If a -bindir argument was supplied, place the dll there. if test -n "$bindir"; then func_relative_path "$install_libdir" "$bindir" tdlname=$func_relative_path_result/$dlname else # Otherwise fall back on heuristic. tdlname=../bin/$dlname fi ;; esac $ECHO > $output "\ # $outputname - a libtool library file # Generated by $PROGRAM (GNU $PACKAGE) $VERSION # # Please DO NOT delete this file! # It is necessary for linking the library. # The name that we can dlopen(3). dlname='$tdlname' # Names of this library. library_names='$library_names' # The name of the static archive. old_library='$old_library' # Linker flags that cannot go in dependency_libs. inherited_linker_flags='$new_inherited_linker_flags' # Libraries that this one depends upon. dependency_libs='$dependency_libs' # Names of additional weak libraries provided by this library weak_library_names='$weak_libs' # Version information for $libname. current=$current age=$age revision=$revision # Is this an already installed library? installed=$installed # Should we warn about portability when linking against -modules? shouldnotlink=$module # Files to dlopen/dlpreopen dlopen='$dlfiles' dlpreopen='$dlprefiles' # Directory that this library needs to be installed in: libdir='$install_libdir'" if test no,yes = "$installed,$need_relink"; then $ECHO >> $output "\ relink_command=\"$relink_command\"" fi done } # Do a symbolic link so that the libtool archive can be found in # LD_LIBRARY_PATH before the program is installed. func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' ;; esac exit $EXIT_SUCCESS } if test link = "$opt_mode" || test relink = "$opt_mode"; then func_mode_link ${1+"$@"} fi # func_mode_uninstall arg... func_mode_uninstall () { $debug_cmd RM=$nonopt files= rmforce=false exit_status=0 # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic=$magic for arg do case $arg in -f) func_append RM " $arg"; rmforce=: ;; -*) func_append RM " $arg" ;; *) func_append files " $arg" ;; esac done test -z "$RM" && \ func_fatal_help "you must specify an RM program" rmdirs= for file in $files; do func_dirname "$file" "" "." dir=$func_dirname_result if test . = "$dir"; then odir=$objdir else odir=$dir/$objdir fi func_basename "$file" name=$func_basename_result test uninstall = "$opt_mode" && odir=$dir # Remember odir for removal later, being careful to avoid duplicates if test clean = "$opt_mode"; then case " $rmdirs " in *" $odir "*) ;; *) func_append rmdirs " $odir" ;; esac fi # Don't error if the file doesn't exist and rm -f was used. if { test -L "$file"; } >/dev/null 2>&1 || { test -h "$file"; } >/dev/null 2>&1 || test -f "$file"; then : elif test -d "$file"; then exit_status=1 continue elif $rmforce; then continue fi rmfiles=$file case $name in *.la) # Possibly a libtool archive, so verify it. if func_lalib_p "$file"; then func_source $dir/$name # Delete the libtool libraries and symlinks. for n in $library_names; do func_append rmfiles " $odir/$n" done test -n "$old_library" && func_append rmfiles " $odir/$old_library" case $opt_mode in clean) case " $library_names " in *" $dlname "*) ;; *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; esac test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" ;; uninstall) if test -n "$library_names"; then # Do each command in the postuninstall commands. func_execute_cmds "$postuninstall_cmds" '$rmforce || exit_status=1' fi if test -n "$old_library"; then # Do each command in the old_postuninstall commands. func_execute_cmds "$old_postuninstall_cmds" '$rmforce || exit_status=1' fi # FIXME: should reinstall the best remaining shared library. ;; esac fi ;; *.lo) # Possibly a libtool object, so verify it. if func_lalib_p "$file"; then # Read the .lo file func_source $dir/$name # Add PIC object to the list of files to remove. if test -n "$pic_object" && test none != "$pic_object"; then func_append rmfiles " $dir/$pic_object" fi # Add non-PIC object to the list of files to remove. if test -n "$non_pic_object" && test none != "$non_pic_object"; then func_append rmfiles " $dir/$non_pic_object" fi fi ;; *) if test clean = "$opt_mode"; then noexename=$name case $file in *.exe) func_stripname '' '.exe' "$file" file=$func_stripname_result func_stripname '' '.exe' "$name" noexename=$func_stripname_result # $file with .exe has already been added to rmfiles, # add $file without .exe func_append rmfiles " $file" ;; esac # Do a test to see if this is a libtool program. if func_ltwrapper_p "$file"; then if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" relink_command= func_source $func_ltwrapper_scriptname_result func_append rmfiles " $func_ltwrapper_scriptname_result" else relink_command= func_source $dir/$noexename fi # note $name still contains .exe if it was in $file originally # as does the version of $file that was added into $rmfiles func_append rmfiles " $odir/$name $odir/${name}S.$objext" if test yes = "$fast_install" && test -n "$relink_command"; then func_append rmfiles " $odir/lt-$name" fi if test "X$noexename" != "X$name"; then func_append rmfiles " $odir/lt-$noexename.c" fi fi fi ;; esac func_show_eval "$RM $rmfiles" 'exit_status=1' done # Try to remove the $objdir's in the directories where we deleted files for dir in $rmdirs; do if test -d "$dir"; then func_show_eval "rmdir $dir >/dev/null 2>&1" fi done exit $exit_status } if test uninstall = "$opt_mode" || test clean = "$opt_mode"; then func_mode_uninstall ${1+"$@"} fi test -z "$opt_mode" && { help=$generic_help func_fatal_help "you must specify a MODE" } test -z "$exec_cmd" && \ func_fatal_help "invalid operation mode '$opt_mode'" if test -n "$exec_cmd"; then eval exec "$exec_cmd" exit $EXIT_FAILURE fi exit $exit_status # The TAGs below are defined such that we never get into a situation # where we disable both kinds of libraries. Given conflicting # choices, we go for a static library, that is the most portable, # since we can't tell whether shared libraries were disabled because # the user asked for that or because the platform doesn't support # them. This is particularly important on AIX, because we don't # support having both static and shared libraries enabled at the same # time on that platform, so we default to a shared-only configuration. # If a disable-shared tag is given, we'll fallback to a static-only # configuration. But we'll never go from static-only to shared-only. # ### BEGIN LIBTOOL TAG CONFIG: disable-shared build_libtool_libs=no build_old_libs=yes # ### END LIBTOOL TAG CONFIG: disable-shared # ### BEGIN LIBTOOL TAG CONFIG: disable-static build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` # ### END LIBTOOL TAG CONFIG: disable-static # Local Variables: # mode:shell-script # sh-indentation:2 # End: libtorrent-0.16.11/doc/0000755000000000000000000000000015175073434010331 5libtorrent-0.16.11/doc/main.xml0000644000000000000000000000035415175073411011714 ]> libTorrent Manual &torrent_section; &http_section; libtorrent-0.16.11/doc/http.xml0000644000000000000000000000477115175073411011756 Http handler
Introduction LibTorrent depends on the client to handle http downloads, thus the library does not have a dependency on any specific http library. The library provides a base class named torrent::Http with virtual member functions that the client must implement, and a sigc++ slot which must be set to create an instance of the derived torrent::Http class when called. The torrent::Http class and the factory slot related functions can be found in the header "torrent/http.h". The http handler should have reasonable connection timeouts, be non-blocking and not do reconnects on failed downloads.
Factory Slot The client registers the desired factory slot with the static torrent::Http::set_factory member function. Using sigc++ the client may bind values to the arguments of their function to avoid depending on globals. The factory slot must return a pointer to a new instance with the base type torrent::Http, and the caller takes responsibility of deleting the object. (Note: consider making the cleanup a slot)
Output Stream The data downloaded by the http handler is to be written to torrent::Http::m_stream which is a pointer to an std::iostream. The http handler must not change any of the flags on the stream.
Start Http::start is called by the library when it wishes to initiate a http download. Your Http derived class must implement this function. It must be non-blocking and thread-safe. This means that if a seperate thread is used for downloading then it must not emit any signal while the main thread is inside the library.
close Http::close is used bu the library to stop and close a download. No signals may be emited after this. Http::m_data should not be cleared. The library may clear the Http::m_data pointer after this.
Signals There are two mutually exclusive signals that are called when the download has stopped. The signal torrent::Http::m_signalDone is called if the download was successful and torrent::Http::m_stream contains the complete data. Or if the download was unsuccessful for some reason, then torrent::Http::m_signalFailed is called with an error message.
libtorrent-0.16.11/doc/torrent.xml0000644000000000000000000000636515175073411012475 Torrent
State
Closed This is the initial state of a download. When switching to this mode, all tracker requests are closed and the bitfield of completed chunks is cleared. File paths can only be changed in this state. Functions for getting information on bitfields, chunk count and various others will return size 0 in this state. (TODO: Check which)
torrent::Download::is_open() == false; torrent::Download::is_active() == false; torrent::Download::is_tracker_busy() == false;
Open This is the state after a successfull call to torrent::Download::open(). This function throws torrent::local_error if the download could not be opened. All files in the download have been created and are open. The initial hash check must be done to get a valid bitfield of completed chunks.
torrent::Download::is_open() == true; torrent::Download::is_active() == false;
Active A download is active after calling torrent::Download::start(). Only downloads that are in an open state and has a valid bitfield of completed chunks can be activated.
torrent::Download::is_open() == true; torrent::Download::is_active() == true; torrent::Download::is_hash_checked() == true;
A tracker request will be made when torrent::Download::stop() is called on an active download. It is not required to wait for the tracker request to finish before calling torrent::Download::close(), but it is recommened so the tracker knows this client is not available.
File Paths The paths of files in a Download consists of two parts, the root directory and the paths of each file. The file paths are read from the torrent file and the files usually reside in the root directory. The root directory is by default "./" for single file torrents and "./[torrent_name]/" for multi-file torrents.
// Get and set the root directory. std::string torrent::Download::get_root_dir(); void torrent::Download::set_root_dir(const std::string& dir); // Get the torrent::Entry class for each file in the download. torrent::Entry torrent::Download::get_entry(uint32_t index); uint32_t torrent::Download::get_entry_size(); typedef std::list<std::string> torrent::Entry::Path; // Get and set the file path. std::string torrent::Entry::get_path(); const Path& torrent::Entry::get_path_list(); void torrent::Entry::set_path_list(const Path& l);
The modifications can only be done while the download is in a closed state. Modifying the file paths will not change the "info hash" part of the bencode'd torrent associated with the download. (TODO: When exporting, save root directory and file paths to another section of the torrent)
libtorrent-0.16.11/src/0000755000000000000000000000000015175073434010353 5libtorrent-0.16.11/src/Makefile.am0000644000000000000000000001065115175073411012325 SUBDIRS = torrent lib_LTLIBRARIES = libtorrent.la noinst_LTLIBRARIES = \ libtorrent_other.la libtorrent_la_LDFLAGS = -version-info $(LIBTORRENT_INTERFACE_VERSION_INFO) libtorrent_la_LIBADD = \ torrent/libtorrent_torrent.la \ libtorrent_other.la libtorrent_la_SOURCES = \ manager.cc \ manager.h \ runtime.cc \ runtime.h \ thread_main.cc \ thread_main.h libtorrent_other_la_SOURCES = \ data/chunk.cc \ data/chunk.h \ data/chunk_handle.h \ data/chunk_iterator.h \ data/chunk_list.cc \ data/chunk_list.h \ data/chunk_list_node.h \ data/chunk_part.cc \ data/chunk_part.h \ data/hash_check_queue.cc \ data/hash_check_queue.h \ data/hash_chunk.cc \ data/hash_chunk.h \ data/hash_queue.cc \ data/hash_queue.h \ data/hash_queue_node.cc \ data/hash_queue_node.h \ data/hash_torrent.cc \ data/hash_torrent.h \ data/memory_chunk.cc \ data/memory_chunk.h \ data/socket_file.cc \ data/socket_file.h \ data/thread_disk.cc \ data/thread_disk.h \ \ dht/dht_bucket.cc \ dht/dht_bucket.h \ dht/dht_hash_map.h \ dht/dht_node.cc \ dht/dht_node.h \ dht/dht_router.cc \ dht/dht_router.h \ dht/dht_server.cc \ dht/dht_server.h \ dht/dht_tracker.cc \ dht/dht_tracker.h \ dht/dht_transaction.cc \ dht/dht_transaction.h \ \ dht/transactions/dht_announce.cc \ dht/transactions/dht_announce.h \ dht/transactions/dht_search.cc \ dht/transactions/dht_search.h \ \ download/available_list.cc \ download/available_list.h \ download/chunk_selector.cc \ download/chunk_selector.h \ download/chunk_statistics.cc \ download/chunk_statistics.h \ download/delegator.cc \ download/delegator.h \ download/download_constructor.cc \ download/download_constructor.h \ download/download_main.cc \ download/download_main.h \ download/download_wrapper.cc \ download/download_wrapper.h \ \ net/address_list.cc \ net/address_list.h \ net/data_buffer.h \ net/curl_get.cc \ net/curl_get.h \ net/curl_socket.cc \ net/curl_socket.h \ net/curl_stack.cc \ net/curl_stack.h \ net/dns_cache.cc \ net/dns_cache.h \ net/dns_buffer.cc \ net/dns_buffer.h \ net/listen.cc \ net/listen.h \ net/protocol_buffer.h \ net/socket_datagram.cc \ net/socket_datagram.h \ net/socket_stream.cc \ net/socket_stream.h \ net/thread_net.cc \ net/thread_net.h \ net/throttle_internal.cc \ net/throttle_internal.h \ net/throttle_list.cc \ net/throttle_list.h \ net/throttle_node.h \ net/udns_resolver.cc \ net/udns_resolver.h \ net/udns_library.cc \ net/udns_library.h \ \ net/udns/config.h \ net/udns/udns.h \ \ protocol/encryption_info.h \ protocol/extensions.cc \ protocol/extensions.h \ protocol/handshake.cc \ protocol/handshake.h \ protocol/handshake_encryption.cc \ protocol/handshake_encryption.h \ protocol/handshake_manager.cc \ protocol/handshake_manager.h \ protocol/initial_seed.cc \ protocol/initial_seed.h \ protocol/peer_chunks.h \ protocol/peer_connection_base.cc \ protocol/peer_connection_base.h \ protocol/peer_connection_leech.cc \ protocol/peer_connection_leech.h \ protocol/peer_connection_metadata.cc \ protocol/peer_connection_metadata.h \ protocol/peer_factory.cc \ protocol/peer_factory.h \ protocol/protocol_base.h \ protocol/request_list.cc \ protocol/request_list.h \ \ tracker/thread_tracker.cc \ tracker/thread_tracker.h \ tracker/tracker_controller.cc \ tracker/tracker_controller.h \ tracker/tracker_dht.cc \ tracker/tracker_dht.h \ tracker/tracker_http.cc \ tracker/tracker_http.h \ tracker/tracker_list.cc \ tracker/tracker_list.h \ tracker/tracker_udp.cc \ tracker/tracker_udp.h \ tracker/tracker_worker.cc \ tracker/tracker_worker.h \ \ utils/diffie_hellman.cc \ utils/diffie_hellman.h \ utils/functional.h \ utils/instrumentation.cc \ utils/instrumentation.h \ utils/partial_queue.h \ utils/rc4.h \ utils/sha1.h \ utils/signal_interrupt.cc \ utils/signal_interrupt.h \ utils/thread_internal.h \ utils/queue_buckets.h AM_CPPFLAGS = -I$(srcdir) -I$(top_srcdir) EXTRA_DIST= \ net/udns/dnsget.c \ net/udns/ex-rdns.c \ net/udns/getopt.c \ net/udns/inet_XtoX.c \ net/udns/rblcheck.c \ net/udns/udns.h \ net/udns/udns_XtoX.c \ net/udns/udns_bl.c \ net/udns/udns_codes.c \ net/udns/udns_dn.c \ net/udns/udns_dntosp.c \ net/udns/udns_init.c \ net/udns/udns_jran.c \ net/udns/udns_misc.c \ net/udns/udns_parse.c \ net/udns/udns_resolver.c \ net/udns/udns_rr_a.c \ net/udns/udns_rr_mx.c \ net/udns/udns_rr_naptr.c \ net/udns/udns_rr_ptr.c \ net/udns/udns_rr_srv.c \ net/udns/udns_rr_txt.c libtorrent-0.16.11/src/torrent/0000755000000000000000000000000015175073434012050 5libtorrent-0.16.11/src/torrent/Makefile.am0000644000000000000000000001275415175073411014030 noinst_LTLIBRARIES = libtorrent_torrent.la libtorrent_torrent_la_SOURCES = \ data/block.cc \ data/block.h \ data/block_failed.h \ data/block_list.cc \ data/block_list.h \ data/block_transfer.h \ data/chunk_utils.cc \ data/chunk_utils.h \ data/download_data.cc \ data/download_data.h \ data/file.cc \ data/file.h \ data/file_list.cc \ data/file_list.h \ data/file_list_iterator.cc \ data/file_list_iterator.h \ data/file_manager.cc \ data/file_manager.h \ data/file_utils.cc \ data/file_utils.h \ data/piece.h \ data/transfer_list.cc \ data/transfer_list.h \ \ download/choke_group.cc \ download/choke_group.h \ download/choke_queue.cc \ download/choke_queue.h \ download/download_manager.cc \ download/download_manager.h \ download/group_entry.h \ download/resource_manager.cc \ download/resource_manager.h \ \ net/address_info.cc \ net/address_info.h \ net/connection_state.h \ net/fd.cc \ net/fd.h \ net/http_get.cc \ net/http_get.h \ net/http_stack.cc \ net/http_stack.h \ net/network_config.cc \ net/network_config.h \ net/poll.h \ net/poll_epoll.cc \ net/poll_kqueue.cc \ net/resolver.cc \ net/resolver.h \ net/socket_address.cc \ net/socket_address.h \ net/socket_address_key.cc \ net/socket_address_key.h \ net/types.h \ \ peer/choke_status.h \ peer/client_info.cc \ peer/client_info.h \ peer/client_list.cc \ peer/client_list.h \ peer/connection_list.cc \ peer/connection_list.h \ peer/peer.cc \ peer/peer.h \ peer/peer_info.cc \ peer/peer_info.h \ peer/peer_list.cc \ peer/peer_list.h \ \ runtime/network_manager.cc \ runtime/network_manager.h \ runtime/socket_manager.cc \ runtime/socket_manager.h \ \ system/thread.cc \ system/thread.h \ \ tracker/dht_controller.cc \ tracker/dht_controller.h \ tracker/manager.cc \ tracker/manager.h \ tracker/tracker.cc \ tracker/tracker.h \ tracker/tracker_state.h \ tracker/wrappers.cc \ tracker/wrappers.h \ \ utils/chrono.h \ utils/directory_events.cc \ utils/directory_events.h \ utils/extents.h \ utils/file_stat.h \ utils/log.cc \ utils/log.h \ utils/log_buffer.cc \ utils/log_buffer.h \ utils/option_strings.cc \ utils/option_strings.h \ utils/random.cc \ utils/random.h \ utils/ranges.h \ utils/resume.cc \ utils/resume.h \ utils/scheduler.cc \ utils/scheduler.h \ utils/signal_bitfield.cc \ utils/signal_bitfield.h \ utils/string_manip.cc \ utils/string_manip.h \ utils/unordered_vector.h \ utils/uri_parser.cc \ utils/uri_parser.h \ \ bitfield.cc \ bitfield.h \ chunk_manager.cc \ chunk_manager.h \ common.h \ connection_manager.cc \ connection_manager.h \ download.cc \ download.h \ download_info.h \ error.cc \ error.h \ event.cc \ event.h \ exceptions.cc \ exceptions.h \ hash_string.h \ object.cc \ object.h \ object_raw_bencode.h \ object_static_map.cc \ object_static_map.h \ object_stream.cc \ object_stream.h \ path.cc \ path.h \ rate.cc \ rate.h \ throttle.cc \ throttle.h \ torrent.cc \ torrent.h AM_CPPFLAGS = -I$(srcdir) -I$(srcdir)/.. -I$(top_srcdir) libtorrent_torrent_data_includedir = $(includedir)/torrent/data libtorrent_torrent_data_include_HEADERS = \ data/block.h \ data/block_list.h \ data/block_transfer.h \ data/chunk_utils.h \ data/download_data.h \ data/file.h \ data/file_list.h \ data/file_list_iterator.h \ data/file_manager.h \ data/file_utils.h \ data/piece.h \ data/transfer_list.h libtorrent_torrent_download_includedir = $(includedir)/torrent/download libtorrent_torrent_download_include_HEADERS = \ download/choke_group.h \ download/choke_queue.h \ download/download_manager.h \ download/group_entry.h \ download/resource_manager.h libtorrent_torrent_net_includedir = $(includedir)/torrent/net libtorrent_torrent_net_include_HEADERS = \ net/address_info.h \ net/connection_state.h \ net/fd.h \ net/http_get.h \ net/http_stack.h \ net/network_config.h \ net/poll.h \ net/resolver.h \ net/socket_address.h \ net/socket_address_key.h \ net/types.h libtorrent_torrent_peer_includedir = $(includedir)/torrent/peer libtorrent_torrent_peer_include_HEADERS = \ peer/choke_status.h \ peer/client_info.h \ peer/client_list.h \ peer/connection_list.h \ peer/peer.h \ peer/peer_info.h \ peer/peer_list.h libtorrent_torrent_runtime_includedir = $(includedir)/torrent/runtime libtorrent_torrent_runtime_include_HEADERS = \ runtime/network_manager.h \ runtime/socket_manager.h libtorrent_torrent_system_includedir = $(includedir)/torrent/system libtorrent_torrent_system_include_HEADERS = \ system/thread.h libtorrent_torrent_tracker_includedir = $(includedir)/torrent/tracker libtorrent_torrent_tracker_include_HEADERS = \ tracker/dht_controller.h \ tracker/manager.h \ tracker/tracker.h \ tracker/tracker_state.h \ tracker/wrappers.h libtorrent_torrent_utils_includedir = $(includedir)/torrent/utils libtorrent_torrent_utils_include_HEADERS = \ utils/chrono.h \ utils/directory_events.h \ utils/extents.h \ utils/file_stat.h \ utils/log.h \ utils/log_buffer.h \ utils/option_strings.h \ utils/random.h \ utils/ranges.h \ utils/resume.h \ utils/scheduler.h \ utils/signal_bitfield.h \ utils/string_manip.h \ utils/unordered_vector.h \ utils/uri_parser.h libtorrent_torrent_includedir = $(includedir)/torrent libtorrent_torrent_include_HEADERS = \ bitfield.h \ chunk_manager.h \ common.h \ connection_manager.h \ download.h \ download_info.h \ error.h \ exceptions.h \ event.h \ hash_string.h \ object.h \ object_raw_bencode.h \ object_static_map.h \ object_stream.h \ path.h \ rate.h \ throttle.h \ torrent.h libtorrent-0.16.11/src/torrent/torrent.cc0000644000000000000000000003030015175073411013763 #include "config.h" #include "torrent/torrent.h" #include #include #include #include "data/file_manager.h" #include "data/hash_queue.h" #include "data/thread_disk.h" #include "download/download_constructor.h" #include "download/download_manager.h" #include "download/download_wrapper.h" #include "manager.h" #include "net/thread_net.h" #include "protocol/handshake_manager.h" #include "protocol/peer_factory.h" #include "thread_main.h" #include "torrent/connection_manager.h" #include "torrent/download/resource_manager.h" #include "torrent/download_info.h" #include "torrent/exceptions.h" #include "torrent/object.h" #include "torrent/object_stream.h" #include "torrent/throttle.h" #include "torrent/peer/connection_list.h" #include "torrent/net/http_stack.h" #include "torrent/net/poll.h" #include "torrent/runtime/network_manager.h" #include "tracker/thread_tracker.h" #include "utils/instrumentation.h" namespace torrent { namespace { uint32_t calculate_max_open_files(uint32_t open_max) { if (open_max >= 16384) return 512; else if (open_max >= 8096) return 256; else if (open_max >= 1024) return 128; else if (open_max >= 512) return 64; else if (open_max >= 128) return 16; else // Assumes we don't try less than 64. return 4; } uint32_t calculate_max_http_host_connections(uint32_t open_max) { if (open_max >= 16384) return 3; else if (open_max >= 8096) return 2; else // Assumes we don't try less than 64. return 1; } uint32_t calculate_max_http_total_connections(uint32_t open_max) { if (open_max >= 16384) return 128; else if (open_max >= 8096) return 64; else if (open_max >= 1024) return 32; else if (open_max >= 512) return 16; else if (open_max >= 128) return 8; else // Assumes we don't try less than 64. return 4; } uint32_t calculate_reserved(uint32_t open_max) { if (open_max >= 16384) return 512; else if (open_max >= 8096) return 256; else if (open_max >= 1024) return 128; else if (open_max >= 512) return 64; else if (open_max >= 128) return 32; else // Assumes we don't try less than 64. return 16; } std::string generate_random(size_t length) { std::random_device rd; std::mt19937 mt(rd()); using bytes_randomizer = std::independent_bits_engine; bytes_randomizer bytes(mt); std::string s; s.reserve(length); std::generate_n(std::back_inserter(s), length, std::ref(bytes)); return s; } } namespace system { // TODO: Move. const char* errno_enum(int status) { // The Open Group Base Specifications Issue 6 switch (status) { case 0: return "0"; case E2BIG: return "E2BIG"; case EACCES: return "EACCES"; case EADDRINUSE: return "EADDRINUSE"; case EADDRNOTAVAIL: return "EADDRNOTAVAIL"; case EAFNOSUPPORT: return "EAFNOSUPPORT"; case EAGAIN: return "EAGAIN"; case EALREADY: return "EALREADY"; case EBADF: return "EBADF"; case EBADMSG: return "EBADMSG"; case EBUSY: return "EBUSY"; case ECANCELED: return "ECANCELED"; case ECHILD: return "ECHILD"; case ECONNABORTED: return "ECONNABORTED"; case ECONNREFUSED: return "ECONNREFUSED"; case ECONNRESET: return "ECONNRESET"; case EDEADLK: return "EDEADLK"; case EDESTADDRREQ: return "EDESTADDRREQ"; case EDOM: return "EDOM"; case EDQUOT: return "EDQUOT"; case EEXIST: return "EEXIST"; case EFAULT: return "EFAULT"; case EFBIG: return "EFBIG"; case EHOSTUNREACH: return "EHOSTUNREACH"; case EIDRM: return "EIDRM"; case EILSEQ: return "EILSEQ"; case EINPROGRESS: return "EINPROGRESS"; case EINTR: return "EINTR"; case EINVAL: return "EINVAL"; case EIO: return "EIO"; case EISCONN: return "EISCONN"; case EISDIR: return "EISDIR"; case ELOOP: return "ELOOP"; case EMFILE: return "EMFILE"; case EMLINK: return "EMLINK"; case EMSGSIZE: return "EMSGSIZE"; #if defined(EMULTIHOP) case EMULTIHOP: return "EMULTIHOP"; #endif case ENAMETOOLONG: return "ENAMETOOLONG"; case ENETDOWN: return "ENETDOWN"; case ENETRESET: return "ENETRESET"; case ENETUNREACH: return "ENETUNREACH"; case ENFILE: return "ENFILE"; case ENOBUFS: return "ENOBUFS"; case ENODATA: return "ENODATA"; case ENODEV: return "ENODEV"; case ENOENT: return "ENOENT"; case ENOEXEC: return "ENOEXEC"; case ENOLCK: return "ENOLCK"; case ENOLINK: return "ENOLINK"; case ENOMEM: return "ENOMEM"; case ENOMSG: return "ENOMSG"; case ENOPROTOOPT: return "ENOPROTOOPT"; case ENOSPC: return "ENOSPC"; case ENOSR: return "ENOSR"; case ENOSTR: return "ENOSTR"; case ENOSYS: return "ENOSYS"; case ENOTCONN: return "ENOTCONN"; case ENOTDIR: return "ENOTDIR"; case ENOTEMPTY: return "ENOTEMPTY"; case ENOTSOCK: return "ENOTSOCK"; case ENOTTY: return "ENOTTY"; case ENXIO: return "ENXIO"; case EOPNOTSUPP: return "EOPNOTSUPP"; case EOVERFLOW: return "EOVERFLOW"; case EPERM: return "EPERM"; case EPIPE: return "EPIPE"; case EPROTO: return "EPROTO"; case EPROTONOSUPPORT: return "EPROTONOSUPPORT"; case EPROTOTYPE: return "EPROTOTYPE"; case ERANGE: return "ERANGE"; case EROFS: return "EROFS"; case ESPIPE: return "ESPIPE"; case ESRCH: return "ESRCH"; case ESTALE: return "ESTALE"; case ETIME: return "ETIME"; case ETIMEDOUT: return "ETIMEDOUT"; case ETXTBSY: return "ETXTBSY"; case EXDEV: return "EXDEV"; default: // Handle potentially duplicate error numbers here. switch (status) { case ENOTSUP: return "ENOTSUP"; case EWOULDBLOCK: return "EWOULDBLOCK"; default: static thread_local char buffer[16]; std::snprintf(buffer, sizeof(buffer), "E%d", status); return buffer; }; }; } std::string errno_enum_str(int status) { return errno_enum(status); } } // namespace torrent::system void initialize_main_thread() { ThreadMain::create_thread(); ThreadMain::thread_main()->init_thread(); } void initialize() { if (manager != nullptr) throw internal_error("torrent::initialize(...) called but the library has already been initialized"); instrumentation_initialize(); curl_global_init(CURL_GLOBAL_ALL); manager = new Manager; ThreadDisk::create_thread(); ThreadNet::create_thread(); ThreadTracker::create_thread(ThreadMain::thread_main()); auto max_open = this_thread::poll()->open_max(); auto max_files = calculate_max_open_files(max_open); auto max_http_connections = calculate_max_http_total_connections(max_open); auto reserved = calculate_reserved(max_open); manager->connection_manager()->set_max_size(max_open - max_files - max_http_connections - reserved); manager->file_manager()->set_max_open_files(max_files); net_thread::http_stack()->set_max_host_connections(calculate_max_http_host_connections(max_open)); net_thread::http_stack()->set_max_total_connections(max_http_connections); thread_disk()->init_thread(); net_thread::thread()->init_thread(); thread_tracker()->init_thread(); thread_disk()->start_thread(); net_thread::thread()->start_thread(); thread_tracker()->start_thread(); } // Clean up and close stuff. Stopping all torrents and waiting for // them to finish is not required, but recommended. void cleanup() { if (manager == nullptr) throw internal_error("torrent::cleanup() called but the library is not initialized."); // Might need to wait for the threads to finish? runtime::network_manager()->cleanup(); thread_tracker()->stop_thread_wait(); thread_disk()->stop_thread_wait(); net_thread::thread()->stop_thread_wait(); ThreadTracker::destroy_thread(); ThreadDisk::destroy_thread(); ThreadNet::destroy_thread(); delete manager; manager = NULL; curl_global_cleanup(); } bool is_initialized() { return manager != NULL; } bool is_inactive() { return manager == nullptr || std::all_of(manager->download_manager()->begin(), manager->download_manager()->end(), std::mem_fn(&DownloadWrapper::is_stopped)); } void set_main_thread_slots(std::function do_work) { ThreadMain::thread_main()->slot_do_work() = std::move(do_work); } ChunkManager* chunk_manager() { return manager->chunk_manager(); } ClientList* client_list() { return manager->client_list(); } ConnectionManager* connection_manager() { return manager->connection_manager(); } FileManager* file_manager() { return manager->file_manager(); } ResourceManager* resource_manager() { return manager->resource_manager(); } uint32_t total_handshakes() { return manager->handshake_manager()->size(); } Throttle* down_throttle_global() { return manager->download_throttle(); } Throttle* up_throttle_global() { return manager->upload_throttle(); } const Rate* down_rate() { return manager->download_throttle()->rate(); } const Rate* up_rate() { return manager->upload_throttle()->rate(); } const char* version() { return VERSION; } EncodingList* encoding_list() { return manager->encoding_list(); } Download download_add(Object* object, uint32_t tracker_key) { auto download = std::make_unique(); DownloadConstructor ctor; ctor.set_download(download.get()); ctor.set_encoding_list(manager->encoding_list()); ctor.initialize(*object); std::string infoHash; if (download->info()->is_meta_download()) infoHash = object->get_key("info").get_key("pieces").as_string(); else infoHash = object_sha1(&object->get_key("info")); if (manager->download_manager()->find(infoHash) != manager->download_manager()->end()) throw input_error("Info hash already used by another torrent."); if (!download->info()->is_meta_download()) { char buffer[1024]; uint64_t metadata_size = 0; object_write_bencode_c(&object_write_to_size, &metadata_size, object_buffer_t(buffer, buffer + sizeof(buffer)), &object->get_key("info")); download->main()->set_metadata_size(metadata_size); } std::string local_id = PEER_NAME + generate_random(20 - std::string(PEER_NAME).size()); download->set_hash_queue(ThreadMain::thread_main()->hash_queue()); download->initialize(infoHash, local_id, tracker_key); // Add trackers, etc, after setting the info hash so that log // entries look sane. ctor.parse_tracker(*object); // Default PeerConnection factory functions. download->main()->connection_list()->slot_new_connection(&createPeerConnectionDefault); // Consider move as much as possible into this function // call. Anything that won't cause possible torrent creation errors // go in there. manager->initialize_download(download.get()); download->set_bencode(object); return Download(download.release()); } void download_remove(Download d) { manager->cleanup_download(d.ptr()); } // Add all downloads to dlist. Make sure it's cleared. void download_list(DList& dlist) { dlist.insert(dlist.end(), manager->download_manager()->begin(), manager->download_manager()->end()); } // Make sure you check that it's valid. Download download_find(const std::string& infohash) { return *manager->download_manager()->find(infohash); } uint32_t download_priority(Download d) { auto itr = manager->resource_manager()->find(d.ptr()->main()); if (itr == manager->resource_manager()->end()) throw internal_error("torrent::download_priority(...) could not find the download in the resource manager."); return itr->priority(); } // TODO: Remove this. void download_set_priority(Download d, uint32_t pri) { auto itr = manager->resource_manager()->find(d.ptr()->main()); if (itr == manager->resource_manager()->end()) throw internal_error("torrent::download_set_priority(...) could not find the download in the resource manager."); if (pri > 1024) throw internal_error("torrent::download_set_priority(...) received an invalid priority."); ResourceManager::set_priority(itr, pri); } } // namespace torrent libtorrent-0.16.11/src/torrent/exceptions.h0000644000000000000000000000752515175073411014326 // Note that some of the exception classes below are strictly speaking // _NOT DOING THE RIGHT THING_. One is really not supposed to use any // calls to malloc/new in an exception's ctor. // // Will be fixed next API update. #ifndef LIBTORRENT_EXCEPTIONS_H #define LIBTORRENT_EXCEPTIONS_H #include #include #include namespace torrent { // All exceptions inherit from std::exception to make catching // everything libtorrent related at the root easier. class LIBTORRENT_EXPORT base_error : public std::exception { }; // The library or application did some borking it shouldn't have, bug // tracking time! class LIBTORRENT_EXPORT internal_error : public base_error { public: internal_error(const char* msg) { initialize(msg); } internal_error(const char* msg, const std::string& context); internal_error(const char* msg, const HashString& hash); internal_error(const std::string& msg) { initialize(msg); } const char* what() const noexcept override; const std::string& backtrace() const noexcept { return m_backtrace; } void push_front(const std::string& msg) { m_msg = msg + m_msg; } private: // Use this function for breaking on throws. void initialize(const std::string& msg); std::string m_msg; std::string m_backtrace; }; // For some reason we couldn't talk with a protocol/tracker, migth be a // library bug, connection problem or bad input. class LIBTORRENT_EXPORT network_error : public base_error { }; class LIBTORRENT_EXPORT communication_error : public network_error { public: communication_error(const char* msg) { initialize(msg); } communication_error(const std::string& msg) { initialize(msg); } const char* what() const noexcept override; private: // Use this function for breaking on throws. void initialize(const std::string& msg); std::string m_msg; }; class LIBTORRENT_EXPORT connection_error : public network_error { public: connection_error(int err) : m_errno(err) {} const char* what() const noexcept override; int get_errno() const { return m_errno; } private: int m_errno; }; class LIBTORRENT_EXPORT address_info_error : public network_error { public: address_info_error(int err) : m_errno(err) {} const char* what() const noexcept override; int get_errno() const { return m_errno; } private: int m_errno; }; class LIBTORRENT_EXPORT close_connection : public network_error { }; class LIBTORRENT_EXPORT blocked_connection : public network_error { }; // Stuff like bad torrent file, disk space and permissions. class LIBTORRENT_EXPORT local_error : public base_error { }; class LIBTORRENT_EXPORT storage_error : public local_error { public: storage_error(const char* msg) { initialize(msg); } storage_error(const std::string& msg) { initialize(msg); } const char* what() const noexcept override; private: // Use this function for breaking on throws. void initialize(const std::string& msg); std::string m_msg; }; class LIBTORRENT_EXPORT resource_error : public local_error { public: resource_error(const char* msg) { initialize(msg); } resource_error(const std::string& msg) { initialize(msg); } const char* what() const noexcept override; private: // Use this function for breaking on throws. void initialize(const std::string& msg); std::string m_msg; }; class LIBTORRENT_EXPORT input_error : public local_error { public: input_error(const char* msg) { initialize(msg); } input_error(const std::string& msg) { initialize(msg); } const char* what() const noexcept override; private: // Use this function for breaking on throws. void initialize(const std::string& msg); std::string m_msg; }; class LIBTORRENT_EXPORT bencode_error : public input_error { public: using input_error::input_error; }; class LIBTORRENT_EXPORT shutdown_exception : public base_error { }; } // namespace torrent #endif libtorrent-0.16.11/src/torrent/exceptions.cc0000644000000000000000000000445715175073411014465 #include "config.h" #include "torrent/exceptions.h" #include #include #include #include "torrent/hash_string.h" #include "torrent/utils/string_manip.h" #ifdef HAVE_BACKTRACE #include #endif namespace torrent { // Use actual functions, instead of inlined, for the ctor of // exceptions. This allows us to create breakpoints at throws. This is // limited to rarely thrown exceptions. void communication_error::initialize(const std::string& msg) { m_msg = msg; } void storage_error::initialize(const std::string& msg) { m_msg = msg; } void resource_error::initialize(const std::string& msg) { m_msg = msg; } void input_error::initialize(const std::string& msg) { m_msg = msg; } internal_error::internal_error(const char* msg, const std::string& context) { initialize(std::string(msg) + " [" + context + "]"); } internal_error::internal_error(const char* msg, const HashString& hash) { initialize(std::string(msg) + " [#" + utils::transform_to_hex_str(hash) + "]"); } const char* internal_error::what() const noexcept { return m_msg.c_str(); } const char* input_error::what() const noexcept { return m_msg.c_str(); } const char* resource_error::what() const noexcept { return m_msg.c_str(); } const char* storage_error::what() const noexcept { return m_msg.c_str(); } const char* communication_error::what() const noexcept { return m_msg.c_str(); } const char* connection_error::what() const noexcept { return std::strerror(m_errno); } const char* address_info_error::what() const noexcept { return ::gai_strerror(m_errno); } void internal_error::initialize(const std::string& msg) { m_msg = msg; #ifdef HAVE_BACKTRACE void* stack_ptrs[20]; int stack_size = ::backtrace(stack_ptrs, 20); char** stack_symbol_names = ::backtrace_symbols(stack_ptrs, stack_size); if (stack_symbol_names == nullptr) { m_backtrace = "backtrace_symbols failed"; return; } std::stringstream output; for (int i = 0; i < stack_size; ++i) { if (stack_symbol_names[i] != nullptr && stack_symbol_names[i] > (void*)0x1000) output << stack_symbol_names[i] << '\n'; else output << "stack_symbol: nullptr" << '\n'; } m_backtrace = output.str(); ::free(stack_symbol_names); #else m_backtrace = "stack dump not enabled"; #endif } } // namespace torrent libtorrent-0.16.11/src/torrent/error.h0000644000000000000000000000654315175073411013275 // libTorrent - BitTorrent library // Copyright (C) 2005-2011, Jari Sundell // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // In addition, as a special exception, the copyright holders give // permission to link the code of portions of this program with the // OpenSSL library under certain conditions as described in each // individual source file, and distribute linked combinations // including the two. // // You must obey the GNU General Public License in all respects for // all of the code used other than OpenSSL. If you modify file(s) // with this exception, you may extend this exception to your version // of the file(s), but you are not obligated to do so. If you do not // wish to do so, delete this exception statement from your version. // If you delete this exception statement from all source files in the // program, then also delete it here. // // Contact: Jari Sundell // // Skomakerveien 33 // 3185 Skoppum, NORWAY #ifndef LIBTORRENT_TORRENT_ERROR_H #define LIBTORRENT_TORRENT_ERROR_H #include namespace torrent { const int e_none = 0; // Handshake errors passed to signal handler const int e_handshake_not_bittorrent = 1; const int e_handshake_not_accepting_connections = 2; const int e_handshake_duplicate = 3; const int e_handshake_unknown_download = 4; const int e_handshake_inactive_download = 5; const int e_handshake_unwanted_connection = 6; const int e_handshake_is_self = 7; const int e_handshake_invalid_value = 8; const int e_handshake_unencrypted_rejected = 9; const int e_handshake_invalid_encryption = 10; const int e_handshake_encryption_sync_failed = 11; const int e_handshake_network_unreachable = 13; const int e_handshake_network_timeout = 14; const int e_handshake_invalid_order = 15; const int e_handshake_toomanyfailed = 16; const int e_handshake_no_peer_info = 17; const int e_handshake_network_socket_error = 18; const int e_handshake_network_read_error = 19; const int e_handshake_network_write_error = 20; // const int e_handshake_incoming = 13; // const int e_handshake_outgoing = 14; // const int e_handshake_outgoing_encrypted = 15; // const int e_handshake_outgoing_proxy = 16; // const int e_handshake_success = 17; // const int e_handshake_retry_plaintext = 18; // const int e_handshake_retry_encrypted = 19; const int e_last = 20; const char* strerror(int err) LIBTORRENT_EXPORT; } // namespace torrent #endif libtorrent-0.16.11/src/torrent/net/0000755000000000000000000000000015175073434012636 5libtorrent-0.16.11/src/torrent/net/address_info.cc0000644000000000000000000000200015175073411015510 #include "config.h" #include "address_info.h" namespace torrent { int ai_get_addrinfo(const char* nodename, const char* servname, const addrinfo* hints, ai_unique_ptr& res) { addrinfo* ai; int err = ::getaddrinfo(nodename, servname, hints, &ai); if (err != 0) return err; res.reset(ai); return 0; } sa_unique_ptr ai_get_first_sa(const char* nodename, const char* servname, const addrinfo* hints) { ai_unique_ptr aip; if (ai_get_addrinfo(nodename, servname, hints, aip) != 0) return nullptr; return sa_copy(aip->ai_addr); } int ai_each_inet_inet6_first(const char* nodename, const ai_sockaddr_func& lambda) { int err; ai_unique_ptr ai; // TODO: Change to a single call using hints with both inet/inet6. if ((err = ai_get_addrinfo(nodename, NULL, ai_make_hint(0, PF_INET, SOCK_STREAM).get(), ai)) != 0 && (err = ai_get_addrinfo(nodename, NULL, ai_make_hint(0, PF_INET6, SOCK_STREAM).get(), ai)) != 0) return err; lambda(ai->ai_addr); return 0; } } // namespace torrent libtorrent-0.16.11/src/torrent/net/fd.cc0000644000000000000000000003321415175073411013454 #include "config.h" #include "fd.h" #include #include #include #include #include "torrent/exceptions.h" #include "torrent/net/socket_address.h" #include "torrent/utils/log.h" #define LT_LOG(log_fmt, ...) \ lt_log_print(LOG_CONNECTION_FD, "fd: " log_fmt, __VA_ARGS__); #define LT_LOG_FLAG(log_fmt) \ lt_log_print(LOG_CONNECTION_FD, "fd: " log_fmt " : flags:0x%x", flags); #define LT_LOG_FLAG_ERROR(log_fmt) \ lt_log_print(LOG_CONNECTION_FD, "fd: " log_fmt " : flags:0x%x errno:%i message:'%s'", \ flags, errno, std::strerror(errno)); #define LT_LOG_FD(log_fmt) \ lt_log_print(LOG_CONNECTION_FD, "fd->%i: " log_fmt, fd); #define LT_LOG_FD_ERROR(log_fmt) \ lt_log_print(LOG_CONNECTION_FD, "fd->%i: " log_fmt " : errno:%i message:'%s'", \ fd, errno, std::strerror(errno)); #define LT_LOG_FD_SOCKADDR(log_fmt) \ lt_log_print(LOG_CONNECTION_FD, "fd->%i: " log_fmt " : address:%s", \ fd, sa_pretty_str(sa).c_str()); #define LT_LOG_FD_SOCKADDR_ERROR(log_fmt) \ lt_log_print(LOG_CONNECTION_FD, "fd->%i: " log_fmt " : address:%s errno:%i message:'%s'", \ fd, sa_pretty_str(sa).c_str(), errno, std::strerror(errno)); #define LT_LOG_FD_SAP(log_fmt) \ lt_log_print(LOG_CONNECTION_FD, "fd->%i: " log_fmt " : address:%s", \ fd, sap_pretty_str(sap).c_str()); #define LT_LOG_FD_FLAG(log_fmt) \ lt_log_print(LOG_CONNECTION_FD, "fd->%i: " log_fmt " : flags:0x%x", fd, flags); #define LT_LOG_FD_FLAG_ERROR(log_fmt) \ lt_log_print(LOG_CONNECTION_FD, "fd->%i: " log_fmt " : flags:0x%x errno:%i message:'%s'", \ fd, flags, errno, std::strerror(errno)); #define LT_LOG_FD_VALUE(log_fmt, value) \ lt_log_print(LOG_CONNECTION_FD, "fd->%i: " log_fmt " : value:%i", fd, (int)value); #define LT_LOG_FD_VALUE_ERROR(log_fmt, value) \ lt_log_print(LOG_CONNECTION_FD, "fd->%i: " log_fmt " : value:%i errno:%i message:'%s'", \ fd, (int)value, errno, std::strerror(errno)); namespace torrent { int fd__accept(int socket, sockaddr *address, socklen_t *address_len) { return ::accept(socket, address, address_len); } int fd__bind(int socket, const sockaddr *address, socklen_t address_len) { return ::bind(socket, address, address_len); } int fd__close(int fildes) { return ::close(fildes); } int fd__connect(int socket, const sockaddr *address, socklen_t address_len) { return ::connect(socket, address, address_len); } int fd__fcntl_int(int fildes, int cmd, int arg) { return ::fcntl(fildes, cmd, arg); } int fd__listen(int socket, int backlog) { return ::listen(socket, backlog); } int fd__setsockopt_int(int socket, int level, int option_name, int option_value) { return ::setsockopt(socket, level, option_name, &option_value, sizeof(int)); } int fd__socket(int domain, int type, int protocol) { return ::socket(domain, type, protocol); } int fd_open(fd_flags flags) { int domain; int protocol; if (!fd_valid_flags(flags)) throw internal_error("torrent::fd_open failed: invalid fd_flags"); if ((flags & fd_flag_stream)) { domain = SOCK_STREAM; protocol = IPPROTO_TCP; } else if ((flags & fd_flag_datagram)) { domain = SOCK_DGRAM; protocol = IPPROTO_UDP; } else { LT_LOG_FLAG("fd_open missing socket type"); errno = EINVAL; return -1; } int fd = -1; if (fd == -1 && !(flags & fd_flag_v4only)) { LT_LOG_FLAG("fd_open opening ipv6 socket"); fd = fd__socket(PF_INET6, domain, protocol); } if (fd == -1 && !(flags & fd_flag_v6only)) { LT_LOG_FLAG("fd_open opening ipv4 socket"); fd = fd__socket(PF_INET, domain, protocol); } if (fd == -1) { LT_LOG_FLAG_ERROR("fd_open failed to open socket"); return -1; } if ((flags & fd_flag_v6only) && !fd_set_v6only(fd, true)) { LT_LOG_FD_FLAG_ERROR("fd_open failed to set v6only"); fd__close(fd); return -1; } if ((flags & fd_flag_nonblock) && !fd_set_nonblock(fd)) { LT_LOG_FD_FLAG_ERROR("fd_open failed to set nonblock"); fd__close(fd); return -1; } if ((flags & fd_flag_reuse_address) && !fd_set_reuse_address(fd, true)) { LT_LOG_FD_FLAG_ERROR("fd_open failed to set reuse_address"); fd__close(fd); return -1; } LT_LOG_FD_FLAG("fd_open succeeded"); return fd; } int fd_open_family(fd_flags flags, int family) { if (family != AF_INET && family != AF_INET6) { LT_LOG_FLAG("fd_open_family invalid family"); errno = EINVAL; return -1; } if (family == AF_INET) flags |= fd_flag_v4; return fd_open(flags); } int fd_open_local(fd_flags flags) { if ((flags & ~(fd_flag_stream | fd_flag_nonblock | fd_flag_reuse_address))) throw internal_error("torrent::fd_open_local() invalid fd_flags"); if (!(flags & fd_flag_stream)) throw internal_error("torrent::fd_open_local() only stream sockets supported"); int fd = fd__socket(AF_LOCAL, SOCK_STREAM, 0); if (fd == -1) { LT_LOG_FLAG_ERROR("fd_open_local() failed to open socket"); return -1; } if ((flags & fd_flag_nonblock) && !fd_set_nonblock(fd)) { LT_LOG_FD_FLAG_ERROR("fd_open_local() failed to set nonblock"); fd__close(fd); return -1; } if ((flags & fd_flag_reuse_address) && !fd_set_reuse_address(fd, true)) { LT_LOG_FD_FLAG_ERROR("fd_open_local() failed to set reuse_address"); fd__close(fd); return -1; } LT_LOG_FD_FLAG("fd_open_local() succeeded"); return fd; } void fd_open_pipe(int& fd1, int& fd2) { int result[2]; if (pipe(result) == -1) throw internal_error("torrent::fd_open_pipe failed: " + std::string(strerror(errno))); fd1 = result[0]; fd2 = result[1]; LT_LOG("fd_open_pipe succeeded : fd1:%i fd2:%i", fd1, fd2); } void fd_open_socket_pair(int& fd1, int& fd2) { int result[2]; if (socketpair(AF_LOCAL, SOCK_STREAM, 0, result) == -1) throw internal_error("torrent::fd_open_socket_pair failed: " + std::string(strerror(errno))); fd1 = result[0]; fd2 = result[1]; LT_LOG("fd_open_socket_pair succeeded : fd1:%i fd2:%i", fd1, fd2); } void fd_close(int fd) { if (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO) throw internal_error("torrent::fd_close: tried to close stdin/out/err"); if (fd__close(fd) == -1) throw internal_error("torrent::fd_close: " + std::string(strerror(errno))); LT_LOG_FD("fd_close succeeded"); } int fd_accept(int fd) { int connection_fd = fd__accept(fd, nullptr, nullptr); if (connection_fd == -1) { LT_LOG_FD_ERROR("fd_accept() failed"); return -1; } LT_LOG_FD("fd_accept() succeeded"); return connection_fd; } fd_sap_tuple fd_sap_accept(int fd) { sa_inet_union sau{}; socklen_t sau_length = sizeof(sockaddr_in6); int connection_fd = fd__accept(fd, &sau.sa, &sau_length); if (connection_fd == -1) { LT_LOG_FD_ERROR("fd_sap_accept() failed"); return fd_sap_tuple{-1, nullptr}; } auto sap = sa_copy(&sau.sa); LT_LOG_FD_SAP("fd_sap_accept() succeeded"); return fd_sap_tuple{connection_fd, std::move(sap)}; } bool fd_bind(int fd, const sockaddr* sa) { if (fd__bind(fd, sa, sa_length(sa)) == -1) { LT_LOG_FD_SOCKADDR_ERROR("fd_bind() failed"); return false; } LT_LOG_FD_SOCKADDR("fd_bind() succeeded"); return true; } bool fd_bind_with_length(int fd, const sockaddr* sa, socklen_t length) { if (fd__bind(fd, sa, length) == -1) { LT_LOG_FD_SOCKADDR_ERROR("fd_bind() failed"); return false; } LT_LOG_FD_SOCKADDR("fd_bind() succeeded"); return true; } bool fd_connect(int fd, const sockaddr* sa) { if (fd__connect(fd, sa, sa_length(sa)) == 0) { LT_LOG_FD_SOCKADDR("fd_connect() succeeded"); return true; } if (errno == EINPROGRESS) { LT_LOG_FD_SOCKADDR("fd_connect() succeeded and in progress"); return true; } LT_LOG_FD_SOCKADDR_ERROR("fd_connect() failed"); return false; } bool fd_connect_with_family(int fd, const sockaddr* sa, int family) { switch (sa->sa_family) { case AF_UNSPEC: errno = EINVAL; LT_LOG_FD("fd_connect_with_family() cannot connect unspecified address"); return false; case AF_INET: if (family == AF_INET6) { LT_LOG_FD_SOCKADDR("fd_connect_with_family() connecting ipv4 using ipv6"); return fd_connect(fd, sa_to_v4mapped(sa).get()); } LT_LOG_FD_SOCKADDR("fd_connect_with_family() connecting ipv4"); return fd_connect(fd, sa); case AF_INET6: if (family == AF_INET) { if (sa_is_v4mapped(sa)) { LT_LOG_FD_SOCKADDR("fd_connect_with_family() connecting ipv4in6 as ipv4"); return fd_connect(fd, sa_from_v4mapped(sa).get()); } errno = EINVAL; LT_LOG_FD("fd_connect_with_family() cannot connect ipv6 address with ipv4 bind"); return false; } LT_LOG_FD_SOCKADDR("fd_connect_with_family() connecting ipv6"); return fd_connect(fd, sa); default: errno = EINVAL; LT_LOG_FD_VALUE("fd_connect_with_family() invalid sa_family", sa->sa_family); return false; } } bool fd_listen(int fd, int backlog) { if (fd__listen(fd, backlog) == -1) { LT_LOG_FD_VALUE_ERROR("fd_listen() failed", backlog); return false; } LT_LOG_FD_VALUE("fd_listen() succeeded", backlog); return true; } c_sa_unique_ptr fd_get_peer_name(int fd) { sa_inet_union sau{}; sockaddr* sa = &sau.sa; socklen_t sau_length = sizeof(sockaddr_in6); if (getpeername(fd, sa, &sau_length) == -1) { LT_LOG_FD_ERROR("fd_get_peer_name() failed"); return nullptr; } if (sau_length < sa_length(sa)) { LT_LOG_FD_ERROR("fd_get_peer_name() returned invalid length"); return nullptr; } LT_LOG_FD_SOCKADDR("fd_get_peer_name() succeeded"); return sa_copy(sa); } bool fd_get_socket_error(int fd, int* value) { socklen_t length = sizeof(int); if (getsockopt(fd, SOL_SOCKET, SO_ERROR, value, &length) == -1) { LT_LOG_FD_ERROR("fd_get_socket_error() failed"); return false; } LT_LOG_FD_VALUE("fd_get_socket_error() succeeded", *value); return true; } c_sa_unique_ptr fd_get_socket_name(int fd) { sa_inet_union sau{}; sockaddr* sa = &sau.sa; socklen_t sau_length = sizeof(sockaddr_in6); if (getsockname(fd, sa, &sau_length) == -1) { LT_LOG_FD_ERROR("fd_get_socket_name() failed"); return nullptr; } if (sau_length < sa_length(sa)) { LT_LOG_FD_ERROR("fd_get_socket_name() returned invalid length"); return nullptr; } LT_LOG_FD_SOCKADDR("fd_get_socket_name() succeeded"); return sa_copy(sa); } bool fd_get_type(int fd, int* value) { socklen_t length = sizeof(int); if (getsockopt(fd, SOL_SOCKET, SO_TYPE, value, &length) == -1) { LT_LOG_FD_ERROR("fd_get_type() failed"); return false; } LT_LOG_FD_VALUE("fd_get_type() succeeded", *value); return true; } bool fd_set_dont_route(int fd, bool state) { if (fd__setsockopt_int(fd, SOL_SOCKET, SO_DONTROUTE, state) == -1) { LT_LOG_FD_VALUE_ERROR("fd_set_dont_route() failed", state); return false; } LT_LOG_FD_VALUE("fd_set_dont_route() succeeded", state); return true; } bool fd_set_nonblock(int fd) { int flags = fd__fcntl_int(fd, F_GETFL, 0); if (flags == -1) { LT_LOG_FD_ERROR("fd_set_nonblock() failed reading flags"); return false; } if (fd__fcntl_int(fd, F_SETFL, flags | O_NONBLOCK) == -1) { LT_LOG_FD_ERROR("fd_set_nonblock() failed"); return false; } LT_LOG_FD("fd_set_nonblock() succeeded"); return true; } bool fd_set_reuse_address(int fd, bool state) { if (fd__setsockopt_int(fd, SOL_SOCKET, SO_REUSEADDR, state) == -1) { LT_LOG_FD_VALUE_ERROR("fd_set_reuse_address() failed", state); return false; } LT_LOG_FD_VALUE("fd_set_reuse_address() succeeded", state); return true; } bool fd_set_priority(int fd, int family, int priority) { int level; int opt; switch (family) { case AF_INET: level = IPPROTO_IP; opt = IP_TOS; break; case AF_INET6: level = IPPROTO_IPV6; opt = IPV6_TCLASS; break; default: errno = EINVAL; LT_LOG_FD_VALUE("fd_set_priority invalid family", family); return false; } if (fd__setsockopt_int(fd, level, opt, priority) == -1) { LT_LOG_FD_VALUE_ERROR("fd_set_priority() failed", priority); return false; } LT_LOG_FD_VALUE("fd_set_priority() succeeded", priority); return true; } bool fd_set_tcp_nodelay(int fd) { if (fd__setsockopt_int(fd, IPPROTO_TCP, TCP_NODELAY, true) == -1) { LT_LOG_FD_VALUE_ERROR("fd_set_tcp_nodelay() failed", true); return false; } LT_LOG_FD_VALUE("fd_set_tcp_nodelay() succeeded", true); return true; } bool fd_set_v6only(int fd, bool state) { if (fd__setsockopt_int(fd, IPPROTO_IPV6, IPV6_V6ONLY, state) == -1) { LT_LOG_FD_VALUE_ERROR("fd_set_v6only() failed", state); return false; } LT_LOG_FD_VALUE("fd_set_v6only() succeeded", state); return true; } bool fd_set_send_buffer_size(int fd, uint32_t size) { int opt = size; if (fd__setsockopt_int(fd, SOL_SOCKET, SO_SNDBUF, opt) == -1) { LT_LOG_FD_VALUE_ERROR("fd_set_send_buffer_size() failed", opt); return false; } LT_LOG_FD_VALUE("fd_set_send_buffer_size() succeeded", opt); return true; } bool fd_set_receive_buffer_size(int fd, uint32_t size) { int opt = size; if (fd__setsockopt_int(fd, SOL_SOCKET, SO_RCVBUF, opt) == -1) { LT_LOG_FD_VALUE_ERROR("fd_set_receive_buffer_size() failed", opt); return false; } LT_LOG_FD_VALUE("fd_set_receive_buffer_size() succeeded", opt); return true; } } // namespace torrent libtorrent-0.16.11/src/torrent/net/types.h0000644000000000000000000000477615175073411014104 #ifndef LIBTORRENT_NET_TYPES_H #define LIBTORRENT_NET_TYPES_H #include #include #include #include #include #include struct sockaddr_in; struct sockaddr_in6; struct sockaddr_un; namespace torrent::net { const char* gai_enum_error(int status) LIBTORRENT_EXPORT; void sa_free(const sockaddr* sa) LIBTORRENT_EXPORT; } // namespace torrent::net namespace torrent { struct sockaddr_deleter { constexpr sockaddr_deleter() noexcept = default; void operator()(const sockaddr* sa) const { net::sa_free(sa); } }; using sa_unique_ptr = std::unique_ptr; using sin_unique_ptr = std::unique_ptr; using sin6_unique_ptr = std::unique_ptr; using sun_unique_ptr = std::unique_ptr; using c_sa_unique_ptr = std::unique_ptr; using c_sin_unique_ptr = std::unique_ptr; using c_sin6_unique_ptr = std::unique_ptr; using c_sun_unique_ptr = std::unique_ptr; // Shared pointer objects of sockaddr type must use sa_free as deleter. using sa_shared_ptr = std::shared_ptr; using sin_shared_ptr = std::shared_ptr; using sin6_shared_ptr = std::shared_ptr; using sun_shared_ptr = std::shared_ptr; using c_sa_shared_ptr = std::shared_ptr; using c_sin_shared_ptr = std::shared_ptr; using c_sin6_shared_ptr = std::shared_ptr; using c_sun_shared_ptr = std::shared_ptr; using fd_sap_tuple = std::tuple; using sin46_shared_pair = std::pair; using resolver_callback = std::function; struct listen_result_type { int fd; sa_unique_ptr address; }; union sa_inet_union { // Ensure the largest member is first as it used for default list-initialization. sockaddr_in6 inet6; sockaddr_in inet; sockaddr sa; }; // TODO: Move to a separate header file. c_sa_shared_ptr sa_lookup_address(const std::string& address_str, int family) LIBTORRENT_EXPORT; sin46_shared_pair try_lookup_numeric(const std::string& hostname, int family) LIBTORRENT_EXPORT; const char* family_str(int family) LIBTORRENT_EXPORT; namespace net { std::tuple parse_uri_host_port(const std::string& uri) LIBTORRENT_EXPORT; } // namespace net } // namespace torrent #endif libtorrent-0.16.11/src/torrent/net/http_stack.h0000644000000000000000000000352415175073411015072 #ifndef TORRENT_NET_HTTP_GET_H #define TORRENT_NET_HTTP_GET_H #include #include #include namespace torrent { class ThreadNet; } namespace torrent::net { class CurlStack; class LIBTORRENT_EXPORT HttpStack { public: HttpStack(system::Thread* thread); ~HttpStack(); void shutdown(); void start_get(HttpGet& http_get); unsigned int size() const; unsigned int max_cache_connections() const; unsigned int max_host_connections() const; unsigned int max_total_connections() const; void set_max_cache_connections(unsigned int value); void set_max_host_connections(unsigned int value); void set_max_total_connections(unsigned int value); std::string user_agent() const; std::string http_proxy() const; std::string http_capath() const; std::string http_cacert() const; void set_user_agent(const std::string& s); void set_http_proxy(const std::string& s); void set_http_capath(const std::string& s); void set_http_cacert(const std::string& s); bool ssl_verify_host() const; bool ssl_verify_peer() const; void set_ssl_verify_host(bool s); void set_ssl_verify_peer(bool s); long dns_timeout() const; void set_dns_timeout(long timeout); protected: friend class HttpGet; friend class torrent::ThreadNet; CurlStack* curl_stack() { return m_stack.get(); } private: HttpStack() = delete; HttpStack(const HttpStack&) = delete; HttpStack& operator=(const HttpStack&) = delete; std::unique_ptr m_stack; }; } // namespace torrent::net #endif // TORRENT_NET_HTTP_GET_H libtorrent-0.16.11/src/torrent/net/address_info.h0000644000000000000000000000365415175073411015372 #ifndef LIBTORRENT_NET_ADDRESS_INFO_H #define LIBTORRENT_NET_ADDRESS_INFO_H #include #include #include #include #include #include #include namespace torrent { struct ai_deleter { void operator()(addrinfo* ai) const { if (ai != nullptr) ::freeaddrinfo(ai); } }; using ai_unique_ptr = std::unique_ptr; using c_ai_unique_ptr = std::unique_ptr; using ai_sockaddr_func = std::function; inline std::unique_ptr ai_make_hint(int flags, int family, int socktype); int ai_get_addrinfo(const char* nodename, const char* servname, const addrinfo* hints, ai_unique_ptr& res) LIBTORRENT_EXPORT; // Helper functions: // TODO: Consider servname "0". // TODO: ai_get_first_sa_err that returns a tuple? sa_unique_ptr ai_get_first_sa(const char* nodename, const char* servname = nullptr, const addrinfo* hints = nullptr) LIBTORRENT_EXPORT; int ai_each_inet_inet6_first(const char* nodename, const ai_sockaddr_func& lambda) LIBTORRENT_EXPORT; // Get all addrinfo's, iterate, etc. // // Safe conversion from unique_ptr arguments: // inline void aip_clear(ai_unique_ptr& aip) { *aip = addrinfo{}; } inline int aip_get_addrinfo(const char* nodename, const char* servname, const ai_unique_ptr& hints, ai_unique_ptr& res) { return ai_get_addrinfo(nodename, servname, hints.get(), res); } inline int aip_get_addrinfo(const char* nodename, const char* servname, const c_ai_unique_ptr& hints, ai_unique_ptr& res) { return ai_get_addrinfo(nodename, servname, hints.get(), res); } // // Implementations: // inline std::unique_ptr ai_make_hint(int flags, int family, int socktype) { auto aip = std::make_unique(); *aip = addrinfo{}; aip->ai_flags = flags; aip->ai_family = family; aip->ai_socktype = socktype; return aip; } } // namespace torrent #endif libtorrent-0.16.11/src/torrent/net/socket_address_key.cc0000644000000000000000000000012715175073411016725 // Copyright (C) 2005-2014, Jari Sundell // All rights reserved. #include "config.h" libtorrent-0.16.11/src/torrent/net/poll_epoll.cc0000644000000000000000000003015415175073411015224 #include "config.h" #ifdef USE_EPOLL #include "torrent/net/poll.h" #include #include #include #include "torrent/exceptions.h" #include "torrent/event.h" #include "torrent/system/thread.h" #include "torrent/utils/log.h" #define LT_LOG(log_fmt, ...) \ lt_log_print(LOG_CONNECTION_FD, "epoll: " log_fmt, __VA_ARGS__); #define LT_LOG_EVENT(log_fmt, ...) \ lt_log_print(LOG_CONNECTION_FD, "epoll->%i : %s : " log_fmt, event->file_descriptor(), event->type_name(), __VA_ARGS__); #if 0 #define LT_LOG_DEBUG_DATA_FD(log_fmt, ...) \ lt_log_print(LOG_CONNECTION_FD, "epoll->%i: " log_fmt, itr->data.fd, __VA_ARGS__); #else #define LT_LOG_DEBUG_DATA_FD(log_fmt, ...) #endif namespace torrent::net { class PollEvent { public: PollEvent(Event* event) : event(event) {} ~PollEvent() = default; uint32_t mask{}; Event* event{}; }; class PollInternal { public: using Table = std::map>; uint32_t event_mask(Event* event); void set_event_mask(Event* event, uint32_t mask); void flush(); void modify(torrent::Event* event, unsigned short op, uint32_t mask, uint32_t old_mask); int m_fd; unsigned int m_max_sockets{}; unsigned int m_max_events{}; unsigned int m_waiting_events{}; Table m_table; std::unique_ptr m_events; }; uint32_t PollInternal::event_mask(Event* event) { if (event->file_descriptor() == -1) throw internal_error("PollInternal::event_mask() invalid file descriptor for event: " + event->print_name_fd_str()); auto itr = m_table.find(event->file_descriptor()); if (itr == m_table.end()) throw internal_error("PollInternal::event_mask() event not found: " + event->print_name_fd_str()); if (event != itr->second->event) throw internal_error("PollInternal::event_mask() event mismatch: " + event->print_name_fd_str()); return itr->second->mask; } void PollInternal::set_event_mask(Event* event, uint32_t mask) { if (event->file_descriptor() == -1) throw internal_error("PollInternal::set_event_mask() invalid file descriptor for event: " + event->print_name_fd_str()); event->m_poll_event->mask = mask; } // See https://github.com/enki/libev/blob/master/ev_epoll.c for suggestions. void PollInternal::modify(Event* event, unsigned short op, uint32_t mask, uint32_t old_mask) { if (event_mask(event) == mask) return; LT_LOG_EVENT("modify event : op:%hx mask:%hx", op, mask); if (event->m_poll_event == nullptr) throw internal_error("PollInternal::modify(): event has no PollEvent associated: " + event->print_name_fd_str()); epoll_event e{}; e.data.ptr = event->m_poll_event.get(); e.events = mask; set_event_mask(event, mask); if (epoll_ctl(m_fd, op, event->file_descriptor(), &e)) { switch (op) { case EPOLL_CTL_ADD: LT_LOG_EVENT("modify event EPOLL_CTL_ADD failed: %s", std::strerror(errno)); throw internal_error("PollInternal::modify(): epoll_ctl(ADD) error for event: " + event->print_name_fd_str() + " : " + std::string(std::strerror(errno))); case EPOLL_CTL_MOD: if (errno == ENOENT) { LT_LOG_EVENT("modify event EPOLL_CTL_MOD failed with ENOENT", 0); // TODO: We might be getting removed because EPOLLERR is not considered being in the poll? // // We still seem to be getting error events (verify with libcurl idle poll). // // Add a test here to see if we're moving from no events to some events, and only retry in that case. if (old_mask & (EPOLLIN | EPOLLOUT)) { LT_LOG_EVENT("modify event EPOLL_CTL_MOD cannot retry as old mask had read/write", 0); throw internal_error("PollInternal::modify(): epoll_ctl(MOD) error for event: " + event->print_name_fd_str() + " : in read/write but got ENOENT"); } if (epoll_ctl(m_fd, EPOLL_CTL_ADD, event->file_descriptor(), &e) == 0) { LT_LOG_EVENT("modify event EPOLL_CTL_ADD retry after ENOENT succeeded", 0); return; } } LT_LOG_EVENT("modify event EPOLL_CTL_MOD failed: %s", std::strerror(errno)); throw internal_error("PollInternal::modify(): epoll_ctl(MOD) error for event: " + event->print_name_fd_str() + " : " + std::string(std::strerror(errno))); case EPOLL_CTL_DEL: LT_LOG_EVENT("modify event EPOLL_CTL_DEL failed: %s", std::strerror(errno)); throw internal_error("PollInternal::modify(): epoll_ctl(DEL) error for event: " + event->print_name_fd_str() + " : " + std::string(std::strerror(errno))); default: throw internal_error("PollInternal::modify(): unknown epoll_ctl operation: " + std::to_string(op) + " for event: " + event->print_name_fd_str()); } } } std::unique_ptr Poll::create() { auto socket_open_max = sysconf(_SC_OPEN_MAX); if (socket_open_max == -1) throw internal_error("Poll::create() : sysconf(_SC_OPEN_MAX) failed : " + std::string(std::strerror(errno))); int fd = epoll_create(socket_open_max); if (fd == -1) throw internal_error("Poll::create() : kqueue() failed : " + std::string(std::strerror(errno))); auto poll = new Poll(); poll->m_internal = std::make_unique(); poll->m_internal->m_fd = fd; poll->m_internal->m_max_sockets = static_cast(socket_open_max); poll->m_internal->m_max_events = 1024; poll->m_internal->m_events = std::make_unique(poll->m_internal->m_max_events); return std::unique_ptr(poll); } Poll::~Poll() { assert(m_internal->m_table.empty() && "Poll::~Poll() called with non-empty event table."); ::close(m_internal->m_fd); m_internal->m_fd = -1; } unsigned int Poll::do_poll(int64_t timeout_usec) { int status = poll(timeout_usec); if (status == -1) { if (errno != EINTR) throw internal_error("Poll::work() " + std::string(std::strerror(errno))); return 0; } return process(); } int Poll::poll(int timeout_usec) { int nfds = ::epoll_wait(m_internal->m_fd, m_internal->m_events.get(), m_internal->m_max_events, timeout_usec / 1000); if (nfds == -1) return -1; m_internal->m_waiting_events = nfds; return nfds; } // We check m_internal->m_table to make sure the Event is still listening to the // event, so it is safe to remove Event's while in working. // // TODO: Do we want to guarantee if the Event has been removed from // some event but not closed, it won't call that event? Think so... unsigned int Poll::process() { unsigned int count{}; m_processing = true; m_closed_events.clear(); for (epoll_event *itr = m_internal->m_events.get(), *last = m_internal->m_events.get() + m_internal->m_waiting_events; itr != last; ++itr) { if (system::Thread::self()->callbacks_should_interrupt_polling()) system::Thread::self()->process_callbacks(true); auto* poll_event = static_cast(itr->data.ptr); if (itr->events & EPOLLERR) { count++; if (poll_event->event == nullptr) continue; // TODO: EPOLLERR is always reported, so we don't need error event registration. if (!(poll_event->mask & EPOLLERR)) throw internal_error("Poll::process() received error event for event not in error: " + poll_event->event->print_name_fd_str()); auto event_info = poll_event->event->print_name_fd_str(); poll_event->event->event_error(); if (poll_event->mask != 0) throw internal_error("Poll::process() event_error called but event mask not cleared: " + event_info); // We assume that the event gets closed if we get an error. continue; } if (itr->events & EPOLLIN && poll_event->mask & EPOLLIN) { poll_event->event->event_read(); count++; } if (itr->events & EPOLLOUT && poll_event->mask & EPOLLOUT) { poll_event->event->event_write(); count++; } } m_closed_events.clear(); m_processing = false; m_internal->m_waiting_events = 0; return count; } uint32_t Poll::open_max() const { return m_internal->m_max_sockets; } // TODO: Change open() to take initial filter state. // TODO: Make open register for at least error events. void Poll::open(Event* event) { LT_LOG_EVENT("open event", 0); if (event->file_descriptor() == -1) throw internal_error("Poll::open() invalid file descriptor for event: " + event->print_name_fd_str()); if (event->m_poll_event != nullptr) throw internal_error("Poll::open() called but the event is already associated with a poll: " + event->print_name_fd_str()); if (m_internal->m_table.find(event->file_descriptor()) != m_internal->m_table.end()) throw internal_error("Poll::open() event already exists: " + event->print_name_fd_str()); event->m_poll_event = std::make_shared(event); m_internal->m_table[event->file_descriptor()] = event->m_poll_event; } void Poll::close(Event* event) { LT_LOG_EVENT("close event", 0); auto* poll_event = event->m_poll_event.get(); if (poll_event == nullptr) return; if (poll_event->event != event) throw internal_error("Poll::close() event mismatch: " + event->print_name_fd_str()); if (m_internal->event_mask(event) != 0) throw internal_error("Poll::close() called but the file descriptor is active: " + event->print_name_fd_str()); if (m_internal->m_table.erase(event->file_descriptor()) == 0) throw internal_error("Poll::close() event not found: " + event->print_name_fd_str()); if (m_processing) m_closed_events.push_back(event->m_poll_event); poll_event->event = nullptr; event->m_poll_event = nullptr; } bool Poll::in_read(Event* event) { return m_internal->event_mask(event) & EPOLLIN; } bool Poll::in_write(Event* event) { return m_internal->event_mask(event) & EPOLLOUT; } bool Poll::in_error(Event* event) { return m_internal->event_mask(event) & EPOLLERR; } void Poll::insert_read(Event* event) { auto mask = m_internal->event_mask(event); if (mask & EPOLLIN) return; LT_LOG_EVENT("insert read", 0); m_internal->modify(event, mask ? EPOLL_CTL_MOD : EPOLL_CTL_ADD, mask | EPOLLIN, mask); } void Poll::insert_write(Event* event) { auto mask = m_internal->event_mask(event); if (mask & EPOLLOUT) return; LT_LOG_EVENT("insert write", 0); m_internal->modify(event, mask ? EPOLL_CTL_MOD : EPOLL_CTL_ADD, mask | EPOLLOUT, mask); } void Poll::insert_error(Event* event) { auto mask = m_internal->event_mask(event); if (mask & EPOLLERR) return; LT_LOG_EVENT("insert error", 0); m_internal->modify(event, mask ? EPOLL_CTL_MOD : EPOLL_CTL_ADD, mask | EPOLLERR, mask); } void Poll::remove_read(Event* event) { auto mask = m_internal->event_mask(event); auto new_mask = mask & ~EPOLLIN; if (!(mask & EPOLLIN)) return; LT_LOG_EVENT("remove read", 0); m_internal->modify(event, new_mask ? EPOLL_CTL_MOD : EPOLL_CTL_DEL, new_mask, mask); } void Poll::remove_write(Event* event) { auto mask = m_internal->event_mask(event); auto new_mask = mask & ~EPOLLOUT; if (!(mask & EPOLLOUT)) return; LT_LOG_EVENT("remove write", 0); m_internal->modify(event, new_mask ? EPOLL_CTL_MOD : EPOLL_CTL_DEL, new_mask, mask); } void Poll::remove_error(Event* event) { auto mask = m_internal->event_mask(event); auto new_mask = mask & ~EPOLLERR; if (!(mask & EPOLLERR)) return; LT_LOG_EVENT("remove error", 0); m_internal->modify(event, new_mask ? EPOLL_CTL_MOD : EPOLL_CTL_DEL, new_mask, mask); } void Poll::remove_and_close(Event* event) { remove_read(event); remove_write(event); remove_error(event); close(event); } } // namespace torrent #endif // USE_EPOLL libtorrent-0.16.11/src/torrent/net/http_get.h0000644000000000000000000000510015175073411014534 #ifndef LIBTORRENT_TORRENT_NET_HTTP_GET_H #define LIBTORRENT_TORRENT_NET_HTTP_GET_H #include #include #include #include #include #include namespace torrent::net { class CurlGet; class CurlStack; class HttpStack; class LIBTORRENT_EXPORT HttpGet { public: HttpGet(); HttpGet(std::string url, std::shared_ptr stream); ~HttpGet(); HttpGet(const HttpGet&) = default; HttpGet& operator=(const HttpGet&) = default; bool is_valid() const { return m_curl_get != nullptr; } // close_and_keep_callbacks() and close_and_cancel_callbacks() do not immediately close as they // use callbacks to thread_net. Some functions throw internal_error if they don't wait for close // to finish. void close_and_keep_callbacks(); void close_and_cancel_callbacks(system::Thread* callback_thread); // Always call before reset() if the HttpGet is being reused. void wait_for_close(); bool try_wait_for_close(); // Calling reset is not allowed while the HttpGet is in the stack. Does not clear slots or callbacks. void reset(const std::string& url, std::shared_ptr str); std::string url() const; uint32_t timeout() const; int64_t size_done() const; int64_t size_total() const; void set_timeout(uint32_t seconds); void use_ipv4(); void use_ipv6(); void prefer_ipv4(); void prefer_ipv6(); // The slots add callbacks to the calling thread when triggered, and all slots will remain in the // thread's callback queue even if the underlying CurlGet is closed or deleted. // // Calling add_*_slot is not allowed while the HttpGet is in the stack. void add_done_slot(const std::function& slot); void add_failed_slot(const std::function& slot); // TODO: Add a closed_slot. bool operator<(const HttpGet& other) const; bool operator==(const HttpGet& other) const; protected: friend class HttpStack; auto curl_get() { return m_curl_get; } private: std::shared_ptr m_curl_get; }; inline bool HttpGet::operator<(const HttpGet& other) const { return m_curl_get < other.m_curl_get; } inline bool HttpGet::operator==(const HttpGet& other) const { return m_curl_get == other.m_curl_get; } } // namespace torrent::net #endif // TORRENT_NET_HTTP_GET_H libtorrent-0.16.11/src/torrent/net/socket_address_key.h0000644000000000000000000000561015175073411016571 // Copyright (C) 2005-2014, Jari Sundell // All rights reserved. #ifndef LIBTORRENT_UTILS_SOCKET_ADDRESS_KEY_H #define LIBTORRENT_UTILS_SOCKET_ADDRESS_KEY_H #include #include #include #include // Unique key for the socket address, excluding port numbers, etc. // TODO: Add include files... namespace torrent { class [[gnu::packed]] socket_address_key { public: // TODO: Disable default ctor? // socket_address_key(const sockaddr* sa) : m_sockaddr(sa) {} bool is_valid() const { return m_family != AF_UNSPEC; } // // Rename, add same family, valid inet4/6. // TODO: Make from_sockaddr an rvalue reference. static bool is_comparable_sockaddr(const sockaddr* sa); static socket_address_key from_sockaddr(const sockaddr* sa); static socket_address_key from_sin_addr(const sockaddr_in& sa); static socket_address_key from_sin6_addr(const sockaddr_in6& sa); bool operator < (const socket_address_key& sa) const; bool operator > (const socket_address_key& sa) const; bool operator == (const socket_address_key& sa) const; private: sa_family_t m_family; union { in_addr m_addr; in6_addr m_addr6; }; }; inline bool socket_address_key::is_comparable_sockaddr(const sockaddr* sa) { return sa != NULL && (sa->sa_family == AF_INET || sa->sa_family == AF_INET6); } // TODO: Require socket length? inline socket_address_key socket_address_key::from_sockaddr(const sockaddr* sa) { socket_address_key result{}; result.m_family = AF_UNSPEC; if (sa == NULL) return result; switch (sa->sa_family) { case AF_INET: // Using hardware order to allo for the use of operator < to // sort in lexical order. result.m_family = AF_INET; result.m_addr.s_addr = ntohl(reinterpret_cast(sa)->sin_addr.s_addr); break; case AF_INET6: result.m_family = AF_INET6; result.m_addr6 = reinterpret_cast(sa)->sin6_addr; break; default: break; } return result; } inline socket_address_key socket_address_key::from_sin_addr(const sockaddr_in& sa) { socket_address_key result{}; result.m_family = AF_INET; result.m_addr.s_addr = ntohl(sa.sin_addr.s_addr); return result; } inline socket_address_key socket_address_key::from_sin6_addr(const sockaddr_in6& sa) { socket_address_key result{}; result.m_family = AF_INET6; result.m_addr6 = sa.sin6_addr; return result; } inline bool socket_address_key::operator < (const socket_address_key& sa) const { return std::memcmp(this, &sa, sizeof(socket_address_key)) < 0; } inline bool socket_address_key::operator > (const socket_address_key& sa) const { return std::memcmp(this, &sa, sizeof(socket_address_key)) > 0; } inline bool socket_address_key::operator == (const socket_address_key& sa) const { return std::memcmp(this, &sa, sizeof(socket_address_key)) == 0; } } // namespace torrent #endif libtorrent-0.16.11/src/torrent/net/http_get.cc0000644000000000000000000000644115175073411014703 #include "config.h" #include "torrent/net/http_get.h" #include #include #include "net/curl_get.h" #include "net/curl_stack.h" #include "torrent/exceptions.h" #include "torrent/net/http_stack.h" #include "torrent/system/thread.h" namespace torrent::net { // TODO: Use Resolver for dns lookups? HttpGet::HttpGet() = default; HttpGet::HttpGet(std::string url, std::shared_ptr stream) : m_curl_get(new CurlGet(std::move(url), std::move(stream))) { } HttpGet::~HttpGet() = default; void HttpGet::close_and_keep_callbacks() { if (!is_valid()) throw torrent::internal_error("HttpGet::close() called on an invalid HttpGet object."); CurlGet::close_and_keep_callbacks(m_curl_get); } void HttpGet::close_and_cancel_callbacks(system::Thread* callback_thread) { if (!is_valid()) throw torrent::internal_error("HttpGet::close_and_cancel_callbacks() called on an invalid HttpGet object."); CurlGet::close_and_cancel_callbacks(m_curl_get, callback_thread); } void HttpGet::wait_for_close() { if (!is_valid()) throw torrent::internal_error("HttpGet::wait_for_close() called on an invalid HttpGet object."); m_curl_get->wait_for_close(); } bool HttpGet::try_wait_for_close() { if (!is_valid()) return false; return m_curl_get->try_wait_for_close(); } void HttpGet::reset(const std::string& url, std::shared_ptr stream) { if (m_curl_get == nullptr) m_curl_get = std::make_shared(); m_curl_get->reset(url, std::move(stream)); } std::string HttpGet::url() const { return m_curl_get->url(); } uint32_t HttpGet::timeout() const { return m_curl_get->timeout(); } int64_t HttpGet::size_done() const { return m_curl_get->size_done(); } int64_t HttpGet::size_total() const { return m_curl_get->size_total(); } void HttpGet::set_timeout(uint32_t seconds) { m_curl_get->set_timeout(seconds); } void HttpGet::use_ipv4() { m_curl_get->set_initial_resolve(CurlGet::RESOLVE_IPV4); m_curl_get->set_retry_resolve(CurlGet::RESOLVE_NONE); } void HttpGet::use_ipv6() { m_curl_get->set_initial_resolve(CurlGet::RESOLVE_IPV6); m_curl_get->set_retry_resolve(CurlGet::RESOLVE_NONE); } void HttpGet::prefer_ipv4() { m_curl_get->set_initial_resolve(CurlGet::RESOLVE_IPV4); m_curl_get->set_retry_resolve(CurlGet::RESOLVE_IPV6); } void HttpGet::prefer_ipv6() { m_curl_get->set_initial_resolve(CurlGet::RESOLVE_IPV6); m_curl_get->set_retry_resolve(CurlGet::RESOLVE_IPV4); } void HttpGet::add_done_slot(const std::function& slot) { if (m_curl_get == nullptr) throw torrent::internal_error("HttpGet::add_done_slot() called on an invalid HttpGet object."); auto thread = this_thread::thread(); m_curl_get->add_done_slot([thread, slot, curl_get = m_curl_get.get()]() { thread->callback(curl_get, [slot]() { slot(); }); }); } void HttpGet::add_failed_slot(const std::function& slot) { if (m_curl_get == nullptr) throw torrent::internal_error("HttpGet::add_failed_slot() called on an invalid HttpGet object."); auto thread = this_thread::thread(); m_curl_get->add_failed_slot([thread, slot, curl_get = m_curl_get.get()](const std::string& error) { thread->callback(curl_get, [slot, error]() { slot(error); }); }); } } // namespace torrent::net libtorrent-0.16.11/src/torrent/net/http_stack.cc0000644000000000000000000000701315175073411015225 #include "config.h" #include "torrent/net/http_stack.h" #include #include #include #include "net/curl_get.h" #include "net/curl_stack.h" #include "net/thread_net.h" #include "torrent/exceptions.h" #include "torrent/net/http_get.h" #include "torrent/system/thread.h" namespace torrent::net { // TODO: This should be in a net/utils file. // TODO: Require scheme to also be returned / checked? std::tuple parse_uri_host_port(const std::string& uri) { char* host_ptr{}; char* port_ptr{}; CURLU* curlu = curl_url(); if (curl_url_set(curlu, CURLUPART_URL, uri.c_str(), CURLU_NON_SUPPORT_SCHEME) != CURLUE_OK) { curl_url_cleanup(curlu); return {"", 0}; } if (curl_url_get(curlu, CURLUPART_HOST, &host_ptr, 0) != CURLUE_OK) { curl_url_cleanup(curlu); return {"", 0}; } std::string host(host_ptr); uint16_t port{}; curl_free(host_ptr); if (curl_url_get(curlu, CURLUPART_PORT, &port_ptr, 0) != CURLUE_OK) { curl_url_cleanup(curlu); return {host, 0}; } auto result = std::from_chars(port_ptr, port_ptr + std::strlen(port_ptr), port); curl_free(port_ptr); curl_url_cleanup(curlu); if (result.ec != std::errc()) return {"", 0}; return {host, port}; } HttpStack::HttpStack(system::Thread* thread) : m_stack(new CurlStack(thread)) { } HttpStack::~HttpStack() = default; void HttpStack::shutdown() { m_stack->shutdown(); } void HttpStack::start_get(HttpGet& http_get) { if (!http_get.is_valid()) throw torrent::internal_error("HttpStack::start_get() called with an invalid HttpGet object."); CurlGet::start(http_get.curl_get(), m_stack.get()); } unsigned int HttpStack::size() const { return m_stack->size(); } unsigned int HttpStack::max_cache_connections() const { return m_stack->max_cache_connections(); } unsigned int HttpStack::max_host_connections() const { return m_stack->max_host_connections(); } unsigned int HttpStack::max_total_connections() const { return m_stack->max_total_connections(); } void HttpStack::set_max_cache_connections(unsigned int value) { m_stack->set_max_cache_connections(value); } void HttpStack::set_max_host_connections(unsigned int value) { m_stack->set_max_host_connections(value); } void HttpStack::set_max_total_connections(unsigned int value) { m_stack->set_max_total_connections(value); } std::string HttpStack::user_agent() const { return m_stack->user_agent(); } std::string HttpStack::http_proxy() const { return m_stack->http_proxy(); } std::string HttpStack::http_capath() const { return m_stack->http_capath(); } std::string HttpStack::http_cacert() const { return m_stack->http_cacert(); } void HttpStack::set_user_agent(const std::string& s) { m_stack->set_user_agent(s); } void HttpStack::set_http_proxy(const std::string& s) { m_stack->set_http_proxy(s); } void HttpStack::set_http_capath(const std::string& s) { m_stack->set_http_capath(s); } void HttpStack::set_http_cacert(const std::string& s) { m_stack->set_http_cacert(s); } bool HttpStack::ssl_verify_host() const { return m_stack->ssl_verify_host(); } bool HttpStack::ssl_verify_peer() const { return m_stack->ssl_verify_peer(); } void HttpStack::set_ssl_verify_host(bool s) { m_stack->set_ssl_verify_host(s); } void HttpStack::set_ssl_verify_peer(bool s) { m_stack->set_ssl_verify_peer(s); } long HttpStack::dns_timeout() const { return m_stack->dns_timeout(); } void HttpStack::set_dns_timeout(long timeout) { m_stack->set_dns_timeout(timeout); } } // namespace torrent::net libtorrent-0.16.11/src/torrent/net/network_config.cc0000644000000000000000000004163115175073411016103 #include "config.h" #include "torrent/net/network_config.h" #include "torrent/exceptions.h" #include "torrent/net/http_stack.h" #include "torrent/net/socket_address.h" #include "torrent/runtime/network_manager.h" #include "torrent/utils/log.h" // TODO: Add net category and add it to important/complete log outputs. #define LT_LOG_NOTICE(log_fmt, ...) \ lt_log_print_subsystem(LOG_NOTICE, "net::network_config", log_fmt, __VA_ARGS__); namespace torrent::net { namespace { c_sa_shared_ptr inet_any_value = sa_make_inet_any(); c_sa_shared_ptr inet6_any_value = sa_make_inet6_any(); } NetworkConfig::NetworkConfig() { m_bind_inet_address = sa_make_unspec(); m_bind_inet6_address = sa_make_unspec(); m_local_inet_address = sa_make_unspec(); m_local_inet6_address = sa_make_unspec(); m_proxy_address = sa_make_unspec(); } bool NetworkConfig::is_block_ipv4() const { auto guard = lock_guard(); return m_block_ipv4; } bool NetworkConfig::is_block_ipv6() const { auto guard = lock_guard(); return m_block_ipv6; } bool NetworkConfig::is_block_ipv4in6() const { auto guard = lock_guard(); return m_block_ipv4in6; } bool NetworkConfig::is_block_outgoing() const { auto guard = lock_guard(); return m_block_outgoing; } bool NetworkConfig::is_prefer_ipv6() const { auto guard = lock_guard(); return m_prefer_ipv6; } void NetworkConfig::set_block_ipv4(bool v) { auto guard = lock_guard(); m_block_ipv4 = v; runtime::network_manager()->restart_listen(); } void NetworkConfig::set_block_ipv6(bool v) { auto guard = lock_guard(); m_block_ipv6 = v; runtime::network_manager()->restart_listen(); } void NetworkConfig::set_block_ipv4in6(bool v) { auto guard = lock_guard(); m_block_ipv4in6 = v; runtime::network_manager()->restart_listen(); } void NetworkConfig::set_block_outgoing(bool v) { auto guard = lock_guard(); m_block_outgoing = v; runtime::network_manager()->restart_listen(); } void NetworkConfig::set_prefer_ipv6(bool v) { auto guard = lock_guard(); m_prefer_ipv6 = v; } int NetworkConfig::priority() const { auto guard = lock_guard(); return m_priority; } void NetworkConfig::set_priority(int p) { auto guard = lock_guard(); m_priority = p; } c_sa_shared_ptr NetworkConfig::bind_address_best_match() const { return generic_address_best_match(m_bind_inet_address, m_bind_inet6_address); } std::string NetworkConfig::bind_address_best_match_str() const { return generic_address_best_match_str(m_bind_inet_address, m_bind_inet6_address); } c_sa_shared_ptr NetworkConfig::bind_address_or_unspec_and_null() const { return generic_address_or_unspec_and_null(m_bind_inet_address, m_bind_inet6_address); } c_sa_shared_ptr NetworkConfig::bind_address_or_any_and_null() const { return generic_address_or_any_and_null(m_bind_inet_address, m_bind_inet6_address); } c_sa_shared_ptr NetworkConfig::bind_address_for_connect(int family) const { return generic_address_for_connect(family, m_bind_inet_address, m_bind_inet6_address); } c_sa_shared_ptr NetworkConfig::bind_inet_address() const { auto guard = lock_guard(); return m_bind_inet_address; } std::string NetworkConfig::bind_inet_address_str() const { auto guard = lock_guard(); return sa_addr_str(m_bind_inet_address.get()); } c_sa_shared_ptr NetworkConfig::bind_inet6_address() const { auto guard = lock_guard(); return m_bind_inet6_address; } std::string NetworkConfig::bind_inet6_address_str() const { auto guard = lock_guard(); return sa_addr_str(m_bind_inet6_address.get()); } std::tuple NetworkConfig::bind_addresses_or_null() const { auto guard = lock_guard(); auto inet_addr = m_bind_inet_address; auto inet6_addr = m_bind_inet6_address; if (inet_addr->sa_family != AF_UNSPEC && inet6_addr->sa_family == AF_UNSPEC) inet6_addr = nullptr; else if (inet6_addr->sa_family != AF_UNSPEC && inet_addr->sa_family == AF_UNSPEC) inet_addr = nullptr; if (m_block_ipv4) inet_addr = nullptr; if (m_block_ipv6) inet6_addr = nullptr; return std::make_tuple(inet_addr, inet6_addr); } std::tuple NetworkConfig::bind_addresses_str() const { auto guard = lock_guard(); return std::make_tuple(sa_addr_str(m_bind_inet_address.get()), sa_addr_str(m_bind_inet6_address.get())); } c_sa_shared_ptr NetworkConfig::local_address_best_match() const { return generic_address_best_match(m_local_inet_address, m_local_inet6_address); } std::string NetworkConfig::local_address_best_match_str() const { return generic_address_best_match_str(m_local_inet_address, m_local_inet6_address); } c_sa_shared_ptr NetworkConfig::local_address_or_unspec_and_null() const { return generic_address_or_unspec_and_null(m_local_inet_address, m_local_inet6_address); } c_sa_shared_ptr NetworkConfig::local_address_or_any_and_null() const { return generic_address_or_any_and_null(m_local_inet_address, m_local_inet6_address); } c_sa_shared_ptr NetworkConfig::local_inet_address() const { auto guard = lock_guard(); return m_local_inet_address; } c_sa_shared_ptr NetworkConfig::local_inet_address_or_null() const { auto guard = lock_guard(); if (m_block_ipv4 || m_local_inet_address->sa_family == AF_UNSPEC) return nullptr; return m_local_inet_address; } std::string NetworkConfig::local_inet_address_str() const { auto guard = lock_guard(); return sa_addr_str(m_local_inet_address.get()); } c_sa_shared_ptr NetworkConfig::local_inet6_address() const { auto guard = lock_guard(); return m_local_inet6_address; } c_sa_shared_ptr NetworkConfig::local_inet6_address_or_null() const { auto guard = lock_guard(); if (m_block_ipv6 || m_local_inet6_address->sa_family == AF_UNSPEC) return nullptr; return m_local_inet6_address; } std::string NetworkConfig::local_inet6_address_str() const { auto guard = lock_guard(); return sa_addr_str(m_local_inet6_address.get()); } c_sa_shared_ptr NetworkConfig::proxy_address() const { auto guard = lock_guard(); return m_proxy_address; } std::string NetworkConfig::proxy_address_str() const { auto guard = lock_guard(); return sa_pretty_str(m_proxy_address.get()); } // TODO: Move all management tasks here. void NetworkConfig::set_bind_address(const sockaddr* sa) { auto guard = lock_guard(); set_generic_address_unsafe("bind", m_bind_inet_address, m_bind_inet6_address, sa); runtime::network_manager()->restart_listen(); } void NetworkConfig::set_bind_address_str(const std::string& addr) { set_bind_address(sa_lookup_address(addr, AF_UNSPEC).get()); } void NetworkConfig::set_bind_inet_address(const sockaddr* sa) { auto guard = lock_guard(); set_generic_inet_address_unsafe("bind", m_bind_inet_address, sa); runtime::network_manager()->restart_listen(); } void NetworkConfig::set_bind_inet_address_str(const std::string& addr) { set_bind_inet_address(sa_lookup_address(addr, AF_INET).get()); } void NetworkConfig::set_bind_inet6_address(const sockaddr* sa) { auto guard = lock_guard(); set_generic_inet6_address_unsafe("bind", m_bind_inet6_address, sa); runtime::network_manager()->restart_listen(); } void NetworkConfig::set_bind_inet6_address_str(const std::string& addr) { set_bind_inet6_address(sa_lookup_address(addr, AF_INET6).get()); } void NetworkConfig::set_local_address(const sockaddr* sa) { if (sa_is_any(sa)) throw input_error("Tried to set local address to an any address."); auto guard = lock_guard(); set_generic_address_unsafe("local", m_local_inet_address, m_local_inet6_address, sa); } void NetworkConfig::set_local_address_str(const std::string& addr) { set_local_address(sa_lookup_address(addr, AF_UNSPEC).get()); } void NetworkConfig::set_local_inet_address(const sockaddr* sa) { if (sa_is_any(sa)) throw input_error("Tried to set local inet address to an any address."); auto guard = lock_guard(); set_generic_inet_address_unsafe("local", m_local_inet_address, sa); } void NetworkConfig::set_local_inet_address_str(const std::string& addr) { set_local_inet_address(sa_lookup_address(addr, AF_INET).get()); } void NetworkConfig::set_local_inet6_address(const sockaddr* sa) { if (sa_is_any(sa)) throw input_error("Tried to set local inet6 address to an any address."); auto guard = lock_guard(); set_generic_inet6_address_unsafe("local", m_local_inet6_address, sa); } void NetworkConfig::set_local_inet6_address_str(const std::string& addr) { set_local_inet6_address(sa_lookup_address(addr, AF_INET6).get()); } void NetworkConfig::set_proxy_address(const sockaddr* sa) { if (sa->sa_family != AF_INET && sa->sa_family != AF_UNSPEC) throw input_error("Tried to set a proxy address that is not an unspec/inet address."); if (sa_port(sa) == 0) throw input_error("Tried to set a proxy address with a zero port."); auto guard = lock_guard(); LT_LOG_NOTICE("proxy address : %s", sa_pretty_str(sa).c_str()); m_proxy_address = sa_copy(sa); } uint32_t NetworkConfig::encryption_options() const { auto guard = lock_guard(); return m_encryption_options; } void NetworkConfig::set_encryption_options(uint32_t opts) { auto guard = lock_guard(); m_encryption_options = opts; } int NetworkConfig::listen_backlog() const { auto guard = lock_guard(); return m_listen_backlog; } void NetworkConfig::set_listen_backlog(int backlog) { if (backlog < 1) throw input_error("Tried to set a listen backlog less than 1."); if (backlog > (1 << 16)) throw input_error("Tried to set a listen backlog greater than 65536."); auto guard = lock_guard(); m_listen_backlog = backlog; runtime::network_manager()->restart_listen(); } uint16_t NetworkConfig::override_dht_port() const { auto guard = lock_guard(); return m_override_dht_port; } void NetworkConfig::set_override_dht_port(uint16_t port) { auto guard = lock_guard(); m_override_dht_port = port; } uint32_t NetworkConfig::send_buffer_size() const { auto guard = lock_guard(); return m_send_buffer_size; } void NetworkConfig::set_send_buffer_size(uint32_t s) { auto guard = lock_guard(); m_send_buffer_size = s; } uint32_t NetworkConfig::receive_buffer_size() const { auto guard = lock_guard(); return m_receive_buffer_size; } void NetworkConfig::set_receive_buffer_size(uint32_t s) { auto guard = lock_guard(); m_receive_buffer_size = s; } NetworkConfig::listen_addresses NetworkConfig::listen_addresses_unsafe() { auto inet_address = m_block_ipv4 ? nullptr : m_bind_inet_address; auto inet6_address = m_block_ipv6 ? nullptr : m_bind_inet6_address; if (inet_address == nullptr && inet6_address == nullptr) return {}; if (inet_address == nullptr) { if (inet6_address->sa_family == AF_UNSPEC) return {nullptr, inet6_any_value, m_block_ipv4in6}; return {nullptr, inet6_address, m_block_ipv4in6}; } if (inet6_address == nullptr) { if (inet_address->sa_family == AF_UNSPEC) return {inet_any_value, nullptr, false}; return {inet_address, nullptr, false}; } if (inet_address->sa_family == AF_UNSPEC && inet6_address->sa_family == AF_UNSPEC) { if (m_block_ipv4in6) return {inet_any_value, inet6_any_value, true}; return {nullptr, inet6_any_value, false}; } if (inet_address->sa_family != AF_UNSPEC && inet6_address->sa_family != AF_UNSPEC) return {inet_address, inet6_address, m_block_ipv4in6}; if (inet_address->sa_family != AF_UNSPEC) return {inet_address, nullptr, false}; if (inet6_address->sa_family != AF_UNSPEC) return {nullptr, inet6_address, m_block_ipv4in6}; throw internal_error("NetworkConfig::listen_addresses_unsafe(): reached unreachable code."); } int NetworkConfig::listen_backlog_unsafe() const { return m_listen_backlog; } // // Helper Functions: // // The caller must make sure the address family is not blocked before making a connection. c_sa_shared_ptr NetworkConfig::generic_address_best_match(const c_sa_shared_ptr& inet_address, const c_sa_shared_ptr& inet6_address) const { auto guard = lock_guard(); if (inet_address->sa_family == AF_UNSPEC) return inet6_address; if (inet6_address->sa_family == AF_UNSPEC) return inet_address; if (m_prefer_ipv6) { if (m_block_ipv6 && !m_block_ipv4) return inet_address; return inet6_address; } if (m_block_ipv4 && !m_block_ipv6) return inet6_address; return inet_address; } std::string NetworkConfig::generic_address_best_match_str(const c_sa_shared_ptr& inet_address, const c_sa_shared_ptr& inet6_address) const { return sa_addr_str(generic_address_best_match(inet_address, inet6_address).get()); } // TODO: There's a race condition if block/local is changed after returning unspec, and the caller // checks if ipv4/6 is blocked. Create a function that locks NC and sets up and locals fd. c_sa_shared_ptr NetworkConfig::generic_address_or_unspec_and_null(const c_sa_shared_ptr& inet_address, const c_sa_shared_ptr& inet6_address) const { auto guard = lock_guard(); if (m_block_ipv4 && m_block_ipv6) return nullptr; if (inet_address->sa_family == AF_UNSPEC && inet6_address->sa_family == AF_UNSPEC) return inet_address; if (inet_address->sa_family == AF_UNSPEC) { if (m_block_ipv6) return nullptr; return inet6_address; } if (inet6_address->sa_family == AF_UNSPEC) { if (m_block_ipv4) return nullptr; return inet_address; } if (m_prefer_ipv6 && !m_block_ipv6) return inet6_address; if (m_block_ipv4) return inet6_address; return inet_address; } c_sa_shared_ptr NetworkConfig::generic_address_or_any_and_null(const c_sa_shared_ptr& inet_address, const c_sa_shared_ptr& inet6_address) const { auto address = generic_address_or_unspec_and_null(inet_address, inet6_address); if (address == nullptr) return nullptr; if (address->sa_family != AF_UNSPEC) return address; if (!m_block_ipv6) return inet6_any_value; if (!m_block_ipv4) return inet_any_value; throw internal_error("NetworkConfig::generic_address_or_any_and_null(): both ipv4 and ipv6 are blocked and returned unspec"); } c_sa_shared_ptr NetworkConfig::generic_address_for_connect(int family, const c_sa_shared_ptr& inet_address, const c_sa_shared_ptr& inet6_address) const { auto guard = lock_guard(); // if (m_block_outgoing) // return nullptr; switch (family) { case AF_INET: if (m_block_ipv4) return nullptr; if (inet_address->sa_family != AF_UNSPEC) return inet_address; if (inet6_address->sa_family != AF_UNSPEC) { if (m_block_ipv4in6) return nullptr; return inet6_address; } return inet_any_value; case AF_INET6: if (m_block_ipv6) return nullptr; if (inet6_address->sa_family != AF_UNSPEC) return inet6_address; if (inet_address->sa_family != AF_UNSPEC) return nullptr; return inet6_any_value; default: throw input_error("NetworkConfig::generic_address_for_connect() called with invalid address family"); } } // TODO: Move all management tasks here. void NetworkConfig::set_generic_address_unsafe(const char* category, c_sa_shared_ptr& inet_address, c_sa_shared_ptr& inet6_address, const sockaddr* sa) { if (sa->sa_family != AF_INET && sa->sa_family != AF_UNSPEC) throw input_error("Tried to set a " + std::string(category) + " address that is not an unspec/inet address."); if (sa_port(sa) != 0) throw input_error("Tried to set a " + std::string(category) + " address with a non-zero port."); LT_LOG_NOTICE("%s address : %s", category, sa_pretty_str(sa).c_str()); switch (sa->sa_family) { case AF_UNSPEC: inet_address = sa_make_unspec(); inet6_address = sa_make_unspec(); break; case AF_INET: inet_address = sa_copy(sa); inet6_address = sa_make_unspec(); break; case AF_INET6: inet_address = sa_make_unspec(); inet6_address = sa_copy(sa); break; default: throw internal_error("NetworkConfig::set_" + std::string(category) + "_address: invalid address family"); } // TODO: Warning if not matching block/prefer } void NetworkConfig::set_generic_inet_address_unsafe(const char* category, c_sa_shared_ptr& inet_address, const sockaddr* sa) { if (sa->sa_family != AF_INET && sa->sa_family != AF_UNSPEC) throw input_error("Tried to set a " + std::string(category) + " inet address that is not an unspec/inet address."); if (sa_port(sa) != 0) throw input_error("Tried to set a " + std::string(category) + " inet address with a non-zero port."); LT_LOG_NOTICE("%s inet address : %s", category, sa_pretty_str(sa).c_str()); inet_address = sa_copy(sa); } void NetworkConfig::set_generic_inet6_address_unsafe(const char* category, c_sa_shared_ptr& inet6_address, const sockaddr* sa) { if (sa->sa_family != AF_INET6 && sa->sa_family != AF_UNSPEC) throw input_error("Tried to set a " + std::string(category) + " inet6 address that is not an unspec/inet6 address."); if (sa_port(sa) != 0) throw input_error("Tried to set a " + std::string(category) + " inet6 address with a non-zero port."); LT_LOG_NOTICE("%s inet6 address : %s", category, sa_pretty_str(sa).c_str()); inet6_address = sa_copy(sa); } } // namespace torrent::net libtorrent-0.16.11/src/torrent/net/socket_address.h0000644000000000000000000003640615175073411015730 #ifndef LIBTORRENT_NET_SOCKET_ADDRESS_H #define LIBTORRENT_NET_SOCKET_ADDRESS_H #include #include #include namespace torrent { bool sa_is_unspec(const sockaddr* sa) LIBTORRENT_EXPORT; bool sa_is_inet(const sockaddr* sa) LIBTORRENT_EXPORT; bool sa_is_inet6(const sockaddr* sa) LIBTORRENT_EXPORT; bool sa_is_inet_inet6(const sockaddr* sa) LIBTORRENT_EXPORT; bool sa_is_any(const sockaddr* sa) LIBTORRENT_EXPORT; bool sin_is_any(const sockaddr_in* sa) LIBTORRENT_EXPORT; bool sin6_is_any(const sockaddr_in6* sa) LIBTORRENT_EXPORT; bool sa_is_broadcast(const sockaddr* sa) LIBTORRENT_EXPORT; bool sin_is_broadcast(const sockaddr_in* sa) LIBTORRENT_EXPORT; bool sa_is_v4mapped(const sockaddr* sa) LIBTORRENT_EXPORT; bool sin6_is_v4mapped(const sockaddr_in6* sa) LIBTORRENT_EXPORT; bool sa_is_port_any(const sockaddr* sa) LIBTORRENT_EXPORT; size_t sa_length(const sockaddr* sa) LIBTORRENT_EXPORT; sa_unique_ptr sa_make_unspec() LIBTORRENT_EXPORT; sa_unique_ptr sa_make_inet() LIBTORRENT_EXPORT; sa_unique_ptr sa_make_inet_any() LIBTORRENT_EXPORT; sa_unique_ptr sa_make_inet_h(uint32_t addr, uint16_t port) LIBTORRENT_EXPORT; sa_unique_ptr sa_make_inet_n(uint32_t addr, uint16_t port) LIBTORRENT_EXPORT; sa_unique_ptr sa_make_inet6() LIBTORRENT_EXPORT; sa_unique_ptr sa_make_inet6_any() LIBTORRENT_EXPORT; sa_unique_ptr sa_make_unix(const std::string& pathname) LIBTORRENT_EXPORT; sa_unique_ptr sa_convert(const sockaddr* sa) LIBTORRENT_EXPORT; sa_unique_ptr sa_copy(const sockaddr* sa) LIBTORRENT_EXPORT; sa_unique_ptr sa_copy_in(const sockaddr_in* sa) LIBTORRENT_EXPORT; sa_unique_ptr sa_copy_in6(const sockaddr_in6* sa) LIBTORRENT_EXPORT; sa_unique_ptr sa_copy_addr(const sockaddr* sa, uint16_t port = 0) LIBTORRENT_EXPORT; sa_unique_ptr sa_copy_addr_in(const sockaddr_in* sa, uint16_t port = 0) LIBTORRENT_EXPORT; sa_unique_ptr sa_copy_addr_in6(const sockaddr_in6* sa, uint16_t port = 0) LIBTORRENT_EXPORT; sa_unique_ptr sa_copy_unmapped(const sockaddr* sa) LIBTORRENT_EXPORT; sin_unique_ptr sin_copy(const sockaddr_in* sa) LIBTORRENT_EXPORT; sin6_unique_ptr sin6_copy(const sockaddr_in6* sa) LIBTORRENT_EXPORT; sin_unique_ptr sin_make() LIBTORRENT_EXPORT; sin_unique_ptr sin_make_any() LIBTORRENT_EXPORT; sin_unique_ptr sin_make_h(uint32_t addr, uint16_t port) LIBTORRENT_EXPORT; sin_unique_ptr sin_make_n(uint32_t addr, uint16_t port) LIBTORRENT_EXPORT; sin6_unique_ptr sin6_make() LIBTORRENT_EXPORT; sin6_unique_ptr sin6_make_any() LIBTORRENT_EXPORT; sa_unique_ptr sa_from_v4mapped(const sockaddr* sa) LIBTORRENT_EXPORT; sa_unique_ptr sa_to_v4mapped(const sockaddr* sa) LIBTORRENT_EXPORT; sa_unique_ptr sa_from_v4mapped_in6(const sockaddr_in6* sin6) LIBTORRENT_EXPORT; sa_unique_ptr sa_to_v4mapped_in(const sockaddr_in* sin) LIBTORRENT_EXPORT; sin_unique_ptr sin_from_v4mapped_in6(const sockaddr_in6* sin6) LIBTORRENT_EXPORT; sin6_unique_ptr sin6_to_v4mapped_in(const sockaddr_in* sin) LIBTORRENT_EXPORT; sa_unique_ptr sa_from_in(sin_unique_ptr sinp) LIBTORRENT_EXPORT; c_sa_unique_ptr sa_from_in(c_sin_unique_ptr sinp) LIBTORRENT_EXPORT; sa_unique_ptr sa_from_in6(sin6_unique_ptr sin6p) LIBTORRENT_EXPORT; c_sa_unique_ptr sa_from_in6(c_sin6_unique_ptr sin6p) LIBTORRENT_EXPORT; sin_unique_ptr sin_from_sa(sa_unique_ptr sap) LIBTORRENT_EXPORT; sin6_unique_ptr sin6_from_sa(sa_unique_ptr sap) LIBTORRENT_EXPORT; c_sin_unique_ptr sin_from_c_sa(c_sa_unique_ptr sap) LIBTORRENT_EXPORT; c_sin6_unique_ptr sin6_from_c_sa(c_sa_unique_ptr sap) LIBTORRENT_EXPORT; void sa_clear_inet6(sockaddr_in6* sa) LIBTORRENT_EXPORT; uint16_t sa_port(const sockaddr* sa) LIBTORRENT_EXPORT; void sa_set_port(sockaddr* sa, uint16_t port) LIBTORRENT_EXPORT; bool sa_equal(const sockaddr* lhs, const sockaddr* rhs) LIBTORRENT_EXPORT; bool sin_equal(const sockaddr_in* lhs, const sockaddr_in* rhs) LIBTORRENT_EXPORT; bool sin6_equal(const sockaddr_in6* lhs, const sockaddr_in6* rhs) LIBTORRENT_EXPORT; bool sa_equal_addr(const sockaddr* lhs, const sockaddr* rhs) LIBTORRENT_EXPORT; bool sin_equal_addr(const sockaddr_in* lhs, const sockaddr_in* rhs) LIBTORRENT_EXPORT; bool sin6_equal_addr(const sockaddr_in6* lhs, const sockaddr_in6* rhs) LIBTORRENT_EXPORT; bool sa_less(const sockaddr* lhs, const sockaddr* rhs) LIBTORRENT_EXPORT; bool sa_less_addr(const sockaddr* lhs, const sockaddr* rhs) LIBTORRENT_EXPORT; std::string sa_addr_str(const sockaddr* sa) LIBTORRENT_EXPORT; std::string sin_addr_str(const sockaddr_in* sa) LIBTORRENT_EXPORT; std::string sin6_addr_str(const sockaddr_in6* sa) LIBTORRENT_EXPORT; std::string sa_pretty_str(const sockaddr* sa) LIBTORRENT_EXPORT; std::string sin_pretty_str(const sockaddr_in* sa) LIBTORRENT_EXPORT; std::string sin_pretty_or_empty(const sockaddr_in* sa) LIBTORRENT_EXPORT; std::string sin6_pretty_str(const sockaddr_in6* sa) LIBTORRENT_EXPORT; std::string sin6_pretty_or_empty(const sockaddr_in6* sa) LIBTORRENT_EXPORT; // // Other types: // sa_inet_union sa_inet_union_from_sa(const sockaddr* sa) LIBTORRENT_EXPORT; bool fd_sap_equal(const fd_sap_tuple& lhs, const fd_sap_tuple& rhs) LIBTORRENT_EXPORT; // // Safe conversion from unique_ptr arguments: // inline bool sap_is_unspec(const sa_unique_ptr& sap) { return sa_is_unspec(sap.get()); } inline bool sap_is_unspec(const c_sa_unique_ptr& sap) { return sa_is_unspec(sap.get()); } inline bool sap_is_inet(const sa_unique_ptr& sap) { return sa_is_inet(sap.get()); } inline bool sap_is_inet(const c_sa_unique_ptr& sap) { return sa_is_inet(sap.get()); } inline bool sap_is_inet6(const sa_unique_ptr& sap) { return sa_is_inet6(sap.get()); } inline bool sap_is_inet6(const c_sa_unique_ptr& sap) { return sa_is_inet6(sap.get()); } inline bool sap_is_inet_inet6(const sa_unique_ptr& sap) { return sa_is_inet_inet6(sap.get()); } inline bool sap_is_inet_inet6(const c_sa_unique_ptr& sap) { return sa_is_inet_inet6(sap.get()); } inline bool sap_is_any(const sa_unique_ptr& sap) { return sa_is_any(sap.get()); } inline bool sap_is_any(const c_sa_unique_ptr& sap) { return sa_is_any(sap.get()); } inline bool sinp_is_any(const sin_unique_ptr& sinp) { return sin_is_any(sinp.get()); } inline bool sinp_is_any(const c_sin_unique_ptr& sinp) { return sin_is_any(sinp.get()); } inline bool sinp6_is_any(const sin6_unique_ptr& sin6p) { return sin6_is_any(sin6p.get()); } inline bool sinp6_is_any(const c_sin6_unique_ptr& sin6p) { return sin6_is_any(sin6p.get()); } inline bool sap_is_broadcast(const sa_unique_ptr& sap) { return sa_is_broadcast(sap.get()); } inline bool sap_is_broadcast(const c_sa_unique_ptr& sap) { return sa_is_broadcast(sap.get()); } inline bool sinp_is_broadcast(const sin_unique_ptr& sap) { return sin_is_broadcast(sap.get()); } inline bool sinp_is_broadcast(const c_sin_unique_ptr& sap) { return sin_is_broadcast(sap.get()); } inline bool sap_is_v4mapped(const sa_unique_ptr& sap) { return sa_is_v4mapped(sap.get()); } inline bool sap_is_v4mapped(const c_sa_unique_ptr& sap) { return sa_is_v4mapped(sap.get()); } inline bool sinp6_is_v4mapped(const sin6_unique_ptr& sin6p) { return sin6_is_v4mapped(sin6p.get()); } inline bool sinp6_is_v4mapped(const c_sin6_unique_ptr& sin6p) { return sin6_is_v4mapped(sin6p.get()); } inline bool sap_is_port_any(const sa_unique_ptr& sap) { return sa_is_port_any(sap.get()); } inline bool sap_is_port_any(const c_sa_unique_ptr& sap) { return sa_is_port_any(sap.get()); } inline size_t sap_length(const sa_unique_ptr& sap) { return sa_length(sap.get()); } inline size_t sap_length(const c_sa_unique_ptr& sap) { return sa_length(sap.get()); } inline sa_unique_ptr sap_copy(const sa_unique_ptr& sap) { return sa_copy(sap.get()); } inline sa_unique_ptr sap_copy(const c_sa_unique_ptr& sap) { return sa_copy(sap.get()); } inline sa_unique_ptr sap_copy_addr(const sa_unique_ptr& sap, uint16_t port = 0) { return sa_copy_addr(sap.get(), port); } inline sa_unique_ptr sap_copy_addr(const c_sa_unique_ptr& sap, uint16_t port = 0) { return sa_copy_addr(sap.get(), port); } inline sa_unique_ptr sap_copy_in(const sin_unique_ptr& sinp) { return sa_copy_in(sinp.get()); } inline sa_unique_ptr sap_copy_in(const c_sin_unique_ptr& sinp) { return sa_copy_in(sinp.get()); } inline sa_unique_ptr sap_copy_in6(const sin6_unique_ptr& sin6p) { return sa_copy_in6(sin6p.get()); } inline sa_unique_ptr sap_copy_in6(const c_sin6_unique_ptr& sin6p) { return sa_copy_in6(sin6p.get()); } inline sin_unique_ptr sinp_copy(const sin_unique_ptr& sinp) { return sin_copy(sinp.get()); } inline sin_unique_ptr sinp_copy(const c_sin_unique_ptr& sinp) { return sin_copy(sinp.get()); } inline sin6_unique_ptr sin6p_copy(const sin6_unique_ptr& sin6p) { return sin6_copy(sin6p.get()); } inline sin6_unique_ptr sin6p_copy(const c_sin6_unique_ptr& sin6p) { return sin6_copy(sin6p.get()); } inline sa_unique_ptr sap_from_v4mapped(const sa_unique_ptr& sap) { return sa_from_v4mapped(sap.get()); } inline sa_unique_ptr sap_from_v4mapped(const c_sa_unique_ptr& sap) { return sa_from_v4mapped(sap.get()); } inline sa_unique_ptr sap_to_v4mapped(const sa_unique_ptr& sap) { return sa_to_v4mapped(sap.get()); } inline sa_unique_ptr sap_to_v4mapped(const c_sa_unique_ptr& sap) { return sa_to_v4mapped(sap.get()); } inline sin_unique_ptr sinp_from_v4mapped_in6(const sin6_unique_ptr& sin6p) { return sin_from_v4mapped_in6(sin6p.get()); } inline sin_unique_ptr sinp_from_v4mapped_in6(const c_sin6_unique_ptr& sin6p) { return sin_from_v4mapped_in6(sin6p.get()); } inline sin6_unique_ptr sin6p_to_v4mapped_in(const sin_unique_ptr& sinp) { return sin6_to_v4mapped_in(sinp.get()); } inline sin6_unique_ptr sin6p_to_v4mapped_in(const c_sin_unique_ptr& sinp) { return sin6_to_v4mapped_in(sinp.get()); } inline uint16_t sap_port(const sa_unique_ptr& sap) { return sa_port(sap.get()); } inline uint16_t sap_port(const c_sa_unique_ptr& sap) { return sa_port(sap.get()); } inline void sap_set_port(const sa_unique_ptr& sap, uint16_t port) { sa_set_port(sap.get(), port); } inline bool sap_equal(const sa_unique_ptr& lhs, const sa_unique_ptr& rhs) { return sa_equal(lhs.get(), rhs.get()); } inline bool sap_equal(const sa_unique_ptr& lhs, const c_sa_unique_ptr& rhs) { return sa_equal(lhs.get(), rhs.get()); } inline bool sap_equal(const c_sa_unique_ptr& lhs, const sa_unique_ptr& rhs) { return sa_equal(lhs.get(), rhs.get()); } inline bool sap_equal(const c_sa_unique_ptr& lhs, const c_sa_unique_ptr& rhs) { return sa_equal(lhs.get(), rhs.get()); } inline bool sinp_equal(const sin_unique_ptr& lhs, const sin_unique_ptr& rhs) { return sin_equal(lhs.get(), rhs.get()); } inline bool sinp_equal(const sin_unique_ptr& lhs, const c_sin_unique_ptr& rhs) { return sin_equal(lhs.get(), rhs.get()); } inline bool sinp_equal(const c_sin_unique_ptr& lhs, const sin_unique_ptr& rhs) { return sin_equal(lhs.get(), rhs.get()); } inline bool sinp_equal(const c_sin_unique_ptr& lhs, const c_sin_unique_ptr& rhs) { return sin_equal(lhs.get(), rhs.get()); } inline bool sin6p_equal(const sin6_unique_ptr& lhs, const sin6_unique_ptr& rhs) { return sin6_equal(lhs.get(), rhs.get()); } inline bool sin6p_equal(const sin6_unique_ptr& lhs, const c_sin6_unique_ptr& rhs) { return sin6_equal(lhs.get(), rhs.get()); } inline bool sin6p_equal(const c_sin6_unique_ptr& lhs, const sin6_unique_ptr& rhs) { return sin6_equal(lhs.get(), rhs.get()); } inline bool sin6p_equal(const c_sin6_unique_ptr& lhs, const c_sin6_unique_ptr& rhs) { return sin6_equal(lhs.get(), rhs.get()); } inline bool sap_equal_addr(const sa_unique_ptr& lhs, const sa_unique_ptr& rhs) { return sa_equal_addr(lhs.get(), rhs.get()); } inline bool sap_equal_addr(const sa_unique_ptr& lhs, const c_sa_unique_ptr& rhs) { return sa_equal_addr(lhs.get(), rhs.get()); } inline bool sap_equal_addr(const c_sa_unique_ptr& lhs, const sa_unique_ptr& rhs) { return sa_equal_addr(lhs.get(), rhs.get()); } inline bool sap_equal_addr(const c_sa_unique_ptr& lhs, const c_sa_unique_ptr& rhs) { return sa_equal_addr(lhs.get(), rhs.get()); } inline bool sinp_equal_addr(const sin_unique_ptr& lhs, const sin_unique_ptr& rhs) { return sin_equal_addr(lhs.get(), rhs.get()); } inline bool sinp_equal_addr(const sin_unique_ptr& lhs, const c_sin_unique_ptr& rhs) { return sin_equal_addr(lhs.get(), rhs.get()); } inline bool sinp_equal_addr(const c_sin_unique_ptr& lhs, const sin_unique_ptr& rhs) { return sin_equal_addr(lhs.get(), rhs.get()); } inline bool sinp_equal_addr(const c_sin_unique_ptr& lhs, const c_sin_unique_ptr& rhs) { return sin_equal_addr(lhs.get(), rhs.get()); } inline bool sin6p_equal_addr(const sin6_unique_ptr& lhs, const sin6_unique_ptr& rhs) { return sin6_equal_addr(lhs.get(), rhs.get()); } inline bool sin6p_equal_addr(const sin6_unique_ptr& lhs, const c_sin6_unique_ptr& rhs) { return sin6_equal_addr(lhs.get(), rhs.get()); } inline bool sin6p_equal_addr(const c_sin6_unique_ptr& lhs, const sin6_unique_ptr& rhs) { return sin6_equal_addr(lhs.get(), rhs.get()); } inline bool sin6p_equal_addr(const c_sin6_unique_ptr& lhs, const c_sin6_unique_ptr& rhs) { return sin6_equal_addr(lhs.get(), rhs.get()); } inline std::string sap_addr_str(const sa_unique_ptr& sap) { return sa_addr_str(sap.get()); } inline std::string sap_addr_str(const c_sa_unique_ptr& sap) { return sa_addr_str(sap.get()); } inline std::string sap_pretty_str(const sa_unique_ptr& sap) { return sa_pretty_str(sap.get()); } inline std::string sap_pretty_str(const c_sa_unique_ptr& sap) { return sa_pretty_str(sap.get()); } inline std::string sinp_pretty_str(const sin_unique_ptr& sinp) { return sin_pretty_str(sinp.get()); } inline std::string sinp_pretty_str(const c_sin_unique_ptr& sinp) { return sin_pretty_str(sinp.get()); } inline std::string sin6p_pretty_str(const sin6_unique_ptr& sin6p) { return sin6_pretty_str(sin6p.get()); } inline std::string sin6p_pretty_str(const c_sin6_unique_ptr& sin6p) { return sin6_pretty_str(sin6p.get()); } // // Implementations: // inline sa_unique_ptr sa_from_v4mapped_in6(const sockaddr_in6* sin6) { return sa_from_in(sin_from_v4mapped_in6(sin6)); } inline sa_unique_ptr sa_to_v4mapped_in(const sockaddr_in* sin) { return sa_from_in6(sin6_to_v4mapped_in(sin)); } inline sa_unique_ptr sa_from_in(sin_unique_ptr sinp) { return sa_unique_ptr(reinterpret_cast(sinp.release())); } inline c_sa_unique_ptr sa_from_in(c_sin_unique_ptr sinp) { return c_sa_unique_ptr(reinterpret_cast(sinp.release())); } inline sa_unique_ptr sa_from_in6(sin6_unique_ptr sin6p) { return sa_unique_ptr(reinterpret_cast(sin6p.release())); } inline c_sa_unique_ptr sa_from_in6(c_sin6_unique_ptr sin6p) { return c_sa_unique_ptr(reinterpret_cast(sin6p.release())); } inline bool fd_sap_equal(const fd_sap_tuple& lhs, const fd_sap_tuple& rhs) { return std::get<0>(lhs) == std::get<0>(rhs) && sap_equal(std::get<1>(lhs), std::get<1>(rhs)); } } // namespace torrent #endif libtorrent-0.16.11/src/torrent/net/fd.h0000644000000000000000000000651315175073411013320 #ifndef LIBTORRENT_NET_FD_H #define LIBTORRENT_NET_FD_H #include #include #include namespace torrent { enum fd_flags : int { fd_flag_stream = 0x1, fd_flag_datagram = 0x10, fd_flag_nonblock = 0x20, fd_flag_reuse_address = 0x40, fd_flag_v4 = 0x80, // renamed fd_flag_v4only = 0x80, fd_flag_v6only = 0x100, fd_flag_all = 0x1ff, }; constexpr bool fd_valid_flags(fd_flags flags); int fd_open(fd_flags flags) LIBTORRENT_EXPORT; int fd_open_family(fd_flags flags, int family) LIBTORRENT_EXPORT; int fd_open_local(fd_flags flags) LIBTORRENT_EXPORT; void fd_open_pipe(int& fd1, int& fd2) LIBTORRENT_EXPORT; void fd_open_socket_pair(int& fd1, int& fd2) LIBTORRENT_EXPORT; void fd_close(int fd) LIBTORRENT_EXPORT; int fd_accept(int fd) LIBTORRENT_EXPORT; fd_sap_tuple fd_sap_accept(int fd) LIBTORRENT_EXPORT; bool fd_bind(int fd, const sockaddr* sa) LIBTORRENT_EXPORT; bool fd_bind_with_length(int fd, const sockaddr* sa, socklen_t length) LIBTORRENT_EXPORT; bool fd_connect(int fd, const sockaddr* sa) LIBTORRENT_EXPORT; bool fd_connect_with_family(int fd, const sockaddr* sa, int family) LIBTORRENT_EXPORT; bool fd_listen(int fd, int backlog) LIBTORRENT_EXPORT; c_sa_unique_ptr fd_get_peer_name(int fd) LIBTORRENT_EXPORT; bool fd_get_socket_error(int fd, int* value) LIBTORRENT_EXPORT; c_sa_unique_ptr fd_get_socket_name(int fd) LIBTORRENT_EXPORT; bool fd_get_type(int fd, int* value) LIBTORRENT_EXPORT; bool fd_set_dont_route(int fd, bool state) LIBTORRENT_EXPORT; bool fd_set_nonblock(int fd) LIBTORRENT_EXPORT; bool fd_set_reuse_address(int fd, bool state) LIBTORRENT_EXPORT; bool fd_set_priority(int fd, int family, int priority) LIBTORRENT_EXPORT; bool fd_set_tcp_nodelay(int fd) LIBTORRENT_EXPORT; bool fd_set_v6only(int fd, bool state) LIBTORRENT_EXPORT; bool fd_set_send_buffer_size(int fd, uint32_t size) LIBTORRENT_EXPORT; bool fd_set_receive_buffer_size(int fd, uint32_t size) LIBTORRENT_EXPORT; // Defined with gnu::weak so that we can override them in tests. [[gnu::weak]] int fd__accept(int socket, sockaddr *address, socklen_t *address_len) LIBTORRENT_EXPORT; [[gnu::weak]] int fd__bind(int socket, const sockaddr *address, socklen_t address_len) LIBTORRENT_EXPORT; [[gnu::weak]] int fd__close(int fildes) LIBTORRENT_EXPORT; [[gnu::weak]] int fd__connect(int socket, const sockaddr *address, socklen_t address_len) LIBTORRENT_EXPORT; [[gnu::weak]] int fd__fcntl_int(int fildes, int cmd, int arg) LIBTORRENT_EXPORT; [[gnu::weak]] int fd__listen(int socket, int backlog) LIBTORRENT_EXPORT; [[gnu::weak]] int fd__setsockopt_int(int socket, int level, int option_name, int option_value) LIBTORRENT_EXPORT; [[gnu::weak]] int fd__socket(int domain, int type, int protocol) LIBTORRENT_EXPORT; constexpr fd_flags operator |(fd_flags lhs, fd_flags rhs) { return static_cast(static_cast(lhs) | static_cast(rhs)); } inline fd_flags& operator |=(fd_flags& lhs, fd_flags rhs) { return (lhs = lhs | rhs); } constexpr bool fd_valid_flags(fd_flags flags) { return ((flags & fd_flag_stream) || (flags & fd_flag_datagram)) && !((flags & fd_flag_stream) && (flags & fd_flag_datagram)) && !((flags & fd_flag_v4only) && (flags & fd_flag_v6only)) && !(flags & ~(fd_flag_all)); } } // namespace torrent #endif libtorrent-0.16.11/src/torrent/net/network_config.h0000644000000000000000000001700015175073411015736 #ifndef LIBTORRENT_TORRENT_NET_NETWORK_CONFIG_H #define LIBTORRENT_TORRENT_NET_NETWORK_CONFIG_H #include #include #include #include namespace torrent::net { class LIBTORRENT_EXPORT NetworkConfig { public: static constexpr int iptos_default = 0; static constexpr int iptos_lowdelay = IPTOS_LOWDELAY; static constexpr int iptos_throughput = IPTOS_THROUGHPUT; static constexpr int iptos_reliability = IPTOS_RELIABILITY; static constexpr uint32_t encryption_none = 0; static constexpr uint32_t encryption_allow_incoming = 0x1; static constexpr uint32_t encryption_try_outgoing = 0x2; static constexpr uint32_t encryption_require = 0x3; static constexpr uint32_t encryption_require_RC4 = 0x4; static constexpr uint32_t encryption_enable_retry = 0x8; static constexpr uint32_t encryption_prefer_plaintext = 0x10; // Internal to libtorrent. static constexpr uint32_t encryption_use_proxy = 0x20; static constexpr uint32_t encryption_retrying = 0x40; NetworkConfig(); // TODO: Move helper functions in rtorrent manager here. // TODO: Verify we attempt to connect to cached peers on startup, even before tracker requests. bool is_block_ipv4() const; bool is_block_ipv6() const; bool is_block_ipv4in6() const; bool is_block_outgoing() const; bool is_prefer_ipv6() const; void set_block_ipv4(bool v); void set_block_ipv6(bool v); void set_block_ipv4in6(bool v); void set_block_outgoing(bool v); void set_prefer_ipv6(bool v); int priority() const; void set_priority(int p); // Use bind_address_best_match for display purposes only, or if you manually check blocking. // // If bind_address_or_null returns null, then available protocols are blocked. This means if the // user binds to e.g. inet6 and blocks ipv6, then no connections are possible. // // To bind one and keep the other protocol unbound, set the other address to either 0.0.0.0 or ::. c_sa_shared_ptr bind_address_best_match() const; std::string bind_address_best_match_str() const; c_sa_shared_ptr bind_address_or_unspec_and_null() const; c_sa_shared_ptr bind_address_or_any_and_null() const; c_sa_shared_ptr bind_address_for_connect(int family) const; c_sa_shared_ptr bind_inet_address() const; std::string bind_inet_address_str() const; c_sa_shared_ptr bind_inet6_address() const; std::string bind_inet6_address_str() const; std::tuple bind_addresses_or_null() const; std::tuple bind_addresses_str() const; c_sa_shared_ptr local_address_best_match() const; std::string local_address_best_match_str() const; c_sa_shared_ptr local_address_or_unspec_and_null() const; c_sa_shared_ptr local_address_or_any_and_null() const; c_sa_shared_ptr local_inet_address() const; c_sa_shared_ptr local_inet_address_or_null() const; std::string local_inet_address_str() const; c_sa_shared_ptr local_inet6_address() const; c_sa_shared_ptr local_inet6_address_or_null() const; std::string local_inet6_address_str() const; c_sa_shared_ptr proxy_address() const; std::string proxy_address_str() const; void set_bind_address(const sockaddr* sa); void set_bind_address_str(const std::string& addr); void set_bind_inet_address(const sockaddr* sa); void set_bind_inet_address_str(const std::string& addr); void set_bind_inet6_address(const sockaddr* sa); void set_bind_inet6_address_str(const std::string& addr); void set_local_address(const sockaddr* sa); void set_local_address_str(const std::string& addr); void set_local_inet_address(const sockaddr* sa); void set_local_inet_address_str(const std::string& addr); void set_local_inet6_address(const sockaddr* sa); void set_local_inet6_address_str(const std::string& addr); void set_proxy_address(const sockaddr* sa); uint32_t encryption_options() const; void set_encryption_options(uint32_t opts); int listen_backlog() const; void set_listen_backlog(int backlog); uint16_t override_dht_port() const; void set_override_dht_port(uint16_t port); uint32_t send_buffer_size() const; void set_send_buffer_size(uint32_t s); uint32_t receive_buffer_size() const; void set_receive_buffer_size(uint32_t s); protected: friend class torrent::ConnectionManager; friend class torrent::runtime::NetworkManager; typedef std::tuple listen_addresses; void lock() const { m_mutex.lock(); } auto lock_guard() const { return std::lock_guard(m_mutex); } void unlock() const { m_mutex.unlock(); } auto& mutex() const { return m_mutex; } listen_addresses listen_addresses_unsafe(); int listen_backlog_unsafe() const; private: c_sa_shared_ptr generic_address_best_match(const c_sa_shared_ptr& inet_address, const c_sa_shared_ptr& inet6_address) const; std::string generic_address_best_match_str(const c_sa_shared_ptr& inet_address, const c_sa_shared_ptr& inet6_address) const; c_sa_shared_ptr generic_address_or_unspec_and_null(const c_sa_shared_ptr& inet_address, const c_sa_shared_ptr& inet6_address) const; c_sa_shared_ptr generic_address_or_any_and_null(const c_sa_shared_ptr& inet_address, const c_sa_shared_ptr& inet6_address) const; c_sa_shared_ptr generic_address_for_connect(int family, const c_sa_shared_ptr& inet_address, const c_sa_shared_ptr& inet6_address) const; c_sa_shared_ptr generic_address_for_family(int family, const c_sa_shared_ptr& inet_address, const c_sa_shared_ptr& inet6_address) const; void set_generic_address_unsafe(const char* category, c_sa_shared_ptr& inet_address, c_sa_shared_ptr& inet6_address, const sockaddr* sa); void set_generic_inet_address_unsafe(const char* category, c_sa_shared_ptr& inet_address, const sockaddr* sa); void set_generic_inet6_address_unsafe(const char* category, c_sa_shared_ptr& inet6_address, const sockaddr* sa); mutable std::mutex m_mutex; bool m_block_ipv4{false}; bool m_block_ipv6{false}; bool m_block_ipv4in6{false}; bool m_block_outgoing{false}; bool m_prefer_ipv6{false}; // TODO: Rename m_tos_priority. int m_priority{iptos_throughput}; c_sa_shared_ptr m_bind_inet_address; c_sa_shared_ptr m_bind_inet6_address; c_sa_shared_ptr m_local_inet_address; c_sa_shared_ptr m_local_inet6_address; c_sa_shared_ptr m_proxy_address; int m_encryption_options{encryption_none}; int m_listen_backlog{SOMAXCONN}; uint16_t m_override_dht_port{0}; uint32_t m_send_buffer_size{0}; uint32_t m_receive_buffer_size{0}; }; } // namespace torrent::net #endif libtorrent-0.16.11/src/torrent/net/poll_kqueue.cc0000644000000000000000000002655215175073411015417 #include "config.h" #ifdef USE_KQUEUE #include "poll.h" #include #include #include #include #include #include "utils/log.h" #include "torrent/event.h" #include "torrent/exceptions.h" #include "torrent/system/thread.h" // TODO: Change to LOG_CONNECTION_POLL // TODO: Optimize table memory size, and add a reference to Event for direct lookup. #define LT_LOG(log_fmt, ...) \ lt_log_print(LOG_CONNECTION_FD, "kqueue: " log_fmt, __VA_ARGS__); #define LT_LOG_EVENT(log_fmt, ...) \ lt_log_print(LOG_CONNECTION_FD, "kqueue->%i : %s : " log_fmt, event->file_descriptor(), event->type_name(), __VA_ARGS__); #if 1 #define LT_LOG_DEBUG(log_fmt, ...) #define LT_LOG_DEBUG_IDENT(log_fmt, ...) #else #define LT_LOG_DEBUG(log_fmt, ...) \ lt_log_print(LOG_CONNECTION_FD, "kqueue: " log_fmt, __VA_ARGS__); #define LT_LOG_DEBUG_IDENT(log_fmt, ...) \ lt_log_print(LOG_CONNECTION_FD, "kqueue->%u : " log_fmt, static_cast(itr->ident), __VA_ARGS__); #endif namespace torrent::net { class PollEvent { public: PollEvent(Event* e) : event(e) {} ~PollEvent() = default; uint32_t mask{}; Event* event{}; }; class PollInternal { public: using Table = std::map>; static constexpr uint32_t flag_read = 0x1; static constexpr uint32_t flag_write = 0x2; static constexpr uint32_t flag_error = 0x4; uint32_t event_mask(Event* event); void set_event_mask(Event* event, uint32_t mask); void flush(); void modify(torrent::Event* event, unsigned short op, short mask); int m_fd; unsigned int m_max_sockets{}; unsigned int m_max_events{}; unsigned int m_waiting_events{}; unsigned int m_changed_events{}; Table m_table; std::unique_ptr m_events; std::unique_ptr m_changes; }; uint32_t PollInternal::event_mask(Event* event) { // TODO: Replace `file_descriptor()` with m_event_poll. if (event->file_descriptor() == -1) throw internal_error("PollInternal::event_mask() invalid file descriptor for event: " + event->print_name_fd_str()); auto itr = m_table.find(event->file_descriptor()); if (itr == m_table.end()) throw internal_error("PollInternal::event_mask() event not found: " + event->print_name_fd_str()); if (event != itr->second->event) throw internal_error("PollInternal::event_mask() event mismatch: " + event->print_name_fd_str()); return itr->second->mask; } void PollInternal::set_event_mask(Event* event, uint32_t mask) { if (event->file_descriptor() == -1) throw internal_error("PollInternal::set_event_mask() invalid file descriptor for event: " + event->print_name_fd_str()); event->m_poll_event->mask = mask; } void PollInternal::flush() { if (m_changed_events == 0) return; LT_LOG_DEBUG("flushing events : changed:%u", m_changed_events); if (::kevent(m_fd, m_changes.get(), m_changed_events, nullptr, 0, nullptr) == -1) throw internal_error("PollInternal::flush() error: " + std::string(std::strerror(errno))); m_changed_events = 0; } void PollInternal::modify(Event* event, unsigned short op, short mask) { LT_LOG_EVENT("modify event : op:%hx mask:%hx changed:%u", op, mask, m_changed_events); // Flush the changed filters to the kernel if the buffer is full. if (m_changed_events == m_max_events) flush(); struct kevent* itr = m_changes.get() + (m_changed_events++); EV_SET(itr, event->file_descriptor(), mask, op, 0, 0, event->m_poll_event.get()); } std::unique_ptr Poll::create() { auto socket_open_max = sysconf(_SC_OPEN_MAX); if (socket_open_max == -1) throw internal_error("Poll::create() : sysconf(_SC_OPEN_MAX) failed : " + std::string(std::strerror(errno))); int fd = ::kqueue(); if (fd == -1) throw internal_error("Poll::create() : kqueue() failed : " + std::string(std::strerror(errno))); auto poll = new Poll(); poll->m_internal = std::make_unique(); poll->m_internal->m_fd = fd; poll->m_internal->m_max_sockets = static_cast(socket_open_max); poll->m_internal->m_max_events = 1024; poll->m_internal->m_events = std::make_unique(poll->m_internal->m_max_events); poll->m_internal->m_changes = std::make_unique(poll->m_internal->m_max_events); return std::unique_ptr(poll); } Poll::~Poll() { assert(m_internal->m_table.empty() && "Poll::~Poll() called with non-empty event table."); ::close(m_internal->m_fd); m_internal->m_fd = -1; } unsigned int Poll::do_poll(int64_t timeout_usec) { int status = poll(timeout_usec); if (status == -1) { if (errno != EINTR) throw internal_error("Poll::do_poll() error: " + std::string(std::strerror(errno))); return 0; } return process(); } int Poll::poll(int timeout_usec) { timespec timeout = { timeout_usec / 1000000, (timeout_usec % 1000000) * 1000 }; int nfds = ::kevent(m_internal->m_fd, m_internal->m_changes.get(), m_internal->m_changed_events, m_internal->m_events.get(), m_internal->m_max_events, &timeout); // Clear the changed events even on fail as we might have received a // signal or similar, and the changed events have already been // consumed. // // There's a chance a bad changed event could make kevent return -1, // but it won't as long as there is room enough in m_internal->m_events. m_internal->m_changed_events = 0; if (nfds == -1) return -1; m_internal->m_waiting_events = nfds; return nfds; } unsigned int Poll::process() { unsigned int count{}; m_processing = true; m_closed_events.clear(); for (struct kevent *itr = m_internal->m_events.get(), *last = m_internal->m_events.get() + m_internal->m_waiting_events; itr != last; ++itr) { if (system::Thread::self()->callbacks_should_interrupt_polling()) system::Thread::self()->process_callbacks(true); auto* poll_event = static_cast(itr->udata); if ((itr->flags & EV_ERROR)) { count++; if (poll_event->event == nullptr) continue; if (!(poll_event->mask & PollInternal::flag_error)) throw internal_error("Poll::process() received error event for event not in error: " + poll_event->event->print_name_fd_str()); auto event_info = poll_event->event->print_name_fd_str(); poll_event->event->event_error(); if (poll_event->mask != 0) throw internal_error("Poll::process() event_error called but event mask not cleared: " + event_info); // We assume that the event gets closed if we get an error. continue; } if (itr->filter == EVFILT_READ && (poll_event->mask & PollInternal::flag_read)) { count++; poll_event->event->event_read(); } else if (itr->filter == EVFILT_READ) { LT_LOG_DEBUG_IDENT("spurious read event, skipping", 0); } if (itr->filter == EVFILT_WRITE && (poll_event->mask & PollInternal::flag_write)) { count++; poll_event->event->event_write(); } else if (itr->filter == EVFILT_WRITE) { LT_LOG_DEBUG_IDENT("spurious write event, skipping", 0); } } m_closed_events.clear(); m_processing = false; m_internal->m_waiting_events = 0; return count; } uint32_t Poll::open_max() const { return m_internal->m_max_sockets; } void Poll::open(Event* event) { LT_LOG_EVENT("open event", 0); if (event->file_descriptor() == -1) throw internal_error("Poll::open() invalid file descriptor for event: " + event->print_name_fd_str()); if (event->m_poll_event != nullptr) throw internal_error("Poll::open() called but the event is already associated with a poll: " + event->print_name_fd_str()); if (m_internal->m_table.find(event->file_descriptor()) != m_internal->m_table.end()) throw internal_error("Poll::open() event already exists: " + event->print_name_fd_str()); event->m_poll_event = std::make_shared(event); m_internal->m_table[event->file_descriptor()] = event->m_poll_event; } void Poll::close(Event* event) { LT_LOG_EVENT("close event", 0); auto* poll_event = event->m_poll_event.get(); if (poll_event == nullptr) return; if (poll_event->event != event) throw internal_error("Poll::close() event mismatch: " + event->print_name_fd_str()); if (m_internal->event_mask(event) != 0) throw internal_error("Poll::close() called but the file descriptor is active: " + event->print_name_fd_str()); if (m_internal->m_table.erase(event->file_descriptor()) == 0) throw internal_error("Poll::close() event not found: " + event->print_name_fd_str()); m_internal->flush(); if (m_processing) m_closed_events.push_back(event->m_poll_event); poll_event->event = nullptr; event->m_poll_event = nullptr; } bool Poll::in_read(Event* event) { return m_internal->event_mask(event) & PollInternal::flag_read; } bool Poll::in_write(Event* event) { return m_internal->event_mask(event) & PollInternal::flag_write; } bool Poll::in_error(Event* event) { return m_internal->event_mask(event) & PollInternal::flag_error; } void Poll::insert_read(Event* event) { auto event_mask = m_internal->event_mask(event); if (event_mask & PollInternal::flag_read) return; LT_LOG_EVENT("insert read", 0); m_internal->set_event_mask(event, event_mask | PollInternal::flag_read); m_internal->modify(event, EV_ADD, EVFILT_READ); } void Poll::insert_write(Event* event) { auto event_mask = m_internal->event_mask(event); if (event_mask & PollInternal::flag_write) return; LT_LOG_EVENT("insert write", 0); m_internal->set_event_mask(event, event_mask | PollInternal::flag_write); m_internal->modify(event, EV_ADD, EVFILT_WRITE); } void Poll::insert_error(Event* event) { auto event_mask = m_internal->event_mask(event); if (event_mask & PollInternal::flag_error) return; LT_LOG_EVENT("insert error", 0); m_internal->set_event_mask(event, event_mask | PollInternal::flag_error); // Kqueue always monitors errors, no need to insert. } void Poll::remove_read(Event* event) { auto event_mask = m_internal->event_mask(event); if (!(event_mask & PollInternal::flag_read)) return; LT_LOG_EVENT("remove read", 0); m_internal->set_event_mask(event, event_mask & ~PollInternal::flag_read); m_internal->modify(event, EV_DELETE, EVFILT_READ); } void Poll::remove_write(Event* event) { auto event_mask = m_internal->event_mask(event); if (!(event_mask & PollInternal::flag_write)) return; LT_LOG_EVENT("remove write", 0); m_internal->set_event_mask(event, event_mask & ~PollInternal::flag_write); m_internal->modify(event, EV_DELETE, EVFILT_WRITE); } void Poll::remove_error(Event* event) { auto event_mask = m_internal->event_mask(event); if (!(event_mask & PollInternal::flag_error)) return; LT_LOG_EVENT("remove error", 0); m_internal->set_event_mask(event, event_mask & ~PollInternal::flag_error); // Kqueue always monitors errors, no need to remove. } void Poll::remove_and_close(Event* event) { LT_LOG_EVENT("remove and close", 0); remove_read(event); remove_write(event); remove_error(event); close(event); } } #endif // USE_KQUEUE libtorrent-0.16.11/src/torrent/net/poll.h0000644000000000000000000000364415175073411013677 #ifndef LIBTORRENT_TORRENT_POLL_H #define LIBTORRENT_TORRENT_POLL_H #include #include #include namespace torrent::net { class PollEvent; class PollInternal; class LIBTORRENT_EXPORT Poll { public: static std::unique_ptr create(); ~Poll(); // TODO: Make protected. unsigned int do_poll(int64_t timeout_usec); // The open max value is used when initializing libtorrent, it // should be less than or equal to sysconf(_SC_OPEN_MAX). uint32_t open_max() const; // Event::get_fd() is guaranteed to be valid and remain constant // from open(...) is called to close(...) returns. The implementor // of this class should not open nor close the file descriptor. void open(Event* event); void close(Event* event); // Functions for checking whetever the Event is listening to r/w/e? bool in_read(Event* event); bool in_write(Event* event); bool in_error(Event* event); // These functions may be called on 'event's that might, or might // not, already be in the set. void insert_read(Event* event); void insert_write(Event* event); void insert_error(Event* event); void remove_read(Event* event); void remove_write(Event* event); void remove_error(Event* event); void remove_and_close(Event* event); // Add one for HUP? Or would that be in event? private: using poll_event_list = std::vector>; Poll() = default; Poll(const Poll&) = delete; Poll& operator=(const Poll&) = delete; int poll(int timeout_usec); unsigned int process(); bool m_processing{false}; poll_event_list m_closed_events; std::unique_ptr m_internal; }; } // namespace torrent #endif libtorrent-0.16.11/src/torrent/net/resolver.cc0000644000000000000000000001356115175073411014727 #include "config.h" #include "torrent/net/resolver.h" #include #include #include "net/thread_net.h" #include "net/dns_buffer.h" #include "net/dns_cache.h" #include "torrent/exceptions.h" #include "torrent/net/socket_address.h" #include "torrent/system/thread.h" namespace torrent::net { const char* gai_enum_error(int status) { switch (status) { case EAI_AGAIN: return "EAI_AGAIN"; case EAI_BADFLAGS: return "EAI_BADFLAGS"; case EAI_FAIL: return "EAI_FAIL"; case EAI_FAMILY: return "EAI_FAMILY"; case EAI_MEMORY: return "EAI_MEMORY"; case EAI_NONAME: return "EAI_NONAME"; case EAI_OVERFLOW: return "EAI_OVERFLOW"; case EAI_SERVICE: return "EAI_SERVICE"; case EAI_SOCKTYPE: return "EAI_SOCKTYPE"; case EAI_SYSTEM: return "EAI_SYSTEM"; default: return "unknown"; } } void Resolver::init() { m_thread = torrent::system::Thread::self(); assert(m_thread != nullptr && "Resolver::m_thread is nullptr."); } void Resolver::resolve_both(void* requester, const std::string& hostname, int family, both_callback&& callback) { auto [sin, sin6] = try_lookup_numeric(hostname, family); if (sin || sin6) { m_thread->callback(requester, [family, callback = std::move(callback), sin = std::move(sin), sin6 = std::move(sin6)]() mutable { int err = (!sin && family == AF_UNSPEC) ? EAI_NONAME : 0; int err6 = (!sin6 && family == AF_UNSPEC) ? EAI_NONAME : 0; callback(std::move(sin), err, std::move(sin6), err6); }); return; } auto cb = [this, requester, hostname, family, callback = std::move(callback)]() mutable { auto fn = [this, requester, callback = std::move(callback)](sin_shared_ptr sin, int err, sin6_shared_ptr sin6, int err6) mutable { m_thread->callback(requester, std::bind(std::move(callback), std::move(sin), err, std::move(sin6), err6)); }; ThreadNet::thread_net()->dns_cache()->resolve(requester, hostname, family, std::move(fn)); }; net_thread::callback(requester, std::move(cb)); } void Resolver::resolve_preferred(void* requester, const std::string& hostname, int family, int preferred, single_callback&& callback) { if (preferred != AF_INET && preferred != AF_INET6) throw internal_error("Resolver::resolve_preferred() invalid preferred family."); auto [sin, sin6] = try_lookup_numeric(hostname, family); if (sin || sin6) { sa_shared_ptr sa = sin ? sa_copy_in(sin.get()) : sa_copy_in6(sin6.get()); m_thread->callback(requester, [callback = std::move(callback), sa = std::move(sa)]() mutable { callback(sa, 0); }); return; } auto cb = [this, requester, hostname, family, preferred, callback = std::move(callback)] () mutable { auto fn = [this, requester, preferred, callback = std::move(callback)](const auto& sin, int err, const auto& sin6, int err6) mutable { // 'result' copies the deleter from the unique_ptr returned by sa_copy_in. sa_shared_ptr result; int error{}; // TODO: Do we need to handle no-record differently? if (preferred == AF_INET) { if (err == 0 && sin != nullptr) result = sa_copy_in(sin.get()); else if (err6 == 0 && sin6 != nullptr) result = sa_copy_in6(sin6.get()); else error = err != 0 ? err : err6; } else { if (err6 == 0 && sin6 != nullptr) result = sa_copy_in6(sin6.get()); else if (err == 0 && sin != nullptr) result = sa_copy_in(sin.get()); else error = err6 != 0 ? err6 : err; } m_thread->callback(requester, std::bind(std::move(callback), std::move(result), error)); }; ThreadNet::thread_net()->dns_cache()->resolve(requester, hostname, family, std::move(fn)); }; net_thread::callback(requester, std::move(cb)); } void Resolver::resolve_specific(void* requester, const std::string& hostname, int family, single_callback&& callback) { if (family != AF_INET && family != AF_INET6) throw internal_error("Resolver::resolve_specific() invalid family."); auto [sin, sin6] = try_lookup_numeric(hostname, family); if (sin || sin6) { sa_shared_ptr sa = sin ? sa_copy_in(sin.get()) : sa_copy_in6(sin6.get()); m_thread->callback(requester, [callback = std::move(callback), sa = std::move(sa)]() mutable { callback(sa, 0); }); return; } auto cb = [this, requester, hostname, family, callback = std::move(callback)]() mutable { auto fn = [this, requester, family, callback = std::move(callback)](const auto& sin, int err, const auto& sin6, int err6) mutable { sa_shared_ptr result; int error{}; if (family == AF_INET) { if (err == 0 && sin != nullptr) result = sa_copy_in(sin.get()); else error = err; } else { if (err6 == 0 && sin6 != nullptr) result = sa_copy_in6(sin6.get()); else error = err6; } m_thread->callback(requester, std::bind(std::move(callback), std::move(result), error)); }; ThreadNet::thread_net()->dns_cache()->resolve(requester, hostname, family, std::move(fn)); }; net_thread::callback(requester, std::move(cb)); } void Resolver::cancel(void* requester) { assert(m_thread != nullptr && std::this_thread::get_id() == m_thread->thread_id()); // Make sure no new resolve requests get added. net_thread::cancel_callback_and_wait(requester); // No new resolve results will be added after this. ThreadNet::thread_net()->dns_buffer()->cancel_safe(requester); // Remove any new resolve results that got added before between the above two calls. net_thread::cancel_callback_and_wait(requester); // Self thread doesn't need to wait. m_thread->cancel_callback(requester); } } // namespace torrent::net libtorrent-0.16.11/src/torrent/net/resolver.h0000644000000000000000000000227415175073411014570 #ifndef TORRENT_NET_RESOLVER_H #define TORRENT_NET_RESOLVER_H #include #include #include #include namespace torrent::net { class LIBTORRENT_EXPORT Resolver { public: using both_callback = std::function; using single_callback = std::function; Resolver() = default; ~Resolver() = default; // May be called from any thread. void resolve_both(void* requester, const std::string& hostname, int family, both_callback&& callback); void resolve_preferred(void* requester, const std::string& hostname, int family, int preferred, single_callback&& callback); void resolve_specific(void* requester, const std::string& hostname, int family, single_callback&& callback); // Must be called from the owning thread. void cancel(void* requester); protected: friend class system::Thread; void init(); private: Resolver(const Resolver&) = delete; Resolver& operator=(const Resolver&) = delete; system::Thread* m_thread{nullptr}; }; } // namespace torrent::net #endif libtorrent-0.16.11/src/torrent/net/connection_state.h0000644000000000000000000000302015175073411016254 #ifndef LIBTORRENT_TORRENT_NET_CONNECTION_STATE_H #define LIBTORRENT_TORRENT_NET_CONNECTION_STATE_H #include namespace torrent::net { class LIBTORRENT_EXPORT ConnectionState { public: int current_family() const { return m_current_family; } int last_failure_family() const { return m_last_failure_family; } void set_current_family(int family); void set_last_failure_family(int family); int success_inet() const { return m_success_inet; } int success_inet6() const { return m_success_inet6; } int failures_inet() const { return m_failures_inet; } int failures_inet6() const { return m_failures_inet6; } private: int m_current_family{AF_UNSPEC}; int m_last_failure_family{AF_UNSPEC}; int m_success_inet{0}; int m_success_inet6{0}; int m_failures_inet{0}; int m_failures_inet6{0}; // c_sa_shared_ptr m_bind_address; // has connected to inet/inet6 // int m_attempts{0}; // int m_successes{0}; // int m_failures{0}; // int m_last_family{AF_UNSPEC}; // bool m_failed{false}; }; int select_next_address_family(ConnectionState& state); } // namespace torrent::net #endif libtorrent-0.16.11/src/torrent/net/socket_address.cc0000644000000000000000000005114315175073411016061 #include "config.h" #include #include #include #include #include #include "torrent/exceptions.h" #include "torrent/net/socket_address.h" namespace torrent::net { void sa_free(const sockaddr* sa) { if (sa == nullptr) return; switch (sa->sa_family) { case AF_UNSPEC: delete reinterpret_cast(sa); break; case AF_INET: delete reinterpret_cast(sa); break; case AF_INET6: delete reinterpret_cast(sa); break; case AF_UNIX: delete reinterpret_cast(sa); break; default: throw internal_error("torrent::sa_free() invalid family type"); } } } // torrent::net namespace torrent { static constexpr uint32_t sin6_addr32_index(const sockaddr_in6* sa, unsigned int index) { return (sa->sin6_addr.s6_addr[index * 4 + 0] << 24) + (sa->sin6_addr.s6_addr[index * 4 + 1] << 16) + (sa->sin6_addr.s6_addr[index * 4 + 2] << 8) + (sa->sin6_addr.s6_addr[index * 4 + 3] << 0); } static in6_addr sin6_make_addr32(uint32_t addr0, uint32_t addr1, uint32_t addr2, uint32_t addr3) { uint32_t addr32[4]; addr32[0] = htonl(addr0); addr32[1] = htonl(addr1); addr32[2] = htonl(addr2); addr32[3] = htonl(addr3); return *reinterpret_cast(addr32); } bool sa_is_unspec(const sockaddr* sa) { return sa != NULL && sa->sa_family == AF_UNSPEC; } bool sa_is_inet(const sockaddr* sa) { return sa != NULL && sa->sa_family == AF_INET; } bool sa_is_inet6(const sockaddr* sa) { return sa != NULL && sa->sa_family == AF_INET6; } bool sa_is_inet_inet6(const sockaddr* sa) { return sa != NULL && (sa->sa_family == AF_INET || sa->sa_family == AF_INET6); } bool sa_is_any(const sockaddr* sa) { switch (sa->sa_family) { case AF_INET: return sin_is_any(reinterpret_cast(sa)); case AF_INET6: if (sa_is_v4mapped(sa)) return sin6_addr32_index(reinterpret_cast(sa), 3) == htonl(INADDR_ANY); return sin6_is_any(reinterpret_cast(sa)); default: return true; } } bool sin_is_any(const sockaddr_in* sa) { return sa->sin_addr.s_addr == htonl(INADDR_ANY); } bool sin6_is_any(const sockaddr_in6* sa) { return std::memcmp(&sa->sin6_addr, &in6addr_any, sizeof(in6_addr)) == 0; } bool sa_is_broadcast(const sockaddr* sa) { switch (sa->sa_family) { case AF_INET: return sin_is_broadcast(reinterpret_cast(sa)); case AF_INET6: if (sa_is_v4mapped(sa)) return sin6_addr32_index(reinterpret_cast(sa), 3) == htonl(INADDR_BROADCAST); return false; default: return false; } } bool sin_is_broadcast(const sockaddr_in* sa) { return sa->sin_addr.s_addr == htonl(INADDR_BROADCAST); } bool sa_is_v4mapped(const sockaddr* sa) { return sa != nullptr && sa->sa_family == AF_INET6 && sin6_is_v4mapped(reinterpret_cast(sa)); } bool sin6_is_v4mapped(const sockaddr_in6* sa) { return sa != nullptr && IN6_IS_ADDR_V4MAPPED(&sa->sin6_addr); } bool sa_is_port_any(const sockaddr* sa) { return sa_port(sa) == 0; } size_t sa_length(const sockaddr* sa) { switch(sa->sa_family) { case AF_UNSPEC: return sizeof(sockaddr); case AF_INET: return sizeof(sockaddr_in); case AF_INET6: return sizeof(sockaddr_in6); case AF_UNIX: return sizeof(sockaddr_un); default: throw internal_error("torrent::sa_length() sockaddr is not a valid family"); } } sa_unique_ptr sa_make_unspec() { sa_unique_ptr sa(new sockaddr{}); sa->sa_family = AF_UNSPEC; return sa; } sa_unique_ptr sa_make_inet() { return sa_unique_ptr(reinterpret_cast(sin_make().release())); } sa_unique_ptr sa_make_inet_any() { return sa_unique_ptr(reinterpret_cast(sin_make_any().release())); } sa_unique_ptr sa_make_inet_h(uint32_t addr, uint16_t port) { return sa_unique_ptr(reinterpret_cast(sin_make_h(addr, port).release())); } sa_unique_ptr sa_make_inet_n(uint32_t addr, uint16_t port) { return sa_unique_ptr(reinterpret_cast(sin_make_n(addr, port).release())); } sa_unique_ptr sa_make_inet6() { return sa_unique_ptr(reinterpret_cast(sin6_make().release())); } sa_unique_ptr sa_make_inet6_any() { return sa_unique_ptr(reinterpret_cast(sin6_make_any().release())); } sa_unique_ptr sa_make_unix(const std::string& pathname) { if (!pathname.empty()) throw internal_error("torrent::sa_make_unix() function not implemented"); sun_unique_ptr sunp(new sockaddr_un{}); sunp->sun_family = AF_UNIX; // TODO: verify length, copy pathname return sa_unique_ptr(reinterpret_cast(sunp.release())); } sa_unique_ptr sa_convert(const sockaddr* sa) { if (sa == NULL) return sa_make_unspec(); switch(sa->sa_family) { case AF_INET: return sa_copy_in(reinterpret_cast(sa)); case AF_INET6: if (sin6_is_v4mapped(reinterpret_cast(sa))) return sa_from_v4mapped_in6(reinterpret_cast(sa)); return sa_copy_in6(reinterpret_cast(sa)); case AF_UNSPEC: return sa_make_unspec(); default: throw internal_error("torrent::sa_convert() sockaddr is not a valid family"); } } sa_unique_ptr sa_copy(const sockaddr* sa) { if (sa == nullptr) throw internal_error("torrent::sa_copy() sockaddr is a nullptr"); switch(sa->sa_family) { case AF_INET: return sa_copy_in(reinterpret_cast(sa)); case AF_INET6: return sa_copy_in6(reinterpret_cast(sa)); case AF_UNSPEC: return sa_make_unspec(); default: throw internal_error("torrent::sa_copy() sockaddr is not a valid family"); } } sa_unique_ptr sa_copy_in(const sockaddr_in* sa) { sa_unique_ptr result(reinterpret_cast(new sockaddr_in)); std::memcpy(result.get(), sa, sizeof(sockaddr_in)); return result; } sa_unique_ptr sa_copy_in6(const sockaddr_in6* sa) { sa_unique_ptr result(reinterpret_cast(new sockaddr_in6)); std::memcpy(result.get(), sa, sizeof(sockaddr_in6)); return result; } sa_unique_ptr sa_copy_addr(const sockaddr* sa, uint16_t port) { if (sa == nullptr) throw internal_error("torrent::sa_copy_addr() sockaddr is a nullptr"); switch(sa->sa_family) { case AF_INET: return sa_copy_addr_in(reinterpret_cast(sa), port); case AF_INET6: return sa_copy_addr_in6(reinterpret_cast(sa), port); case AF_UNSPEC: return sa_make_unspec(); default: throw internal_error("torrent::sa_copy_addr() sockaddr is not a valid family"); } } sa_unique_ptr sa_copy_addr_in(const sockaddr_in* sa, uint16_t port) { sa_unique_ptr result(reinterpret_cast(new sockaddr_in{})); reinterpret_cast(result.get())->sin_family = AF_INET; reinterpret_cast(result.get())->sin_addr = sa->sin_addr; reinterpret_cast(result.get())->sin_port = htons(port); return result; } sa_unique_ptr sa_copy_addr_in6(const sockaddr_in6* sa, uint16_t port) { sa_unique_ptr result(reinterpret_cast(new sockaddr_in6{})); reinterpret_cast(result.get())->sin6_family = AF_INET6; std::memcpy(&reinterpret_cast(result.get())->sin6_addr, &sa->sin6_addr, sizeof(in6_addr)); reinterpret_cast(result.get())->sin6_port = htons(port); return result; } sa_unique_ptr sa_copy_unmapped(const sockaddr* sa) { if (sa == nullptr) throw internal_error("torrent::sa_copy_unmapped() sockaddr is a nullptr"); switch(sa->sa_family) { case AF_INET: return sa_copy_in(reinterpret_cast(sa)); case AF_INET6: if (sin6_is_v4mapped(reinterpret_cast(sa))) return sa_from_v4mapped_in6(reinterpret_cast(sa)); return sa_copy_in6(reinterpret_cast(sa)); case AF_UNSPEC: return sa_make_unspec(); default: throw internal_error("torrent::sa_copy_unmapped() sockaddr is not a valid family"); } } sin_unique_ptr sin_copy(const sockaddr_in* sa) { sin_unique_ptr result(new sockaddr_in); std::memcpy(result.get(), sa, sizeof(sockaddr_in)); return result; } sin6_unique_ptr sin6_copy(const sockaddr_in6* sa) { sin6_unique_ptr result(new sockaddr_in6); std::memcpy(result.get(), sa, sizeof(sockaddr_in6)); return result; } sin_unique_ptr sin_make() { sin_unique_ptr sa(new sockaddr_in{}); sa->sin_family = AF_INET; return sa; } sin_unique_ptr sin_make_any() { sin_unique_ptr sa(new sockaddr_in{}); sa->sin_family = AF_INET; sa->sin_addr.s_addr = htonl(INADDR_ANY); return sa; } sin_unique_ptr sin_make_h(uint32_t addr, uint16_t port) { sin_unique_ptr sa(new sockaddr_in{}); sa->sin_family = AF_INET; sa->sin_addr.s_addr = htonl(addr); sa->sin_port = htons(port); return sa; } sin_unique_ptr sin_make_n(uint32_t addr, uint16_t port) { sin_unique_ptr sa(new sockaddr_in{}); sa->sin_family = AF_INET; sa->sin_addr.s_addr = addr; sa->sin_port = port; return sa; } sin6_unique_ptr sin6_make() { sin6_unique_ptr sa(new sockaddr_in6{}); sa->sin6_family = AF_INET6; return sa; } sin6_unique_ptr sin6_make_any() { sin6_unique_ptr sa(new sockaddr_in6{}); sa->sin6_family = AF_INET6; sa->sin6_addr = in6addr_any; return sa; } sa_unique_ptr sa_from_v4mapped(const sockaddr* sa) { if (!sa_is_inet6(sa)) throw internal_error("torrent::sa_from_v4mapped() sockaddr is not inet6"); return sa_from_in(sin_from_v4mapped_in6(reinterpret_cast(sa))); } sa_unique_ptr sa_to_v4mapped(const sockaddr* sa) { if (!sa_is_inet(sa)) throw internal_error("torrent::sa_to_v4mapped() sockaddr is not inet"); return sa_from_in6(sin6_to_v4mapped_in(reinterpret_cast(sa))); } sin_unique_ptr sin_from_v4mapped_in6(const sockaddr_in6* sin6) { if (!sin6_is_v4mapped(sin6)) throw internal_error("torrent::sin6_is_v4mapped() sockaddr_in6 is not v4mapped"); sin_unique_ptr result = sin_make(); result->sin_addr.s_addr = reinterpret_cast(htonl(sin6_addr32_index(sin6, 3))); result->sin_port = sin6->sin6_port; return result; } sin6_unique_ptr sin6_to_v4mapped_in(const sockaddr_in* sin) { sin6_unique_ptr result = sin6_make(); result->sin6_addr = sin6_make_addr32(0, 0, 0xffff, ntohl(sin->sin_addr.s_addr)); result->sin6_port = sin->sin_port; return result; } sin_unique_ptr sin_from_sa(sa_unique_ptr sap) { if (!sap_is_inet(sap)) throw internal_error("torrent::sin_from_sa() sockaddr is nullptr or not inet"); return sin_unique_ptr(reinterpret_cast(sap.release())); } sin6_unique_ptr sin6_from_sa(sa_unique_ptr sap) { if (!sap_is_inet6(sap)) throw internal_error("torrent::sin6_from_sa() sockaddr is nullptr or not inet6"); return sin6_unique_ptr(reinterpret_cast(sap.release())); } c_sin_unique_ptr sin_from_c_sa(c_sa_unique_ptr sap) { if (!sap_is_inet(sap)) throw internal_error("torrent::sin_from_c_sa() sockaddr is nullptr or not inet"); return c_sin_unique_ptr(reinterpret_cast(sap.release())); } c_sin6_unique_ptr sin6_from_c_sa(c_sa_unique_ptr sap) { if (!sap_is_inet6(sap)) throw internal_error("torrent::sin6_from_c_sa() sockaddr is nullptr or not inet6"); return c_sin6_unique_ptr(reinterpret_cast(sap.release())); } void sa_clear_inet6(sockaddr_in6* sa) { *sa = sockaddr_in6{}; sa->sin6_family = AF_INET6; } uint16_t sa_port(const sockaddr* sa) { if (sa == NULL) return 0; switch(sa->sa_family) { case AF_INET: return ntohs(reinterpret_cast(sa)->sin_port); case AF_INET6: return ntohs(reinterpret_cast(sa)->sin6_port); default: return 0; } } void sa_set_port(sockaddr* sa, uint16_t port) { switch(sa->sa_family) { case AF_INET: reinterpret_cast(sa)->sin_port = htons(port); return; case AF_INET6: reinterpret_cast(sa)->sin6_port = htons(port); return; default: throw internal_error("torrent::sa_set_port() invalid family type"); } } bool sa_equal(const sockaddr* lhs, const sockaddr* rhs) { switch(rhs->sa_family) { case AF_INET: case AF_INET6: case AF_UNSPEC: break; default: throw internal_error("torrent::sa_equal() rhs sockaddr is not a valid family"); } switch(lhs->sa_family) { case AF_INET: return lhs->sa_family == rhs->sa_family && sin_equal(reinterpret_cast(lhs), reinterpret_cast(rhs)); case AF_INET6: return lhs->sa_family == rhs->sa_family && sin6_equal(reinterpret_cast(lhs), reinterpret_cast(rhs)); case AF_UNSPEC: return lhs->sa_family == rhs->sa_family; default: throw internal_error("torrent::sa_equal() lhs sockaddr is not a valid family"); } } bool sin_equal(const sockaddr_in* lhs, const sockaddr_in* rhs) { return lhs->sin_port == rhs->sin_port && lhs->sin_addr.s_addr == rhs->sin_addr.s_addr; } bool sin6_equal(const sockaddr_in6* lhs, const sockaddr_in6* rhs) { return lhs->sin6_port == rhs->sin6_port && std::equal(lhs->sin6_addr.s6_addr, lhs->sin6_addr.s6_addr + 16, rhs->sin6_addr.s6_addr); } bool sa_equal_addr(const sockaddr* lhs, const sockaddr* rhs) { switch(rhs->sa_family) { case AF_INET: case AF_INET6: case AF_UNSPEC: break; default: throw internal_error("torrent::sa_equal_addr() rhs sockaddr is not a valid family"); } switch(lhs->sa_family) { case AF_INET: return lhs->sa_family == rhs->sa_family && sin_equal_addr(reinterpret_cast(lhs), reinterpret_cast(rhs)); case AF_INET6: return lhs->sa_family == rhs->sa_family && sin6_equal_addr(reinterpret_cast(lhs), reinterpret_cast(rhs)); case AF_UNSPEC: return lhs->sa_family == rhs->sa_family; default: throw internal_error("torrent::sa_equal_addr() lhs sockaddr is not a valid family"); } } bool sin_equal_addr(const sockaddr_in* lhs, const sockaddr_in* rhs) { return lhs->sin_addr.s_addr == rhs->sin_addr.s_addr; } bool sin6_equal_addr(const sockaddr_in6* lhs, const sockaddr_in6* rhs) { return std::equal(lhs->sin6_addr.s6_addr, lhs->sin6_addr.s6_addr + 16, rhs->sin6_addr.s6_addr); } bool sa_less(const sockaddr* lhs, const sockaddr* rhs) { if (lhs->sa_family != AF_INET && lhs->sa_family != AF_INET6) throw internal_error("torrent::sa_less() lhs sockaddr is not inet or inet6"); if (rhs->sa_family != AF_INET && rhs->sa_family != AF_INET6) throw internal_error("torrent::sa_less() rhs sockaddr is not inet or inet6"); if (lhs->sa_family != rhs->sa_family) return lhs->sa_family == AF_INET; if (lhs->sa_family == AF_INET) { const sockaddr_in* lsin = reinterpret_cast(lhs); const sockaddr_in* rsin = reinterpret_cast(rhs); if (lsin->sin_addr.s_addr != rsin->sin_addr.s_addr) return ntohl(lsin->sin_addr.s_addr) < ntohl(rsin->sin_addr.s_addr); return ntohs(lsin->sin_port) < ntohs(rsin->sin_port); } else { const sockaddr_in6* lsin6 = reinterpret_cast(lhs); const sockaddr_in6* rsin6 = reinterpret_cast(rhs); auto result = std::memcmp(&lsin6->sin6_addr, &rsin6->sin6_addr, sizeof(in6_addr)); if (result != 0) return result < 0; return ntohs(lsin6->sin6_port) < ntohs(rsin6->sin6_port); } } bool sa_less_addr(const sockaddr* lhs, const sockaddr* rhs) { if (lhs->sa_family != AF_INET && lhs->sa_family != AF_INET6) throw internal_error("torrent::sa_less_addr() lhs sockaddr is not inet or inet6"); if (rhs->sa_family != AF_INET && rhs->sa_family != AF_INET6) throw internal_error("torrent::sa_less_addr() rhs sockaddr is not inet or inet6"); if (lhs->sa_family != rhs->sa_family) return lhs->sa_family == AF_INET; if (lhs->sa_family == AF_INET) { const sockaddr_in* lsin = reinterpret_cast(lhs); const sockaddr_in* rsin = reinterpret_cast(rhs); return ntohl(lsin->sin_addr.s_addr) < ntohl(rsin->sin_addr.s_addr); } else { const sockaddr_in6* lsin6 = reinterpret_cast(lhs); const sockaddr_in6* rsin6 = reinterpret_cast(rhs); return std::memcmp(&lsin6->sin6_addr, &rsin6->sin6_addr, sizeof(in6_addr)) < 0; } } std::string sa_addr_str(const sockaddr* sa) { if (sa == nullptr) return ""; switch (sa->sa_family) { case AF_INET: return sin_addr_str(reinterpret_cast(sa)); case AF_INET6: return sin6_addr_str(reinterpret_cast(sa)); case AF_UNSPEC: return ""; default: throw internal_error("torrent::sa_addr_str() sockaddr is not a valid family"); } } std::string sin_addr_str(const sockaddr_in* sa) { char buffer[INET_ADDRSTRLEN]; if (inet_ntop(AF_INET, &sa->sin_addr, buffer, INET_ADDRSTRLEN) == NULL) throw internal_error("torrent::sin_addr_str() inet_ntop failed"); return buffer; } std::string sin6_addr_str(const sockaddr_in6* sa) { char buffer[INET6_ADDRSTRLEN]; if (inet_ntop(AF_INET6, &sa->sin6_addr, buffer, INET6_ADDRSTRLEN) == NULL) throw internal_error("torrent::sin6_addr_str() inet_ntop failed"); return buffer; } std::string sa_pretty_str(const sockaddr* sa) { if (sa == nullptr) return "null"; switch (sa->sa_family) { case AF_INET: return sin_pretty_str(reinterpret_cast(sa)); case AF_INET6: return sin6_pretty_str(reinterpret_cast(sa)); case AF_UNSPEC: return "unspec"; default: return "invalid"; } } std::string sin_pretty_str(const sockaddr_in* sa) { auto result = sin_addr_str(sa); if (sa->sin_port != 0) result += ':' + std::to_string(ntohs(sa->sin_port)); return result; } std::string sin_pretty_or_empty(const sockaddr_in* sa) { if (sa == nullptr) return ""; auto result = sin_addr_str(sa); if (sa->sin_port != 0) result += ':' + std::to_string(ntohs(sa->sin_port)); return result; } std::string sin6_pretty_str(const sockaddr_in6* sa) { auto result = "[" + sin6_addr_str(sa) + "]"; if (sa->sin6_port != 0) result += ':' + std::to_string(ntohs(sa->sin6_port)); return result; } std::string sin6_pretty_or_empty(const sockaddr_in6* sa) { if (sa == nullptr) return ""; auto result = "[" + sin6_addr_str(sa) + "]"; if (sa->sin6_port != 0) result += ':' + std::to_string(ntohs(sa->sin6_port)); return result; } c_sa_shared_ptr sa_lookup_address(const std::string& address_str, int family) { if (address_str.empty()) return sa_make_unspec(); addrinfo hints = {}; hints.ai_family = family; hints.ai_socktype = SOCK_STREAM; addrinfo* res; int err = ::getaddrinfo(address_str.c_str(), nullptr, &hints, &res); if (err != 0) throw input_error("Could not get address info: " + address_str + ": " + std::string(gai_strerror(err))); try { auto sa = sa_copy(res->ai_addr); ::freeaddrinfo(res); return sa; } catch (input_error& e) { ::freeaddrinfo(res); throw e; } } // // Other types: // sin46_shared_pair try_lookup_numeric(const std::string& hostname, int family) { addrinfo hints{}; addrinfo* result{}; hints.ai_family = family; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_NUMERICHOST; auto ret = ::getaddrinfo(hostname.c_str(), nullptr, &hints, &result); if (ret == EAI_NONAME || ret == EAI_ADDRFAMILY) return {nullptr, nullptr}; if (ret != 0) throw internal_error("getaddrinfo failed: " + std::string(gai_strerror(ret))); if (result->ai_family == AF_INET) { sin_shared_ptr sin_addr = sin_copy(reinterpret_cast(result->ai_addr)); ::freeaddrinfo(result); return {sin_addr, nullptr}; } if (result->ai_family == AF_INET6) { sin6_shared_ptr sin6_addr = sin6_copy(reinterpret_cast(result->ai_addr)); ::freeaddrinfo(result); return {nullptr, sin6_addr}; } ::freeaddrinfo(result); throw internal_error("getaddrinfo returned unsupported family"); } sa_inet_union sa_inet_union_from_sa(const sockaddr* sa) { sa_inet_union su{}; switch (sa->sa_family) { case AF_INET: su.inet = *reinterpret_cast(sa); return su; case AF_INET6: su.inet6 = *reinterpret_cast(sa); return su; default: throw internal_error("torrent::sa_inet_union_from_sa() sockaddr is not inet or inet6"); } } const char* family_str(int family) { switch (family) { case AF_UNSPEC: return "AF_UNSPEC"; case AF_INET: return "AF_INET"; case AF_INET6: return "AF_INET6"; case AF_UNIX: return "AF_UNIX"; default: return "AF_UNKNOWN"; } } } // namespace torrent libtorrent-0.16.11/src/torrent/connection_manager.h0000644000000000000000000000473715175073411016000 #ifndef LIBTORRENT_CONNECTION_MANAGER_H #define LIBTORRENT_CONNECTION_MANAGER_H #include #include #include #include #include #include #include #include namespace torrent { // Standard pair of up/down throttles. // First element is upload throttle, second element is download throttle. using ThrottlePair = std::pair; class LIBTORRENT_EXPORT ConnectionManager { public: using size_type = uint32_t; using port_type = uint16_t; // TODO: Move. enum { handshake_incoming = 1, handshake_outgoing = 2, handshake_outgoing_encrypted = 3, handshake_outgoing_proxy = 4, handshake_success = 5, handshake_dropped = 6, handshake_failed = 7, handshake_retry_plaintext = 8, handshake_retry_encrypted = 9 }; using slot_filter_type = std::function; using slot_throttle_type = std::function; ConnectionManager(); ~ConnectionManager(); ConnectionManager(const ConnectionManager&) = delete; ConnectionManager& operator=(const ConnectionManager&) = delete; // Check that we have not surpassed the max number of open sockets // and that we're allowed to connect to the socket address. // // Consider only checking max number of open sockets. bool can_connect() const; // TODO: Move this to SocketManager? // Call this to keep the socket count up to date. void inc_socket_count() { m_size++; } void dec_socket_count() { m_size--; } size_type size() const { return m_size; } size_type max_size() const { return m_maxSize; } void set_max_size(size_type s) { m_maxSize = s; } uint32_t filter(const sockaddr* sa); void set_filter(const slot_filter_type& s) { m_slot_filter = s; } // The slot returns a ThrottlePair to use for the given address, or // NULLs to use the default throttle. slot_throttle_type& address_throttle() { return m_slot_address_throttle; } private: size_type m_size{0}; size_type m_maxSize{0}; slot_filter_type m_slot_filter; slot_throttle_type m_slot_address_throttle; }; } // namespace torrent #endif libtorrent-0.16.11/src/torrent/hash_string.h0000644000000000000000000000731015175073411014446 // A fixed with char array used to store 20 byte with hashes. This // should really be replaced with std::array<20>. #ifndef LIBTORRENT_HASH_STRING_H #define LIBTORRENT_HASH_STRING_H #include #include #include #include namespace torrent { class LIBTORRENT_EXPORT HashString { public: using value_type = char; using reference = value_type&; using const_reference = const value_type&; using iterator = value_type*; using const_iterator = const value_type*; using size_type = std::size_t; using difference_type = std::ptrdiff_t; using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; static constexpr size_type size_data = 20; static size_type size() { return size_data; } iterator begin() { return m_data; } const_iterator begin() const { return m_data; } iterator end() { return m_data + size(); } const_iterator end() const { return m_data + size(); } reverse_iterator rbegin() { return reverse_iterator(end()); } const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } reverse_iterator rend() { return reverse_iterator(begin()); } const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } reference operator [] (size_type n) { return *(m_data + n); } const_reference operator [] (size_type n) const { return *(m_data + n); } value_type* data() { return m_data; } const value_type* data() const { return m_data; } const value_type* c_str() const { return m_data; } std::string str() const { return std::string(m_data, size_data); } void clear(int v = 0) { std::memset(data(), v, size()); } void assign(const value_type* src) { std::memcpy(data(), src, size()); } bool equal_to(const char* hash) const { return std::memcmp(m_data, hash, size()) == 0; } bool not_equal_to(const char* hash) const { return std::memcmp(m_data, hash, size()) != 0; } static HashString new_zero(); // It is the users responsibility to ensure src.length() >= // size_data. static const HashString* cast_from(const char* src) { return reinterpret_cast(src); } static const HashString* cast_from(const std::string& src) { return reinterpret_cast(src.c_str()); } static HashString* cast_from(char* src) { return reinterpret_cast(src); } private: char m_data[size_data]; }; inline HashString HashString::new_zero() { HashString hash; hash.clear(); return hash; } inline bool operator == (const HashString& one, const HashString& two) { return std::memcmp(one.begin(), two.begin(), HashString::size_data) == 0; } inline bool operator != (const HashString& one, const HashString& two) { return std::memcmp(one.begin(), two.begin(), HashString::size_data) != 0; } inline bool operator < (const HashString& one, const HashString& two) { return std::memcmp(one.begin(), two.begin(), HashString::size_data) < 0; } inline bool operator <= (const HashString& one, const HashString& two) { return std::memcmp(one.begin(), two.begin(), HashString::size_data) <= 0; } } // namespace torrent #endif libtorrent-0.16.11/src/torrent/bitfield.h0000644000000000000000000000651715175073411013727 #ifndef LIBTORRENT_BITFIELD_H #define LIBTORRENT_BITFIELD_H #include #include namespace torrent { class LIBTORRENT_EXPORT Bitfield { public: using size_type = uint32_t; using value_type = uint8_t; using const_value_type = const uint8_t; using iterator = value_type*; using const_iterator = const value_type*; Bitfield() = default; ~Bitfield() { clear(); } Bitfield(const Bitfield&) = delete; Bitfield& operator=(const Bitfield&) = delete; bool empty() const { return m_data == nullptr; } bool is_all_set() const { return m_set == m_size; } bool is_all_unset() const { return m_set == 0; } bool is_tail_cleared() const { return m_size % 8 == 0 || !((*(end() - 1) & mask_from(m_size % 8))); } size_type size_bits() const { return m_size; } size_type size_bytes() const { return (m_size + 7) / 8; } size_type size_set() const { return m_set; } size_type size_unset() const { return m_size - m_set; } void set_size_bits(size_type s); void set_size_set(size_type s); // Call update if you've changed the data directly and want to // update the counters and unset the last unused bits. // // Resize clears the data? void update(); void allocate(); void unallocate(); void clear() { unallocate(); m_size = 0; m_set = 0; } void clear_tail() { if (m_size % 8) *(end() - 1) &= mask_before(m_size % 8); } void copy(const Bitfield& bf); void swap(Bitfield& bf) noexcept; void set_all(); void set_range(size_type first, size_type last); void unset_all(); void unset_range(size_type first, size_type last); bool get(size_type idx) const { return m_data[idx / 8] & mask_at(idx % 8); } void set(size_type idx) { m_set += !get(idx); m_data[idx / 8] |= mask_at(idx % 8); } void unset(size_type idx) { m_set -= get(idx); m_data[idx / 8] &= ~mask_at(idx % 8); } iterator begin() { return m_data.get(); } const_iterator begin() const { return m_data.get(); } iterator end() { return m_data.get() + size_bytes(); } const_iterator end() const { return m_data.get() + size_bytes(); } size_type position(const_iterator itr) const { return (itr - m_data.get()) * 8; } void from_c_str(const char* str) { std::memcpy(m_data.get(), str, size_bytes()); update(); } // Remember to use modulo. static value_type mask_at(size_type idx) { return 1 << (7 - idx); } static value_type mask_before(size_type idx) { return value_type{0xff} << (8 - idx); } static value_type mask_from(size_type idx) { return value_type{0xff} >> idx; } private: size_type m_size{}; size_type m_set{}; std::unique_ptr m_data; }; } // namespace torrent #endif libtorrent-0.16.11/src/torrent/throttle.cc0000644000000000000000000000501415175073411014137 #include "config.h" #include "throttle.h" #include #include "exceptions.h" #include "net/throttle_internal.h" #include "net/throttle_list.h" namespace torrent { // Plans: // // Make ThrottleList do a callback when it needs more? This would // allow us to remove us from the task scheduler when we're full. Also // this would let us be abit more flexible with the interval. Throttle* Throttle::create_throttle() { auto throttle = new ThrottleInternal(ThrottleInternal::flag_root); throttle->m_maxRate = 0; throttle->m_throttleList = new ThrottleList(); return throttle; } void Throttle::destroy_throttle(Throttle* throttle) { delete throttle->m_ptr()->m_throttleList; delete throttle->m_ptr(); } Throttle* Throttle::create_slave() { return m_ptr()->create_slave(); } bool Throttle::is_throttled() const { return m_maxRate != 0 && m_maxRate < UINT_MAX; } void Throttle::set_max_rate(uint64_t v) { if (v == m_maxRate) return; if (v > (UINT_MAX - 1)) throw input_error("Throttle rate must be between 0 and 4294967295."); uint64_t oldRate = m_maxRate; m_maxRate = v; m_throttleList->set_min_chunk_size(calculate_min_chunk_size()); m_throttleList->set_max_chunk_size(calculate_max_chunk_size()); if (!m_ptr()->is_root()) return; if (oldRate == 0) m_ptr()->enable(); else if (m_maxRate == 0) m_ptr()->disable(); } const Rate* Throttle::rate() const { return m_throttleList->rate_slow(); } uint32_t Throttle::calculate_min_chunk_size() const { // Just for each modification, make this into a function, rather // than if-else chain. if (m_maxRate <= (8 << 10)) return (1 << 9); else if (m_maxRate <= (32 << 10)) return (2 << 9); else if (m_maxRate <= (64 << 10)) return (3 << 9); else if (m_maxRate <= (128 << 10)) return (4 << 9); else if (m_maxRate <= (512 << 10)) return (8 << 9); else if (m_maxRate <= (2048 << 10)) return (16 << 9); else return (32 << 9); } uint32_t Throttle::calculate_max_chunk_size() const { // Make this return a lower value for very low throttle settings. return calculate_min_chunk_size() * 4; } uint32_t Throttle::calculate_interval() const { uint32_t rate = m_throttleList->rate_slow()->rate(); if (rate < 1024) return 10 * 100000; // At least two max chunks per tick. uint32_t interval = (5 * m_throttleList->max_chunk_size()) / rate; if (interval == 0) return 1 * 100000; else if (interval > 10) return 10 * 100000; else return interval * 100000; } } // namespace torrent libtorrent-0.16.11/src/torrent/rate.cc0000644000000000000000000000160515175073411013227 #include "config.h" #include "rate.h" #include "exceptions.h" namespace torrent { inline void Rate::discard_old() const { while (!m_container.empty() && m_container.back().first < this_thread::cached_seconds().count() - m_span) { m_current -= m_container.back().second; m_container.pop_back(); } } Rate::rate_type Rate::rate() const { discard_old(); return m_current / m_span; } void Rate::insert(rate_type bytes) { discard_old(); if (m_current > (rate_type{1} << 40) || bytes > (rate_type{1} << 28)) throw internal_error("Rate::insert(bytes) received out-of-bounds values.."); if (m_container.empty() || m_container.front().first != this_thread::cached_seconds().count()) m_container.emplace_front(this_thread::cached_seconds().count(), bytes); else m_container.front().second += bytes; m_total += bytes; m_current += bytes; } } // namespace torrent libtorrent-0.16.11/src/torrent/runtime/0000755000000000000000000000000015175073434013533 5libtorrent-0.16.11/src/torrent/runtime/socket_manager.cc0000644000000000000000000003332015175073411016740 #include "config.h" #include "torrent/runtime/socket_manager.h" #include #include "torrent/event.h" #include "torrent/exceptions.h" #include "torrent/net/socket_address.h" #include "torrent/utils/log.h" #include "torrent/system/thread.h" #define LT_LOG(log_fmt, ...) \ lt_log_print(LOG_NET_SOCKET, "socket_manager: " log_fmt, __VA_ARGS__); namespace torrent::runtime { SocketManager::SocketManager() { // TODO: Set load factor a bit higher than default to account for peak usage during startup / etc. } SocketManager::~SocketManager() { assert(m_socket_map.empty() && "SocketManager::~SocketManager(): socket map not empty on destruction."); } void SocketManager::open_event_or_throw(Event* event, std::function func) { auto guard = lock_guard(); if (event->is_open()) throw internal_error("SocketManager::open_event_or_throw(): event is already open"); func(); if (!event->is_open()) { LT_LOG("open_event_or_throw() : %s:%s : failed to open socket", this_thread::thread()->name(), event->type_name()); return; } auto fd = event->file_descriptor(); auto itr = m_socket_map.find(fd); if (itr != m_socket_map.end()) { // We don't allow conflicts for this function. LT_LOG("open_event_or_throw() : %s:%s:%i : tried to use an existing file descriptor : %s:%s", this_thread::thread()->name(), event->type_name(), fd, itr->second.thread->name(), itr->second.event->type_name()); throw internal_error("SocketManager::open_event_or_throw(): tried to use an existing file descriptor: " + std::string(itr->second.thread->name()) + ":" + std::string(itr->second.event->type_name()) + ":" + std::to_string(fd)); } LT_LOG("open_event_or_throw() : %s:%s:%i : opened socket", this_thread::thread()->name(), event->type_name(), fd); m_socket_map.emplace(fd, SocketInfo{fd, event, this_thread::thread()}); } bool SocketManager::open_event_or_cleanup(Event* event, std::function func, std::function cleanup) { auto guard = lock_guard(); if (event->is_open()) throw internal_error("SocketManager::open_event_or_cleanup(): event is already open"); func(); if (!event->is_open()) { LT_LOG("open_event_or_cleanup() : %s:%s : failed to open socket", this_thread::thread()->name(), event->type_name()); cleanup(); return false; } auto fd = event->file_descriptor(); auto itr = m_socket_map.find(fd); if (itr != m_socket_map.end()) { if (!handle_reused_socket(itr)) { // TODO: Make this a macro. use (sss : ss) LT_LOG("open_event_or_cleanup() : %s:%s:%i : failed to reuse existing file descriptor : %s:%s", this_thread::thread()->name(), event->type_name(), fd, itr->second.thread->name(), itr->second.event->type_name()); cleanup(); return false; } LT_LOG("open_event_or_cleanup() : %s:%s:%i : reused existing file descriptor : %s:%s", this_thread::thread()->name(), event->type_name(), fd, itr->second.thread->name(), itr->second.event->type_name()); itr->second = SocketInfo{fd, event, this_thread::thread()}; return true; } LT_LOG("open_event_or_cleanup() : %s:%s:%i : opened socket", this_thread::thread()->name(), event->type_name(), fd); m_socket_map.emplace(fd, SocketInfo{fd, event, this_thread::thread()}); return true; } void SocketManager::close_event_or_throw(Event* event, std::function func) { auto guard = lock_guard(); if (!event->is_open()) throw internal_error("SocketManager::close_event_or_throw(): event is not open"); auto fd = event->file_descriptor(); auto itr = m_socket_map.find(fd); if (itr == m_socket_map.end()) { LT_LOG("close_event_or_throw() : %s:%s:%i : trying to close unknown socket", this_thread::thread()->name(), event->type_name(), fd); throw internal_error("SocketManager::close_event_or_throw(): trying to close unknown socket fd"); } if (itr->second.event != event) { LT_LOG("close_event_or_throw() : %s:%s:%i : event mismatch when trying to close socket : %s:%s", this_thread::thread()->name(), event->type_name(), fd, itr->second.thread->name(), itr->second.event->type_name()); throw internal_error("SocketManager::close_event_or_throw(): event mismatch when trying to close socket fd"); } func(); if (event->is_open()) throw internal_error("SocketManager::close_event_or_throw(): event is still open after close function"); LT_LOG("close_event_or_throw() : %s:%s:%i : closed socket", this_thread::thread()->name(), event->type_name(), fd); m_socket_map.erase(itr); } void SocketManager::register_event_or_throw(Event* event, std::function func) { auto guard = lock_guard(); if (!event->is_open()) throw internal_error("SocketManager::register_event_or_throw(): event is not open"); auto fd = event->file_descriptor(); auto itr = m_socket_map.find(fd); if (itr != m_socket_map.end()) { LT_LOG("register_event_or_throw() : %s:%s:%i : tried to register an existing file descriptor : %s:%s", this_thread::thread()->name(), event->type_name(), fd, itr->second.thread->name(), itr->second.event->type_name()); throw internal_error("SocketManager::register_event_or_throw(): tried to register an existing file descriptor: " + std::string(this_thread::thread()->name()) + ":" + std::string(event->type_name()) + ":" + std::to_string(fd) + " -> " + std::string(itr->second.thread->name()) + ":" + std::string(itr->second.event->type_name())); } func(); LT_LOG("register_event_or_throw() : %s:%s:%i : registered socket", this_thread::thread()->name(), event->type_name(), fd); m_socket_map.emplace(fd, SocketInfo{fd, event, this_thread::thread()}); } void SocketManager::unregister_event_or_throw(Event* event, std::function func) { auto guard = lock_guard(); if (!event->is_open()) throw internal_error("SocketManager::unregister_event_or_throw(): event is not open"); auto fd = event->file_descriptor(); auto itr = m_socket_map.find(fd); if (itr == m_socket_map.end()) { LT_LOG("unregister_event_or_throw() : %s:%s:%i : trying to unregister unknown socket", this_thread::thread()->name(), event->type_name(), fd); throw internal_error("SocketManager::unregister_event_or_throw(): trying to unregister unknown socket fd"); } if (itr->second.event != event) { LT_LOG("unregister_event_or_throw() : %s:%s:%i : event mismatch when trying to unregister socket : %s:%s", this_thread::thread()->name(), event->type_name(), fd, itr->second.thread->name(), itr->second.event->type_name()); throw internal_error("SocketManager::unregister_event_or_throw(): event mismatch when trying to unregister socket fd"); } func(); LT_LOG("unregister_event_or_throw() : %s:%s:%i : unregistered socket", this_thread::thread()->name(), event->type_name(), fd); m_socket_map.erase(itr); } // Always returns non-null if func() succeeds. Event* SocketManager::transfer_event(Event* event_from, std::function func) { auto guard = lock_guard(); if (!event_from->is_open()) throw internal_error("SocketManager::transfer_event(): source event is not open"); auto fd = event_from->file_descriptor(); auto itr = m_socket_map.find(fd); if (itr == m_socket_map.end()) { LT_LOG("transfer_event() : %s:%s:%i : trying to transfer unknown socket", this_thread::thread()->name(), event_from->type_name(), fd); throw internal_error("SocketManager::transfer_event(): trying to transfer unknown socket fd"); } if (itr->second.event != event_from) throw internal_error("SocketManager::transfer_event(): event mismatch when trying to transfer socket fd"); auto event_to = func(); if (event_to == nullptr) { // Transfer failed, the func is responsible for cleaning up event_from. LT_LOG("transfer_event() : %s:%s:%i : socket transfer function returned nullptr", this_thread::thread()->name(), event_from->type_name(), fd); m_socket_map.erase(itr); return nullptr; } if (!event_to->is_open()) throw internal_error("SocketManager::transfer_event(): target event is not open after transfer"); itr->second.event = event_to; LT_LOG("transfer_event() : %s:%s:%i : transferred socket : %s", this_thread::thread()->name(), event_from->type_name(), fd, event_to->type_name()); return event_to; } bool SocketManager::execute_if_not_present(int fd, std::function func) { auto guard = lock_guard(); auto itr = m_socket_map.find(fd); if (itr != m_socket_map.end()) return false; func(); return true; } bool SocketManager::mark_event_active_or_fail(Event* event) { auto guard = lock_guard(); if (!event->is_open()) throw internal_error("SocketManager::mark_event_active(): event is not open"); auto fd = event->file_descriptor(); auto itr = m_socket_map.find(fd); if (itr == m_socket_map.end()) { LT_LOG("mark_event_active_or_fail() : %s:%s:%i : fd was likely reused, then closed", this_thread::thread()->name(), event->type_name(), fd); return false; } if (itr->second.event != event) { LT_LOG("mark_event_active_or_fail() : %s:%s:%i : fd has been reused and is active : %s:%s", this_thread::thread()->name(), event->type_name(), fd, itr->second.thread->name(), itr->second.event->type_name()); return false; } if (event->socket_address() != nullptr) { if (!event->update_and_verify_socket_address()) { LT_LOG("mark_event_active_or_fail() : %s:%s:%i : socket address verification failed", this_thread::thread()->name(), event->type_name(), fd); return false; } if (!event->update_and_verify_peer_address()) { LT_LOG("mark_event_active_or_fail() : %s:%s:%i : peer address verification failed", this_thread::thread()->name(), event->type_name(), fd); return false; } } itr->second.flags &= ~flag_inactive; LT_LOG("mark_event_active() : %s:%s:%i : marked socket active", this_thread::thread()->name(), event->type_name(), fd); return true; } void SocketManager::mark_event_inactive(Event* event, std::function func) { auto guard = lock_guard(); if (!event->is_open()) throw internal_error("SocketManager::mark_event_inactive(): event is not open"); auto fd = event->file_descriptor(); auto itr = m_socket_map.find(fd); if (itr == m_socket_map.end()) throw internal_error("SocketManager::mark_event_inactive(): trying to mark unknown socket fd inactive"); if (itr->second.event != event) throw internal_error("SocketManager::mark_event_inactive(): event mismatch when trying to mark socket fd inactive"); func(); itr->second.flags |= flag_inactive; LT_LOG("mark_event_inactive() : %s:%s:%i : marked socket inactive", this_thread::thread()->name(), event->type_name(), fd); } // The socket must be in read/write to avoid reuse before calling this. // // Returns false is the socket was not connected. // Some of this relies on no non-SocketManager managed sockets being added to this_thread's // poller. Or else cleanup that removes reused fd's can cause issues. // TODO: Rename inet? bool SocketManager::mark_stream_event_inactive(Event* event, std::function func, std::function on_reuse) { auto guard = lock_guard(); if (!event->is_open()) throw internal_error("SocketManager::mark_event_inactive(): event is not open"); auto fd = event->file_descriptor(); auto itr = m_socket_map.find(fd); if (itr == m_socket_map.end()) throw internal_error("SocketManager::mark_event_inactive(): trying to mark unknown socket fd inactive"); if (itr->second.event != event) throw internal_error("SocketManager::mark_event_inactive(): event mismatch when trying to mark socket fd inactive"); if (!event->update_and_verify_socket_address()) { LT_LOG("mark_stream_event_inactive() : %s:%s:%i : socket address verification failed", this_thread::thread()->name(), event->type_name(), event->file_descriptor()); on_reuse(); return false; } if (!event->update_and_verify_peer_address()) { LT_LOG("mark_stream_event_inactive() : %s:%s:%i : peer address verification failed", this_thread::thread()->name(), event->type_name(), event->file_descriptor()); // TODO: Check if socket is still valid? on_reuse(); return false; } if (!event->socket_address()) { LT_LOG("mark_stream_event_inactive() : %s:%s:%i : socket address is null after update", this_thread::thread()->name(), event->type_name(), event->file_descriptor()); on_reuse(); return false; } // TODO: Check if we got a valid socket_address (a must). LT_LOG("mark_stream_event_inactive() : %s:%s:%i : marking stream socket inactive : socket:%s peer:%s", this_thread::thread()->name(), event->type_name(), event->file_descriptor(), sa_pretty_str(event->socket_address()).c_str(), sa_pretty_str(event->peer_address()).c_str()); func(); itr->second.flags |= flag_inactive; LT_LOG("mark_event_inactive() : %s:%s:%i : marked socket inactive", this_thread::thread()->name(), event->type_name(), fd); return true; } // TODO: Finish implementation of reuse logic. (not as needed now that we check) bool SocketManager::handle_reused_socket(socket_map::iterator itr) { if (!(itr->second.flags & flag_inactive)) return false; // TODO: Add event to a closed list, which will be checked when mark_event_active is called. // // TODO: Until the, just disallow reuse. return false; // return true; } } // namespace torrent::runtime libtorrent-0.16.11/src/torrent/runtime/network_manager.cc0000644000000000000000000001255515175073411017150 #include "config.h" #include "torrent/runtime/network_manager.h" #include "net/listen.h" #include "torrent/exceptions.h" #include "torrent/net/network_config.h" #include "torrent/tracker/dht_controller.h" #include "torrent/utils/log.h" #include "torrent/system/thread.h" // TODO: Add runtime category and add it to important/complete log outputs. #define LT_LOG_NOTICE(log_fmt, ...) \ lt_log_print_subsystem(LOG_NOTICE, "runtime::network_manager", log_fmt, __VA_ARGS__); namespace torrent::runtime { NetworkManager::NetworkManager(system::Thread* main_thread) : m_main_thread(main_thread), m_listen_inet(new Listen), m_listen_inet6(new Listen), m_dht_controller(new tracker::DhtController) { } NetworkManager::~NetworkManager() { m_main_thread->cancel_callback_and_wait(this); } bool NetworkManager::is_listening() const { auto guard = lock_guard(); return is_listening_unsafe(); } bool NetworkManager::is_dht_valid() const { // auto guard = lock_guard(); return m_dht_controller->is_valid(); } bool NetworkManager::is_dht_active() const { // auto guard = lock_guard(); return m_dht_controller->is_active(); } bool NetworkManager::is_dht_active_and_receiving_requests() const { // auto guard = lock_guard(); return m_dht_controller->is_active() && m_dht_controller->is_receiving_requests(); } // Cleanup should get called twice; when shutdown is initiated and on libtorrent cleanup. void NetworkManager::cleanup() { auto guard = lock_guard(); m_dht_controller->stop(); listen_close_unsafe(); } // TODO: Currently only opens one listen socket, either ipv4 or ipv6 based on bind address. // TODO: Log here // TODO: Verify various combinations of addresses/block_ipv4in6 match tcp46/udp46 sockets // TODO: Fix DHT bool NetworkManager::listen_open(uint16_t begin, uint16_t end) { auto guard = lock_guard(); return listen_open_unsafe(begin, end); } void NetworkManager::listen_close() { auto guard = lock_guard(); listen_close_unsafe(); // m_dht_controller->stop(); } uint16_t NetworkManager::listen_port() const { auto guard = lock_guard(); return m_listen_port; } uint16_t NetworkManager::listen_port_or_throw() const { auto guard = lock_guard(); if (m_listen_port == 0) throw input_error("Tried to get listen port but it is not set."); return m_listen_port; } uint16_t NetworkManager::dht_port() { // auto guard = lock_guard(); return m_dht_controller->port(); } // TODO: Make bootstrap nodes explicit, and when we add them also try adding as node if we're // already running. // TODO: Consider adding dht bootstrap nodes to network config. void NetworkManager::dht_add_bootstrap_node(std::string host, int port){ // auto guard = lock_guard(); m_dht_controller->add_bootstrap_node(std::move(host), port); } void NetworkManager::dht_add_peer_node([[maybe_unused]] const sockaddr* sa, [[maybe_unused]] int port) { // Ignore peer nodes as we shouldn't need them(?) // // Re-enable this if it causes issues. } bool NetworkManager::is_listening_unsafe() const { return m_listen_inet->is_open() || m_listen_inet6->is_open(); } void NetworkManager::restart_listen() { auto guard = lock_guard(); if (m_listen_restarting || !is_listening_unsafe()) return; m_listen_restarting = true; m_main_thread->callback(this, [this]() { perform_restart_listen(); }); } bool NetworkManager::listen_open_unsafe(uint16_t begin, uint16_t end) { auto config_guard = config::network_config()->lock_guard(); auto backlog = config::network_config()->listen_backlog_unsafe(); if (m_listen_inet->is_open() || m_listen_inet6->is_open()) throw internal_error("NetworkManager::open_listen(): Tried to open listen socket when one is already open."); auto [inet_address, inet6_address, block_ipv4in6] = config::network_config()->listen_addresses_unsafe(); if (inet_address == nullptr && inet6_address == nullptr) throw input_error("Neither IPv4 nor IPv6 listen address are suitable for opening listen sockets, check block_ipv4 and block_ipv6 settings."); if (inet_address != nullptr && inet6_address != nullptr) { if (!Listen::open_both(m_listen_inet.get(), m_listen_inet6.get(), inet_address.get(), inet6_address.get(), begin, end, backlog, block_ipv4in6)) return false; m_listen_port = m_listen_inet->port(); return true; } if (inet_address != nullptr) { if (!Listen::open_single(m_listen_inet.get(), inet_address.get(), begin, end, backlog, false)) return false; m_listen_port = m_listen_inet->port(); return true; } if (inet6_address != nullptr) { if (!Listen::open_single(m_listen_inet6.get(), inet6_address.get(), begin, end, backlog, block_ipv4in6)) return false; m_listen_port = m_listen_inet6->port(); return true; } throw internal_error("NetworkManager::open_listen(): reached unreachable code."); } void NetworkManager::listen_close_unsafe() { m_listen_inet->close(); m_listen_inet6->close(); } void NetworkManager::perform_restart_listen() { auto guard = lock_guard(); m_listen_restarting = false; if (!is_listening_unsafe()) return; // TODO: Move DHT here and restart. listen_close_unsafe(); try { listen_open_unsafe(m_listen_port, m_listen_port); } catch (const base_error& e) { LT_LOG_NOTICE("could not restart listen socket: %s", e.what()); } } } // namespace torrent::runtime libtorrent-0.16.11/src/torrent/runtime/socket_manager.h0000644000000000000000000000627515175073411016613 #ifndef LIBTORRENT_TORRENT_RUNTIME_SOCKET_MANAGER_H #define LIBTORRENT_TORRENT_RUNTIME_SOCKET_MANAGER_H #include #include #include // A socket that is closed by the kernel while neitehr ready nor write polling will be considered // uninterested by the kernel, and possibly reused. // // Those sockets must be marked as 'inactive' in the socket manager, and when entering active state // it must check the socket manager if the socket is still valid. // // File and other socket types that do not unexpectedly get closed by the kernel do not need to be // managed. namespace torrent::runtime { struct SocketInfo { // TODO: Replace with Event*, and add thread to PollEvent? // TODO: Event should contain the owning thread, and not be included here. // TODO: Fd not needed here. int fd{-1}; Event* event{}; system::Thread* thread{}; int flags{}; }; class LIBTORRENT_EXPORT SocketManager { public: static constexpr int flag_inactive = (1 << 0); SocketManager(); ~SocketManager(); // TODO: Rename / change _or_throw to be more specific about what we throw, as it currently calls // internal errors. DHT server should probably throw resource_error instead? Or retry. (this // however hides errors for normal users) // // TODO: Finish implementation of reuse logic. // To avoid reuse race conditions, these calls must also add the Event to read/write polling. // Throw internal_error on conflicts, as the caller isn't expecting conflicts. void open_event_or_throw(Event* event, std::function func); // Try to reuse existing socket, if that fails call cleanup. // // This is used for listen accept and other cases where the caller doesn't mind ignoring failures. bool open_event_or_cleanup(Event* event, std::function func, std::function cleanup); void close_event_or_throw(Event* event, std::function func); // Event already opened the socket, just register it. void register_event_or_throw(Event* event, std::function func); void unregister_event_or_throw(Event* event, std::function func); // The func must close event_from and the pointer must remain valid. Event* transfer_event(Event* event_from, std::function func); bool execute_if_not_present(int fd, std::function func); [[nodiscard]] bool mark_event_active_or_fail(Event* event); void mark_event_inactive(Event* event, std::function func); [[nodiscard]] bool mark_stream_event_inactive(Event* event, std::function func, std::function on_reuse); // No, this should take Event*? // bool is_socket_reused(int fd); protected: auto lock_guard() { return std::lock_guard(m_mutex); } private: using socket_map = std::unordered_map; bool handle_reused_socket(socket_map::iterator itr); std::mutex m_mutex; socket_map m_socket_map; }; } // namespace torrent::runtime #endif // LIBTORRENT_TORRENT_RUNTIME_SOCKET_MANAGER_H libtorrent-0.16.11/src/torrent/runtime/network_manager.h0000644000000000000000000000520415175073411017003 #ifndef LIBTORRENT_TORRENT_RUNTIME_NETWORK_MANAGER_H #define LIBTORRENT_TORRENT_RUNTIME_NETWORK_MANAGER_H #include #include namespace torrent { class Manager; } // namespace torrent namespace torrent::runtime { class LIBTORRENT_EXPORT NetworkManager { public: NetworkManager(system::Thread* main_thread); ~NetworkManager(); bool is_listening() const; bool is_dht_valid() const; bool is_dht_active() const; bool is_dht_active_and_receiving_requests() const; void cleanup(); // TODO: Change to have network_config hold the port range / random info. bool listen_open(uint16_t first, uint16_t last); void listen_close(); // Port number remains set after listen_close. uint16_t listen_port() const; uint16_t listen_port_or_throw() const; // TODO: Only allowed to be called from main thread (tracker thread when moved). // TODO: Move DHT on/off/auto handlig here. auto* dht_controller(); uint16_t dht_port(); void dht_add_bootstrap_node(std::string host, int port); void dht_add_peer_node(const sockaddr* sa, int port); protected: friend class torrent::Manager; friend class torrent::net::NetworkConfig; void lock() const { m_mutex.lock(); } auto lock_guard() const { return std::lock_guard(m_mutex); } void unlock() const { m_mutex.unlock(); } auto& mutex() const { return m_mutex; } bool is_listening_unsafe() const; auto listen_inet_unsafe() { return m_listen_inet.get(); } auto listen_inet6_unsafe() { return m_listen_inet6.get(); } void restart_listen(); private: bool listen_open_unsafe(uint16_t first, uint16_t last); void listen_close_unsafe(); void perform_restart_listen(); system::Thread* m_main_thread; mutable std::mutex m_mutex; std::unique_ptr m_listen_inet; std::unique_ptr m_listen_inet6; uint16_t m_listen_port{0}; bool m_listen_restarting{}; std::unique_ptr m_dht_controller; }; // We don't need locking for objects we initialize/destruct in the ctor/dtor. inline auto* NetworkManager::dht_controller() { return m_dht_controller.get(); } } // namespace torrent::runtime #endif // LIBTORRENT_TORRENT_RUNTIME_NETWORK_MANAGER_H libtorrent-0.16.11/src/torrent/event.cc0000644000000000000000000000563715175073411013426 #include "config.h" #include "event.h" #include #include "torrent/exceptions.h" #include "torrent/net/fd.h" #include "torrent/net/socket_address.h" namespace torrent { Event::~Event() { assert(m_poll_event == nullptr && "Event::~Event() called with m_poll_event != nullptr."); } int Event::socket_type_or_zero() const { if (!is_open()) throw internal_error("Event::socket_type_or_zero() called on closed event."); int socktype{}; if (!fd_get_type(m_fileDesc, &socktype)) { if (errno != EBADF) throw internal_error("Event::socket_type_or_zero() error getting socket type"); return 0; } return socktype; } const char* Event::type_name() const { throw internal_error("Event::type_name() must be overridden in derived class."); } std::string Event::print_name_fd_str() const { return "name:" + std::string(type_name()) + " fd:" + std::to_string(file_descriptor()); } // TODO: Add "check_socket_valid_and_same". bool Event::update_socket_address() { if (!is_open()) throw internal_error("Event::update_socket_address() called on closed event."); int socktype = socket_type_or_zero(); if (socktype == 0 || (socktype != SOCK_STREAM && socktype != SOCK_DGRAM)) return false; auto address = fd_get_socket_name(m_fileDesc); if (address == nullptr) { if (errno != EBADF && errno != ENOTCONN && errno != EINVAL) throw internal_error("Event::update_socket_address() error getting socket address"); return false; } m_socket_address = std::move(address); return true; } bool Event::update_peer_address() { if (!is_open()) throw internal_error("Event::update_peer_address() called on closed event."); int socktype = socket_type_or_zero(); if (socktype == 0 || (socktype != SOCK_STREAM && socktype != SOCK_DGRAM)) return false; auto address = fd_get_peer_name(m_fileDesc); if (address == nullptr) { if (errno != EBADF && errno != ENOTCONN && errno != EINVAL) throw internal_error("Event::update_peer_address() error getting peer address"); return false; } m_peer_address = std::move(address); return true; } bool Event::update_and_verify_socket_address() { auto old_address = std::move(m_socket_address); if (!update_socket_address()) { m_socket_address = std::move(old_address); return m_socket_address == nullptr; } if (old_address == nullptr) return true; if (!sap_equal(old_address, m_socket_address)) { m_socket_address = std::move(old_address); return false; } return true; } bool Event::update_and_verify_peer_address() { auto old_address = std::move(m_peer_address); if (!update_peer_address()) { m_peer_address = std::move(old_address); return m_peer_address == nullptr; } if (old_address == nullptr) return true; if (!sap_equal(old_address, m_peer_address)) { m_peer_address = std::move(old_address); return false; } return true; } } // namespace torrent libtorrent-0.16.11/src/torrent/torrent.h0000644000000000000000000000464415175073411013641 #ifndef LIBTORRENT_TORRENT_H #define LIBTORRENT_TORRENT_H #include #include #include #include namespace torrent { // Make sure you seed srandom and srand48 if available. void initialize_main_thread()LIBTORRENT_EXPORT; void initialize() LIBTORRENT_EXPORT; // Clean up and close stuff. Stopping all torrents and waiting for // them to finish is not required, but recommended. void cleanup() LIBTORRENT_EXPORT; bool is_inactive() LIBTORRENT_EXPORT; bool is_initialized() LIBTORRENT_EXPORT; void set_main_thread_slots(std::function do_work) LIBTORRENT_EXPORT; ChunkManager* chunk_manager() LIBTORRENT_EXPORT; ClientList* client_list() LIBTORRENT_EXPORT; ConnectionManager* connection_manager() LIBTORRENT_EXPORT; FileManager* file_manager() LIBTORRENT_EXPORT; ResourceManager* resource_manager() LIBTORRENT_EXPORT; uint32_t total_handshakes() LIBTORRENT_EXPORT; Throttle* down_throttle_global() LIBTORRENT_EXPORT; Throttle* up_throttle_global() LIBTORRENT_EXPORT; const Rate* down_rate() LIBTORRENT_EXPORT; const Rate* up_rate() LIBTORRENT_EXPORT; const char* version() LIBTORRENT_EXPORT; using DList = std::list; using EncodingList = std::list; EncodingList* encoding_list() LIBTORRENT_EXPORT; // Will always return a valid Download. On errors it // throws. 'encodingList' contains a list of prefered encodings to use // for file names. // // The Object must be on the heap allocated with 'new'. If // 'download_add' throws the client must handle the deletion, else it // is done by 'download_remove'. // // Might consider redesigning that... Download download_add(Object* s, uint32_t tracker_key) LIBTORRENT_EXPORT; void download_remove(Download d) LIBTORRENT_EXPORT; // Add all downloads to dlist. The client is responsible for clearing // it before the call. void download_list(DList& dlist) LIBTORRENT_EXPORT; // Make sure you check the returned Download's is_valid(). Download download_find(const std::string& infohash) LIBTORRENT_EXPORT; uint32_t download_priority(Download d) LIBTORRENT_EXPORT; void download_set_priority(Download d, uint32_t pri) LIBTORRENT_EXPORT; } // namespace torrent #endif libtorrent-0.16.11/src/torrent/event.h0000644000000000000000000000374015175073411013261 #ifndef LIBTORRENT_TORRENT_EVENT_H #define LIBTORRENT_TORRENT_EVENT_H #include #include #include namespace torrent { namespace net { class PollEvent; class PollInternal; } class LIBTORRENT_EXPORT Event { public: virtual ~Event(); bool is_open() const; bool is_polling() const; int file_descriptor() const; int socket_type_or_zero() const; auto peer_address() const; auto socket_address() const; std::string print_name_fd_str() const; virtual const char* type_name() const; // TODO: Make these protected. virtual void event_read() = 0; virtual void event_write() = 0; virtual void event_error() = 0; // TODO: Add bool event_fd_reused(). protected: friend class net::Poll; friend class net::PollInternal; friend class runtime::SocketManager; void set_file_descriptor(int fd); bool update_socket_address(); bool update_peer_address(); // Returns true if the update failed and the address was null. bool update_and_verify_socket_address(); bool update_and_verify_peer_address(); std::shared_ptr m_poll_event; int m_fileDesc{-1}; private: // TODO: Add socket type to validation. c_sa_unique_ptr m_peer_address; c_sa_unique_ptr m_socket_address; }; inline bool Event::is_open() const { return file_descriptor() != -1; } inline bool Event::is_polling() const { return m_poll_event != nullptr; } inline int Event::file_descriptor() const { return m_fileDesc; } inline void Event::set_file_descriptor(int fd) { m_fileDesc = fd; } inline auto Event::peer_address() const { return m_peer_address.get(); } inline auto Event::socket_address() const { return m_socket_address.get(); } } // namespace torrent #endif libtorrent-0.16.11/src/torrent/Makefile.in0000644000000000000000000016665015175073426014054 # Makefile.in generated by automake 1.17 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2024 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) am__rm_f = rm -f $(am__rm_f_notfound) am__rm_rf = rm -rf $(am__rm_f_notfound) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = src/torrent ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/scripts/attributes.m4 \ $(top_srcdir)/scripts/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/scripts/ax_execinfo.m4 \ $(top_srcdir)/scripts/ax_pthread.m4 \ $(top_srcdir)/scripts/check_atomic.m4 \ $(top_srcdir)/scripts/checks.m4 \ $(top_srcdir)/scripts/common.m4 \ $(top_srcdir)/scripts/libtool.m4 \ $(top_srcdir)/scripts/ltoptions.m4 \ $(top_srcdir)/scripts/ltsugar.m4 \ $(top_srcdir)/scripts/ltversion.m4 \ $(top_srcdir)/scripts/lt~obsolete.m4 \ $(top_srcdir)/scripts/rak_compiler.m4 \ $(top_srcdir)/scripts/ssl.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am \ $(libtorrent_torrent_data_include_HEADERS) \ $(libtorrent_torrent_download_include_HEADERS) \ $(libtorrent_torrent_include_HEADERS) \ $(libtorrent_torrent_net_include_HEADERS) \ $(libtorrent_torrent_peer_include_HEADERS) \ $(libtorrent_torrent_runtime_include_HEADERS) \ $(libtorrent_torrent_system_include_HEADERS) \ $(libtorrent_torrent_tracker_include_HEADERS) \ $(libtorrent_torrent_utils_include_HEADERS) $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libtorrent_torrent_la_LIBADD = am__dirstamp = $(am__leading_dot)dirstamp am_libtorrent_torrent_la_OBJECTS = data/block.lo data/block_list.lo \ data/chunk_utils.lo data/download_data.lo data/file.lo \ data/file_list.lo data/file_list_iterator.lo \ data/file_manager.lo data/file_utils.lo data/transfer_list.lo \ download/choke_group.lo download/choke_queue.lo \ download/download_manager.lo download/resource_manager.lo \ net/address_info.lo net/fd.lo net/http_get.lo \ net/http_stack.lo net/network_config.lo net/poll_epoll.lo \ net/poll_kqueue.lo net/resolver.lo net/socket_address.lo \ net/socket_address_key.lo peer/client_info.lo \ peer/client_list.lo peer/connection_list.lo peer/peer.lo \ peer/peer_info.lo peer/peer_list.lo runtime/network_manager.lo \ runtime/socket_manager.lo system/thread.lo \ tracker/dht_controller.lo tracker/manager.lo \ tracker/tracker.lo tracker/wrappers.lo \ utils/directory_events.lo utils/log.lo utils/log_buffer.lo \ utils/option_strings.lo utils/random.lo utils/resume.lo \ utils/scheduler.lo utils/signal_bitfield.lo \ utils/string_manip.lo utils/uri_parser.lo bitfield.lo \ chunk_manager.lo connection_manager.lo download.lo error.lo \ event.lo exceptions.lo object.lo object_static_map.lo \ object_stream.lo path.lo rate.lo throttle.lo torrent.lo libtorrent_torrent_la_OBJECTS = $(am_libtorrent_torrent_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/bitfield.Plo \ ./$(DEPDIR)/chunk_manager.Plo \ ./$(DEPDIR)/connection_manager.Plo ./$(DEPDIR)/download.Plo \ ./$(DEPDIR)/error.Plo ./$(DEPDIR)/event.Plo \ ./$(DEPDIR)/exceptions.Plo ./$(DEPDIR)/object.Plo \ ./$(DEPDIR)/object_static_map.Plo \ ./$(DEPDIR)/object_stream.Plo ./$(DEPDIR)/path.Plo \ ./$(DEPDIR)/rate.Plo ./$(DEPDIR)/throttle.Plo \ ./$(DEPDIR)/torrent.Plo data/$(DEPDIR)/block.Plo \ data/$(DEPDIR)/block_list.Plo data/$(DEPDIR)/chunk_utils.Plo \ data/$(DEPDIR)/download_data.Plo data/$(DEPDIR)/file.Plo \ data/$(DEPDIR)/file_list.Plo \ data/$(DEPDIR)/file_list_iterator.Plo \ data/$(DEPDIR)/file_manager.Plo data/$(DEPDIR)/file_utils.Plo \ data/$(DEPDIR)/transfer_list.Plo \ download/$(DEPDIR)/choke_group.Plo \ download/$(DEPDIR)/choke_queue.Plo \ download/$(DEPDIR)/download_manager.Plo \ download/$(DEPDIR)/resource_manager.Plo \ net/$(DEPDIR)/address_info.Plo net/$(DEPDIR)/fd.Plo \ net/$(DEPDIR)/http_get.Plo net/$(DEPDIR)/http_stack.Plo \ net/$(DEPDIR)/network_config.Plo net/$(DEPDIR)/poll_epoll.Plo \ net/$(DEPDIR)/poll_kqueue.Plo net/$(DEPDIR)/resolver.Plo \ net/$(DEPDIR)/socket_address.Plo \ net/$(DEPDIR)/socket_address_key.Plo \ peer/$(DEPDIR)/client_info.Plo peer/$(DEPDIR)/client_list.Plo \ peer/$(DEPDIR)/connection_list.Plo peer/$(DEPDIR)/peer.Plo \ peer/$(DEPDIR)/peer_info.Plo peer/$(DEPDIR)/peer_list.Plo \ runtime/$(DEPDIR)/network_manager.Plo \ runtime/$(DEPDIR)/socket_manager.Plo \ system/$(DEPDIR)/thread.Plo \ tracker/$(DEPDIR)/dht_controller.Plo \ tracker/$(DEPDIR)/manager.Plo tracker/$(DEPDIR)/tracker.Plo \ tracker/$(DEPDIR)/wrappers.Plo \ utils/$(DEPDIR)/directory_events.Plo utils/$(DEPDIR)/log.Plo \ utils/$(DEPDIR)/log_buffer.Plo \ utils/$(DEPDIR)/option_strings.Plo utils/$(DEPDIR)/random.Plo \ utils/$(DEPDIR)/resume.Plo utils/$(DEPDIR)/scheduler.Plo \ utils/$(DEPDIR)/signal_bitfield.Plo \ utils/$(DEPDIR)/string_manip.Plo \ utils/$(DEPDIR)/uri_parser.Plo am__mv = mv -f CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) AM_V_CXX = $(am__v_CXX_@AM_V@) am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) am__v_CXX_0 = @echo " CXX " $@; am__v_CXX_1 = CXXLD = $(CXX) CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libtorrent_torrent_la_SOURCES) DIST_SOURCES = $(libtorrent_torrent_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && echo $$files | $(am__xargs_n) 40 $(am__rm_f); }; \ } am__installdirs = "$(DESTDIR)$(libtorrent_torrent_data_includedir)" \ "$(DESTDIR)$(libtorrent_torrent_download_includedir)" \ "$(DESTDIR)$(libtorrent_torrent_includedir)" \ "$(DESTDIR)$(libtorrent_torrent_net_includedir)" \ "$(DESTDIR)$(libtorrent_torrent_peer_includedir)" \ "$(DESTDIR)$(libtorrent_torrent_runtime_includedir)" \ "$(DESTDIR)$(libtorrent_torrent_system_includedir)" \ "$(DESTDIR)$(libtorrent_torrent_tracker_includedir)" \ "$(DESTDIR)$(libtorrent_torrent_utils_includedir)" HEADERS = $(libtorrent_torrent_data_include_HEADERS) \ $(libtorrent_torrent_download_include_HEADERS) \ $(libtorrent_torrent_include_HEADERS) \ $(libtorrent_torrent_net_include_HEADERS) \ $(libtorrent_torrent_peer_include_HEADERS) \ $(libtorrent_torrent_runtime_include_HEADERS) \ $(libtorrent_torrent_system_include_HEADERS) \ $(libtorrent_torrent_tracker_include_HEADERS) \ $(libtorrent_torrent_utils_include_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ ATOMIC_LIBS = @ATOMIC_LIBS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPUNIT_CFLAGS = @CPPUNIT_CFLAGS@ CPPUNIT_LIBS = @CPPUNIT_LIBS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FILECMD = @FILECMD@ GREP = @GREP@ HAVE_CXX17 = @HAVE_CXX17@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBCURL = @LIBCURL@ LIBCURL_CFLAGS = @LIBCURL_CFLAGS@ LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@ LIBCURL_LIBS = @LIBCURL_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTORRENT_CFLAGS = @LIBTORRENT_CFLAGS@ LIBTORRENT_CURRENT = @LIBTORRENT_CURRENT@ LIBTORRENT_INTERFACE_VERSION_INFO = @LIBTORRENT_INTERFACE_VERSION_INFO@ LIBTORRENT_INTERFACE_VERSION_NO = @LIBTORRENT_INTERFACE_VERSION_NO@ LIBTORRENT_LIBS = @LIBTORRENT_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_CXX = @PTHREAD_CXX@ PTHREAD_LIBS = @PTHREAD_LIBS@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ _libcurl_config = @_libcurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__rm_f_notfound = @am__rm_f_notfound@ am__tar = @am__tar@ am__untar = @am__untar@ am__xargs_n = @am__xargs_n@ ax_pthread_config = @ax_pthread_config@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ noinst_LTLIBRARIES = libtorrent_torrent.la libtorrent_torrent_la_SOURCES = \ data/block.cc \ data/block.h \ data/block_failed.h \ data/block_list.cc \ data/block_list.h \ data/block_transfer.h \ data/chunk_utils.cc \ data/chunk_utils.h \ data/download_data.cc \ data/download_data.h \ data/file.cc \ data/file.h \ data/file_list.cc \ data/file_list.h \ data/file_list_iterator.cc \ data/file_list_iterator.h \ data/file_manager.cc \ data/file_manager.h \ data/file_utils.cc \ data/file_utils.h \ data/piece.h \ data/transfer_list.cc \ data/transfer_list.h \ \ download/choke_group.cc \ download/choke_group.h \ download/choke_queue.cc \ download/choke_queue.h \ download/download_manager.cc \ download/download_manager.h \ download/group_entry.h \ download/resource_manager.cc \ download/resource_manager.h \ \ net/address_info.cc \ net/address_info.h \ net/connection_state.h \ net/fd.cc \ net/fd.h \ net/http_get.cc \ net/http_get.h \ net/http_stack.cc \ net/http_stack.h \ net/network_config.cc \ net/network_config.h \ net/poll.h \ net/poll_epoll.cc \ net/poll_kqueue.cc \ net/resolver.cc \ net/resolver.h \ net/socket_address.cc \ net/socket_address.h \ net/socket_address_key.cc \ net/socket_address_key.h \ net/types.h \ \ peer/choke_status.h \ peer/client_info.cc \ peer/client_info.h \ peer/client_list.cc \ peer/client_list.h \ peer/connection_list.cc \ peer/connection_list.h \ peer/peer.cc \ peer/peer.h \ peer/peer_info.cc \ peer/peer_info.h \ peer/peer_list.cc \ peer/peer_list.h \ \ runtime/network_manager.cc \ runtime/network_manager.h \ runtime/socket_manager.cc \ runtime/socket_manager.h \ \ system/thread.cc \ system/thread.h \ \ tracker/dht_controller.cc \ tracker/dht_controller.h \ tracker/manager.cc \ tracker/manager.h \ tracker/tracker.cc \ tracker/tracker.h \ tracker/tracker_state.h \ tracker/wrappers.cc \ tracker/wrappers.h \ \ utils/chrono.h \ utils/directory_events.cc \ utils/directory_events.h \ utils/extents.h \ utils/file_stat.h \ utils/log.cc \ utils/log.h \ utils/log_buffer.cc \ utils/log_buffer.h \ utils/option_strings.cc \ utils/option_strings.h \ utils/random.cc \ utils/random.h \ utils/ranges.h \ utils/resume.cc \ utils/resume.h \ utils/scheduler.cc \ utils/scheduler.h \ utils/signal_bitfield.cc \ utils/signal_bitfield.h \ utils/string_manip.cc \ utils/string_manip.h \ utils/unordered_vector.h \ utils/uri_parser.cc \ utils/uri_parser.h \ \ bitfield.cc \ bitfield.h \ chunk_manager.cc \ chunk_manager.h \ common.h \ connection_manager.cc \ connection_manager.h \ download.cc \ download.h \ download_info.h \ error.cc \ error.h \ event.cc \ event.h \ exceptions.cc \ exceptions.h \ hash_string.h \ object.cc \ object.h \ object_raw_bencode.h \ object_static_map.cc \ object_static_map.h \ object_stream.cc \ object_stream.h \ path.cc \ path.h \ rate.cc \ rate.h \ throttle.cc \ throttle.h \ torrent.cc \ torrent.h AM_CPPFLAGS = -I$(srcdir) -I$(srcdir)/.. -I$(top_srcdir) libtorrent_torrent_data_includedir = $(includedir)/torrent/data libtorrent_torrent_data_include_HEADERS = \ data/block.h \ data/block_list.h \ data/block_transfer.h \ data/chunk_utils.h \ data/download_data.h \ data/file.h \ data/file_list.h \ data/file_list_iterator.h \ data/file_manager.h \ data/file_utils.h \ data/piece.h \ data/transfer_list.h libtorrent_torrent_download_includedir = $(includedir)/torrent/download libtorrent_torrent_download_include_HEADERS = \ download/choke_group.h \ download/choke_queue.h \ download/download_manager.h \ download/group_entry.h \ download/resource_manager.h libtorrent_torrent_net_includedir = $(includedir)/torrent/net libtorrent_torrent_net_include_HEADERS = \ net/address_info.h \ net/connection_state.h \ net/fd.h \ net/http_get.h \ net/http_stack.h \ net/network_config.h \ net/poll.h \ net/resolver.h \ net/socket_address.h \ net/socket_address_key.h \ net/types.h libtorrent_torrent_peer_includedir = $(includedir)/torrent/peer libtorrent_torrent_peer_include_HEADERS = \ peer/choke_status.h \ peer/client_info.h \ peer/client_list.h \ peer/connection_list.h \ peer/peer.h \ peer/peer_info.h \ peer/peer_list.h libtorrent_torrent_runtime_includedir = $(includedir)/torrent/runtime libtorrent_torrent_runtime_include_HEADERS = \ runtime/network_manager.h \ runtime/socket_manager.h libtorrent_torrent_system_includedir = $(includedir)/torrent/system libtorrent_torrent_system_include_HEADERS = \ system/thread.h libtorrent_torrent_tracker_includedir = $(includedir)/torrent/tracker libtorrent_torrent_tracker_include_HEADERS = \ tracker/dht_controller.h \ tracker/manager.h \ tracker/tracker.h \ tracker/tracker_state.h \ tracker/wrappers.h libtorrent_torrent_utils_includedir = $(includedir)/torrent/utils libtorrent_torrent_utils_include_HEADERS = \ utils/chrono.h \ utils/directory_events.h \ utils/extents.h \ utils/file_stat.h \ utils/log.h \ utils/log_buffer.h \ utils/option_strings.h \ utils/random.h \ utils/ranges.h \ utils/resume.h \ utils/scheduler.h \ utils/signal_bitfield.h \ utils/string_manip.h \ utils/unordered_vector.h \ utils/uri_parser.h libtorrent_torrent_includedir = $(includedir)/torrent libtorrent_torrent_include_HEADERS = \ bitfield.h \ chunk_manager.h \ common.h \ connection_manager.h \ download.h \ download_info.h \ error.h \ exceptions.h \ event.h \ hash_string.h \ object.h \ object_raw_bencode.h \ object_static_map.h \ object_stream.h \ path.h \ rate.h \ throttle.h \ torrent.h all: all-am .SUFFIXES: .SUFFIXES: .cc .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/torrent/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/torrent/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -$(am__rm_f) $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ echo rm -f $${locs}; \ $(am__rm_f) $${locs} data/$(am__dirstamp): @$(MKDIR_P) data @: >>data/$(am__dirstamp) data/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) data/$(DEPDIR) @: >>data/$(DEPDIR)/$(am__dirstamp) data/block.lo: data/$(am__dirstamp) data/$(DEPDIR)/$(am__dirstamp) data/block_list.lo: data/$(am__dirstamp) \ data/$(DEPDIR)/$(am__dirstamp) data/chunk_utils.lo: data/$(am__dirstamp) \ data/$(DEPDIR)/$(am__dirstamp) data/download_data.lo: data/$(am__dirstamp) \ data/$(DEPDIR)/$(am__dirstamp) data/file.lo: data/$(am__dirstamp) data/$(DEPDIR)/$(am__dirstamp) data/file_list.lo: data/$(am__dirstamp) data/$(DEPDIR)/$(am__dirstamp) data/file_list_iterator.lo: data/$(am__dirstamp) \ data/$(DEPDIR)/$(am__dirstamp) data/file_manager.lo: data/$(am__dirstamp) \ data/$(DEPDIR)/$(am__dirstamp) data/file_utils.lo: data/$(am__dirstamp) \ data/$(DEPDIR)/$(am__dirstamp) data/transfer_list.lo: data/$(am__dirstamp) \ data/$(DEPDIR)/$(am__dirstamp) download/$(am__dirstamp): @$(MKDIR_P) download @: >>download/$(am__dirstamp) download/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) download/$(DEPDIR) @: >>download/$(DEPDIR)/$(am__dirstamp) download/choke_group.lo: download/$(am__dirstamp) \ download/$(DEPDIR)/$(am__dirstamp) download/choke_queue.lo: download/$(am__dirstamp) \ download/$(DEPDIR)/$(am__dirstamp) download/download_manager.lo: download/$(am__dirstamp) \ download/$(DEPDIR)/$(am__dirstamp) download/resource_manager.lo: download/$(am__dirstamp) \ download/$(DEPDIR)/$(am__dirstamp) net/$(am__dirstamp): @$(MKDIR_P) net @: >>net/$(am__dirstamp) net/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) net/$(DEPDIR) @: >>net/$(DEPDIR)/$(am__dirstamp) net/address_info.lo: net/$(am__dirstamp) net/$(DEPDIR)/$(am__dirstamp) net/fd.lo: net/$(am__dirstamp) net/$(DEPDIR)/$(am__dirstamp) net/http_get.lo: net/$(am__dirstamp) net/$(DEPDIR)/$(am__dirstamp) net/http_stack.lo: net/$(am__dirstamp) net/$(DEPDIR)/$(am__dirstamp) net/network_config.lo: net/$(am__dirstamp) \ net/$(DEPDIR)/$(am__dirstamp) net/poll_epoll.lo: net/$(am__dirstamp) net/$(DEPDIR)/$(am__dirstamp) net/poll_kqueue.lo: net/$(am__dirstamp) net/$(DEPDIR)/$(am__dirstamp) net/resolver.lo: net/$(am__dirstamp) net/$(DEPDIR)/$(am__dirstamp) net/socket_address.lo: net/$(am__dirstamp) \ net/$(DEPDIR)/$(am__dirstamp) net/socket_address_key.lo: net/$(am__dirstamp) \ net/$(DEPDIR)/$(am__dirstamp) peer/$(am__dirstamp): @$(MKDIR_P) peer @: >>peer/$(am__dirstamp) peer/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) peer/$(DEPDIR) @: >>peer/$(DEPDIR)/$(am__dirstamp) peer/client_info.lo: peer/$(am__dirstamp) \ peer/$(DEPDIR)/$(am__dirstamp) peer/client_list.lo: peer/$(am__dirstamp) \ peer/$(DEPDIR)/$(am__dirstamp) peer/connection_list.lo: peer/$(am__dirstamp) \ peer/$(DEPDIR)/$(am__dirstamp) peer/peer.lo: peer/$(am__dirstamp) peer/$(DEPDIR)/$(am__dirstamp) peer/peer_info.lo: peer/$(am__dirstamp) peer/$(DEPDIR)/$(am__dirstamp) peer/peer_list.lo: peer/$(am__dirstamp) peer/$(DEPDIR)/$(am__dirstamp) runtime/$(am__dirstamp): @$(MKDIR_P) runtime @: >>runtime/$(am__dirstamp) runtime/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) runtime/$(DEPDIR) @: >>runtime/$(DEPDIR)/$(am__dirstamp) runtime/network_manager.lo: runtime/$(am__dirstamp) \ runtime/$(DEPDIR)/$(am__dirstamp) runtime/socket_manager.lo: runtime/$(am__dirstamp) \ runtime/$(DEPDIR)/$(am__dirstamp) system/$(am__dirstamp): @$(MKDIR_P) system @: >>system/$(am__dirstamp) system/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) system/$(DEPDIR) @: >>system/$(DEPDIR)/$(am__dirstamp) system/thread.lo: system/$(am__dirstamp) \ system/$(DEPDIR)/$(am__dirstamp) tracker/$(am__dirstamp): @$(MKDIR_P) tracker @: >>tracker/$(am__dirstamp) tracker/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) tracker/$(DEPDIR) @: >>tracker/$(DEPDIR)/$(am__dirstamp) tracker/dht_controller.lo: tracker/$(am__dirstamp) \ tracker/$(DEPDIR)/$(am__dirstamp) tracker/manager.lo: tracker/$(am__dirstamp) \ tracker/$(DEPDIR)/$(am__dirstamp) tracker/tracker.lo: tracker/$(am__dirstamp) \ tracker/$(DEPDIR)/$(am__dirstamp) tracker/wrappers.lo: tracker/$(am__dirstamp) \ tracker/$(DEPDIR)/$(am__dirstamp) utils/$(am__dirstamp): @$(MKDIR_P) utils @: >>utils/$(am__dirstamp) utils/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) utils/$(DEPDIR) @: >>utils/$(DEPDIR)/$(am__dirstamp) utils/directory_events.lo: utils/$(am__dirstamp) \ utils/$(DEPDIR)/$(am__dirstamp) utils/log.lo: utils/$(am__dirstamp) utils/$(DEPDIR)/$(am__dirstamp) utils/log_buffer.lo: utils/$(am__dirstamp) \ utils/$(DEPDIR)/$(am__dirstamp) utils/option_strings.lo: utils/$(am__dirstamp) \ utils/$(DEPDIR)/$(am__dirstamp) utils/random.lo: utils/$(am__dirstamp) utils/$(DEPDIR)/$(am__dirstamp) utils/resume.lo: utils/$(am__dirstamp) utils/$(DEPDIR)/$(am__dirstamp) utils/scheduler.lo: utils/$(am__dirstamp) \ utils/$(DEPDIR)/$(am__dirstamp) utils/signal_bitfield.lo: utils/$(am__dirstamp) \ utils/$(DEPDIR)/$(am__dirstamp) utils/string_manip.lo: utils/$(am__dirstamp) \ utils/$(DEPDIR)/$(am__dirstamp) utils/uri_parser.lo: utils/$(am__dirstamp) \ utils/$(DEPDIR)/$(am__dirstamp) libtorrent_torrent.la: $(libtorrent_torrent_la_OBJECTS) $(libtorrent_torrent_la_DEPENDENCIES) $(EXTRA_libtorrent_torrent_la_DEPENDENCIES) $(AM_V_CXXLD)$(CXXLINK) $(libtorrent_torrent_la_OBJECTS) $(libtorrent_torrent_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) -rm -f data/*.$(OBJEXT) -rm -f data/*.lo -rm -f download/*.$(OBJEXT) -rm -f download/*.lo -rm -f net/*.$(OBJEXT) -rm -f net/*.lo -rm -f peer/*.$(OBJEXT) -rm -f peer/*.lo -rm -f runtime/*.$(OBJEXT) -rm -f runtime/*.lo -rm -f system/*.$(OBJEXT) -rm -f system/*.lo -rm -f tracker/*.$(OBJEXT) -rm -f tracker/*.lo -rm -f utils/*.$(OBJEXT) -rm -f utils/*.lo distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bitfield.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chunk_manager.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/connection_manager.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/download.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/error.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/event.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exceptions.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/object.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/object_static_map.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/object_stream.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/path.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rate.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/throttle.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/torrent.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@data/$(DEPDIR)/block.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@data/$(DEPDIR)/block_list.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@data/$(DEPDIR)/chunk_utils.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@data/$(DEPDIR)/download_data.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@data/$(DEPDIR)/file.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@data/$(DEPDIR)/file_list.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@data/$(DEPDIR)/file_list_iterator.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@data/$(DEPDIR)/file_manager.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@data/$(DEPDIR)/file_utils.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@data/$(DEPDIR)/transfer_list.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@download/$(DEPDIR)/choke_group.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@download/$(DEPDIR)/choke_queue.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@download/$(DEPDIR)/download_manager.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@download/$(DEPDIR)/resource_manager.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@net/$(DEPDIR)/address_info.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@net/$(DEPDIR)/fd.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@net/$(DEPDIR)/http_get.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@net/$(DEPDIR)/http_stack.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@net/$(DEPDIR)/network_config.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@net/$(DEPDIR)/poll_epoll.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@net/$(DEPDIR)/poll_kqueue.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@net/$(DEPDIR)/resolver.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@net/$(DEPDIR)/socket_address.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@net/$(DEPDIR)/socket_address_key.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@peer/$(DEPDIR)/client_info.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@peer/$(DEPDIR)/client_list.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@peer/$(DEPDIR)/connection_list.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@peer/$(DEPDIR)/peer.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@peer/$(DEPDIR)/peer_info.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@peer/$(DEPDIR)/peer_list.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@runtime/$(DEPDIR)/network_manager.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@runtime/$(DEPDIR)/socket_manager.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@system/$(DEPDIR)/thread.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@tracker/$(DEPDIR)/dht_controller.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@tracker/$(DEPDIR)/manager.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@tracker/$(DEPDIR)/tracker.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@tracker/$(DEPDIR)/wrappers.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@utils/$(DEPDIR)/directory_events.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@utils/$(DEPDIR)/log.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@utils/$(DEPDIR)/log_buffer.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@utils/$(DEPDIR)/option_strings.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@utils/$(DEPDIR)/random.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@utils/$(DEPDIR)/resume.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@utils/$(DEPDIR)/scheduler.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@utils/$(DEPDIR)/signal_bitfield.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@utils/$(DEPDIR)/string_manip.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@utils/$(DEPDIR)/uri_parser.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @: >>$@ am--depfiles: $(am__depfiles_remade) .cc.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cc.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cc.lo: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs -rm -rf data/.libs data/_libs -rm -rf download/.libs download/_libs -rm -rf net/.libs net/_libs -rm -rf peer/.libs peer/_libs -rm -rf runtime/.libs runtime/_libs -rm -rf system/.libs system/_libs -rm -rf tracker/.libs tracker/_libs -rm -rf utils/.libs utils/_libs install-libtorrent_torrent_data_includeHEADERS: $(libtorrent_torrent_data_include_HEADERS) @$(NORMAL_INSTALL) @list='$(libtorrent_torrent_data_include_HEADERS)'; test -n "$(libtorrent_torrent_data_includedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libtorrent_torrent_data_includedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libtorrent_torrent_data_includedir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libtorrent_torrent_data_includedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(libtorrent_torrent_data_includedir)" || exit $$?; \ done uninstall-libtorrent_torrent_data_includeHEADERS: @$(NORMAL_UNINSTALL) @list='$(libtorrent_torrent_data_include_HEADERS)'; test -n "$(libtorrent_torrent_data_includedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(libtorrent_torrent_data_includedir)'; $(am__uninstall_files_from_dir) install-libtorrent_torrent_download_includeHEADERS: $(libtorrent_torrent_download_include_HEADERS) @$(NORMAL_INSTALL) @list='$(libtorrent_torrent_download_include_HEADERS)'; test -n "$(libtorrent_torrent_download_includedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libtorrent_torrent_download_includedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libtorrent_torrent_download_includedir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libtorrent_torrent_download_includedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(libtorrent_torrent_download_includedir)" || exit $$?; \ done uninstall-libtorrent_torrent_download_includeHEADERS: @$(NORMAL_UNINSTALL) @list='$(libtorrent_torrent_download_include_HEADERS)'; test -n "$(libtorrent_torrent_download_includedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(libtorrent_torrent_download_includedir)'; $(am__uninstall_files_from_dir) install-libtorrent_torrent_includeHEADERS: $(libtorrent_torrent_include_HEADERS) @$(NORMAL_INSTALL) @list='$(libtorrent_torrent_include_HEADERS)'; test -n "$(libtorrent_torrent_includedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libtorrent_torrent_includedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libtorrent_torrent_includedir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libtorrent_torrent_includedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(libtorrent_torrent_includedir)" || exit $$?; \ done uninstall-libtorrent_torrent_includeHEADERS: @$(NORMAL_UNINSTALL) @list='$(libtorrent_torrent_include_HEADERS)'; test -n "$(libtorrent_torrent_includedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(libtorrent_torrent_includedir)'; $(am__uninstall_files_from_dir) install-libtorrent_torrent_net_includeHEADERS: $(libtorrent_torrent_net_include_HEADERS) @$(NORMAL_INSTALL) @list='$(libtorrent_torrent_net_include_HEADERS)'; test -n "$(libtorrent_torrent_net_includedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libtorrent_torrent_net_includedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libtorrent_torrent_net_includedir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libtorrent_torrent_net_includedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(libtorrent_torrent_net_includedir)" || exit $$?; \ done uninstall-libtorrent_torrent_net_includeHEADERS: @$(NORMAL_UNINSTALL) @list='$(libtorrent_torrent_net_include_HEADERS)'; test -n "$(libtorrent_torrent_net_includedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(libtorrent_torrent_net_includedir)'; $(am__uninstall_files_from_dir) install-libtorrent_torrent_peer_includeHEADERS: $(libtorrent_torrent_peer_include_HEADERS) @$(NORMAL_INSTALL) @list='$(libtorrent_torrent_peer_include_HEADERS)'; test -n "$(libtorrent_torrent_peer_includedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libtorrent_torrent_peer_includedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libtorrent_torrent_peer_includedir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libtorrent_torrent_peer_includedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(libtorrent_torrent_peer_includedir)" || exit $$?; \ done uninstall-libtorrent_torrent_peer_includeHEADERS: @$(NORMAL_UNINSTALL) @list='$(libtorrent_torrent_peer_include_HEADERS)'; test -n "$(libtorrent_torrent_peer_includedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(libtorrent_torrent_peer_includedir)'; $(am__uninstall_files_from_dir) install-libtorrent_torrent_runtime_includeHEADERS: $(libtorrent_torrent_runtime_include_HEADERS) @$(NORMAL_INSTALL) @list='$(libtorrent_torrent_runtime_include_HEADERS)'; test -n "$(libtorrent_torrent_runtime_includedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libtorrent_torrent_runtime_includedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libtorrent_torrent_runtime_includedir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libtorrent_torrent_runtime_includedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(libtorrent_torrent_runtime_includedir)" || exit $$?; \ done uninstall-libtorrent_torrent_runtime_includeHEADERS: @$(NORMAL_UNINSTALL) @list='$(libtorrent_torrent_runtime_include_HEADERS)'; test -n "$(libtorrent_torrent_runtime_includedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(libtorrent_torrent_runtime_includedir)'; $(am__uninstall_files_from_dir) install-libtorrent_torrent_system_includeHEADERS: $(libtorrent_torrent_system_include_HEADERS) @$(NORMAL_INSTALL) @list='$(libtorrent_torrent_system_include_HEADERS)'; test -n "$(libtorrent_torrent_system_includedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libtorrent_torrent_system_includedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libtorrent_torrent_system_includedir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libtorrent_torrent_system_includedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(libtorrent_torrent_system_includedir)" || exit $$?; \ done uninstall-libtorrent_torrent_system_includeHEADERS: @$(NORMAL_UNINSTALL) @list='$(libtorrent_torrent_system_include_HEADERS)'; test -n "$(libtorrent_torrent_system_includedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(libtorrent_torrent_system_includedir)'; $(am__uninstall_files_from_dir) install-libtorrent_torrent_tracker_includeHEADERS: $(libtorrent_torrent_tracker_include_HEADERS) @$(NORMAL_INSTALL) @list='$(libtorrent_torrent_tracker_include_HEADERS)'; test -n "$(libtorrent_torrent_tracker_includedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libtorrent_torrent_tracker_includedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libtorrent_torrent_tracker_includedir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libtorrent_torrent_tracker_includedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(libtorrent_torrent_tracker_includedir)" || exit $$?; \ done uninstall-libtorrent_torrent_tracker_includeHEADERS: @$(NORMAL_UNINSTALL) @list='$(libtorrent_torrent_tracker_include_HEADERS)'; test -n "$(libtorrent_torrent_tracker_includedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(libtorrent_torrent_tracker_includedir)'; $(am__uninstall_files_from_dir) install-libtorrent_torrent_utils_includeHEADERS: $(libtorrent_torrent_utils_include_HEADERS) @$(NORMAL_INSTALL) @list='$(libtorrent_torrent_utils_include_HEADERS)'; test -n "$(libtorrent_torrent_utils_includedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libtorrent_torrent_utils_includedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libtorrent_torrent_utils_includedir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libtorrent_torrent_utils_includedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(libtorrent_torrent_utils_includedir)" || exit $$?; \ done uninstall-libtorrent_torrent_utils_includeHEADERS: @$(NORMAL_UNINSTALL) @list='$(libtorrent_torrent_utils_include_HEADERS)'; test -n "$(libtorrent_torrent_utils_includedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(libtorrent_torrent_utils_includedir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(libtorrent_torrent_data_includedir)" "$(DESTDIR)$(libtorrent_torrent_download_includedir)" "$(DESTDIR)$(libtorrent_torrent_includedir)" "$(DESTDIR)$(libtorrent_torrent_net_includedir)" "$(DESTDIR)$(libtorrent_torrent_peer_includedir)" "$(DESTDIR)$(libtorrent_torrent_runtime_includedir)" "$(DESTDIR)$(libtorrent_torrent_system_includedir)" "$(DESTDIR)$(libtorrent_torrent_tracker_includedir)" "$(DESTDIR)$(libtorrent_torrent_utils_includedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -$(am__rm_f) $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || $(am__rm_f) $(CONFIG_CLEAN_VPATH_FILES) -$(am__rm_f) data/$(DEPDIR)/$(am__dirstamp) -$(am__rm_f) data/$(am__dirstamp) -$(am__rm_f) download/$(DEPDIR)/$(am__dirstamp) -$(am__rm_f) download/$(am__dirstamp) -$(am__rm_f) net/$(DEPDIR)/$(am__dirstamp) -$(am__rm_f) net/$(am__dirstamp) -$(am__rm_f) peer/$(DEPDIR)/$(am__dirstamp) -$(am__rm_f) peer/$(am__dirstamp) -$(am__rm_f) runtime/$(DEPDIR)/$(am__dirstamp) -$(am__rm_f) runtime/$(am__dirstamp) -$(am__rm_f) system/$(DEPDIR)/$(am__dirstamp) -$(am__rm_f) system/$(am__dirstamp) -$(am__rm_f) tracker/$(DEPDIR)/$(am__dirstamp) -$(am__rm_f) tracker/$(am__dirstamp) -$(am__rm_f) utils/$(DEPDIR)/$(am__dirstamp) -$(am__rm_f) utils/$(am__dirstamp) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/bitfield.Plo -rm -f ./$(DEPDIR)/chunk_manager.Plo -rm -f ./$(DEPDIR)/connection_manager.Plo -rm -f ./$(DEPDIR)/download.Plo -rm -f ./$(DEPDIR)/error.Plo -rm -f ./$(DEPDIR)/event.Plo -rm -f ./$(DEPDIR)/exceptions.Plo -rm -f ./$(DEPDIR)/object.Plo -rm -f ./$(DEPDIR)/object_static_map.Plo -rm -f ./$(DEPDIR)/object_stream.Plo -rm -f ./$(DEPDIR)/path.Plo -rm -f ./$(DEPDIR)/rate.Plo -rm -f ./$(DEPDIR)/throttle.Plo -rm -f ./$(DEPDIR)/torrent.Plo -rm -f data/$(DEPDIR)/block.Plo -rm -f data/$(DEPDIR)/block_list.Plo -rm -f data/$(DEPDIR)/chunk_utils.Plo -rm -f data/$(DEPDIR)/download_data.Plo -rm -f data/$(DEPDIR)/file.Plo -rm -f data/$(DEPDIR)/file_list.Plo -rm -f data/$(DEPDIR)/file_list_iterator.Plo -rm -f data/$(DEPDIR)/file_manager.Plo -rm -f data/$(DEPDIR)/file_utils.Plo -rm -f data/$(DEPDIR)/transfer_list.Plo -rm -f download/$(DEPDIR)/choke_group.Plo -rm -f download/$(DEPDIR)/choke_queue.Plo -rm -f download/$(DEPDIR)/download_manager.Plo -rm -f download/$(DEPDIR)/resource_manager.Plo -rm -f net/$(DEPDIR)/address_info.Plo -rm -f net/$(DEPDIR)/fd.Plo -rm -f net/$(DEPDIR)/http_get.Plo -rm -f net/$(DEPDIR)/http_stack.Plo -rm -f net/$(DEPDIR)/network_config.Plo -rm -f net/$(DEPDIR)/poll_epoll.Plo -rm -f net/$(DEPDIR)/poll_kqueue.Plo -rm -f net/$(DEPDIR)/resolver.Plo -rm -f net/$(DEPDIR)/socket_address.Plo -rm -f net/$(DEPDIR)/socket_address_key.Plo -rm -f peer/$(DEPDIR)/client_info.Plo -rm -f peer/$(DEPDIR)/client_list.Plo -rm -f peer/$(DEPDIR)/connection_list.Plo -rm -f peer/$(DEPDIR)/peer.Plo -rm -f peer/$(DEPDIR)/peer_info.Plo -rm -f peer/$(DEPDIR)/peer_list.Plo -rm -f runtime/$(DEPDIR)/network_manager.Plo -rm -f runtime/$(DEPDIR)/socket_manager.Plo -rm -f system/$(DEPDIR)/thread.Plo -rm -f tracker/$(DEPDIR)/dht_controller.Plo -rm -f tracker/$(DEPDIR)/manager.Plo -rm -f tracker/$(DEPDIR)/tracker.Plo -rm -f tracker/$(DEPDIR)/wrappers.Plo -rm -f utils/$(DEPDIR)/directory_events.Plo -rm -f utils/$(DEPDIR)/log.Plo -rm -f utils/$(DEPDIR)/log_buffer.Plo -rm -f utils/$(DEPDIR)/option_strings.Plo -rm -f utils/$(DEPDIR)/random.Plo -rm -f utils/$(DEPDIR)/resume.Plo -rm -f utils/$(DEPDIR)/scheduler.Plo -rm -f utils/$(DEPDIR)/signal_bitfield.Plo -rm -f utils/$(DEPDIR)/string_manip.Plo -rm -f utils/$(DEPDIR)/uri_parser.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-libtorrent_torrent_data_includeHEADERS \ install-libtorrent_torrent_download_includeHEADERS \ install-libtorrent_torrent_includeHEADERS \ install-libtorrent_torrent_net_includeHEADERS \ install-libtorrent_torrent_peer_includeHEADERS \ install-libtorrent_torrent_runtime_includeHEADERS \ install-libtorrent_torrent_system_includeHEADERS \ install-libtorrent_torrent_tracker_includeHEADERS \ install-libtorrent_torrent_utils_includeHEADERS install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/bitfield.Plo -rm -f ./$(DEPDIR)/chunk_manager.Plo -rm -f ./$(DEPDIR)/connection_manager.Plo -rm -f ./$(DEPDIR)/download.Plo -rm -f ./$(DEPDIR)/error.Plo -rm -f ./$(DEPDIR)/event.Plo -rm -f ./$(DEPDIR)/exceptions.Plo -rm -f ./$(DEPDIR)/object.Plo -rm -f ./$(DEPDIR)/object_static_map.Plo -rm -f ./$(DEPDIR)/object_stream.Plo -rm -f ./$(DEPDIR)/path.Plo -rm -f ./$(DEPDIR)/rate.Plo -rm -f ./$(DEPDIR)/throttle.Plo -rm -f ./$(DEPDIR)/torrent.Plo -rm -f data/$(DEPDIR)/block.Plo -rm -f data/$(DEPDIR)/block_list.Plo -rm -f data/$(DEPDIR)/chunk_utils.Plo -rm -f data/$(DEPDIR)/download_data.Plo -rm -f data/$(DEPDIR)/file.Plo -rm -f data/$(DEPDIR)/file_list.Plo -rm -f data/$(DEPDIR)/file_list_iterator.Plo -rm -f data/$(DEPDIR)/file_manager.Plo -rm -f data/$(DEPDIR)/file_utils.Plo -rm -f data/$(DEPDIR)/transfer_list.Plo -rm -f download/$(DEPDIR)/choke_group.Plo -rm -f download/$(DEPDIR)/choke_queue.Plo -rm -f download/$(DEPDIR)/download_manager.Plo -rm -f download/$(DEPDIR)/resource_manager.Plo -rm -f net/$(DEPDIR)/address_info.Plo -rm -f net/$(DEPDIR)/fd.Plo -rm -f net/$(DEPDIR)/http_get.Plo -rm -f net/$(DEPDIR)/http_stack.Plo -rm -f net/$(DEPDIR)/network_config.Plo -rm -f net/$(DEPDIR)/poll_epoll.Plo -rm -f net/$(DEPDIR)/poll_kqueue.Plo -rm -f net/$(DEPDIR)/resolver.Plo -rm -f net/$(DEPDIR)/socket_address.Plo -rm -f net/$(DEPDIR)/socket_address_key.Plo -rm -f peer/$(DEPDIR)/client_info.Plo -rm -f peer/$(DEPDIR)/client_list.Plo -rm -f peer/$(DEPDIR)/connection_list.Plo -rm -f peer/$(DEPDIR)/peer.Plo -rm -f peer/$(DEPDIR)/peer_info.Plo -rm -f peer/$(DEPDIR)/peer_list.Plo -rm -f runtime/$(DEPDIR)/network_manager.Plo -rm -f runtime/$(DEPDIR)/socket_manager.Plo -rm -f system/$(DEPDIR)/thread.Plo -rm -f tracker/$(DEPDIR)/dht_controller.Plo -rm -f tracker/$(DEPDIR)/manager.Plo -rm -f tracker/$(DEPDIR)/tracker.Plo -rm -f tracker/$(DEPDIR)/wrappers.Plo -rm -f utils/$(DEPDIR)/directory_events.Plo -rm -f utils/$(DEPDIR)/log.Plo -rm -f utils/$(DEPDIR)/log_buffer.Plo -rm -f utils/$(DEPDIR)/option_strings.Plo -rm -f utils/$(DEPDIR)/random.Plo -rm -f utils/$(DEPDIR)/resume.Plo -rm -f utils/$(DEPDIR)/scheduler.Plo -rm -f utils/$(DEPDIR)/signal_bitfield.Plo -rm -f utils/$(DEPDIR)/string_manip.Plo -rm -f utils/$(DEPDIR)/uri_parser.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-libtorrent_torrent_data_includeHEADERS \ uninstall-libtorrent_torrent_download_includeHEADERS \ uninstall-libtorrent_torrent_includeHEADERS \ uninstall-libtorrent_torrent_net_includeHEADERS \ uninstall-libtorrent_torrent_peer_includeHEADERS \ uninstall-libtorrent_torrent_runtime_includeHEADERS \ uninstall-libtorrent_torrent_system_includeHEADERS \ uninstall-libtorrent_torrent_tracker_includeHEADERS \ uninstall-libtorrent_torrent_utils_includeHEADERS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-generic clean-libtool clean-noinstLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am \ install-libtorrent_torrent_data_includeHEADERS \ install-libtorrent_torrent_download_includeHEADERS \ install-libtorrent_torrent_includeHEADERS \ install-libtorrent_torrent_net_includeHEADERS \ install-libtorrent_torrent_peer_includeHEADERS \ install-libtorrent_torrent_runtime_includeHEADERS \ install-libtorrent_torrent_system_includeHEADERS \ install-libtorrent_torrent_tracker_includeHEADERS \ install-libtorrent_torrent_utils_includeHEADERS install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ uninstall-libtorrent_torrent_data_includeHEADERS \ uninstall-libtorrent_torrent_download_includeHEADERS \ uninstall-libtorrent_torrent_includeHEADERS \ uninstall-libtorrent_torrent_net_includeHEADERS \ uninstall-libtorrent_torrent_peer_includeHEADERS \ uninstall-libtorrent_torrent_runtime_includeHEADERS \ uninstall-libtorrent_torrent_system_includeHEADERS \ uninstall-libtorrent_torrent_tracker_includeHEADERS \ uninstall-libtorrent_torrent_utils_includeHEADERS .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: # Tell GNU make to disable its built-in pattern rules. %:: %,v %:: RCS/%,v %:: RCS/% %:: s.% %:: SCCS/s.% libtorrent-0.16.11/src/torrent/object_static_map.cc0000644000000000000000000000201015175073411015735 #include "config.h" #include "torrent/object_static_map.h" #include "utils/functional.h" namespace torrent { static_map_key_search_result find_key_match(const static_map_mapping_type* first, const static_map_mapping_type* last, const char* key_first, const char* key_last) { // unsigned int key_length = strlen(key); const static_map_mapping_type* itr = first; while (itr != last) { unsigned int base = ::utils::count_base(key_first, key_last, itr->key, itr->key + torrent::static_map_mapping_type::max_key_size); if (key_first[base] != '\0') { // Return not found here if we know the entry won't come after // this. itr++; continue; } if (itr->key[base] == '\0' || itr->key[base] == '*' || (itr->key[base] == ':' && itr->key[base + 1] == ':') || (itr->key[base] == '[' && itr->key[base + 1] == ']')) return static_map_key_search_result(itr, base); break; } return static_map_key_search_result(first, 0); } } // namespace torrent libtorrent-0.16.11/src/torrent/system/0000755000000000000000000000000015175073434013374 5libtorrent-0.16.11/src/torrent/system/thread.cc0000644000000000000000000002433015175073411015067 #include "config.h" #include "torrent/system/thread.h" #include #include #include #include #include #include "torrent/exceptions.h" #include "torrent/net/poll.h" #include "torrent/net/resolver.h" #include "torrent/runtime/socket_manager.h" #include "torrent/utils/chrono.h" #include "torrent/utils/log.h" #include "torrent/utils/scheduler.h" #include "utils/instrumentation.h" #include "utils/signal_interrupt.h" #include "utils/thread_internal.h" namespace torrent::system { thread_local Thread* Thread::m_self{nullptr}; Thread::~Thread() = default; Thread* Thread::self() { return m_self; } void Thread::init_thread() {} void Thread::init_thread_pre_start() {} void Thread::init_thread_post_local() {} void Thread::cleanup_thread() {} Thread::Thread() : m_instrumentation_index(INSTRUMENTATION_POLLING_DO_POLL_OTHERS - INSTRUMENTATION_POLLING_DO_POLL), m_poll(net::Poll::create()), m_scheduler(new utils::Scheduler) { std::tie(m_interrupt_sender, m_interrupt_receiver) = SignalInterrupt::create_pair(); m_cached_time = utils::time_since_epoch(); m_scheduler->set_cached_time(m_cached_time); } void Thread::start_thread() { if (m_poll == nullptr) throw internal_error("No poll object for thread defined."); if (!is_initialized()) throw internal_error("Called Thread::start_thread on an uninitialized object."); init_thread_pre_start(); if (pthread_create(&m_thread, nullptr, &Thread::enter_event_loop, this)) throw internal_error("Failed to create thread."); while (m_state != STATE_ACTIVE) usleep(100); } // Each thread needs to check flag_do_shutdown in call_events() and decide how to cleanly shut down. void Thread::stop_thread_wait() { m_flags |= flag_do_shutdown; interrupt(); pthread_join(m_thread, nullptr); assert(is_inactive()); } void Thread::callback(void* target, std::function&& fn) { { auto lock = std::lock_guard(m_callbacks_lock); m_callbacks.emplace(target, std::move(fn)); } interrupt(); } void Thread::callback_interrupt_polling(void* target, std::function&& fn) { { auto lock = std::lock_guard(m_callbacks_lock); m_interrupt_callbacks.emplace(target, std::move(fn)); m_callbacks_should_interrupt_polling = true; } interrupt(); } void Thread::callback_interrupt_polling_and_wait(void* target, std::function&& fn) { std::mutex callback_mutex; std::condition_variable callback_cv; bool done{}; auto wrapped_fn = [&callback_mutex, &callback_cv, &done, fn = std::move(fn)]() { fn(); { auto lock = std::lock_guard(callback_mutex); done = true; } callback_cv.notify_one(); }; callback_interrupt_polling(target, std::move(wrapped_fn)); { auto lock = std::unique_lock(callback_mutex); callback_cv.wait(lock, [&done]() { return done; }); } } void Thread::cancel_callback(void* target) { if (target == nullptr) throw internal_error("Thread::cancel_callback called() with a null pointer target."); auto lock = std::lock_guard(m_callbacks_lock); m_callbacks.erase(target); m_interrupt_callbacks.erase(target); } void Thread::cancel_callback_and_wait(void* target) { cancel_callback(target); if (std::this_thread::get_id() != m_thread_id && m_callbacks_processing) { { auto lock = std::lock_guard(m_callbacks_processing_lock); } // Remove 'target' again in case it was added by the processed callback. cancel_callback(target); } } // Fix interrupting when shutting down thread. void Thread::interrupt() { // Only poke when polling, set no_timeout if (is_polling()) m_interrupt_sender->poke(); } bool Thread::should_handle_sigusr1() { return false; } void* Thread::enter_event_loop(void* thread) { auto t = static_cast(thread); if (t == nullptr) throw internal_error("Thread::enter_event_loop called with a null pointer thread"); t->init_thread_local(); t->init_thread_post_local(); t->event_loop(); t->cleanup_thread_local(); return nullptr; } void Thread::event_loop() { lt_log_print(LOG_THREAD_NOTICE, "%s : starting thread event loop", name()); try { runtime::socket_manager()->register_event_or_throw(m_interrupt_receiver.get(), [this]() { m_poll->open(m_interrupt_receiver.get()); m_poll->insert_read(m_interrupt_receiver.get()); m_poll->insert_error(m_interrupt_receiver.get()); }); runtime::socket_manager()->register_event_or_throw(m_interrupt_sender.get(), []() {}); while (true) { process_events(); m_flags |= flag_polling; // Call again after setting flag_polling to ensure we process any events that have // race-conditions with flag_polling. process_events(); instrumentation_update(INSTRUMENTATION_POLLING_DO_POLL, 1); instrumentation_update(instrumentation_enum(INSTRUMENTATION_POLLING_DO_POLL + m_instrumentation_index), 1); auto timeout = std::max(next_timeout(), std::chrono::microseconds(0)); if (!m_scheduler->empty()) timeout = std::min(timeout, m_scheduler->next_timeout()); int event_count = m_poll->do_poll(timeout.count()); instrumentation_update(INSTRUMENTATION_POLLING_EVENTS, event_count); instrumentation_update(instrumentation_enum(INSTRUMENTATION_POLLING_EVENTS + m_instrumentation_index), event_count); m_flags &= ~flag_polling; } } catch (const shutdown_exception&) { lt_log_print(LOG_THREAD_NOTICE, "%s: Shutting down thread.", name()); } catch (const internal_error& e) { // Uncaught internal errors in threads cause the program to exit, and we need to flush the logs. if (this_thread::thread_id() != torrent::main_thread::thread_id()) log_cleanup(); throw; } runtime::socket_manager()->unregister_event_or_throw(m_interrupt_receiver.get(), [this]() { m_poll->remove_read(m_interrupt_receiver.get()); m_poll->remove_error(m_interrupt_receiver.get()); m_poll->close(m_interrupt_receiver.get()); }); runtime::socket_manager()->unregister_event_or_throw(m_interrupt_sender.get(), []() {}); auto previous_state = STATE_ACTIVE; if (!m_state.compare_exchange_strong(previous_state, STATE_INACTIVE)) throw internal_error("Thread::event_loop called on an object that is not in the active state."); } void Thread::init_thread_local() { #if defined(HAS_PTHREAD_SETNAME_NP_DARWIN) pthread_setname_np(name()); #elif defined(HAS_PTHREAD_SETNAME_NP_GENERIC) // Cannot use thread->m_thread here as it may not be set before pthread_create returns. pthread_setname_np(pthread_self(), name()); #endif m_self = this; m_thread = pthread_self(); m_thread_id = std::this_thread::get_id(); m_scheduler->set_thread_id(m_thread_id); m_signal_bitfield.handover(m_thread_id); set_cached_time(utils::time_since_epoch()); if (m_resolver) m_resolver->init(); auto previous_state = STATE_INITIALIZED; if (!m_state.compare_exchange_strong(previous_state, STATE_ACTIVE)) throw internal_error("Thread::init_thread_local() : " + std::string(name()) + " : called on an object that is not in the initialized state."); } void Thread::cleanup_thread_local() { lt_log_print(LOG_THREAD_NOTICE, "%s : cleaning up thread local data", name()); cleanup_thread(); // TODO: Cleanup the resolver, scheduler, and poll objects. m_self = nullptr; } void Thread::process_events() { // TODO: We should call process_callbacks() here before and after call_events, however due to the // many different cached times in the code, we need to let each thread manage this themselves. set_cached_time(utils::time_since_epoch()); call_events(); m_signal_bitfield.work(); set_cached_time(utils::time_since_epoch()); m_scheduler->perform(m_cached_time); } // Used for testing. void Thread::process_events_without_cached_time() { call_events(); m_signal_bitfield.work(); m_scheduler->perform(m_cached_time); } // TODO: This should be called in process_events. void Thread::process_callbacks(bool only_interrupt) { m_callbacks_should_interrupt_polling = false; while (true) { std::function callback; { auto lock = std::lock_guard(m_callbacks_lock); if (!m_interrupt_callbacks.empty()) callback = m_interrupt_callbacks.extract(m_interrupt_callbacks.begin()).mapped(); else if (!only_interrupt && !m_callbacks.empty()) callback = m_callbacks.extract(m_callbacks.begin()).mapped(); else break; // The 'm_callbacks_processing_lock' is used by 'cancel_callback_and_wait' as a way to wait // for the processing of the callbacks to finish. m_callbacks_processing_lock.lock(); m_callbacks_processing = true; } callback(); m_callbacks_processing = false; m_callbacks_processing_lock.unlock(); } } void Thread::set_cached_time(std::chrono::microseconds t) { m_cached_time = t; m_scheduler->set_cached_time(t); } } // namespace torrent::utils namespace torrent::this_thread { torrent::system::Thread* thread() { return system::ThreadInternal::thread(); } std::thread::id thread_id() { return system::ThreadInternal::thread_id(); } std::chrono::microseconds cached_time() { return system::ThreadInternal::cached_time(); } std::chrono::seconds cached_seconds() { return system::ThreadInternal::cached_seconds(); } void callback(void* target, std::function&& fn) { system::ThreadInternal::callback(target, std::move(fn)); } void cancel_callback(void* target) { system::ThreadInternal::cancel_callback(target); } void cancel_callback_and_wait(void* target) { system::ThreadInternal::cancel_callback_and_wait(target); } net::Poll* poll() { return system::ThreadInternal::poll(); } net::Resolver* resolver() { return system::ThreadInternal::resolver(); } utils::Scheduler* scheduler() { return system::ThreadInternal::scheduler(); } } // namespace torrent::this_thread libtorrent-0.16.11/src/torrent/system/thread.h0000644000000000000000000001304415175073411014731 #ifndef LIBTORRENT_TORRENT_UTILS_THREAD_H #define LIBTORRENT_TORRENT_UTILS_THREAD_H #include #include #include #include #include #include #include #include namespace torrent { class SignalInterrupt; } // namespace torrent namespace torrent::system { class ThreadInternal; class LIBTORRENT_EXPORT Thread { public: using pthread_func = void* (*)(void*); enum state_type { STATE_UNKNOWN, STATE_INITIALIZED, STATE_ACTIVE, STATE_INACTIVE }; static constexpr int flag_do_shutdown = 0x1; static constexpr int flag_did_shutdown = 0x2; static constexpr int flag_polling = 0x4; // The ctor and dtor are called outside of the thread, so thread-specific initialization and // destruction should be done in init_thread() and cleanup_thread() respectively. Thread(); virtual ~Thread(); // TODO: Should we clear m_self after event_loop ends? static Thread* self(); virtual const char* name() const = 0; bool is_initialized() const { return state() == STATE_INITIALIZED; } bool is_active() const { return state() == STATE_ACTIVE; } bool is_inactive() const { return state() == STATE_INACTIVE; } bool is_polling() const; bool is_current() const; bool has_do_shutdown() const { return (flags() & flag_do_shutdown); } bool has_did_shutdown() const { return (flags() & flag_did_shutdown); } pthread_t pthread() const { return m_thread; } std::thread::id thread_id() const { return m_thread_id; } state_type state() const { return m_state; } int flags() const { return m_flags; } // TODO: This shouldn't be atomic, and should be in torrent::this_thread::cached_time(). auto cached_time() const { return m_cached_time.load(); } // Only call these from the same thread, or before start_thread. // auto signal_bitfield() { return &m_signal_bitfield; } virtual void init_thread(); void start_thread(); void stop_thread_wait(); void callback(void* target, std::function&& fn); void callback_interrupt_polling(void* target, std::function&& fn); void callback_interrupt_polling_and_wait(void* target, std::function&& fn); void cancel_callback(void* target); void cancel_callback_and_wait(void* target); void interrupt(); void send_event_signal(unsigned int index, bool interrupt = true); static bool should_handle_sigusr1(); void event_loop(); protected: friend class torrent::net::Poll; friend class ThreadInternal; net::Resolver* resolver() { return m_resolver.get(); } utils::Scheduler* scheduler() { return m_scheduler.get(); } bool callbacks_should_interrupt_polling() const { return m_callbacks_should_interrupt_polling.load(); } static void* enter_event_loop(void* thread); virtual void call_events() = 0; virtual std::chrono::microseconds next_timeout() = 0; virtual void init_thread_pre_start(); void init_thread_local(); virtual void init_thread_post_local(); // It is assumed that any thread-specific resources no longer are accessed at the time // cleanup_thread is called, or that those resources remain safe to call. // // This mean that e.g. tracker::Manager never gets called once thread_tracker is stopped. virtual void cleanup_thread(); void cleanup_thread_local(); void process_events(); void process_events_without_cached_time(); void process_callbacks(bool only_interrupt = false); void set_cached_time(std::chrono::microseconds t); static thread_local Thread* m_self; // TODO: Remove m_thread. pthread_t m_thread{}; std::atomic m_thread_id; std::atomic m_state{STATE_UNKNOWN}; std::atomic_int m_flags{0}; // TODO: Make it so only thread_this can access m_cached_time. std::atomic m_cached_time; int m_instrumentation_index; std::unique_ptr m_poll; std::unique_ptr m_resolver; std::unique_ptr m_scheduler; class signal_bitfield m_signal_bitfield; std::unique_ptr m_interrupt_sender; std::unique_ptr m_interrupt_receiver; std::mutex m_callbacks_lock; std::multimap> m_callbacks; std::multimap> m_interrupt_callbacks; std::atomic m_callbacks_should_interrupt_polling{false}; std::mutex m_callbacks_processing_lock; std::atomic m_callbacks_processing{false}; }; inline bool Thread::is_polling() const { return (flags() & flag_polling); } inline bool Thread::is_current() const { return m_thread == pthread_self(); } inline void Thread::send_event_signal(unsigned int index, bool do_interrupt) { m_signal_bitfield.signal(index); if (do_interrupt) interrupt(); } } // namespace torrent::utils #endif libtorrent-0.16.11/src/torrent/utils/0000755000000000000000000000000015175073434013210 5libtorrent-0.16.11/src/torrent/utils/option_strings.h0000644000000000000000000000250515175073411016357 #ifndef LIBTORRENT_UTILS_OPTION_STRINGS_H #define LIBTORRENT_UTILS_OPTION_STRINGS_H #include #include namespace torrent { class Object; enum option_enum { OPTION_CONNECTION_TYPE, OPTION_CHOKE_HEURISTICS, OPTION_CHOKE_HEURISTICS_DOWNLOAD, OPTION_CHOKE_HEURISTICS_UPLOAD, OPTION_ENCRYPTION, OPTION_IP_FILTER, OPTION_IP_TOS, OPTION_TRACKER_MODE, OPTION_HANDSHAKE_CONNECTION, OPTION_LOG_GROUP, OPTION_TRACKER_EVENT, OPTION_MAX_SIZE, OPTION_START_COMPACT = OPTION_HANDSHAKE_CONNECTION, OPTION_SINGLE_SIZE = OPTION_MAX_SIZE - OPTION_START_COMPACT }; int option_find_string(option_enum opt_enum, const char* name) LIBTORRENT_EXPORT; inline int option_find_string_str(option_enum opt_enum, const std::string& name) { return option_find_string(opt_enum, name.c_str()); } const char* option_to_string(option_enum opt_enum, unsigned int value, const char* not_found = "invalid") LIBTORRENT_EXPORT; const char* option_to_string_or_throw(option_enum opt_enum, unsigned int value, const char* not_found = "Invalid option value") LIBTORRENT_EXPORT; // TODO: Deprecated. const char* option_as_string(option_enum opt_enum, unsigned int value) LIBTORRENT_EXPORT; torrent::Object option_list_strings(option_enum opt_enum) LIBTORRENT_EXPORT; } // namespace torrent #endif libtorrent-0.16.11/src/torrent/utils/unordered_vector.h0000644000000000000000000000316215175073411016647 #ifndef LIBTORRENT_TORRENT_UTILS_UNORDERED_VECTOR_H #define LIBTORRENT_TORRENT_UTILS_UNORDERED_VECTOR_H #include namespace torrent::utils { template class unordered_vector : private std::vector<_Tp> { public: typedef std::vector<_Tp> Base; typedef typename Base::value_type value_type; typedef typename Base::pointer pointer; typedef typename Base::const_pointer const_pointer; typedef typename Base::reference reference; typedef typename Base::const_reference const_reference; typedef typename Base::size_type size_type; typedef typename Base::difference_type difference_type; typedef typename Base::allocator_type allocator_type; typedef typename Base::iterator iterator; typedef typename Base::reverse_iterator reverse_iterator; typedef typename Base::const_iterator const_iterator; typedef typename Base::const_reverse_iterator const_reverse_iterator; using Base::clear; using Base::empty; using Base::size; using Base::reserve; using Base::front; using Base::back; using Base::begin; using Base::end; using Base::rbegin; using Base::rend; using Base::push_back; using Base::pop_back; // Use the range erase function, the single element erase gets // overloaded. using Base::erase; iterator erase(iterator position); private: }; template typename unordered_vector<_Tp>::iterator unordered_vector<_Tp>::erase(iterator position) { // We don't need to check if position == end - 1 since we then copy // to the position we pop later. *position = std::move(Base::back()); Base::pop_back(); return position; } } #endif libtorrent-0.16.11/src/torrent/utils/directory_events.h0000644000000000000000000000235715175073411016673 #ifndef LIBTORRENT_DIRECTORY_EVENTS_H #define LIBTORRENT_DIRECTORY_EVENTS_H #include #include #include #include namespace torrent { struct watch_descriptor { using slot_string = std::function; bool compare_desc(int desc) const { return desc == descriptor; } int descriptor; std::string path; slot_string slot; }; class LIBTORRENT_EXPORT directory_events : public Event { public: using wd_list = std::vector; using slot_string = watch_descriptor::slot_string; static constexpr int flag_on_added = 0x1; static constexpr int flag_on_removed = 0x2; static constexpr int flag_on_updated = 0x3; directory_events() { m_fileDesc = -1; } ~directory_events() override = default; bool open(); void close(); void notify_on(const std::string& path, int flags, const slot_string& slot); void event_read() override; void event_write() override; void event_error() override; const char* type_name() const override { return "directory_events"; } private: wd_list m_wd_list; }; } // namespace torrent #endif libtorrent-0.16.11/src/torrent/utils/random.cc0000644000000000000000000000126715175073411014720 #include "config.h" #include "random.h" #include "torrent/exceptions.h" namespace torrent { template std::enable_if_t, T> static random_uniform_template(T min, T max) { if (min > max) throw internal_error("random_uniform: min > max"); if (min == max) return min; static thread_local std::mt19937 mt(std::random_device{}()); return std::uniform_int_distribution(min, max)(mt); } uint16_t random_uniform_uint16(uint16_t min, uint16_t max) { return random_uniform_template(min, max); } uint32_t random_uniform_uint32(uint32_t min, uint32_t max) { return random_uniform_template(min, max); } } // namespace torrent libtorrent-0.16.11/src/torrent/utils/chrono.h0000644000000000000000000000231415175073411014564 #ifndef TORRENT_UTILS_CHRONO_H #define TORRENT_UTILS_CHRONO_H #include using namespace std::chrono_literals; namespace torrent::utils { std::chrono::microseconds ceil_seconds(std::chrono::microseconds t); std::chrono::seconds cast_seconds(std::chrono::microseconds t); std::chrono::microseconds time_since_epoch(); // Implementation: inline std::chrono::seconds cast_seconds(std::chrono::microseconds t) { return std::chrono::duration_cast(t); } inline std::chrono::microseconds ceil_seconds(std::chrono::microseconds t) { // C++17 // return std::chrono::duration_cast(t.ceil()); auto seconds = std::chrono::duration_cast(t + 1s - 1us); return std::chrono::duration_cast(seconds); } inline std::chrono::seconds ceil_cast_seconds(std::chrono::microseconds t) { return std::chrono::duration_cast(t + 1s - 1us); } inline std::chrono::microseconds time_since_epoch() { return std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()); } } // namespace torrent::utils #endif // TORRENT_UTILS_CHRONO_H libtorrent-0.16.11/src/torrent/utils/scheduler.h0000644000000000000000000000561215175073411015256 #ifndef TORRENT_UTILS_SCHEDULER_H #define TORRENT_UTILS_SCHEDULER_H #include #include #include #include #include namespace torrent::utils { class LIBTORRENT_EXPORT Scheduler : public std::vector { public: using base_type = std::vector; using time_type = std::chrono::microseconds; using base_type::begin; using base_type::end; using base_type::front; using base_type::size; using base_type::empty; using base_type::clear; ~Scheduler() = default; // time_type is microseconds since unix epoch. time_type next_timeout() const; void erase(SchedulerEntry* entry); void wait_until(SchedulerEntry* entry, time_type time); void wait_for(SchedulerEntry* entry, time_type time); void wait_for_ceil_seconds(SchedulerEntry* entry, time_type time); void update_wait_until(SchedulerEntry* entry, time_type time); void update_wait_for(SchedulerEntry* entry, time_type time); void update_wait_for_ceil_seconds(SchedulerEntry* entry, time_type time); protected: friend class system::Thread; void perform(time_type time); void set_thread_id(std::thread::id id) { m_thread_id = id; } void set_cached_time(time_type t) { m_cached_time = t; } private: void make_heap(); void push_heap(); std::atomic m_thread_id; time_type m_cached_time{}; }; class LIBTORRENT_EXPORT SchedulerEntry { public: using slot_type = std::function; using time_type = std::chrono::microseconds; SchedulerEntry() = default; ~SchedulerEntry(); bool is_valid() const { return m_slot != nullptr; } bool is_scheduled() const { return m_scheduler != nullptr; } slot_type& slot() { return m_slot; } Scheduler* scheduler() const { return m_scheduler; } time_type time() const { return m_time; } protected: friend class Scheduler; void set_scheduler(Scheduler* s) { m_scheduler = s; } void set_time(time_type t) { m_time = t; } private: SchedulerEntry(const SchedulerEntry&) = delete; SchedulerEntry& operator=(const SchedulerEntry&) = delete; slot_type m_slot; Scheduler* m_scheduler{}; time_type m_time{}; }; class LIBTORRENT_EXPORT ExternalScheduler : public Scheduler { public: void external_perform(time_type time) { perform(time); } void external_set_thread_id(std::thread::id id) { set_thread_id(id); } void external_set_cached_time(time_type t) { set_cached_time(t); } }; } // namespace torrent::utils #endif // TORRENT_UTILS_SCHEDULER_H libtorrent-0.16.11/src/torrent/utils/log_buffer.h0000644000000000000000000000367215175073411015416 #ifndef LIBTORRENT_TORRENT_UTILS_LOG_BUFFER_H #define LIBTORRENT_TORRENT_UTILS_LOG_BUFFER_H #include #include #include #include #include #include #include namespace torrent { struct log_entry { log_entry(int32_t t, int32_t grp, std::string msg) : timestamp(t), group(grp), message(std::move(msg)) {} bool is_older_than(int32_t t) const { return timestamp < t; } bool is_younger_than(int32_t t) const { return timestamp > t; } bool is_younger_or_same(int32_t t) const { return timestamp >= t; } int32_t timestamp; int32_t group; std::string message; }; class LIBTORRENT_EXPORT log_buffer : private std::deque { public: using base_type = std::deque; using slot_void = std::function; using base_type::iterator; using base_type::const_iterator; using base_type::reverse_iterator; using base_type::const_reverse_iterator; using base_type::begin; using base_type::end; using base_type::rbegin; using base_type::rend; using base_type::front; using base_type::back; using base_type::empty; using base_type::size; unsigned int max_size() const { return m_max_size; } // Always lock before calling any function. void lock() { m_lock.lock(); } void unlock() { m_lock.unlock(); } const_iterator find_older(int32_t older_than); void lock_and_set_update_slot(const slot_void& slot) { lock(); m_slot_update = slot; unlock(); } void lock_and_push_log(const char* data, size_t length, int group); private: std::mutex m_lock; unsigned int m_max_size{200}; slot_void m_slot_update; }; typedef std::unique_ptr> log_buffer_ptr; log_buffer_ptr log_open_log_buffer(const char* name) LIBTORRENT_EXPORT; } // namespace torrent #endif libtorrent-0.16.11/src/torrent/utils/uri_parser.cc0000644000000000000000000001514715175073411015615 #include "config.h" #include "torrent/utils/uri_parser.h" #include #include #include #include namespace torrent::utils { static inline bool is_unreserved_uri_char(char c) { return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '-' || c == '_' || c == '.' || c == '~'; } static inline bool is_valid_uri_query_char(char c) { return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '-' || c == '_' || c == '.' || c == '~' || c == ':' || c == '&' || c == '=' || c == '/' || c == '%'; } static inline bool is_unreserved_uri_query_char(char c) { return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '-' || c == '_' || c == '.' || c == '~' || c == ':' || c == '=' || c == '/' || c == '%'; } static inline bool is_not_unreserved_uri_char(char c) { return !is_unreserved_uri_char(c); } static inline bool is_not_valid_uri_query_char(char c) { return !is_valid_uri_query_char(c); } static inline bool is_not_unreserved_uri_query_char(char c) { return !is_unreserved_uri_query_char(c); } template static inline char value_to_hexchar(Value v) { v >>= pos * 4; v &= 0xf; if (v < 0xA) return '0' + v; else return 'A' + v - 0xA; } template static inline std::string::const_iterator uri_string_copy_until(std::string::const_iterator first, std::string::const_iterator last, std::string& result, Ftor check) { std::string::const_iterator next = std::find_if(first, last, check); result = std::string(first, next); return next; } static inline void uri_parse_throw_error(const char* error_msg, char invalid_char) { std::string error_str = std::string(error_msg); error_str += value_to_hexchar<1>(invalid_char); error_str += value_to_hexchar<0>(invalid_char); throw uri_error(error_str); } void uri_parse_str(std::string uri, uri_state& state) { if (state.state != uri_state::state_empty) throw uri_error("uri_state.state is not uri_state::state_empty"); state.uri.swap(uri); state.state = uri_state::state_invalid; std::string::const_iterator first = state.uri.begin(); std::string::const_iterator last = state.uri.end(); // Parse scheme: first = uri_string_copy_until(first, last, state.scheme, &is_not_unreserved_uri_char); if (first == last) goto uri_parse_success; if (*first++ != ':') uri_parse_throw_error("could not find ':' after scheme, found character 0x", *--first); // Parse resource: first = uri_string_copy_until(first, last, state.resource, &is_not_unreserved_uri_char); if (first == last) goto uri_parse_success; if (*first++ != '?') uri_parse_throw_error("could not find '?' after resource, found character 0x", *--first); // Parse query: first = uri_string_copy_until(first, last, state.query, &is_not_valid_uri_query_char); if (first == last) goto uri_parse_success; if (*first++ != '#') uri_parse_throw_error("could not find '#' after query, found character 0x", *--first); uri_parse_success: state.state = uri_state::state_valid; return; } void uri_parse_c_str(const char* uri, uri_state& state) { uri_parse_str(std::string(uri), state); } // * Letters (A-Z and a-z), numbers (0-9) and the characters // '.','-','~' and '_' are left as-is // * SPACE is encoded as '+' or "%20" // * All other characters are encoded as %HH hex representation with // any non-ASCII characters first encoded as UTF-8 (or other // specified encoding) void uri_parse_query_str(std::string query, uri_query_state& state) { if (state.state != uri_query_state::state_empty) throw uri_error("uri_query_state.state is not uri_query_state::state_empty"); state.query.swap(query); state.state = uri_state::state_invalid; std::string::const_iterator first = state.query.begin(); std::string::const_iterator last = state.query.end(); while (first != last) { std::string element; first = uri_string_copy_until(first, last, element, &is_not_unreserved_uri_query_char); if (first != last && *first++ != '&') { std::string invalid_hex; invalid_hex += value_to_hexchar<1>(*--first); invalid_hex += value_to_hexchar<0>(*first); throw uri_error("query element contains invalid character 0x" + invalid_hex); } state.elements.push_back(element); } state.state = uri_state::state_valid; } std::string uri_generate_scrape_url(std::string uri) { size_t delim_slash = uri.rfind('/'); if (delim_slash == std::string::npos || uri.find("/announce", delim_slash) != delim_slash) throw input_error("Tried to make scrape url from invalid uri."); return uri.replace(delim_slash, sizeof("/announce") - 1, "/scrape"); } bool uri_can_scrape(const std::string& uri) { // TODO: Replace with uri parsers above. size_t delim_slash = uri.rfind('/'); if (delim_slash == std::string::npos) return false; // TODO: This should be more robust. return uri.find("/announce", delim_slash) == delim_slash; } bool uri_has_query(const std::string& uri) { // TODO: Replace with uri parsers above. size_t delim_options = uri.rfind('?'); if (delim_options == std::string::npos) return false; return uri.find('/', delim_options) == std::string::npos; } int uri_detect_numeric(const std::string& uri) { CURLU *url = curl_url(); char *host; if (curl_url_set(url, CURLUPART_URL, uri.c_str(), 0) != CURLUE_OK) { curl_url_cleanup(url); return AF_UNSPEC; } if (curl_url_get(url, CURLUPART_HOST, &host, 0) != CURLUE_OK) { curl_url_cleanup(url); return AF_UNSPEC; } char buf[16]; int family = AF_UNSPEC; size_t host_len = strlen(host); if (host_len >= 2 && host[0] == '[' && host[host_len - 1] == ']') { host[host_len - 1] = '\0'; if (::inet_pton(AF_INET6, host + 1, buf) == 1) family = AF_INET6; } else { if (::inet_pton(AF_INET, host, buf) == 1) family = AF_INET; } curl_free(host); curl_url_cleanup(url); return family; } std::string uri_escape_html(const char* first, const char* last) { std::string result; result.reserve(std::distance(first, last) * 3); while (first != last) { if ((*first >= 'A' && *first <= 'Z') || (*first >= 'a' && *first <= 'z') || (*first >= '0' && *first <= '9') || *first == '-') { result.push_back(*first); } else { result.push_back('%'); result.push_back(value_to_hexchar<1>(*first)); result.push_back(value_to_hexchar<0>(*first)); } ++first; } return result; } } // namespace torrent::utils libtorrent-0.16.11/src/torrent/utils/file_stat.h0000644000000000000000000000351715175073411015254 #ifndef TORRENT_UTILS_FILE_STAT_H #define TORRENT_UTILS_FILE_STAT_H #include #include #include namespace torrent::utils { class FileStat { public: bool update(int fd) { return fstat(fd, &m_stat) == 0; } bool update(const char* filename) { return stat(filename, &m_stat) == 0; } bool update(const std::string& filename) { return update(filename.c_str()); } bool update_link(const char* filename) { return lstat(filename, &m_stat) == 0; } bool update_link(const std::string& filename) { return update_link(filename.c_str()); } bool is_regular() const { return S_ISREG(m_stat.st_mode); } bool is_directory() const { return S_ISDIR(m_stat.st_mode); } bool is_character() const { return S_ISCHR(m_stat.st_mode); } bool is_block() const { return S_ISBLK(m_stat.st_mode); } bool is_fifo() const { return S_ISFIFO(m_stat.st_mode); } bool is_link() const { return S_ISLNK(m_stat.st_mode); } bool is_socket() const { return S_ISSOCK(m_stat.st_mode); } off_t size() const { return m_stat.st_size; } time_t access_time() const { return m_stat.st_atime; } time_t change_time() const { return m_stat.st_ctime; } time_t modified_time() const { return m_stat.st_mtime; } private: struct stat m_stat; }; } // namespace torrent::utils #endif // TORRENT_UTILS_FILE_STAT_H libtorrent-0.16.11/src/torrent/utils/random.h0000644000000000000000000000103715175073411014555 #ifndef LIBTORRENT_TORRENT_UTILS_RANDOM_H #define LIBTORRENT_TORRENT_UTILS_RANDOM_H #include #include #include namespace torrent { [[gnu::weak]] LIBTORRENT_EXPORT uint16_t random_uniform_uint16(uint16_t min = std::numeric_limits::min(), uint16_t max = std::numeric_limits::max()); [[gnu::weak]] LIBTORRENT_EXPORT uint32_t random_uniform_uint32(uint32_t min = std::numeric_limits::min(), uint32_t max = std::numeric_limits::max()); } // namespace torrent #endif libtorrent-0.16.11/src/torrent/utils/log_buffer.cc0000644000000000000000000000214515175073411015546 #include "config.h" #include "log_buffer.h" #include #include "log.h" namespace torrent { // Rename function/args? log_buffer::const_iterator log_buffer::find_older(int32_t older_than) { if (empty() || !back().is_younger_than(older_than)) return end(); return std::find_if(begin(), end(), [older_than](const auto& entry) { return entry.is_younger_or_same(older_than); }); } void log_buffer::lock_and_push_log(const char* data, size_t length, int group) { if (group < 0) return; lock(); if (size() >= max_size()) base_type::pop_front(); base_type::push_back(log_entry(this_thread::cached_seconds().count(), group % 6, std::string(data, length))); if (m_slot_update) m_slot_update(); unlock(); } static void log_buffer_deleter(log_buffer* lb) { delete lb; } log_buffer_ptr log_open_log_buffer(const char* name) { // TODO: Deregister when deleting. auto buffer = log_buffer_ptr(new log_buffer, &log_buffer_deleter); log_open_output(name, [b = buffer.get()](auto d, auto l, auto g) { b->lock_and_push_log(d, l, g); }); return buffer; } } // namespace torrent libtorrent-0.16.11/src/torrent/utils/string_manip.cc0000644000000000000000000000515715175073411016134 #include "config.h" #include "torrent/utils/string_manip.h" #include #include #include "torrent/common.h" namespace torrent::utils { std::string_view trim_spaces(std::string_view s) { auto first = std::find_if(s.begin(), s.end(), [](unsigned char ch) { return ch != ' ' && ch != '\t' && ch != '\n' && ch != '\r' && ch != '\f' && ch != '\v'; }); auto last = std::find_if(s.rbegin(), std::make_reverse_iterator(first), [](unsigned char ch) { return ch != ' ' && ch != '\t' && ch != '\n' && ch != '\r' && ch != '\f' && ch != '\v'; }).base(); if (first >= last) return std::string_view(); return std::string_view(first, last - first); } std::string trim_spaces_str(std::string_view s) { return std::string(trim_spaces(s)); } std::string string_with_escape_codes(const std::string& str) { std::string result; for (auto c : str) { if (c < ' ' || c > '~') { result += '%'; result += value_to_hex1(c); result += value_to_hex0(c); continue; } result += c; } return result; } std::string sanitize_string(const std::string& str) { std::string result; bool unprintable{}; bool space{}; for (auto c : str) { if (c < ' ' || c > '~') { if (c == '\n' || c == '\r' || c == '\t') { if (!space && !unprintable) result += ' '; space = true; continue; } if (!unprintable) result += '*'; unprintable = true; space = false; continue; } result += c; unprintable = false; space = false; } return trim_spaces_str(result); } std::string sanitize_string_with_escape_codes(const std::string& str) { std::string result; bool space{}; for (auto c : str) { if (c < ' ' || c > '~') { if (c == '\n' || c == '\r' || c == '\t') { if (!space) result += ' '; space = true; continue; } result += '%'; result += value_to_hex1(c); result += value_to_hex0(c); space = false; continue; } result += c; space = false; } return trim_spaces_str(result); } std::string sanitize_string_with_tags(const std::string& str) { bool in_tag{}; std::string result; std::string sanitized = sanitize_string(str); for (auto c : sanitized) { if (c == '>') { in_tag = false; continue; } if (in_tag || c == '<') { in_tag = true; continue; } result += c; } result = trim_spaces_str(result); if (result.empty()) return trim_spaces_str(sanitized); return result; } } // namespace torrent::utils libtorrent-0.16.11/src/torrent/utils/log.h0000644000000000000000000001521015175073411014054 #ifndef LIBTORRENT_UTILS_LOG_H #define LIBTORRENT_UTILS_LOG_H #include #include #include #include #include #include namespace torrent { // TODO: Add option_strings support. enum { LOG_CRITICAL, LOG_ERROR, LOG_WARN, LOG_NOTICE, LOG_INFO, LOG_DEBUG, LOG_PEER_CRITICAL, LOG_PEER_ERROR, LOG_PEER_WARN, LOG_PEER_NOTICE, LOG_PEER_INFO, LOG_PEER_DEBUG, // TODO: Deprecate, not used. LOG_SOCKET_CRITICAL, LOG_SOCKET_ERROR, LOG_SOCKET_WARN, LOG_SOCKET_NOTICE, LOG_SOCKET_INFO, LOG_SOCKET_DEBUG, LOG_STORAGE_CRITICAL, LOG_STORAGE_ERROR, LOG_STORAGE_WARN, LOG_STORAGE_NOTICE, LOG_STORAGE_INFO, LOG_STORAGE_DEBUG, LOG_THREAD_CRITICAL, LOG_THREAD_ERROR, LOG_THREAD_WARN, LOG_THREAD_NOTICE, LOG_THREAD_INFO, LOG_THREAD_DEBUG, LOG_TORRENT_CRITICAL, LOG_TORRENT_ERROR, LOG_TORRENT_WARN, LOG_TORRENT_NOTICE, LOG_TORRENT_INFO, LOG_TORRENT_DEBUG, LOG_NON_CASCADING, LOG_CONNECTION, LOG_CONNECTION_BIND, LOG_CONNECTION_FD, LOG_CONNECTION_FILTER, LOG_CONNECTION_HANDSHAKE, LOG_CONNECTION_LISTEN, LOG_DHT, LOG_DHT_ALL, LOG_DHT_ERROR, LOG_DHT_CONTROLLER, LOG_DHT_NODE, LOG_DHT_ROUTER, LOG_DHT_SERVER, LOG_INSTRUMENTATION_MEMORY, LOG_INSTRUMENTATION_MINCORE, LOG_INSTRUMENTATION_CHOKE, LOG_INSTRUMENTATION_POLLING, LOG_INSTRUMENTATION_TRANSFERS, LOG_MOCK_CALLS, LOG_NET_DNS, LOG_NET_SOCKET, LOG_PEER_LIST_EVENTS, LOG_PEER_LIST_ADDRESS, LOG_PROTOCOL_PIECE_EVENTS, LOG_PROTOCOL_METADATA_EVENTS, LOG_PROTOCOL_NETWORK_ERRORS, LOG_PROTOCOL_STORAGE_ERRORS, LOG_RESUME_DATA, LOG_RPC_EVENTS, LOG_RPC_DUMP, LOG_SESSION_EVENTS, LOG_STORAGE, LOG_SYSTEM, LOG_TRACKER_DUMP, LOG_TRACKER_EVENTS, LOG_TRACKER_REQUESTS, LOG_UI_EVENTS, LOG_GROUP_MAX_SIZE }; #define lt_log_is_valid(log_group) (torrent::log_groups[log_group].valid()) #define lt_log_print(log_group, ...) \ { if (torrent::log_groups[log_group].valid()) \ torrent::log_groups[log_group].internal_print(NULL, NULL, NULL, 0, __VA_ARGS__); } #define lt_log_print_hash(log_group, log_hash, log_subsystem, ...) \ { if (torrent::log_groups[log_group].valid()) \ torrent::log_groups[log_group].internal_print(&log_hash, log_subsystem, NULL, 0, __VA_ARGS__); } #define lt_log_print_info(log_group, log_info, log_subsystem, ...) \ { if (torrent::log_groups[log_group].valid()) \ torrent::log_groups[log_group].internal_print(&log_info->hash(), log_subsystem, NULL, 0, __VA_ARGS__); } #define lt_log_print_data(log_group, log_data, log_subsystem, ...) \ { if (torrent::log_groups[log_group].valid()) \ torrent::log_groups[log_group].internal_print(&log_data->hash(), log_subsystem, NULL, 0, __VA_ARGS__); } #define lt_log_print_dump(log_group, log_dump_data, log_dump_size, ...) \ { if (torrent::log_groups[log_group].valid()) \ torrent::log_groups[log_group].internal_print(NULL, NULL, log_dump_data, log_dump_size, __VA_ARGS__); } #define lt_log_print_hash_dump(log_group, log_dump_data, log_dump_size, log_hash, log_subsystem, ...) \ { if (torrent::log_groups[log_group].valid()) \ torrent::log_groups[log_group].internal_print(&log_hash, log_subsystem, log_dump_data, log_dump_size, __VA_ARGS__); } #define lt_log_print_info_dump(log_group, log_dump_data, log_dump_size, log_info, log_subsystem, ...) \ { if (torrent::log_groups[log_group].valid()) \ torrent::log_groups[log_group].internal_print(&log_info->hash(), log_subsystem, log_dump_data, log_dump_size, __VA_ARGS__); } #define lt_log_print_subsystem(log_group, log_subsystem, ...) \ { if (torrent::log_groups[log_group].valid()) \ torrent::log_groups[log_group].internal_print(NULL, log_subsystem, NULL, 0, __VA_ARGS__); } using log_slot = std::function; class LIBTORRENT_EXPORT log_group { public: using outputs_type = std::bitset<64>; log_group() { m_outputs.reset(); m_cached_outputs.reset(); } bool valid() const { return m_first != NULL; } bool empty() const { return m_first == NULL; } size_t size_outputs() const { return std::distance(m_first, m_last); } static size_t max_size_outputs() { return 64; } // // Internal: // void internal_print(const HashString* hash, const char* subsystem, const void* dump_data, size_t dump_size, const char* fmt, ...); const outputs_type& outputs() const { return m_outputs; } const outputs_type& cached_outputs() const { return m_cached_outputs; } void clear_cached_outputs() { m_cached_outputs = m_outputs; } void set_outputs(const outputs_type& val) { m_outputs = val; } void set_cached_outputs(const outputs_type& val) { m_cached_outputs = val; } void set_output_at(size_t index, bool val) { m_outputs[index] = val; } void set_cached(log_slot* f, log_slot* l) { m_first = f; m_last = l; } private: outputs_type m_outputs; outputs_type m_cached_outputs; log_slot* m_first{}; log_slot* m_last{}; }; using log_group_list = std::array; using log_output_list = std::vector>; extern log_group_list log_groups LIBTORRENT_EXPORT; extern log_output_list log_outputs LIBTORRENT_EXPORT; void log_initialize() LIBTORRENT_EXPORT; void log_cleanup() LIBTORRENT_EXPORT; void log_open_output(const char* name, const log_slot& slot) LIBTORRENT_EXPORT; void log_close_output(const char* name) LIBTORRENT_EXPORT; void log_close_output_str(const std::string& name) LIBTORRENT_EXPORT; void log_add_group_output(int group, const char* name) LIBTORRENT_EXPORT; void log_remove_group_output(int group, const char* name) LIBTORRENT_EXPORT; void log_add_child(int group, int child) LIBTORRENT_EXPORT; void log_remove_child(int group, int child) LIBTORRENT_EXPORT; void log_open_file_output(const char* name, const char* filename, bool append = false, bool flush = false) LIBTORRENT_EXPORT; void log_open_gz_file_output(const char* name, const char* filename, bool append = false) LIBTORRENT_EXPORT; // // Implementation: // inline void log_close_output_str(const std::string& name) { log_close_output(name.c_str()); } } // namespace torrent #endif libtorrent-0.16.11/src/torrent/utils/resume.h0000644000000000000000000000670215175073411014601 // libTorrent - BitTorrent library // Copyright (C) 2005-2011, Jari Sundell // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // In addition, as a special exception, the copyright holders give // permission to link the code of portions of this program with the // OpenSSL library under certain conditions as described in each // individual source file, and distribute linked combinations // including the two. // // You must obey the GNU General Public License in all respects for // all of the code used other than OpenSSL. If you modify file(s) // with this exception, you may extend this exception to your version // of the file(s), but you are not obligated to do so. If you do not // wish to do so, delete this exception statement from your version. // If you delete this exception statement from all source files in the // program, then also delete it here. // // Contact: Jari Sundell // // Skomakerveien 33 // 3185 Skoppum, NORWAY // Various functions for loading and saving various states of a // download to an Object. // // These functions use only the public interface, and thus the client // may choose to replace these with their own resume code. // Should propably move this into a sub-directory. #ifndef LIBTORRENT_UTILS_RESUME_H #define LIBTORRENT_UTILS_RESUME_H #include namespace torrent { // When saving resume data for a torrent that is currently active, set // 'onlyCompleted' to ensure that a crash, etc, will cause incomplete // files to be hashed. void resume_load_progress(Download download, const Object& object) LIBTORRENT_EXPORT; void resume_save_progress(Download download, Object& object) LIBTORRENT_EXPORT; void resume_clear_progress(Download download, Object& object) LIBTORRENT_EXPORT; bool resume_load_bitfield(Download download, const Object& object) LIBTORRENT_EXPORT; void resume_save_bitfield(Download download, Object& object) LIBTORRENT_EXPORT; // Do not call 'resume_load_uncertain_pieces' directly. void resume_load_uncertain_pieces(Download download, const Object& object) LIBTORRENT_EXPORT; void resume_save_uncertain_pieces(Download download, Object& object) LIBTORRENT_EXPORT; bool resume_check_target_files(Download download, const Object& object) LIBTORRENT_EXPORT; void resume_load_file_priorities(Download download, const Object& object) LIBTORRENT_EXPORT; void resume_save_file_priorities(Download download, Object& object) LIBTORRENT_EXPORT; void resume_load_addresses(Download download, const Object& object) LIBTORRENT_EXPORT; void resume_save_addresses(Download download, Object& object) LIBTORRENT_EXPORT; void resume_load_tracker_settings(Download download, const Object& object) LIBTORRENT_EXPORT; void resume_save_tracker_settings(Download download, Object& object) LIBTORRENT_EXPORT; } // namespace torrent #endif libtorrent-0.16.11/src/torrent/utils/signal_bitfield.cc0000644000000000000000000000236415175073411016556 #include "config.h" #include "signal_bitfield.h" #include #include "torrent/exceptions.h" namespace torrent { // Only the thread owning this signal bitfield should add signals. unsigned int signal_bitfield::add_signal(const slot_type& slot) { if (m_thread_id != std::this_thread::get_id()) throw internal_error("signal_bitfield::add_signal(...): Only the owning thread can add signals."); if (m_size >= max_size) throw internal_error("signal_bitfield::add_signal(...): No more available slots."); if (!slot) throw internal_error("signal_bitfield::add_signal(...): Cannot add empty slot."); unsigned int index = m_size++; m_slots[index] = slot; return index; } void signal_bitfield::work() { // static_assert(std::atomic()::is_always_lock_free(), "signal_bitfield::work(...): Bitfield type is not lockfree."); if (m_thread_id != std::this_thread::get_id()) throw internal_error("signal_bitfield::work(...): Only the owning thread can do work for signal bitfields."); auto bitfield = m_bitfield.exchange(0); for (unsigned int i = 0; bitfield != 0 && i < m_size; i++) { if ((bitfield & (1 << i))) { m_slots[i](); bitfield = bitfield & ~(1 << i); } } } } // namespace torrent libtorrent-0.16.11/src/torrent/utils/extents.h0000644000000000000000000001342615175073411014774 #ifndef LIBTORRENT_UTILS_EXTENTS_H #define LIBTORRENT_UTILS_EXTENTS_H #include #include namespace torrent { template > class extents { public: using key_type = Address; // start address using mapped_value_type = Value; // The value mapped to the ip range using mapped_type = std::pair; // End address, value mapped to ip range using range_map_type = std::map; // The map itself void insert(key_type address_start, key_type address_end, mapped_value_type value); bool defined(key_type address_start, key_type address_end); bool defined(key_type address); key_type get_matching_key(key_type address_start, key_type address_end); // throws error on not defined. test with defined() mapped_value_type at(key_type address_start, key_type address_end); // throws error on not defined. test with defined() mapped_value_type at(key_type address); // throws error on not defined. test with defined() unsigned int sizeof_data() const; range_map_type range_map; }; ////////////////////////////////////////////////////////////////////////////////// // INSERT O(log N) assuming no overlapping ranges ///////////////////////////////////////////////////////////////////////////////// template void extents::insert(key_type address_start, key_type address_end, mapped_value_type value) { //we allow overlap ranges though not 100% overlap but only if mapped values are the same. first remove any overlap range that has a different value. typename range_map_type::iterator iter = range_map.upper_bound(address_start); if( iter != range_map.begin() ) { iter--; } bool ignore_due_to_total_overlap = false; while( iter->first <= address_end && iter != range_map.end() ) { key_type delete_key = iter->first; bool do_delete_due_to_overlap = iter->first <= address_end && (iter->second).first >= address_start && (iter->second).second != value; bool do_delete_due_to_total_overlap = address_start <= iter->first && address_end >= (iter->second).first; iter++; if(do_delete_due_to_overlap || do_delete_due_to_total_overlap) { range_map.erase (delete_key); } else if (iter != range_map.end()) { ignore_due_to_total_overlap = ignore_due_to_total_overlap || ( iter->first <= address_start && (iter->second).first >= address_end ); } } if(!ignore_due_to_total_overlap) { mapped_type entry; entry.first = address_end; entry.second = value; range_map.insert( std::pair(address_start, entry) ); } } ////////////////////////////////////////////////////////////////////// // DEFINED O(log N) assuming no overlapping ranges ////////////////////////////////////////////////////////////////////// template bool extents::defined(key_type address_start, key_type address_end) { bool defined = false; auto iter = range_map.upper_bound(address_start); if( iter != range_map.begin() ) { iter--; } while( iter->first <= address_end && !defined && iter != range_map.end() ) { defined = iter->first <= address_end && (iter->second).first >= address_start; iter++; } return defined; } template bool extents::defined(key_type address) { return defined(address, address); } ////////////////////////////////////////////////////////////////////// // GET_MATCHING_KEY O(log N) assuming no overlapping ranges ////////////////////////////////////////////////////////////////////// template typename extents::key_type extents::get_matching_key(key_type address_start, key_type address_end) { key_type key{}; bool defined = false; auto iter = range_map.upper_bound(address_start); if( iter != range_map.begin() ) { iter--; } while( iter->first <= address_end && !defined && iter != range_map.end() ) { defined = iter->first <= address_end && (iter->second).first >= address_start; if(defined) key = iter->first; iter++; } // this will cause exception to be thrown if(!defined) { std::out_of_range e("nothing defined for specified key"); throw e; } return key; } ////////////////////////////////////////////////////////////////////// // AT O(log N) assuming no overlapping ranges ////////////////////////////////////////////////////////////////////// template typename extents::mapped_value_type extents::at(key_type address_start, key_type address_end) { key_type key = get_matching_key(address_start, address_end); mapped_type entry = range_map.at(key); return entry.second; } template typename extents::mapped_value_type extents::at(key_type address) { return at(address, address); } ////////////////////////////////////////////////////////////////////// // SIZEOF_DATA O(1) ////////////////////////////////////////////////////////////////////// template unsigned int extents::sizeof_data() const { // we don't know overhead on map, so this won't be accurate. just estimate. unsigned int entry_size = sizeof(key_type) + sizeof(mapped_type); return entry_size * range_map.size(); } } // namespace torrent #endif libtorrent-0.16.11/src/torrent/utils/string_manip.h0000644000000000000000000002256015175073411015773 #ifndef LIBTORRENT_TORRENT_UTILS_STRING_MANIP_H #define LIBTORRENT_TORRENT_UTILS_STRING_MANIP_H #include #include #include #include #include namespace torrent::utils { // TODO: Add a copy_escape_html() version that copies to a perfect sized std::string. // TODO: Consider forward declaring these functions, and instantiating the required specializations in the .cc file. std::string_view trim_spaces(std::string_view s) LIBTORRENT_EXPORT; std::string trim_spaces_str(std::string_view s) LIBTORRENT_EXPORT; std::string string_with_escape_codes(const std::string& str) LIBTORRENT_EXPORT; std::string sanitize_string(const std::string& str) LIBTORRENT_EXPORT; std::string sanitize_string_with_escape_codes(const std::string& str) LIBTORRENT_EXPORT; std::string sanitize_string_with_tags(const std::string& str) LIBTORRENT_EXPORT; char hex_to_value_or_zero(char c); char hex_to_value_or_error(char c); char value_to_hex0(char value); char value_to_hex1(char value); template std::string copy_escape_html_str(const Container& src); template std::string copy_escape_html_str(SrcItr src_first, SrcItr src_last); template DestItr copy_escape_html(SrcItr src_first, SrcItr src_last, DestItr dst_first, DestItr dst_last); template DestItr copy_escape_html(const SrcContainer& src, DestItr dst_first, DestItr dst_last); template typename DstContainer::iterator copy_escape_html(const SrcContainer& src, DstContainer& dst); template typename DstContainer::iterator copy_escape_html(SrcItr src_first, SrcItr src_last, DstContainer& dst); template DestItr transform_from_hex(SrcItr src_first, SrcItr src_last, DestItr dst_first, DestItr dst_last); template DestItr transform_from_hex(const SrcContainer& src, DestItr dst_first, DestItr dst_last); template typename DstContainer::iterator transform_from_hex(const SrcContainer& src, DstContainer& dst); template typename DstContainer::iterator transform_from_hex(SrcItr src_first, SrcItr src_last, DstContainer& dst); template DestItr transform_to_hex(SrcItr src_first, SrcItr src_last, DestItr dst_first, DestItr dst_last); template DestItr transform_to_hex(const SrcContainer& src, DestItr dst_first, DestItr dst_last); template typename DstContainer::iterator transform_to_hex(const SrcContainer& src, DstContainer& dst); template typename DstContainer::iterator transform_to_hex(SrcItr src_first, SrcItr src_last, DstContainer& dst); template std::string transform_to_hex_str(const Container& src); template std::string transform_to_hex_str(SrcItr src_first, SrcItr src_last); // // Conversion between hex char and value. // // Could optimize this abit. inline char hex_to_value_or_zero(char c) { if (c >= '0' && c <= '9') return c - '0'; if (c >= 'A' && c <= 'F') return 10 + c - 'A'; if (c >= 'a' && c <= 'f') return 10 + c - 'a'; return 0; } inline char hex_to_value_or_error(char c) { if (c >= '0' && c <= '9') return c - '0'; if (c >= 'A' && c <= 'F') return 10 + c - 'A'; if (c >= 'a' && c <= 'f') return 10 + c - 'a'; return -1; } inline char value_to_hex0(char value) { value = value & 0x0f; if (value < 10) return '0' + value; return 'A' + (value - 10); } inline char value_to_hex1(char value) { value = (value >> 4) & 0x0f; if (value < 10) return '0' + value; return 'A' + (value - 10); } // // Escape all characters that are not alphanumeric or '-' with %XX. // template std::string copy_escape_html_str(const Container& src) { return copy_escape_html_str(src.begin(), src.end()); } template std::string copy_escape_html_str(SrcItr src_first, SrcItr src_last) { std::string dest; dest.reserve(std::distance(src_first, src_last) * 3); while (src_first != src_last) { if ((*src_first >= 'A' && *src_first <= 'Z') || (*src_first >= 'a' && *src_first <= 'z') || (*src_first >= '0' && *src_first <= '9') || *src_first == '-') { dest += *src_first; } else { dest += '%'; dest += value_to_hex1(*src_first); dest += value_to_hex0(*src_first); } ++src_first; } return dest; } template DestItr copy_escape_html(SrcItr src_first, SrcItr src_last, DestItr dst_first, DestItr dst_last) { while (src_first != src_last) { if ((*src_first >= 'A' && *src_first <= 'Z') || (*src_first >= 'a' && *src_first <= 'z') || (*src_first >= '0' && *src_first <= '9') || *src_first == '-') { if (dst_first == dst_last) break; else *(dst_first++) = *src_first; } else { if (dst_first == dst_last) break; else *(dst_first++) = '%'; if (dst_first == dst_last) break; else *(dst_first++) = value_to_hex1(*src_first); if (dst_first == dst_last) break; else *(dst_first++) = value_to_hex0(*src_first); } ++src_first; } return dst_first; } template DestItr copy_escape_html(const SrcContainer& src, DestItr dst_first, DestItr dst_last) { return copy_escape_html(src.begin(), src.end(), dst_first, dst_last); } template typename DstContainer::iterator copy_escape_html(const SrcContainer& src, DstContainer& dst) { return copy_escape_html(src.begin(), src.end(), dst.begin(), dst.end()); } template typename DstContainer::iterator copy_escape_html(SrcItr src_first, SrcItr src_last, DstContainer& dst) { return copy_escape_html(src_first, src_last, dst.begin(), dst.end()); } // // Transform a sequence of bytes from/to a hex string. // template DestItr transform_from_hex(SrcItr src_first, SrcItr src_last, DestItr dst_first, DestItr dst_last) { auto dst_first_start = dst_first; while (src_first != src_last) { if (dst_first == dst_last) break; char high = hex_to_value_or_error(*src_first++); if (src_first == src_last) break; if (dst_first == dst_last || high == -1) return dst_first_start; char low = hex_to_value_or_error(*src_first++); if (dst_first == dst_last || low == -1) return dst_first_start; *dst_first++ = (high << 4) + low; } if (src_first != src_last) return dst_first_start; return dst_first; } template DestItr transform_from_hex(const SrcContainer& src, DestItr dst_first, DestItr dst_last) { return transform_from_hex(src.begin(), src.end(), dst_first, dst_last); } template typename DstContainer::iterator transform_from_hex(const SrcContainer& src, DstContainer& dst) { return transform_from_hex(src.begin(), src.end(), dst.begin(), dst.end()); } template typename DstContainer::iterator transform_from_hex(SrcItr src_first, SrcItr src_last, DstContainer& dst) { return transform_from_hex(src_first, src_last, dst.begin(), dst.end()); } template DestItr transform_to_hex(SrcItr src_first, SrcItr src_last, DestItr dst_first, DestItr dst_last) { if (std::distance(src_first, src_last) * 2 != std::distance(dst_first, dst_last)) throw internal_error("transform_to_hex() incorrect destination size"); while (src_first != src_last) { if (dst_first == dst_last) break; *(dst_first++) = value_to_hex1(*src_first); if (dst_first == dst_last) break; *(dst_first++) = value_to_hex0(*src_first); ++src_first; } return dst_first; } template DestItr transform_to_hex(const SrcContainer& src, DestItr dst_first, DestItr dst_last) { return transform_to_hex(src.begin(), src.end(), dst_first, dst_last); } template typename DstContainer::iterator transform_to_hex(const SrcContainer& src, DstContainer& dst) { return transform_to_hex(src.begin(), src.end(), dst.begin(), dst.end()); } template typename DstContainer::iterator transform_to_hex(SrcItr src_first, SrcItr src_last, DstContainer& dst) { return transform_to_hex(src_first, src_last, dst.begin(), dst.end()); } template std::string transform_to_hex_str(const Container& src) { return transform_to_hex_str(src.begin(), src.end()); } template std::string transform_to_hex_str(SrcItr src_first, SrcItr src_last) { std::string dest; dest.reserve(std::distance(src_first, src_last) * 2); while (src_first != src_last) { dest += value_to_hex1(*src_first); dest += value_to_hex0(*src_first); ++src_first; } return dest; } } // namespace torrent::utils #endif // LIBTORRENT_TORRENT_UTILS_STRING_MANIP_H libtorrent-0.16.11/src/torrent/utils/ranges.h0000644000000000000000000001370615175073411014562 #ifndef LIBTORRENT_UTILS_RANGES_H #define LIBTORRENT_UTILS_RANGES_H #include #include namespace torrent { template class ranges : private std::vector > { public: using base_type = std::vector>; using bound_type = RangesType; using value_type = typename base_type::value_type; using reference = typename base_type::reference; using iterator = typename base_type::iterator; using const_iterator = typename base_type::const_iterator; using reverse_iterator = typename base_type::reverse_iterator; using base_type::clear; using base_type::empty; using base_type::size; using base_type::begin; using base_type::end; using base_type::rbegin; using base_type::rend; using base_type::front; using base_type::back; void insert(bound_type first, bound_type last) { insert(std::make_pair(first, last)); } void erase(bound_type first, bound_type last) { erase(std::make_pair(first, last)); } void insert(value_type r); void erase(value_type r); // Find the first ranges that has an end greater than index. iterator find(bound_type index); const_iterator find(bound_type index) const; // Use find with no closest match. bool has(bound_type index) const; size_t intersect_distance(bound_type first, bound_type last) const; size_t intersect_distance(value_type range) const; static ranges create_union(const ranges& left, const ranges& right); }; template void ranges::insert(value_type r) { if (r.first >= r.second) return; auto first = std::find_if(begin(), end(), [r](const value_type v) { return r.first <= v.second; }); if (first == end() || r.second < first->first) { // The new range is before the first, after the last or between // two ranges. base_type::insert(first, r); } else { first->first = std::min(r.first, first->first); first->second = std::max(r.second, first->second); auto last = std::find_if(first, end(), [first](const value_type v) { return first->second < v.second; }); if (last != end() && first->second >= last->first) first->second = (last++)->second; base_type::erase(first + 1, last); } } template void ranges::erase(value_type r) { if (r.first >= r.second) return; auto first = std::find_if(begin(), end(), [r](const value_type v) { return r.first < v.second; }); auto last = std::find_if(first, end(), [r](const value_type v) { return r.second < v.second; }); if (first == end()) return; if (first == last) { if (r.first > first->first) { std::swap(first->first, r.second); base_type::insert(first, value_type(r.second, r.first)); } else if (r.second > first->first) { first->first = r.second; } } else { if (r.first > first->first) (first++)->second = r.first; if (last != end() && r.second > last->first) last->first = r.second; base_type::erase(first, last); } } // Find the first ranges that has an end greater than index. template inline typename ranges::iterator ranges::find(bound_type index) { return std::find_if(begin(), end(), [index](const value_type v) { return index < v.second; }); } template inline typename ranges::const_iterator ranges::find(bound_type index) const { return std::find_if(begin(), end(), [index](const value_type v) { return index < v.second; }); } // Use find with no closest match. template bool ranges::has(bound_type index) const { auto itr = find(index); return itr != end() && index >= itr->first; } template size_t ranges::intersect_distance(bound_type first, bound_type last) const { return intersect_distance(std::make_pair(first, last)); } // The total length of all the extents within the bounds of 'range'. template size_t ranges::intersect_distance(value_type range) const { auto first = find(range.first); if (first == end() || range.second <= first->first) return 0; size_t dist = std::min(range.second, first->second) - std::max(range.first, first->first); while (++first != end() && range.second > first->first) dist += std::min(range.second, first->second) - first->first; return dist; } template ranges ranges::create_union(const ranges& left, const ranges& right) { if (left.empty()) return right; if (right.empty()) return left; ranges result; auto left_itr = left.begin(); auto left_last = left.end(); auto right_itr = right.begin(); auto right_last = right.end(); if (left_itr->first < right_itr->first) result.base_type::push_back(*left_itr++); else result.base_type::push_back(*right_itr++); while (left_itr != left_last && right_itr != right_last) { value_type next; if (left_itr->first < right_itr->first) next = *left_itr++; else next = *right_itr++; if (next.first <= result.back().second) result.back().second = std::max(next.second, result.back().second); else result.base_type::push_back(next); } // Only one of these while loops will be triggered. for (; left_itr != left_last; left_itr++) { if (left_itr->first <= result.back().second) result.back().second = std::max(left_itr->second, result.back().second); else result.base_type::push_back(*left_itr); } for (; right_itr != right_last; right_itr++) { if (right_itr->first <= result.back().second) result.back().second = std::max(right_itr->second, result.back().second); else result.base_type::push_back(*right_itr); } return result; } } // namespace torrent #endif libtorrent-0.16.11/src/torrent/utils/resume.cc0000644000000000000000000004661615175073411014747 #include "config.h" #include "resume.h" #include "data/file.h" #include "data/file_list.h" #include "data/transfer_list.h" #include "download/download_main.h" #include "net/address_list.h" #include "peer/peer_info.h" #include "peer/peer_list.h" #include "torrent/common.h" #include "torrent/bitfield.h" #include "torrent/download.h" #include "torrent/download_info.h" #include "torrent/object.h" #include "torrent/tracker/tracker.h" #include "torrent/utils/file_stat.h" #include "torrent/utils/log.h" #include "tracker/tracker_list.h" #define LT_LOG_LOAD(log_fmt, ...) \ lt_log_print_info(LOG_RESUME_DATA, download.info(), "resume_load", log_fmt, __VA_ARGS__); #define LT_LOG_LOAD_INVALID(log_fmt, ...) \ lt_log_print_info(LOG_RESUME_DATA, download.info(), "resume_load", "invalid resume data: " log_fmt, __VA_ARGS__); #define LT_LOG_LOAD_FILE(log_fmt, ...) \ lt_log_print_info(LOG_RESUME_DATA, download.info(), "resume_load", "file[%u]: " log_fmt, \ file_index, __VA_ARGS__); #define LT_LOG_SAVE(log_fmt, ...) \ lt_log_print_info(LOG_RESUME_DATA, download.info(), "resume_save", log_fmt, __VA_ARGS__); #define LT_LOG_SAVE_FILE(log_fmt, ...) \ lt_log_print_info(LOG_RESUME_DATA, download.info(), "resume_save", "file[%u]: " log_fmt, \ file_index, __VA_ARGS__); namespace torrent { void resume_load_progress(Download download, const Object& object) { if (!object.has_key_list("files")) { LT_LOG_LOAD("could not find 'files' key", 0); return; } const Object::list_type& files = object.get_key_list("files"); if (files.size() != download.file_list()->size_files()) { LT_LOG_LOAD_INVALID("number of resumable files does not match files in torrent", 0); return; } if (!resume_load_bitfield(download, object)) return; auto filesItr = files.begin(); FileList* fileList = download.file_list(); for (auto listItr = fileList->begin(), listLast = fileList->end(); listItr != listLast; ++listItr, ++filesItr) { if ( (*listItr)->is_padding()) continue; unsigned int file_index = std::distance(fileList->begin(), listItr); utils::FileStat fs; if (!filesItr->has_key_value("mtime")) { LT_LOG_LOAD_FILE("no mtime found, file:create|resize range:clear|recheck", 0); // If 'mtime' is erased, it means we should start hashing and // downloading the file as if it was a new torrent. (*listItr)->set_flags(File::flag_create_queued | File::flag_resize_queued); download.update_range(Download::update_range_recheck | Download::update_range_clear, (*listItr)->range().first, (*listItr)->range().second); continue; } int64_t mtimeValue = filesItr->get_key_value("mtime"); bool fileExists = fs.update(fileList->root_dir() + (*listItr)->path()->as_string()); // The default action when we have 'mtime' is not to create nor // resize the file. (*listItr)->unset_flags(File::flag_create_queued | File::flag_resize_queued); if (mtimeValue == ~int64_t{0} || mtimeValue == ~int64_t{1}) { // If 'mtime' is ~0 it means we haven't gotten around to // creating the file. // // Else if it is ~1 it means the file doesn't exist nor do we // want to create it. // // When 'mtime' is ~2 we need to recheck the hash without // creating the file. It will just fail on the mtime check // later, so we don't need to handle it explicitly. if (mtimeValue == ~int64_t{0}) { LT_LOG_LOAD_FILE("file not created by client, file:create|resize range:clear|(recheck)", 0); (*listItr)->set_flags(File::flag_create_queued | File::flag_resize_queued); } else { LT_LOG_LOAD_FILE("do not create file, file:- range:clear|(recheck)", 0); } // Ensure the bitfield range is cleared so that stray resume // data doesn't get counted. download.update_range(Download::update_range_clear | (fileExists ? Download::update_range_recheck : 0), (*listItr)->range().first, (*listItr)->range().second); continue; } // If the file is the wrong size, queue resize and clear resume // data for that file. if (static_cast(fs.size()) != (*listItr)->size_bytes()) { if (fs.size() == 0) { LT_LOG_LOAD_FILE("zero-length file found, file:resize range:clear|recheck", 0); } else { LT_LOG_LOAD_FILE("file has the wrong size, file:resize range:clear|recheck", 0); } (*listItr)->set_flags(File::flag_resize_queued); download.update_range(Download::update_range_clear | Download::update_range_recheck, (*listItr)->range().first, (*listItr)->range().second); continue; } // An 'mtime' of ~3 means the resume data was written while the // torrent was actively downloading, and thus we need to recheck // chunks that might not have been completely written to disk. // // This gets handled below, so just skip to the next file. if (mtimeValue == ~int64_t{3}) { LT_LOG_LOAD_FILE("file was downloading", 0); continue; } // An 'mtime' of ~2 indicates that the resume data was made by an // old rtorrent version which does not include 'uncertain_pieces' // field, and thus can't be relied upon. // // If the 'mtime' is an actual mtime we check to see if it matches // the file, else clear the range. This should be set only for // files that have completed and got no indices in // TransferList::completed_list(). if (mtimeValue == ~int64_t{2} || mtimeValue != fs.modified_time()) { LT_LOG_LOAD_FILE("resume data doesn't include uncertain pieces, range:clear|recheck", 0); download.update_range(Download::update_range_clear | Download::update_range_recheck, (*listItr)->range().first, (*listItr)->range().second); continue; } LT_LOG_LOAD_FILE("no recheck needed", 0); } resume_load_uncertain_pieces(download, object); } void resume_save_progress(Download download, Object& object) { // We don't remove the old hash data since it might still be valid, // just that the client didn't finish the check this time. if (!download.is_hash_checked()) { LT_LOG_SAVE("hash not checked, no progress saved", 0); return; } download.sync_chunks(); // If syncing failed, invalidate all resume data and return. if (!download.is_hash_checked()) { LT_LOG_SAVE("sync failed, invalidating resume data", 0); if (!object.has_key_list("files")) return; Object::list_type& files = object.get_key_list("files"); for (auto& file : files) file.insert_key("mtime", ~int64_t{2}); return; } resume_save_bitfield(download, object); auto& files = object.insert_preserve_copy("files", Object::create_list()).first->second.as_list(); auto filesItr = files.begin(); FileList* fileList = download.file_list(); for (auto listItr = fileList->begin(), listLast = fileList->end(); listItr != listLast; ++listItr, ++filesItr) { unsigned int file_index = std::distance(fileList->begin(), listItr); if (filesItr == files.end()) filesItr = files.insert(filesItr, Object::create_map()); else if (!filesItr->is_map()) *filesItr = Object::create_map(); filesItr->insert_key("completed", static_cast((*listItr)->completed_chunks())); utils::FileStat fs; bool fileExists = fs.update(fileList->root_dir() + (*listItr)->path()->as_string()); if (!fileExists) { if ((*listItr)->is_create_queued()) { // ~0 means the file still needs to be created. filesItr->insert_key("mtime", ~int64_t{0}); LT_LOG_SAVE_FILE("file not created, create queued", 0); } else { // ~1 means the file shouldn't be created. filesItr->insert_key("mtime", ~int64_t{1}); LT_LOG_SAVE_FILE("file not created, create not queued", 0); } // } else if ((*listItr)->completed_chunks() == (*listItr)->size_chunks()) { } else if (fileList->bitfield()->is_all_set()) { // Currently only checking if we're finished. This needs to be // smarter when it comes to downloading partial torrents, etc. // This assumes the syncs are properly called before // resume_save_progress gets called after finishing a torrent. filesItr->insert_key("mtime", static_cast(fs.modified_time())); LT_LOG_SAVE_FILE("file completed, mtime:%" PRIi64, (int64_t)fs.modified_time()); } else if (!download.info()->is_active()) { // When stopped, all chunks should have received sync, thus the // file's mtime will be correct. (We hope) filesItr->insert_key("mtime", static_cast(fs.modified_time())); LT_LOG_SAVE_FILE("file inactive and assumed sync'ed, mtime:%" PRIi64, (int64_t)fs.modified_time()); } else { // If the torrent isn't done and we've not shut down, then set // 'mtime' to ~3 so as to indicate that the 'mtime' is not to be // trusted, yet we have a partial bitfield for the file. filesItr->insert_key("mtime", ~int64_t{3}); LT_LOG_SAVE_FILE("file actively downloading", 0); } } } void resume_clear_progress([[maybe_unused]] Download download, Object& object) { object.erase_key("bitfield"); } bool resume_load_bitfield(Download download, const Object& object) { if (object.has_key_string("bitfield")) { const Object::string_type& bitfield = object.get_key_string("bitfield"); if (bitfield.size() != download.file_list()->bitfield()->size_bytes()) { LT_LOG_LOAD_INVALID("size of resumable bitfield does not match bitfield size of torrent", 0); return false; } LT_LOG_LOAD("restoring partial bitfield", 0); download.set_bitfield(reinterpret_cast(bitfield.c_str()), (reinterpret_cast(bitfield.c_str()) + bitfield.size())); } else if (object.has_key_value("bitfield")) { Object::value_type chunksDone = object.get_key_value("bitfield"); if (chunksDone == download.file_list()->bitfield()->size_bits()) { LT_LOG_LOAD("restoring completed bitfield", 0); download.set_bitfield(true); } else if (chunksDone == 0) { LT_LOG_LOAD("restoring empty bitfield", 0); download.set_bitfield(false); } else { LT_LOG_LOAD_INVALID("restoring empty bitfield", 0); return false; } } else { LT_LOG_LOAD_INVALID("valid 'bitfield' not found", 0); return false; } return true; } void resume_save_bitfield(Download download, Object& object) { const Bitfield* bitfield = download.file_list()->bitfield(); if (bitfield->is_all_set() || bitfield->is_all_unset()) { LT_LOG_SAVE("uniform bitfield, saving size only", 0); object.insert_key("bitfield", bitfield->size_set()); } else { LT_LOG_SAVE("saving bitfield", 0); object.insert_key("bitfield", std::string(bitfield->begin(), bitfield->end())); } } void resume_load_uncertain_pieces(Download download, const Object& object) { // Don't rehash when loading resume data within the same session. if (!object.has_key_string("uncertain_pieces")) { LT_LOG_LOAD("no uncertain pieces marked", 0); return; } if (!object.has_key_value("uncertain_pieces.timestamp") || object.get_key_value("uncertain_pieces.timestamp") >= static_cast(download.info()->load_date())) { LT_LOG_LOAD_INVALID("invalid information on uncertain pieces", 0); return; } const Object::string_type& uncertain = object.get_key_string("uncertain_pieces"); LT_LOG_LOAD("found %zu uncertain pieces", uncertain.size() / 2); const char* itr = uncertain.c_str(); const char* last = uncertain.c_str() + uncertain.size(); while (itr + sizeof(uint32_t) <= last) { // Fix this so it does full ranges. download.update_range(Download::update_range_recheck | Download::update_range_clear, ntohl(*reinterpret_cast(itr)), ntohl(*reinterpret_cast(itr)) + 1); itr += sizeof(uint32_t); } } void resume_save_uncertain_pieces(Download download, Object& object) { // Add information on what chunks might still not have been properly // written to disk. object.erase_key("uncertain_pieces"); object.erase_key("uncertain_pieces.timestamp"); const TransferList::completed_list_type& completedList = download.transfer_list()->completed_list(); auto itr = std::find_if(completedList.begin(), completedList.end(), [](const auto& v) { return this_thread::cached_time() - 15min <= std::chrono::microseconds(v.first); }); if (itr == completedList.end()) return; std::vector buffer; buffer.reserve(std::distance(itr, completedList.end())); while (itr != completedList.end()) buffer.push_back((itr++)->second); std::sort(buffer.begin(), buffer.end()); for (unsigned int& itr2 : buffer) itr2 = htonl(itr2); object.insert_key("uncertain_pieces.timestamp", this_thread::cached_seconds().count()); Object::string_type& completed = object.insert_key("uncertain_pieces", std::string()).as_string(); completed.append(reinterpret_cast(&buffer.front()), buffer.size() * sizeof(uint32_t)); } bool resume_check_target_files(Download download, [[maybe_unused]] const Object& object) { FileList* fileList = download.file_list(); if (!fileList->is_open()) return false; if (!fileList->is_root_dir_created()) return false; if (fileList->is_multi_file()) { // Here we should probably check all/most of the files within the // torrent. But for now just return true, as the root dir is // usually created for each (multi) torrent. // int failed = 0; // int exists = 0; // for (FileList::const_iterator itr = fileList->begin(), last = fileList->end(); itr != last; itr++) { // if (!(*itr)->is_previously_created()) // continue; // if ((*itr)->is_created()) // exists++; // else // failed++; // } // return failed >= exists; return true; } else { // We consider empty file lists as being valid. return fileList->empty() || fileList->front()->is_created(); } } void resume_load_file_priorities(Download download, const Object& object) { if (!object.has_key_list("files")) return; const Object::list_type& files = object.get_key_list("files"); auto filesItr = files.begin(); auto filesLast = files.end(); FileList* fileList = download.file_list(); for (auto listItr = fileList->begin(), listLast = fileList->end(); listItr != listLast; ++listItr, ++filesItr) { if (filesItr == filesLast) return; // Update the priority from the fast resume data. if (filesItr->has_key_value("priority") && filesItr->get_key_value("priority") >= 0 && filesItr->get_key_value("priority") <= PRIORITY_HIGH) (*listItr)->set_priority(static_cast(filesItr->get_key_value("priority"))); if (filesItr->has_key_value("completed")) { auto completed = filesItr->get_key_value("completed"); if (completed < 0 || completed > (*listItr)->size_chunks()) { LT_LOG_LOAD_INVALID("invalid completed chunks value: %" PRIi64 ", resetting to 0", completed); completed = 0; } (*listItr)->set_completed_chunks(completed); } } } void resume_save_file_priorities(Download download, Object& object) { auto& files = object.insert_preserve_copy("files", Object::create_list()).first->second.as_list(); auto filesItr = files.begin(); FileList* fileList = download.file_list(); for (auto listItr = fileList->begin(), listLast = fileList->end(); listItr != listLast; ++listItr, ++filesItr) { if (filesItr == files.end()) filesItr = files.insert(filesItr, Object::create_map()); else if (!filesItr->is_map()) *filesItr = Object::create_map(); filesItr->insert_key("priority", static_cast((*listItr)->priority())); } } void resume_load_addresses(Download download, const Object& object) { if (!object.has_key_list("peers")) return; PeerList* peerList = download.peer_list(); // TODO: Add support for inet6. for (const auto& key : object.get_key_list("peers")) { if (!key.is_map() || !key.has_key_string("inet") || !key.has_key_value("failed") || !key.has_key_value("last")) continue; if (key.get_key_value("last") > this_thread::cached_seconds().count()) continue; auto& inet_str = key.get_key_string("inet"); if (inet_str.size() != sizeof(SocketAddressCompact)) continue; int flags = 0; auto compact_sa = reinterpret_cast(inet_str.c_str()); sa_inet_union sa = *compact_sa; if (compact_sa->port != 0) flags |= PeerList::address_available; PeerInfo* peerInfo = peerList->insert_address(&sa.sa, flags); if (peerInfo == NULL) continue; peerInfo->set_failed_counter(key.get_key_value("failed")); peerInfo->set_last_connection(key.get_key_value("last")); } // Tell rTorrent to harvest addresses. } void resume_save_addresses(Download download, Object& object) { auto& dest = object.insert_key("peers", Object::create_list()); for (const auto& dlp : *download.peer_list()) { // Add some checks, like see if there's anything interesting to // save, etc. Or if we can reconnect to it at some later time. // // This should really ensure that if called on a torrent that has // been closed for a while, it won't throw out perfectly good // entries. Object& peer = dest.insert_back(Object::create_map()); auto sa = dlp.second->socket_address(); if (sa->sa_family == AF_INET) peer.insert_key("inet", SocketAddressCompact(reinterpret_cast(sa)).str()); peer.insert_key("failed", dlp.second->failed_counter()); peer.insert_key("last", dlp.second->is_connected() ? this_thread::cached_seconds().count() : dlp.second->last_connection()); } } void resume_load_tracker_settings(Download download, const Object& object) { if (!object.has_key_map("trackers")) return; auto& src = object.get_key("trackers"); auto tracker_list = download.main()->tracker_list(); for (const auto& map : src.as_map()) { if (!map.second.has_key("extra_tracker") || map.second.get_key_value("extra_tracker") == 0 || !map.second.has_key("group")) continue; if (tracker_list->find_url(map.first) != tracker_list->end()) continue; download.main()->tracker_list()->insert_url(map.second.get_key_value("group"), map.first); } for (auto tracker : *tracker_list) { if (!src.has_key_map(tracker.url())) continue; const Object& trackerObject = src.get_key(tracker.url()); if (trackerObject.has_key_value("enabled") && trackerObject.get_key_value("enabled") == 0) tracker.disable(); else tracker.enable(); } } void resume_save_tracker_settings(Download download, Object& object) { auto& dest = object.insert_preserve_copy("trackers", Object::create_map()).first->second; auto tracker_list = download.main()->tracker_list(); for (const auto& tracker : *tracker_list) { Object& trackerObject = dest.insert_key(tracker.url(), Object::create_map()); trackerObject.insert_key("enabled", Object(static_cast(tracker.is_enabled()))); if (tracker.is_extra_tracker()) { trackerObject.insert_key("extra_tracker", Object(int64_t{1})); trackerObject.insert_key("group", tracker.group()); } } } } // namespace torrent libtorrent-0.16.11/src/torrent/utils/signal_bitfield.h0000644000000000000000000000204115175073411016410 // Allows a thread to define work it will do when receiving a signal. #ifndef LIBTORRENT_UTILS_SIGNAL_BITFIELD_H #define LIBTORRENT_UTILS_SIGNAL_BITFIELD_H #include #include #include #include namespace torrent { class LIBTORRENT_EXPORT signal_bitfield { public: using bitfield_type = uint32_t; using slot_type = std::function; static constexpr unsigned int max_size = 32; signal_bitfield() = default; unsigned int add_signal(const slot_type& slot); bool has_signal(unsigned int index) const { return m_bitfield & (1 << index); } void signal(unsigned int index) { m_bitfield |= 1 << index; } void work(); void handover(std::thread::id thread_id) { m_thread_id = thread_id; } private: unsigned int m_size{0}; slot_type m_slots[max_size]; std::atomic m_thread_id{std::this_thread::get_id()}; std::atomic m_bitfield{0}; }; } // namespace torrent #endif libtorrent-0.16.11/src/torrent/utils/log.cc0000644000000000000000000003060315175073411014215 #include "config.h" #include "torrent/utils/log.h" #include #include #include #include #include #include #include #include #include #include "torrent/exceptions.h" #include "torrent/hash_string.h" #include "torrent/utils/string_manip.h" namespace torrent { struct log_cache_entry { using outputs_type = log_group::outputs_type; bool equal_outputs(const outputs_type& out) const { return out == outputs; } void allocate(unsigned int count) { cache_first = new log_slot[count]; cache_last = cache_first + count; } void clear() { delete [] cache_first; cache_first = NULL; cache_last = NULL; } outputs_type outputs; log_slot* cache_first; log_slot* cache_last; }; struct log_stream_output { log_stream_output(std::ostream* stream) : stream(stream) {} std::mutex mutex; std::unique_ptr stream; }; struct log_gz_output { log_gz_output(const char* filename, bool append) : gz_file(gzopen(filename, append ? "a" : "w"), gzclose) {} bool is_valid() const { return gz_file != Z_NULL; } // bool set_buffer(unsigned size) { return gzbuffer(gz_file.get(), size) == 0; } std::unique_ptr gz_file; }; using log_cache_list = std::vector; using log_child_list = std::vector>; log_group_list log_groups; log_output_list log_outputs; static log_cache_list log_cache; static log_child_list log_children; static std::mutex log_mutex; static const char log_level_char[] = { 'C', 'E', 'W', 'N', 'I', 'D' }; // Removing logs always triggers a check if we got any un-used // log_output objects. static void log_update_child_cache(int index) { auto first = std::find_if(log_children.begin(), log_children.end(), [index](const auto& pair) { return pair >= std::make_pair(index, 0); }); if (first == log_children.end()) return; const log_group::outputs_type& outputs = log_groups[index].cached_outputs(); while (first != log_children.end() && first->first == index) { if ((outputs & log_groups[first->second].cached_outputs()) != outputs) { log_groups[first->second].set_cached_outputs(outputs | log_groups[first->second].cached_outputs()); log_update_child_cache(first->second); } first++; } // If we got any circular connections re-do the update to ensure all // children have our new outputs. if (outputs != log_groups[index].cached_outputs()) log_update_child_cache(index); } static void log_rebuild_cache() { std::for_each(log_groups.begin(), log_groups.end(), std::mem_fn(&log_group::clear_cached_outputs)); for (int i = 0; i < LOG_GROUP_MAX_SIZE; i++) log_update_child_cache(i); // Clear the cache... std::for_each(log_cache.begin(), log_cache.end(), std::mem_fn(&log_cache_entry::clear)); log_cache.clear(); for (auto& idx : log_groups) { const log_group::outputs_type& use_outputs = idx.cached_outputs(); if (use_outputs == 0) { idx.set_cached(NULL, NULL); continue; } auto cache_itr = std::find_if(log_cache.begin(), log_cache.end(), [&use_outputs](const auto& entry) { return entry.equal_outputs(use_outputs); }); if (cache_itr == log_cache.end()) { cache_itr = log_cache.insert(log_cache.end(), log_cache_entry()); cache_itr->outputs = use_outputs; cache_itr->allocate(use_outputs.count()); log_slot* dest_itr = cache_itr->cache_first; for (size_t index = 0; index < log_outputs.size(); index++) { if (use_outputs[index]) *dest_itr++ = log_outputs[index].second; } } idx.set_cached(cache_itr->cache_first, cache_itr->cache_last); } } void log_group::internal_print(const HashString* hash, const char* subsystem, const void* dump_data, size_t dump_size, const char* fmt, ...) { va_list ap; const unsigned int buffer_size = 4096; char buffer[buffer_size]; char* first = buffer; if (subsystem != NULL) { if (hash != NULL) { first = utils::transform_to_hex(*hash, first, first + 40); first += snprintf(first, 4096 - (first - buffer), "->%s: ", subsystem); } else { first += snprintf(first, 4096 - (first - buffer), "%s: ", subsystem); } } va_start(ap, fmt); int count = vsnprintf(first, 4096 - (first - buffer), fmt, ap); first += std::min(count, buffer_size - 1); va_end(ap); if (count <= 0) return; auto lock = std::scoped_lock(log_mutex); std::for_each(m_first, m_last, [this, &buffer, first](const auto& elem) { return elem(buffer, std::distance(buffer, first), std::distance(log_groups.begin(), this)); }); if (dump_data != NULL) { std::for_each(m_first, m_last, [dump_data, dump_size](const auto& log) { return log(static_cast(dump_data), dump_size, -1); }); } } #define LOG_CASCADE(parent) LOG_CHILDREN_CASCADE(parent, parent) #define LOG_LINK(parent, child) log_children.emplace_back(parent, child) #define LOG_CHILDREN_CASCADE(parent, subgroup) \ log_children.emplace_back(parent + LOG_ERROR, subgroup + LOG_CRITICAL); \ log_children.emplace_back(parent + LOG_WARN, subgroup + LOG_ERROR); \ log_children.emplace_back(parent + LOG_NOTICE, subgroup + LOG_WARN); \ log_children.emplace_back(parent + LOG_INFO, subgroup + LOG_NOTICE); \ log_children.emplace_back(parent + LOG_DEBUG, subgroup + LOG_INFO); #define LOG_CHILDREN_SUBGROUP(parent, subgroup) \ log_children.emplace_back(parent + LOG_CRITICAL, subgroup + LOG_CRITICAL); \ log_children.emplace_back(parent + LOG_ERROR, subgroup + LOG_ERROR); \ log_children.emplace_back(parent + LOG_WARN, subgroup + LOG_WARN); \ log_children.emplace_back(parent + LOG_NOTICE, subgroup + LOG_NOTICE); \ log_children.emplace_back(parent + LOG_INFO, subgroup + LOG_INFO); \ log_children.emplace_back(parent + LOG_DEBUG, subgroup + LOG_DEBUG); void log_initialize() { auto lock = std::scoped_lock(log_mutex); LOG_CASCADE(LOG_CRITICAL); LOG_CASCADE(LOG_PEER_CRITICAL); LOG_CASCADE(LOG_SOCKET_CRITICAL); LOG_CASCADE(LOG_STORAGE_CRITICAL); LOG_CASCADE(LOG_THREAD_CRITICAL); LOG_CASCADE(LOG_TORRENT_CRITICAL); LOG_CHILDREN_CASCADE(LOG_CRITICAL, LOG_PEER_CRITICAL); LOG_CHILDREN_CASCADE(LOG_CRITICAL, LOG_SOCKET_CRITICAL); LOG_CHILDREN_CASCADE(LOG_CRITICAL, LOG_STORAGE_CRITICAL); LOG_CHILDREN_CASCADE(LOG_CRITICAL, LOG_THREAD_CRITICAL); LOG_CHILDREN_CASCADE(LOG_CRITICAL, LOG_TORRENT_CRITICAL); LOG_LINK(LOG_CONNECTION, LOG_CONNECTION_BIND); LOG_LINK(LOG_CONNECTION, LOG_CONNECTION_FD); LOG_LINK(LOG_CONNECTION, LOG_CONNECTION_FILTER); LOG_LINK(LOG_CONNECTION, LOG_CONNECTION_HANDSHAKE); LOG_LINK(LOG_CONNECTION, LOG_CONNECTION_LISTEN); LOG_LINK(LOG_DHT, LOG_DHT_ERROR); LOG_LINK(LOG_DHT, LOG_DHT_CONTROLLER); LOG_LINK(LOG_DHT_ALL, LOG_DHT_ERROR); LOG_LINK(LOG_DHT_ALL, LOG_DHT_CONTROLLER); LOG_LINK(LOG_DHT_ALL, LOG_DHT_NODE); LOG_LINK(LOG_DHT_ALL, LOG_DHT_ROUTER); LOG_LINK(LOG_DHT_ALL, LOG_DHT_SERVER); std::sort(log_children.begin(), log_children.end()); log_rebuild_cache(); } void log_cleanup() { auto lock = std::scoped_lock(log_mutex); std::fill(log_groups.begin(), log_groups.end(), log_group()); log_outputs.clear(); log_children.clear(); std::for_each(log_cache.begin(), log_cache.end(), std::mem_fn(&log_cache_entry::clear)); log_cache.clear(); } static log_output_list::iterator log_find_output_name(const char* name) { auto itr = log_outputs.begin(); auto last = log_outputs.end(); while (itr != last && itr->first != name) itr++; return itr; } void log_open_output(const char* name, const log_slot& slot) { auto lock = std::scoped_lock(log_mutex); if (log_outputs.size() >= log_group::max_size_outputs()) { throw input_error("Cannot open more than 64 log output handlers."); } auto itr = log_find_output_name(name); if (itr == log_outputs.end()) { log_outputs.emplace_back(name, slot); } else { // by replacing the "write" slot binding, the old file gets closed // (handles are shared pointers) itr->second = slot; } log_rebuild_cache(); } void log_close_output(const char* name) { auto lock = std::scoped_lock(log_mutex); auto itr = log_find_output_name(name); if (itr != log_outputs.end()) log_outputs.erase(itr); } void log_add_group_output(int group, const char* name) { auto lock = std::scoped_lock(log_mutex); auto itr = log_find_output_name(name); size_t index = std::distance(log_outputs.begin(), itr); if (itr == log_outputs.end()) throw input_error("Log name not found: '" + std::string(name) + "'"); if (index >= log_group::max_size_outputs()) throw input_error("Cannot add more log group outputs."); log_groups[group].set_output_at(index, true); log_rebuild_cache(); } void log_remove_group_output([[maybe_unused]] int group, [[maybe_unused]] const char* name) { } // The log_children list is since we build the output // cache by crawling from child to parent. void log_add_child(int group, int child) { auto lock = std::scoped_lock(log_mutex); if (std::find(log_children.begin(), log_children.end(), std::make_pair(group, child)) != log_children.end()) return; log_children.emplace_back(group, child); std::sort(log_children.begin(), log_children.end()); log_rebuild_cache(); } void log_remove_child([[maybe_unused]] int group, [[maybe_unused]] int child) { // Remove from all groups, then modify all outputs. } // TODO: Add lock for file writes. static void log_file_write(const std::unique_ptr& outfile, const char* data, size_t length, int group) { // Add group name, data, etc as flags. // Normal groups are nul-terminated strings. if (group >= LOG_NON_CASCADING) { *outfile << this_thread::cached_seconds().count() << ' ' << data << '\n'; } else if (group >= 0) { *outfile << this_thread::cached_seconds().count() << ' ' << log_level_char[group % 6] << ' ' << data << '\n'; } else if (group == -1) { *outfile << "---DUMP---" << '\n'; if (length != 0) { outfile->rdbuf()->sputn(data, length); *outfile << '\n'; } *outfile << "---END---" << '\n'; } } static void log_gz_file_write(const std::shared_ptr& outfile, const char* data, size_t length, int group) { char buffer[64]; // Normal groups are nul-terminated strings. if (group >= 0) { int buffer_length = snprintf(buffer, 64, (group >= LOG_NON_CASCADING) ? ("%" PRIi64 " ") : ("%" PRIi64 " %c "), static_cast(this_thread::cached_seconds().count()), log_level_char[group % 6]); if (buffer_length > 0) gzwrite(outfile->gz_file.get(), buffer, buffer_length); gzwrite(outfile->gz_file.get(), data, length); gzwrite(outfile->gz_file.get(), "\n", 1); } else if (group == -1) { gzwrite(outfile->gz_file.get(), "---DUMP---\n", sizeof("---DUMP---\n") - 1); if (length != 0) gzwrite(outfile->gz_file.get(), data, length); gzwrite(outfile->gz_file.get(), "---END---\n", sizeof("---END---\n") - 1); } } void log_open_file_output(const char* name, const char* filename, bool append, bool flush) { std::ios_base::openmode mode = std::ofstream::out; if (append) mode |= std::ofstream::app; auto outfile = std::make_shared(new std::ofstream(filename, mode)); if (!outfile->stream->good()) throw input_error("Could not open log file '" + std::string(filename) + "'."); if (flush) log_open_output(name, [outfile](auto d, auto l, auto g) { auto lock = std::lock_guard(outfile->mutex); log_file_write(outfile->stream, d, l, g); outfile->stream->flush(); }); else log_open_output(name, [outfile](auto d, auto l, auto g) { auto lock = std::lock_guard(outfile->mutex); log_file_write(outfile->stream, d, l, g); }); } void log_open_gz_file_output(const char* name, const char* filename, bool append) { auto outfile = std::make_shared(filename, append); if (!outfile->is_valid()) throw input_error("Could not open log gzip file '" + std::string(filename) + "'."); // if (!outfile->set_buffer(1 << 14)) // throw input_error("Could not set gzip log file buffer size."); log_open_output(name, [outfile](auto d, auto l, auto g) { log_gz_file_write(outfile, d, l, g); }); } } // namespace torrent libtorrent-0.16.11/src/torrent/utils/directory_events.cc0000644000000000000000000000556515175073411017035 #include "config.h" #include "directory_events.h" #include #include #include #ifdef USE_INOTIFY #include #endif #include "torrent/exceptions.h" #include "torrent/net/fd.h" #include "torrent/net/poll.h" namespace torrent { bool directory_events::open() { if (is_open()) return true; errno = 0; #ifdef USE_INOTIFY m_fileDesc = inotify_init(); if (!fd_set_nonblock(m_fileDesc)) { fd_close(m_fileDesc); m_fileDesc = -1; } #else errno = ENODEV; #endif if (!is_open()) return false; this_thread::poll()->open(this); this_thread::poll()->insert_read(this); return true; } void directory_events::close() { if (!is_open()) return; this_thread::poll()->remove_read(this); this_thread::poll()->close(this); ::close(m_fileDesc); m_fileDesc = -1; m_wd_list.clear(); } void directory_events::notify_on(const std::string& path, [[maybe_unused]] int flags, [[maybe_unused]] const slot_string& slot) { if (path.empty()) throw input_error("Cannot add notification event for empty paths."); #ifdef USE_INOTIFY int in_flags = IN_MASK_ADD; #ifdef IN_EXCL_UNLINK in_flags |= IN_EXCL_UNLINK; #endif #ifdef IN_ONLYDIR in_flags |= IN_ONLYDIR; #endif if ((flags & flag_on_added)) in_flags |= (IN_CREATE | IN_MOVED_TO); if ((flags & flag_on_updated)) in_flags |= IN_CLOSE_WRITE; if ((flags & flag_on_removed)) in_flags |= (IN_DELETE | IN_MOVED_FROM); int result = inotify_add_watch(m_fileDesc, path.c_str(), in_flags); if (result == -1) throw input_error("Call to inotify_add_watch(...) failed: " + std::string(std::strerror(errno))); auto& wd = m_wd_list.emplace_back(); wd.descriptor = result; wd.path = path + (path.back() != '/' ? "/" : ""); wd.slot = slot; #else throw input_error("No support for inotify."); #endif } void directory_events::event_read() { #ifdef USE_INOTIFY char buffer[2048]; ssize_t result = ::read(m_fileDesc, buffer, 2048); if (result < static_cast(sizeof(struct inotify_event))) return; auto event = reinterpret_cast(buffer); while (event + 1 <= reinterpret_cast(buffer + result)) { auto next_event = reinterpret_cast(event) + sizeof(struct inotify_event) + event->len; if (event->len == 0 || next_event > buffer + result) return; auto itr = std::find_if(m_wd_list.begin(), m_wd_list.end(), [event](const auto& w) { return w.compare_desc(event->wd); }); if (itr != m_wd_list.end()) { std::string sname(event->name); if (sname.size() >= 8 && sname.compare(sname.size() - 8, 8, ".torrent") == 0) itr->slot(itr->path + event->name); } event = reinterpret_cast(next_event); } #endif } void directory_events::event_write() { } void directory_events::event_error() { } } // namespace torrent libtorrent-0.16.11/src/torrent/utils/scheduler.cc0000644000000000000000000001242115175073411015410 #include "config.h" #include "torrent/utils/scheduler.h" #include #include #include "torrent/exceptions.h" #include "torrent/utils/chrono.h" namespace torrent::utils { SchedulerEntry::~SchedulerEntry() { assert(!is_scheduled() && "SchedulerEntry::~SchedulerEntry() called on a scheduled item."); assert(m_time == time_type{} && "SchedulerEntry::~SchedulerEntry() called on an item with a time."); m_slot = nullptr; m_scheduler = nullptr; m_time = time_type{}; } inline void Scheduler::make_heap() { std::make_heap(begin(), end(), [](const SchedulerEntry* a, const SchedulerEntry* b) { return a->time() > b->time(); }); } inline void Scheduler::push_heap() { std::push_heap(begin(), end(), [](const SchedulerEntry* a, const SchedulerEntry* b) { return a->time() > b->time(); }); } Scheduler::time_type Scheduler::next_timeout() const { assert(!empty()); return std::max(front()->time() - m_cached_time, Scheduler::time_type()); } // We can't make erase/update part of SchedulerItem in case another thread tries to call the // scheduler, which is not thread-safe. void Scheduler::erase(SchedulerEntry* entry) { assert(m_thread_id == std::thread::id() || m_thread_id == std::this_thread::get_id()); if (!entry->is_scheduled()) return; // Check is_valid() after is_schedulerd() so that it is safe to call // erase on untouched instances. if (!entry->is_valid()) throw torrent::internal_error("Scheduler::erase(...) called on an invalid entry."); if (entry->scheduler() != this) throw torrent::internal_error("Scheduler::erase(...) called on an entry that is in another scheduler."); auto itr = std::find_if(begin(), end(), [entry](const SchedulerEntry* e) { return e == entry; }); if (itr == end()) throw torrent::internal_error("Scheduler::erase(...) could not find item in queue."); entry->set_scheduler(nullptr); entry->set_time(Scheduler::time_type{}); base_type::erase(itr); make_heap(); } void Scheduler::wait_until(SchedulerEntry* entry, Scheduler::time_type time) { assert(m_thread_id == std::thread::id() || m_thread_id == std::this_thread::get_id()); if (time == Scheduler::time_type()) throw torrent::internal_error("Scheduler::wait_until(...) received a bad timer."); if (time < Scheduler::time_type(365 * 24h)) throw torrent::internal_error("Scheduler::wait_until(...) received a too small timer."); if (!entry->is_valid()) throw torrent::internal_error("Scheduler::wait_until(...) called on an invalid entry."); if (entry->is_scheduled()) throw torrent::internal_error("Scheduler::wait_until(...) called on an already scheduled entry."); entry->set_scheduler(this); entry->set_time(time); base_type::push_back(entry); push_heap(); } void Scheduler::wait_for(SchedulerEntry* entry, Scheduler::time_type time) { if (time > Scheduler::time_type(10 * 365 * 24h)) throw torrent::internal_error("Scheduler::wait_after(...) received a too large timer."); wait_until(entry, m_cached_time + time); } void Scheduler::wait_for_ceil_seconds(SchedulerEntry* entry, Scheduler::time_type time) { if (time > Scheduler::time_type(10 * 365 * 24h)) throw torrent::internal_error("Scheduler::wait_after_ceil_seconds(...) received a too large timer."); wait_until(entry, ceil_seconds(m_cached_time + time)); } void Scheduler::update_wait_until(SchedulerEntry* entry, Scheduler::time_type time) { assert(m_thread_id == std::thread::id() || m_thread_id == std::this_thread::get_id()); if (time == Scheduler::time_type()) throw torrent::internal_error("Scheduler::update_wait(...) received a bad timer."); if (time < Scheduler::time_type(365 * 24h)) throw torrent::internal_error("Scheduler::update_wait(...) received a too small timer."); if (!entry->is_valid()) throw torrent::internal_error("Scheduler::update_wait(...) called on an invalid entry."); if (entry->is_scheduled()) { if (entry->scheduler() != this) throw torrent::internal_error("Scheduler::update_wait(...) called on an entry that is in another scheduler."); entry->set_time(time); make_heap(); return; } entry->set_scheduler(this); entry->set_time(time); base_type::push_back(entry); push_heap(); } void Scheduler::update_wait_for(SchedulerEntry* entry, Scheduler::time_type time) { if (time > Scheduler::time_type(10 * 365 * 24h)) throw torrent::internal_error("Scheduler::update_wait_after(...) received a too large timer."); update_wait_until(entry, m_cached_time + time); } void Scheduler::update_wait_for_ceil_seconds(SchedulerEntry* entry, Scheduler::time_type time) { if (time > Scheduler::time_type(10 * 365 * 24h)) throw torrent::internal_error("Scheduler::update_wait_after_ceil_seconds(...) received a too large timer."); update_wait_until(entry, ceil_seconds(m_cached_time + time)); } void Scheduler::perform(Scheduler::time_type current_time) { while (!empty() && base_type::front()->time() <= current_time) { auto entry = base_type::front(); std::pop_heap(begin(), end(), [](const SchedulerEntry* a, const SchedulerEntry* b) { return a->time() > b->time(); }); base_type::pop_back(); entry->set_scheduler(nullptr); entry->set_time(Scheduler::time_type{}); entry->slot()(); } } } // namespace torrent::utils libtorrent-0.16.11/src/torrent/utils/option_strings.cc0000644000000000000000000001733415175073411016523 #include "config.h" #include #include #include "torrent/download.h" #include "torrent/exceptions.h" #include "torrent/object.h" #include "torrent/download/choke_group.h" #include "torrent/download/choke_queue.h" #include "torrent/net/network_config.h" #include "torrent/peer/peer_info.h" #include "torrent/utils/option_strings.h" namespace torrent { struct option_single { unsigned int size; const char* const* name; }; struct option_pair { const char* name; unsigned int value; }; constexpr option_pair option_list_connection_type[] = { { "leech", Download::CONNECTION_LEECH }, { "seed", Download::CONNECTION_SEED }, { "initial_seed", Download::CONNECTION_INITIAL_SEED }, { "metadata", Download::CONNECTION_METADATA }, { NULL, 0 } }; constexpr option_pair option_list_heuristics[] = { { "upload_leech", choke_queue::HEURISTICS_UPLOAD_LEECH }, { "upload_leech_experimental", choke_queue::HEURISTICS_UPLOAD_LEECH_EXPERIMENTAL }, { "upload_seed", choke_queue::HEURISTICS_UPLOAD_SEED }, { "download_leech", choke_queue::HEURISTICS_DOWNLOAD_LEECH }, { "invalid", choke_queue::HEURISTICS_MAX_SIZE }, { NULL, 0 } }; constexpr option_pair option_list_heuristics_download[] = { { "download_leech", choke_queue::HEURISTICS_DOWNLOAD_LEECH }, { NULL, 0 } }; constexpr option_pair option_list_heuristics_upload[] = { { "upload_leech", choke_queue::HEURISTICS_UPLOAD_LEECH }, { "upload_leech_experimental", choke_queue::HEURISTICS_UPLOAD_LEECH_EXPERIMENTAL }, { "upload_seed", choke_queue::HEURISTICS_UPLOAD_SEED }, { NULL, 0 } }; constexpr option_pair option_list_encryption[] = { { "none", torrent::net::NetworkConfig::encryption_none }, { "allow_incoming", torrent::net::NetworkConfig::encryption_allow_incoming }, { "try_outgoing", torrent::net::NetworkConfig::encryption_try_outgoing }, { "require", torrent::net::NetworkConfig::encryption_require }, { "require_RC4", torrent::net::NetworkConfig::encryption_require_RC4 }, { "require_rc4", torrent::net::NetworkConfig::encryption_require_RC4 }, { "enable_retry", torrent::net::NetworkConfig::encryption_enable_retry }, { "prefer_plaintext", torrent::net::NetworkConfig::encryption_prefer_plaintext }, { NULL, 0 } }; constexpr option_pair option_list_ip_filter[] = { { "unwanted", PeerInfo::flag_unwanted }, { "preferred", PeerInfo::flag_preferred }, { NULL, 0 } }; constexpr option_pair option_list_ip_tos[] = { { "default", torrent::net::NetworkConfig::iptos_default }, { "lowdelay", torrent::net::NetworkConfig::iptos_lowdelay }, { "throughput", torrent::net::NetworkConfig::iptos_throughput }, { "reliability", torrent::net::NetworkConfig::iptos_reliability }, { NULL, 0 } }; constexpr option_pair option_list_tracker_mode[] = { { "normal", choke_group::TRACKER_MODE_NORMAL }, { "aggressive", choke_group::TRACKER_MODE_AGGRESSIVE }, { NULL, 0 } }; constexpr const char* option_list_handshake_connection[] = { "none", "incoming", "outgoing_normal", "outgoing_encrypted", "outgoing_proxy", "success", "dropped", "failed", "retry_plaintext", "retry_encrypted", nullptr }; constexpr const char* option_list_log_group[] = { "critical", "error", "warn", "notice", "info", "debug", "peer_critical", "peer_error", "peer_warn", "peer_notice", "peer_info", "peer_debug", "socket_critical", "socket_error", "socket_warn", "socket_notice", "socket_info", "socket_debug", "storage_critical", "storage_error", "storage_warn", "storage_notice", "storage_info", "storage_debug", "thread_critical", "thread_error", "thread_warn", "thread_notice", "thread_info", "thread_debug", "torrent_critical", "torrent_error", "torrent_warn", "torrent_notice", "torrent_info", "torrent_debug", "__non_cascading__", "connection", "connection_bind", "connection_fd", "connection_filter", "connection_hanshake", "connection_listen", "dht", "dht_all", "dht_error", "dht_controller", "dht_node", "dht_router", "dht_server", "instrumentation_memory", "instrumentation_mincore", "instrumentation_choke", "instrumentation_polling", "instrumentation_transfers", "mock_calls", "net_dns", "net_socket", "peer_list_events", "peer_list_address", "protocol_piece_events", "protocol_metadata_events", "protocol_network_errors", "protocol_storage_errors", "resume_data", "rpc_events", "rpc_dump", "session_events", "storage", "system", "tracker_dump", "tracker_events", "tracker_requests", "ui_events", NULL }; constexpr const char* option_list_tracker_event[] = { "updated", "completed", "started", "stopped", "scrape", NULL }; constexpr std::array option_pair_lists{ option_list_connection_type, option_list_heuristics, option_list_heuristics_download, option_list_heuristics_upload, option_list_encryption, option_list_ip_filter, option_list_ip_tos, option_list_tracker_mode, }; static_assert(option_pair_lists.size() == OPTION_START_COMPACT); #define OPTION_SINGLE_ENTRY(single_name) \ option_single{ sizeof(single_name) / sizeof(const char*) - 1, single_name } constexpr std::array option_single_lists{ OPTION_SINGLE_ENTRY(option_list_handshake_connection), OPTION_SINGLE_ENTRY(option_list_log_group), OPTION_SINGLE_ENTRY(option_list_tracker_event), }; static_assert(option_single_lists.size() == OPTION_SINGLE_SIZE); int option_find_string(option_enum opt_enum, const char* name) { if (opt_enum < OPTION_START_COMPACT) { auto itr = option_pair_lists[opt_enum]; do { if (std::strcmp(itr->name, name) == 0) return itr->value; } while ((++itr)->name != NULL); } else if (opt_enum < OPTION_MAX_SIZE) { auto itr = option_single_lists[opt_enum - OPTION_START_COMPACT].name; do { if (std::strcmp(*itr, name) == 0) return std::distance(option_single_lists[opt_enum - OPTION_START_COMPACT].name, itr); } while (*++itr != NULL); } throw input_error("invalid option name : enum:" + std::to_string(opt_enum) + " name:'" + std::string(name) + "'"); } const char* option_to_string(option_enum opt_enum, unsigned int value, const char* not_found) { if (opt_enum < OPTION_START_COMPACT) { auto itr = option_pair_lists[opt_enum]; do { if (itr->value == value) return itr->name; } while ((++itr)->name != NULL); } else if (opt_enum < OPTION_MAX_SIZE) { if (value < option_single_lists[opt_enum - OPTION_START_COMPACT].size) return option_single_lists[opt_enum - OPTION_START_COMPACT].name[value]; } return not_found; } const char* option_to_string_or_throw(option_enum opt_enum, unsigned int value, const char* not_found) { const char* result = option_to_string(opt_enum, value, NULL); if (result == NULL) throw input_error(not_found); return result; } const char* option_as_string(option_enum opt_enum, unsigned int value) { const char* result = option_to_string(opt_enum, value, NULL); if (result == NULL) throw input_error("invalid option value : enum:" + std::to_string(opt_enum) + " value:" + std::to_string(value)); return result; } torrent::Object option_list_strings(option_enum opt_enum) { Object::list_type result; if (opt_enum < OPTION_START_COMPACT) { auto itr = option_pair_lists[opt_enum]; while (itr->name != NULL) result.emplace_back(std::string(itr++->name)); } else if (opt_enum < OPTION_MAX_SIZE) { auto itr = option_single_lists[opt_enum - OPTION_START_COMPACT].name; while (*itr != NULL) result.emplace_back(std::string(*itr++)); } return Object::from_list(result); } } // namespace torrent libtorrent-0.16.11/src/torrent/utils/uri_parser.h0000644000000000000000000000371515175073411015455 #ifndef LIBTORRENT_UTILS_URI_PARSER_H #define LIBTORRENT_UTILS_URI_PARSER_H #include #include #include #include namespace torrent::utils { using uri_resource_list = std::vector; using uri_query_list = std::vector; struct uri_base_state { static constexpr int state_empty = 0; static constexpr int state_valid = 1; static constexpr int state_invalid = 2; int state{state_empty}; }; struct uri_state : uri_base_state { std::string uri; std::string scheme; std::string resource; std::string query; std::string fragment; }; struct uri_resource_state : public uri_base_state { std::string resource; uri_resource_list path; }; struct uri_query_state : public uri_base_state { std::string query; uri_query_list elements; }; class uri_error : public ::torrent::input_error { public: using input_error::input_error; }; void uri_parse_str(std::string uri, uri_state& state) LIBTORRENT_EXPORT; void uri_parse_c_str(const char* uri, uri_state& state) LIBTORRENT_EXPORT; void uri_parse_resource(std::string query, uri_query_state& state) LIBTORRENT_EXPORT; void uri_parse_resource_authority(std::string query, uri_query_state& state) LIBTORRENT_EXPORT; void uri_parse_resource_path(std::string query, uri_query_state& state) LIBTORRENT_EXPORT; void uri_parse_query_str(std::string query, uri_query_state& state) LIBTORRENT_EXPORT; void uri_parse_query_c_str(const char* query, uri_query_state& state) LIBTORRENT_EXPORT; std::string uri_generate_scrape_url(std::string uri) LIBTORRENT_EXPORT; bool uri_can_scrape(const std::string& uri) LIBTORRENT_EXPORT; bool uri_has_query(const std::string& uri) LIBTORRENT_EXPORT; int uri_detect_numeric(const std::string& uri) LIBTORRENT_EXPORT; std::string uri_escape_html(const char* first, const char* last) LIBTORRENT_EXPORT; } // namespace torrent::utils #endif libtorrent-0.16.11/src/torrent/tracker/0000755000000000000000000000000015175073434013503 5libtorrent-0.16.11/src/torrent/tracker/manager.cc0000644000000000000000000000652015175073411015342 #include "config.h" #include #include #include "torrent/download_info.h" #include "torrent/exceptions.h" #include "torrent/tracker/manager.h" #include "torrent/tracker/tracker.h" #include "torrent/utils/log.h" #include "torrent/system/thread.h" #include "torrent/utils/string_manip.h" #include "tracker/tracker_controller.h" #include "tracker/tracker_list.h" #include "tracker/tracker_worker.h" #define LT_LOG_TRACKER_EVENTS(log_fmt, ...) \ lt_log_print_subsystem(LOG_TRACKER_EVENTS, "tracker::manager", log_fmt, __VA_ARGS__); namespace torrent::tracker { Manager::Manager(system::Thread* main_thread, system::Thread* tracker_thread) : m_main_thread(main_thread), m_tracker_thread(tracker_thread) { if (m_main_thread == nullptr) throw internal_error("tracker::Manager::Manager(...) main_thread is null."); if (m_tracker_thread == nullptr) throw internal_error("tracker::Manager::Manager(...) tracker_thread is null."); } TrackerControllerWrapper Manager::add_controller(DownloadInfo* download_info, std::shared_ptr controller) { assert(std::this_thread::get_id() == m_main_thread->thread_id()); if (download_info->hash() == HashString::new_zero()) throw internal_error("tracker::Manager::add(...) invalid info_hash."); auto lock = std::scoped_lock(m_lock); auto wrapper = TrackerControllerWrapper(download_info->hash(), std::move(controller)); auto result = m_controllers.insert(wrapper); if (!result.second) throw internal_error("tracker::Manager::add_controller(...) controller already exists."); LT_LOG_TRACKER_EVENTS("added controller: info_hash:%s", utils::transform_to_hex_str(download_info->hash()).c_str()); return wrapper; } void Manager::remove_controller(TrackerControllerWrapper controller) { assert(std::this_thread::get_id() == m_main_thread->thread_id()); auto lock = std::scoped_lock(m_lock); // We assume there are other references to the controller, so gracefully close it. if (m_controllers.erase(controller) != 1) throw internal_error("tracker::Manager::remove_controller(...) controller not found or has multiple references."); for (auto& tracker : *controller.get()->tracker_list()) remove_events(tracker.get_worker()); LT_LOG_TRACKER_EVENTS("removed controller: info_hash:%s", utils::transform_to_hex_str(controller.info_hash()).c_str()); } void Manager::send_event(tracker::Tracker& tracker, tracker::TrackerState::event_enum new_event) { assert(std::this_thread::get_id() == m_main_thread->thread_id()); // TODO: Currently executing in main thread, but should be in tracker thread. tracker.get_worker()->send_event(new_event); } void Manager::send_scrape(tracker::Tracker& tracker) { assert(std::this_thread::get_id() == m_main_thread->thread_id()); // TODO: Currently executing in main thread, but should be in tracker thread. tracker.get_worker()->send_scrape(); } // Events are queued by the trackers and run in the main thread. void Manager::add_event(torrent::TrackerWorker* tracker_worker, std::function event) { m_main_thread->callback(tracker_worker, std::move(event)); } void Manager::remove_events(torrent::TrackerWorker* tracker_worker) { m_main_thread->cancel_callback_and_wait(tracker_worker); m_tracker_thread->cancel_callback_and_wait(tracker_worker); } } // namespace torrent::tracker libtorrent-0.16.11/src/torrent/tracker/tracker.cc0000644000000000000000000000543715175073411015371 #include "config.h" #include "torrent/tracker/tracker.h" #include "tracker/tracker_worker.h" namespace torrent::tracker { // TODO: Handle !is_valid() errors. Tracker::Tracker(std::shared_ptr&& worker) : m_worker(std::move(worker)) { } bool Tracker::is_busy() const { auto lock_guard = m_worker->lock_guard(); return m_worker->is_busy(); } bool Tracker::is_busy_not_scrape() const { auto lock_guard = m_worker->lock_guard(); return m_worker->is_busy_not_scrape(); } bool Tracker::is_enabled() const { auto lock_guard = m_worker->lock_guard(); return m_worker->m_state.is_enabled(); } bool Tracker::is_extra_tracker() const { auto lock_guard = m_worker->lock_guard(); return m_worker->m_state.is_extra_tracker(); } bool Tracker::is_in_use() const { auto lock_guard = m_worker->lock_guard(); return m_worker->m_state.is_in_use(); } bool Tracker::is_usable() const { auto lock_guard = m_worker->lock_guard(); return m_worker->is_usable(); } bool Tracker::is_scrapable() const { auto lock_guard = m_worker->lock_guard(); return m_worker->m_state.is_scrapable(); } bool Tracker::can_request_state() const { auto lock_guard = m_worker->lock_guard(); if (!m_worker->is_usable()) return false; return !m_worker->is_busy_not_scrape(); } void Tracker::enable() { { auto lock_guard = m_worker->lock_guard(); if (m_worker->m_state.is_enabled()) return; m_worker->m_state.m_flags |= tracker::TrackerState::flag_enabled; } if (m_worker->m_slot_enabled) m_worker->m_slot_enabled(); } void Tracker::disable() { { auto lock_guard = m_worker->lock_guard(); if (!m_worker->m_state.is_enabled()) return; m_worker->m_state.m_flags &= ~tracker::TrackerState::flag_enabled; } // TODO: This should be called through manager? It works atm as the trackers are all running on main // thread. m_worker->close(); if (m_worker->m_slot_disabled) m_worker->m_slot_disabled(); } tracker_enum Tracker::type() const { return m_worker->type(); } const std::string& Tracker::url() const { return m_worker->info().url; } std::string Tracker::tracker_id() const { auto lock_guard = m_worker->lock_guard(); return m_worker->tracker_id(); } uint32_t Tracker::group() const { auto lock_guard = m_worker->lock_guard(); return m_worker->group(); } tracker::TrackerState Tracker::state() const { auto lock_guard = m_worker->lock_guard(); return m_worker->state(); } std::string Tracker::status() const { return m_worker->lock_and_status(); } void Tracker::lock_and_call_state(const std::function& f) const { auto lock_guard = m_worker->lock_guard(); f(m_worker->state()); } void Tracker::clear_stats() { m_worker->lock_and_clear_stats(); } } // namespace torrent::tracker libtorrent-0.16.11/src/torrent/tracker/tracker.h0000644000000000000000000000346015175073411015225 #ifndef LIBTORRENT_TRACKER_TRACKER_H #define LIBTORRENT_TRACKER_TRACKER_H #include #include #include #include #include class TrackerTest; namespace torrent { class ThreadTracker; } // namespace torrent namespace torrent::tracker { class LIBTORRENT_EXPORT Tracker { public: bool is_valid() const { return m_worker != nullptr; } bool is_busy() const; bool is_busy_not_scrape() const; bool is_enabled() const; bool is_extra_tracker() const; bool is_in_use() const; bool is_usable() const; bool is_scrapable() const; bool can_request_state() const; void enable(); void disable(); torrent::tracker_enum type() const; const std::string& url() const; std::string tracker_id() const; uint32_t group() const; TrackerState state() const; std::string status() const; void lock_and_call_state(const std::function& f) const; bool operator< (const Tracker& rhs) const { return m_worker < rhs.m_worker; } bool operator==(const Tracker& rhs) const { return m_worker == rhs.m_worker; } protected: friend class Manager; friend class TrackerControllerWrapper; friend class torrent::ThreadTracker; friend class torrent::TrackerList; friend class ::TrackerTest; Tracker(std::shared_ptr&& worker); TrackerWorker* get_worker() { return m_worker.get(); } void clear_stats(); private: std::shared_ptr m_worker; }; } // namespace torrent::tracker #endif libtorrent-0.16.11/src/torrent/tracker/dht_controller.cc0000644000000000000000000000756115175073411016760 #include "config.h" #include "dht_controller.h" #include "dht/dht_router.h" #include "src/manager.h" #include "torrent/exceptions.h" #include "torrent/net/socket_address.h" #include "torrent/net/network_config.h" #include "torrent/runtime/network_manager.h" #include "torrent/utils/log.h" #define LT_LOG(log_fmt, ...) \ lt_log_print_subsystem(torrent::LOG_DHT_CONTROLLER, "dht_controller", log_fmt, __VA_ARGS__); namespace torrent::tracker { DhtController::DhtController() = default; DhtController::~DhtController() { stop(); } bool DhtController::is_valid() { auto lock = std::lock_guard(m_lock); return m_router != nullptr; } bool DhtController::is_active() { auto lock = std::lock_guard(m_lock); return m_router && m_router->is_active(); } bool DhtController::is_receiving_requests() { auto lock = std::lock_guard(m_lock); return m_receive_requests; } uint16_t DhtController::port() { auto lock = std::lock_guard(m_lock); return m_port; } void DhtController::initialize(const Object& dht_cache) { auto lock = std::lock_guard(m_lock); if (m_router != nullptr) throw internal_error("DhtController::initialize() called with DHT already active."); LT_LOG("initializing", 0); try { m_router = std::make_unique(dht_cache); } catch (const torrent::local_error& e) { LT_LOG("initialization failed : %s", e.what()); } } bool DhtController::start() { auto lock = std::lock_guard(m_lock); if (m_router == nullptr) throw internal_error("DhtController::start() called without initializing first."); auto port = config::network_config()->override_dht_port(); if (port == 0) port = runtime::network_manager()->listen_port_or_throw(); LT_LOG("starting : port:%d", port); try { m_router->start(port); m_port = port; } catch (const torrent::local_error& e) { LT_LOG("start failed : %s", e.what()); return false; } return true; } void DhtController::stop() { auto lock = std::lock_guard(m_lock); if (!m_router) return; LT_LOG("stopping", 0); m_router->stop(); m_port = 0; } void DhtController::set_receive_requests(bool state) { auto lock = std::lock_guard(m_lock); m_receive_requests = state; } void DhtController::add_bootstrap_node(std::string host, int port) { auto lock = std::lock_guard(m_lock); if (m_router) m_router->add_bootstrap_contact(std::move(host), port); } void DhtController::add_node(const sockaddr* sa, int port) { auto lock = std::lock_guard(m_lock); if (m_router) m_router->contact(sa, port); } Object* DhtController::store_cache(Object* container) { auto lock = std::lock_guard(m_lock); if (!m_router) throw internal_error("DhtController::store_cache() called but DHT not initialized."); return m_router->store_cache(container); } DhtController::statistics_type DhtController::get_statistics() { auto lock = std::lock_guard(m_lock); if (!m_router) throw internal_error("DhtController::get_statistics() called but DHT not initialized."); return m_router->get_statistics(); } void DhtController::reset_statistics() { auto lock = std::lock_guard(m_lock); if (!m_router) throw internal_error("DhtController::reset_statistics() called but DHT not initialized."); m_router->reset_statistics(); } void DhtController::announce(const HashString& info_hash, TrackerDht* tracker) { auto lock = std::lock_guard(m_lock); if (!m_router) throw internal_error("DhtController::announce() called but DHT not initialized."); m_router->announce(info_hash, tracker); } void DhtController::cancel_announce(const HashString* info_hash, const torrent::TrackerDht* tracker) { auto lock = std::lock_guard(m_lock); if (!m_router) throw internal_error("DhtController::cancel_announce() called but DHT not initialized."); m_router->cancel_announce(info_hash, tracker); } } // namespace torrent::tracker libtorrent-0.16.11/src/torrent/tracker/wrappers.h0000644000000000000000000000703315175073411015435 // Temporary classes for thread-safe tracker related classes. // // These will be renamed after movimg the old torrent/tracker_* classes to src/tracker. #ifndef LIBTORRENT_TRACKER_WRAPPER_H #define LIBTORRENT_TRACKER_WRAPPER_H #include #include #include #include // TODO: Rename to TrackerController when torrent::TrackerController is moved. namespace torrent::tracker { class LIBTORRENT_EXPORT TrackerControllerWrapper { public: using ptr_type = std::shared_ptr; using slot_string = std::function; using slot_address_list = std::function; TrackerControllerWrapper() = default; TrackerControllerWrapper(const HashString& info_hash, std::shared_ptr&& controller); bool is_valid() const { return m_ptr != nullptr; } bool is_active() const; bool is_requesting() const; bool is_failure_mode() const; bool is_promiscuous_mode() const; bool has_active_trackers() const; bool has_active_trackers_not_scrape() const; bool has_usable_trackers() const; const HashString& info_hash() const { return m_info_hash; } uint32_t key() const; int32_t numwant() const; void set_numwant(int32_t n); uint32_t size() const; Tracker at(uint32_t index) const; void add_extra_tracker(uint32_t group, const std::string& url); uint32_t seconds_to_next_timeout() const; uint32_t seconds_to_next_scrape() const; void manual_request(bool request_now); void scrape_request(uint32_t seconds_to_request); void cycle_group(uint32_t group); // Algorithms: Tracker find_if(const std::function& f); void for_each(const std::function& f); Tracker c_find_if(const std::function& f) const; void c_for_each(const std::function& f) const; bool operator<(const TrackerControllerWrapper& rhs) const; protected: friend class torrent::Download; friend class torrent::DownloadMain; friend class torrent::DownloadWrapper; friend class Manager; TrackerController* get() { return m_ptr.get(); } const TrackerController* get() const { return m_ptr.get(); } ptr_type& get_shared() { return m_ptr; } void enable(); void enable_dont_reset_stats(); void disable(); void close(); void send_start_event(); void send_stop_event(); void send_completed_event(); void send_update_event(); void start_requesting(); void stop_requesting(); void set_slots(slot_address_list success, slot_string failure); private: ptr_type m_ptr; HashString m_info_hash; }; inline TrackerControllerWrapper::TrackerControllerWrapper(const HashString& info_hash, std::shared_ptr&& controller) : m_ptr(std::move(controller)), m_info_hash(info_hash) { } inline bool TrackerControllerWrapper::operator<(const TrackerControllerWrapper& rhs) const { return this->get() < rhs.get(); } } // namespace torrent::tracker #endif // LIBTORRENT_TRACKER_TRACKER_WRAPPER_H libtorrent-0.16.11/src/torrent/tracker/dht_controller.h0000644000000000000000000000447315175073411016621 #ifndef LIBTORRENT_TRACKER_DHT_CONTROLLER_H #define LIBTORRENT_TRACKER_DHT_CONTROLLER_H #include #include #include namespace torrent { class TrackerDht; } // namespace torrent namespace torrent::tracker { class LIBTORRENT_EXPORT DhtController { public: struct statistics_type { // Cycle; 0=inactive, 1=initial bootstrapping, 2 and up=normal operation unsigned int cycle{}; // DHT query statistics. unsigned int queries_received{}; unsigned int queries_sent{}; unsigned int replies_received{}; unsigned int errors_received{}; unsigned int errors_caught{}; // DHT node info. unsigned int num_nodes{}; unsigned int num_buckets{}; // DHT tracker info. unsigned int num_peers{}; unsigned int max_peers{}; unsigned int num_trackers{}; }; DhtController(); ~DhtController(); // Thread-safe: bool is_valid(); bool is_active(); bool is_receiving_requests(); void set_receive_requests(bool state); // TODO: This is the active port, move this to NetworkConfig? (or make this unavailable) uint16_t port(); // Main thread: void initialize(const Object& dht_cache); bool start(); void stop(); // Store DHT cache in the given container and return the container. Object* store_cache(Object* container); // Add a node by host (from a torrent file), or by address from explicit add_node // command or the BT PORT message. void add_bootstrap_node(std::string host, int port); void add_node(const sockaddr* sa, int port); statistics_type get_statistics(); void reset_statistics(); protected: friend class torrent::TrackerDht; // Thread-safe: void announce(const HashString& info_hash, TrackerDht* tracker); void cancel_announce(const HashString* info_hash, const torrent::TrackerDht* tracker); private: std::mutex m_lock; uint16_t m_port{0}; bool m_receive_requests{true}; std::unique_ptr m_router; }; } // namespace torrent::tracker #endif // LIBTORRENT_TRACKER_DHT_CONTROLLER_H libtorrent-0.16.11/src/torrent/tracker/manager.h0000644000000000000000000000332415175073411015203 // Thread-safe manager for all trackers loaded by the client. #ifndef LIBTORRENT_TRACKER_MANAGER_H #define LIBTORRENT_TRACKER_MANAGER_H #include #include #include #include namespace torrent::tracker { struct TrackerListEvent { TrackerList* tracker_list; std::function event; }; class LIBTORRENT_EXPORT Manager { public: Manager(system::Thread* main_thread, system::Thread* tracker_thread); ~Manager() = default; protected: friend class torrent::DownloadMain; friend class torrent::DownloadWrapper; friend class torrent::TrackerList; friend class torrent::ThreadTracker; // Main thread: TrackerControllerWrapper add_controller(DownloadInfo* download_info, std::shared_ptr controller); void remove_controller(TrackerControllerWrapper controller); void send_event(tracker::Tracker& tracker, tracker::TrackerState::event_enum new_event); void send_scrape(tracker::Tracker& tracker); // Any thread: // remove_events() only removes events from the main thread. void add_event(torrent::TrackerWorker* tracker_worker, std::function event); void remove_events(torrent::TrackerWorker* tracker_worker); private: Manager(const Manager&) = delete; Manager& operator=(const Manager&) = delete; system::Thread* m_main_thread{nullptr}; system::Thread* m_tracker_thread{nullptr}; unsigned int m_signal_process_events{~0u}; std::mutex m_lock; std::set m_controllers; }; } // namespace torrent::tracker #endif // LIBTORRENT_TRACKER_MANAGER_H libtorrent-0.16.11/src/torrent/tracker/tracker_state.h0000644000000000000000000001226715175073411016432 #ifndef LIBTORRENT_TRACKER_TRACKER_STATE_H #define LIBTORRENT_TRACKER_TRACKER_STATE_H #include #include class TrackerTest; namespace torrent { class TrackerDht; class TrackerHttp; class TrackerList; class TrackerUdp; class TrackerWorker; namespace tracker { class TrackerState { public: enum event_enum { EVENT_NONE, EVENT_COMPLETED, EVENT_STARTED, EVENT_STOPPED, EVENT_SCRAPE }; static constexpr int flag_enabled = 0x1; static constexpr int flag_extra_tracker = 0x2; static constexpr int flag_scrapable = 0x4; // TODO: Remove these: // static constexpr int max_flag_size = 0x10; // static constexpr int mask_base_flags = 0x10 - 1; static constexpr int default_min_interval = 600; static constexpr int min_min_interval = 300; static constexpr int max_min_interval = 4 * 3600; static constexpr int default_normal_interval = 1800; static constexpr int min_normal_interval = 600; static constexpr int max_normal_interval = 8 * 3600; int flags() const { return m_flags; } bool is_enabled() const { return (m_flags & flag_enabled); } bool is_extra_tracker() const { return (m_flags & flag_extra_tracker); } bool is_in_use() const { return is_enabled() && m_success_counter != 0; } bool is_scrapable() const { return (m_flags & flag_scrapable); } uint32_t normal_interval() const { return m_normal_interval; } uint32_t min_interval() const { return m_min_interval; } event_enum latest_event() const { return m_latest_event; } uint32_t latest_new_peers() const { return m_latest_new_peers; } uint32_t latest_sum_peers() const { return m_latest_sum_peers; } uint32_t success_time_next() const; uint32_t success_time_last() const { return m_success_time_last; } uint32_t success_counter() const { return m_success_counter; } uint32_t failed_time_next() const; uint32_t failed_time_last() const { return m_failed_time_last; } uint32_t failed_counter() const { return m_failed_counter; } uint32_t activity_time_last() const { return failed_counter() ? m_failed_time_last : m_success_time_last; } uint32_t activity_time_next() const { return failed_counter() ? failed_time_next() : success_time_next(); } uint32_t scrape_time_last() const { return m_scrape_time_last; } uint32_t scrape_counter() const { return m_scrape_counter; } uint32_t scrape_complete() const { return m_scrape_complete; } uint32_t scrape_incomplete() const { return m_scrape_incomplete; } uint32_t scrape_downloaded() const { return m_scrape_downloaded; } protected: friend class torrent::TrackerDht; friend class torrent::TrackerHttp; friend class torrent::TrackerList; friend class torrent::TrackerUdp; friend class torrent::TrackerWorker; friend class torrent::tracker::Tracker; friend class ::TrackerTest; void clear_intervals(); void clear_stats(); void set_normal_interval(int v); void set_min_interval(int v); void inc_request_counter(); int m_flags; uint32_t m_normal_interval{0}; uint32_t m_min_interval{0}; event_enum m_latest_event{EVENT_NONE}; uint32_t m_latest_new_peers{0}; uint32_t m_latest_new_peers_delta{0}; uint32_t m_latest_sum_peers{0}; uint32_t m_success_time_last{0}; uint32_t m_success_counter{0}; uint32_t m_failed_time_last{0}; uint32_t m_failed_counter{0}; uint32_t m_scrape_time_last{0}; uint32_t m_scrape_counter{0}; uint32_t m_scrape_complete{0}; uint32_t m_scrape_incomplete{0}; uint32_t m_scrape_downloaded{0}; }; inline uint32_t TrackerState::success_time_next() const { if (m_success_counter == 0) return 0; return m_success_time_last + std::max(m_normal_interval, static_cast(min_normal_interval)); } inline uint32_t TrackerState::failed_time_next() const { if (m_failed_counter == 0) return 0; if (m_min_interval > min_min_interval) return m_failed_time_last + m_min_interval; return m_failed_time_last + std::min(5 << std::min(m_failed_counter - 1, 6), min_min_interval - 1); } inline void TrackerState::clear_intervals() { m_normal_interval = 0; m_min_interval = 0; } inline void TrackerState::clear_stats() { m_latest_new_peers = 0; m_latest_sum_peers = 0; m_success_counter = 0; m_failed_counter = 0; m_scrape_counter = 0; } inline void TrackerState::set_normal_interval(int v) { m_normal_interval = std::min(std::max(min_normal_interval, v), max_normal_interval); } inline void TrackerState::set_min_interval(int v) { m_min_interval = std::min(std::max(min_min_interval, v), max_min_interval); } } // namespace tracker } // namespace torrent #endif // LIBTORRENT_TRACKER_TRACKER_STATE_H libtorrent-0.16.11/src/torrent/tracker/wrappers.cc0000644000000000000000000001014315175073411015567 #include "config.h" #include "torrent/tracker/wrappers.h" #include #include "tracker/tracker_list.h" #include "tracker/tracker_controller.h" namespace torrent::tracker { // Must be called from main thread. bool TrackerControllerWrapper::is_active() const { return m_ptr->is_active(); } bool TrackerControllerWrapper::is_requesting() const { return m_ptr->is_requesting(); } bool TrackerControllerWrapper::is_failure_mode() const { return m_ptr->is_failure_mode(); } bool TrackerControllerWrapper::is_promiscuous_mode() const { return m_ptr->is_promiscuous_mode(); } bool TrackerControllerWrapper::has_active_trackers() const { return m_ptr->tracker_list()->has_active(); } bool TrackerControllerWrapper::has_active_trackers_not_scrape() const { return m_ptr->tracker_list()->has_active_not_scrape(); } bool TrackerControllerWrapper::has_usable_trackers() const { return m_ptr->tracker_list()->has_usable(); } uint32_t TrackerControllerWrapper::key() const { return m_ptr->tracker_list()->key(); } int32_t TrackerControllerWrapper::numwant() const { return m_ptr->tracker_list()->numwant(); } void TrackerControllerWrapper::set_numwant(int32_t n) { m_ptr->tracker_list()->set_numwant(n); } uint32_t TrackerControllerWrapper::size() const { return m_ptr->tracker_list()->size(); } Tracker TrackerControllerWrapper::at(uint32_t index) const { // TODO: This function should make it a hard exception if the index is out of range, and have a // different function that can return invalid trackers. return m_ptr->tracker_list()->at(index); } void TrackerControllerWrapper::add_extra_tracker(uint32_t group, const std::string& url) { m_ptr->tracker_list()->insert_url(group, url, true); } uint32_t TrackerControllerWrapper::seconds_to_next_timeout() const { return m_ptr->seconds_to_next_timeout(); } uint32_t TrackerControllerWrapper::seconds_to_next_scrape() const { return m_ptr->seconds_to_next_scrape(); } void TrackerControllerWrapper::manual_request(bool request_now) { m_ptr->manual_request(request_now); } void TrackerControllerWrapper::scrape_request(uint32_t seconds_to_request) { m_ptr->scrape_request(seconds_to_request); } void TrackerControllerWrapper::cycle_group(uint32_t group) { m_ptr->tracker_list()->cycle_group(group); } // Algorithms: Tracker TrackerControllerWrapper::find_if(const std::function& f) { for (auto& tracker : *m_ptr->tracker_list()) { if (f(tracker)) return tracker; } return Tracker(std::shared_ptr()); } void TrackerControllerWrapper::for_each(const std::function& f) { for (auto& tracker : *m_ptr->tracker_list()) f(tracker); } Tracker TrackerControllerWrapper::c_find_if(const std::function& f) const { for (auto& tracker : *m_ptr->tracker_list()) { if (f(tracker)) return tracker; } return Tracker(std::shared_ptr()); } void TrackerControllerWrapper::c_for_each(const std::function& f) const { for (auto& tracker : *m_ptr->tracker_list()) f(tracker); } // Private: void TrackerControllerWrapper::enable() { m_ptr->enable(); } void TrackerControllerWrapper::enable_dont_reset_stats() { m_ptr->enable(TrackerController::enable_dont_reset_stats); } void TrackerControllerWrapper::disable() { m_ptr->disable(); } void TrackerControllerWrapper::close() { m_ptr->close(); } void TrackerControllerWrapper::send_start_event() { m_ptr->send_start_event(); } void TrackerControllerWrapper::send_stop_event() { m_ptr->send_stop_event(); } void TrackerControllerWrapper::send_completed_event() { m_ptr->send_completed_event(); } void TrackerControllerWrapper::send_update_event() { m_ptr->send_update_event(); } void TrackerControllerWrapper::start_requesting() { m_ptr->start_requesting(); } void TrackerControllerWrapper::stop_requesting() { m_ptr->stop_requesting(); } void TrackerControllerWrapper::set_slots(slot_address_list success, slot_string failure) { m_ptr->slot_success() = std::move(success); m_ptr->slot_failure() = std::move(failure); } } // namespace torrent::tracker libtorrent-0.16.11/src/torrent/rate.h0000644000000000000000000000736215175073411013077 // libTorrent - BitTorrent library // Copyright (C) 2005-2011, Jari Sundell // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // In addition, as a special exception, the copyright holders give // permission to link the code of portions of this program with the // OpenSSL library under certain conditions as described in each // individual source file, and distribute linked combinations // including the two. // // You must obey the GNU General Public License in all respects for // all of the code used other than OpenSSL. If you modify file(s) // with this exception, you may extend this exception to your version // of the file(s), but you are not obligated to do so. If you do not // wish to do so, delete this exception statement from your version. // If you delete this exception statement from all source files in the // program, then also delete it here. // // Contact: Jari Sundell // // Skomakerveien 33 // 3185 Skoppum, NORWAY #ifndef LIBTORRENT_UTILS_RATE_H #define LIBTORRENT_UTILS_RATE_H #include #include namespace torrent { // Keep the current rate count up to date for each call to rate() and // insert(...). This requires a mutable since rate() can be const, but // is justified as we avoid iterating the deque for each call. class LIBTORRENT_EXPORT Rate { public: using timer_type = int32_t; using rate_type = uint64_t; using total_type = uint64_t; using value_type = std::pair; using queue_type = std::deque; Rate(timer_type span) : m_span(span) {} // Bytes per second. rate_type rate() const; // Total bytes transfered. total_type total() const { return m_total; } void set_total(total_type bytes) { m_total = bytes; } // Interval in seconds used to calculate the rate. timer_type span() const { return m_span; } void set_span(timer_type s) { m_span = s; } void insert(rate_type bytes); void reset_rate() { m_current = 0; m_container.clear(); } bool operator < (Rate& r) const { return rate() < r.rate(); } bool operator > (Rate& r) const { return rate() > r.rate(); } bool operator == (Rate& r) const { return rate() == r.rate(); } bool operator != (Rate& r) const { return rate() != r.rate(); } bool operator < (rate_type r) const { return rate() < r; } bool operator > (rate_type r) const { return rate() > r; } bool operator == (rate_type r) const { return rate() == r; } bool operator != (rate_type r) const { return rate() != r; } private: inline void discard_old() const; mutable queue_type m_container; mutable rate_type m_current{0}; total_type m_total{0}; timer_type m_span; }; } // namespace torrent #endif libtorrent-0.16.11/src/torrent/download.cc0000644000000000000000000004034015175073411014102 #include "config.h" #include #include #include "data/block_list.h" #include "data/chunk_list.h" #include "data/hash_queue.h" #include "data/hash_torrent.h" #include "download/chunk_selector.h" #include "download/chunk_statistics.h" #include "download/download_wrapper.h" #include "protocol/peer_connection_base.h" #include "protocol/peer_factory.h" #include "torrent/data/file.h" #include "torrent/download/choke_group.h" #include "torrent/download/choke_queue.h" #include "torrent/download_info.h" #include "torrent/net/socket_address.h" #include "torrent/peer/connection_list.h" #include "torrent/utils/log.h" #include "exceptions.h" #include "download.h" #include "object.h" #include "throttle.h" #define LT_LOG_THIS(log_level, log_fmt, ...) \ lt_log_print_info(LOG_TORRENT_##log_level, m_ptr->info(), "download", log_fmt, __VA_ARGS__); namespace torrent { const DownloadInfo* Download::info() const { return m_ptr->info(); } const download_data* Download::data() const { return m_ptr->data(); } void Download::open(int flags) { if (m_ptr->info()->is_open()) return; LT_LOG_THIS(INFO, "Opening torrent: flags:%0x.", flags); // Currently always open with no_create, as start will make sure // they are created. Need to fix this. m_ptr->main()->open(FileList::open_no_create); m_ptr->hash_checker()->hashing_ranges().insert(0, m_ptr->main()->file_list()->size_chunks()); // Mark the files by default to be created and resized. The client // should be allowed to pass a flag that will keep the old settings, // although loading resume data should really handle everything // properly. int fileFlags = File::flag_create_queued | File::flag_resize_queued; if (flags & open_enable_fallocate) fileFlags |= File::flag_fallocate; for (auto& file : *m_ptr->main()->file_list()) file->set_flags(fileFlags); } void Download::close(int flags) { if (m_ptr->info()->is_active()) stop(0); LT_LOG_THIS(INFO, "Closing torrent: flags:%0x.", flags); m_ptr->close(); } void Download::start(int flags) { DownloadInfo* info = m_ptr->info(); if (!m_ptr->hash_checker()->is_checked()) throw internal_error("Tried to start an unchecked download."); if (!info->is_open()) throw internal_error("Tried to start a closed download."); if (m_ptr->data()->mutable_completed_bitfield()->empty()) throw internal_error("Tried to start a download with empty bitfield."); if (info->is_active()) return; LT_LOG_THIS(INFO, "Starting torrent: flags:%0x.", flags); m_ptr->data()->verify_wanted_chunks("Download::start(...)"); if (m_ptr->connection_type() == CONNECTION_INITIAL_SEED) { if (!m_ptr->main()->start_initial_seeding()) set_connection_type(CONNECTION_SEED); } m_ptr->main()->start(flags); if ((flags & start_skip_tracker)) m_ptr->main()->tracker_controller().enable_dont_reset_stats(); else m_ptr->main()->tracker_controller().enable(); // Reset the uploaded/download baseline when we restart the download // so that broken trackers get the right uploaded ratio. if (!(flags & start_keep_baseline)) { info->set_uploaded_baseline(info->up_rate()->total()); info->set_completed_baseline(m_ptr->main()->file_list()->completed_bytes()); lt_log_print_info(LOG_TRACKER_EVENTS, info, "download", "Setting new baseline on start: uploaded:%" PRIu64 " completed:%" PRIu64 ".", info->uploaded_baseline(), info->completed_baseline()); } if (!(flags & start_skip_tracker)) m_ptr->main()->tracker_controller().send_start_event(); } void Download::stop(int flags) { if (!m_ptr->info()->is_active()) return; LT_LOG_THIS(INFO, "Stopping torrent: flags:%0x.", flags); m_ptr->main()->stop(); if (!(flags & stop_skip_tracker)) m_ptr->main()->tracker_controller().send_stop_event(); m_ptr->main()->tracker_controller().disable(); } // When session data is loaded, it includes a bitfield and list of files+mtime. // // As the download is opened it checks the mtimes of the files, if the file is missing or has wrong mtime then // the file's range is added to hashing_ranges() and the bitfield range is cleared. // // Hash check with try_quick never does any actual hashing, it only checks if the underlying file // exists and if it does it fails the whole try_quick hash check. bool Download::hash_check(bool try_quick) { if (m_ptr->hash_checker()->is_checking()) throw internal_error("Download::hash_check(...) called but the hash is already being checked."); if (!m_ptr->info()->is_open() || m_ptr->info()->is_active()) throw internal_error("Download::hash_check(...) called on a closed or active download."); if (m_ptr->hash_checker()->is_checked()) throw internal_error("Download::hash_check(...) called but already hash checked."); Bitfield* bitfield = m_ptr->data()->mutable_completed_bitfield(); LT_LOG_THIS(INFO, "Checking hash: allocated:%i try_quick:%i.", !bitfield->empty(), (int)try_quick); if (bitfield->empty()) { // The bitfield still hasn't been allocated, so no resume data was // given. bitfield->allocate(); bitfield->unset_all(); m_ptr->hash_checker()->hashing_ranges().insert(0, m_ptr->main()->file_list()->size_chunks()); } else if (!try_quick) { // Clear ranges we're about to recheck so mark_completed can re-set them. for (auto range : m_ptr->hash_checker()->hashing_ranges()) bitfield->unset_range(range.first, range.second); // TODO: Consider adding a sanity check above instead, and print out the files (size+range) of // the invalid marked bit. } m_ptr->main()->file_list()->update_completed(); return m_ptr->hash_checker()->start(try_quick); } // Propably not correct, need to clear content, etc. void Download::hash_stop() { if (!m_ptr->hash_checker()->is_checking()) return; LT_LOG_THIS(INFO, "Hashing stopped.", 0); m_ptr->hash_checker()->hashing_ranges().erase(0, m_ptr->hash_checker()->position()); m_ptr->hash_queue()->remove(m_ptr->data()); m_ptr->hash_checker()->clear(); } bool Download::is_hash_checked() const { return m_ptr->hash_checker()->is_checked(); } bool Download::is_hash_checking() const { return m_ptr->hash_checker()->is_checking(); } void Download::set_pex_enabled(bool enabled) { if (enabled) m_ptr->info()->set_pex_enabled(); else m_ptr->info()->unset_flags(DownloadInfo::flag_pex_enabled); } Object* Download::bencode() { return m_ptr->bencode(); } const Object* Download::bencode() const { return m_ptr->bencode(); } FileList* Download::file_list() const { return m_ptr->main()->file_list(); } tracker::TrackerControllerWrapper Download::tracker_controller() { return m_ptr->main()->tracker_controller(); } const tracker::TrackerControllerWrapper Download::c_tracker_controller() const { return m_ptr->main()->tracker_controller(); } PeerList* Download::peer_list() { return m_ptr->main()->peer_list(); } const PeerList* Download::peer_list() const { return m_ptr->main()->peer_list(); } const TransferList* Download::transfer_list() const { return m_ptr->main()->delegator()->transfer_list(); } ConnectionList* Download::connection_list() { return m_ptr->main()->connection_list(); } const ConnectionList* Download::connection_list() const { return m_ptr->main()->connection_list(); } uint64_t Download::bytes_done() const { uint64_t a = m_ptr->main()->file_list()->completed_bytes(); for (auto list : *m_ptr->main()->delegator()->transfer_list()) a += std::accumulate(list->begin(), list->end(), uint64_t{}, [](auto sum, const auto& t) { return t.is_finished() ? sum + t.piece().length() : sum; }); return a; } uint32_t Download::chunks_hashed() const { return m_ptr->hash_checker()->position(); } const uint8_t* Download::chunks_seen() const { return !m_ptr->main()->chunk_statistics()->empty() ? &*m_ptr->main()->chunk_statistics()->begin() : NULL; } void Download::set_chunks_done(uint32_t chunks_done, uint32_t chunks_wanted) { if (m_ptr->info()->is_open() || !m_ptr->data()->mutable_completed_bitfield()->empty()) throw input_error("Download::set_chunks_done(...) Invalid state."); chunks_done = std::min(chunks_done, m_ptr->file_list()->size_chunks()); chunks_wanted = std::min(chunks_wanted, m_ptr->file_list()->size_chunks() - chunks_done); m_ptr->data()->mutable_completed_bitfield()->set_size_set(chunks_done); m_ptr->data()->set_wanted_chunks(chunks_wanted); } void Download::set_bitfield(bool allSet) { if (m_ptr->hash_checker()->is_checked() || m_ptr->hash_checker()->is_checking()) throw input_error("Download::set_bitfield(...) Download in invalid state."); Bitfield* bitfield = m_ptr->data()->mutable_completed_bitfield(); bitfield->allocate(); if (allSet) bitfield->set_all(); else bitfield->unset_all(); m_ptr->data()->update_wanted_chunks(); m_ptr->hash_checker()->hashing_ranges().clear(); } void Download::set_bitfield(const uint8_t* first, const uint8_t* last) { if (m_ptr->hash_checker()->is_checked() || m_ptr->hash_checker()->is_checking()) throw input_error("Download::set_bitfield(...) Download in invalid state."); if (std::distance(first, last) != static_cast(m_ptr->main()->file_list()->bitfield()->size_bytes())) throw input_error("Download::set_bitfield(...) Invalid length."); Bitfield* bitfield = m_ptr->data()->mutable_completed_bitfield(); bitfield->allocate(); std::memcpy(bitfield->begin(), first, bitfield->size_bytes()); bitfield->update(); m_ptr->data()->update_wanted_chunks(); m_ptr->hash_checker()->hashing_ranges().clear(); } void Download::update_range(int flags, uint32_t first, uint32_t last) { if (m_ptr->hash_checker()->is_checked() || m_ptr->hash_checker()->is_checking()) throw input_error("Download::clear_range(...) Download is hash checked/checking."); if (m_ptr->main()->file_list()->bitfield()->empty()) throw input_error("Download::clear_range(...) Bitfield is empty."); if (flags & update_range_recheck) m_ptr->hash_checker()->hashing_ranges().insert(first, last); if (flags & (update_range_clear | update_range_recheck)) { m_ptr->data()->mutable_completed_bitfield()->unset_range(first, last); m_ptr->data()->update_wanted_chunks(); } } void Download::sync_chunks() { m_ptr->main()->chunk_list()->sync_chunks(ChunkList::sync_all | ChunkList::sync_force); } uint32_t Download::peers_complete() const { return m_ptr->main()->chunk_statistics()->complete(); } uint32_t Download::peers_accounted() const { return m_ptr->main()->chunk_statistics()->accounted(); } uint32_t Download::peers_currently_unchoked() const { return m_ptr->main()->choke_group()->up_queue()->size_unchoked(); } uint32_t Download::peers_currently_interested() const { return m_ptr->main()->choke_group()->up_queue()->size_total(); } uint32_t Download::size_pex() const { return m_ptr->main()->info()->size_pex(); } uint32_t Download::max_size_pex() const { return m_ptr->main()->info()->max_size_pex(); } bool Download::accepting_new_peers() const { return m_ptr->info()->is_accepting_new_peers(); } // DEPRECATE uint32_t Download::uploads_max() const { if (m_ptr->main()->up_group_entry()->max_slots() == DownloadInfo::unlimited) return 0; return m_ptr->main()->up_group_entry()->max_slots(); } uint32_t Download::uploads_min() const { // if (m_ptr->main()->up_group_entry()->min_slots() == DownloadInfo::unlimited) // return 0; return m_ptr->main()->up_group_entry()->min_slots(); } uint32_t Download::downloads_max() const { if (m_ptr->main()->down_group_entry()->max_slots() == DownloadInfo::unlimited) return 0; return m_ptr->main()->down_group_entry()->max_slots(); } uint32_t Download::downloads_min() const { // if (m_ptr->main()->down_group_entry()->min_slots() == DownloadInfo::unlimited) // return 0; return m_ptr->main()->down_group_entry()->min_slots(); } void Download::set_upload_throttle(Throttle* t) { if (m_ptr->info()->is_active()) throw internal_error("Download::set_upload_throttle() called on active download."); m_ptr->main()->set_upload_throttle(t->throttle_list()); } void Download::set_download_throttle(Throttle* t) { if (m_ptr->info()->is_active()) throw internal_error("Download::set_download_throttle() called on active download."); m_ptr->main()->set_download_throttle(t->throttle_list()); } void Download::send_completed() { m_ptr->main()->tracker_controller().send_completed_event(); } void Download::manual_request(bool force) { m_ptr->main()->tracker_controller().manual_request(force); } void Download::manual_cancel() { m_ptr->main()->tracker_controller().close(); } // DEPRECATE void Download::set_uploads_max(uint32_t v) { if (v > (1 << 16)) throw input_error("Max uploads must be between 0 and 2^16."); // For the moment, treat 0 as unlimited. m_ptr->main()->up_group_entry()->set_max_slots(v == 0 ? DownloadInfo::unlimited : v); m_ptr->main()->choke_group()->up_queue()->balance_entry(m_ptr->main()->up_group_entry()); } void Download::set_uploads_min(uint32_t v) { if (v > (1 << 16)) throw input_error("Min uploads must be between 0 and 2^16."); // For the moment, treat 0 as unlimited. m_ptr->main()->up_group_entry()->set_min_slots(v); m_ptr->main()->choke_group()->up_queue()->balance_entry(m_ptr->main()->up_group_entry()); } void Download::set_downloads_max(uint32_t v) { if (v > (1 << 16)) throw input_error("Max downloads must be between 0 and 2^16."); // For the moment, treat 0 as unlimited. m_ptr->main()->down_group_entry()->set_max_slots(v == 0 ? DownloadInfo::unlimited : v); m_ptr->main()->choke_group()->down_queue()->balance_entry(m_ptr->main()->down_group_entry()); } void Download::set_downloads_min(uint32_t v) { if (v > (1 << 16)) throw input_error("Min downloads must be between 0 and 2^16."); // For the moment, treat 0 as unlimited. m_ptr->main()->down_group_entry()->set_min_slots(v); m_ptr->main()->choke_group()->down_queue()->balance_entry(m_ptr->main()->down_group_entry()); } Download::ConnectionType Download::connection_type() const { return static_cast(m_ptr->connection_type()); } void Download::set_connection_type(ConnectionType t) { if (m_ptr->info()->is_meta_download()) { m_ptr->main()->connection_list()->slot_new_connection(&createPeerConnectionMetadata); return; } switch (t) { case CONNECTION_LEECH: m_ptr->main()->connection_list()->slot_new_connection(&createPeerConnectionDefault); break; case CONNECTION_SEED: m_ptr->main()->connection_list()->slot_new_connection(&createPeerConnectionSeed); break; case CONNECTION_INITIAL_SEED: if (info()->is_active() && m_ptr->main()->initial_seeding() == NULL) throw input_error("Can't switch to initial seeding: download is active."); m_ptr->main()->connection_list()->slot_new_connection(&createPeerConnectionInitialSeed); break; default: throw input_error("torrent::Download::set_connection_type(...) received an unknown type."); } m_ptr->set_connection_type(t); } Download::HeuristicType Download::upload_choke_heuristic() const { return static_cast(m_ptr->main()->choke_group()->up_queue()->heuristics()); } void Download::set_upload_choke_heuristic(HeuristicType t) { if (static_cast(t) >= choke_queue::HEURISTICS_MAX_SIZE) throw input_error("Invalid heuristics value."); m_ptr->main()->choke_group()->up_queue()->set_heuristics(static_cast(t)); } Download::HeuristicType Download::download_choke_heuristic() const { return static_cast(m_ptr->main()->choke_group()->down_queue()->heuristics()); } void Download::set_download_choke_heuristic(HeuristicType t) { if (static_cast(t) >= choke_queue::HEURISTICS_MAX_SIZE) throw input_error("Invalid heuristics value."); m_ptr->main()->choke_group()->down_queue()->set_heuristics(static_cast(t)); } void Download::update_priorities() { m_ptr->receive_update_priorities(); } void Download::add_peer(const sockaddr* sa, int port) { if (m_ptr->info()->is_private()) return; auto tmp = sa_copy(sa); sap_set_port(tmp, port); m_ptr->main()->add_peer(tmp.get()); } DownloadMain* Download::main() { return m_ptr->main(); } } // namespace torrent libtorrent-0.16.11/src/torrent/object_static_map.h0000644000000000000000000000475115175073411015615 #ifndef LIBTORRENT_OBJECT_STATIC_MAP_H #define LIBTORRENT_OBJECT_STATIC_MAP_H #include #include #include namespace torrent { struct static_map_mapping_type { static constexpr size_t max_key_size = 16; bool is_end() const { return key[0] == '\0'; } static bool is_not_key_char(char c) { return c == '\0' || c == ':' || c == '[' || c == '*'; } const char* find_key_end(const char* pos) const { return std::find_if(pos, key + max_key_size, &is_not_key_char); } uint32_t index; char key[max_key_size]; }; struct static_map_entry_type { torrent::Object object; }; template class static_map_type { public: using value_type = Object; using key_type = tmpl_key_type; using entry_type = static_map_entry_type; using mapping_type = static_map_mapping_type; typedef mapping_type key_list_type[tmpl_length]; typedef entry_type value_list_type[tmpl_length]; static constexpr size_t size = tmpl_length; static const key_list_type keys; entry_type* values() { return m_values; } const entry_type* values() const { return m_values; } Object& operator [] (key_type key) { return m_values[key].object; } const Object& operator [] (key_type key) const { return m_values[key].object; } private: value_list_type m_values; }; // // Helper functions/classes for parsing keys: // struct static_map_stack_type { void set_key_index(uint32_t start_index, uint32_t end_index, uint32_t delim_size, torrent::Object::type_type type = Object::TYPE_MAP) { key_index = start_index; next_key = end_index + delim_size; obj_type = type; } void clear() { key_index = 0; next_key = 0; obj_type = Object::TYPE_MAP; } uint32_t key_index; uint32_t next_key; Object::type_type obj_type; }; using static_map_key_search_result = std::pair; // Note that the key for both functions must be null-terminated at // 'key_last'. static_map_key_search_result find_key_match(const static_map_mapping_type* first, const static_map_mapping_type* last, const char* key_first, const char* key_last) LIBTORRENT_EXPORT; inline static_map_key_search_result find_key_match(const static_map_mapping_type* first, const static_map_mapping_type* last, const char* key) { return find_key_match(first, last, key, key + strlen(key)); } } // namespace torrent #endif libtorrent-0.16.11/src/torrent/peer/0000755000000000000000000000000015175073434013003 5libtorrent-0.16.11/src/torrent/peer/peer.h0000644000000000000000000000441415175073411014025 #ifndef LIBTORRENT_PEER_H #define LIBTORRENT_PEER_H #include #include namespace torrent { class PeerConnectionBase; // == and = operators works as expected. // The Peer class is a wrapper around the internal peer class. This // peer class may be invalidated during a torrent::work call. So if // you keep a list or single instances in the client, you need to // listen to the appropriate signals from the download to keep up to // date. class LIBTORRENT_EXPORT Peer { public: virtual ~Peer(); Peer(const Peer&) = delete; Peer& operator=(const Peer&) = delete; // Does not check if it has been removed from the download. bool is_incoming() const; bool is_encrypted() const; bool is_obfuscated() const; bool is_up_choked() const; bool is_up_interested() const; bool is_down_choked() const; bool is_down_choked_limited() const; bool is_down_queued() const; bool is_down_interested() const; bool is_snubbed() const; bool is_banned() const; void set_snubbed(bool v); void set_banned(bool v); const HashString& id() const; const char* options() const; const sockaddr* address() const; const Rate* down_rate() const; const Rate* up_rate() const; const Rate* peer_rate() const; const Bitfield* bitfield() const; const BlockTransfer* transfer() const; uint32_t incoming_queue_size() const; uint32_t outgoing_queue_size() const; uint32_t chunks_done() const; uint32_t failed_counter() const; void disconnect(int flags); // // New interface: // const PeerInfo* peer_info() const { return m_peerInfo; } PeerConnectionBase* m_ptr() { return reinterpret_cast(this); } const PeerConnectionBase* c_ptr() const { return reinterpret_cast(this); } protected: Peer() = default; bool operator == (const Peer& p) const; PeerInfo* m_peerInfo; }; } // namespace torrent #endif libtorrent-0.16.11/src/torrent/peer/peer_info.h0000644000000000000000000001162215175073411015037 #ifndef LIBTORRENT_PEER_INFO_H #define LIBTORRENT_PEER_INFO_H #include #include #include #include namespace torrent { class LIBTORRENT_EXPORT PeerInfo { public: friend class ConnectionList; friend class Handshake; friend class HandshakeManager; friend class InitialSeeding; friend class PeerList; friend class ProtocolExtension; static constexpr int flag_connected = (1 << 0); static constexpr int flag_incoming = (1 << 1); static constexpr int flag_handshake = (1 << 2); static constexpr int flag_blocked = (1 << 3); // For initial seeding. static constexpr int flag_restart = (1 << 4); static constexpr int flag_unwanted = (1 << 5); static constexpr int flag_preferred = (1 << 6); static constexpr int mask_ip_table = flag_unwanted | flag_preferred; PeerInfo(const sockaddr* address); ~PeerInfo(); bool is_connected() const { return m_flags & flag_connected; } bool is_incoming() const { return m_flags & flag_incoming; } bool is_handshake() const { return m_flags & flag_handshake; } bool is_blocked() const { return m_flags & flag_blocked; } bool is_restart() const { return m_flags & flag_restart; } bool is_unwanted() const { return m_flags & flag_unwanted; } bool is_preferred() const { return m_flags & flag_preferred; } int flags() const { return m_flags; } const HashString& id() const { return m_id; } const char* id_hex() const { return m_id_hex; } const ClientInfo& client_info() const { return m_clientInfo; } const char* options() const { return m_options; } const sockaddr* socket_address() const { return m_address.get(); } uint16_t listen_port() const { return m_listenPort; } uint32_t failed_counter() const { return m_failedCounter; } void set_failed_counter(uint32_t c) { m_failedCounter = c; } uint32_t transfer_counter() const { return m_transferCounter; } uint32_t last_connection() const { return m_lastConnection; } void set_last_connection(uint32_t tvsec) { m_lastConnection = tvsec; } uint32_t last_handshake() const { return m_lastHandshake; } void set_last_handshake(uint32_t tvsec) { m_lastHandshake = tvsec; } bool supports_dht() const { return m_options[7] & 0x01; } bool supports_extensions() const { return m_options[5] & 0x10; } // // Internal to libTorrent: // PeerConnectionBase* connection() { return m_connection; } void inc_transfer_counter(); void dec_transfer_counter(); protected: void set_flags(int flags) { m_flags |= flags; } void unset_flags(int flags) { m_flags &= ~flags; } HashString& mutable_id() { return m_id; } char* mutable_id_hex() { return m_id_hex; } ClientInfo& mutable_client_info() { return m_clientInfo; } void set_port(uint16_t port) LIBTORRENT_NO_EXPORT; void set_listen_port(uint16_t port) { m_listenPort = port; } char* set_options() { return m_options; } void set_connection(PeerConnectionBase* c) { m_connection = c; } private: PeerInfo(const PeerInfo&) = delete; PeerInfo& operator=(const PeerInfo&) = delete; // Replace id with a char buffer, or a cheap struct? int m_flags{0}; HashString m_id; char m_id_hex[40]; ClientInfo m_clientInfo; char m_options[8]; uint32_t m_failedCounter{0}; uint32_t m_transferCounter{0}; uint32_t m_lastConnection{0}; uint32_t m_lastHandshake{0}; uint16_t m_listenPort{0}; sa_unique_ptr m_address; PeerConnectionBase* m_connection{}; }; inline void PeerInfo::inc_transfer_counter() { if (m_transferCounter == ~uint32_t()) throw internal_error("PeerInfo::inc_transfer_counter() m_transferCounter overflow"); m_transferCounter++; } inline void PeerInfo::dec_transfer_counter() { if (m_transferCounter == 0) throw internal_error("PeerInfo::dec_transfer_counter() m_transferCounter underflow"); m_transferCounter--; } } // namespace torrent #endif libtorrent-0.16.11/src/torrent/peer/connection_list.h0000644000000000000000000000756715175073411016300 #ifndef LIBTORRENT_PEER_CONNECTION_LIST_H #define LIBTORRENT_PEER_CONNECTION_LIST_H #include #include #include #include #include namespace torrent { class AddressList; class Bitfield; class DownloadMain; class DownloadWrapper; class Peer; class PeerConnectionBase; class PeerInfo; class ProtocolExtension; class EncryptionInfo; class HandshakeManager; class LIBTORRENT_EXPORT ConnectionList : private std::vector { public: friend class DownloadMain; friend class DownloadWrapper; friend class HandshakeManager; using base_type = std::vector; using queue_type = std::vector; using size_type = uint32_t; using slot_peer_type = std::function; using signal_peer_type = std::list; using slot_new_conn_type = PeerConnectionBase* (*)(bool encrypted); using base_type::value_type; using base_type::reference; using base_type::difference_type; using base_type::iterator; using base_type::reverse_iterator; using base_type::const_iterator; using base_type::const_reverse_iterator; // using base_type::size; using base_type::empty; using base_type::front; using base_type::back; using base_type::begin; using base_type::end; using base_type::rbegin; using base_type::rend; // Make sure any change here match PeerList's flags. static constexpr int disconnect_available = (1 << 0); static constexpr int disconnect_quick = (1 << 1); static constexpr int disconnect_unwanted = (1 << 2); static constexpr int disconnect_delayed = (1 << 3); ConnectionList(DownloadMain* download); ~ConnectionList() = default; ConnectionList(const ConnectionList&) = delete; ConnectionList& operator=(const ConnectionList&) = delete; // Make these protected? iterator erase(iterator pos, int flags); void erase(Peer* p, int flags); void erase(PeerInfo* peerInfo, int flags); void erase_remaining(iterator pos, int flags); void erase_seeders(); iterator find(const char* id); iterator find(const sockaddr* sa); size_type min_size() const { return m_minSize; } void set_min_size(size_type v); size_type size() const { return base_type::size(); } size_type max_size() const { return m_maxSize; } void set_max_size(size_type v); // Removes from 'l' addresses that are already connected to. Assumes // 'l' is sorted and unique. void set_difference(AddressList* l); signal_peer_type& signal_connected() { return m_signalConnected; } signal_peer_type& signal_disconnected() { return m_signalDisconnected; } // Move to protected: void slot_new_connection(slot_new_conn_type s) { m_slotNewConnection = s; } protected: // Does not do the usual cleanup done by 'erase'. void clear() LIBTORRENT_NO_EXPORT; bool want_connection(PeerInfo* p, Bitfield* bitfield); // Returns NULL if the connection was not added, the caller is then // responsible for cleaning up 'fd'. // // Clean this up, don't use this many arguments. PeerConnectionBase* insert(PeerInfo* p, int fd, Bitfield* bitfield, EncryptionInfo* encryptionInfo, ProtocolExtension* extensions) LIBTORRENT_NO_EXPORT; void disconnect_queued() LIBTORRENT_NO_EXPORT; private: DownloadMain* m_download; size_type m_minSize{50}; size_type m_maxSize{100}; signal_peer_type m_signalConnected; signal_peer_type m_signalDisconnected; slot_new_conn_type m_slotNewConnection; queue_type m_disconnectQueue; }; } // namespace torrent #endif libtorrent-0.16.11/src/torrent/peer/peer.cc0000644000000000000000000000547015175073411014166 #include "config.h" #include "data/block_transfer.h" #include "download/download_main.h" #include "protocol/peer_chunks.h" #include "protocol/peer_connection_base.h" #include "torrent/download/choke_queue.h" #include "connection_list.h" #include "peer.h" #include "peer_info.h" #include "rate.h" namespace torrent { Peer::~Peer() = default; bool Peer::is_incoming() const { return peer_info()->is_incoming(); } bool Peer::is_encrypted() const { return c_ptr()->is_encrypted(); } bool Peer::is_obfuscated() const { return c_ptr()->is_obfuscated(); } bool Peer::is_up_choked() const { return c_ptr()->is_up_choked(); } bool Peer::is_up_interested() const { return c_ptr()->is_down_interested(); } bool Peer::is_down_choked() const { return !c_ptr()->is_down_remote_unchoked(); } bool Peer::is_down_choked_limited() const { return !c_ptr()->is_down_local_unchoked(); } bool Peer::is_down_queued() const { return c_ptr()->is_down_queued(); } bool Peer::is_down_interested() const { return c_ptr()->is_up_interested(); } bool Peer::is_snubbed() const { return c_ptr()->is_up_snubbed(); } bool Peer::is_banned() const { return m_peerInfo->failed_counter() >= 64; } void Peer::set_snubbed(bool v) { m_ptr()->set_upload_snubbed(v); } void Peer::set_banned(bool v) { m_peerInfo->set_failed_counter(v ? 64 : 0); } const HashString& Peer::id() const { return peer_info()->id(); } const char* Peer::options() const { return peer_info()->options(); } const sockaddr* Peer::address() const { return peer_info()->socket_address(); } const Rate* Peer::down_rate() const { return c_ptr()->c_peer_chunks()->download_throttle()->rate(); } const Rate* Peer::up_rate() const { return c_ptr()->c_peer_chunks()->upload_throttle()->rate(); } const Rate* Peer::peer_rate() const { return c_ptr()->c_peer_chunks()->peer_rate(); } const Bitfield* Peer::bitfield() const { return c_ptr()->c_peer_chunks()->bitfield(); } uint32_t Peer::incoming_queue_size() const { return c_ptr()->request_list()->queued_size(); } uint32_t Peer::outgoing_queue_size() const { return c_ptr()->c_peer_chunks()->upload_queue()->size(); } uint32_t Peer::chunks_done() const { return c_ptr()->c_peer_chunks()->bitfield()->size_set(); } uint32_t Peer::failed_counter() const { return peer_info()->failed_counter(); } const BlockTransfer* Peer::transfer() const { if (c_ptr()->request_list()->transfer() != NULL) return c_ptr()->request_list()->transfer(); else if (!c_ptr()->request_list()->queued_empty()) return c_ptr()->request_list()->queued_front(); else return NULL; } void Peer::disconnect(int flags) { m_ptr()->download()->connection_list()->erase(this, flags); } } // namespace torrent libtorrent-0.16.11/src/torrent/peer/client_info.h0000644000000000000000000001046715175073411015370 // libTorrent - BitTorrent library // Copyright (C) 2005-2011, Jari Sundell // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // In addition, as a special exception, the copyright holders give // permission to link the code of portions of this program with the // OpenSSL library under certain conditions as described in each // individual source file, and distribute linked combinations // including the two. // // You must obey the GNU General Public License in all respects for // all of the code used other than OpenSSL. If you modify file(s) // with this exception, you may extend this exception to your version // of the file(s), but you are not obligated to do so. If you do not // wish to do so, delete this exception statement from your version. // If you delete this exception statement from all source files in the // program, then also delete it here. // // Contact: Jari Sundell // // Skomakerveien 33 // 3185 Skoppum, NORWAY #ifndef LIBTORRENT_PEER_CLIENT_INFO_H #define LIBTORRENT_PEER_CLIENT_INFO_H #include namespace torrent { class LIBTORRENT_EXPORT ClientInfo { public: friend class ClientList; enum id_type { TYPE_UNKNOWN, TYPE_AZUREUS, TYPE_COMPACT, TYPE_MAINLINE, TYPE_MAX_SIZE }; static constexpr uint32_t max_key_size = 2; static constexpr uint32_t max_version_size = 4; id_type type() const { return m_type; } const char* key() const { return m_key; } const char* version() const { return m_version; } const char* upper_version() const { return m_upperVersion; } const char* short_description() const { return m_info; } void set_short_description(const char* str) { m_info = str; } static unsigned int key_size(id_type id); static unsigned int version_size(id_type id); // The intersect/disjoint postfix indicates what kind of equivalence // comparison we get when using !less && !greater. static bool less_intersects(const ClientInfo& left, const ClientInfo& right); static bool less_disjoint(const ClientInfo& left, const ClientInfo& right); static bool greater_intersects(const ClientInfo& left, const ClientInfo& right); static bool greater_disjoint(const ClientInfo& left, const ClientInfo& right); static bool intersects(const ClientInfo& left, const ClientInfo& right); static bool equal_to(const ClientInfo& left, const ClientInfo& right); protected: void set_type(id_type t) { m_type = t; } const char* info() const { return m_info; } void set_info(const char* ptr) { m_info = ptr; } char* mutable_key() { return m_key; } char* mutable_version() { return m_version; } char* mutable_upper_version() { return m_upperVersion; } private: id_type m_type; char m_key[max_key_size]; // The client version. The ClientInfo object in ClientList bounds // the versions that this object applies to. When the user searches // the ClientList for a client id, m_version will be set to the // actual client version. char m_version[max_version_size]; char m_upperVersion[max_version_size]; // We don't really care about cleaning up this as deleting an entry // form ClientList shouldn't happen. const char* m_info{}; }; } // namespace torrent #endif libtorrent-0.16.11/src/torrent/peer/client_list.h0000644000000000000000000000607415175073411015407 // libTorrent - BitTorrent library // Copyright (C) 2005-2011, Jari Sundell // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // In addition, as a special exception, the copyright holders give // permission to link the code of portions of this program with the // OpenSSL library under certain conditions as described in each // individual source file, and distribute linked combinations // including the two. // // You must obey the GNU General Public License in all respects for // all of the code used other than OpenSSL. If you modify file(s) // with this exception, you may extend this exception to your version // of the file(s), but you are not obligated to do so. If you do not // wish to do so, delete this exception statement from your version. // If you delete this exception statement from all source files in the // program, then also delete it here. // // Contact: Jari Sundell // // Skomakerveien 33 // 3185 Skoppum, NORWAY #ifndef LIBTORRENT_PEER_CLIENT_LIST_H #define LIBTORRENT_PEER_CLIENT_LIST_H #include #include namespace torrent { class LIBTORRENT_EXPORT ClientList : private std::vector { public: using base_type = std::vector; using size_type = uint32_t; using base_type::value_type; using base_type::reference; using base_type::difference_type; using base_type::iterator; using base_type::reverse_iterator; using base_type::size; using base_type::empty; using base_type::begin; using base_type::end; using base_type::rbegin; using base_type::rend; ClientList(); ~ClientList() = default; ClientList(const ClientList&) = delete; ClientList& operator=(const ClientList&) = delete; iterator insert(ClientInfo::id_type type, const char* key, const char* version, const char* upperVersion); // Helper functions which only require the key to be as long as the // key for that specific id type. iterator insert_helper(ClientInfo::id_type type, const char* key, const char* version, const char* upperVersion, const char* shortDescription); bool retrieve_id(ClientInfo* dest, const HashString& id) const; void retrieve_unknown(ClientInfo* dest) const; }; } // namespace torrent #endif libtorrent-0.16.11/src/torrent/peer/client_info.cc0000644000000000000000000000764115175073411015526 // libTorrent - BitTorrent library // Copyright (C) 2005-2011, Jari Sundell // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // In addition, as a special exception, the copyright holders give // permission to link the code of portions of this program with the // OpenSSL library under certain conditions as described in each // individual source file, and distribute linked combinations // including the two. // // You must obey the GNU General Public License in all respects for // all of the code used other than OpenSSL. If you modify file(s) // with this exception, you may extend this exception to your version // of the file(s), but you are not obligated to do so. If you do not // wish to do so, delete this exception statement from your version. // If you delete this exception statement from all source files in the // program, then also delete it here. // // Contact: Jari Sundell // // Skomakerveien 33 // 3185 Skoppum, NORWAY #include "config.h" #include #include "client_info.h" namespace torrent { unsigned int ClientInfo::key_size(id_type id) { switch (id) { case TYPE_AZUREUS: return 2; case TYPE_COMPACT: case TYPE_MAINLINE: return 1; default: return 0; } } unsigned int ClientInfo::version_size(id_type id) { switch (id) { case TYPE_AZUREUS: return 4; case TYPE_COMPACT: case TYPE_MAINLINE: return 3; default: return 0; } } bool ClientInfo::less_intersects(const ClientInfo& left, const ClientInfo& right) { if (left.type() > right.type()) return false; else if (left.type() < right.type()) return true; int keyComp = std::memcmp(left.key(), right.key(), ClientInfo::max_key_size); return keyComp < 0 || (keyComp == 0 && std::memcmp(left.upper_version(), right.version(), ClientInfo::max_version_size) < 0); } bool ClientInfo::less_disjoint(const ClientInfo& left, const ClientInfo& right) { if (left.type() > right.type()) return false; else if (left.type() < right.type()) return true; int keyComp = std::memcmp(left.key(), right.key(), ClientInfo::max_key_size); return keyComp < 0 || (keyComp == 0 && std::memcmp(left.version(), right.upper_version(), ClientInfo::max_version_size) < 0); } bool ClientInfo::greater_intersects(const ClientInfo& left, const ClientInfo& right) { return less_intersects(right, left); } bool ClientInfo::greater_disjoint(const ClientInfo& left, const ClientInfo& right) { return less_disjoint(right, left); } bool ClientInfo::intersects(const ClientInfo& left, const ClientInfo& right) { return left.type() == right.type() && std::memcmp(left.key(), right.key(), ClientInfo::max_key_size) == 0 && std::memcmp(left.version(), right.upper_version(), ClientInfo::max_version_size) <= 0 && std::memcmp(left.upper_version(), right.version(), ClientInfo::max_version_size) >= 0; } inline bool ClientInfo::equal_to(const ClientInfo& left, const ClientInfo& right) { return left.type() == right.type() && std::memcmp(left.key(), right.key(), ClientInfo::max_key_size) == 0 && std::memcmp(left.version(), right.version(), ClientInfo::max_version_size) == 0 && std::memcmp(left.upper_version(), right.upper_version(), ClientInfo::max_version_size) == 0; } } // namespace torrent libtorrent-0.16.11/src/torrent/peer/peer_list.cc0000644000000000000000000003125115175073411015215 #include "config.h" #include "peer_list.h" #include #include "manager.h" #include "download/available_list.h" #include "torrent/download_info.h" #include "torrent/exceptions.h" #include "torrent/net/socket_address.h" #include "torrent/peer/client_list.h" #include "torrent/peer/peer_info.h" #include "torrent/utils/log.h" #define LT_LOG_EVENTS(log_fmt, ...) \ lt_log_print_info(LOG_PEER_LIST_EVENTS, m_info, "peer_list", log_fmt, __VA_ARGS__); #define LT_LOG_ADDRESS(log_fmt, ...) \ lt_log_print_info(LOG_PEER_LIST_ADDRESS, m_info, "peer_list", log_fmt, __VA_ARGS__); namespace torrent { ipv4_table PeerList::m_ipv4_table; PeerList::PeerList() : m_available_list(new AvailableList) { } PeerList::~PeerList() { LT_LOG_EVENTS("deleting list total:%zu available:%zu", size(), m_available_list->size()); base_type::clear(); m_info = nullptr; } void PeerList::set_info(DownloadInfo* info) { m_info = info; LT_LOG_EVENTS("creating list", 0); } PeerInfo* PeerList::insert_address(const sockaddr* sa, int flags) { socket_address_key sock_key = socket_address_key::from_sockaddr(sa); if (sock_key.is_valid() && !socket_address_key::is_comparable_sockaddr(sa)) { LT_LOG_EVENTS("adding address: not comparable: %s", sa_pretty_str(sa).c_str()); return nullptr; } range_type range = base_type::equal_range(sock_key); auto addr_str = sa_addr_str(sa); auto port = sa_port(sa); // Do some special handling if we got a new port number but the // address was present. // // What we do depends on the flags, but for now just allow one // PeerInfo per address key and do nothing. if (range.first != range.second) { LT_LOG_EVENTS("adding address: already exists: %s", sa_pretty_str(sa).c_str()); return nullptr; } auto peer_info = std::make_unique(sa); peer_info->set_listen_port(port); if (sa->sa_family == AF_INET) { // IPv4 addresses are stored in host byte order in ipv4_table so they are comparable. uint32_t host_byte_order_ipv4_addr = ntohl(reinterpret_cast(sa)->sin_addr.s_addr); if(m_ipv4_table.defined(host_byte_order_ipv4_addr)) peer_info->set_flags(m_ipv4_table.at(host_byte_order_ipv4_addr) & PeerInfo::mask_ip_table); } else if (sa->sa_family == AF_INET6) { // Currently nothing to do for IPv6 addresses. } else { throw internal_error("PeerList::insert_address() only supports INET/INET6 addresses"); } manager->client_list()->retrieve_unknown(&peer_info->mutable_client_info()); if ((flags & address_available) && peer_info->listen_port() != 0) { m_available_list->insert_unique(sa); LT_LOG_EVENTS("adding address: available : %s", sa_pretty_str(sa).c_str()); } else { LT_LOG_EVENTS("adding address: unavailable : %s", sa_pretty_str(sa).c_str()); } auto itr = base_type::insert(range.second, value_type(sock_key, peer_info.release())); return itr->second.get(); } uint32_t PeerList::insert_available(const void* al) { auto address_list = static_cast(al); uint32_t inserted = 0; uint32_t invalid = 0; uint32_t unneeded = 0; uint32_t updated = 0; if (m_available_list->size() + address_list->size() > m_available_list->capacity()) m_available_list->reserve(m_available_list->size() + address_list->size() + 128); // Optimize this so that we don't traverse the tree for every // insert, since we know 'al' is sorted. auto avail_itr = m_available_list->begin(); auto avail_last = m_available_list->end(); for (const auto& addr : *address_list) { auto addr_str = sa_addr_str(&addr.sa); auto port = sa_port(&addr.sa); if (!socket_address_key::is_comparable_sockaddr(&addr.sa) || port == 0) { invalid++; LT_LOG_ADDRESS("adding available address: skipped invalid : %s", sa_pretty_str(&addr.sa).c_str()); continue; } // TODO: Verify we only want to check the address and not the port. avail_itr = std::find_if(avail_itr, avail_last, [&addr](auto& sa) { return sa_less_addr(&sa.sa, &addr.sa); }); if (avail_itr != avail_last && !sa_less_addr(&avail_itr->sa, &addr.sa)) { // The address is already in m_available_list, so don't bother // going further. unneeded++; continue; } socket_address_key sock_key = socket_address_key::from_sockaddr(&addr.sa); // Check if the peerinfo exists, if it does, check if we would // ever want to connect. Just update the timer for the last // availability notice if the peer isn't really ideal, but might // be used in an emergency. range_type range = base_type::equal_range(sock_key); if (range.first != range.second) { // Add some logic here to select the best PeerInfo, but for now // just assume the first one is the only one that exists. PeerInfo* peer_info = range.first->second.get(); if (peer_info->listen_port() == 0) peer_info->set_port(port); if (peer_info->connection() != nullptr || peer_info->last_handshake() + 600 > static_cast(this_thread::cached_seconds().count())) { updated++; continue; } // If the peer has sent us bad chunks or we just connected or // tried to do so a few minutes ago, only update its // availability timer. } // Should we perhaps add to available list even though we don't // want the peer, just to ensure we don't need to search for the // PeerInfo every time it gets reported. Though I'd assume it // won't happen often enough to be worth it. inserted++; m_available_list->insert_unique(&addr.sa); LT_LOG_ADDRESS("adding available address: %s", sa_pretty_str(&addr.sa).c_str()); } LT_LOG_EVENTS("inserted peers" " inserted:%" PRIu32 " invalid:%" PRIu32 " unneeded:%" PRIu32 " updated:%" PRIu32 " total:%" PRIuPTR " available:%" PRIuPTR, inserted, invalid, unneeded, updated, size(), m_available_list->size()); return inserted; } uint32_t PeerList::available_list_size() const { return m_available_list->size(); } // TODO: Rename connecting: PeerInfo* PeerList::connected(const sockaddr* sa, int flags) { // TODO: Rewrite to use new socket address api after fixing bug. // TODO: Handle 4in6 addresses. auto sock_key = socket_address_key::from_sockaddr(sa); auto addr_str = sa_addr_str(sa); auto port = sa_port(sa); if (!sock_key.is_valid() || !socket_address_key::is_comparable_sockaddr(sa)) return nullptr; int filter_value = 0; if (sa->sa_family == AF_INET) { uint32_t host_byte_order_ipv4_addr = ntohl(reinterpret_cast(sa)->sin_addr.s_addr); // IPv4 addresses stored in host byte order in ipv4_table so they are comparable. ntohl has been called if(m_ipv4_table.defined(host_byte_order_ipv4_addr)) filter_value = m_ipv4_table.at(host_byte_order_ipv4_addr); // We should also remove any PeerInfo objects already for this // address. if ((filter_value & PeerInfo::flag_unwanted)) { LT_LOG_EVENTS("connecting peer rejected: flagged as unwanted : %s", sa_pretty_str(sa).c_str()); return nullptr; } } else if (sa->sa_family == AF_INET6) { // Filtering not supported for IPv6 yet. } else { throw internal_error("PeerList::connected() with invalid address family"); } PeerInfo* peer_info; range_type range = base_type::equal_range(sock_key); if (range.first == range.second) { // Create a new entry. peer_info = new PeerInfo(sa); peer_info->set_flags(filter_value & PeerInfo::mask_ip_table); base_type::insert(range.second, value_type(sock_key, peer_info)); } else if (!range.first->second->is_connected()) { // Use an old entry. peer_info = range.first->second.get(); peer_info->set_port(port); } else { // Make sure we don't end up throwing away the port the host is // actually listening on, when there may be several simultaneous // connection attempts to/from different ports. // // This also ensure we can connect to peers running on the same // host as the tracker. // if (flags & connect_keep_handshakes && // range.first->second->is_handshake() && // range.first->second->socket_address()->port() != address->port()) // m_available_list->buffer()->push_back(*address); LT_LOG_EVENTS("connecting peer rejected: already connected (buggy, fixme) : %s", sa_pretty_str(sa).c_str()); // TODO: Verify this works properly, possibly add a check/flag // that allows the handshake manager to notify peer list if the // incoming connection was a duplicate peer hash. //return nullptr; peer_info = new PeerInfo(sa); peer_info->set_flags(filter_value & PeerInfo::mask_ip_table); base_type::insert(range.second, value_type(sock_key, peer_info)); } if ((flags & connect_filter_recent) && peer_info->last_handshake() + 600 > static_cast(this_thread::cached_seconds().count())) { LT_LOG_EVENTS("connecting peer rejected: recent handshake : %s", sa_pretty_str(sa).c_str()); return nullptr; } peer_info->set_flags(PeerInfo::flag_connected); peer_info->set_last_handshake(this_thread::cached_seconds().count()); if ((flags & connect_incoming)) { peer_info->set_flags(PeerInfo::flag_incoming); LT_LOG_EVENTS("connecting peer accepted: incoming : %s", sa_pretty_str(sa).c_str()); } else { peer_info->unset_flags(PeerInfo::flag_incoming); peer_info->set_listen_port(port); LT_LOG_EVENTS("connecting peer accepted: outgoing : %s", sa_pretty_str(sa).c_str()); } return peer_info; } // Make sure we properly clear port when disconnecting. void PeerList::disconnected(PeerInfo* p, int flags) { socket_address_key sock_key = socket_address_key::from_sockaddr(p->socket_address()); range_type range = base_type::equal_range(sock_key); auto itr = std::find_if(range.first, range.second, [p](auto& v) { return p == v.second.get(); }); if (itr == range.second) { if (std::none_of(base_type::begin(), base_type::end(), [p](auto& v){ return p == v.second.get(); })) throw internal_error("PeerList::disconnected(...) itr == range.second, doesn't exist."); else throw internal_error("PeerList::disconnected(...) itr == range.second, not in the range."); } disconnected(itr, flags); } PeerList::iterator PeerList::disconnected(iterator itr, int flags) { if (itr == base_type::end()) throw internal_error("PeerList::disconnected(...) itr == end()."); if (!itr->second->is_connected()) throw internal_error("PeerList::disconnected(...) !itr->is_connected()."); if (itr->second->transfer_counter() != 0) { // Currently we only log these as it only affects the culling of // peers. LT_LOG_EVENTS("disconnected with non-zero transfer counter (%" PRIu32 ") for peer %40s", itr->second->transfer_counter(), itr->second->id_hex()); } itr->second->unset_flags(PeerInfo::flag_connected); // Replace the socket address port with the listening port so that // future outgoing connections will connect to the right port. itr->second->set_port(0); if (flags & disconnect_set_time) itr->second->set_last_connection(this_thread::cached_seconds().count()); if (flags & disconnect_available && itr->second->listen_port() != 0) m_available_list->insert_unique(itr->second->socket_address()); // Do magic to get rid of unneeded entries. return ++itr; } uint32_t PeerList::cull_peers(int flags) { uint32_t counter = 0; uint32_t timer; if (flags & cull_old) timer = this_thread::cached_seconds().count() - 24 * 60 * 60; else timer = 0; for (auto itr = base_type::begin(); itr != base_type::end(); ) { if (itr->second->is_connected() || itr->second->transfer_counter() != 0 || // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! itr->second->last_connection() >= timer || (flags & cull_keep_interesting && (itr->second->failed_counter() != 0 || itr->second->is_blocked()))) { itr++; continue; } // ##################### TODO: LOG CULLING OF PEERS ###################### // *** AND STATS OF DISCONNECTING PEERS (the peer info...)... // The key is a pointer to a member in the value, although the key // shouldn't actually be used in erase (I think), just ot be safe // we delete it after erase. auto tmp = itr++; base_type::erase(tmp); counter++; } return counter; } uint32_t PeerList::insert_pex_list(const raw_string& pex_list) { if (pex_list.empty()) return true; AddressList l; l.parse_address_compact(pex_list); l.sort_and_unique(); LT_LOG_EVENTS("inserting pex list: %" PRIu32 " peers", l.size()); return insert_available(&l); } } // namespace torrent libtorrent-0.16.11/src/torrent/peer/connection_list.cc0000644000000000000000000001406315175073411016423 #include "config.h" #include "torrent/peer/connection_list.h" #include #include "download/download_main.h" #include "net/address_list.h" #include "protocol/peer_connection_base.h" #include "torrent/exceptions.h" #include "torrent/download_info.h" #include "torrent/download/choke_group.h" #include "torrent/download/choke_queue.h" #include "torrent/net/socket_address.h" #include "torrent/peer/peer.h" #include "torrent/peer/peer_info.h" #include "utils/functional.h" // When a peer is connected it should be removed from the list of // available peers. // // When a peer is disconnected the torrent should rebalance the choked // peers and connect to new ones if possible. namespace torrent { ConnectionList::ConnectionList(DownloadMain* download) : m_download(download) { } void ConnectionList::clear() { for (const auto& peer : *this) { delete peer->m_ptr(); } base_type::clear(); m_disconnectQueue.clear(); } bool ConnectionList::want_connection([[maybe_unused]] PeerInfo* p, Bitfield* bitfield) { if (m_download->file_list()->is_done() || m_download->initial_seeding() != NULL) return !bitfield->is_all_set(); if (!m_download->info()->is_accepting_seeders()) return !bitfield->is_all_set(); return true; } PeerConnectionBase* ConnectionList::insert(PeerInfo* peerInfo, int fd, Bitfield* bitfield, EncryptionInfo* encryptionInfo, ProtocolExtension* extensions) { if (size() >= m_maxSize) return NULL; PeerConnectionBase* peerConnection = m_slotNewConnection(encryptionInfo->is_encrypted()); if (peerConnection == NULL || bitfield == NULL) throw internal_error("ConnectionList::insert(...) received a NULL pointer."); peerInfo->set_connection(peerConnection); peerInfo->set_last_connection(this_thread::cached_seconds().count()); peerConnection->initialize(m_download, peerInfo, fd, bitfield, encryptionInfo, extensions); if (peerConnection->file_descriptor() == -1) { delete peerConnection; return NULL; } base_type::push_back(peerConnection); m_download->info()->change_flags(DownloadInfo::flag_accepting_new_peers, size() < m_maxSize); ::utils::slot_list_call(m_signalConnected, peerConnection); return peerConnection; } ConnectionList::iterator ConnectionList::erase(iterator pos, int flags) { if (pos < begin() || pos >= end()) throw internal_error("ConnectionList::erase(...) iterator out or range."); if (flags & disconnect_delayed) { m_disconnectQueue.push_back((*pos)->id()); this_thread::scheduler()->update_wait_for(&m_download->delay_disconnect_peers(), 0us); return pos; } PeerConnectionBase* peerConnection = (*pos)->m_ptr(); // The connection must be erased from the list before the signal is // emited otherwise some listeners might do stuff with the // assumption that the connection will remain in the list. *pos = base_type::back(); base_type::pop_back(); m_download->info()->change_flags(DownloadInfo::flag_accepting_new_peers, size() < m_maxSize); ::utils::slot_list_call(m_signalDisconnected, peerConnection); // Before of after the signal? peerConnection->cleanup(); peerConnection->mutable_peer_info()->set_connection(NULL); m_download->peer_list()->disconnected(peerConnection->mutable_peer_info(), PeerList::disconnect_set_time); // Delete after the signal to ensure the address of 'v' doesn't get // allocated for a different PCB in the signal. delete peerConnection; return pos; } void ConnectionList::erase(Peer* p, int flags) { erase(std::find(begin(), end(), p), flags); } void ConnectionList::erase(PeerInfo* peerInfo, int flags) { auto itr = std::find(begin(), end(), peerInfo->connection()); if (itr == end()) return; erase(itr, flags); } void ConnectionList::erase_remaining(iterator pos, int flags) { flags |= disconnect_quick; // Need to do it one connection at the time to ensure that when the // signal is emited everything is in a valid state. while (pos != end()) erase(--end(), flags); m_download->info()->change_flags(DownloadInfo::flag_accepting_new_peers, size() < m_maxSize); } void ConnectionList::erase_seeders() { erase_remaining(std::partition(begin(), end(), [](Peer* p) { return p->c_ptr()->is_not_seeder(); }), disconnect_unwanted); } void ConnectionList::disconnect_queued() { for (const auto& queue : m_disconnectQueue) { auto conn_itr = find(queue.c_str()); if (conn_itr != end()) erase(conn_itr, 0); } m_disconnectQueue.clear(); } struct connection_list_less { bool operator () (const Peer* p1, const Peer* p2) const { return sa_less(p1->peer_info()->socket_address(), p2->peer_info()->socket_address()); } bool operator () (const sa_inet_union& sa, const Peer* p2) const { return sa_less(&sa.sa, p2->peer_info()->socket_address()); } bool operator () (const Peer* p1, const sa_inet_union& sa) const { return sa_less(p1->peer_info()->socket_address(), &sa.sa); } }; ConnectionList::iterator ConnectionList::find(const char* id) { return std::find_if(begin(), end(), [id](Peer* p) { return *HashString::cast_from(id) == p->m_ptr()->peer_info()->id(); }); } ConnectionList::iterator ConnectionList::find(const sockaddr* sa) { return std::find_if(begin(), end(), [sa](Peer* p) { return sa_equal(p->m_ptr()->peer_info()->socket_address(), sa); }); } void ConnectionList::set_difference(AddressList* l) { std::sort(begin(), end(), connection_list_less()); l->erase(std::set_difference(l->begin(), l->end(), begin(), end(), l->begin(), connection_list_less()), l->end()); } void ConnectionList::set_min_size(size_type v) { if (v > (1 << 16)) throw input_error("Min peer connections must be between 0 and 2^16."); m_minSize = v; } void ConnectionList::set_max_size(size_type v) { if (v > (1 << 16)) throw input_error("Max peer connections must be between 0 and 2^16."); if (v == 0) v = choke_queue::unlimited; m_maxSize = v; m_download->info()->change_flags(DownloadInfo::flag_accepting_new_peers, size() < m_maxSize); //m_download->choke_group()->up_queue()->balance(); } } // namespace torrent libtorrent-0.16.11/src/torrent/peer/peer_info.cc0000644000000000000000000000135515175073411015177 #include "config.h" #include "utils/instrumentation.h" #include #include "torrent/exceptions.h" #include "torrent/net/socket_address.h" #include "torrent/peer/peer_info.h" namespace torrent { // TODO: Use a safer socket address parameter. PeerInfo::PeerInfo(const sockaddr* address) { m_address = sa_copy(address); } PeerInfo::~PeerInfo() { // if (m_transferCounter != 0) // throw internal_error("PeerInfo::~PeerInfo() m_transferCounter != 0."); instrumentation_update(INSTRUMENTATION_TRANSFER_PEER_INFO_UNACCOUNTED, m_transferCounter); assert(!is_blocked() && "PeerInfo::~PeerInfo() peer is blocked."); } void PeerInfo::set_port(uint16_t port) { return sa_set_port(m_address.get(), port); } } // namespace torrent libtorrent-0.16.11/src/torrent/peer/client_list.cc0000644000000000000000000003451515175073411015546 #include "config.h" #include "torrent/peer/client_list.h" #include #include "torrent/exceptions.h" #include "torrent/hash_string.h" #include "torrent/utils/string_manip.h" namespace torrent { ClientList::ClientList() { insert(ClientInfo::TYPE_UNKNOWN, NULL, NULL, NULL); // Move this to a seperate initialize function in libtorrent. // Sorted by popularity to optimize search. This list is heavily // biased by my own prejudices, and not at all based on facts. // First batch of clients. // Updated list of clients. insert_helper(ClientInfo::TYPE_AZUREUS, "lt", NULL, NULL, "libTorrent"); insert_helper(ClientInfo::TYPE_AZUREUS, "qB", NULL, NULL, "qBittorrent"); insert_helper(ClientInfo::TYPE_AZUREUS, "UT", NULL, NULL, "uTorrent"); insert_helper(ClientInfo::TYPE_AZUREUS, "TR", NULL, NULL, "Transmission"); insert_helper(ClientInfo::TYPE_AZUREUS, "DE", NULL, NULL, "DelugeTorrent"); insert_helper(ClientInfo::TYPE_AZUREUS, "AZ", NULL, NULL, "Vuze"); insert_helper(ClientInfo::TYPE_AZUREUS, "UM", NULL, NULL, "uTorrent Mac"); insert_helper(ClientInfo::TYPE_AZUREUS, "LT", NULL, NULL, "libtorrent"); insert_helper(ClientInfo::TYPE_AZUREUS, "BT", NULL, NULL, "Mainline"); insert_helper(ClientInfo::TYPE_MAINLINE, "M", NULL, NULL, "Mainline"); insert_helper(ClientInfo::TYPE_AZUREUS, "A2", NULL, NULL, "aria2"); insert_helper(ClientInfo::TYPE_AZUREUS, "BC", NULL, NULL, "BitComet"); insert_helper(ClientInfo::TYPE_AZUREUS, "XL", NULL, NULL, "Xunlei"); insert_helper(ClientInfo::TYPE_AZUREUS, "SD", NULL, NULL, "Xunlei"); // Other clients. insert_helper(ClientInfo::TYPE_AZUREUS, "7T", NULL, NULL, "aTorrent"); insert_helper(ClientInfo::TYPE_COMPACT, "A", NULL, NULL, "ABC"); insert_helper(ClientInfo::TYPE_AZUREUS, "A~", NULL, NULL, "Ares"); insert_helper(ClientInfo::TYPE_AZUREUS, "AG", NULL, NULL, "Ares"); insert_helper(ClientInfo::TYPE_AZUREUS, "AN", NULL, NULL, "Ares"); insert_helper(ClientInfo::TYPE_AZUREUS, "AR", NULL, NULL, "Ares"); // Ares is more likely than ArcticTorrent insert_helper(ClientInfo::TYPE_AZUREUS, "AT", NULL, NULL, "Artemis"); insert_helper(ClientInfo::TYPE_AZUREUS, "AV", NULL, NULL, "Avicora"); insert_helper(ClientInfo::TYPE_AZUREUS, "AX", NULL, NULL, "BitPump"); insert_helper(ClientInfo::TYPE_AZUREUS, "BB", NULL, NULL, "BitBuddy"); insert_helper(ClientInfo::TYPE_AZUREUS, "BE", NULL, NULL, "BitTorrent SDK"); insert_helper(ClientInfo::TYPE_AZUREUS, "BF", NULL, NULL, "BitFlu"); insert_helper(ClientInfo::TYPE_AZUREUS, "BG", NULL, NULL, "BTGetit"); insert_helper(ClientInfo::TYPE_AZUREUS, "BI", NULL, NULL, "BiglyBT"); insert_helper(ClientInfo::TYPE_AZUREUS, "bk", NULL, NULL, "BitKitten (libtorrent)"); insert_helper(ClientInfo::TYPE_AZUREUS, "BM", NULL, NULL, "BitMagnet"); insert_helper(ClientInfo::TYPE_AZUREUS, "BP", NULL, NULL, "BitTorrent Pro"); insert_helper(ClientInfo::TYPE_AZUREUS, "BR", NULL, NULL, "BitRocket"); insert_helper(ClientInfo::TYPE_AZUREUS, "BS", NULL, NULL, "BTSlave"); insert_helper(ClientInfo::TYPE_AZUREUS, "BW", NULL, NULL, "BitWombat"); insert_helper(ClientInfo::TYPE_AZUREUS, "BX", NULL, NULL, "Bittorrent X"); insert_helper(ClientInfo::TYPE_AZUREUS, "CB", NULL, NULL, "Shareaza Plus"); insert_helper(ClientInfo::TYPE_AZUREUS, "CD", NULL, NULL, "Enhanced CTorrent"); insert_helper(ClientInfo::TYPE_AZUREUS, "cT", NULL, NULL, "CuteTorrent"); insert_helper(ClientInfo::TYPE_AZUREUS, "CT", NULL, NULL, "CTorrent"); insert_helper(ClientInfo::TYPE_AZUREUS, "DP", NULL, NULL, "Propogate Data Client"); insert_helper(ClientInfo::TYPE_AZUREUS, "EB", NULL, NULL, "EBit"); insert_helper(ClientInfo::TYPE_AZUREUS, "ES", NULL, NULL, "Electric Sheep"); insert_helper(ClientInfo::TYPE_AZUREUS, "FC", NULL, NULL, "FileCroc"); insert_helper(ClientInfo::TYPE_AZUREUS, "FD", NULL, NULL, "Free Download Manager"); insert_helper(ClientInfo::TYPE_AZUREUS, "FG", NULL, NULL, "FlashGet"); insert_helper(ClientInfo::TYPE_AZUREUS, "FL", NULL, NULL, "Flud"); insert_helper(ClientInfo::TYPE_AZUREUS, "FT", NULL, NULL, "FoxTorrent/RedSwoosh"); insert_helper(ClientInfo::TYPE_AZUREUS, "FW", NULL, NULL, "FrostWire"); insert_helper(ClientInfo::TYPE_AZUREUS, "FX", NULL, NULL, "Freebox BitTorrent"); insert_helper(ClientInfo::TYPE_AZUREUS, "GR", NULL, NULL, "GetRight"); insert_helper(ClientInfo::TYPE_AZUREUS, "GS", NULL, NULL, "GSTorrent"); insert_helper(ClientInfo::TYPE_AZUREUS, "GT", NULL, NULL, "go.torrent"); insert_helper(ClientInfo::TYPE_AZUREUS, "HL", NULL, NULL, "Halite"); insert_helper(ClientInfo::TYPE_AZUREUS, "HN", NULL, NULL, "Hydranode"); insert_helper(ClientInfo::TYPE_AZUREUS, "IL", NULL, NULL, "iLivid"); insert_helper(ClientInfo::TYPE_AZUREUS, "JS", NULL, NULL, "JSTorrent"); insert_helper(ClientInfo::TYPE_AZUREUS, "JT", NULL, NULL, "jTorrent"); insert_helper(ClientInfo::TYPE_AZUREUS, "jT", NULL, NULL, "jTorrent"); insert_helper(ClientInfo::TYPE_AZUREUS, "KG", NULL, NULL, "KGet"); insert_helper(ClientInfo::TYPE_AZUREUS, "KT", NULL, NULL, "KTorrent"); insert_helper(ClientInfo::TYPE_AZUREUS, "LC", NULL, NULL, "LeechCraft"); insert_helper(ClientInfo::TYPE_AZUREUS, "LH", NULL, NULL, "LH-ABC"); insert_helper(ClientInfo::TYPE_AZUREUS, "LK", NULL, NULL, "linkage"); insert_helper(ClientInfo::TYPE_AZUREUS, "LP", NULL, NULL, "Lphant"); insert_helper(ClientInfo::TYPE_AZUREUS, "Lr", NULL, NULL, "LibreTorrent"); insert_helper(ClientInfo::TYPE_AZUREUS, "LW", NULL, NULL, "LimeWire"); insert_helper(ClientInfo::TYPE_AZUREUS, "MG", NULL, NULL, "MediaGet"); insert_helper(ClientInfo::TYPE_AZUREUS, "MO", NULL, NULL, "MonoTorrent"); insert_helper(ClientInfo::TYPE_AZUREUS, "MP", NULL, NULL, "MooPolice"); insert_helper(ClientInfo::TYPE_AZUREUS, "MR", NULL, NULL, "Miro"); insert_helper(ClientInfo::TYPE_AZUREUS, "MT", NULL, NULL, "MoonlightTorrent"); insert_helper(ClientInfo::TYPE_AZUREUS, "NE", NULL, NULL, "BT Next Evolution"); insert_helper(ClientInfo::TYPE_AZUREUS, "NX", NULL, NULL, "Net Transport"); insert_helper(ClientInfo::TYPE_COMPACT, "O", NULL, NULL, "Osprey Permaseed"); insert_helper(ClientInfo::TYPE_AZUREUS, "OS", NULL, NULL, "OneSwarm"); insert_helper(ClientInfo::TYPE_AZUREUS, "OT", NULL, NULL, "OmegaTorrent"); insert_helper(ClientInfo::TYPE_AZUREUS, "PC", NULL, NULL, "CacheLogic"); insert_helper(ClientInfo::TYPE_AZUREUS, "PI", NULL, NULL, "PicoTorrent"); insert_helper(ClientInfo::TYPE_AZUREUS, "PT", NULL, NULL, "Popcorn Time"); insert_helper(ClientInfo::TYPE_AZUREUS, "PD", NULL, NULL, "Pando"); insert_helper(ClientInfo::TYPE_AZUREUS, "pX", NULL, NULL, "pHoeniX"); insert_helper(ClientInfo::TYPE_COMPACT, "Q", NULL, NULL, "BTQueue"); insert_helper(ClientInfo::TYPE_AZUREUS, "QD", NULL, NULL, "qqdownload"); insert_helper(ClientInfo::TYPE_AZUREUS, "QT", NULL, NULL, "Qt 4 Torrent"); insert_helper(ClientInfo::TYPE_COMPACT, "R", NULL, NULL, "Tribler"); insert_helper(ClientInfo::TYPE_AZUREUS, "RS", NULL, NULL, "Rufus"); insert_helper(ClientInfo::TYPE_AZUREUS, "RT", NULL, NULL, "Retriever"); insert_helper(ClientInfo::TYPE_AZUREUS, "RZ", NULL, NULL, "RezTorrent"); insert_helper(ClientInfo::TYPE_COMPACT, "S", NULL, NULL, "Shadow's client"); insert_helper(ClientInfo::TYPE_AZUREUS, "S~", NULL, NULL, "Shareaza alpha/beta"); insert_helper(ClientInfo::TYPE_AZUREUS, "SB", NULL, NULL, "SwiftBit"); insert_helper(ClientInfo::TYPE_AZUREUS, "SG", NULL, NULL, "GS Torrent"); insert_helper(ClientInfo::TYPE_AZUREUS, "SK", NULL, NULL, "Spark"); insert_helper(ClientInfo::TYPE_AZUREUS, "SM", NULL, NULL, "SoMud"); insert_helper(ClientInfo::TYPE_AZUREUS, "SN", NULL, NULL, "ShareNET"); insert_helper(ClientInfo::TYPE_AZUREUS, "SP", NULL, NULL, "BitSpirit"); insert_helper(ClientInfo::TYPE_AZUREUS, "SS", NULL, NULL, "SwarmScope"); insert_helper(ClientInfo::TYPE_AZUREUS, "ST", NULL, NULL, "SymTorrent"); insert_helper(ClientInfo::TYPE_AZUREUS, "st", NULL, NULL, "SharkTorrent"); insert_helper(ClientInfo::TYPE_AZUREUS, "SZ", NULL, NULL, "Shareaza"); insert_helper(ClientInfo::TYPE_AZUREUS, "tT", NULL, NULL, "tTorrent"); insert_helper(ClientInfo::TYPE_COMPACT, "T", NULL, NULL, "BitTornado"); insert_helper(ClientInfo::TYPE_AZUREUS, "TB", NULL, NULL, "Torch"); insert_helper(ClientInfo::TYPE_AZUREUS, "TG", NULL, NULL, "Torrent GO"); insert_helper(ClientInfo::TYPE_AZUREUS, "TL", NULL, NULL, "Tribler"); insert_helper(ClientInfo::TYPE_AZUREUS, "TN", NULL, NULL, "Torrent.NET"); insert_helper(ClientInfo::TYPE_AZUREUS, "TS", NULL, NULL, "Torrentstorm"); insert_helper(ClientInfo::TYPE_AZUREUS, "TT", NULL, NULL, "TuoTu"); insert_helper(ClientInfo::TYPE_COMPACT, "U", NULL, NULL, "UPnP NAT BitTorrent"); insert_helper(ClientInfo::TYPE_AZUREUS, "UE", NULL, NULL, "uTorrent Embedded"); insert_helper(ClientInfo::TYPE_AZUREUS, "UL", NULL, NULL, "uLeecher!"); insert_helper(ClientInfo::TYPE_AZUREUS, "UW", NULL, NULL, "uTorrent Web"); insert_helper(ClientInfo::TYPE_AZUREUS, "WD", NULL, NULL, "WebTorrent Desktop"); insert_helper(ClientInfo::TYPE_AZUREUS, "WT", NULL, NULL, "Bitlet"); insert_helper(ClientInfo::TYPE_AZUREUS, "WW", NULL, NULL, "WebTorrent"); insert_helper(ClientInfo::TYPE_AZUREUS, "WY", NULL, NULL, "FireTorrent"); insert_helper(ClientInfo::TYPE_AZUREUS, "VG", NULL, NULL, "Vagaa"); insert_helper(ClientInfo::TYPE_AZUREUS, "XC", NULL, NULL, "XTorrent"); insert_helper(ClientInfo::TYPE_AZUREUS, "XF", NULL, NULL, "Xfplay"); insert_helper(ClientInfo::TYPE_AZUREUS, "XT", NULL, NULL, "XanTorrent"); insert_helper(ClientInfo::TYPE_AZUREUS, "XX", NULL, NULL, "XTorrent"); insert_helper(ClientInfo::TYPE_AZUREUS, "ZO", NULL, NULL, "Zona"); insert_helper(ClientInfo::TYPE_AZUREUS, "ZT", NULL, NULL, "ZipTorrent"); } ClientList::iterator ClientList::insert(ClientInfo::id_type type, const char* key, const char* version, const char* upperVersion) { if (type >= ClientInfo::TYPE_MAX_SIZE) throw input_error("Invalid client info id type."); ClientInfo clientInfo; clientInfo.set_type(type); clientInfo.set_short_description("Unknown"); std::memset(clientInfo.mutable_key(), 0, ClientInfo::max_key_size); if (key == NULL) std::memset(clientInfo.mutable_key(), 0, ClientInfo::max_key_size); else std::memcpy(clientInfo.mutable_key(), key, ClientInfo::max_key_size); if (version != NULL) std::memcpy(clientInfo.mutable_version(), version, ClientInfo::max_version_size); else std::memset(clientInfo.mutable_version(), 0, ClientInfo::max_version_size); if (upperVersion != NULL) std::memcpy(clientInfo.mutable_upper_version(), upperVersion, ClientInfo::max_version_size); else std::memset(clientInfo.mutable_upper_version(), -1, ClientInfo::max_version_size); return base_type::insert(end(), clientInfo); } ClientList::iterator ClientList::insert_helper(ClientInfo::id_type type, const char* key, const char* version, const char* upperVersion, const char* shortDescription) { char newKey[ClientInfo::max_key_size]; std::memset(newKey, 0, ClientInfo::max_key_size); std::memcpy(newKey, key, ClientInfo::key_size(type)); auto itr = insert(type, newKey, version, upperVersion); itr->set_short_description(shortDescription); return itr; } // Make this properly honor const-ness. bool ClientList::retrieve_id(ClientInfo* dest, const HashString& id) const { if (id[0] == '-' && id[7] == '-' && std::isalpha(id[1]) && std::isalpha(id[2]) && std::isxdigit(id[3]) && std::isxdigit(id[4]) && std::isxdigit(id[5]) && std::isxdigit(id[6])) { dest->set_type(ClientInfo::TYPE_AZUREUS); dest->mutable_key()[0] = id[1]; dest->mutable_key()[1] = id[2]; for (int i = 0; i < 4; i++) dest->mutable_version()[i] = dest->mutable_upper_version()[i] = utils::hex_to_value_or_zero(id[3 + i]); } else if (std::isalpha(id[0]) && id[4] == '-' && std::isxdigit(id[1]) && std::isxdigit(id[2]) && std::isxdigit(id[3])) { dest->set_type(ClientInfo::TYPE_COMPACT); dest->mutable_key()[0] = id[0]; dest->mutable_key()[1] = '\0'; dest->mutable_version()[0] = dest->mutable_upper_version()[0] = utils::hex_to_value_or_zero(id[1]); dest->mutable_version()[1] = dest->mutable_upper_version()[1] = utils::hex_to_value_or_zero(id[2]); dest->mutable_version()[2] = dest->mutable_upper_version()[2] = utils::hex_to_value_or_zero(id[3]); dest->mutable_version()[3] = dest->mutable_upper_version()[3] = '\0'; } else if (std::isalpha(id[0]) && std::isdigit(id[1]) && id[2] == '-' && std::isdigit(id[3]) && (id[6] == '-' || id[7] == '-')) { dest->set_type(ClientInfo::TYPE_MAINLINE); dest->mutable_key()[0] = id[0]; dest->mutable_key()[1] = '\0'; dest->mutable_version()[0] = dest->mutable_upper_version()[0] = utils::hex_to_value_or_zero(id[1]); if (id[4] == '-' && std::isdigit(id[5]) && id[6] == '-') { dest->mutable_version()[1] = dest->mutable_upper_version()[1] = utils::hex_to_value_or_zero(id[3]); dest->mutable_version()[2] = dest->mutable_upper_version()[2] = utils::hex_to_value_or_zero(id[5]); dest->mutable_version()[3] = dest->mutable_upper_version()[3] = '\0'; } else if (std::isdigit(id[4]) && id[5] == '-' && std::isdigit(id[6]) && id[7] == '-') { dest->mutable_version()[1] = dest->mutable_upper_version()[1] = utils::hex_to_value_or_zero(id[3]) * 10 + utils::hex_to_value_or_zero(id[4]); dest->mutable_version()[2] = dest->mutable_upper_version()[2] = utils::hex_to_value_or_zero(id[6]); dest->mutable_version()[3] = dest->mutable_upper_version()[3] = '\0'; } else { *dest = *begin(); std::memset(dest->mutable_upper_version(), 0, ClientInfo::max_version_size); return false; } } else { // And then the incompatible idiots that make life difficult for us // others. (There's '3' schemes to choose from already...) // // Or not... // The first entry always contains the default ClientInfo. *dest = *begin(); std::memset(dest->mutable_upper_version(), 0, ClientInfo::max_version_size); return false; } auto itr = std::find_if(std::next(begin()), end(), [dest](const auto& client) { return ClientInfo::intersects(*dest, client); }); if (itr == end()) dest->set_info(begin()->info()); else dest->set_info(itr->info()); return true; } void ClientList::retrieve_unknown(ClientInfo* dest) const { *dest = *begin(); std::memset(dest->mutable_upper_version(), 0, ClientInfo::max_version_size); } } // namespace torrent libtorrent-0.16.11/src/torrent/peer/peer_list.h0000644000000000000000000000633015175073411015057 #ifndef LIBTORRENT_PEER_LIST_H #define LIBTORRENT_PEER_LIST_H #include #include #include #include #include namespace torrent { class DownloadInfo; class ProtocolExtension; class raw_string; using ipv4_table = extents; class LIBTORRENT_EXPORT PeerList : private std::multimap> { public: friend class DownloadWrapper; friend class Handshake; friend class HandshakeManager; friend class ConnectionList; using base_type = std::multimap>; using range_type = std::pair; using base_type::value_type; using base_type::reference; using base_type::difference_type; using base_type::iterator; using base_type::reverse_iterator; using base_type::const_iterator; using base_type::const_reverse_iterator; using base_type::size; using base_type::empty; static constexpr int address_available = (1 << 0); static constexpr int connect_incoming = (1 << 0); static constexpr int connect_keep_handshakes = (1 << 1); static constexpr int connect_filter_recent = (1 << 2); // Make sure any change here match ConnectionList's flags. static constexpr int disconnect_available = (1 << 0); static constexpr int disconnect_quick = (1 << 1); static constexpr int disconnect_unwanted = (1 << 2); static constexpr int disconnect_set_time = (1 << 3); static constexpr int cull_old = (1 << 0); static constexpr int cull_keep_interesting = (1 << 1); PeerList(); ~PeerList(); PeerInfo* insert_address(const sockaddr* address, int flags); // This will be used internally only for the moment. uint32_t insert_available(const void* al) LIBTORRENT_NO_EXPORT; static ipv4_table* ipv4_filter() { return &m_ipv4_table; } const auto& available_list() { return m_available_list; } uint32_t available_list_size() const; uint32_t cull_peers(int flags); const_iterator begin() const { return base_type::begin(); } const_iterator end() const { return base_type::end(); } const_reverse_iterator rbegin() const { return base_type::rbegin(); } const_reverse_iterator rend() const { return base_type::rend(); } protected: friend class torrent::ProtocolExtension; void set_info(DownloadInfo* info) LIBTORRENT_NO_EXPORT; // Insert, or find a PeerInfo with socket address 'sa'. Returns end // if no more connections are allowed from that host. PeerInfo* connected(const sockaddr* sa, int flags) LIBTORRENT_NO_EXPORT; void disconnected(PeerInfo* p, int flags) LIBTORRENT_NO_EXPORT; iterator disconnected(iterator itr, int flags) LIBTORRENT_NO_EXPORT; uint32_t insert_pex_list(const raw_string& pex_list) LIBTORRENT_NO_EXPORT; private: PeerList(const PeerList&) = delete; PeerList& operator=(const PeerList&) = delete; static ipv4_table m_ipv4_table; DownloadInfo* m_info; std::unique_ptr m_available_list; }; } // namespace torrent #endif libtorrent-0.16.11/src/torrent/peer/choke_status.h0000644000000000000000000000264515175073411015572 #ifndef LIBTORRENT_DOWNLOAD_CHOKE_STATUS_H #define LIBTORRENT_DOWNLOAD_CHOKE_STATUS_H #include #include namespace torrent { class group_entry; class choke_status { public: group_entry* entry() const { return m_group_entry; } void set_entry(group_entry* grp_ent) { m_group_entry = grp_ent; } bool queued() const { return m_queued; } void set_queued(bool s) { m_queued = s; } bool choked() const { return !m_unchoked; } bool unchoked() const { return m_unchoked; } void set_unchoked(bool s) { m_unchoked = s; } bool snubbed() const { return m_snubbed; } void set_snubbed(bool s) { m_snubbed = s; } auto time_last_choke() const { return m_time_last_choke; } void set_time_last_choke(std::chrono::microseconds t) { m_time_last_choke = t; } private: // TODO: Use flags. group_entry* m_group_entry{}; bool m_queued{false}; bool m_unchoked{false}; bool m_snubbed{false}; std::chrono::microseconds m_time_last_choke{}; }; } // namespace torrent #endif libtorrent-0.16.11/src/torrent/chunk_manager.cc0000644000000000000000000001054715175073411015103 #include "config.h" #include "torrent/chunk_manager.h" #include #include #include "data/chunk_list.h" #include "torrent/exceptions.h" #include "utils/instrumentation.h" namespace torrent { ChunkManager::ChunkManager() = default; ChunkManager::~ChunkManager() { assert(m_memoryUsage == 0 && "ChunkManager::~ChunkManager() m_memoryUsage != 0."); assert(m_memoryBlockCount == 0 && "ChunkManager::~ChunkManager() m_memoryBlockCount != 0."); } uint64_t ChunkManager::sync_queue_memory_usage() const { uint64_t size = 0; for (auto chunk : *this) size += chunk->queue_size() * chunk->chunk_size(); return size; } uint32_t ChunkManager::sync_queue_size() const { uint32_t size = 0; for (auto chunk : *this) size += chunk->queue_size(); return size; } uint64_t ChunkManager::estimate_max_memory_usage() { rlimit rlp; #ifdef RLIMIT_AS if (getrlimit(RLIMIT_AS, &rlp) == 0 && rlp.rlim_cur != RLIM_INFINITY) #else if (getrlimit(RLIMIT_DATA, &rlp) == 0 && rlp.rlim_cur != RLIM_INFINITY) #endif return rlp.rlim_cur; return uint64_t{DEFAULT_ADDRESS_SPACE_SIZE} << 20; } uint64_t ChunkManager::safe_free_diskspace() const { return m_memoryUsage + (uint64_t{512} << 20); } void ChunkManager::insert(ChunkList* chunkList) { chunkList->set_manager(this); base_type::push_back(chunkList); } void ChunkManager::erase(ChunkList* chunkList) { if (chunkList->queue_size() != 0) throw internal_error("ChunkManager::erase(...) chunkList->queue_size() != 0."); auto itr = std::find(base_type::begin(), base_type::end(), chunkList); if (itr == base_type::end()) throw internal_error("ChunkManager::erase(...) itr == base_type::end()."); std::iter_swap(itr, --base_type::end()); base_type::pop_back(); chunkList->set_manager(NULL); } bool ChunkManager::allocate(uint32_t size, int flags) { if (m_memoryUsage + size > (3 * m_maxMemoryUsage) / 4) try_free_memory((1 * m_maxMemoryUsage) / 4); if (m_memoryUsage + size > m_maxMemoryUsage) { if (!(flags & allocate_dont_log)) instrumentation_update(INSTRUMENTATION_MINCORE_ALLOC_FAILED, 1); return false; } if (!(flags & allocate_dont_log)) instrumentation_update(INSTRUMENTATION_MINCORE_ALLOCATIONS, size); m_memoryUsage += size; m_memoryBlockCount++; instrumentation_update(INSTRUMENTATION_MEMORY_CHUNK_COUNT, 1); instrumentation_update(INSTRUMENTATION_MEMORY_CHUNK_USAGE, size); return true; } void ChunkManager::deallocate(uint32_t size, int flags) { if (size > m_memoryUsage) throw internal_error("ChunkManager::deallocate(...) size > m_memoryUsage."); if (!(flags & allocate_dont_log)) { if (flags & allocate_revert_log) instrumentation_update(INSTRUMENTATION_MINCORE_ALLOCATIONS, -size); else instrumentation_update(INSTRUMENTATION_MINCORE_DEALLOCATIONS, size); } m_memoryUsage -= size; m_memoryBlockCount--; instrumentation_update(INSTRUMENTATION_MEMORY_CHUNK_COUNT, -1); instrumentation_update(INSTRUMENTATION_MEMORY_CHUNK_USAGE, -static_cast(size)); } void ChunkManager::try_free_memory(uint64_t size) { // Ensure that we don't call this function too often when futile as // it might be somewhat expensive. // // Note that it won't be able to free chunks that are scheduled for // hash checking, so a too low max memory setting will give problem // at high transfer speed. if (m_timerStarved + 10 >= this_thread::cached_seconds().count()) return; sync_all(0, size <= m_memoryUsage ? (m_memoryUsage - size) : 0); // The caller must ensure he tries to free a sufficiently large // amount of memory to ensure it, and other users, has enough memory // space for at least 10 seconds. m_timerStarved = this_thread::cached_seconds().count(); } void ChunkManager::periodic_sync() { sync_all(ChunkList::sync_use_timeout, 0); } void ChunkManager::sync_all(int flags, uint64_t target) { if (empty()) return; // Start from the next entry so that we don't end up repeatedly // syncing the same torrent. m_lastFreed = m_lastFreed % base_type::size() + 1; auto itr = base_type::begin() + m_lastFreed; do { if (itr == base_type::end()) itr = base_type::begin(); (*itr)->sync_chunks(static_cast(flags)); } while (++itr != base_type::begin() + m_lastFreed && m_memoryUsage >= target); m_lastFreed = itr - begin(); } } // namespace torrent libtorrent-0.16.11/src/torrent/connection_manager.cc0000644000000000000000000000165515175073411016132 #include "config.h" #include "torrent/connection_manager.h" #include "torrent/exceptions.h" #include "torrent/net/socket_address.h" #include "torrent/net/network_config.h" namespace torrent { ConnectionManager::ConnectionManager() = default; ConnectionManager::~ConnectionManager() = default; bool ConnectionManager::can_connect() const { return m_size < m_maxSize; } uint32_t ConnectionManager::filter(const sockaddr* sa) { // TODO: Reverse order of checks, NC should be last. if (config::network_config()->is_block_ipv4() && sa_is_inet(sa)) return 0; if (config::network_config()->is_block_ipv6() && sa_is_inet6(sa)) return 0; if (sa_is_v4mapped(sa)) { if (config::network_config()->is_block_ipv4in6()) return 0; if (m_slot_filter) return m_slot_filter(sa_from_v4mapped(sa).get()); } else { if (m_slot_filter) return m_slot_filter(sa); } return 1; } } // namespace torrent libtorrent-0.16.11/src/torrent/error.cc0000644000000000000000000000667115175073411013435 // libTorrent - BitTorrent library // Copyright (C) 2005-2011, Jari Sundell // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // In addition, as a special exception, the copyright holders give // permission to link the code of portions of this program with the // OpenSSL library under certain conditions as described in each // individual source file, and distribute linked combinations // including the two. // // You must obey the GNU General Public License in all respects for // all of the code used other than OpenSSL. If you modify file(s) // with this exception, you may extend this exception to your version // of the file(s), but you are not obligated to do so. If you do not // wish to do so, delete this exception statement from your version. // If you delete this exception statement from all source files in the // program, then also delete it here. // // Contact: Jari Sundell // // Skomakerveien 33 // 3185 Skoppum, NORWAY #include "config.h" #include #include "error.h" namespace torrent { static constexpr std::array errorStrings{ "unknown error", // e_none "not BitTorrent protocol", // eh_not_bittorrent "not accepting connections", // eh_not_accepting_connections "duplicate peer ID", // eh_duplicate "unknown download", // eh_unknown_download "download inactive", // eh_inactive_download "seeder rejected", // eh_unwanted_connection "is self", // eh_is_self "invalid value received", // eh_invalid_value "unencrypted connection rejected", // eh_unencrypted_rejected "invalid encryption method", // eh_invalid_encryption "encryption sync failed", // eh_encryption_sync_failed "", // eh_ "network unreachable", // eh_network_unreachable "network timeout", // eh_network_timeout "invalid message order", // eh_invalid_order "too many failed chunks", // eh_toomanyfailed "no peer info", // eh_no_peer_info "network socket error", // eh_network_socket_error "network read error", // eh_network_read_error "network write error", // eh_network_write_error // "", // e_handshake_incoming // "", // e_handshake_outgoing // "", // e_handshake_outgoing_encrypted // "", // e_handshake_outgoing_proxy // "", // e_handshake_success // "", // e_handshake_retry_plaintext // "" // e_handshake_retry_encrypted }; const char* strerror(int err) { if (err < 0 || err > e_last) return "Unknown error"; return errorStrings[err]; } } // namespace torrent libtorrent-0.16.11/src/torrent/throttle.h0000644000000000000000000000231215175073411013777 #ifndef LIBTORRENT_TORRENT_THROTTLE_H #define LIBTORRENT_TORRENT_THROTTLE_H #include namespace torrent { class ThrottleList; class ThrottleInternal; class LIBTORRENT_EXPORT Throttle { public: static Throttle* create_throttle(); static void destroy_throttle(Throttle* throttle); Throttle* create_slave(); bool is_throttled() const; // 0 == UNLIMITED. uint64_t max_rate() const { return m_maxRate; } void set_max_rate(uint64_t v); const Rate* rate() const; ThrottleList* throttle_list() { return m_throttleList; } protected: Throttle() = default; ~Throttle() = default; ThrottleInternal* m_ptr() { return reinterpret_cast(this); } const ThrottleInternal* c_ptr() const { return reinterpret_cast(this); } uint32_t calculate_min_chunk_size() const LIBTORRENT_NO_EXPORT; uint32_t calculate_max_chunk_size() const LIBTORRENT_NO_EXPORT; uint32_t calculate_interval() const LIBTORRENT_NO_EXPORT; uint64_t m_maxRate; ThrottleList* m_throttleList; }; } // namespace torrent #endif libtorrent-0.16.11/src/torrent/path.h0000644000000000000000000000701015175073411013066 // libTorrent - BitTorrent library // Copyright (C) 2005-2011, Jari Sundell // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // In addition, as a special exception, the copyright holders give // permission to link the code of portions of this program with the // OpenSSL library under certain conditions as described in each // individual source file, and distribute linked combinations // including the two. // // You must obey the GNU General Public License in all respects for // all of the code used other than OpenSSL. If you modify file(s) // with this exception, you may extend this exception to your version // of the file(s), but you are not obligated to do so. If you do not // wish to do so, delete this exception statement from your version. // If you delete this exception statement from all source files in the // program, then also delete it here. // // Contact: Jari Sundell // // Skomakerveien 33 // 3185 Skoppum, NORWAY #ifndef LIBTORRENT_PATH_H #define LIBTORRENT_PATH_H #include #include #include namespace torrent { // Use a blank first path to get root and "." to get current dir. class LIBTORRENT_EXPORT Path : private std::vector { public: using base_type = std::vector; using value_type = base_type::value_type; using pointer = base_type::pointer; using const_pointer = base_type::const_pointer; using reference = base_type::reference; using const_reference = base_type::const_reference; using size_type = base_type::size_type; using difference_type = base_type::difference_type; using allocator_type = base_type::allocator_type; using iterator = base_type::iterator; using reverse_iterator = base_type::reverse_iterator; using const_iterator = base_type::const_iterator; using const_reverse_iterator = base_type::const_reverse_iterator; using base_type::clear; using base_type::empty; using base_type::size; using base_type::reserve; using base_type::front; using base_type::back; using base_type::begin; using base_type::end; using base_type::rbegin; using base_type::rend; using base_type::push_back; using base_type::at; using base_type::operator[]; void insert_path(iterator pos, const std::string& path); // Return the path as a string with '/' deliminator. The deliminator // is only inserted between path elements. std::string as_string() const; std::string encoding() const { return m_encoding; } void set_encoding(const std::string& enc) { m_encoding = enc; } base_type* base() { return this; } const base_type* base() const { return this; } private: std::string m_encoding; }; } // namespace torrent #endif libtorrent-0.16.11/src/torrent/object_raw_bencode.h0000644000000000000000000001252215175073411015734 #ifndef LIBTORRENT_OBJECT_RAW_BENCODE_H #define LIBTORRENT_OBJECT_RAW_BENCODE_H #include #include #include #include #include namespace torrent { class raw_bencode; class raw_string; class raw_list; class raw_map; // The base class for static constant version of Objects. This class // should never be used directly. class raw_object { public: using value_type = const char; using iterator = const char*; using const_iterator = const char*; using size_type = uint32_t; raw_object() = default; raw_object(value_type* src_data, size_type src_size) : m_data(src_data), m_size(src_size) {} bool empty() const { return m_size == 0; } size_type size() const { return m_size; } iterator begin() const { return m_data; } iterator end() const { return m_data + m_size; } value_type* data() const { return m_data; } bool operator == (const raw_object& rhs) const { return m_size == rhs.m_size && std::memcmp(m_data, rhs.m_data, m_size) == 0; } bool operator != (const raw_object& rhs) const { return m_size != rhs.m_size || std::memcmp(m_data, rhs.m_data, m_size) != 0; } protected: iterator m_data{}; size_type m_size{}; }; #define RAW_BENCODE_SET_USING \ using raw_object::value_type; \ using raw_object::iterator; \ using raw_object::const_iterator; \ using raw_object::size_type; \ using raw_object::empty; \ using raw_object::size; \ using raw_object::begin; \ using raw_object::end; \ using raw_object::data; \ \ bool operator == (const this_type& rhs) const { return raw_object::operator==(rhs); } \ bool operator != (const this_type& rhs) const { return raw_object::operator!=(rhs); } \ // A raw_bencode object shall always contain valid bencode data or be // empty. class raw_bencode : protected raw_object { public: using this_type = raw_bencode; RAW_BENCODE_SET_USING raw_bencode() = default; raw_bencode(value_type* src_data, size_type src_size) : raw_object(src_data, src_size) {} bool is_empty() const { return m_size == 0; } bool is_value() const { return m_size >= 3 && m_data[0] >= 'i'; } bool is_raw_string() const { return m_size >= 2 && m_data[0] >= '0' && m_data[0] <= '9'; } bool is_raw_list() const { return m_size >= 2 && m_data[0] >= 'l'; } bool is_raw_map() const { return m_size >= 2 && m_data[0] >= 'd'; } std::string as_value_string() const; raw_string as_raw_string() const; raw_list as_raw_list() const; raw_map as_raw_map() const; static raw_bencode from_c_str(const char* str) { return raw_bencode(str, std::strlen(str)); } }; class raw_string : protected raw_object { public: using this_type = raw_string; RAW_BENCODE_SET_USING raw_string() = default; raw_string(value_type* src_data, size_type src_size) : raw_object(src_data, src_size) {} std::string as_string() const { return std::string(m_data, m_size); } static raw_string from_c_str(const char* str) { return raw_string(str, std::strlen(str)); } static raw_string from_string(const std::string& str) { return raw_string(str.data(), str.size()); } }; class raw_list : protected raw_object { public: using this_type = raw_list; RAW_BENCODE_SET_USING raw_list() = default; raw_list(value_type* src_data, size_type src_size) : raw_object(src_data, src_size) {} static raw_list from_c_str(const char* str) { return raw_list(str, std::strlen(str)); } }; class raw_map : protected raw_object { public: using this_type = raw_map; RAW_BENCODE_SET_USING raw_map() = default; raw_map(value_type* src_data, size_type src_size) : raw_object(src_data, src_size) {} }; // // // inline std::string raw_bencode::as_value_string() const { if (!is_value()) throw bencode_error("Wrong object type."); return std::string(data() + 1, size() - 2); } inline raw_string raw_bencode::as_raw_string() const { if (!is_raw_string()) throw bencode_error("Wrong object type."); const_iterator itr = std::find(begin(), end(), ':'); if (itr == end()) throw internal_error("Invalid bencode in raw_bencode."); return raw_string(itr + 1, std::distance(itr + 1, end())); } inline raw_list raw_bencode::as_raw_list() const { if (!is_raw_list()) throw bencode_error("Wrong object type."); return raw_list(m_data + 1, m_size - 2); } inline raw_map raw_bencode::as_raw_map() const { if (!is_raw_map()) throw bencode_error("Wrong object type."); return raw_map(m_data + 1, m_size - 2); } // // Redo... // inline bool raw_bencode_equal(const raw_bencode& left, const raw_bencode& right) { return left.size() == right.size() && std::memcmp(left.begin(), right.begin(), left.size()) == 0; } template inline bool raw_bencode_equal(const tmpl_raw_object& left, const char* right, size_t right_size) { return left.size() == right_size && std::memcmp(left.begin(), right, right_size) == 0; } template inline bool raw_bencode_equal_c_str(const tmpl_raw_object& left, const char* right) { return raw_bencode_equal(left, right, strlen(right)); } } // namespace torrent #endif libtorrent-0.16.11/src/torrent/common.h0000644000000000000000000001273215175073411013431 #ifndef LIBTORRENT_COMMON_H #define LIBTORRENT_COMMON_H #include #include #include #include #include #include #include struct sockaddr; struct sockaddr_in; struct sockaddr_in6; struct sockaddr_un; using namespace std::chrono_literals; namespace torrent { enum priority_enum { PRIORITY_OFF = 0, PRIORITY_NORMAL, PRIORITY_HIGH }; enum tracker_enum { TRACKER_NONE, TRACKER_HTTP, TRACKER_UDP, TRACKER_DHT, }; // Just forward declare everything here so we can keep the actual // headers clean. class AddressList; class AvailableList; class Bitfield; class Block; class BlockFailed; class BlockList; class BlockTransfer; class Chunk; class ChunkList; class ChunkManager; class ChunkSelector; class ClientInfo; class ClientList; class ConnectionList; class ConnectionManager; class DhtRouter; class Download; class DownloadInfo; class DownloadMain; class DownloadWrapper; class FileList; class FileManager; class Event; class File; class FileList; class Handshake; class HandshakeManager; class HashString; class Listen; class MemoryChunk; class Object; class Path; class Peer; class PeerConnectionBase; class PeerInfo; class PeerList; class Piece; class ProtocolExtension; class Rate; class ResourceManager; class Throttle; class TrackerController; class TrackerList; class TransferList; namespace net { class HttpGet; class HttpStack; class NetworkConfig; class Poll; class Resolver; } // namespace net namespace runtime { class NetworkManager; class SocketManager; } // namespace runtime namespace tracker { class DhtController; class Tracker; } // namespace tracker namespace system { class Thread; } // namespace system namespace utils { class Scheduler; class SchedulerEntry; } // namespace utils } // namespace torrent // This should only need to be set when compiling libtorrent. #ifdef SUPPORT_ATTRIBUTE_VISIBILITY #define LIBTORRENT_NO_EXPORT __attribute__ ((visibility("hidden"))) #define LIBTORRENT_EXPORT __attribute__ ((visibility("default"))) #else #define LIBTORRENT_NO_EXPORT #define LIBTORRENT_EXPORT #endif namespace torrent::config { torrent::net::NetworkConfig* network_config() LIBTORRENT_EXPORT; } // namespace torrent::config // TODO: Move to runtime/common.h namespace torrent::runtime { // add fd_manager here... NetworkManager* network_manager() LIBTORRENT_EXPORT; SocketManager* socket_manager() LIBTORRENT_EXPORT; void dht_add_peer_node(const sockaddr* sa, uint16_t port) LIBTORRENT_EXPORT; uint16_t listen_port() LIBTORRENT_EXPORT; } // namespace torrent::runtime namespace torrent::system { const char* errno_enum(int status) LIBTORRENT_EXPORT; std::string errno_enum_str(int status) LIBTORRENT_EXPORT; } // namespace torrent::system namespace torrent::this_thread { torrent::system::Thread* thread() LIBTORRENT_EXPORT; std::thread::id thread_id() LIBTORRENT_EXPORT; std::chrono::microseconds cached_time() LIBTORRENT_EXPORT; std::chrono::seconds cached_seconds() LIBTORRENT_EXPORT; void callback(void* target, std::function&& fn) LIBTORRENT_EXPORT; void cancel_callback(void* target) LIBTORRENT_EXPORT; void cancel_callback_and_wait(void* target) LIBTORRENT_EXPORT; net::Poll* poll() LIBTORRENT_EXPORT; net::Resolver* resolver() LIBTORRENT_EXPORT; utils::Scheduler* scheduler() LIBTORRENT_EXPORT; [[gnu::weak]] void event_open(Event* event) LIBTORRENT_EXPORT; [[gnu::weak]] void event_open_and_count(Event* event) LIBTORRENT_EXPORT; [[gnu::weak]] void event_close_and_count(Event* event) LIBTORRENT_EXPORT; [[gnu::weak]] void event_closed_and_count(Event* event) LIBTORRENT_EXPORT; [[gnu::weak]] void event_insert_read(Event* event) LIBTORRENT_EXPORT; [[gnu::weak]] void event_insert_write(Event* event) LIBTORRENT_EXPORT; [[gnu::weak]] void event_insert_error(Event* event) LIBTORRENT_EXPORT; [[gnu::weak]] void event_remove_read(Event* event) LIBTORRENT_EXPORT; [[gnu::weak]] void event_remove_write(Event* event) LIBTORRENT_EXPORT; [[gnu::weak]] void event_remove_error(Event* event) LIBTORRENT_EXPORT; [[gnu::weak]] void event_remove_and_close(Event* event) LIBTORRENT_EXPORT; } // namespace torrent::this_thread namespace torrent::main_thread { system::Thread* thread() LIBTORRENT_EXPORT; std::thread::id thread_id() LIBTORRENT_EXPORT; void callback(void* target, std::function&& fn) LIBTORRENT_EXPORT; void cancel_callback(void* target) LIBTORRENT_EXPORT; void cancel_callback_and_wait(void* target) LIBTORRENT_EXPORT; uint32_t hash_queue_size() LIBTORRENT_EXPORT; } // namespace torrent::main_thread namespace torrent::net_thread { system::Thread* thread() LIBTORRENT_EXPORT; std::thread::id thread_id() LIBTORRENT_EXPORT; void callback(void* target, std::function&& fn) LIBTORRENT_EXPORT; void callback_interrupt_polling(void* target, std::function&& fn) LIBTORRENT_EXPORT; void callback_interrupt_polling_and_wait(void* target, std::function&& fn) LIBTORRENT_EXPORT; void cancel_callback(void* target) LIBTORRENT_EXPORT; void cancel_callback_and_wait(void* target) LIBTORRENT_EXPORT; torrent::net::HttpStack* http_stack() LIBTORRENT_EXPORT; } // namespace torrent::net_thread #endif libtorrent-0.16.11/src/torrent/data/0000755000000000000000000000000015175073434012761 5libtorrent-0.16.11/src/torrent/data/file_manager.h0000644000000000000000000000413015175073411015454 #ifndef LIBTORRENT_DATA_FILE_MANAGER_H #define LIBTORRENT_DATA_FILE_MANAGER_H #include #include namespace torrent { class File; class LIBTORRENT_EXPORT FileManager : private std::vector { public: using base_type = std::vector; using size_type = uint32_t; using base_type::value_type; using base_type::iterator; using base_type::reverse_iterator; using base_type::begin; using base_type::end; using base_type::rbegin; using base_type::rend; FileManager() = default; ~FileManager(); size_type open_files() const { return base_type::size(); } size_type max_open_files() const { return m_max_open_files; } void set_max_open_files(size_type s); bool advise_random() const { return m_advise_random; } void set_advise_random(bool state) { m_advise_random = state; } bool advise_random_hashing() const { return m_advise_random_hashing; } void set_advise_random_hashing(bool state) { m_advise_random_hashing = state; } bool open(value_type file, bool hashing, int prot, int flags); void close(value_type file); // TODO: Close all files held by a download after hashing. Also flush all memory chunks. void close_least_active(); // Statistics: uint64_t files_opened_counter() const { return m_files_opened_counter; } uint64_t files_closed_counter() const { return m_files_closed_counter; } uint64_t files_failed_counter() const { return m_files_failed_counter; } private: FileManager(const FileManager&) = delete; FileManager& operator=(const FileManager&) = delete; size_type m_max_open_files{0}; bool m_advise_random{false}; bool m_advise_random_hashing{false}; uint64_t m_files_opened_counter{0}; uint64_t m_files_closed_counter{0}; uint64_t m_files_failed_counter{0}; }; } // namespace torrent #endif libtorrent-0.16.11/src/torrent/data/file_manager.cc0000644000000000000000000000436615175073411015625 #include "config.h" #include "file_manager.h" #include #include #include #include #include "manager.h" #include "data/socket_file.h" #include "torrent/exceptions.h" #include "torrent/data/file.h" namespace torrent { FileManager::~FileManager() { assert(empty() && "FileManager::~FileManager() called but empty() != true."); } void FileManager::set_max_open_files(size_type s) { if (s < 4 || s > (1 << 16)) throw input_error("Max open files must be between 4 and 2^16."); m_max_open_files = s; while (size() > m_max_open_files) close_least_active(); } bool FileManager::open(value_type file, [[maybe_unused]] bool hashing, int prot, int flags) { if (file->is_padding()) return true; if (file->is_open()) close(file); if (size() > m_max_open_files) throw internal_error("FileManager::open_file(...) m_openSize > m_max_open_files."); if (size() == m_max_open_files) close_least_active(); SocketFile fd; if (!fd.open(file->frozen_path(), prot, flags)) { m_files_failed_counter++; return false; } file->set_protection(prot); file->set_file_descriptor(fd.fd()); #ifdef USE_POSIX_FADVISE if (hashing) { if (m_advise_random_hashing) posix_fadvise(fd.fd(), 0, 0, POSIX_FADV_RANDOM); } else { if (m_advise_random) posix_fadvise(fd.fd(), 0, 0, POSIX_FADV_RANDOM); } #endif base_type::push_back(file); // Consider storing the position of the file here. m_files_opened_counter++; return true; } void FileManager::close(value_type file) { if (!file->is_open()) return; if (file->is_padding()) return; SocketFile(file->file_descriptor()).close(); file->set_protection(0); file->set_file_descriptor(-1); auto itr = std::find(begin(), end(), file); if (itr == end()) throw internal_error("FileManager::close_file(...) itr == end()."); *itr = back(); base_type::pop_back(); m_files_closed_counter++; } void FileManager::close_least_active() { File* least = nullptr; uint64_t last = std::numeric_limits::max(); for (auto f : *this) { if (f->is_open() && f->last_touched() <= last) { last = f->last_touched(); least = f; } } if (least) close(least); } } // namespace torrent libtorrent-0.16.11/src/torrent/data/download_data.cc0000644000000000000000000000552315175073411016010 // libTorrent - BitTorrent library // Copyright (C) 2005-2011, Jari Sundell // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // In addition, as a special exception, the copyright holders give // permission to link the code of portions of this program with the // OpenSSL library under certain conditions as described in each // individual source file, and distribute linked combinations // including the two. // // You must obey the GNU General Public License in all respects for // all of the code used other than OpenSSL. If you modify file(s) // with this exception, you may extend this exception to your version // of the file(s), but you are not obligated to do so. If you do not // wish to do so, delete this exception statement from your version. // If you delete this exception statement from all source files in the // program, then also delete it here. // // Contact: Jari Sundell // // Skomakerveien 33 // 3185 Skoppum, NORWAY #include "config.h" #include "torrent/exceptions.h" #include "download_data.h" namespace torrent { // Calculate the number of chunks remaining to be downloaded. // // Doing it the slow and safe way, optimize this at some point. uint32_t download_data::calc_wanted_chunks() const { if (m_completed_bitfield.is_all_set()) return 0; priority_ranges wanted_ranges = priority_ranges::create_union(m_normal_priority, m_high_priority); if (m_completed_bitfield.is_all_unset()) return wanted_ranges.intersect_distance(0, m_completed_bitfield.size_bits()); if (m_completed_bitfield.empty()) throw internal_error("download_data::update_wanted_chunks() m_completed_bitfield.empty()."); uint32_t result = 0; for (const auto& wanted_range : wanted_ranges) { //remaining = completed->count_range(itr->first, itr->second); uint32_t idx = wanted_range.first; while (idx != wanted_range.second) result += !m_completed_bitfield.get(idx++); } return result; } void download_data::verify_wanted_chunks(const char* where) const { if (m_wanted_chunks != calc_wanted_chunks()) throw internal_error("Invalid download_data::wanted_chunks() value in " + std::string(where) + "."); } } // namespace torrent libtorrent-0.16.11/src/torrent/data/chunk_utils.h0000644000000000000000000000450015175073411015374 // libTorrent - BitTorrent library // Copyright (C) 2005-2011, Jari Sundell // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // In addition, as a special exception, the copyright holders give // permission to link the code of portions of this program with the // OpenSSL library under certain conditions as described in each // individual source file, and distribute linked combinations // including the two. // // You must obey the GNU General Public License in all respects for // all of the code used other than OpenSSL. If you modify file(s) // with this exception, you may extend this exception to your version // of the file(s), but you are not obligated to do so. If you do not // wish to do so, delete this exception statement from your version. // If you delete this exception statement from all source files in the // program, then also delete it here. // // Contact: Jari Sundell // // Skomakerveien 33 // 3185 Skoppum, NORWAY #ifndef LIBTORRENT_CHUNK_UTILS_H #define LIBTORRENT_CHUNK_UTILS_H #include #include #include namespace torrent { class ChunkList; struct vm_mapping { void* ptr; uint64_t length; }; // Change to ChunkList* when that becomes part of the public API. std::vector chunk_list_mapping(Download* download) LIBTORRENT_EXPORT; struct chunk_info_result { Download download; uint32_t chunk_index; uint32_t chunk_offset; const char* file_path; uint64_t file_offset; // void* chunk_begin; // void* chunk_end; // int prot; }; chunk_info_result chunk_list_address_info(void* address) LIBTORRENT_EXPORT; } // namespace torrent #endif libtorrent-0.16.11/src/torrent/data/file.cc0000644000000000000000000000674615175073411014137 #include "config.h" #include "torrent/data/file.h" #include #include "exceptions.h" #include "manager.h" #include "data/socket_file.h" #include "torrent/data/file_manager.h" #include "torrent/utils/file_stat.h" namespace torrent { File::~File() { assert((is_padding() || !is_open()) && "File::~File() called on an open file."); } bool File::is_created() const { if (is_padding()) return true; utils::FileStat fs; // If we can't even get permission to do fstat, we might as well // consider the file as not created. This function is to be used by // the client to check that the torrent files are present and ok, // rather than as a way to find out if it is starting on a blank // slate. if (!fs.update(frozen_path())) // return errno == EACCES; return false; return fs.is_regular(); } bool File::is_correct_size() const { if (is_padding()) return true; utils::FileStat fs; if (!fs.update(frozen_path())) return false; return fs.is_regular() && static_cast(fs.size()) == m_size; } void File::set_completed_chunks(uint32_t v) { if (has_flags(flag_active)) throw internal_error("File::set_completed_chunks(...) called on an active file."); if (v > size_chunks()) throw internal_error("File::set_completed_chunks(...) called with a value larger than the chunk size."); m_completed = v; } // At some point we should pass flags for deciding if the correct size // is necessary, etc. bool File::prepare(bool hashing, int prot, int flags) { if (is_padding()) return true; m_last_touched = this_thread::cached_time().count(); // Check if we got write protection and flag_resize_queued is // set. If so don't quit as we need to try re-sizing, instead call // resize_file. if (is_open() && has_permissions(prot)) return true; // For now don't allow overridding this check in prepare. if (m_flags & flag_create_queued) flags |= SocketFile::o_create; else flags &= ~SocketFile::o_create; if (!manager->file_manager()->open(this, hashing, prot, flags)) return false; m_flags |= flag_previously_created; m_flags &= ~flag_create_queued; // Replace PROT_WRITE with something prettier. if ((m_flags & flag_resize_queued) && has_permissions(PROT_WRITE)) { m_flags &= ~flag_resize_queued; return resize_file(); } return true; } void File::set_range(uint32_t chunkSize) { if (chunkSize == 0) m_range = range_type(0, 0); else if (m_size == 0) m_range = File::range_type(m_offset / chunkSize, m_offset / chunkSize); else m_range = File::range_type(m_offset / chunkSize, (m_offset + m_size + chunkSize - 1) / chunkSize); } void File::set_match_depth(File* left, File* right) { uint32_t level = 0; auto itrLeft = left->path()->begin(); auto itrRight = right->path()->begin(); while (itrLeft != left->path()->end() && itrRight != right->path()->end() && *itrLeft == *itrRight) { itrLeft++; itrRight++; level++; } left->m_match_depth_next = level; right->m_match_depth_prev = level; } bool File::resize_file() const { if (is_padding()) return true; if (!is_open()) return false; // This doesn't try to re-open it as rw. if (m_size == SocketFile(m_fd).size()) return true; if (!SocketFile(m_fd).set_size(m_size)) return false; if (m_flags & flag_fallocate) { // Only do non-blocking fallocate. if (!SocketFile(m_fd).allocate(m_size, SocketFile::flag_fallocate)) return false; } return true; } } // namespace torrent libtorrent-0.16.11/src/torrent/data/chunk_utils.cc0000644000000000000000000000647315175073411015545 // libTorrent - BitTorrent library // Copyright (C) 2005-2011, Jari Sundell // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // In addition, as a special exception, the copyright holders give // permission to link the code of portions of this program with the // OpenSSL library under certain conditions as described in each // individual source file, and distribute linked combinations // including the two. // // You must obey the GNU General Public License in all respects for // all of the code used other than OpenSSL. If you modify file(s) // with this exception, you may extend this exception to your version // of the file(s), but you are not obligated to do so. If you do not // wish to do so, delete this exception statement from your version. // If you delete this exception statement from all source files in the // program, then also delete it here. // // Contact: Jari Sundell // // Skomakerveien 33 // 3185 Skoppum, NORWAY #include "config.h" #include "chunk_utils.h" #include "download.h" #include "manager.h" #include "download/download_wrapper.h" #include "torrent/chunk_manager.h" #include "torrent/download/download_manager.h" #include "data/chunk_list.h" #include "data/file.h" namespace torrent { std::vector chunk_list_mapping(Download* download) { ChunkList* chunk_list = download->ptr()->main()->chunk_list(); std::vector mappings; for (const auto& chunk : *chunk_list) { if (!chunk.is_valid()) continue; for (const auto& itr2 : *chunk.chunk()) { if (itr2.mapped() != ChunkPart::MAPPED_MMAP) continue; vm_mapping val = {itr2.chunk().ptr(), itr2.chunk().size_aligned()}; mappings.push_back(val); } } return mappings; } chunk_info_result chunk_list_address_info(void* address) { for (const auto& chunk : *manager->chunk_manager()) { auto result = chunk->find_address(address); if (result.first != chunk->end()) { auto d_itr = manager->download_manager()->find_chunk_list(chunk); if (d_itr == manager->download_manager()->end()) return chunk_info_result(); chunk_info_result ci; ci.download = Download(*d_itr); ci.chunk_index = result.first->index(); ci.chunk_offset = result.second->position() + std::distance(result.second->chunk().begin(), static_cast(address)); ci.file_path = result.second->file()->frozen_path().c_str(); ci.file_offset = result.second->file_offset() + std::distance(result.second->chunk().begin(), static_cast(address)); return ci; } } return chunk_info_result(); } } // namespace torrent libtorrent-0.16.11/src/torrent/data/block_transfer.h0000644000000000000000000000666015175073411016053 #ifndef LIBTORRENT_BLOCK_TRANSFER_H #define LIBTORRENT_BLOCK_TRANSFER_H #include #include #include #include #include namespace torrent { class LIBTORRENT_EXPORT BlockTransfer { public: static constexpr uint32_t invalid_index = ~uint32_t(); using key_type = PeerInfo*; enum state_type { STATE_ERASED, STATE_QUEUED, STATE_LEADER, STATE_NOT_LEADER }; BlockTransfer() = default; ~BlockTransfer(); BlockTransfer(const BlockTransfer&) = delete; BlockTransfer& operator=(const BlockTransfer&) = delete; // TODO: Do we need to also check for peer_info?... bool is_valid() const { return m_block != NULL; } bool is_erased() const { return m_state == STATE_ERASED; } bool is_queued() const { return m_state == STATE_QUEUED; } bool is_leader() const { return m_state == STATE_LEADER; } bool is_not_leader() const { return m_state == STATE_NOT_LEADER; } bool is_finished() const { return m_position == m_piece.length(); } key_type peer_info() { return m_peer_info; } key_type const_peer_info() const { return m_peer_info; } Block* block() { return m_block; } const Block* const_block() const { return m_block; } const Piece& piece() const { return m_piece; } uint32_t index() const { return m_piece.index(); } state_type state() const { return m_state; } int32_t request_time() const { return m_request_time; } // Adjust the position after any actions like erasing it from a // Block, but before if finishing. uint32_t position() const { return m_position; } uint32_t stall() const { return m_stall; } uint32_t failed_index() const { return m_failedIndex; } void set_peer_info(key_type p); void set_block(Block* b) { m_block = b; } void set_piece(const Piece& p) { m_piece = p; } void set_state(state_type s) { m_state = s; } void set_request_time(int32_t t) { m_request_time = t; } void set_position(uint32_t p) { m_position = p; } void adjust_position(uint32_t p) { m_position += p; } void set_stall(uint32_t s) { m_stall = s; } void set_failed_index(uint32_t i) { m_failedIndex = i; } private: key_type m_peer_info{}; Block* m_block{}; Piece m_piece; state_type m_state; int32_t m_request_time; uint32_t m_position; uint32_t m_stall; uint32_t m_failedIndex; }; inline BlockTransfer::~BlockTransfer() { assert(m_block == NULL && "BlockTransfer::~BlockTransfer() block not NULL"); assert(m_peer_info == NULL && "BlockTransfer::~BlockTransfer() peer_info not NULL"); } inline void BlockTransfer::set_peer_info(key_type p) { if (m_peer_info != NULL) m_peer_info->dec_transfer_counter(); m_peer_info = p; if (m_peer_info != NULL) m_peer_info->inc_transfer_counter(); } } // namespace torrent #endif libtorrent-0.16.11/src/torrent/data/block.h0000644000000000000000000001170715175073411014145 #ifndef LIBTORRENT_BLOCK_H #define LIBTORRENT_BLOCK_H #include #include #include #include namespace torrent { // If you start adding slots, make sure the rest of the code creates // copies and clears the original variables before calls to erase etc. class LIBTORRENT_EXPORT Block { public: // Using vectors as they will remain small, thus the cost of erase // should be small. Later we can do faster erase by ignoring the // ordering. using transfer_list_type = std::vector; using size_type = uint32_t; enum state_type { STATE_INCOMPLETE, STATE_COMPLETED, STATE_INVALID }; Block() = default; ~Block(); // Only allow move constructions Block(const Block&) = delete; Block& operator=(const Block&) = delete; Block(Block&&) = default; Block& operator=(Block&&) = default; bool is_stalled() const { return m_notStalled == 0; } bool is_finished() const; bool is_transfering() const; bool is_peer_queued(const PeerInfo* p) const { return find_queued(p) != NULL; } bool is_peer_transfering(const PeerInfo* p) const { return find_transfer(p) != NULL; } size_type size_all() const { return m_queued.size() + m_transfers.size(); } size_type size_not_stalled() const { return m_notStalled; } BlockList* parent() { return m_parent; } const BlockList* parent() const { return m_parent; } void set_parent(BlockList* p) { m_parent = p; } const Piece& piece() const { return m_piece; } void set_piece(const Piece& p) { m_piece = p; } uint32_t index() const { return m_piece.index(); } const transfer_list_type* queued() const { return &m_queued; } const transfer_list_type* transfers() const { return &m_transfers; } // The leading transfer, whom's data we're currently using. BlockTransfer* leader() { return m_leader; } const BlockTransfer* leader() const { return m_leader; } BlockTransfer* find(const PeerInfo* p); const BlockTransfer* find(const PeerInfo* p) const; BlockTransfer* find_queued(const PeerInfo* p); const BlockTransfer* find_queued(const PeerInfo* p) const; BlockTransfer* find_transfer(const PeerInfo* p); const BlockTransfer* find_transfer(const PeerInfo* p) const; // Internal to libTorrent: BlockTransfer* insert(PeerInfo* peerInfo); void erase(BlockTransfer* transfer); bool transfering(BlockTransfer* transfer); void transfer_dissimilar(BlockTransfer* transfer); bool completed(BlockTransfer* transfer); void retry_transfer(); static void stalled(BlockTransfer* transfer); void stalled_transfer(BlockTransfer* transfer); void change_leader(BlockTransfer* transfer); void failed_leader(); BlockFailed* failed_list() { return m_failedList; } void set_failed_list(BlockFailed* f) { m_failedList = f; } static void create_dummy(BlockTransfer* transfer, PeerInfo* peerInfo, const Piece& piece); // If the queued or transfering is already removed from the block it // will just delete the object. Made static so it can be called when // block == NULL. static void release(BlockTransfer* transfer); private: void invalidate_transfer(BlockTransfer* transfer) LIBTORRENT_NO_EXPORT; void remove_erased_transfers() LIBTORRENT_NO_EXPORT; void remove_non_leader_transfers() LIBTORRENT_NO_EXPORT; BlockList* m_parent{}; Piece m_piece; state_type m_state{STATE_INCOMPLETE}; uint32_t m_notStalled{0}; transfer_list_type m_queued; transfer_list_type m_transfers; BlockTransfer* m_leader{}; BlockFailed* m_failedList{}; }; inline BlockTransfer* Block::find(const PeerInfo* p) { if (auto transfer = find_queued(p)) return transfer; else return find_transfer(p); } inline const BlockTransfer* Block::find(const PeerInfo* p) const { if (auto transfer = find_queued(p)) return transfer; else return find_transfer(p); } } // namespace torrent #endif libtorrent-0.16.11/src/torrent/data/transfer_list.cc0000644000000000000000000001735115175073411016071 #include "config.h" #include "transfer_list.h" #include #include #include #include #include "data/chunk.h" #include "peer/peer_info.h" #include "block_failed.h" #include "block_transfer.h" #include "block_list.h" #include "exceptions.h" #include "piece.h" namespace torrent { TransferList::~TransferList() { assert(base_type::empty() && "TransferList::~TransferList() called on an non-empty object"); } TransferList::iterator TransferList::find(uint32_t index) { return std::find_if(begin(), end(), [index](BlockList* b) { return index == b->index(); }); } TransferList::const_iterator TransferList::find(uint32_t index) const { return std::find_if(begin(), end(), [index](BlockList* b) { return index == b->index(); }); } void TransferList::clear() { for (const auto& block_list : *this) { m_slot_canceled(block_list->index()); } for (const auto& block_list : *this) { delete block_list; } base_type::clear(); } TransferList::iterator TransferList::insert(const Piece& piece, uint32_t blockSize) { if (find(piece.index()) != end()) throw internal_error("Delegator::new_chunk(...) received an index that is already delegated."); auto blockList = new BlockList(piece, blockSize); m_slot_queued(piece.index()); return base_type::insert(end(), blockList); } // TODO: Create a destructor to ensure all blocklists have been cleared/invaldiated? TransferList::iterator TransferList::erase(iterator itr) { if (itr == end()) throw internal_error("TransferList::erase(...) itr == m_chunks.end()."); delete *itr; return base_type::erase(itr); } void TransferList::finished(BlockTransfer* transfer) { if (!transfer->is_valid()) throw internal_error("TransferList::finished(...) got transfer with wrong state."); uint32_t index = transfer->block()->index(); // Marks the transfer as complete and erases it. if (transfer->block()->completed(transfer)) m_slot_completed(index); } void TransferList::hash_succeeded(uint32_t index, Chunk* chunk) { auto blockListItr = find(index); if (!std::all_of((*blockListItr)->begin(), (*blockListItr)->end(), std::mem_fn(&Block::is_finished))) throw internal_error("TransferList::hash_succeeded(...) Finished blocks does not match size."); // The chunk should also be marked here or by the caller so that it // gets priority for syncing back to disk. if ((*blockListItr)->failed() != 0) mark_failed_peers(*blockListItr, chunk); // Add to a list of finished chunks indices with timestamps. This is // mainly used for torrent resume data on which chunks need to be // rehashed on crashes. // // We assume the chunk gets sync'ed within 10 minutes, so minimum // retention time of 30 minutes should be enough. The list only gets // pruned every 60 minutes, so any timer that reads values once // every 30 minutes is guaranteed to get them all as long as it is // ordered properly. m_completedList.emplace_back(this_thread::cached_time().count(), index); if (std::chrono::microseconds(m_completedList.front().first) + 60min < this_thread::cached_time()) { auto itr = std::find_if(m_completedList.begin(), m_completedList.end(), [](auto v) { return this_thread::cached_time() - 30min <= std::chrono::microseconds(v.first); }); m_completedList.erase(m_completedList.begin(), itr); } m_succeededCount++; erase(blockListItr); } struct transfer_list_compare_data { transfer_list_compare_data(Chunk* chunk, const Piece& p) : m_chunk(chunk), m_piece(p) { } bool operator () (BlockFailed::value_type failed) const { return m_chunk->compare_buffer(failed.first, m_piece.offset(), m_piece.length()); } Chunk* m_chunk; Piece m_piece; }; void TransferList::hash_failed(uint32_t index, Chunk* chunk) { auto blockListItr = find(index); if (blockListItr == end()) throw internal_error("TransferList::hash_failed(...) Could not find index."); if (!std::all_of((*blockListItr)->begin(), (*blockListItr)->end(), std::mem_fn(&Block::is_finished))) throw internal_error("TransferList::hash_failed(...) Finished blocks does not match size."); m_failedCount++; // Could propably also check promoted against size of the block // list. if ((*blockListItr)->attempt() == 0) { unsigned int promoted = update_failed(*blockListItr, chunk); if (promoted > 0 || promoted < (*blockListItr)->size()) { // Retry with the most popular blocks. (*blockListItr)->set_attempt(1); retry_most_popular(*blockListItr, chunk); // Also consider various other schemes, like using blocks from // only/mainly one peer. return; } } // Should we check if there's any peers whom have sent us bad data // before, and just clear those first? // Re-download the blocks. (*blockListItr)->do_all_failed(); } // update_failed(...) either increments the reference count of a // failed entry, or creates a new one if the data differs. unsigned int TransferList::update_failed(BlockList* blockList, Chunk* chunk) { unsigned int promoted = 0; blockList->inc_failed(); for (auto& transfer : *blockList) { if (transfer.failed_list() == NULL) transfer.set_failed_list(new BlockFailed()); auto failedItr = std::find_if(transfer.failed_list()->begin(), transfer.failed_list()->end(), transfer_list_compare_data(chunk, transfer.piece())); if (failedItr == transfer.failed_list()->end()) { // We've never encountered this data before, make a new entry. auto buffer = new char[transfer.piece().length()]; chunk->to_buffer(buffer, transfer.piece().offset(), transfer.piece().length()); transfer.failed_list()->emplace_back(buffer, 1); failedItr = transfer.failed_list()->end() - 1; // Count how many new data sets? } else { // Increment promoted when the entry's reference count becomes // larger than others, but not if it previously was the largest. auto maxItr = transfer.failed_list()->max_element(); if (maxItr->second == failedItr->second && maxItr != (transfer.failed_list()->reverse_max_element().base() - 1)) promoted++; failedItr->second++; } transfer.failed_list()->set_current(failedItr); transfer.leader()->set_failed_index(failedItr - transfer.failed_list()->begin()); } return promoted; } void TransferList::mark_failed_peers(BlockList* blockList, Chunk* chunk) { std::set badPeers; for (auto& block : *blockList) { // This chunk data is good, set it as current and // everyone who sent something else is a bad peer. block.failed_list()->set_current(std::find_if(block.failed_list()->begin(), block.failed_list()->end(), transfer_list_compare_data(chunk, block.piece()))); for (auto& transfer : *block.transfers()) if (transfer->failed_index() != block.failed_list()->current() && transfer->failed_index() != ~uint32_t()) badPeers.insert(transfer->peer_info()); } std::for_each(badPeers.begin(), badPeers.end(), m_slot_corrupt); } // Copy the stored data to the chunk from the failed entries with // largest reference counts. void TransferList::retry_most_popular(BlockList* blockList, Chunk* chunk) { for (auto& block : *blockList) { auto failedItr = block.failed_list()->reverse_max_element(); if (failedItr == block.failed_list()->rend()) throw internal_error("TransferList::retry_most_popular(...) No failed list entry found."); // The data is the same, so no need to copy. if (failedItr == block.failed_list()->current_reverse_iterator()) continue; // Change the leader to the currently held buffer? chunk->from_buffer(failedItr->first, block.piece().offset(), block.piece().length()); block.failed_list()->set_current(failedItr); } m_slot_completed(blockList->index()); } } // namespace torrent libtorrent-0.16.11/src/torrent/data/file_list_iterator.h0000644000000000000000000001006215175073411016727 #ifndef LIBTORRENT_FILE_LIST_ITERATOR_H #define LIBTORRENT_FILE_LIST_ITERATOR_H #include #include #include namespace torrent { class File; // A special purpose iterator class for iterating through FileList as // a dired structure. class LIBTORRENT_EXPORT FileListIterator { public: using iterator = FileList::iterator; using reference = File*; using pointer = File**; FileListIterator() = default; explicit FileListIterator(iterator pos, uint32_t depth = 0) : m_position(pos), m_depth(depth) {} bool is_file() const; bool is_empty() const; bool is_entering() const; bool is_leaving() const { return m_depth < 0; } uint32_t depth() const { return std::abs(m_depth); } iterator base() const { return m_position; } reference file() const { return m_position->get(); } FileListIterator& operator ++(); FileListIterator& operator --(); FileListIterator operator ++(int); FileListIterator operator --(int); FileListIterator& forward_current_depth(); FileListIterator& backward_current_depth(); friend bool operator ==(const FileListIterator& left, const FileListIterator& right); friend bool operator !=(const FileListIterator& left, const FileListIterator& right); private: iterator m_position; int32_t m_depth; }; inline FileListIterator FileListIterator::operator ++(int) { FileListIterator tmp = *this; ++(*this); return tmp; } inline FileListIterator FileListIterator::operator --(int) { FileListIterator tmp = *this; --(*this); return tmp; } inline bool operator ==(const FileListIterator& left, const FileListIterator& right) { return left.m_position == right.m_position && left.m_depth == right.m_depth; } inline bool operator !=(const FileListIterator& left, const FileListIterator& right) { return left.m_position != right.m_position || left.m_depth != right.m_depth; } // Take a range as input and return the next entry at the same // directory depth as first. If the returned iterator equals 'last' or // is_leaving() == true then the search failed. class LIBTORRENT_EXPORT file_list_collapsed_iterator : private FileListIterator { public: using base_type = FileListIterator; using this_type = file_list_collapsed_iterator; using base_type::iterator; using base_type::reference; using base_type::pointer; using base_type::is_file; using base_type::is_empty; using base_type::is_entering; using base_type::is_leaving; using base_type::depth; using base_type::file; file_list_collapsed_iterator() = default; file_list_collapsed_iterator(const FileListIterator& src) : FileListIterator(src) {} explicit file_list_collapsed_iterator(iterator pos, uint32_t depth = 0) : FileListIterator(pos, depth) {} base_type base() const { return *static_cast(this); } this_type& operator ++() { base_type::forward_current_depth(); return *this; } this_type& operator --() { base_type::backward_current_depth(); return *this; } this_type operator ++(int); this_type operator --(int); friend bool operator ==(const file_list_collapsed_iterator& left, const file_list_collapsed_iterator& right); friend bool operator !=(const file_list_collapsed_iterator& left, const file_list_collapsed_iterator& right); }; inline bool operator ==(const file_list_collapsed_iterator& left, const file_list_collapsed_iterator& right) { return left.base() == right.base(); } inline bool operator !=(const file_list_collapsed_iterator& left, const file_list_collapsed_iterator& right) { return left.base() != right.base(); } inline file_list_collapsed_iterator file_list_collapsed_iterator::operator ++(int) { this_type tmp = *this; ++(*this); return tmp; } inline file_list_collapsed_iterator file_list_collapsed_iterator::operator --(int) { this_type tmp = *this; --(*this); return tmp; } } // namespace torrent #endif libtorrent-0.16.11/src/torrent/data/file_list.cc0000644000000000000000000005131215175073411015157 #include "config.h" #include "torrent/data/file_list.h" #include #include #include #include #include #include #include "manager.h" #include "piece.h" #include "data/chunk.h" #include "data/memory_chunk.h" #include "data/socket_file.h" #include "torrent/exceptions.h" #include "torrent/path.h" #include "torrent/data/file.h" #include "torrent/data/file_manager.h" #include "torrent/utils/file_stat.h" #include "torrent/utils/log.h" #if HAVE_SYS_VFS_H #include #endif #if HAVE_SYS_STATVFS_H #include #endif #if HAVE_SYS_STATFS_H #include #endif #define LT_LOG_FL(log_level, log_fmt, ...) \ lt_log_print_data(LOG_STORAGE_##log_level, (&m_data), "file_list", log_fmt, __VA_ARGS__); namespace torrent { static void verify_file_list(const FileList* fl) { if (fl->empty()) throw internal_error("verify_file_list() 1.", fl->data()->hash()); if ((*fl->begin())->match_depth_prev() != 0 || (*fl->rbegin())->match_depth_next() != 0) throw internal_error("verify_file_list() 2.", fl->data()->hash()); for (auto itr = fl->begin(), last = fl->end() - 1; itr != last; itr++) if ((*itr)->match_depth_next() != (*(itr + 1))->match_depth_prev() || (*itr)->match_depth_next() >= (*itr)->path()->size()) throw internal_error("verify_file_list() 3.", fl->data()->hash()); } FileList::FileList() = default; FileList::~FileList() { // Can we skip close()? close(); base_type::clear(); m_torrent_size = 0; } bool FileList::is_valid_piece(const Piece& piece) const { return piece.index() < size_chunks() && piece.length() != 0 && // Make sure offset does not overflow 32 bits. piece.offset() + piece.length() >= piece.offset() && piece.offset() + piece.length() <= chunk_index_size(piece.index()); } bool FileList::is_root_dir_created() const { utils::FileStat fs; if (!fs.update(m_root_dir)) // return errno == EACCES return false; return fs.is_directory(); } bool FileList::is_multi_file() const { // Currently only check if we got just one file. In the future this // should be a bool, which will be set based on what flags are // passed when the torrent was loaded. return m_multi_file; } uint64_t FileList::completed_bytes() const { // Chunk size needs to be cast to a uint64_t for the below to work. uint64_t cs = chunk_size(); if (bitfield()->empty()) return bitfield()->is_all_set() ? size_bytes() : (completed_chunks() * cs); if (!bitfield()->get(size_chunks() - 1) || size_bytes() % cs == 0) { // The last chunk is not done, or the last chunk is the same size // as the others. return completed_chunks() * cs; } else { if (completed_chunks() == 0) throw internal_error("FileList::bytes_completed() completed_chunks() == 0.", data()->hash()); return (completed_chunks() - 1) * cs + size_bytes() % cs; } } uint64_t FileList::left_bytes() const { uint64_t left = size_bytes() - completed_bytes(); if (left > (uint64_t{1} << 60)) throw internal_error("FileList::bytes_left() is too large.", data()->hash()); if (completed_chunks() == size_chunks() && left != 0) throw internal_error("FileList::bytes_left() has an invalid size.", data()->hash()); return left; } uint32_t FileList::chunk_index_size(uint32_t index) const { if (index + 1 != size_chunks() || size_bytes() % chunk_size() == 0) return chunk_size(); else return size_bytes() % chunk_size(); } void FileList::set_root_dir(const std::string& path) { if (is_open()) throw input_error("Tried to change the root directory on an open download."); std::string::size_type last = path.find_last_not_of('/'); if (last == std::string::npos) m_root_dir = "."; else m_root_dir = path.substr(0, last + 1); } void FileList::set_max_file_size(uint64_t size) { if (is_open()) throw input_error("Tried to change the max file size for an open download."); m_max_file_size = size; } // This function should really ensure that we arn't dealing files // spread over multiple mount-points. uint64_t FileList::free_diskspace() const { uint64_t free_diskspace = std::numeric_limits::max(); for (const auto& link : m_indirect_links) { FS_STAT_STRUCT m_stat; auto fn = link.c_str(); if (!(FS_STAT_FN)) continue; free_diskspace = std::min(free_diskspace, (int64_t)(FS_STAT_BLOCK_SIZE) * m_stat.f_bavail); } return free_diskspace != std::numeric_limits::max() ? free_diskspace : 0; } FileList::iterator_range FileList::split(iterator position, split_type* first, split_type* last) { if (is_open()) throw internal_error("FileList::split(...) is_open().", data()->hash()); if (first == last || position == end()) throw internal_error("FileList::split(...) invalid arguments.", data()->hash()); if (position != begin()) (*(position - 1))->set_match_depth_next(0); if (position + 1 != end()) (*(position + 1))->set_match_depth_prev(0); auto old_file = std::move(*position); uint64_t offset = old_file->offset(); size_type index = std::distance(begin(), position); size_type length = std::distance(first, last); // This is inefficient, but the simplest way to do it with unique_ptr vector i could find. for (size_type i = 0; i < length - 1; i++) base_type::insert(begin() + index, nullptr); position = begin() + index; auto itr = position; while (first != last) { auto new_file = std::make_unique(); new_file->set_offset(offset); new_file->set_size_bytes(std::get<0>(*first)); new_file->set_range(m_chunk_size); *new_file->mutable_path() = std::get<1>(*first); new_file->set_flags(std::get<2>(*first)); offset += std::get<0>(*first); *itr = std::move(new_file); itr++; first++; } if (offset != old_file->offset() + old_file->size_bytes()) throw internal_error("FileList::split(...) split size does not match the old size.", data()->hash()); return iterator_range(position, itr); } FileList::iterator FileList::merge(iterator first, iterator last, const Path& path) { auto new_file = std::make_unique(); // Set the path before deleting any iterators in case it refers to // one of the objects getting deleted. *(new_file->mutable_path()) = path; if (first == last) { if (first == end()) new_file->set_offset(m_torrent_size); else new_file->set_offset((*first)->offset()); first = base_type::insert(first, std::move(new_file)); } else { new_file->set_offset((*first)->offset()); for (auto itr = first; itr != last; ++itr) new_file->set_size_bytes(new_file->size_bytes() + (*itr)->size_bytes()); first = base_type::erase(first + 1, last) - 1; *first = std::move(new_file); } (*first)->set_range(m_chunk_size); if (first == begin()) (*first)->set_match_depth_prev(0); else File::set_match_depth(std::prev(first)->get(), first->get()); if (first + 1 == end()) (*first)->set_match_depth_next(0); else File::set_match_depth(first->get(), std::next(first)->get()); return first; } // If the user supplies an invalid range, it will bork in weird ways. void FileList::update_paths(iterator first, iterator last) { // Check if we're open? if (first == last) return; if (first != begin()) File::set_match_depth((first - 1)->get(), first->get()); while (first != last && ++first != end()) File::set_match_depth((first - 1)->get(), first->get()); verify_file_list(this); } bool FileList::make_root_path() { if (!is_open()) return false; return ::mkdir(m_root_dir.c_str(), 0777) == 0 || errno == EEXIST; } bool FileList::make_all_paths() { if (!is_open()) return false; Path dummyPath; const Path* lastPath = &dummyPath; for (auto& entry : *this) { // No need to create directories if the entry has already been // opened. if (entry->is_open()) continue; if (entry->path()->empty()) throw storage_error("Found an empty filename."); auto lastPathItr = lastPath->begin(); auto firstMismatch = entry->path()->begin(); // Couldn't find a suitable stl algo, need to write my own. while (firstMismatch != entry->path()->end() && lastPathItr != lastPath->end() && *firstMismatch == *lastPathItr) { lastPathItr++; firstMismatch++; } errno = 0; make_directory(entry->path()->begin(), entry->path()->end(), firstMismatch); lastPath = entry->path(); } return true; } // Initialize FileList and add a dummy file that may be split into // multiple files. void FileList::initialize(uint64_t torrentSize, uint32_t chunkSize) { if (sizeof(off_t) != 8) throw internal_error("Last minute panic; sizeof(off_t) != 8.", data()->hash()); if (chunkSize == 0) throw internal_error("FileList::initialize() chunk_size() == 0.", data()->hash()); m_chunk_size = chunkSize; m_torrent_size = torrentSize; m_root_dir = "."; m_data.mutable_completed_bitfield()->set_size_bits((size_bytes() + chunk_size() - 1) / chunk_size()); m_data.mutable_normal_priority()->insert(0, size_chunks()); m_data.set_wanted_chunks(size_chunks()); auto new_file = std::make_unique(); new_file->set_offset(0); new_file->set_size_bytes(torrentSize); new_file->set_range(m_chunk_size); base_type::push_back(std::move(new_file)); } struct file_list_cstr_less { bool operator () (const char* c1, const char* c2) const { return std::strcmp(c1, c2) < 0; } }; void FileList::open(bool hashing, int flags) { using path_set = std::set; LT_LOG_FL(INFO, "Opening.", 0); if (m_root_dir.empty()) throw internal_error("FileList::open() m_root_dir.empty().", data()->hash()); m_indirect_links.push_back(m_root_dir); Path lastPath; path_set pathSet; auto itr = end(); try { if (!(flags & open_no_create) && !make_root_path()) throw storage_error("Could not create directory '" + m_root_dir + "': " + std::strerror(errno)); for (auto& entry : *this) { // We no longer consider it an error to open a previously opened // FileList as we now use the same function to create // non-existent files. // // Since m_is_open is set, we know root dir wasn't changed, thus // we can keep the previously opened file. if (entry->is_open()) continue; if (entry->is_padding()) continue; // Update the path during open so that any changes to root dir // and file paths are properly handled. if (entry->path()->back().empty()) entry->set_frozen_path(std::string()); else entry->set_frozen_path(m_root_dir + entry->path()->as_string()); if (!pathSet.insert(entry->frozen_path().c_str()).second) throw storage_error("Duplicate filename found."); if (entry->size_bytes() > m_max_file_size) throw storage_error("File exceedes the configured max file size."); if (entry->path()->empty()) throw storage_error("Empty filename is not allowed."); // Handle directory creation outside of open_file, so we can do // it here if necessary. entry->set_flags_protected(File::flag_active); if (!open_file(&*entry, lastPath, hashing, flags)) { // This needs to check if the error was due to open_no_create // being set or not. if (!(flags & open_no_create)) // Also check if open_require_all_open is set. throw storage_error("Could not open file: " + std::string(std::strerror(errno))); // Don't set the lastPath as we haven't created the directory. continue; } lastPath = *entry->path(); } } catch (const local_error& e) { for (auto& entry : *this) { entry->unset_flags_protected(File::flag_active); manager->file_manager()->close(entry.get()); } if (itr == end()) { LT_LOG_FL(ERROR, "Failed to prepare file list: %s", e.what()); } else { LT_LOG_FL(ERROR, "Failed to prepare file '%s': %s", (*itr)->path()->as_string().c_str(), e.what()); } // Set to false here in case we tried to open the FileList for the // second time. m_is_open = false; throw; } m_is_open = true; m_frozen_root_dir = m_root_dir; // For meta-downloads, if the file exists, we have to assume that // it is either 0 or 1 length or the correct size. If the size // turns out wrong later, a storage_error will be thrown elsewhere // to alert the user in this (unlikely) case. // // DEBUG: Make this depend on a flag... if (size_bytes() < 2) { utils::FileStat stat; // This probably recurses into open() once, but that is harmless. if (stat.update((*begin())->frozen_path()) && stat.size() > 1) return reset_filesize(stat.size()); } } void FileList::close() { if (!is_open()) return; LT_LOG_FL(INFO, "Closing.", 0); for (auto& entry : *this) { entry->unset_flags_protected(File::flag_active); manager->file_manager()->close(entry.get()); } m_is_open = false; m_indirect_links.clear(); m_data.mutable_completed_bitfield()->unallocate(); } void FileList::close_all_files() { if (!is_open()) return; LT_LOG_FL(INFO, "Closing all files.", 0); for (auto& entry : *this) manager->file_manager()->close(entry.get()); } void FileList::make_directory(Path::const_iterator pathBegin, Path::const_iterator pathEnd, Path::const_iterator startItr) { std::string path = m_root_dir; while (pathBegin != pathEnd) { path += "/" + *pathBegin; if (pathBegin++ != startItr) continue; startItr++; utils::FileStat fileStat; if (fileStat.update_link(path) && fileStat.is_link() && std::find(m_indirect_links.begin(), m_indirect_links.end(), path) == m_indirect_links.end()) m_indirect_links.push_back(path); if (pathBegin == pathEnd) break; if (::mkdir(path.c_str(), 0777) != 0 && errno != EEXIST) throw storage_error("Could not create directory '" + path + "': " + std::strerror(errno)); } } bool FileList::open_file(File* file_node, const Path& lastPath, bool hashing, int flags) { errno = 0; if (!(flags & open_no_create)) { const Path* path = file_node->path(); auto lastItr = lastPath.begin(); auto firstMismatch = path->begin(); // Couldn't find a suitable stl algo, need to write my own. while (firstMismatch != path->end() && lastItr != lastPath.end() && *firstMismatch == *lastItr) { lastItr++; firstMismatch++; } make_directory(path->begin(), path->end(), firstMismatch); } // Some torrents indicate an empty directory by having a path with // an empty last element. This entry must be zero length. if (file_node->path()->back().empty()) return file_node->size_bytes() == 0; utils::FileStat file_stat; if (file_stat.update(file_node->frozen_path()) && !file_stat.is_regular() && !file_stat.is_link()) { // Might also bork on other kinds of file types, but there's no // suitable errno for all cases. errno = EISDIR; return false; } return file_node->prepare(hashing, MemoryChunk::prot_read, 0); } MemoryChunk FileList::create_chunk_part(FileList::iterator itr, uint64_t offset, uint32_t length, bool hashing, int prot) const { offset -= (*itr)->offset(); length = std::min(length, (*itr)->size_bytes() - offset); if ((*itr)->is_padding()) return SocketFile::create_padding_chunk(length, prot, MemoryChunk::map_shared); if (static_cast(offset) < 0) throw internal_error("FileList::chunk_part(...) caught a negative offset", data()->hash()); // Check that offset != length of file. if (!(*itr)->prepare(hashing, prot, 0)) return MemoryChunk(); auto mc = SocketFile((*itr)->file_descriptor()).create_chunk(offset, length, prot, MemoryChunk::map_shared); if (!mc.is_valid()) return MemoryChunk(); if (mc.size() == 0) throw internal_error("FileList::create_chunk(...) mc.size() == 0.", data()->hash()); if (mc.size() > length) throw internal_error("FileList::create_chunk(...) mc.size() > length.", data()->hash()); #ifdef USE_MADVISE // TODO: Update all uses of madvise to posix_madvise. if (hashing) { if (manager->file_manager()->advise_random_hashing()) madvise(mc.ptr(), mc.size(), MADV_RANDOM); } else { if (manager->file_manager()->advise_random()) madvise(mc.ptr(), mc.size(), MADV_RANDOM); } #endif return mc; } Chunk* FileList::create_chunk(uint64_t offset, uint32_t length, bool hashing, int prot) { if (offset + length > m_torrent_size) throw internal_error("Tried to access chunk out of range in FileList", data()->hash()); auto chunk = std::make_unique(); auto itr = std::find_if(begin(), end(), [offset](const value_type& file) { return file->is_valid_position(offset); }); for (; length != 0; ++itr) { if (itr == end()) throw internal_error("FileList could not find a valid file for chunk", data()->hash()); if ((*itr)->size_bytes() == 0) continue; MemoryChunk mc = create_chunk_part(itr, offset, length, hashing, prot); if (!mc.is_valid()) return nullptr; chunk->push_back(ChunkPart::MAPPED_MMAP, mc); chunk->back().set_file(itr->get(), offset - (*itr)->offset()); offset += mc.size(); length -= mc.size(); } if (chunk->empty()) return NULL; return chunk.release(); } Chunk* FileList::create_chunk_index(uint32_t index, int prot) { return create_chunk(static_cast(index) * chunk_size(), chunk_index_size(index), false, prot); } Chunk* FileList::create_hashing_chunk_index(uint32_t index, int prot) { return create_chunk(static_cast(index) * chunk_size(), chunk_index_size(index), true, prot); } void FileList::mark_completed(uint32_t index) { if (index >= size_chunks() || completed_chunks() >= size_chunks()) throw internal_error("FileList::mark_completed(...) received an invalid index.", data()->hash()); if (bitfield()->empty()) throw internal_error("FileList::mark_completed(...) bitfield is empty.", data()->hash()); if (bitfield()->size_bits() != size_chunks()) throw internal_error("FileList::mark_completed(...) bitfield is not the right size.", data()->hash()); if (bitfield()->get(index)) throw internal_error("FileList::mark_completed(...) received a chunk that has already been finished.", data()->hash()); if (bitfield()->size_set() >= bitfield()->size_bits()) throw internal_error("FileList::mark_completed(...) bitfield()->size_set() >= bitfield()->size_bits().", data()->hash()); LT_LOG_FL(DEBUG, "Done chunk: index:%" PRIu32 ".", index); m_data.mutable_completed_bitfield()->set(index); inc_completed(begin(), index); // TODO: Remember to validate 'wanted_chunks'. if (m_data.normal_priority()->has(index) || m_data.high_priority()->has(index)) { if (m_data.wanted_chunks() == 0) throw internal_error("FileList::mark_completed(...) m_data.wanted_chunks() == 0.", data()->hash()); m_data.set_wanted_chunks(m_data.wanted_chunks() - 1); } } FileList::iterator FileList::inc_completed(iterator firstItr, uint32_t index) { firstItr = std::find_if(firstItr, end(), [index](value_type& file) { return index < file->range_second(); }); auto lastItr = std::find_if(firstItr, end(), [index](value_type& file) { return index+1 < file->range_second(); }); if (firstItr == end()) throw internal_error("FileList::inc_completed() first == m_entryList->end().", data()->hash()); // TODO: Check if this works right for zero-length files. std::for_each(firstItr, lastItr == end() ? end() : (lastItr + 1), std::mem_fn(&File::inc_completed_protected)); return lastItr; } void FileList::update_completed() { if (!bitfield()->is_tail_cleared()) throw internal_error("Content::update_done() called but m_bitfield's tail isn't cleared.", data()->hash()); m_data.update_wanted_chunks(); if (bitfield()->is_all_set()) { for (auto& entry : *this) entry->set_completed_protected(entry->size_chunks()); } else { // Clear any old progress data from the entries as we don't clear // this on close, etc. for (auto& entry : *this) entry->set_completed_protected(0); if (bitfield()->is_all_unset()) return; auto entryItr = begin(); for (Bitfield::size_type index = 0; index < bitfield()->size_bits(); ++index) if (bitfield()->get(index)) entryItr = inc_completed(entryItr, index); } } // Used for metadata downloads. void FileList::reset_filesize(int64_t size) { LT_LOG_FL(INFO, "Resetting torrent size: size:%" PRIi64 ".", size); close(); m_chunk_size = size; m_torrent_size = size; (*begin())->set_size_bytes(size); (*begin())->set_range(m_chunk_size); m_data.mutable_completed_bitfield()->allocate(); m_data.mutable_completed_bitfield()->unset_all(); open(false, open_no_create); } } // namespace torrent libtorrent-0.16.11/src/torrent/data/download_data.h0000644000000000000000000000703415175073411015651 #ifndef LIBTORRENT_DATA_DOWNLOAD_DATA_H #define LIBTORRENT_DATA_DOWNLOAD_DATA_H #include #include #include #include #include namespace torrent { class ChunkListNode; class ChunkSelector; class Download; class DownloadWrapper; class FileList; class download_data { public: using priority_ranges = ranges; using slot_void = std::function; using slot_chunk_list_node_p = std::function; const HashString& hash() const { return m_hash; } bool is_partially_done() const { return m_wanted_chunks == 0; } bool is_not_partially_done() const { return m_wanted_chunks != 0; } const Bitfield* completed_bitfield() const { return &m_completed_bitfield; } const Bitfield* untouched_bitfield() const { return &m_untouched_bitfield; } const priority_ranges* high_priority() const { return &m_high_priority; } const priority_ranges* normal_priority() const { return &m_normal_priority; } uint32_t wanted_chunks() const { return m_wanted_chunks; } uint32_t calc_wanted_chunks() const; void verify_wanted_chunks(const char* where) const; slot_void& slot_initial_hash() const { return m_slot_initial_hash; } slot_void& slot_download_done() const { return m_slot_download_done; } slot_void& slot_partially_done() const { return m_slot_partially_done; } slot_void& slot_partially_restarted() const { return m_slot_partially_restarted; } slot_chunk_list_node_p& slot_chunk_done() const {return m_slot_chunk_done;} protected: friend class ChunkList; friend class ChunkSelector; friend class Download; friend class DownloadWrapper; friend class FileList; HashString& mutable_hash() { return m_hash; } Bitfield* mutable_completed_bitfield() { return &m_completed_bitfield; } Bitfield* mutable_untouched_bitfield() { return &m_untouched_bitfield; } priority_ranges* mutable_high_priority() { return &m_high_priority; } priority_ranges* mutable_normal_priority() { return &m_normal_priority; } void update_wanted_chunks() { m_wanted_chunks = calc_wanted_chunks(); } void set_wanted_chunks(uint32_t n) { m_wanted_chunks = n; } void call_download_done() { if (m_slot_download_done) m_slot_download_done(); } void call_partially_done() { if (m_slot_partially_done) m_slot_partially_done(); } void call_partially_restarted() { if (m_slot_partially_restarted) m_slot_partially_restarted(); } void call_chunk_done(ChunkListNode* chunk_ptr) {if(m_slot_chunk_done) m_slot_chunk_done(chunk_ptr);} private: HashString m_hash; Bitfield m_completed_bitfield; Bitfield m_untouched_bitfield; priority_ranges m_high_priority; priority_ranges m_normal_priority; uint32_t m_wanted_chunks{0}; mutable slot_void m_slot_initial_hash; mutable slot_void m_slot_download_done; mutable slot_void m_slot_partially_done; mutable slot_void m_slot_partially_restarted; mutable slot_chunk_list_node_p m_slot_chunk_done; }; } // namespace torrent #endif // LIBTORRENT_DATA_DOWNLOAD_DATA_H libtorrent-0.16.11/src/torrent/data/transfer_list.h0000644000000000000000000000477215175073411015736 #ifndef LIBTORRENT_TRANSFER_LIST_H #define LIBTORRENT_TRANSFER_LIST_H #include #include #include namespace torrent { class LIBTORRENT_EXPORT TransferList : public std::vector { public: using base_type = std::vector; using completed_list_type = std::vector>; using base_type::value_type; using base_type::reference; using base_type::difference_type; using base_type::iterator; using base_type::const_iterator; using base_type::reverse_iterator; using base_type::const_reverse_iterator; using base_type::size; using base_type::empty; using base_type::begin; using base_type::end; using base_type::rbegin; using base_type::rend; TransferList() = default; ~TransferList(); TransferList(const TransferList&) = delete; TransferList& operator=(const TransferList&) = delete; iterator find(uint32_t index); const_iterator find(uint32_t index) const; const completed_list_type& completed_list() const { return m_completedList; } uint32_t succeeded_count() const { return m_succeededCount; } uint32_t failed_count() const { return m_failedCount; } // // Internal to libTorrent: // void clear(); iterator insert(const Piece& piece, uint32_t blockSize); iterator erase(iterator itr); void finished(BlockTransfer* transfer); void hash_succeeded(uint32_t index, Chunk* chunk); void hash_failed(uint32_t index, Chunk* chunk); using slot_chunk_index = std::function; using slot_peer_info = std::function; slot_chunk_index& slot_canceled() { return m_slot_canceled; } slot_chunk_index& slot_completed() { return m_slot_completed; } slot_chunk_index& slot_queued() { return m_slot_queued; } slot_peer_info& slot_corrupt() { return m_slot_corrupt; } private: static unsigned int update_failed(BlockList* blockList, Chunk* chunk); void mark_failed_peers(BlockList* blockList, Chunk* chunk); void retry_most_popular(BlockList* blockList, Chunk* chunk); slot_chunk_index m_slot_canceled; slot_chunk_index m_slot_completed; slot_chunk_index m_slot_queued; slot_peer_info m_slot_corrupt; completed_list_type m_completedList; uint32_t m_succeededCount{0}; uint32_t m_failedCount{0}; }; } // namespace torrent #endif libtorrent-0.16.11/src/torrent/data/file_utils.cc0000644000000000000000000000674015175073411015351 // libTorrent - BitTorrent library // Copyright (C) 2005-2011, Jari Sundell // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // In addition, as a special exception, the copyright holders give // permission to link the code of portions of this program with the // OpenSSL library under certain conditions as described in each // individual source file, and distribute linked combinations // including the two. // // You must obey the GNU General Public License in all respects for // all of the code used other than OpenSSL. If you modify file(s) // with this exception, you may extend this exception to your version // of the file(s), but you are not obligated to do so. If you do not // wish to do so, delete this exception statement from your version. // If you delete this exception statement from all source files in the // program, then also delete it here. // // Contact: Jari Sundell // // Skomakerveien 33 // 3185 Skoppum, NORWAY #include "config.h" #include "exceptions.h" #include "file.h" #include "file_utils.h" namespace torrent { FileList::iterator file_split(FileList* fileList, FileList::iterator position, uint64_t maxSize, const std::string& suffix) { const Path* srcPath = (*position)->path(); uint64_t splitSize = ((*position)->size_bytes() + maxSize - 1) / maxSize; if (srcPath->empty() || (*position)->size_bytes() == 0) throw input_error("Tried to split a file with an empty path or zero length file."); if (splitSize > 1000) throw input_error("Tried to split a file into more than 1000 parts."); // Also replace dwnlctor's vector. auto splitList = new FileList::split_type[splitSize]; auto splitItr = splitList; const unsigned int nameSize = srcPath->back().size() + suffix.size(); std::string name; name.reserve(nameSize + 4); name += srcPath->back(); name += suffix; for (unsigned int i = 0; i != splitSize; ++i, ++splitItr) { if (i == splitSize - 1 && (*position)->size_bytes() % maxSize != 0) std::get<0>(*splitItr) = (*position)->size_bytes() % maxSize; else std::get<0>(*splitItr) = maxSize; name[nameSize + 0] = '0' + (i / 100) % 10; name[nameSize + 1] = '0' + (i / 10) % 10; name[nameSize + 2] = '0' + (i / 1) % 10; name[nameSize + 3] = '\0'; std::get<1>(*splitItr) = *srcPath; std::get<1>(*splitItr).back() = name; } return fileList->split(position, splitList, splitItr).second; } void file_split_all(FileList* fileList, uint64_t maxSize, const std::string& suffix) { if (maxSize == 0) throw input_error("Tried to split torrent files into zero sized chunks."); auto itr = fileList->begin(); while (itr != fileList->end()) if ((*itr)->size_bytes() > maxSize && !(*itr)->path()->empty()) itr = file_split(fileList, itr, maxSize, suffix); else itr++; } } // namespace torrent libtorrent-0.16.11/src/torrent/data/block.cc0000644000000000000000000002703115175073411014300 #include "config.h" #include #include #include "peer/peer_info.h" #include "protocol/peer_connection_base.h" #include "block.h" #include "block_failed.h" #include "block_list.h" #include "block_transfer.h" #include "exceptions.h" namespace torrent { Block::~Block() { assert((m_state == STATE_INCOMPLETE || m_state == STATE_COMPLETED) && "Block dtor with 'm_state != STATE_INCOMPLETE && m_state != STATE_COMPLETED'"); if (m_state == STATE_COMPLETED) { assert(m_leader != NULL && "Block dtor with 'm_state == STATE_COMPLETED && m_leader == NULL'"); m_leader->set_peer_info(NULL); } m_leader = NULL; m_state = STATE_INVALID; for (auto& block : m_queued) { invalidate_transfer(block); } m_queued.clear(); for (auto& block : m_transfers) { invalidate_transfer(block); } m_transfers.clear(); assert(m_notStalled == 0 && "Block::clear() m_stalled != 0."); delete m_failedList; } bool Block::is_finished() const { return m_leader != nullptr && m_leader->is_finished(); } bool Block::is_transfering() const { return m_leader != nullptr && !m_leader->is_finished(); } BlockTransfer* Block::insert(PeerInfo* peerInfo) { if (find_queued(peerInfo) || find_transfer(peerInfo)) return NULL; m_notStalled++; auto block = new BlockTransfer; block->set_peer_info(peerInfo); block->set_block(this); block->set_piece(m_piece); block->set_state(BlockTransfer::STATE_QUEUED); block->set_request_time(this_thread::cached_seconds().count()); block->set_position(0); block->set_stall(0); block->set_failed_index(BlockFailed::invalid_index); return m_queued.emplace_back(block); } void Block::erase(BlockTransfer* transfer) { if (transfer->is_erased()) throw internal_error("Block::erase(...) transfer already erased"); if (transfer->peer_info() != NULL) throw internal_error("Block::erase(...) transfer has non-null peer info"); m_notStalled -= transfer->stall() == 0; if (transfer->is_queued()) { auto itr = std::find(m_queued.begin(), m_queued.end(), transfer); if (itr == m_queued.end()) throw internal_error("Block::erase(...) Could not find transfer."); m_queued.erase(itr); } else if (!transfer->is_finished()) { auto itr = std::find(m_transfers.begin(), m_transfers.end(), transfer); if (itr == m_transfers.end()) throw internal_error("Block::erase(...) Could not find transfer."); // Need to do something different here for now, i think. m_transfers.erase(itr); if (transfer == m_leader) { if (m_state == STATE_COMPLETED) throw internal_error("Block::erase with 'transfer == m_transfer && m_state == STATE_COMPLETED'"); // When the leader is erased then any non-leading transfer must // be promoted. These non-leading transfers are guaranteed to // have the same data up to their position. PeerConnectionBase // assumes that a Block with non-leaders have a leader. // Create a range containing transfers with // is_not_leader(). Erased transfer will end up in the back. auto first = std::find_if_not(m_transfers.begin(), m_transfers.end(), std::mem_fn(&BlockTransfer::is_leader)); auto last = std::stable_partition(first, m_transfers.end(), std::mem_fn(&BlockTransfer::is_not_leader)); auto new_leader = std::max_element(first, last, [](BlockTransfer* t1, BlockTransfer* t2) { return t1->position() < t2->position(); }); if (new_leader != last) { m_leader = *new_leader; m_leader->set_state(BlockTransfer::STATE_LEADER); } else { m_leader = NULL; // If we have no new leader, remove the erased (dissimilar) // transfers so they can get another shot. They cannot be // removed when found dissimilar as that would result in them // being queued immediately. remove_erased_transfers(); } } } else { throw internal_error("Block::erase(...) Transfer is finished."); } // Check if we need to check for peer_info not being null. transfer->set_block(NULL); delete transfer; } bool Block::transfering(BlockTransfer* transfer) { if (!transfer->is_valid()) throw internal_error("Block::transfering(...) transfer->block() == NULL."); auto itr = std::find(m_queued.begin(), m_queued.end(), transfer); if (itr == m_queued.end()) throw internal_error("Block::transfering(...) not queued."); m_queued.erase(itr); m_transfers.push_back(transfer); // If this block already has an active transfer, make this transfer // skip the piece. If this transfer gets ahead of the currently // transfering, it will (a) take over as the leader if the data is // the same or (b) erase itself from this block if the data does not // match. if (m_leader != NULL) { transfer->set_state(BlockTransfer::STATE_NOT_LEADER); return false; } else { m_leader = transfer; transfer->set_state(BlockTransfer::STATE_LEADER); return true; } } // TODO: Don't depend on m_leader for access to block transfer data of // done peer_info, etc. bool Block::completed(BlockTransfer* transfer) { if (!transfer->is_valid()) throw internal_error("Block::completed(...) transfer->block() == NULL."); if (!transfer->is_leader()) throw internal_error("Block::completed(...) transfer is not the leader."); // Special case where another ignored transfer finished before the // leader? // // Perhaps do magic to the transfer, erase it or something. if (!is_finished()) throw internal_error("Block::completed(...) !is_finished()."); if (transfer != m_leader) throw internal_error("Block::completed(...) transfer != m_leader."); m_parent->inc_finished(); if (static_cast(std::count_if(m_parent->begin(), m_parent->end(), std::mem_fn(&Block::is_finished))) < m_parent->finished()) throw internal_error("Block::completed(...) Finished blocks too large."); m_notStalled -= transfer->stall() == 0; transfer->set_block(NULL); transfer->set_stall(~uint32_t()); // Currently just throw out the queued transfers. In case the hash // check fails, we might consider telling pcb during the call to // Block::transfering(...). But that would propably not be correct // as we want to trigger cancel messages from here, as hash fail is // a rare occurrence. for (const auto& block : m_queued) { invalidate_transfer(block); } m_queued.clear(); // We need to invalidate those unfinished and keep the one that // finished for later reference. remove_non_leader_transfers(); // We now know that all transfers except the current leader we're // handling has been invalidated. if (m_transfers.empty() || m_transfers.back() != transfer) throw internal_error("Block::completed(...) m_transfers.empty() || m_transfers.back() != transfer."); m_state = STATE_COMPLETED; return m_parent->is_all_finished(); } void Block::retry_transfer() { m_state = STATE_INCOMPLETE; } // Mark a non-leading transfer as having received dissimilar data to // the leader. It is then marked as erased so that we know its data // was not used, yet keep it in m_transfers so as not to cause a // re-download. void Block::transfer_dissimilar(BlockTransfer* transfer) { if (!transfer->is_not_leader() || m_leader == transfer) throw internal_error("Block::transfer_dissimilar(...) transfer is the leader."); m_notStalled -= transfer->stall() == 0; // Why not just delete? Gets done by completed(), though when // erasing the leader we need to remove dissimilar unless we have // another leader. transfer->set_state(BlockTransfer::STATE_ERASED); transfer->set_position(0); transfer->set_block(NULL); } void Block::stalled(BlockTransfer* transfer) { if (!transfer->is_valid()) return; transfer->block()->stalled_transfer(transfer); } void Block::stalled_transfer(BlockTransfer* transfer) { if (transfer->stall() == 0) { if (m_notStalled == 0) throw internal_error("Block::stalled(...) m_notStalled == 0."); m_notStalled--; // Do magic here. } transfer->set_stall(transfer->stall() + 1); } void Block::change_leader(BlockTransfer* transfer) { if (m_leader == transfer) throw internal_error("Block::change_leader(...) m_leader == transfer."); if (is_finished()) throw internal_error("Block::change_leader(...) is_finished()."); if (m_leader != NULL) m_leader->set_state(BlockTransfer::STATE_NOT_LEADER); m_leader = transfer; m_leader->set_state(BlockTransfer::STATE_LEADER); } void Block::failed_leader() { if (!is_finished()) throw internal_error("Block::failed_leader(...) !is_finished()."); m_leader = NULL; if (m_failedList != NULL) m_failedList->set_current(BlockFailed::invalid_index); } void Block::create_dummy(BlockTransfer* transfer, PeerInfo* peerInfo, const Piece& piece) { transfer->set_peer_info(peerInfo); transfer->set_block(NULL); transfer->set_piece(piece); transfer->set_state(BlockTransfer::STATE_ERASED); transfer->set_position(0); transfer->set_stall(0); transfer->set_failed_index(BlockTransfer::invalid_index); } void Block::release(BlockTransfer* transfer) { transfer->set_peer_info(NULL); if (!transfer->is_valid()) delete transfer; else // TODO: Do we need to verify that the block is 'this'? transfer->block()->erase(transfer); } // // Private: // void Block::invalidate_transfer(BlockTransfer* transfer) { if (transfer == m_leader) throw internal_error("Block::invalidate_transfer(...) transfer == m_leader."); // Check if the block is this. transfer->set_block(NULL); if (transfer->stall() == 0) { if (m_notStalled == 0) throw internal_error("Block::invalidate_transfer(...) m_notStalled == 0."); m_notStalled--; } if (transfer->peer_info() == NULL) { delete transfer; return; // Consider if this should be an exception. } // Do the canceling magic here. if (transfer->peer_info()->connection() != NULL) transfer->peer_info()->connection()->cancel_transfer(transfer); } void Block::remove_erased_transfers() { auto split = std::stable_partition(m_transfers.begin(), m_transfers.end(), std::not_fn(std::mem_fn(&BlockTransfer::is_erased))); std::for_each(split, m_transfers.end(), [this](auto block) { invalidate_transfer(block); }); m_transfers.erase(split, m_transfers.end()); } void Block::remove_non_leader_transfers() { auto split = std::stable_partition(m_transfers.begin(), m_transfers.end(), std::mem_fn(&BlockTransfer::is_leader)); std::for_each(split, m_transfers.end(), [this](auto block) { invalidate_transfer(block); }); m_transfers.erase(split, m_transfers.end()); } BlockTransfer* Block::find_queued(const PeerInfo* p) { auto itr = std::find_if(m_queued.begin(), m_queued.end(), [p](BlockTransfer* t) { return p == t->peer_info(); }); if (itr == m_queued.end()) return NULL; else return *itr; } const BlockTransfer* Block::find_queued(const PeerInfo* p) const { auto itr = std::find_if(m_queued.begin(), m_queued.end(), [p](BlockTransfer* t) { return p == t->peer_info(); }); if (itr == m_queued.end()) return NULL; else return *itr; } BlockTransfer* Block::find_transfer(const PeerInfo* p) { auto itr = std::find_if(m_transfers.begin(), m_transfers.end(), [p](BlockTransfer* t) { return p == t->peer_info(); }); if (itr == m_transfers.end()) return NULL; else return *itr; } const BlockTransfer* Block::find_transfer(const PeerInfo* p) const { auto itr = std::find_if(m_transfers.begin(), m_transfers.end(), [p](BlockTransfer* t) { return p == t->peer_info(); }); if (itr == m_transfers.end()) return NULL; else return *itr; } } // namespace torrent libtorrent-0.16.11/src/torrent/data/file_list_iterator.cc0000644000000000000000000001047615175073411017076 // libTorrent - BitTorrent library // Copyright (C) 2005-2011, Jari Sundell // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // In addition, as a special exception, the copyright holders give // permission to link the code of portions of this program with the // OpenSSL library under certain conditions as described in each // individual source file, and distribute linked combinations // including the two. // // You must obey the GNU General Public License in all respects for // all of the code used other than OpenSSL. If you modify file(s) // with this exception, you may extend this exception to your version // of the file(s), but you are not obligated to do so. If you do not // wish to do so, delete this exception statement from your version. // If you delete this exception statement from all source files in the // program, then also delete it here. // // Contact: Jari Sundell // // Skomakerveien 33 // 3185 Skoppum, NORWAY #include "config.h" #include "torrent/exceptions.h" #include "file.h" #include "file_list_iterator.h" namespace torrent { bool FileListIterator::is_file() const { return m_depth >= 0 && m_depth + 1 == static_cast((*m_position)->path()->size()); } bool FileListIterator::is_empty() const { return (*m_position)->path()->empty(); } bool FileListIterator::is_entering() const { return m_depth >= 0 && m_depth + 1 != static_cast((*m_position)->path()->size()); } FileListIterator& FileListIterator::operator ++() { int32_t size = (*m_position)->path()->size(); if (size == 0) { m_position++; return *this; } m_depth++; if (m_depth > size) throw internal_error("FileListIterator::operator ++() m_depth > size."); if (m_depth == size) m_depth = -(size - 1); if (m_depth == -static_cast((*m_position)->match_depth_next())) { m_depth = (*m_position)->match_depth_next(); m_position++; } return *this; } FileListIterator& FileListIterator::operator --() { // We're guaranteed that if m_depth != 0 then so is the path size, // so there's no need to check for it. if (m_depth == 0) { m_position--; // This ensures we properly start iterating the paths in a tree // without failing badly when size == 0. if ((*m_position)->path()->size() > 1) m_depth = -1; } else if (m_depth == static_cast((*m_position)->match_depth_prev())) { m_position--; // If only the last element differs, then we don't switch to // negative depth. Also make sure we skip the negative of the // current depth, as we index by the depth we're exiting from. if (m_depth + 1 != static_cast((*m_position)->path()->size())) m_depth = -(m_depth + 1); } else { auto size = static_cast((*m_position)->path()->size()); m_depth--; if (m_depth < -size) throw internal_error("FileListIterator::operator --() m_depth < -size."); if (m_depth == -size) m_depth = size - 1; } return *this; } FileListIterator& FileListIterator::forward_current_depth() { uint32_t baseDepth = depth(); if (!is_entering()) return ++(*this); // If the above test was false then we know there must be a // 'leaving' at baseDepth before the end of the list. do { ++(*this); } while (depth() > baseDepth); return *this; } FileListIterator& FileListIterator::backward_current_depth() { --(*this); if (is_entering() || is_file() || is_empty()) return *this; if (depth() == 0) throw internal_error("FileListIterator::backward_current_depth() depth() == 0."); uint32_t baseDepth = depth(); while (depth() >= baseDepth) --(*this); return *this; } } // namespace torrent libtorrent-0.16.11/src/torrent/data/file_list.h0000644000000000000000000001530315175073411015021 #ifndef LIBTORRENT_FILE_LIST_H #define LIBTORRENT_FILE_LIST_H #include #include #include #include #include #include #include namespace torrent { class Content; class Download; class DownloadConstructor; class DownloadMain; class DownloadWrapper; class Handshake; class LIBTORRENT_EXPORT FileList : private std::vector> { public: friend class Content; friend class Download; friend class DownloadConstructor; friend class DownloadMain; friend class DownloadWrapper; friend class Handshake; using base_type = std::vector>; using path_list = std::vector; using split_type = std::tuple; // The below are using-directives that make visible functions and // typedefs in the parent std::vector, only those listed below are // accessible. If you don't understand how this works, use google, // don't ask me. using base_type::value_type; using base_type::iterator; using base_type::const_iterator; using base_type::reverse_iterator; using base_type::const_reverse_iterator; using iterator_range = std::pair; using base_type::begin; using base_type::end; using base_type::rbegin; using base_type::rend; using base_type::front; using base_type::back; using base_type::empty; using base_type::reserve; using base_type::at; using base_type::operator[]; FileList(); ~FileList(); bool is_open() const { return m_is_open; } bool is_done() const { return completed_chunks() == size_chunks(); } bool is_valid_piece(const Piece& piece) const; bool is_root_dir_created() const; // Check if the torrent is loaded as a multi-file torrent. This may // return true even for a torrent with just one file. bool is_multi_file() const; void set_multi_file(bool state) { m_multi_file = state; } size_t size_files() const { return base_type::size(); } uint64_t size_bytes() const { return m_torrent_size; } uint32_t size_chunks() const { return bitfield()->size_bits(); } uint32_t completed_chunks() const { return bitfield()->size_set(); } uint64_t completed_bytes() const; uint64_t left_bytes() const; uint32_t chunk_size() const { return m_chunk_size; } uint32_t chunk_index_size(uint32_t index) const; uint64_t chunk_index_position(uint32_t index) const { return index * chunk_size(); } const download_data* data() const { return &m_data; } const Bitfield* bitfield() const { return m_data.completed_bitfield(); } // You may only call set_root_dir after all nodes have been added. const std::string& root_dir() const { return m_root_dir; } const std::string& frozen_root_dir() const { return m_frozen_root_dir; } void set_root_dir(const std::string& path); uint64_t max_file_size() const { return m_max_file_size; } void set_max_file_size(uint64_t size); // If the files span multiple disks, the one with the least amount // of free diskspace will be returned. uint64_t free_diskspace() const; // List of directories in the torrent that might be on different // volumes as they are links, including the root directory. Used by // 'free_diskspace()'. const path_list* indirect_links() const { return &m_indirect_links; } // The sum of the sizes in the range [first,last> must be equal to // the size of 'position'. Do not use the old pointer in 'position' // after this call. iterator_range split(iterator position, split_type* first, split_type* last); // Use an empty range to insert a zero length file. iterator merge(iterator first, iterator last, const Path& path); iterator merge(iterator_range range, const Path& path) { return merge(range.first, range.second, path); } void update_paths(iterator first, iterator last); bool make_root_path(); bool make_all_paths(); protected: static constexpr int open_no_create = (1 << 0); static constexpr int open_require_all_open = (1 << 1); void initialize(uint64_t torrentSize, uint32_t chunkSize) LIBTORRENT_NO_EXPORT; void open(bool hashing, int flags) LIBTORRENT_NO_EXPORT; void close() LIBTORRENT_NO_EXPORT; void close_all_files() LIBTORRENT_NO_EXPORT; download_data* mutable_data() { return &m_data; } // Before calling this function, make sure you clear errno. If // creating the chunk failed, NULL is returned and errno is set. Chunk* create_chunk_index(uint32_t index, int prot) LIBTORRENT_NO_EXPORT; Chunk* create_hashing_chunk_index(uint32_t index, int prot) LIBTORRENT_NO_EXPORT; void mark_completed(uint32_t index) LIBTORRENT_NO_EXPORT; iterator inc_completed(iterator firstItr, uint32_t index) LIBTORRENT_NO_EXPORT; void update_completed() LIBTORRENT_NO_EXPORT; // Used for meta downloads; we only know the // size after the first extension handshake. void reset_filesize(int64_t) LIBTORRENT_NO_EXPORT; private: bool open_file(File* node, const Path& lastPath, bool hashing, int flags) LIBTORRENT_NO_EXPORT; void make_directory(Path::const_iterator pathBegin, Path::const_iterator pathEnd, Path::const_iterator startItr) LIBTORRENT_NO_EXPORT; Chunk* create_chunk(uint64_t offset, uint32_t length, bool hashing, int prot) LIBTORRENT_NO_EXPORT; MemoryChunk create_chunk_part(FileList::iterator itr, uint64_t offset, uint32_t length, bool hashing, int prot) const LIBTORRENT_NO_EXPORT; download_data m_data; bool m_is_open{false}; uint64_t m_torrent_size{0}; uint32_t m_chunk_size{0}; uint64_t m_max_file_size{~uint64_t()}; std::string m_root_dir; path_list m_indirect_links; // Reorder next minor version bump: bool m_multi_file{false}; std::string m_frozen_root_dir; }; } // namespace torrent #endif libtorrent-0.16.11/src/torrent/data/block_failed.h0000644000000000000000000000741715175073411015454 // libTorrent - BitTorrent library // Copyright (C) 2005-2011, Jari Sundell // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // In addition, as a special exception, the copyright holders give // permission to link the code of portions of this program with the // OpenSSL library under certain conditions as described in each // individual source file, and distribute linked combinations // including the two. // // You must obey the GNU General Public License in all respects for // all of the code used other than OpenSSL. If you modify file(s) // with this exception, you may extend this exception to your version // of the file(s), but you are not obligated to do so. If you do not // wish to do so, delete this exception statement from your version. // If you delete this exception statement from all source files in the // program, then also delete it here. // // Contact: Jari Sundell // // Skomakerveien 33 // 3185 Skoppum, NORWAY #ifndef LIBTORRENT_BLOCK_FAILED_H #define LIBTORRENT_BLOCK_FAILED_H #include #include #include #include namespace torrent { class BlockFailed : public std::vector > { public: using base_type = std::vector>; using base_type::value_type; using base_type::reference; using base_type::size_type; using base_type::difference_type; using base_type::iterator; using base_type::reverse_iterator; using base_type::size; using base_type::empty; using base_type::begin; using base_type::end; using base_type::rbegin; using base_type::rend; using base_type::operator[]; static constexpr uint32_t invalid_index = ~uint32_t(); BlockFailed() = default; ~BlockFailed(); BlockFailed(const BlockFailed&) = delete; BlockFailed& operator=(const BlockFailed&) = delete; size_type current() const { return m_current; } iterator current_iterator() { return begin() + m_current; } reverse_iterator current_reverse_iterator() { return reverse_iterator(begin() + m_current + 1); } void set_current(size_type idx) { m_current = idx; } void set_current(iterator itr) { m_current = itr - begin(); } void set_current(reverse_iterator itr) { m_current = itr.base() - begin() - 1; } iterator max_element(); reverse_iterator reverse_max_element(); private: static void delete_entry(value_type e) { delete [] e.first; } static bool compare_entries(value_type e1, value_type e2) { return e1.second < e2.second; } size_type m_current{invalid_index}; }; inline BlockFailed::~BlockFailed() { std::for_each(begin(), end(), &BlockFailed::delete_entry); } inline BlockFailed::iterator BlockFailed::max_element() { return std::max_element(begin(), end(), &BlockFailed::compare_entries); } inline BlockFailed::reverse_iterator BlockFailed::reverse_max_element() { return std::max_element(rbegin(), rend(), &BlockFailed::compare_entries); } } // namespace torrent #endif libtorrent-0.16.11/src/torrent/data/block_list.h0000644000000000000000000000456115175073411015200 #ifndef LIBTORRENT_BLOCK_LIST_H #define LIBTORRENT_BLOCK_LIST_H #include #include #include #include namespace torrent { class LIBTORRENT_EXPORT BlockList : private std::vector { public: using size_type = uint32_t; using base_type = std::vector; using base_type::value_type; using base_type::reference; using base_type::difference_type; using base_type::iterator; using base_type::const_iterator; using base_type::size; using base_type::empty; using base_type::begin; using base_type::end; using base_type::operator[]; BlockList(const Piece& piece, uint32_t blockLength); ~BlockList(); BlockList(const BlockList&) = delete; BlockList& operator=(const BlockList&) = delete; bool is_all_finished() const { return m_finished == size(); } const Piece& piece() const { return m_piece; } uint32_t index() const { return m_piece.index(); } priority_enum priority() const { return m_priority; } void set_priority(priority_enum p) { m_priority = p; } size_type finished() const { return m_finished; } void inc_finished() { m_finished++; } void clear_finished() { m_finished = 0; } uint32_t failed() const { return m_failed; } // Temporary, just increment for now. void inc_failed() { m_failed++; } uint32_t attempt() const { return m_attempt; } void set_attempt(uint32_t a) { m_attempt = a; } // Set when the chunk was initially requested from a seeder. This // allows us to quickly determine if it is a suitable chunk to // request from another seeder, e.g by already knowing it is a rare // piece. bool by_seeder() const { return m_bySeeder; } void set_by_seeder(bool state) { m_bySeeder = state; } void do_all_failed(); private: Piece m_piece; priority_enum m_priority{PRIORITY_OFF}; size_type m_finished{0}; uint32_t m_failed{0}; uint32_t m_attempt{0}; bool m_bySeeder{false}; }; } // namespace torrent #endif libtorrent-0.16.11/src/torrent/data/file_utils.h0000644000000000000000000000421015175073411015201 // libTorrent - BitTorrent library // Copyright (C) 2005-2011, Jari Sundell // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // In addition, as a special exception, the copyright holders give // permission to link the code of portions of this program with the // OpenSSL library under certain conditions as described in each // individual source file, and distribute linked combinations // including the two. // // You must obey the GNU General Public License in all respects for // all of the code used other than OpenSSL. If you modify file(s) // with this exception, you may extend this exception to your version // of the file(s), but you are not obligated to do so. If you do not // wish to do so, delete this exception statement from your version. // If you delete this exception statement from all source files in the // program, then also delete it here. // // Contact: Jari Sundell // // Skomakerveien 33 // 3185 Skoppum, NORWAY #ifndef LIBTORRENT_FILE_UTILS_H #define LIBTORRENT_FILE_UTILS_H #include #include namespace torrent { // Split 'position' into 'maxSize' sized files and return the iterator // after the last new entry. FileList::iterator file_split(FileList* fileList, FileList::iterator position, uint64_t maxSize, const std::string& suffix) LIBTORRENT_EXPORT; void file_split_all(FileList* fileList, uint64_t maxSize, const std::string& suffix) LIBTORRENT_EXPORT; } // namespace torrent #endif libtorrent-0.16.11/src/torrent/data/block_list.cc0000644000000000000000000000567115175073411015341 // libTorrent - BitTorrent library // Copyright (C) 2005-2011, Jari Sundell // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // In addition, as a special exception, the copyright holders give // permission to link the code of portions of this program with the // OpenSSL library under certain conditions as described in each // individual source file, and distribute linked combinations // including the two. // // You must obey the GNU General Public License in all respects for // all of the code used other than OpenSSL. If you modify file(s) // with this exception, you may extend this exception to your version // of the file(s), but you are not obligated to do so. If you do not // wish to do so, delete this exception statement from your version. // If you delete this exception statement from all source files in the // program, then also delete it here. // // Contact: Jari Sundell // // Skomakerveien 33 // 3185 Skoppum, NORWAY #include "config.h" #include #include #include "block_list.h" #include "exceptions.h" namespace torrent { BlockList::BlockList(const Piece& piece, uint32_t blockLength) : m_piece(piece) { if (piece.length() == 0) throw internal_error("BlockList::BlockList(...) received zero length piece."); // Look into optimizing this by using input iterators in the ctor. base_type::resize((m_piece.length() + blockLength - 1) / blockLength); // ATM assume offset of 0. // uint32_t offset = m_piece.offset(); uint32_t offset = 0; for (auto itr = begin(), last = end() - 1; itr != last; ++itr, offset += blockLength) { itr->set_parent(this); itr->set_piece(Piece(m_piece.index(), offset, blockLength)); } base_type::back().set_parent(this); base_type::back().set_piece(Piece(m_piece.index(), offset, (m_piece.length() % blockLength) ? m_piece.length() % blockLength : blockLength)); } // The default dtor's handles cleaning up the blocks and block transfers. BlockList::~BlockList() = default; void BlockList::do_all_failed() { clear_finished(); set_attempt(0); // Clear leaders when we want to redownload the chunk. std::for_each(begin(), end(), std::mem_fn(&Block::failed_leader)); std::for_each(begin(), end(), std::mem_fn(&Block::retry_transfer)); } } // namespace torrent libtorrent-0.16.11/src/torrent/data/file.h0000644000000000000000000001332715175073411013772 #ifndef LIBTORRENT_FILE_H #define LIBTORRENT_FILE_H #include #include namespace torrent { class LIBTORRENT_EXPORT File { public: friend class FileList; using range_type = std::pair; static constexpr int flag_active = (1 << 0); static constexpr int flag_create_queued = (1 << 1); static constexpr int flag_resize_queued = (1 << 2); static constexpr int flag_fallocate = (1 << 3); static constexpr int flag_previously_created = (1 << 4); static constexpr int flag_prioritize_first = (1 << 5); static constexpr int flag_prioritize_last = (1 << 6); static constexpr int flag_attr_padding = (1 << 7); File() =default; ~File(); bool is_created() const; bool is_open() const { return m_fd != -1; } bool is_correct_size() const; bool is_valid_position(uint64_t p) const; bool is_create_queued() const { return m_flags & flag_create_queued; } bool is_resize_queued() const { return m_flags & flag_resize_queued; } bool is_previously_created() const { return m_flags & flag_previously_created; } bool is_padding() const { return m_flags & flag_attr_padding; } bool has_flags(int flags) const { return m_flags & flags; } void set_flags(int flags); void unset_flags(int flags); bool has_permissions(int prot) const { return !(prot & ~m_protection); } uint64_t offset() const { return m_offset; } uint64_t size_bytes() const { return m_size; } uint32_t size_chunks() const { return m_range.second - m_range.first; } uint32_t completed_chunks() const { return m_completed; } void set_completed_chunks(uint32_t v); const range_type& range() const { return m_range; } uint32_t range_first() const { return m_range.first; } uint32_t range_second() const { return m_range.second; } priority_enum priority() const { return m_priority; } void set_priority(priority_enum t) { m_priority = t; } const Path* path() const { return &m_path; } Path* mutable_path() { return &m_path; } const std::string& frozen_path() const { return m_frozen_path; } uint32_t match_depth_prev() const { return m_match_depth_prev; } uint32_t match_depth_next() const { return m_match_depth_next; } // This should only be changed by libtorrent. int file_descriptor() const { return m_fd; } void set_file_descriptor(int fd) { m_fd = fd; } // This might actually be wanted, as it would be nice to allow the // File to decide if it needs to try creating the underlying file or // not. bool prepare(bool hashing, int prot, int flags); int protection() const { return m_protection; } void set_protection(int prot) { m_protection = prot; } uint64_t last_touched() const { return m_last_touched; } void set_last_touched(uint64_t t) { m_last_touched = t; } protected: void set_flags_protected(int flags) { m_flags |= flags; } void unset_flags_protected(int flags) { m_flags &= ~flags; } void set_frozen_path(const std::string& path) { m_frozen_path = path; } void set_offset(uint64_t off) { m_offset = off; } void set_size_bytes(uint64_t size) { m_size = size; } void set_range(uint32_t chunkSize); void set_completed_protected(uint32_t v) { m_completed = v; } void inc_completed_protected() { m_completed++; } static void set_match_depth(File* left, File* right); void set_match_depth_prev(uint32_t l) { m_match_depth_prev = l; } void set_match_depth_next(uint32_t l) { m_match_depth_next = l; } private: File(const File&) = delete; File& operator=(const File&) = delete; bool resize_file() const; int m_fd{-1}; int m_protection{0}; int m_flags{0}; Path m_path; std::string m_frozen_path; uint64_t m_offset{0}; uint64_t m_size{0}; uint64_t m_last_touched{0}; range_type m_range; uint32_t m_completed{0}; priority_enum m_priority{PRIORITY_NORMAL}; uint32_t m_match_depth_prev{0}; uint32_t m_match_depth_next{0}; }; inline bool File::is_valid_position(uint64_t p) const { return p >= m_offset && p < m_offset + m_size; } inline void File::set_flags(int flags) { set_flags_protected(flags & (flag_create_queued | flag_resize_queued | flag_fallocate | flag_prioritize_first | flag_prioritize_last | flag_attr_padding)); } inline void File::unset_flags(int flags) { unset_flags_protected(flags & (flag_create_queued | flag_resize_queued | flag_fallocate | flag_prioritize_first | flag_prioritize_last| flag_attr_padding)); } } // namespace torrent #endif libtorrent-0.16.11/src/torrent/data/piece.h0000644000000000000000000000566515175073411014146 // libTorrent - BitTorrent library // Copyright (C) 2005-2011, Jari Sundell // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // In addition, as a special exception, the copyright holders give // permission to link the code of portions of this program with the // OpenSSL library under certain conditions as described in each // individual source file, and distribute linked combinations // including the two. // // You must obey the GNU General Public License in all respects for // all of the code used other than OpenSSL. If you modify file(s) // with this exception, you may extend this exception to your version // of the file(s), but you are not obligated to do so. If you do not // wish to do so, delete this exception statement from your version. // If you delete this exception statement from all source files in the // program, then also delete it here. // // Contact: Jari Sundell // // Skomakerveien 33 // 3185 Skoppum, NORWAY #ifndef LIBTORRENT_PIECE_H #define LIBTORRENT_PIECE_H #include namespace torrent { class LIBTORRENT_EXPORT Piece { public: static constexpr uint32_t invalid_index = ~uint32_t(); Piece() = default; ~Piece() = default; Piece(const Piece&) = default; Piece& operator=(const Piece&) = default; Piece(uint32_t index, uint32_t offset, uint32_t length) : m_index(index), m_offset(offset), m_length(length) {} bool is_valid() const { return m_index != invalid_index; } uint32_t index() const { return m_index; } void set_index(uint32_t v) { m_index = v; } uint32_t offset() const { return m_offset; } void set_offset(uint32_t v) { m_offset = v; } uint32_t length() const { return m_length; } void set_length(uint32_t v) { m_length = v; } bool operator == (const Piece& p) const { return m_index == p.m_index && m_offset == p.m_offset && m_length == p.m_length; } bool operator != (const Piece& p) const { return m_index != p.m_index || m_offset != p.m_offset || m_length != p.m_length; } private: uint32_t m_index{invalid_index}; uint32_t m_offset{}; uint32_t m_length{}; }; } // namespace torrent #endif libtorrent-0.16.11/src/torrent/download.h0000644000000000000000000001261415175073411013747 #ifndef LIBTORRENT_DOWNLOAD_H #define LIBTORRENT_DOWNLOAD_H #include #include #include #include #include #include namespace torrent { class ConnectionList; class DownloadInfo; class DownloadMain; class download_data; // Download is safe to copy and destory as it is just a pointer to an // internal class. class LIBTORRENT_EXPORT Download { public: static constexpr uint32_t numwanted_diabled = ~uint32_t(); // Start and open flags can be stored in the same integer, same for // stop and close flags. static constexpr int open_enable_fallocate = (1 << 0); static constexpr int start_no_create = (1 << 1); static constexpr int start_keep_baseline = (1 << 2); static constexpr int start_skip_tracker = (1 << 3); static constexpr int stop_skip_tracker = (1 << 0); Download(DownloadWrapper* d = NULL) : m_ptr(d) {} const DownloadInfo* info() const; const download_data* data() const; // Not active atm. Opens and prepares/closes the files. void open(int flags = 0); void close(int flags = 0); // When 'tryQuick' is true, it will only check if the chunks can be // mmaped and stops if one is encountered. If it doesn't find any // mappable chunks it will return true to indicate that it is // finished and a hash done signal has been queued. // // Chunk ranges that have valid resume data won't be checked. bool hash_check(bool tryQuick); void hash_stop(); // Start/stop the download. The torrent must be open. void start(int flags = 0); void stop(int flags = 0); // Does not check if the download has been removed. bool is_valid() const { return m_ptr; } bool is_hash_checked() const; bool is_hash_checking() const; void set_pex_enabled(bool enabled); Object* bencode(); const Object* bencode() const; tracker::TrackerControllerWrapper tracker_controller(); const tracker::TrackerControllerWrapper c_tracker_controller() const; FileList* file_list() const; PeerList* peer_list(); const PeerList* peer_list() const; const TransferList* transfer_list() const; ConnectionList* connection_list(); const ConnectionList* connection_list() const; // Bytes completed. uint64_t bytes_done() const; uint32_t chunks_hashed() const; const uint8_t* chunks_seen() const; // Set the number of finished chunks for closed torrents. void set_chunks_done(uint32_t chunks_done, uint32_t chunks_wanted); // Use the below to set the resume data and what chunk ranges need // to be hash checked. If they arn't called then by default it will // use an cleared bitfield and check the whole range. // // These must be called when is_open, !is_checked and !is_checking. void set_bitfield(bool allSet); void set_bitfield(const uint8_t* first, const uint8_t* last); static constexpr int update_range_recheck = (1 << 0); static constexpr int update_range_clear = (1 << 1); void update_range(int flags, uint32_t first, uint32_t last); // Temporary hack for syncing chunks to disk before hash resume is // saved. void sync_chunks(); uint32_t peers_complete() const; uint32_t peers_accounted() const; uint32_t peers_currently_unchoked() const; uint32_t peers_currently_interested() const; uint32_t size_pex() const; uint32_t max_size_pex() const; bool accepting_new_peers() const; uint32_t uploads_max() const; void set_uploads_max(uint32_t v); uint32_t uploads_min() const; void set_uploads_min(uint32_t v); uint32_t downloads_max() const; void set_downloads_max(uint32_t v); uint32_t downloads_min() const; void set_downloads_min(uint32_t v); void set_upload_throttle(Throttle* t); void set_download_throttle(Throttle* t); // Some temporary functions that are routed to // TrackerManager... Clean this up. void send_completed(); void manual_request(bool force); void manual_cancel(); enum ConnectionType { CONNECTION_LEECH, CONNECTION_SEED, CONNECTION_INITIAL_SEED, CONNECTION_METADATA, }; ConnectionType connection_type() const; void set_connection_type(ConnectionType t); enum HeuristicType { }; HeuristicType upload_choke_heuristic() const; void set_upload_choke_heuristic(HeuristicType t); HeuristicType download_choke_heuristic() const; void set_download_choke_heuristic(HeuristicType t); // Call this when you want the modifications of the download priorities // in the entries to take effect. It is slightly expensive as it rechecks // all the peer bitfields to see if we are still interested. void update_priorities(); void add_peer(const sockaddr* addr, int port); DownloadWrapper* ptr() { return m_ptr; } DownloadMain* main(); private: DownloadWrapper* m_ptr; }; } // namespace torrent #endif libtorrent-0.16.11/src/torrent/download_info.h0000644000000000000000000002030115175073411014752 #ifndef LIBTORRENT_DOWNLOAD_INFO_H #define LIBTORRENT_DOWNLOAD_INFO_H #include #include #include #include #include #include namespace torrent { class FileList; class DownloadMain; // This will become a Download 'handle' of kinds. // TODO: Split into DownloadInfo and DownloadState. // TODO: Rename 'hash' to 'info_hash'. class LIBTORRENT_EXPORT DownloadInfo { public: using slot_stat_type = std::function; using signal_void_type = std::list>; using signal_string_type = std::list>; enum State { NONE, COMPLETED, STARTED, STOPPED }; static constexpr int flag_open = (1 << 0); static constexpr int flag_active = (1 << 1); static constexpr int flag_accepting_new_peers = (1 << 3); static constexpr int flag_accepting_seeders = (1 << 4); // Only used during leeching. static constexpr int flag_private = (1 << 5); static constexpr int flag_meta_download = (1 << 6); static constexpr int flag_pex_enabled = (1 << 7); static constexpr int flag_pex_active = (1 << 8); static constexpr int public_flags = flag_accepting_seeders; static constexpr uint32_t unlimited = ~uint32_t(); const std::string& name() const { return m_name; } void set_name(const std::string& s) { m_name = s; } const HashString& hash() const { return m_hash; } const HashString& info_hash() const { return m_hash; } HashString& mutable_hash() { return m_hash; } const HashString& hash_obfuscated() const { return m_hash_obfuscated; } const HashString& info_hash_obfuscated() const { return m_hash_obfuscated; } HashString& mutable_hash_obfuscated() { return m_hash_obfuscated; } const HashString& local_id() const { return m_local_id; } HashString& mutable_local_id() { return m_local_id; } bool is_open() const { return m_flags & flag_open; } bool is_active() const { return m_flags & flag_active; } bool is_accepting_new_peers() const { return m_flags & flag_accepting_new_peers; } bool is_accepting_seeders() const { return m_flags & flag_accepting_seeders; } bool is_private() const { return m_flags & flag_private; } bool is_meta_download() const { return m_flags & flag_meta_download; } bool is_pex_enabled() const { return m_flags & flag_pex_enabled; } bool is_pex_active() const { return m_flags & flag_pex_active; } int flags() const { return m_flags; } void set_flags(int flags) { m_flags |= flags; } void unset_flags(int flags) { m_flags &= ~flags; } void change_flags(int flags, bool state) { if (state) set_flags(flags); else unset_flags(flags); } void public_set_flags(int flags) const { m_flags |= (flags & public_flags); } void public_unset_flags(int flags) const { m_flags &= ~(flags & public_flags); } void public_change_flags(int flags, bool state) const { if (state) public_set_flags(flags); else public_unset_flags(flags); } void set_private() { set_flags(flag_private); unset_flags(flag_pex_enabled); } void set_pex_enabled() { if (!is_private()) set_flags(flag_pex_enabled); } const Rate* up_rate() const { return &m_up_rate; } const Rate* down_rate() const { return &m_down_rate; } const Rate* skip_rate() const { return &m_skip_rate; } Rate* mutable_up_rate() const { return &m_up_rate; } Rate* mutable_down_rate() const { return &m_down_rate; } Rate* mutable_skip_rate() const { return &m_skip_rate; } uint64_t uploaded_baseline() const { return m_uploaded_baseline; } uint64_t uploaded_adjusted() const { return std::max(m_up_rate.total() - uploaded_baseline(), 0); } void set_uploaded_baseline(uint64_t b) { m_uploaded_baseline = b; } uint64_t completed_baseline() const { return m_completed_baseline; } uint64_t completed_adjusted() const { return std::max(m_slot_stat_completed() - completed_baseline(), 0); } void set_completed_baseline(uint64_t b) { m_completed_baseline = b; } size_t metadata_size() const { return m_metadata_size; } void set_metadata_size(size_t size) { m_metadata_size = size; } uint32_t size_pex() const { return m_size_pex; } void set_size_pex(uint32_t b) { m_size_pex = b; } uint32_t max_size_pex() const { return m_max_size_pex; } void set_max_size_pex(uint32_t b) { m_max_size_pex = b; } static uint32_t max_size_pex_list() { return 200; } // Unix epoche, 0 == unknown. uint32_t creation_date() const { return m_creation_date; } uint32_t load_date() const { return m_load_date; } uint32_t upload_unchoked() const { return m_upload_unchoked; } uint32_t download_unchoked() const { return m_download_unchoked; } // The list of addresses is guaranteed to be sorted and unique. signal_void_type& signal_tracker_success() const { return m_signal_tracker_success; } signal_string_type& signal_tracker_failed() const { return m_signal_tracker_failed; } // // Libtorrent internal: // void set_creation_date(uint32_t d) { m_creation_date = d; } void set_upload_unchoked(uint32_t num) { m_upload_unchoked = num; } void set_download_unchoked(uint32_t num) { m_download_unchoked = num; } slot_stat_type& slot_left() { return m_slot_stat_left; } slot_stat_type& slot_completed() { return m_slot_stat_completed; } protected: friend class DownloadMain; void set_load_date(uint32_t d) { m_load_date = d; } private: std::string m_name; HashString m_hash{HashString::new_zero()}; HashString m_hash_obfuscated{HashString::new_zero()}; HashString m_local_id{HashString::new_zero()}; mutable int m_flags{flag_accepting_new_peers | flag_accepting_seeders | flag_pex_enabled | flag_pex_active}; mutable Rate m_up_rate{60}; mutable Rate m_down_rate{60}; mutable Rate m_skip_rate{60}; uint64_t m_uploaded_baseline{}; uint64_t m_completed_baseline{}; uint32_t m_size_pex{}; uint32_t m_max_size_pex{8}; size_t m_metadata_size{}; uint32_t m_creation_date{}; uint32_t m_load_date{}; uint32_t m_upload_unchoked{}; uint32_t m_download_unchoked{}; slot_stat_type m_slot_stat_left; slot_stat_type m_slot_stat_completed; mutable signal_void_type m_signal_tracker_success; mutable signal_string_type m_signal_tracker_failed; }; } // namespace torrent #endif libtorrent-0.16.11/src/torrent/object.h0000644000000000000000000005720715175073411013415 #ifndef LIBTORRENT_OBJECT_H #define LIBTORRENT_OBJECT_H #include #include #include #include #include #include #include namespace torrent { class LIBTORRENT_EXPORT Object { public: using value_type = int64_t; using string_type = std::string; using list_type = std::vector; using map_type = std::map; using map_ptr_type = map_type*; using key_type = map_type::key_type; using dict_key_type = std::pair; using list_iterator = list_type::iterator; using list_const_iterator = list_type::const_iterator; using list_reverse_iterator = list_type::reverse_iterator; using list_const_reverse_iterator = list_type::const_reverse_iterator; using map_iterator = map_type::iterator; using map_const_iterator = map_type::const_iterator; using map_reverse_iterator = map_type::reverse_iterator; using map_const_reverse_iterator = map_type::const_reverse_iterator; using map_insert_type = std::pair; // Flags in the range of 0xffff0000 may be set by the user, however // 0x00ff0000 are reserved for keywords defined by libtorrent. static constexpr uint32_t mask_type = 0xff; static constexpr uint32_t mask_flags = ~mask_type; static constexpr uint32_t mask_internal = 0xffff; static constexpr uint32_t mask_public = ~mask_internal; static constexpr uint32_t flag_unordered = 0x100; // bencode dictionary was not sorted static constexpr uint32_t flag_static_data = 0x010000; // Object does not change across sessions. static constexpr uint32_t flag_session_data = 0x020000; // Object changes between sessions. static constexpr uint32_t flag_function = 0x040000; // A function object. static constexpr uint32_t flag_function_q1 = 0x080000; // A quoted function object. static constexpr uint32_t flag_function_q2 = 0x100000; // A double-quoted function object. static constexpr uint32_t mask_function = 0x1C0000; // Mask for function objects. enum type_type { TYPE_NONE, TYPE_RAW_BENCODE, TYPE_RAW_STRING, TYPE_RAW_LIST, TYPE_RAW_MAP, TYPE_VALUE, TYPE_STRING, TYPE_LIST, TYPE_MAP, TYPE_DICT_KEY }; Object(const value_type v) : m_flags(TYPE_VALUE) { new (&_value()) value_type(v); } Object(const char* s) : m_flags(TYPE_STRING) { new (&_string()) string_type(s); } Object(const string_type& s) : m_flags(TYPE_STRING) { new (&_string()) string_type(s); } Object(const raw_bencode& r) : m_flags(TYPE_RAW_BENCODE) { new (&_raw_bencode()) raw_bencode(r); } Object(const raw_string& r) : m_flags(TYPE_RAW_STRING) { new (&_raw_string()) raw_string(r); } Object(const raw_list& r) : m_flags(TYPE_RAW_LIST) { new (&_raw_list()) raw_list(r); } Object(const raw_map& r) : m_flags(TYPE_RAW_MAP) { new (&_raw_map()) raw_map(r); } Object() {} ~Object() { clear(); } Object(const Object& b); Object& operator=(const Object& b); // TODO: Move this out of the class namespace, call them // make_object_. static Object create_empty(type_type t); static Object create_value() { return Object(value_type()); } static Object create_string() { return Object(string_type()); } static Object create_list() { Object tmp; tmp.m_flags = TYPE_LIST; new (&tmp._list()) list_type(); return tmp; } static Object create_map() { Object tmp; tmp.m_flags = TYPE_MAP; tmp._map_ptr() = new map_type(); return tmp; } static Object create_dict_key(); static Object create_raw_bencode(raw_bencode obj = raw_bencode()); static Object create_raw_string(raw_string obj = raw_string()); static Object create_raw_list(raw_list obj = raw_list()); static Object create_raw_map(raw_map obj = raw_map()); template static Object create_list_range(ForwardIterator first, ForwardIterator last); static const char* type_to_c_str(type_type t); static Object from_list(const list_type& src); // Clear should probably not be inlined due to size and not being // optimized away in pretty much any case. Might not work well in // cases where we pass constant rvalues. void clear(); type_type type() const { return static_cast(m_flags & mask_type); } uint32_t flags() const { return m_flags & mask_flags; } void set_flags(uint32_t f) { m_flags |= f & mask_public; } void unset_flags(uint32_t f) { m_flags &= ~(f & mask_public); } void set_internal_flags(uint32_t f) { m_flags |= f & (mask_internal & ~mask_type); } void unset_internal_flags(uint32_t f) { m_flags &= ~(f & (mask_internal & ~mask_type)); } // Add functions for setting/clearing the public flags. bool is_empty() const { return type() == TYPE_NONE; } bool is_not_empty() const { return type() != TYPE_NONE; } bool is_value() const { return type() == TYPE_VALUE; } bool is_string() const { return type() == TYPE_STRING; } bool is_string_empty() const { return type() != TYPE_STRING || _string().empty(); } bool is_list() const { return type() == TYPE_LIST; } bool is_map() const { return type() == TYPE_MAP; } bool is_dict_key() const { return type() == TYPE_DICT_KEY; } bool is_raw_bencode() const { return type() == TYPE_RAW_BENCODE; } bool is_raw_string() const { return type() == TYPE_RAW_STRING; } bool is_raw_list() const { return type() == TYPE_RAW_LIST; } bool is_raw_map() const { return type() == TYPE_RAW_MAP; } value_type& as_value() { check_throw(TYPE_VALUE); return _value(); } const value_type& as_value() const { check_throw(TYPE_VALUE); return _value(); } string_type& as_string() { check_throw(TYPE_STRING); return _string(); } const string_type& as_string() const { check_throw(TYPE_STRING); return _string(); } const string_type& as_string_c() const { check_throw(TYPE_STRING); return _string(); } const char* as_c_str() const { check_throw(TYPE_STRING); return _string().c_str(); } list_type& as_list() { check_throw(TYPE_LIST); return _list(); } const list_type& as_list() const { check_throw(TYPE_LIST); return _list(); } map_type& as_map() { check_throw(TYPE_MAP); return _map(); } const map_type& as_map() const { check_throw(TYPE_MAP); return _map(); } string_type& as_dict_key() { check_throw(TYPE_DICT_KEY); return _dict_key().first; } const string_type& as_dict_key() const { check_throw(TYPE_DICT_KEY); return _dict_key().first; } Object& as_dict_obj() { check_throw(TYPE_DICT_KEY); return *_dict_key().second; } const Object& as_dict_obj() const { check_throw(TYPE_DICT_KEY); return *_dict_key().second; } raw_bencode& as_raw_bencode() { check_throw(TYPE_RAW_BENCODE); return _raw_bencode(); } const raw_bencode& as_raw_bencode() const { check_throw(TYPE_RAW_BENCODE); return _raw_bencode(); } raw_string& as_raw_string() { check_throw(TYPE_RAW_STRING); return _raw_string(); } const raw_string& as_raw_string() const { check_throw(TYPE_RAW_STRING); return _raw_string(); } raw_list& as_raw_list() { check_throw(TYPE_RAW_LIST); return _raw_list(); } const raw_list& as_raw_list() const { check_throw(TYPE_RAW_LIST); return _raw_list(); } raw_map& as_raw_map() { check_throw(TYPE_RAW_MAP); return _raw_map(); } const raw_map& as_raw_map() const { check_throw(TYPE_RAW_MAP); return _raw_map(); } template T as_value_type(const char* err_msg) const { check_value_throw(err_msg); return _value(); } bool has_key(const key_type& k) const { check_throw(TYPE_MAP); return _map().find(k) != _map().end(); } bool has_key_value(const key_type& k) const { check_throw(TYPE_MAP); return check(_map().find(k), TYPE_VALUE); } bool has_key_string(const key_type& k) const { check_throw(TYPE_MAP); return check(_map().find(k), TYPE_STRING); } bool has_key_list(const key_type& k) const { check_throw(TYPE_MAP); return check(_map().find(k), TYPE_LIST); } bool has_key_map(const key_type& k) const { check_throw(TYPE_MAP); return check(_map().find(k), TYPE_MAP); } bool has_key_raw_bencode(const key_type& k) const { check_throw(TYPE_MAP); return check(_map().find(k), TYPE_RAW_BENCODE); } bool has_key_raw_string(const key_type& k) const { check_throw(TYPE_MAP); return check(_map().find(k), TYPE_RAW_STRING); } bool has_key_raw_list(const key_type& k) const { check_throw(TYPE_MAP); return check(_map().find(k), TYPE_RAW_LIST); } bool has_key_raw_map(const key_type& k) const { check_throw(TYPE_MAP); return check(_map().find(k), TYPE_RAW_MAP); } // Should have an interface for that returns pointer or something, // so we don't need to search twice. // Make these inline... Object& get_key(const key_type& k); const Object& get_key(const key_type& k) const; Object& get_key(const char* k); const Object& get_key(const char* k) const; template value_type& get_key_value(const T& k) { return get_key(k).as_value(); } template const value_type& get_key_value(const T& k) const { return get_key(k).as_value(); } template string_type& get_key_string(const T& k) { return get_key(k).as_string(); } template const string_type& get_key_string(const T& k) const { return get_key(k).as_string(); } template list_type& get_key_list(const T& k) { return get_key(k).as_list(); } template const list_type& get_key_list(const T& k) const { return get_key(k).as_list(); } template map_type& get_key_map(const T& k) { return get_key(k).as_map(); } template const map_type& get_key_map(const T& k) const { return get_key(k).as_map(); } Object& insert_key(const key_type& k, const Object& b) { check_throw(TYPE_MAP); return _map()[k] = b; } Object& insert_key_move(const key_type& k, Object& b) { check_throw(TYPE_MAP); return _map()[k].move(b); } // 'insert_preserve_*' inserts the object 'b' if the key 'k' does // not exist, else it returns the old entry. The type specific // versions also require the old entry to be of the same type. // // Consider making insert_preserve_* return std::pair or // something similar. map_insert_type insert_preserve_any(const key_type& k, const Object& b) { check_throw(TYPE_MAP); return _map().insert(map_type::value_type(k, b)); } map_insert_type insert_preserve_type(const key_type& k, Object& b); map_insert_type insert_preserve_copy(const key_type& k, Object b) { return insert_preserve_type(k, b); } void erase_key(const key_type& k) { check_throw(TYPE_MAP); _map().erase(k); } Object& insert_front(const Object& b) { check_throw(TYPE_LIST); return *_list().insert(_list().begin(), b); } Object& insert_back(const Object& b) { check_throw(TYPE_LIST); return *_list().insert(_list().end(), b); } // Copy and merge operations: Object& move(Object& b) noexcept; Object& swap(Object& b) noexcept; Object& swap_same_type(Object& b) noexcept; // Only map entries are merged. Object& merge_move(Object& object, uint32_t maxDepth = ~uint32_t()); Object& merge_copy(const Object& object, uint32_t skip_mask = flag_static_data, uint32_t maxDepth = ~uint32_t()); // Internal: static void swap_same_type(Object& left, Object& right) noexcept; private: bool check(map_type::const_iterator itr, type_type t) const; void check_throw(type_type t) const; template void check_value_throw(const char* err_msg) const; uint32_t m_flags{TYPE_NONE}; #ifndef HAVE_STDCXX_0X value_type& _value() { return t_value; } const value_type& _value() const { return t_value; } string_type& _string() { return t_string; } const string_type& _string() const { return t_string; } list_type& _list() { return t_list; } const list_type& _list() const { return t_list; } map_type& _map() { return *t_map; } const map_type& _map() const { return *t_map; } map_ptr_type& _map_ptr() { return t_map; } const map_ptr_type& _map_ptr() const { return t_map; } dict_key_type& _dict_key() { return t_dict_key; } const dict_key_type& _dict_key() const { return t_dict_key; } raw_object& _raw_object() { return t_raw_object; } const raw_object& _raw_object() const { return t_raw_object; } raw_bencode& _raw_bencode() { return t_raw_bencode; } const raw_bencode& _raw_bencode() const { return t_raw_bencode; } raw_string& _raw_string() { return t_raw_string; } const raw_string& _raw_string() const { return t_raw_string; } raw_list& _raw_list() { return t_raw_list; } const raw_list& _raw_list() const { return t_raw_list; } raw_map& _raw_map() { return t_raw_map; } const raw_map& _raw_map() const { return t_raw_map; } union pod_types { value_type t_value; raw_object t_raw_object; raw_bencode t_raw_bencode; raw_string t_raw_string; raw_list t_raw_list; raw_map t_raw_map; }; union { pod_types t_pod; value_type t_value; string_type t_string; list_type t_list; map_type* t_map; dict_key_type t_dict_key; raw_object t_raw_object; raw_bencode t_raw_bencode; raw_string t_raw_string; raw_list t_raw_list; raw_map t_raw_map; }; #else // #error "WTF we're testing C++11 now." value_type& _value() { return reinterpret_cast(t_pod); } const value_type& _value() const { return reinterpret_cast(t_pod); } string_type& _string() { return reinterpret_cast(t_string); } const string_type& _string() const { return reinterpret_cast(t_string); } list_type& _list() { return reinterpret_cast(t_list); } const list_type& _list() const { return reinterpret_cast(t_list); } map_type& _map() { return *reinterpret_cast(t_pod); } const map_type& _map() const { return *reinterpret_cast(t_pod); } map_ptr_type& _map_ptr() { return reinterpret_cast(t_pod); } const map_ptr_type& _map_ptr() const { return reinterpret_cast(t_pod); } dict_key_type& _dict_key() { return reinterpret_cast(t_pod); } const dict_key_type& _dict_key() const { return reinterpret_cast(t_pod); } raw_object& _raw_object() { return reinterpret_cast(t_pod); } const raw_object& _raw_object() const { return reinterpret_cast(t_pod); } raw_bencode& _raw_bencode() { return reinterpret_cast(t_pod); } const raw_bencode& _raw_bencode() const { return reinterpret_cast(t_pod); } raw_string& _raw_string() { return reinterpret_cast(t_pod); } const raw_string& _raw_string() const { return reinterpret_cast(t_pod); } raw_list& _raw_list() { return reinterpret_cast(t_pod); } const raw_list& _raw_list() const { return reinterpret_cast(t_pod); } raw_map& _raw_map() { return reinterpret_cast(t_pod); } const raw_map& _raw_map() const { return reinterpret_cast(t_pod); } union pod_types { value_type t_value; map_type* t_map; char t_raw_object[sizeof(raw_object)]; }; union { pod_types t_pod; char t_string[sizeof(string_type)]; char t_list[sizeof(list_type)]; char t_dict_key[sizeof(dict_key_type)]; }; #endif }; inline Object::Object(const Object& b) : m_flags(b.m_flags & (mask_type | mask_public)) { switch (type()) { case TYPE_NONE: case TYPE_RAW_BENCODE: case TYPE_RAW_STRING: case TYPE_RAW_LIST: case TYPE_RAW_MAP: case TYPE_VALUE: t_pod = b.t_pod; break; case TYPE_STRING: new (&_string()) string_type(b._string()); break; case TYPE_LIST: new (&_list()) list_type(b._list()); break; case TYPE_MAP: _map_ptr() = new map_type(b._map()); break; case TYPE_DICT_KEY: new (&_dict_key().first) string_type(b._dict_key().first); _dict_key().second = new Object(*b._dict_key().second); break; } } inline Object Object::create_empty(type_type t) { switch (t) { case TYPE_RAW_BENCODE: return create_raw_bencode(); case TYPE_RAW_STRING: return create_raw_string(); case TYPE_RAW_LIST: return create_raw_list(); case TYPE_RAW_MAP: return create_raw_map(); case TYPE_VALUE: return create_value(); case TYPE_STRING: return create_string(); case TYPE_LIST: return create_list(); case TYPE_MAP: return create_map(); case TYPE_DICT_KEY: return create_dict_key(); case TYPE_NONE: default: return torrent::Object(); } } inline Object object_create_raw_bencode_c_str(const char str[]) { return Object::create_raw_bencode(raw_bencode(str, strlen(str))); } // TODO: These do not preserve the flag... Object object_create_normal(const raw_bencode& obj) LIBTORRENT_EXPORT; Object object_create_normal(const raw_list& obj) LIBTORRENT_EXPORT; Object object_create_normal(const raw_map& obj) LIBTORRENT_EXPORT; inline Object object_create_normal(const raw_string& obj) { return torrent::Object(obj.as_string()); } inline Object Object::create_dict_key() { Object tmp; tmp.m_flags = TYPE_DICT_KEY; new (&tmp._dict_key()) dict_key_type(); tmp._dict_key().second = new Object(); return tmp; } inline Object Object::create_raw_bencode(raw_bencode obj) { Object tmp; tmp.m_flags = TYPE_RAW_BENCODE; new (&tmp._raw_bencode()) raw_bencode(obj); return tmp; } inline Object Object::create_raw_string(raw_string obj) { Object tmp; tmp.m_flags = TYPE_RAW_STRING; new (&tmp._raw_string()) raw_string(obj); return tmp; } inline Object Object::create_raw_list(raw_list obj) { Object tmp; tmp.m_flags = TYPE_RAW_LIST; new (&tmp._raw_list()) raw_list(obj); return tmp; } inline Object Object::create_raw_map(raw_map obj) { Object tmp; tmp.m_flags = TYPE_RAW_MAP; new (&tmp._raw_map()) raw_map(obj); return tmp; } inline Object object_create_normal(const Object& obj) { switch (obj.type()) { case Object::TYPE_RAW_BENCODE: return object_create_normal(obj.as_raw_bencode()); case Object::TYPE_RAW_STRING: return object_create_normal(obj.as_raw_string()); case Object::TYPE_RAW_LIST: return object_create_normal(obj.as_raw_list()); case Object::TYPE_RAW_MAP: return object_create_normal(obj.as_raw_map()); default: return obj; } } inline std::string object_create_string(const torrent::Object& obj) { switch (obj.type()) { case Object::TYPE_RAW_BENCODE: return obj.as_raw_bencode().as_raw_string().as_string(); case Object::TYPE_RAW_STRING: return obj.as_raw_string().as_string(); default: return obj.as_string(); } } template inline Object Object::create_list_range(ForwardIterator first, ForwardIterator last) { Object tmp; tmp.m_flags = TYPE_LIST; new (&tmp._list()) list_type(first, last); return tmp; } inline const char* Object::type_to_c_str(type_type t) { switch (t) { case TYPE_NONE: return "none"; case TYPE_RAW_BENCODE: return "raw_bencode"; case TYPE_RAW_STRING: return "raw_string"; case TYPE_RAW_LIST: return "raw_list"; case TYPE_RAW_MAP: return "raw_map"; case TYPE_VALUE: return "value"; case TYPE_STRING: return "string"; case TYPE_LIST: return "list"; case TYPE_MAP: return "map"; case TYPE_DICT_KEY: return "dict_key"; default: return "invalid"; } } inline Object Object::from_list(const list_type& src) { Object tmp; tmp.m_flags = TYPE_LIST; new (&tmp._list()) list_type(src); return tmp; } inline void Object::clear() { switch (type()) { case TYPE_STRING: _string().~string_type(); break; case TYPE_LIST: _list().~list_type(); break; case TYPE_MAP: delete _map_ptr(); break; case TYPE_DICT_KEY: delete _dict_key().second; _dict_key().~dict_key_type(); break; default: break; } // Only clear type? m_flags = TYPE_NONE; } inline void Object::swap_same_type(Object& left, Object& right) noexcept { std::swap(left.m_flags, right.m_flags); switch (left.type()) { case Object::TYPE_STRING: left._string().swap(right._string()); break; case Object::TYPE_LIST: left._list().swap(right._list()); break; case Object::TYPE_DICT_KEY: std::swap(left._dict_key().first, right._dict_key().first); std::swap(left._dict_key().second, right._dict_key().second); break; default: std::swap(left.t_pod, right.t_pod); break; } } inline void swap(Object& left, Object& right) noexcept { left.swap(right); } inline bool object_equal(const Object& left, const Object& right) { if (left.type() != right.type()) return false; switch (left.type()) { case Object::TYPE_NONE: return true; case Object::TYPE_VALUE: return left.as_value() == right.as_value(); case Object::TYPE_STRING: return left.as_string() == right.as_string(); default: return false; } } inline bool Object::check(map_type::const_iterator itr, type_type t) const { return itr != _map().end() && itr->second.type() == t; } inline void Object::check_throw(type_type t) const { if (t != type()) throw bencode_error("Wrong object type: expected: " + std::string(type_to_c_str(t)) + " actual: " + std::string(type_to_c_str(type()))); } template inline void Object::check_value_throw(const char* err_msg) const { if (!std::numeric_limits::is_integer) throw internal_error("Tried to check value with non-integer type."); if (!is_value()) throw bencode_error(err_msg); if (!(_value() >= std::numeric_limits::min() && _value() <= std::numeric_limits::max())) throw bencode_error(err_msg); } } // namespace torrent #endif libtorrent-0.16.11/src/torrent/object.cc0000644000000000000000000001637015175073411013547 // libTorrent - BitTorrent library // Copyright (C) 2005-2011, Jari Sundell // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // In addition, as a special exception, the copyright holders give // permission to link the code of portions of this program with the // OpenSSL library under certain conditions as described in each // individual source file, and distribute linked combinations // including the two. // // You must obey the GNU General Public License in all respects for // all of the code used other than OpenSSL. If you modify file(s) // with this exception, you may extend this exception to your version // of the file(s), but you are not obligated to do so. If you do not // wish to do so, delete this exception statement from your version. // If you delete this exception statement from all source files in the // program, then also delete it here. // // Contact: Jari Sundell // // Skomakerveien 33 // 3185 Skoppum, NORWAY #include "config.h" #include #include "object.h" #include "object_stream.h" namespace torrent { Object& Object::get_key(const std::string& k) { check_throw(TYPE_MAP); auto itr = _map().find(k); if (itr == _map().end()) throw bencode_error("Object operator [" + k + "] could not find element"); return itr->second; } const Object& Object::get_key(const std::string& k) const { check_throw(TYPE_MAP); auto itr = _map().find(k); if (itr == _map().end()) throw bencode_error("Object operator [" + k + "] could not find element"); return itr->second; } Object& Object::get_key(const char* k) { check_throw(TYPE_MAP); auto itr = _map().find(std::string(k)); if (itr == _map().end()) throw bencode_error("Object operator [" + std::string(k) + "] could not find element"); return itr->second; } const Object& Object::get_key(const char* k) const { check_throw(TYPE_MAP); auto itr = _map().find(std::string(k)); if (itr == _map().end()) throw bencode_error("Object operator [" + std::string(k) + "] could not find element"); return itr->second; } Object::map_insert_type Object::insert_preserve_type(const key_type& k, Object& b) { check_throw(TYPE_MAP); map_insert_type result = _map().insert(map_type::value_type(k, b)); if (!result.second && result.first->second.type() != b.type()) { result.first->second.move(b); result.second = true; } return result; } Object& Object::move(Object& src) noexcept { if (this == &src) return *this; *this = create_empty(src.type()); swap_same_type(*this, src); return *this; } Object& Object::swap(Object& src) noexcept { if (this == &src) return *this; if (type() != src.type()) { torrent::Object tmp = create_empty(src.type()); swap_same_type(tmp, src); src = create_empty(this->type()); swap_same_type(src, *this); *this = create_empty(tmp.type()); swap_same_type(*this, tmp); } else { swap_same_type(*this, src); } return *this; } Object& Object::merge_copy(const Object& object, uint32_t skip_mask, uint32_t maxDepth) { if (maxDepth == 0 || m_flags & skip_mask) return (*this = object); if (object.is_map()) { if (!is_map()) *this = create_map(); map_type& dest = as_map(); auto destItr = dest.begin(); for (const auto& map : object.as_map()) { destItr = std::find_if(destItr, dest.end(), [&map](const auto& v) { return map.first <= v.first; }); if (map.first < destItr->first) // destItr remains valid and pointing to the next possible // position. dest.insert(destItr, map); else destItr->second.merge_copy(map.second, maxDepth - 1); } // } else if (object.is_list()) { // if (!is_list()) // *this = create_list(); // list_type& dest = as_list(); // list_type::iterator destItr = dest.begin(); // list_type::const_iterator srcItr = object.as_list().begin(); // list_type::const_iterator srcLast = object.as_list().end(); // while (srcItr != srcLast) { // if (destItr == dest.end()) // destItr = dest.insert(destItr, *srcItr); // else // destItr->merge_copy(*srcItr, maxDepth - 1); // destItr++; // } } else { *this = object; } return *this; } Object& Object::operator = (const Object& src) { if (&src == this) return *this; clear(); // Need some more magic here? m_flags = src.m_flags & (mask_type | mask_public); switch (type()) { case TYPE_STRING: new (&_string()) string_type(src._string()); break; case TYPE_LIST: new (&_list()) list_type(src._list()); break; case TYPE_MAP: _map_ptr() = new map_type(src._map()); break; case TYPE_DICT_KEY: new (&_dict_key()) dict_key_type(src._dict_key()); _dict_key().second = new Object(*src._dict_key().second); break; default: t_pod = src.t_pod; break; } return *this; } Object object_create_normal(const raw_bencode& obj) { torrent::Object result; if (object_read_bencode_c(obj.begin(), obj.end(), &result, 128) != obj.end()) throw bencode_error("Invalid bencode data."); return result; } Object object_create_normal(const raw_list& obj) { torrent::Object result = Object::create_list(); raw_list::iterator first = obj.begin(); raw_list::iterator last = obj.end(); while (first != last) { auto& new_entry = result.as_list().emplace_back(); first = object_read_bencode_c(first, last, &new_entry, 128); // The unordered flag is inherited also from list elements who // have been marked as unordered, though e.g. unordered strings // in the list itself does not cause this flag to be set. if (new_entry.flags() & Object::flag_unordered) result.set_internal_flags(Object::flag_unordered); } return result; } Object object_create_normal(const raw_map& obj) { torrent::Object result = Object::create_map(); raw_list::iterator first = obj.begin(); raw_list::iterator last = obj.end(); Object::string_type prev; while (first != last) { raw_string raw_str = object_read_bencode_c_string(first, last); first = raw_str.end(); Object::string_type key_str = raw_str.as_string(); // We do not set flag_unordered if the first key was zero // length, while multiple zero length keys will trigger the // unordered_flag. if (key_str <= prev && !result.as_map().empty()) result.set_internal_flags(Object::flag_unordered); Object* value = &result.as_map()[key_str]; first = object_read_bencode_c(first, last, value, 128); if (value->flags() & Object::flag_unordered) result.set_internal_flags(Object::flag_unordered); key_str.swap(prev); } return result; } } // namespace torrent libtorrent-0.16.11/src/torrent/bitfield.cc0000644000000000000000000000466415175073411014066 #include "config.h" #include "bitfield.h" #include #include "exceptions.h" #include "utils/instrumentation.h" namespace { template inline int popcount_wrapper(T t) { #if USE_BUILTIN_POPCOUNT return __builtin_popcountll(t); #else #error __builtin_popcount not found. unsigned int count = 0; while (t) { count += t & 0x1; t >> 1; } return count; #endif } } namespace torrent { void Bitfield::set_size_bits(size_type s) { if (m_data != NULL) throw internal_error("Bitfield::set_size_bits(size_type s) m_data != NULL."); m_size = s; } void Bitfield::set_size_set(size_type s) { if (s > m_size || m_data != NULL) throw internal_error("Bitfield::set_size_set(size_type s) s > m_size."); m_set = s; } void Bitfield::allocate() { if (m_data != nullptr) return; m_data = std::make_unique(size_bytes()); instrumentation_update(INSTRUMENTATION_MEMORY_BITFIELDS, static_cast(size_bytes())); } void Bitfield::unallocate() { if (m_data == nullptr) return; m_data = nullptr; instrumentation_update(INSTRUMENTATION_MEMORY_BITFIELDS, -static_cast(size_bytes())); } void Bitfield::update() { // Clears the unused bits. clear_tail(); m_set = 0; iterator itr = m_data.get(); iterator last = end(); while (itr + sizeof(unsigned int) <= last) { m_set += popcount_wrapper(*reinterpret_cast(itr)); itr += sizeof(unsigned int); } while (itr != last) { m_set += popcount_wrapper(*itr++); } } void Bitfield::copy(const Bitfield& bf) { unallocate(); m_size = bf.m_size; m_set = bf.m_set; if (bf.m_data == nullptr) { m_data = nullptr; } else { allocate(); std::copy_n(bf.m_data.get(), size_bytes(), m_data.get()); } } void Bitfield::swap(Bitfield& bf) noexcept { std::swap(m_size, bf.m_size); std::swap(m_set, bf.m_set); std::swap(m_data, bf.m_data); } void Bitfield::set_all() { m_set = m_size; std::fill_n(m_data.get(), size_bytes(), ~value_type{}); clear_tail(); } void Bitfield::unset_all() { m_set = 0; std::fill_n(m_data.get(), size_bytes(), value_type{}); } // Quick hack. Speed improvements would require that m_set is kept // up-to-date. void Bitfield::set_range(size_type first, size_type last) { while (first != last) set(first++); } void Bitfield::unset_range(size_type first, size_type last) { while (first != last) unset(first++); } } // namespace torrent libtorrent-0.16.11/src/torrent/download/0000755000000000000000000000000015175073434013657 5libtorrent-0.16.11/src/torrent/download/choke_group.h0000644000000000000000000000465015175073411016255 #ifndef LIBTORRENT_DOWNLOAD_CHOKE_GROUP_H #define LIBTORRENT_DOWNLOAD_CHOKE_GROUP_H #include #include #include #include #include // TODO: Separate out resource_manager_entry. #include namespace torrent { class choke_queue; class resource_manager_entry; class LIBTORRENT_EXPORT choke_group { public: enum tracker_mode_enum { TRACKER_MODE_NORMAL, TRACKER_MODE_AGGRESSIVE }; const std::string& name() const { return m_name; } void set_name(const std::string& name) { m_name = name; } tracker_mode_enum tracker_mode() const { return m_tracker_mode; } void set_tracker_mode(tracker_mode_enum tm) { m_tracker_mode = tm; } choke_queue* up_queue() { return &m_up_queue; } choke_queue* down_queue() { return &m_down_queue; } const choke_queue* c_up_queue() const { return &m_up_queue; } const choke_queue* c_down_queue() const { return &m_down_queue; } uint32_t up_requested() const { return std::min(m_up_queue.size_total(), m_up_queue.max_unchoked()); } uint32_t down_requested() const { return std::min(m_down_queue.size_total(), m_down_queue.max_unchoked()); } bool empty() const { return m_first == m_last; } uint32_t size() const { return std::distance(m_first, m_last); } uint64_t up_rate() const; uint64_t down_rate() const; unsigned int up_unchoked() const { return m_up_queue.size_unchoked(); } unsigned int down_unchoked() const { return m_down_queue.size_unchoked(); } // Internal: resource_manager_entry* first() { return m_first; } resource_manager_entry* last() { return m_last; } void set_first(resource_manager_entry* first) { m_first = first; } void set_last(resource_manager_entry* last) { m_last = last; } void inc_iterators() { m_first++; m_last++; } void dec_iterators() { m_first--; m_last--; } private: std::string m_name; tracker_mode_enum m_tracker_mode{TRACKER_MODE_NORMAL}; choke_queue m_up_queue; choke_queue m_down_queue{choke_queue::flag_unchoke_all_new}; resource_manager_entry* m_first{}; resource_manager_entry* m_last{}; }; } // namespace torrent #endif libtorrent-0.16.11/src/torrent/download/choke_queue.h0000644000000000000000000001264315175073411016246 #ifndef LIBTORRENT_DOWNLOAD_CHOKE_QUEUE_H #define LIBTORRENT_DOWNLOAD_CHOKE_QUEUE_H #include #include #include #include #include #include #include namespace torrent { class choke_status; class group_entry; class ConnectionList; class PeerConnectionBase; class DownloadMain; struct group_stats { unsigned int sum_min_needed; unsigned int sum_max_needed; unsigned int sum_max_leftovers; unsigned int changed_choked; unsigned int changed_unchoked; unsigned int now_choked; unsigned int now_unchoked; }; class LIBTORRENT_EXPORT choke_queue { public: using slot_unchoke = std::function; using slot_can_unchoke = std::function; using slot_connection = std::function; using container_type = std::vector; using value_type = container_type::value_type; using iterator = container_type::iterator; using target_type = std::pair; using group_container_type = std::vector; using slot_weight = void (*)(iterator first, iterator last); static constexpr int flag_unchoke_all_new = 0x1; static constexpr uint32_t order_base = (1 << 30); static constexpr uint32_t order_max_size = 4; static constexpr uint32_t weight_size_bytes = order_max_size * sizeof(uint32_t); static constexpr uint32_t unlimited = ~uint32_t(); struct heuristics_type { slot_weight slot_choke_weight; slot_weight slot_unchoke_weight; uint32_t choke_weight[order_max_size]; uint32_t unchoke_weight[order_max_size]; }; enum heuristics_enum { HEURISTICS_UPLOAD_LEECH, HEURISTICS_UPLOAD_SEED, HEURISTICS_UPLOAD_LEECH_EXPERIMENTAL, HEURISTICS_DOWNLOAD_LEECH, HEURISTICS_MAX_SIZE }; choke_queue(int flags = 0) : m_flags(flags) {} ~choke_queue(); bool is_full() const { return !is_unlimited() && size_unchoked() >= m_maxUnchoked; } bool is_unlimited() const { return m_maxUnchoked == unlimited; } uint32_t size_unchoked() const { return m_currently_unchoked; } uint32_t size_queued() const { return m_currently_queued; } uint32_t size_total() const { return size_unchoked() + size_queued(); } // This must be unsigned. uint32_t max_unchoked() const { return m_maxUnchoked; } int32_t max_unchoked_signed() const { return m_maxUnchoked; } void set_max_unchoked(uint32_t v) { m_maxUnchoked = v; } void balance(); void balance_entry(group_entry* entry); int cycle(uint32_t quota); // Assume interested state is already updated for the PCB and that // this gets called once every time the status changes. void set_queued(PeerConnectionBase* pc, choke_status* base); void set_not_queued(PeerConnectionBase* pc, choke_status* base); void set_snubbed(PeerConnectionBase* pc, choke_status* base); void set_not_snubbed(PeerConnectionBase* pc, choke_status* base); void disconnected(PeerConnectionBase* pc, choke_status* base); static void move_connections(choke_queue* src, choke_queue* dest, DownloadMain* download, group_entry* base); heuristics_enum heuristics() const { return m_heuristics; } void set_heuristics(heuristics_enum hs) { m_heuristics = hs; } void set_slot_unchoke(slot_unchoke s) { m_slotUnchoke = std::move(s); } void set_slot_can_unchoke(slot_can_unchoke s) { m_slotCanUnchoke = std::move(s); } void set_slot_connection(slot_connection s) { m_slotConnection = std::move(s); } // TODO: Consider putting this in queue_group. group_container_type& group_container() { return m_group_container; } void modify_currently_queued(int value) { m_currently_queued += value; } void modify_currently_unchoked(int value) { m_currently_unchoked += value; } private: choke_queue(const choke_queue&) = delete; choke_queue& operator=(const choke_queue&) = delete; group_stats prepare_weights(group_stats gs); group_stats retrieve_connections(group_stats gs, container_type* queued, container_type* unchoked); void rebuild_containers(container_type* queued, container_type* unchoked); inline uint32_t max_alternate() const; uint32_t adjust_choke_range(iterator first, iterator last, container_type* src_container, container_type* dest_container, uint32_t max, bool is_choke); static heuristics_type m_heuristics_list[HEURISTICS_MAX_SIZE]; int m_flags; heuristics_enum m_heuristics{HEURISTICS_MAX_SIZE}; uint32_t m_maxUnchoked{unlimited}; uint32_t m_currently_queued{0}; uint32_t m_currently_unchoked{0}; slot_unchoke m_slotUnchoke; slot_can_unchoke m_slotCanUnchoke; slot_connection m_slotConnection; group_container_type m_group_container; }; } // namespace torrent #endif libtorrent-0.16.11/src/torrent/download/download_manager.h0000644000000000000000000000665715175073411017262 // libTorrent - BitTorrent library // Copyright (C) 2005-2011, Jari Sundell // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // In addition, as a special exception, the copyright holders give // permission to link the code of portions of this program with the // OpenSSL library under certain conditions as described in each // individual source file, and distribute linked combinations // including the two. // // You must obey the GNU General Public License in all respects for // all of the code used other than OpenSSL. If you modify file(s) // with this exception, you may extend this exception to your version // of the file(s), but you are not obligated to do so. If you do not // wish to do so, delete this exception statement from your version. // If you delete this exception statement from all source files in the // program, then also delete it here. // // Contact: Jari Sundell // // Skomakerveien 33 // 3185 Skoppum, NORWAY #ifndef LIBTORRENT_DOWNLOAD_MANAGER_H #define LIBTORRENT_DOWNLOAD_MANAGER_H #include #include #include namespace torrent { class ChunkList; class DownloadWrapper; class DownloadInfo; class DownloadMain; class LIBTORRENT_EXPORT DownloadManager : private std::vector { public: using base_type = std::vector; using value_type = base_type::value_type; using pointer = base_type::pointer; using const_pointer = base_type::const_pointer; using reference = base_type::reference; using const_reference = base_type::const_reference; using size_type = base_type::size_type; using iterator = base_type::iterator; using reverse_iterator = base_type::reverse_iterator; using const_iterator = base_type::const_iterator; using const_reverse_iterator = base_type::const_reverse_iterator; using base_type::empty; using base_type::size; using base_type::begin; using base_type::end; using base_type::rbegin; using base_type::rend; DownloadManager() = default; ~DownloadManager() { clear(); } DownloadManager(const DownloadManager&) = default; DownloadManager& operator=(const DownloadManager&) = default; iterator find(const std::string& hash); iterator find(const HashString& hash); iterator find(DownloadInfo* info); iterator find_chunk_list(ChunkList* cl); DownloadMain* find_main(const char* hash); DownloadMain* find_main_obfuscated(const char* hash); // // Don't export: // iterator insert(DownloadWrapper* d) LIBTORRENT_NO_EXPORT; iterator erase(DownloadWrapper* d) LIBTORRENT_NO_EXPORT; void clear() LIBTORRENT_NO_EXPORT; }; } // namespace torrent #endif libtorrent-0.16.11/src/torrent/download/resource_manager.cc0000644000000000000000000003233015175073411017423 #include "config.h" #include #include #include #include #include "download/download_main.h" #include "protocol/peer_connection_base.h" #include "torrent/download/choke_group.h" #include "torrent/download_info.h" #include "torrent/exceptions.h" #include "torrent/utils/log.h" #include "choke_queue.h" #include "resource_manager.h" #define LT_LOG_THIS(log_fmt, ...) \ lt_log_print_subsystem(LOG_TORRENT_INFO, "resource_manager", log_fmt, __VA_ARGS__); #define LT_LOG_ITR(log_fmt, ...) \ lt_log_print_info(LOG_TORRENT_INFO, itr->download()->info(), "resource_manager", log_fmt, __VA_ARGS__); namespace torrent { const Rate* resource_manager_entry::up_rate() const { return m_download->info()->up_rate(); } const Rate* resource_manager_entry::down_rate() const { return m_download->info()->down_rate(); } ResourceManager::~ResourceManager() { assert(m_currentlyUploadUnchoked == 0 && "ResourceManager::~ResourceManager() called but m_currentlyUploadUnchoked != 0."); assert(m_currentlyDownloadUnchoked == 0 && "ResourceManager::~ResourceManager() called but m_currentlyDownloadUnchoked != 0."); std::for_each(choke_base_type::begin(), choke_base_type::end(), [](choke_group* g) { delete g; }); } // If called directly ensure a valid group has been selected. ResourceManager::iterator ResourceManager::insert(const resource_manager_entry& entry) { bool will_realloc = true; //size() == capacity(); auto itr = base_type::insert(find_group_end(entry.group()), entry); DownloadMain* download = itr->download(); download->set_choke_group(choke_base_type::at(entry.group())); if (will_realloc) { update_group_iterators(); } else { auto group_itr = choke_base_type::begin() + itr->group(); (*group_itr)->set_last((*group_itr)->last() + 1); std::for_each(++group_itr, choke_base_type::end(), std::mem_fn(&choke_group::inc_iterators)); } choke_queue::move_connections(NULL, group_at(entry.group())->up_queue(), download, download->up_group_entry()); choke_queue::move_connections(NULL, group_at(entry.group())->down_queue(), download, download->down_group_entry()); return itr; } void ResourceManager::update_group_iterators() { auto entry_itr = base_type::begin(); auto group_itr = choke_base_type::begin(); while (group_itr != choke_base_type::end()) { (*group_itr)->set_first(&*entry_itr); entry_itr = std::find_if(entry_itr, end(), [group_itr, this](value_type v) { return (std::distance(choke_base_type::begin(), group_itr)) < v.group(); }); (*group_itr)->set_last(&*entry_itr); group_itr++; } } void ResourceManager::validate_group_iterators() { auto entry_itr = base_type::begin(); auto group_itr = choke_base_type::begin(); while (group_itr != choke_base_type::end()) { if ((*group_itr)->first() != &*entry_itr) throw internal_error("ResourceManager::receive_tick() invalid first iterator."); entry_itr = std::find_if(entry_itr, end(), [group_itr, this](value_type v) { return (std::distance(choke_base_type::begin(), group_itr)) < v.group(); }); if ((*group_itr)->last() != &*entry_itr) throw internal_error("ResourceManager::receive_tick() invalid last iterator."); group_itr++; } } void ResourceManager::erase(DownloadMain* d) { auto itr = std::find_if(begin(), end(), [d](value_type e) { return d == e.download(); }); if (itr == end()) throw internal_error("ResourceManager::erase() itr == end()."); choke_queue::move_connections(group_at(itr->group())->up_queue(), NULL, d, d->up_group_entry()); choke_queue::move_connections(group_at(itr->group())->down_queue(), NULL, d, d->down_group_entry()); auto group_itr = choke_base_type::begin() + itr->group(); (*group_itr)->set_last((*group_itr)->last() - 1); std::for_each(++group_itr, choke_base_type::end(), std::mem_fn(&choke_group::dec_iterators)); base_type::erase(itr); } void ResourceManager::push_group(const std::string& name) { if (name.empty() || std::any_of(choke_base_type::begin(), choke_base_type::end(), [name](choke_group* g) { return name == g->name(); })) throw input_error("Duplicate name for choke group."); choke_base_type::push_back(new choke_group()); choke_base_type::back()->set_name(name); choke_base_type::back()->set_first(&*base_type::end()); choke_base_type::back()->set_last(&*base_type::end()); choke_base_type::back()->up_queue()->set_heuristics(choke_queue::HEURISTICS_UPLOAD_LEECH); choke_base_type::back()->down_queue()->set_heuristics(choke_queue::HEURISTICS_DOWNLOAD_LEECH); choke_base_type::back()->up_queue()->set_slot_unchoke([this](int n) { receive_upload_unchoke(n); }); choke_base_type::back()->down_queue()->set_slot_unchoke([this](int n) { receive_download_unchoke(n); }); choke_base_type::back()->up_queue()->set_slot_can_unchoke([this] { return retrieve_upload_can_unchoke(); }); choke_base_type::back()->down_queue()->set_slot_can_unchoke([this] { return retrieve_download_can_unchoke(); }); choke_base_type::back()->up_queue()->set_slot_connection(&PeerConnectionBase::receive_upload_choke); choke_base_type::back()->down_queue()->set_slot_connection(&PeerConnectionBase::receive_download_choke); } ResourceManager::iterator ResourceManager::find(const DownloadMain* d) { return std::find_if(begin(), end(), [d](value_type e) { return d == e.download(); }); } ResourceManager::iterator ResourceManager::find_throw(const DownloadMain* d) { auto itr = find(d); if (itr == end()) throw input_error("Could not find download in resource manager."); return itr; } ResourceManager::iterator ResourceManager::find_group_end(uint16_t group) { return std::find_if(begin(), end(), [group](value_type v) { return group < v.group(); }); } choke_group* ResourceManager::group_at(uint16_t grp) { if (grp >= choke_base_type::size()) throw input_error("Choke group not found."); return choke_base_type::at(grp); } choke_group* ResourceManager::group_at_name(const std::string& name) { auto itr = std::find_if(choke_base_type::begin(), choke_base_type::end(), [name](choke_group* g) { return name == g->name(); }); if (itr == choke_base_type::end()) throw input_error("Choke group not found."); return *itr; } int ResourceManager::group_index_of(const std::string& name) { auto itr = std::find_if(choke_base_type::begin(), choke_base_type::end(), [name](choke_group* g) { return name == g->name(); }); if (itr == choke_base_type::end()) throw input_error("Choke group not found."); return std::distance(choke_base_type::begin(), itr); } void ResourceManager::set_priority(iterator itr, uint16_t pri) { LT_LOG_ITR("set priority: %" PRIu16, 0); itr->set_priority(pri); } void ResourceManager::set_group(iterator itr, uint16_t grp) { if (itr->group() == grp) return; if (grp >= choke_base_type::size()) throw input_error("Choke group not found."); choke_queue::move_connections(itr->download()->choke_group()->up_queue(), choke_base_type::at(grp)->up_queue(), itr->download(), itr->download()->up_group_entry()); choke_queue::move_connections(itr->download()->choke_group()->down_queue(), choke_base_type::at(grp)->down_queue(), itr->download(), itr->download()->down_group_entry()); auto group_src = choke_base_type::begin() + itr->group(); auto group_dest = choke_base_type::begin() + grp; resource_manager_entry entry = *itr; entry.set_group(grp); entry.download()->set_choke_group(choke_base_type::at(entry.group())); base_type::erase(itr); base_type::insert(find_group_end(entry.group()), entry); // Update the group iterators after the move. We know the groups are // not the same, so no need to check for that. if (group_dest < group_src) { (*group_dest)->set_last((*group_dest)->last() + 1); std::for_each(++group_dest, group_src, std::mem_fn(&choke_group::inc_iterators)); (*group_src)->set_first((*group_src)->first() + 1); } else { (*group_src)->set_last((*group_src)->last() - 1); std::for_each(++group_src, group_dest, std::mem_fn(&choke_group::dec_iterators)); (*group_dest)->set_first((*group_dest)->first() - 1); } } void ResourceManager::set_max_upload_unchoked(unsigned int m) { if (m > (1 << 20)) throw input_error("Max unchoked must be between 0 and 2^20."); m_maxUploadUnchoked = m; } void ResourceManager::set_max_download_unchoked(unsigned int m) { if (m > (1 << 20)) throw input_error("Max unchoked must be between 0 and 2^20."); m_maxDownloadUnchoked = m; } // The choking choke manager won't updated it's count until after // possibly multiple calls of this function. void ResourceManager::receive_upload_unchoke(int num) { LT_LOG_THIS("adjusting upload unchoked slots; current:%u adjusted:%i", m_currentlyUploadUnchoked, num); if (static_cast(m_currentlyUploadUnchoked) + num < 0) throw internal_error("ResourceManager::receive_upload_unchoke(...) received an invalid value."); m_currentlyUploadUnchoked += num; } void ResourceManager::receive_download_unchoke(int num) { LT_LOG_THIS("adjusting download unchoked slots; current:%u adjusted:%i", m_currentlyDownloadUnchoked, num); if (static_cast(m_currentlyDownloadUnchoked) + num < 0) throw internal_error("ResourceManager::receive_download_unchoke(...) received an invalid value."); m_currentlyDownloadUnchoked += num; } int ResourceManager::retrieve_upload_can_unchoke() const { if (m_maxUploadUnchoked == 0) return std::numeric_limits::max(); return static_cast(m_maxUploadUnchoked) - static_cast(m_currentlyUploadUnchoked); } int ResourceManager::retrieve_download_can_unchoke() const { if (m_maxDownloadUnchoked == 0) return std::numeric_limits::max(); return static_cast(m_maxDownloadUnchoked) - static_cast(m_currentlyDownloadUnchoked); } void ResourceManager::receive_tick() { validate_group_iterators(); m_currentlyUploadUnchoked += balance_unchoked(choke_base_type::size(), m_maxUploadUnchoked, true); m_currentlyDownloadUnchoked += balance_unchoked(choke_base_type::size(), m_maxDownloadUnchoked, false); auto up_unchoked = std::accumulate(choke_base_type::begin(), choke_base_type::end(), 0U, [](auto sum, auto group) { return sum + group->up_unchoked(); }); auto down_unchoked = std::accumulate(choke_base_type::begin(), choke_base_type::end(), 0U, [](auto sum, auto group) { return sum + group->down_unchoked(); }); if (m_currentlyUploadUnchoked != up_unchoked) throw torrent::internal_error("m_currentlyUploadUnchoked != choke_base_type::back()->up_queue()->size_unchoked()"); if (m_currentlyDownloadUnchoked != down_unchoked) throw torrent::internal_error("m_currentlyDownloadUnchoked != choke_base_type::back()->down_queue()->size_unchoked()"); } unsigned int ResourceManager::total_weight() const { // TODO: This doesn't take into account inactive downloads. unsigned int total = 0; for (const auto& resource : *this) total += resource.priority(); return total; } int ResourceManager::balance_unchoked(unsigned int weight, unsigned int max_unchoked, bool is_up) { int change = 0; if (max_unchoked == 0) { auto group_itr = choke_base_type::begin(); while (group_itr != choke_base_type::end()) { choke_queue* cm = is_up ? (*group_itr)->up_queue() : (*group_itr)->down_queue(); change += cm->cycle(std::numeric_limits::max()); group_itr++; } return change; } unsigned int quota = max_unchoked; // We put the downloads with fewest interested first so that those // with more interested will gain any unused slots from the // preceding downloads. Consider multiplying with priority. // // Consider skipping the leading zero interested downloads. Though // that won't work as they need to choke peers once their priority // is turned off. auto choke_groups = std::vector(choke_base_type::begin(), choke_base_type::end()); // Start with the group requesting fewest slots (relative to weight) // so that we only need to iterate through the list once allocating // slots. There will be no slots left unallocated unless all groups // have reached max slots allowed. if (is_up) { std::sort(choke_groups.begin(), choke_groups.end(), [](auto lhs, auto rhs) { return lhs->up_requested() < rhs->up_requested(); }); LT_LOG_THIS("balancing upload unchoked slots; current_unchoked:%u change:%i max_unchoked:%u", m_currentlyUploadUnchoked, change, max_unchoked); } else { std::sort(choke_groups.begin(), choke_groups.end(), [](auto lhs, auto rhs) { return lhs->down_requested() < rhs->down_requested(); }); LT_LOG_THIS("balancing download unchoked slots; current_unchoked:%u change:%i max_unchoked:%u", m_currentlyDownloadUnchoked, change, max_unchoked); } for (const auto& group : choke_groups) { choke_queue* cm = is_up ? group->up_queue() : group->down_queue(); // change += cm->cycle(weight != 0 ? (quota * itr->priority()) / weight : 0); change += cm->cycle(weight != 0 ? quota / weight : 0); quota -= cm->size_unchoked(); // weight -= itr->priority(); weight--; } if (weight != 0) throw internal_error("ResourceManager::balance_unchoked(...) weight did not reach zero."); return change; } } // namespace torrent libtorrent-0.16.11/src/torrent/download/download_manager.cc0000644000000000000000000000727315175073411017413 // libTorrent - BitTorrent library // Copyright (C) 2005-2011, Jari Sundell // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // In addition, as a special exception, the copyright holders give // permission to link the code of portions of this program with the // OpenSSL library under certain conditions as described in each // individual source file, and distribute linked combinations // including the two. // // You must obey the GNU General Public License in all respects for // all of the code used other than OpenSSL. If you modify file(s) // with this exception, you may extend this exception to your version // of the file(s), but you are not obligated to do so. If you do not // wish to do so, delete this exception statement from your version. // If you delete this exception statement from all source files in the // program, then also delete it here. // // Contact: Jari Sundell // // Skomakerveien 33 // 3185 Skoppum, NORWAY #include "config.h" #include "torrent/download_info.h" #include "torrent/exceptions.h" #include "download/download_wrapper.h" #include "download_manager.h" namespace torrent { DownloadManager::iterator DownloadManager::insert(DownloadWrapper* d) { if (find(d->info()->hash()) != end()) throw internal_error("Could not add torrent as it already exists."); return base_type::insert(end(), d); } DownloadManager::iterator DownloadManager::erase(DownloadWrapper* d) { auto itr = std::find(begin(), end(), d); if (itr == end()) throw internal_error("Tried to remove a torrent that doesn't exist"); delete *itr; return base_type::erase(itr); } void DownloadManager::clear() { while (!empty()) { delete base_type::back(); base_type::pop_back(); } } DownloadManager::iterator DownloadManager::find(const std::string& hash) { return find(*HashString::cast_from(hash)); } DownloadManager::iterator DownloadManager::find(const HashString& hash) { return std::find_if(begin(), end(), [hash](const auto& wrapper){ return hash == wrapper->info()->hash(); }); } DownloadManager::iterator DownloadManager::find(DownloadInfo* info) { return std::find_if(begin(), end(), [info](const auto& wrapper){ return info == wrapper->info(); }); } DownloadManager::iterator DownloadManager::find_chunk_list(ChunkList* cl) { return std::find_if(begin(), end(), [cl](const auto& wrapper){ return cl == wrapper->chunk_list(); }); } DownloadMain* DownloadManager::find_main(const char* hash) { auto hash_str = *HashString::cast_from(hash); auto itr = std::find_if(begin(), end(), [hash_str](const auto& wrapper){ return hash_str == wrapper->info()->hash(); }); if (itr == end()) return NULL; else return (*itr)->main(); } DownloadMain* DownloadManager::find_main_obfuscated(const char* hash) { auto hash_str = *HashString::cast_from(hash); auto itr = std::find_if(begin(), end(), [hash_str](const auto& wrapper){ return hash_str == wrapper->info()->hash_obfuscated(); }); if (itr == end()) return NULL; else return (*itr)->main(); } } // namespace torrent libtorrent-0.16.11/src/torrent/download/group_entry.h0000644000000000000000000001165715175073411016332 // libTorrent - BitTorrent library // Copyright (C) 2005-2011, Jari Sundell // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // In addition, as a special exception, the copyright holders give // permission to link the code of portions of this program with the // OpenSSL library under certain conditions as described in each // individual source file, and distribute linked combinations // including the two. // // You must obey the GNU General Public License in all respects for // all of the code used other than OpenSSL. If you modify file(s) // with this exception, you may extend this exception to your version // of the file(s), but you are not obligated to do so. If you do not // wish to do so, delete this exception statement from your version. // If you delete this exception statement from all source files in the // program, then also delete it here. // // Contact: Jari Sundell // // Skomakerveien 33 // 3185 Skoppum, NORWAY #ifndef LIBTORRENT_DOWNLOAD_GROUP_ENTRY_H #define LIBTORRENT_DOWNLOAD_GROUP_ENTRY_H #include #include #include #include #include namespace torrent { class choke_queue; class PeerConnectionBase; struct weighted_connection { weighted_connection(PeerConnectionBase* pcb, uint32_t w) : connection(pcb), weight(w) {} bool operator == (const PeerConnectionBase* pcb) const { return pcb == connection; } bool operator != (const PeerConnectionBase* pcb) const { return pcb != connection; } PeerConnectionBase* connection; uint32_t weight; }; // TODO: Rename to choke_entry, create an new class called group entry? class group_entry { public: using container_type = std::vector; static constexpr uint32_t unlimited = ~uint32_t(); uint32_t size_connections() const { return m_queued.size() + m_unchoked.size(); } uint32_t max_slots() const { return m_max_slots; } uint32_t min_slots() const { return m_min_slots; } void set_max_slots(uint32_t s) { m_max_slots = s; } void set_min_slots(uint32_t s) { m_min_slots = s; } const container_type* queued() { return &m_queued; } const container_type* unchoked() { return &m_unchoked; } protected: friend class choke_queue; friend class PeerConnectionBase; container_type* mutable_queued() { return &m_queued; } container_type* mutable_unchoked() { return &m_unchoked; } void connection_unchoked(PeerConnectionBase* pcb); void connection_choked(PeerConnectionBase* pcb); void connection_queued(PeerConnectionBase* pcb); void connection_unqueued(PeerConnectionBase* pcb); private: uint32_t m_max_slots{unlimited}; uint32_t m_min_slots{0}; // After a cycle the end of the vector should have the // highest-priority connections, and any new connections get put at // the back so they should always good candidates for unchoking. container_type m_queued; container_type m_unchoked; }; inline void group_entry::connection_unchoked(PeerConnectionBase* pcb) { auto itr = std::find(m_unchoked.begin(), m_unchoked.end(), pcb); if (itr != m_unchoked.end()) throw internal_error("group_entry::connection_unchoked(pcb) failed."); m_unchoked.emplace_back(pcb, uint32_t()); } inline void group_entry::connection_queued(PeerConnectionBase* pcb) { auto itr = std::find(m_queued.begin(), m_queued.end(), pcb); if (itr != m_queued.end()) throw internal_error("group_entry::connection_queued(pcb) failed."); m_queued.emplace_back(pcb, uint32_t()); } inline void group_entry::connection_choked(PeerConnectionBase* pcb) { auto itr = std::find(m_unchoked.begin(), m_unchoked.end(), pcb); if (itr == m_unchoked.end()) throw internal_error("group_entry::connection_choked(pcb) failed."); std::swap(*itr, m_unchoked.back()); m_unchoked.pop_back(); } inline void group_entry::connection_unqueued(PeerConnectionBase* pcb) { auto itr = std::find(m_queued.begin(), m_queued.end(), pcb); if (itr == m_queued.end()) throw internal_error("group_entry::connection_unqueued(pcb) failed."); std::swap(*itr, m_queued.back()); m_queued.pop_back(); } } // namespace torrent #endif libtorrent-0.16.11/src/torrent/download/choke_queue.cc0000644000000000000000000006135415175073411016407 #include "config.h" #include "choke_queue.h" #include #include #include #include "protocol/peer_connection_base.h" #include "torrent/download/group_entry.h" #include "torrent/peer/connection_list.h" #include "torrent/peer/choke_status.h" #include "torrent/utils/log.h" // TODO: Add a different logging category. #define LT_LOG_THIS(log_fmt, ...) \ lt_log_print_subsystem(LOG_TORRENT_INFO, "choke_queue", log_fmt, __VA_ARGS__); namespace torrent { static bool choke_manager_less(choke_queue::value_type v1, choke_queue::value_type v2) { return v1.weight < v2.weight; } static inline bool should_connection_unchoke(choke_queue* cq, PeerConnectionBase* pcb) { return pcb->should_connection_unchoke(cq); } static inline void log_choke_changes_func_new(void* address, const char* title, int quota, int adjust) { lt_log_print(LOG_INSTRUMENTATION_CHOKE, "%p %i %s %i %i", address, 0, //lf->last_update(), title, quota, adjust); } choke_queue::~choke_queue() { assert(m_currently_unchoked == 0 && "choke_queue::~choke_queue() called but m_currently_unchoked != 0."); assert(m_currently_queued == 0 && "choke_queue::~choke_queue() called but m_currently_queued != 0."); } // 1 > 1 // 9 > 2 // 17 > 3 < 21 // 25 > 4 < 31 // 33 > 5 < 41 // 65 > 9 < 81 inline uint32_t choke_queue::max_alternate() const { if (m_currently_unchoked < 31) return (m_currently_unchoked + 7) / 8; else return (m_currently_unchoked + 9) / 10; } group_stats choke_queue::prepare_weights(group_stats gs) { // gs.sum_min_needed = 0; // gs.sum_max_needed = 0; // gs.sum_max_leftovers = 0; // Needs to reflect how many we can optimistically unchoke after choking unchoked connections? // // also remember to clear the queue/unchoked thingies. for (auto group : m_group_container) { m_heuristics_list[m_heuristics].slot_choke_weight(group->mutable_unchoked()->begin(), group->mutable_unchoked()->end()); std::sort(group->mutable_unchoked()->begin(), group->mutable_unchoked()->end(), choke_manager_less); m_heuristics_list[m_heuristics].slot_unchoke_weight(group->mutable_queued()->begin(), group->mutable_queued()->end()); std::sort(group->mutable_queued()->begin(), group->mutable_queued()->end(), choke_manager_less); // Aggregate the statistics... Remember to update them after // optimistic/pessimistic unchokes. gs.sum_min_needed += std::min({group->size_connections(), group->max_slots(), group->min_slots()}); uint32_t max_slots = std::min(group->size_connections(), group->max_slots()); gs.sum_max_needed += max_slots; gs.sum_max_leftovers += group->size_connections() - max_slots; // Counter for how many can choke/unchoke based on weights? // However one should never have zero weight for any weight group. } return gs; } group_stats choke_queue::retrieve_connections(group_stats gs, container_type* queued, container_type* unchoked) { for (auto entry : m_group_container) { unsigned int min_slots = std::min(entry->min_slots(), entry->max_slots()); lt_log_print(LOG_PEER_DEBUG, "Choke queue retrieve_connections; queued:%u unchoked:%u min_slots:%u max_slots:%u.", (unsigned)entry->queued()->size(), (unsigned)entry->unchoked()->size(), min_slots, entry->max_slots()); // Disable this after finding the flaw... ? // if (entry->unchoked()->size() > entry->max_slots()) { // unsigned int count = 0; // // Still needing choke/unchoke to fill min_size. // while (entry->unchoked()->size() > entry->max_slots() && !entry->unchoked()->empty()) // count += m_slotConnection(entry->unchoked()->back().connection, true); // // m_slotUnchoke(-count); // Move this? // gs.now_choked += entry->unchoked()->size(); // Need to add this... // } if (entry->unchoked()->size() < min_slots) { // Currently unchoked is less than min_slots, so don't give any // candidates for choking and also check if we can fill the // requirement by unchoking queued connections. unsigned int count = 0; // Still needing choke/unchoke to fill min_size. while (!entry->queued()->empty() && entry->unchoked()->size() < min_slots) count += m_slotConnection(entry->queued()->back().connection, false); gs.changed_unchoked += count; gs.now_unchoked += entry->unchoked()->size(); } else { // TODO: This only handles a single weight group, fixme. auto first = entry->unchoked()->begin() + min_slots; auto last = entry->unchoked()->end(); unchoked->insert(unchoked->end(), first, last); gs.now_unchoked += min_slots; } // TODO: Does not do optimistic unchokes if min_slots >= max_slots. if (entry->unchoked()->size() < entry->max_slots()) { // We can assume that at either we have no queued connections or // 'min_slots' has been reached. queued->insert(queued->end(), entry->queued()->end() - std::min(entry->queued()->size(), entry->max_slots() - entry->unchoked()->size()), entry->queued()->end()); } } return gs; } void choke_queue::rebuild_containers(container_type* queued, container_type* unchoked) { queued->clear(); unchoked->clear(); for (auto& group : m_group_container) { queued->insert(queued->end(), group->queued()->begin(), group->queued()->end()); unchoked->insert(unchoked->end(), group->unchoked()->begin(), group->unchoked()->end()); } } void choke_queue::balance() { LT_LOG_THIS("balancing queue: heuristics:%i currently_unchoked:%" PRIu32 " max_unchoked:%" PRIu32, m_heuristics, m_currently_unchoked, m_maxUnchoked); // Return if no balancing is needed. Don't return if is_unlimited() // as we might have just changed the value and have interested that // can be unchoked. // // TODO: Check if unlimited, in that case we don't need to balance // if we got no queued connections. if (m_currently_unchoked == m_maxUnchoked) return; container_type queued; container_type unchoked; group_stats gs{}; gs = prepare_weights(gs); gs = retrieve_connections(gs, &queued, &unchoked); if (gs.changed_unchoked != 0) m_slotUnchoke(gs.changed_unchoked); // If we have more unchoked than max global slots allow for, // 'can_unchoke' will be negative. // // Throws std::bad_function_call if 'set_slot_can_unchoke' is not // set. int can_unchoke = m_slotCanUnchoke(); int max_unchoked = std::min(m_maxUnchoked, uint32_t{1} << 20); int adjust = max_unchoked - static_cast(unchoked.size() + gs.now_unchoked); adjust = std::min(adjust, can_unchoke); log_choke_changes_func_new(this, "balance", m_maxUnchoked, adjust); int result = 0; if (adjust > 0) { result = adjust_choke_range(queued.begin(), queued.end(), &queued, &unchoked, adjust, false); } else if (adjust < 0) { // We can do the choking before the slot is called as this // choke_queue won't be unchoking the same peers due to the // call-back. result = -adjust_choke_range(unchoked.begin(), unchoked.end(), &unchoked, &queued, -adjust, true); } if (result != 0) m_slotUnchoke(result); LT_LOG_THIS("balanced queue: adjust:%i can_unchoke:%i queued:%zu unchoked:%zu result:%i", adjust, can_unchoke, queued.size(), unchoked.size(), result); } void choke_queue::balance_entry(group_entry* entry) { m_heuristics_list[m_heuristics].slot_choke_weight(entry->mutable_unchoked()->begin(), entry->mutable_unchoked()->end()); std::sort(entry->mutable_unchoked()->begin(), entry->mutable_unchoked()->end(), choke_manager_less); m_heuristics_list[m_heuristics].slot_unchoke_weight(entry->mutable_queued()->begin(), entry->mutable_queued()->end()); std::sort(entry->mutable_queued()->begin(), entry->mutable_queued()->end(), choke_manager_less); int count = 0; unsigned int min_slots = std::min(entry->min_slots(), entry->max_slots()); while (!entry->unchoked()->empty() && entry->unchoked()->size() > entry->max_slots()) count -= m_slotConnection(entry->unchoked()->back().connection, true); while (!entry->queued()->empty() && entry->unchoked()->size() < min_slots) count += m_slotConnection(entry->queued()->back().connection, false); m_slotUnchoke(count); } int choke_queue::cycle(uint32_t quota) { // TODO: This should not use the old values, but rather the number // of unchoked this round. // HACKKKKKK container_type queued; container_type unchoked; rebuild_containers(&queued, &unchoked); int oldSize = unchoked.size(); uint32_t alternate = max_alternate(); queued.clear(); unchoked.clear(); group_stats gs{}; gs = prepare_weights(gs); gs = retrieve_connections(gs, &queued, &unchoked); quota = std::min(quota, m_maxUnchoked); quota = quota - std::min(quota, gs.now_unchoked); uint32_t adjust = (unchoked.size() < quota) ? (quota - unchoked.size()) : 0; adjust = std::max(adjust, alternate); adjust = std::min(adjust, quota); log_choke_changes_func_new(this, "cycle", quota, adjust); lt_log_print(LOG_PEER_DEBUG, "Called cycle; quota:%u adjust:%i alternate:%i queued:%u unchoked:%u.", quota, adjust, alternate, (unsigned)queued.size(), (unsigned)unchoked.size()); uint32_t unchoked_count = adjust_choke_range(queued.begin(), queued.end(), &queued, &unchoked, adjust, false); if (unchoked.size() > quota) adjust_choke_range(unchoked.begin(), unchoked.end() - unchoked_count, &unchoked, &queued, unchoked.size() - quota, true); if (unchoked.size() > quota) throw internal_error("choke_queue::cycle() unchoked.size() > quota."); rebuild_containers(&queued, &unchoked); // Remove... lt_log_print(LOG_PEER_DEBUG, "After cycle; queued:%u unchoked:%u unchoked_count:%i old_size:%i.", (unsigned)queued.size(), (unsigned)unchoked.size(), unchoked_count, oldSize); return (static_cast(unchoked.size()) - oldSize); // + gs.changed_unchoke } void choke_queue::set_queued(PeerConnectionBase* pc, choke_status* base) { if (base->queued() || base->unchoked()) return; base->set_queued(true); if (base->snubbed()) return; base->entry()->connection_queued(pc); modify_currently_queued(1); if (!is_full() && (m_flags & flag_unchoke_all_new || m_slotCanUnchoke() > 0) && should_connection_unchoke(this, pc) && base->time_last_choke() + 10s < this_thread::cached_time()) { m_slotConnection(pc, false); m_slotUnchoke(1); } } void choke_queue::set_not_queued(PeerConnectionBase* pc, choke_status* base) { if (!base->queued()) return; base->set_queued(false); if (base->snubbed()) return; if (base->unchoked()) { m_slotConnection(pc, true); m_slotUnchoke(-1); } base->entry()->connection_unqueued(pc); modify_currently_queued(-1); } void choke_queue::set_snubbed(PeerConnectionBase* pc, choke_status* base) { if (base->snubbed()) return; base->set_snubbed(true); if (base->unchoked()) { m_slotConnection(pc, true); m_slotUnchoke(-1); } else if (!base->queued()) { return; } base->entry()->connection_unqueued(pc); modify_currently_queued(-1); base->set_queued(false); } void choke_queue::set_not_snubbed(PeerConnectionBase* pc, choke_status* base) { if (!base->snubbed()) return; base->set_snubbed(false); if (!base->queued()) return; if (base->unchoked()) throw internal_error("choke_queue::set_not_snubbed(...) base->unchoked()."); base->entry()->connection_queued(pc); modify_currently_queued(1); if (!is_full() && (m_flags & flag_unchoke_all_new || m_slotCanUnchoke() > 0) && should_connection_unchoke(this, pc) && base->time_last_choke() + 10s < this_thread::cached_time()) { m_slotConnection(pc, false); m_slotUnchoke(1); } } // We are no longer in m_connectionList. void choke_queue::disconnected(PeerConnectionBase* pc, choke_status* base) { if (base->snubbed()) { // Do nothing. } else if (base->unchoked()) { m_slotUnchoke(-1); base->entry()->connection_choked(pc); modify_currently_unchoked(-1); } else if (base->queued()) { base->entry()->connection_unqueued(pc); modify_currently_queued(-1); } base->set_queued(false); } // No need to do any choking as the next choke balancing will take // care of things. void choke_queue::move_connections(choke_queue* src, choke_queue* dest, [[maybe_unused]] DownloadMain* download, group_entry* base) { if (src != NULL) { auto itr = std::find(src->m_group_container.begin(), src->m_group_container.end(), base); if (itr == src->m_group_container.end()) throw internal_error("choke_queue::move_connections(...) could not find group."); std::swap(*itr, src->m_group_container.back()); src->m_group_container.pop_back(); } if (dest != NULL) { dest->m_group_container.push_back(base); } if (src == NULL || dest == NULL) return; src->modify_currently_queued(-base->queued()->size()); src->modify_currently_unchoked(-base->unchoked()->size()); dest->modify_currently_queued(base->queued()->size()); dest->modify_currently_unchoked(base->unchoked()->size()); } // // Heuristics: // static void choke_manager_allocate_slots(choke_queue::iterator first, choke_queue::iterator last, uint32_t max, const uint32_t* weights, choke_queue::target_type* target) { // Sorting the connections from the lowest to highest value. // TODO: std::sort(first, last, choke_manager_less); // 'weightTotal' only contains the weight of targets that have // connections to unchoke. When all connections are in a group are // to be unchoked, then the group's weight is removed. uint32_t weightTotal = 0; uint32_t unchoke = max; target[0].second = first; for (uint32_t i = 0; i < choke_queue::order_max_size; i++) { target[i].first = 0; target[i + 1].second = std::find_if(target[i].second, last, [i](auto& v) { return (i * choke_queue::order_base + (choke_queue::order_base - 1)) < v.weight; }); if (std::distance(target[i].second, target[i + 1].second) != 0) weightTotal += weights[i]; } // Spread available unchoke slots as long as we can give everyone an // equal share. while (weightTotal != 0 && unchoke / weightTotal > 0) { uint32_t base = unchoke / weightTotal; for (uint32_t itr = 0; itr < choke_queue::order_max_size; itr++) { uint32_t s = std::distance(target[itr].second, target[itr + 1].second); if (weights[itr] == 0 || target[itr].first >= s) continue; uint32_t u = std::min(s - target[itr].first, base * weights[itr]); unchoke -= u; target[itr].first += u; if (target[itr].first >= s) weightTotal -= weights[itr]; } } // Spread the remainder starting from a random position based on the // total weight. This will ensure that aggregated over time we // spread the unchokes equally according to the weight table. if (weightTotal != 0 && unchoke != 0) { uint32_t start = ::random() % weightTotal; unsigned int itr = 0; for ( ; ; itr++) { uint32_t s = std::distance(target[itr].second, target[itr + 1].second); if (weights[itr] == 0 || target[itr].first >= s) continue; if (start < weights[itr]) break; start -= weights[itr]; } for ( ; weightTotal != 0 && unchoke != 0; itr = (itr + 1) % choke_queue::order_max_size) { uint32_t s = std::distance(target[itr].second, target[itr + 1].second); if (weights[itr] == 0 || target[itr].first >= s) continue; uint32_t u = std::min({unchoke, s - target[itr].first, weights[itr] - start}); start = 0; unchoke -= u; target[itr].first += u; if (target[itr].first >= s) weightTotal -= weights[itr]; } } } template static bool range_is_contained(Itr first, Itr last, Itr lower_bound, Itr upper_bound) { return first >= lower_bound && last <= upper_bound && first <= last; } uint32_t choke_queue::adjust_choke_range(iterator first, iterator last, container_type* src_container, container_type* dest_container, uint32_t max, bool is_choke) { target_type target[order_max_size + 1]; if (is_choke) { // TODO: m_heuristics_list[m_heuristics].slot_choke_weight(first, last); choke_manager_allocate_slots(first, last, max, m_heuristics_list[m_heuristics].choke_weight, target); } else { // m_heuristics_list[m_heuristics].slot_unchoke_weight(first, last); choke_manager_allocate_slots(first, last, max, m_heuristics_list[m_heuristics].unchoke_weight, target); } if (lt_log_is_valid(LOG_INSTRUMENTATION_CHOKE)) { for (uint32_t i = 0; i < choke_queue::order_max_size; i++) lt_log_print(LOG_INSTRUMENTATION_CHOKE, "%p %i %s %u %u %zd", this, 0, //lf->last_update(), (const char*)"unchoke" + 2*is_choke, i, target[i].first, std::distance(target[i].second, target[i + 1].second)); } // Now do the actual unchoking. uint32_t count = 0; uint32_t skipped = 0; for (target_type* itr = target + order_max_size; itr != target; itr--) { uint32_t order_size = std::distance((itr - 1)->second, itr->second); uint32_t order_remaining = order_size - (itr - 1)->first; if ((itr - 1)->first > order_size) throw internal_error("choke_queue::adjust_choke_range(...) itr->first > std::distance((itr - 1)->second, itr->second)."); (itr - 1)->first += std::min(skipped, order_remaining); skipped -= std::min(skipped, order_remaining); auto first_adjust = itr->second - (itr - 1)->first; auto last_adjust = itr->second; if (!range_is_contained(first_adjust, last_adjust, src_container->begin(), src_container->end())) throw internal_error("choke_queue::adjust_choke_range(...) bad iterator range."); // We start by unchoking the highest priority in this group, and // if we find any peers we can't choke/unchoke we'll move them to // the last spot in the container and decrement 'last_adjust'. auto itr_adjust = last_adjust; while (itr_adjust != first_adjust) { itr_adjust--; // if (!is_choke && !should_connection_unchoke(this, itr_adjust->first)) { // Swap with end and continue if not done with group. Count how many? // std::iter_swap(itr_adjust, --last_adjust); // if (first_adjust == (itr - 1)->second) // skipped++; // else // first_adjust--; // continue; // } m_slotConnection(itr_adjust->connection, is_choke); count++; lt_log_print(LOG_INSTRUMENTATION_CHOKE, "%p %i %s %p %X %llu %llu", this, 0, //lf->last_update(), (const char*)"unchoke" + 2*is_choke, itr_adjust->connection, itr_adjust->weight, (long long unsigned int)itr_adjust->connection->up_rate()->rate(), (long long unsigned int)itr_adjust->connection->down_rate()->rate()); } // The 'target' iterators remain valid after erase since we're // removing them in reverse order. dest_container->insert(dest_container->end(), first_adjust, last_adjust); src_container->erase(first_adjust, last_adjust); } if (count > max) throw internal_error("choke_queue::adjust_choke_range(...) count > max."); return count; } // Note that these algorithms fail if the rate >= 2^30. // Need to add the recently unchoked check here? static void calculate_upload_choke(choke_queue::iterator first, choke_queue::iterator last) { while (first != last) { // Very crude version for now. // // This needs to give more weight to peers that haven't had time to unchoke us. uint32_t downloadRate = first->connection->peer_chunks()->download_throttle()->rate()->rate() / 16; first->weight = choke_queue::order_base - 1 - downloadRate; first++; } } static void calculate_upload_unchoke(choke_queue::iterator first, choke_queue::iterator last) { while (first != last) { if (first->connection->is_down_local_unchoked()) { uint32_t downloadRate = first->connection->peer_chunks()->download_throttle()->rate()->rate() / 16; // If the peer transmits at less than 1KB, we should consider it // to be a rather stingy peer, and should look for new ones. if (downloadRate < 2048 / 16) first->weight = downloadRate; else first->weight = 3 * choke_queue::order_base + downloadRate; } else { // This will be our optimistic unchoke queue, should be // semi-random. Give lower weights to known stingy peers. int order = 1 + first->connection->peer_info()->is_preferred(); first->weight = order * choke_queue::order_base + ::random() % (1 << 10); } first++; } } // Improved heuristics intended for seeding. static void calculate_upload_choke_seed(choke_queue::iterator first, choke_queue::iterator last) { while (first != last) { int order = 1; // + first->connection->peer_info()->is_preferred(); uint32_t upload_rate = first->connection->peer_chunks()->upload_throttle()->rate()->rate() / 16; first->weight = order * choke_queue::order_base - 1 - upload_rate; first++; } } static void calculate_upload_unchoke_seed(choke_queue::iterator first, choke_queue::iterator last) { while (first != last) { int order = first->connection->peer_info()->is_preferred(); first->weight = order * choke_queue::order_base + ::random() % (1 << 10); first++; } } // // New leeching choke algorithm: // // Order 0: Normal // Order 1: No choking of newly unchoked peers. static void calculate_choke_upload_leech_experimental(choke_queue::iterator first, choke_queue::iterator last) { while (first != last) { // Don't choke a peer that hasn't had time to unchoke us. if (first->connection->up_choke()->time_last_choke() + 50s > this_thread::cached_time()) { first->weight = 1 * choke_queue::order_base; first++; continue; } // Preferred peers will get 4 times higher weight. int multiplier = 1 + 3 * first->connection->peer_info()->is_preferred(); uint32_t download_rate = first->connection->peer_chunks()->download_throttle()->rate()->rate() / 64; uint32_t upload_rate = first->connection->peer_chunks()->upload_throttle()->rate()->rate() / (64 * 4); first->weight = choke_queue::order_base - 1 - (download_rate + upload_rate) * multiplier; first++; } } // Order 0: Optimistic unchokes. // Order 1: Normal unchokes. static void calculate_unchoke_upload_leech_experimental(choke_queue::iterator first, choke_queue::iterator last) { while (first != last) { // Consider checking for is_down_remote_unchoked(). if (first->connection->is_down_local_unchoked()) { int multiplier = 1 + 3 * first->connection->peer_info()->is_preferred(); uint32_t download_rate = first->connection->peer_chunks()->download_throttle()->rate()->rate() / 64; first->weight = choke_queue::order_base + download_rate * multiplier; } else { // This will be our optimistic unchoke queue, should be // semi-random. Give lower weights to known stingy peers and // higher weight for preferred ones. int base = (1 << 10); if (first->connection->peer_info()->is_preferred()) base *= 4; // else if () // base /= 8; first->weight = ::random() % base; } first++; } } // Fix this, but for now just use something simple. static void calculate_download_choke(choke_queue::iterator first, choke_queue::iterator last) { while (first != last) { // Very crude version for now. uint32_t downloadRate = first->connection->peer_chunks()->download_throttle()->rate()->rate() / 16; first->weight = choke_queue::order_base - 1 - downloadRate; first++; } } static void calculate_download_unchoke(choke_queue::iterator first, choke_queue::iterator last) { while (first != last) { // Very crude version for now. uint32_t downloadRate = first->connection->peer_chunks()->download_throttle()->rate()->rate() / 16; first->weight = downloadRate; first++; } } choke_queue::heuristics_type choke_queue::m_heuristics_list[HEURISTICS_MAX_SIZE] = { { &calculate_upload_choke, &calculate_upload_unchoke, { 1, 1, 1, 1 }, { 1, 3, 6, 9 } }, { &calculate_upload_choke_seed, &calculate_upload_unchoke_seed, { 1, 1, 1, 1 }, { 1, 3, 6, 9 } }, { &calculate_choke_upload_leech_experimental, &calculate_unchoke_upload_leech_experimental, { 32, 1, 1, 1 }, { 1, 6, 8, 16 } }, { &calculate_download_choke, &calculate_download_unchoke, { 1, 1, 1, 1 }, { 1, 1, 1, 1 } }, }; } // namespace torrent libtorrent-0.16.11/src/torrent/download/resource_manager.h0000644000000000000000000001434215175073411017270 // libTorrent - BitTorrent library // Copyright (C) 2005-2011, Jari Sundell // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // In addition, as a special exception, the copyright holders give // permission to link the code of portions of this program with the // OpenSSL library under certain conditions as described in each // individual source file, and distribute linked combinations // including the two. // // You must obey the GNU General Public License in all respects for // all of the code used other than OpenSSL. If you modify file(s) // with this exception, you may extend this exception to your version // of the file(s), but you are not obligated to do so. If you do not // wish to do so, delete this exception statement from your version. // If you delete this exception statement from all source files in the // program, then also delete it here. // // Contact: Jari Sundell // // Skomakerveien 33 // 3185 Skoppum, NORWAY #ifndef LIBTORRENT_PEER_RESOURCE_MANAGER_H #define LIBTORRENT_PEER_RESOURCE_MANAGER_H #include #include #include #include namespace torrent { // This class will handle the division of various resources like // uploads. For now the weight is equal to the value of the priority. // // Although the ConnectionManager class keeps a tally of open sockets, // we still need to balance them across the different downloads so // ResourceManager will also keep track of those. // // Add unlimited handling later. class choke_group; class DownloadMain; class Rate; class ResourceManager; class LIBTORRENT_EXPORT resource_manager_entry { public: friend class ResourceManager; resource_manager_entry(DownloadMain* d = NULL, uint16_t pri = 0, uint16_t grp = 0) : m_download(d), m_priority(pri), m_group(grp) {} DownloadMain* download() { return m_download; } const DownloadMain* c_download() const { return m_download; } uint16_t priority() const { return m_priority; } uint16_t group() const { return m_group; } const Rate* up_rate() const; const Rate* down_rate() const; protected: void set_priority(uint16_t pri) { m_priority = pri; } void set_group(uint16_t grp) { m_group = grp; } private: DownloadMain* m_download; uint16_t m_priority; uint16_t m_group; }; class LIBTORRENT_EXPORT ResourceManager : private std::vector, private std::vector { public: using base_type = std::vector; using choke_base_type = std::vector; using value_type = base_type::value_type; using iterator = base_type::iterator; using group_iterator = choke_base_type::iterator; using base_type::begin; using base_type::end; using base_type::size; using base_type::capacity; ResourceManager() = default; ~ResourceManager(); void insert(DownloadMain* d, uint16_t priority) { insert(value_type(d, priority)); } void erase(DownloadMain* d); void push_group(const std::string& name); iterator find(const DownloadMain* d); iterator find_throw(const DownloadMain* d); iterator find_group_end(uint16_t group); unsigned int group_size() const { return choke_base_type::size(); } choke_group* group_back() { return choke_base_type::back(); } choke_group* group_at(uint16_t grp); choke_group* group_at_name(const std::string& name); int group_index_of(const std::string& name); group_iterator group_begin() { return choke_base_type::begin(); } group_iterator group_end() { return choke_base_type::end(); } resource_manager_entry& entry_at(const DownloadMain* d) { return *find_throw(d); } static void set_priority(iterator itr, uint16_t pri); void set_group(iterator itr, uint16_t grp); // When setting this, make sure you choke peers, else change // receive_can_unchoke. unsigned int currently_upload_unchoked() const { return m_currentlyUploadUnchoked; } unsigned int currently_download_unchoked() const { return m_currentlyDownloadUnchoked; } unsigned int max_upload_unchoked() const { return m_maxUploadUnchoked; } unsigned int max_download_unchoked() const { return m_maxDownloadUnchoked; } void set_max_upload_unchoked(unsigned int m); void set_max_download_unchoked(unsigned int m); void receive_upload_unchoke(int num); void receive_download_unchoke(int num); int retrieve_upload_can_unchoke() const; int retrieve_download_can_unchoke() const; void receive_tick(); private: ResourceManager(const ResourceManager&) = delete; ResourceManager& operator=(const ResourceManager&) = delete; iterator insert(const resource_manager_entry& entry); void update_group_iterators(); void validate_group_iterators(); unsigned int total_weight() const; int balance_unchoked(unsigned int weight, unsigned int max_unchoked, bool is_up); unsigned int m_currentlyUploadUnchoked{0}; unsigned int m_currentlyDownloadUnchoked{0}; unsigned int m_maxUploadUnchoked{0}; unsigned int m_maxDownloadUnchoked{0}; }; } // namespace torrent #endif libtorrent-0.16.11/src/torrent/download/choke_group.cc0000644000000000000000000000076115175073411016412 #include "config.h" #include "choke_group.h" #include #include "download/download_main.h" #include "download_info.h" namespace torrent { uint64_t choke_group::up_rate() const { return std::accumulate(m_first, m_last, uint64_t{0}, [](uint64_t i, auto r) { return i + r.up_rate()->rate(); }); } uint64_t choke_group::down_rate() const { return std::accumulate(m_first, m_last, uint64_t{0}, [](uint64_t i, auto r) { return i + r.down_rate()->rate(); }); } } // namespace torrent libtorrent-0.16.11/src/torrent/path.cc0000644000000000000000000000436115175073411013232 // libTorrent - BitTorrent library // Copyright (C) 2005-2011, Jari Sundell // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // In addition, as a special exception, the copyright holders give // permission to link the code of portions of this program with the // OpenSSL library under certain conditions as described in each // individual source file, and distribute linked combinations // including the two. // // You must obey the GNU General Public License in all respects for // all of the code used other than OpenSSL. If you modify file(s) // with this exception, you may extend this exception to your version // of the file(s), but you are not obligated to do so. If you do not // wish to do so, delete this exception statement from your version. // If you delete this exception statement from all source files in the // program, then also delete it here. // // Contact: Jari Sundell // // Skomakerveien 33 // 3185 Skoppum, NORWAY #include "config.h" #include #include "path.h" namespace torrent { void Path::insert_path(iterator pos, const std::string& path) { std::string::const_iterator first = path.begin(); std::string::const_iterator last; while (first != path.end()) { pos = insert(pos, std::string(first, (last = std::find(first, path.end(), '/')))); if (last == path.end()) return; first = last; first++; } } std::string Path::as_string() const { if (empty()) return std::string(); std::string s; for (const auto& c : *this) { s += '/'; s += c; } return s; } } // namespace torrent libtorrent-0.16.11/src/torrent/chunk_manager.h0000644000000000000000000001250315175073411014737 #ifndef LIBTORRENT_CHUNK_MANAGER_H #define LIBTORRENT_CHUNK_MANAGER_H #include #include namespace torrent { // TODO: Currently all chunk lists are inserted, despite the download // not being open/active. class LIBTORRENT_EXPORT ChunkManager : private std::vector { public: using base_type = std::vector; using size_type = uint32_t; using base_type::iterator; using base_type::reverse_iterator; using base_type::const_iterator; using base_type::begin; using base_type::end; using base_type::size; using base_type::empty; ChunkManager(); ~ChunkManager(); uint64_t memory_usage() const { return m_memoryUsage; } uint64_t sync_queue_memory_usage() const; uint32_t memory_block_count() const { return m_memoryBlockCount; } uint32_t sync_queue_size() const; // Should we allow the client to reserve some memory? // The client should set this automatically if ulimit is set. uint64_t max_memory_usage() const { return m_maxMemoryUsage; } void set_max_memory_usage(uint64_t bytes) { m_maxMemoryUsage = bytes; } // Estimate the max memory usage possible, capped at 1GB. static uint64_t estimate_max_memory_usage(); uint64_t safe_free_diskspace() const; bool safe_sync() const { return m_safeSync; } void set_safe_sync(uint32_t state) { m_safeSync = state; } // Set the interval to wait after the last write to a chunk before // trying to sync it. By not forcing a sync too early it should give // the kernel an oppertunity to sync at its convenience. uint32_t timeout_sync() const { return m_timeoutSync; } void set_timeout_sync(uint32_t seconds) { m_timeoutSync = seconds; } uint32_t timeout_safe_sync() const { return m_timeoutSafeSync; } void set_timeout_safe_sync(uint32_t seconds) { m_timeoutSafeSync = seconds; } // Set to 0 to disable preloading. // // How the value is used is yet to be determined, but it won't be // able to use actual requests in the request queue as we can easily // stay ahead of it causing preloading to fail. uint32_t preload_type() const { return m_preloadType; } void set_preload_type(uint32_t t) { m_preloadType = t; } uint32_t preload_min_size() const { return m_preloadMinSize; } void set_preload_min_size(uint32_t bytes) { m_preloadMinSize = bytes; } // Required rate before attempting to preload chunk, per whole // megabyte of chunk size. uint32_t preload_required_rate() const { return m_preloadRequiredRate; } void set_preload_required_rate(uint32_t bytes) { m_preloadRequiredRate = bytes; } void insert(ChunkList* chunkList); void erase(ChunkList* chunkList); // The client may use these functions to affect the library's memory // usage by indicating how much it uses. This shouldn't really be // nessesary unless the client maps large amounts of memory. // // If the caller finds out the allocated memory quota isn't needed // due to e.g. other errors then 'deallocate_unused' must be called // within the context of the original 'allocate' caller in order to // properly be reflected when logging. // // The primary user of these functions is ChunkList. static constexpr int allocate_revert_log = (1 << 0); static constexpr int allocate_dont_log = (1 << 1); bool allocate(uint32_t size, int flags = 0); void deallocate(uint32_t size, int flags = 0); void try_free_memory(uint64_t size); void periodic_sync(); // Not sure if I wnt these here. Consider implementing a generic // statistics API. uint32_t stats_preloaded() const { return m_statsPreloaded; } void inc_stats_preloaded() { m_statsPreloaded++; } uint32_t stats_not_preloaded() const { return m_statsNotPreloaded; } void inc_stats_not_preloaded() { m_statsNotPreloaded++; } private: ChunkManager(const ChunkManager&) = delete; ChunkManager& operator=(const ChunkManager&) = delete; void sync_all(int flags, uint64_t target) LIBTORRENT_NO_EXPORT; uint64_t m_memoryUsage{0}; // 1/5 of the available memory should be enough for the client. If // the client really requires alot more memory it should call this // itself. uint64_t m_maxMemoryUsage{(estimate_max_memory_usage() * 4) / 5}; uint32_t m_memoryBlockCount{0}; bool m_safeSync{false}; uint32_t m_timeoutSync{600}; uint32_t m_timeoutSafeSync{900}; uint32_t m_preloadType{0}; uint32_t m_preloadMinSize{256 << 10}; uint32_t m_preloadRequiredRate{5 << 10}; uint32_t m_statsPreloaded{0}; uint32_t m_statsNotPreloaded{0}; int32_t m_timerStarved{0}; size_type m_lastFreed{0}; }; } // namespace torrent #endif libtorrent-0.16.11/src/torrent/object_stream.cc0000644000000000000000000005725615175073411015132 #include "config.h" #include "torrent/object_stream.h" #include #include #include #include #include "torrent/object.h" #include "torrent/object_static_map.h" #include "utils/functional.h" #include "utils/sha1.h" namespace torrent { static bool object_read_string(std::istream* input, std::string& str) { uint32_t size; *input >> size; if (input->fail() || input->get() != ':') return false; try { str.resize(size); } catch (const std::length_error&) { return false; } for (auto& c : str) { if (!input->good()) break; c = input->get(); } return !input->fail(); } static const char* object_read_bencode_c_value(const char* first, const char* last, int64_t& value) { if (first == last) return first; bool neg = false; if (*first == '-') { // Don't allow '-0', or '-' followed by non-numeral. if ((first + 1) == last || *(first + 1) <= '0' || *(first + 1) > '9') return first; neg = true; first++; } value = 0; while (first != last && *first >= '0' && *first <= '9') value = value * 10 + (*first++ - '0'); if (neg) value = -value; return first; } raw_string object_read_bencode_c_string(const char* first, const char* last) { // Set the most-significant bit so that if there are no numbers in // the input it will fail the length check, while "0" will shift the // bit out. unsigned int length = 0x1U << (std::numeric_limits::digits - 1); while (first != last && *first >= '0' && *first <= '9') length = length * 10 + (*first++ - '0'); if (length + 1 > static_cast(std::distance(first, last)) || length + 1 == 0 || *first++ != ':') throw torrent::bencode_error("Invalid bencode data."); return raw_string(first, length); } // Could consider making this non-recursive, but they seldomly are // deep enough to make that worth-while. void object_read_bencode(std::istream* input, Object* object, uint32_t depth) { int c; switch ((c = input->peek())) { case 'i': input->get(); *object = Object::create_value(); *input >> object->as_value(); if (input->get() != 'e') break; return; case 'l': input->get(); *object = Object::create_list(); if (++depth >= 1024) break; while (input->good()) { if (input->peek() == 'e') { input->get(); return; } auto& obj = object->as_list().emplace_back(); object_read_bencode(input, &obj, depth); // The unordered flag is inherited also from list elements who // have been marked as unordered, though e.g. unordered strings // in the list itself does not cause this flag to be set. if (obj.flags() & Object::flag_unordered) object->set_internal_flags(Object::flag_unordered); } break; case 'd': { input->get(); *object = Object::create_map(); if (++depth >= 1024) break; Object::string_type last; while (input->good()) { if (input->peek() == 'e') { input->get(); return; } Object::string_type str; if (!object_read_string(input, str)) break; // We do not set flag_unordered if the first key was zero // length, while multiple zero length keys will trigger the // unordered_flag. if (str <= last && !object->as_map().empty()) object->set_internal_flags(Object::flag_unordered); Object* value = &object->as_map()[str]; object_read_bencode(input, value, depth); if (value->flags() & Object::flag_unordered) object->set_internal_flags(Object::flag_unordered); str.swap(last); } break; } default: if (c >= '0' && c <= '9') { *object = Object::create_string(); if (object_read_string(input, object->as_string())) return; } break; } input->setstate(std::istream::failbit); object->clear(); } const char* object_read_bencode_c(const char* first, const char* last, Object* object, uint32_t depth) { if (first == last) throw torrent::bencode_error("Invalid bencode data."); switch (*first) { case 'i': *object = Object::create_value(); first = object_read_bencode_c_value(first + 1, last, object->as_value()); if (first == last || *first++ != 'e') break; return first; case 'l': if (++depth >= 1024) break; first++; *object = Object::create_list(); while (first != last) { if (*first == 'e') return first + 1; auto& obj = object->as_list().emplace_back(); first = object_read_bencode_c(first, last, &obj, depth); // The unordered flag is inherited also from list elements who // have been marked as unordered, though e.g. unordered strings // in the list itself does not cause this flag to be set. if (obj.flags() & Object::flag_unordered) object->set_internal_flags(Object::flag_unordered); } break; case 'd': { if (++depth >= 1024) break; first++; *object = Object::create_map(); Object::string_type prev; while (first != last) { if (*first == 'e') return first + 1; raw_string raw_str = object_read_bencode_c_string(first, last); first = raw_str.end(); Object::string_type str = raw_str.as_string(); // We do not set flag_unordered if the first key was zero // length, while multiple zero length keys will trigger the // unordered_flag. if (str <= prev && !object->as_map().empty()) object->set_internal_flags(Object::flag_unordered); Object* value = &object->as_map()[str]; first = object_read_bencode_c(first, last, value, depth); if (value->flags() & Object::flag_unordered) object->set_internal_flags(Object::flag_unordered); str.swap(prev); } break; } default: if (*first < '0' || *first > '9') throw torrent::bencode_error("Invalid bencode data."); raw_string raw_str = object_read_bencode_c_string(first, last); *object = raw_str.as_string(); return raw_str.end(); } object->clear(); throw torrent::bencode_error("Invalid bencode data."); } static bool object_is_not_digit(char c) { return c < '0' || c > '9'; } const char* object_read_bencode_skip_c(const char* first, const char* last) { char stack[128] = { 0 }; char* stack_itr = stack; while (first != last) { if (*first == 'e') { if (stack_itr-- == stack) throw torrent::bencode_error("Invalid bencode data."); first++; if (stack_itr == stack) return first; continue; } // Currently reading a dictionary, so ensure the first entry is a // string. if (*stack_itr && (first = object_read_bencode_c_string(first, last).end()) == last) break; switch (*first) { case 'i': if (first != last && *++first == '-') { if (first != last && *++first == '0') throw torrent::bencode_error("Invalid bencode data."); } first = std::find_if(first, last, &object_is_not_digit); if (first == last || *first++ != 'e') throw torrent::bencode_error("Invalid bencode data."); break; case 'l': case 'd': if (++stack_itr == stack + 128) throw torrent::bencode_error("Invalid bencode data."); *stack_itr = (*first++ == 'd'); continue; default: first = object_read_bencode_c_string(first, last).end(); } if (stack_itr == stack) return first; } throw torrent::bencode_error("Invalid bencode data."); } static const char* object_read_bencode_raw_c(const char* first, const char* last, torrent::Object* object, char type) { const char* tmp = first; first = object_read_bencode_skip_c(first, last); raw_bencode obj = raw_bencode(tmp, std::distance(tmp, first)); // if (obj.is_empty()) // throw torrent::bencode_error("Invalid bencode data."); switch (type) { case 'S': if (obj.is_raw_string()) *object = obj.as_raw_string(); break; case 'L': if (obj.is_raw_list()) *object = obj.as_raw_list(); break; case 'M': if (obj.is_raw_map()) *object = obj.as_raw_map(); break; default: *object = obj; } return first; } // Would be nice to have a straight stream to hash conversion. std::string object_sha1(const Object* object) { Sha1 sha; char buffer[1024]; sha.init(); object_write_bencode_c(&object_write_to_sha1, &sha, object_buffer_t(buffer, buffer + 1024), object); sha.final_c(buffer); return std::string(buffer, 20); } std::istream& operator >> (std::istream& input, Object& object) { std::locale locale = input.imbue(std::locale::classic()); object.clear(); object_read_bencode(&input, &object); input.imbue(locale); return input; } std::ostream& operator << (std::ostream& output, const Object& object) { object_write_bencode(&output, &object); return output; } struct object_write_data_t { object_write_t writeFunc; void* data; object_buffer_t buffer; char* pos; }; static void object_write_bencode_c_string(object_write_data_t* output, const char* srcData, uint32_t srcLength) { while (srcLength != 0) { uint32_t len = std::min(srcLength, std::distance(output->pos, output->buffer.second)); std::memcpy(output->pos, srcData, len); output->pos += len; if (output->pos == output->buffer.second) { output->buffer = output->writeFunc(output->data, output->buffer); output->pos = output->buffer.first; if (output->buffer.first == output->buffer.second) return; } srcData += len; srcLength -= len; } } static void object_write_bencode_c_char(object_write_data_t* output, char src) { if (output->pos == output->buffer.second) { output->buffer = output->writeFunc(output->data, output->buffer); output->pos = output->buffer.first; if (output->buffer.first == output->buffer.second) return; } *output->pos++ = src; } // A new wheel. Look, how shiny and new. static void object_write_bencode_c_value(object_write_data_t* output, int64_t src) { if (src == 0) return object_write_bencode_c_char(output, '0'); if (src < 0) { object_write_bencode_c_char(output, '-'); src = -src; } char buffer[20]; char* first = buffer + 20; // We don't need locale support, so just do this directly. while (src != 0) { *--first = '0' + src % 10; src /= 10; } object_write_bencode_c_string(output, first, 20 - std::distance(buffer, first)); } static void object_write_bencode_c_obj_value(object_write_data_t* output, int64_t value) { object_write_bencode_c_char(output, 'i'); object_write_bencode_c_value(output, value); object_write_bencode_c_char(output, 'e'); } static void object_write_bencode_c_obj_string(object_write_data_t* output, const char* data, uint32_t size) { object_write_bencode_c_value(output, size); object_write_bencode_c_char(output, ':'); object_write_bencode_c_string(output, data, size); } static void object_write_bencode_c_obj_string(object_write_data_t* output, const std::string& str) { object_write_bencode_c_obj_string(output, str.c_str(), str.size()); } static void object_write_bencode_c_object(object_write_data_t* output, const Object* object, uint32_t skip_mask) { switch (object->type()) { case Object::TYPE_NONE: break; case Object::TYPE_RAW_BENCODE: { raw_bencode raw = object->as_raw_bencode(); object_write_bencode_c_string(output, raw.begin(), raw.size()); break; } case Object::TYPE_RAW_STRING: { raw_string raw = object->as_raw_string(); object_write_bencode_c_value(output, raw.size()); object_write_bencode_c_char(output, ':'); object_write_bencode_c_string(output, raw.begin(), raw.size()); break; } case Object::TYPE_RAW_LIST: { raw_list raw = object->as_raw_list(); object_write_bencode_c_char(output, 'l'); object_write_bencode_c_string(output, raw.begin(), raw.size()); object_write_bencode_c_char(output, 'e'); break; } case Object::TYPE_RAW_MAP: { raw_map raw = object->as_raw_map(); object_write_bencode_c_char(output, 'd'); object_write_bencode_c_string(output, raw.begin(), raw.size()); object_write_bencode_c_char(output, 'e'); break; } case Object::TYPE_VALUE: object_write_bencode_c_obj_value(output, object->as_value()); break; case Object::TYPE_STRING: object_write_bencode_c_obj_string(output, object->as_string()); break; case Object::TYPE_LIST: object_write_bencode_c_char(output, 'l'); for (const auto& list : object->as_list()) { if (list.is_empty() || list.flags() & skip_mask) continue; object_write_bencode_c_object(output, &list, skip_mask); } object_write_bencode_c_char(output, 'e'); break; case Object::TYPE_MAP: object_write_bencode_c_char(output, 'd'); for (const auto& map : object->as_map()) { if (map.second.is_empty() || map.second.flags() & skip_mask) continue; object_write_bencode_c_obj_string(output, map.first); object_write_bencode_c_object(output, &map.second, skip_mask); } object_write_bencode_c_char(output, 'e'); break; case Object::TYPE_DICT_KEY: throw torrent::bencode_error("Cannot bencode internal dict_key type."); } } void object_write_bencode(std::ostream* output, const Object* object, uint32_t skip_mask) { char buffer[1024]; object_write_bencode_c(&object_write_to_stream, output, object_buffer_t(buffer, buffer + 1024), object, skip_mask); } object_buffer_t object_write_bencode(char* first, char* last, const Object* object, uint32_t skip_mask) { object_buffer_t buffer = object_buffer_t(first, last); return object_write_bencode_c(&object_write_to_buffer, &buffer, buffer, object, skip_mask); } object_buffer_t object_write_bencode_c(object_write_t writeFunc, void* data, object_buffer_t buffer, const Object* object, uint32_t skip_mask) { object_write_data_t output; output.writeFunc = writeFunc; output.data = data; output.buffer = buffer; output.pos = buffer.first; if (!(object->flags() & skip_mask)) object_write_bencode_c_object(&output, object, skip_mask); // Don't flush the buffer. if (output.pos == output.buffer.first) return output.buffer; return output.writeFunc(output.data, object_buffer_t(output.buffer.first, output.pos)); } object_buffer_t object_write_to_buffer([[maybe_unused]] void* data, object_buffer_t buffer) { if (buffer.first == buffer.second) throw internal_error("object_write_to_buffer(...) buffer overflow."); // Hmm... this does something weird... return object_buffer_t(buffer.second, buffer.second); } object_buffer_t object_write_to_sha1(void* data, object_buffer_t buffer) { static_cast(data)->update(buffer.first, std::distance(buffer.first, buffer.second)); return buffer; } object_buffer_t object_write_to_stream(void* data, object_buffer_t buffer) { static_cast(data)->write(buffer.first, std::distance(buffer.first, buffer.second)); if (static_cast(data)->bad()) return object_buffer_t(buffer.first, buffer.first); return buffer; } object_buffer_t object_write_to_size(void* data, object_buffer_t buffer) { *static_cast(data) += std::distance(buffer.first, buffer.second); return buffer; } // // static_map operations: // const char* static_map_read_bencode_c(const char* first, const char* last, static_map_entry_type* entry_values, const static_map_mapping_type* first_key, const static_map_mapping_type* last_key) { // Temp hack... validate that we got valid bencode data... // { // torrent::Object obj; // if (object_read_bencode_c(first, last, &obj) != last) { // std::string escaped = copy_escape_html(first, last); // char buffer[1024]; // sprintf(buffer, "Verified wrong, %u, '%u', '%s'.", std::distance(first, last), (unsigned int)*first, escaped.c_str()); // throw torrent::internal_error("Invalid bencode data."); // } // } if (first == last || *first++ != 'd') throw torrent::bencode_error("Invalid bencode data."); static_map_stack_type stack[8]; static_map_stack_type* stack_itr = stack; stack_itr->clear(); char current_key[static_map_mapping_type::max_key_size + 2] = ""; while (first != last) { // End a dictionary/list or the whole stream. if (*first == 'e') { first++; if (stack_itr == stack) return first; stack_itr--; continue; } raw_string raw_key = object_read_bencode_c_string(first, last); first = raw_key.end(); // Optimze this buy directly copying into 'current_key'. // // The max length of 'current_key' is one char more than the // mapping key so any bencode which exceeds that will always fail // to find a match. if (raw_key.size() >= static_map_mapping_type::max_key_size - stack_itr->next_key) { first = object_read_bencode_skip_c(first, last); continue; } memcpy(current_key + stack_itr->next_key, raw_key.data(), raw_key.size()); current_key[stack_itr->next_key + raw_key.size()] = '\0'; // Locate the right key. Optimize this by remembering previous // position... static_map_key_search_result key_search = find_key_match(first_key, last_key, current_key); // We're not interest in this object, skip it. if (key_search.second == 0) { first = object_read_bencode_skip_c(first, last); continue; } // Check if we're interested in any dictionaries/lists entries // under this key. // // Note that 'find_key_match' only returns 'key_search.second != // 0' for keys where the next characters are '\0', '::' or '[]'. switch (key_search.first->key[key_search.second]) { case '\0': first = object_read_bencode_c(first, last, &entry_values[key_search.first->index].object); first_key = key_search.first + 1; break; case '*': first = object_read_bencode_raw_c(first, last, &entry_values[key_search.first->index].object, key_search.first->key[key_search.second + 1]); first_key = key_search.first + 1; break; case ':': if (first == last) break; // The bencode object isn't a list. This should either skip it // or produce an error. if (*first++ != 'd') { first = object_read_bencode_skip_c(first - 1, last); break; } stack_itr++; stack_itr->set_key_index((stack_itr - 1)->next_key, key_search.second, 2); current_key[key_search.second] = ':'; current_key[key_search.second + 1] = ':'; break; case '[': { if (first == last) break; // The bencode object isn't a list. This should either skip it // or produce an error. if (*first++ != 'l') { first = object_read_bencode_skip_c(first - 1, last); break; } first_key = key_search.first; while (first != last) { if (*first == 'e') { first++; break; } if (first_key->key[key_search.second + 2] == '*') { first = object_read_bencode_raw_c(first, last, &entry_values[first_key->index].object, key_search.first->key[key_search.second + 1]); } else { first = object_read_bencode_c(first, last, &entry_values[first_key->index].object); } if (++first_key == last_key || strcmp(first_key->key, (first_key - 1)->key) != 0) { while (first != last) { if (*first == 'e') { first++; break; } first = object_read_bencode_skip_c(first, last); } break; } } break; } default: throw internal_error("static_map_read_bencode_c: key_search.first->key[base] returned invalid character."); } } throw torrent::bencode_error("Invalid bencode data."); } static void static_map_write_bencode_c_values(object_write_data_t* output, const static_map_entry_type* entry_values, const static_map_mapping_type* first_key, const static_map_mapping_type* last_key) { const char* prev_key = NULL; static_map_stack_type stack[8]; static_map_stack_type* stack_itr = stack; stack_itr->clear(); object_write_bencode_c_char(output, 'd'); while (first_key != last_key) { if (entry_values[first_key->index].object.is_empty()) { first_key++; continue; } // Compare the keys to see if they are part of the same // dictionaries/lists. unsigned int base_size = ::utils::count_base(first_key->key, first_key->key + stack_itr->next_key, prev_key, prev_key + stack_itr->next_key); while (base_size < stack_itr->next_key) { object_write_bencode_c_char(output, 'e'); stack_itr--; } const char* key_begin = first_key->key + stack_itr->next_key; do { const char* key_end = first_key->find_key_end(key_begin); if (stack_itr->obj_type == Object::TYPE_MAP) object_write_bencode_c_obj_string(output, key_begin, std::distance(key_begin, key_end)); // Check if '::' or '[' were found... if (*key_end == ':' && *(key_end + 1) == ':') { (++stack_itr)->set_key_index(std::distance(first_key->key, key_begin), std::distance(first_key->key, key_end), 2); key_begin = key_end + 2; object_write_bencode_c_char(output, 'd'); continue; } // Handle "foo[]..." entries. We iterate once for each "foo[]" // found in the key list. if (*key_end == '[' && *(key_end + 1) == ']') { (++stack_itr)->set_key_index(std::distance(first_key->key, key_begin), std::distance(first_key->key, key_end), 2, Object::TYPE_LIST); key_begin = key_end + 2; object_write_bencode_c_char(output, 'l'); continue; } // We have a leaf object. if (*key_end != '\0' && *key_end != '*') throw internal_error("static_map_type key is invalid."); object_write_bencode_c_object(output, &entry_values[first_key->index].object, 0); break; } while (true); prev_key = (first_key++)->key; } do { object_write_bencode_c_char(output, 'e'); } while (stack_itr-- != stack); } object_buffer_t static_map_write_bencode_c_wrap(object_write_t writeFunc, void* data, object_buffer_t buffer, const static_map_entry_type* entry_values, const static_map_mapping_type* first_key, const static_map_mapping_type* last_key) { object_write_data_t output; output.writeFunc = writeFunc; output.data = data; output.buffer = buffer; output.pos = buffer.first; static_map_write_bencode_c_values(&output, entry_values, first_key, last_key); // DEBUG: Remove this. // { // torrent::Object obj; // if (object_read_bencode_c(output.buffer.first, output.pos, &obj) != output.pos) { // std::string escaped = copy_escape_html(output.buffer.first, output.pos); // //char buffer[1024]; // // sprintf(buffer, "Verified wrong, %u, '%u', '%s'.", std::distanescaped.c_str()); // throw torrent::internal_error("Invalid bencode data generated: '" + escaped + "'"); // } // } // Don't flush the buffer. if (output.pos == output.buffer.first) return output.buffer; return output.writeFunc(output.data, object_buffer_t(output.buffer.first, output.pos)); } } // namespace torrent libtorrent-0.16.11/src/torrent/object_stream.h0000644000000000000000000000770115175073411014762 #ifndef LIBTORRENT_OBJECT_STREAM_H #define LIBTORRENT_OBJECT_STREAM_H #include #include #include namespace torrent { class raw_string; std::string object_sha1(const Object* object) LIBTORRENT_EXPORT; raw_string object_read_bencode_c_string(const char* first, const char* last) LIBTORRENT_EXPORT; // Assumes the stream's locale has been set to POSIX or C. Max depth // is 1024, this ensures files consisting of only 'l' don't segfault // the client. void object_read_bencode(std::istream* input, Object* object, uint32_t depth = 0) LIBTORRENT_EXPORT; const char* object_read_bencode_c(const char* first, const char* last, Object* object, uint32_t depth = 0) LIBTORRENT_EXPORT; const char* object_read_bencode_skip_c(const char* first, const char* last) LIBTORRENT_EXPORT; std::istream& operator >> (std::istream& input, Object& object) LIBTORRENT_EXPORT; std::ostream& operator << (std::ostream& output, const Object& object) LIBTORRENT_EXPORT; // object_buffer_t contains the start and end of the buffer. using object_buffer_t = std::pair; using object_write_t = object_buffer_t (*)(void* data, object_buffer_t buffer); // Assumes the stream's locale has been set to POSIX or C. void object_write_bencode(std::ostream* output, const Object* object, uint32_t skip_mask = 0) LIBTORRENT_EXPORT; object_buffer_t object_write_bencode(char* first, char* last, const Object* object, uint32_t skip_mask = 0) LIBTORRENT_EXPORT; object_buffer_t object_write_bencode_c(object_write_t writeFunc, void* data, object_buffer_t buffer, const Object* object, uint32_t skip_mask = 0) LIBTORRENT_EXPORT; // To char buffer. 'data' is NULL. object_buffer_t object_write_to_buffer(void* data, object_buffer_t buffer) LIBTORRENT_EXPORT; object_buffer_t object_write_to_sha1(void* data, object_buffer_t buffer) LIBTORRENT_EXPORT; object_buffer_t object_write_to_stream(void* data, object_buffer_t buffer) LIBTORRENT_EXPORT; // Measures bencode size, 'data' is uint64_t*. object_buffer_t object_write_to_size(void* data, object_buffer_t buffer) LIBTORRENT_EXPORT; // // static_map operations: // template class static_map_type; struct static_map_mapping_type; struct static_map_entry_type; // Convert buffer to static key map. Inlined because we don't want // a separate wrapper function for each template argument. template inline const char* static_map_read_bencode(const char* first, const char* last, static_map_type& object) { return static_map_read_bencode_c(first, last, object.values(), object.keys, object.keys + object.size); } template inline object_buffer_t static_map_write_bencode_c(object_write_t writeFunc, void* data, object_buffer_t buffer, const static_map_type& object) { return static_map_write_bencode_c_wrap(writeFunc, data, buffer, object.values(), object.keys, object.keys + object.size); } const char* static_map_read_bencode_c(const char* first, const char* last, static_map_entry_type* entry_values, const static_map_mapping_type* first_key, const static_map_mapping_type* last_key) LIBTORRENT_EXPORT; object_buffer_t static_map_write_bencode_c_wrap(object_write_t writeFunc, void* data, object_buffer_t buffer, const static_map_entry_type* entry_values, const static_map_mapping_type* first_key, const static_map_mapping_type* last_key) LIBTORRENT_EXPORT; } // namespace torrent #endif libtorrent-0.16.11/src/protocol/0000755000000000000000000000000015175073434012214 5libtorrent-0.16.11/src/protocol/extensions.cc0000644000000000000000000002550415175073411014643 #include "config.h" #include "extensions.h" #include #include #include "download/download_main.h" #include "download/download_wrapper.h" #include "manager.h" #include "protocol/peer_connection_base.h" #include "torrent/connection_manager.h" #include "torrent/download/download_manager.h" #include "torrent/download_info.h" #include "torrent/object_stream.h" #include "torrent/net/network_config.h" #include "torrent/net/socket_address.h" #include "torrent/peer/connection_list.h" #include "torrent/peer/peer_info.h" namespace torrent { template <> const ExtHandshakeMessage::key_list_type ExtHandshakeMessage::keys = { { key_e, "e" }, { key_m_utMetadata, "m::ut_metadata" }, { key_m_utPex, "m::ut_pex" }, { key_metadataSize, "metadata_size" }, { key_p, "p" }, { key_reqq, "reqq" }, { key_v, "v" }, }; template <> const ExtPEXMessage::key_list_type ExtPEXMessage::keys = { { key_pex_added, "added*S" }, }; // DEBUG: Add type info. template <> const ExtMetadataMessage::key_list_type ExtMetadataMessage::keys = { { key_msgType, "msg_type" }, { key_piece, "piece" }, { key_totalSize, "total_size" }, }; struct message_type { const char* key; ext_handshake_keys index; }; const message_type message_keys[] = { { "HANDSHAKE", key_handshake_LAST }, { "ut_pex", key_m_utPex }, { "metadata_size", key_m_utMetadata } }; void ProtocolExtension::cleanup() { // if (is_default()) // return; for (int t = HANDSHAKE + 1; t < FIRST_INVALID; t++) if (is_local_enabled(t)) unset_local_enabled(t); } void ProtocolExtension::set_local_enabled(int t) { if (is_local_enabled(t)) return; m_flags |= flag_local_enabled_base << t; switch (t) { case UT_PEX: m_download->info()->set_size_pex(m_download->info()->size_pex() + 1); break; default: break; } } void ProtocolExtension::unset_local_enabled(int t) { if (!is_local_enabled(t)) return; m_flags &= ~(flag_local_enabled_base << t); switch (t) { case UT_PEX: m_download->info()->set_size_pex(m_download->info()->size_pex() - 1); break; default: break; } } DataBuffer ProtocolExtension::generate_handshake_message() { ExtHandshakeMessage message; // Add "e" key if encryption is enabled, set it to 1 if we require // encryption for incoming connections, or 0 otherwise. if ((config::network_config()->encryption_options() & net::NetworkConfig::encryption_allow_incoming) != 0) message[key_e] = (config::network_config()->encryption_options() & net::NetworkConfig::encryption_require) != 0; message[key_p] = runtime::listen_port(); message[key_v] = raw_string::from_c_str("libTorrent " VERSION); message[key_reqq] = 2048; // maximum request queue size if (!m_download->info()->is_meta_download()) message[key_metadataSize] = m_download->info()->metadata_size(); message[key_m_utPex] = is_local_enabled(UT_PEX) ? UT_PEX : 0; message[key_m_utMetadata] = UT_METADATA; char buffer[1024]; object_buffer_t result = static_map_write_bencode_c(object_write_to_buffer, NULL, std::make_pair(buffer, buffer + sizeof(buffer)), message); int length = result.second - buffer; auto copy = new char[length]; memcpy(copy, buffer, length); return DataBuffer(copy, copy + length); } inline DataBuffer ProtocolExtension::build_bencode(size_t maxLength, const char* format, ...) { auto b = new char[maxLength]; va_list args; va_start(args, format); unsigned int length = vsnprintf(b, maxLength, format, args); va_end(args); if (length > maxLength) throw internal_error("ProtocolExtension::build_bencode wrote past buffer."); return DataBuffer(b, b + length); } DataBuffer ProtocolExtension::generate_toggle_message(MessageType t, bool on) { // TODO: Check if we're accepting this message type? // Manually create bencoded map { "m" => { message_keys[t] => on ? t : 0 } } return build_bencode(32, "d1:md%zu:%si%deee", strlen(message_keys[t].key), message_keys[t].key, on ? t : 0); } DataBuffer ProtocolExtension::generate_ut_pex_message(const PEXList& added, const PEXList& removed) { if (added.empty() && removed.empty()) return DataBuffer(); int added_len = added.size() * 6; int removed_len = removed.size() * 6; // Manually create bencoded map { "added" => added, "dropped" => dropped } auto buffer = new char[32 + added_len + removed_len]; auto end = buffer; end += sprintf(end, "d5:added%d:", added_len); memcpy(end, added.begin()->c_str(), added_len); end += added_len; end += sprintf(end, "7:dropped%d:", removed_len); memcpy(end, removed.begin()->c_str(), removed_len); end += removed_len; *end++ = 'e'; if (end - buffer > 32 + added_len + removed_len) throw internal_error("ProtocolExtension::ut_pex_message wrote beyond buffer."); return DataBuffer(buffer, end); } void ProtocolExtension::read_start(int type, uint32_t length, bool skip) { if (is_default() || (type >= FIRST_INVALID) || length > (1 << 15)) throw communication_error("Received invalid extension message."); if (m_read != NULL || static_cast(length) < 0) throw internal_error("ProtocolExtension::read_start called in inconsistent state."); m_readLeft = length; if (skip || !is_local_enabled(type)) { m_readType = SKIP_EXTENSION; } else { m_readType = type; } // Allocate the buffer even for SKIP_EXTENSION, just to make things // simpler. m_readPos = m_read = new char[length]; } bool ProtocolExtension::read_done() { bool result = true; try { switch(m_readType) { case SKIP_EXTENSION: break; case HANDSHAKE: result = parse_handshake(); break; case UT_PEX: result = parse_ut_pex(); break; case UT_METADATA: result = parse_ut_metadata(); break; default: throw internal_error("ProtocolExtension::read_done called with invalid extension type."); } } catch (const bencode_error&) { // Ignore malformed messages. // DEBUG: // throw internal_error("ProtocolExtension::read_done '" + std::string(m_read, std::distance(m_read, m_readPos)) + "'"); } delete [] m_read; m_read = NULL; m_readType = FIRST_INVALID; m_flags |= flag_received_ext; return result; } // Called whenever peer enables or disables an extension. void ProtocolExtension::peer_toggle_remote(int type, bool active) { if (type == UT_PEX) { // When ut_pex is enabled, the first peer exchange afterwards needs // to be a full message, not delta. if (active) m_flags |= flag_initial_pex; } } bool ProtocolExtension::parse_handshake() { ExtHandshakeMessage message; static_map_read_bencode(m_read, m_readPos, message); for (int t = HANDSHAKE + 1; t < FIRST_INVALID; t++) { if (!message[message_keys[t].index].is_value()) continue; uint8_t id = message[message_keys[t].index].as_value(); set_remote_supported(t); if (id != m_idMap[t - 1]) { peer_toggle_remote(t, id != 0); m_idMap[t - 1] = id; } } // If this is the first handshake, then disable any local extensions // not supported by remote. if (is_initial_handshake()) { for (int t = HANDSHAKE + 1; t < FIRST_INVALID; t++) if (!is_remote_supported(t)) unset_local_enabled(t); } if (message[key_p].is_value()) { uint16_t port = message[key_p].as_value(); if (port > 0) m_peerInfo->set_listen_port(port); } if (message[key_reqq].is_value()) m_maxQueueLength = message[key_reqq].as_value(); if (message[key_metadataSize].is_value()) m_download->set_metadata_size(message[key_metadataSize].as_value()); m_flags &= ~flag_initial_handshake; return true; } bool ProtocolExtension::parse_ut_pex() { // Ignore message if we're still in the handshake (no connection // yet), or no peers are present. ExtPEXMessage message; static_map_read_bencode(m_read, m_readPos, message); // TODO: Check if pex is enabled? if (!message[key_pex_added].is_raw_string()) return true; m_download->peer_list()->insert_pex_list(message[key_pex_added].as_raw_string()); return true; } bool ProtocolExtension::parse_ut_metadata() { ExtMetadataMessage message; // Piece data comes after bencoded extension message. const char* dataStart = static_map_read_bencode(m_read, m_readPos, message); switch(message[key_msgType].as_value()) { case 0: // Can't process new request while still having data to send. if (has_pending_message()) return false; send_metadata_piece(message[key_piece].as_value()); break; case 1: if (m_connection == NULL) break; m_connection->receive_metadata_piece(message[key_piece].as_value(), dataStart, m_readPos - dataStart); break; case 2: if (m_connection == NULL) break; m_connection->receive_metadata_piece(message[key_piece].as_value(), NULL, 0); break; } return true; } void ProtocolExtension::send_metadata_piece(size_t piece) { // Reject out-of-range piece, or if we don't have the complete metadata yet. size_t metadataSize = m_download->info()->metadata_size(); size_t pieceEnd = (metadataSize + metadata_piece_size - 1) >> metadata_piece_shift; if (m_download->info()->is_meta_download() || piece >= pieceEnd) { // reject: { "msg_type" => 2, "piece" => ... } m_pendingType = UT_METADATA; m_pending = build_bencode(sizeof(size_t) + 36, "d8:msg_typei2e5:piecei%zuee", piece); return; } // These messages will be rare, so we'll just build the // metadata here instead of caching it uselessly. auto buffer = new char[metadataSize]; object_write_bencode_c(object_write_to_buffer, NULL, object_buffer_t(buffer, buffer + metadataSize), &(*manager->download_manager()->find(m_download->info()))->bencode()->get_key("info")); // data: { "msg_type" => 1, "piece" => ..., "total_size" => ... } followed by piece data (outside of dictionary) size_t length = piece == pieceEnd - 1 ? m_download->info()->metadata_size() % metadata_piece_size : metadata_piece_size; m_pendingType = UT_METADATA; m_pending = build_bencode((2 * sizeof(size_t)) + length + 120, "d8:msg_typei1e5:piecei%zue10:total_sizei%zuee", piece, metadataSize); memcpy(m_pending.end(), buffer + (piece << metadata_piece_shift), length); m_pending.set(m_pending.data(), m_pending.end() + length, m_pending.owned()); delete [] buffer; } bool ProtocolExtension::request_metadata_piece(const Piece* p) { if (p->offset() % metadata_piece_size) throw internal_error("ProtocolExtension::request_metadata_piece got misaligned piece offset."); if (has_pending_message()) return false; m_pendingType = UT_METADATA; m_pending = build_bencode(40, "d8:msg_typei0e5:piecei%uee", static_cast(p->offset() >> metadata_piece_shift)); return true; } } // namespace torrent libtorrent-0.16.11/src/protocol/peer_connection_base.cc0000644000000000000000000010261515175073411016607 #include "config.h" #include "peer_connection_base.h" #include #include "manager.h" #include "data/chunk_iterator.h" #include "data/chunk_list.h" #include "download/chunk_selector.h" #include "download/chunk_statistics.h" #include "download/download_main.h" #include "torrent/chunk_manager.h" #include "torrent/connection_manager.h" #include "torrent/exceptions.h" #include "torrent/throttle.h" #include "torrent/data/block.h" #include "torrent/download/choke_group.h" #include "torrent/download/choke_queue.h" #include "torrent/download_info.h" #include "torrent/net/fd.h" #include "torrent/peer/connection_list.h" #include "torrent/peer/peer_info.h" #include "torrent/runtime/socket_manager.h" #include "torrent/utils/log.h" #include "utils/instrumentation.h" #define LT_LOG_PIECE_EVENTS(log_fmt, ...) \ lt_log_print_info(LOG_PROTOCOL_PIECE_EVENTS, this->download()->info(), "piece_events", "%40s " log_fmt, this->peer_info()->id_hex(), __VA_ARGS__); namespace torrent { static void log_mincore_stats_func(bool is_incore, bool new_index, bool& continous) { if (!new_index && is_incore) { instrumentation_update(INSTRUMENTATION_MINCORE_INCORE_TOUCHED, 1); } if (new_index && is_incore) { instrumentation_update(INSTRUMENTATION_MINCORE_INCORE_NEW, 1); } if (!new_index && !is_incore) { instrumentation_update(INSTRUMENTATION_MINCORE_NOT_INCORE_TOUCHED, 1); } if (new_index && !is_incore) { instrumentation_update(INSTRUMENTATION_MINCORE_NOT_INCORE_NEW, 1); } if (continous && !is_incore) { instrumentation_update(INSTRUMENTATION_MINCORE_INCORE_BREAK, 1); } continous = is_incore; } PeerConnectionBase::PeerConnectionBase() : m_down(new ProtocolRead()), m_up(new ProtocolWrite()) { m_peerInfo = nullptr; } PeerConnectionBase::~PeerConnectionBase() { delete m_up; delete m_down; if (m_extensions != NULL && !m_extensions->is_default()) delete m_extensions; m_extensionMessage.clear(); } void PeerConnectionBase::initialize(DownloadMain* download, PeerInfo* peerInfo, int fd, Bitfield* bitfield, EncryptionInfo* encryptionInfo, ProtocolExtension* extensions) { if (is_open()) throw internal_error("Tried to re-set PeerConnection."); if (fd < 0) throw internal_error("PeerConnectionBase::initialize() received invalid fd."); if (encryptionInfo->is_encrypted() != encryptionInfo->decrypt_valid()) throw internal_error("Encryption and decryption inconsistent."); m_fileDesc = fd; m_peerInfo = peerInfo; m_download = download; m_encryption = *encryptionInfo; m_extensions = extensions; m_extensions->set_connection(this); m_upChoke.set_entry(m_download->up_group_entry()); m_downChoke.set_entry(m_download->down_group_entry()); m_peerChunks.set_peer_info(m_peerInfo); m_peerChunks.bitfield()->swap(*bitfield); std::pair throttles = m_download->throttles(m_peerInfo->socket_address()); m_up->set_throttle(throttles.first); m_down->set_throttle(throttles.second); m_peerChunks.upload_throttle()->set_list_iterator(m_up->throttle()->end()); m_peerChunks.upload_throttle()->slot_activate() = [this] { this_thread::poll()->insert_write(this); }; m_peerChunks.download_throttle()->set_list_iterator(m_down->throttle()->end()); m_peerChunks.download_throttle()->slot_activate() = [this] { this_thread::poll()->insert_read(this); }; request_list()->set_delegator(m_download->delegator()); request_list()->set_peer_chunks(&m_peerChunks); try { initialize_custom(); } catch (const close_connection&) { // The handshake manager closes the socket for us. m_peerInfo = nullptr; m_download = nullptr; m_extensions = nullptr; m_fileDesc = -1; return; } this_thread::poll()->open(this); this_thread::poll()->insert_read(this); this_thread::poll()->insert_write(this); this_thread::poll()->insert_error(this); m_time_last_read = this_thread::cached_time(); m_download->chunk_statistics()->received_connect(&m_peerChunks); // Hmm... cleanup? // update_interested(); m_peerChunks.download_cache()->clear(); if (!m_download->file_list()->is_done()) { m_sendInterested = true; m_downInterested = true; } } void PeerConnectionBase::cleanup() { if (!is_open()) return; if (m_download == NULL) throw internal_error("PeerConnection::~PeerConnection() m_fd is valid but m_state and/or m_net is NULL"); // TODO: Verify that transfer counter gets modified by this... m_request_list.clear(); up_chunk_release(); down_chunk_release(); m_download->info()->set_upload_unchoked(m_download->info()->upload_unchoked() - m_upChoke.unchoked()); m_download->info()->set_download_unchoked(m_download->info()->download_unchoked() - m_downChoke.unchoked()); m_download->choke_group()->up_queue()->disconnected(this, &m_upChoke); m_download->choke_group()->down_queue()->disconnected(this, &m_downChoke); m_download->chunk_statistics()->received_disconnect(&m_peerChunks); if (!m_extensions->is_default()) m_extensions->cleanup(); runtime::socket_manager()->close_event_or_throw(this, [this]() { this_thread::poll()->remove_and_close(this); fd_close(m_fileDesc); m_fileDesc = -1; }); manager->connection_manager()->dec_socket_count(); m_up->throttle()->erase(m_peerChunks.upload_throttle()); m_down->throttle()->erase(m_peerChunks.download_throttle()); m_up->set_state(ProtocolWrite::INTERNAL_ERROR); m_down->set_state(ProtocolRead::INTERNAL_ERROR); m_download = NULL; } void PeerConnectionBase::set_upload_snubbed(bool v) { if (v) m_download->choke_group()->up_queue()->set_snubbed(this, &m_upChoke); else m_download->choke_group()->up_queue()->set_not_snubbed(this, &m_upChoke); } bool PeerConnectionBase::receive_upload_choke(bool choke) { if (choke == m_upChoke.choked()) throw internal_error("PeerConnectionBase::receive_upload_choke(...) already set to the same state."); write_insert_poll_safe(); m_sendChoked = true; m_upChoke.set_unchoked(!choke); m_upChoke.set_time_last_choke(this_thread::cached_time()); if (choke) { m_download->info()->set_upload_unchoked(m_download->info()->upload_unchoked() - 1); m_upChoke.entry()->connection_choked(this); m_upChoke.entry()->connection_queued(this); m_download->choke_group()->up_queue()->modify_currently_unchoked(-1); m_download->choke_group()->up_queue()->modify_currently_queued(1); } else { m_download->info()->set_upload_unchoked(m_download->info()->upload_unchoked() + 1); m_upChoke.entry()->connection_unqueued(this); m_upChoke.entry()->connection_unchoked(this); m_download->choke_group()->up_queue()->modify_currently_unchoked(1); m_download->choke_group()->up_queue()->modify_currently_queued(-1); } return true; } bool PeerConnectionBase::receive_download_choke(bool choke) { if (choke == m_downChoke.choked()) throw internal_error("PeerConnectionBase::receive_download_choke(...) already set to the same state."); write_insert_poll_safe(); m_downChoke.set_unchoked(!choke); m_downChoke.set_time_last_choke(this_thread::cached_time()); if (choke) { m_download->info()->set_download_unchoked(m_download->info()->download_unchoked() - 1); m_downChoke.entry()->connection_choked(this); m_downChoke.entry()->connection_queued(this); m_download->choke_group()->down_queue()->modify_currently_unchoked(-1); m_download->choke_group()->down_queue()->modify_currently_queued(1); } else { m_download->info()->set_download_unchoked(m_download->info()->download_unchoked() + 1); m_downChoke.entry()->connection_unqueued(this); m_downChoke.entry()->connection_unchoked(this); m_download->choke_group()->down_queue()->modify_currently_unchoked(1); m_download->choke_group()->down_queue()->modify_currently_queued(-1); } if (choke) { m_peerChunks.download_cache()->disable(); // If the queue isn't empty, then we might still receive some // pieces, so don't remove us from throttle or release the chunk. if (!request_list()->is_downloading() && request_list()->queued_empty()) { m_down->throttle()->erase(m_peerChunks.download_throttle()); down_chunk_release(); } // Send uninterested if unchoked, but only _after_ receiving our // chunks? if (m_downUnchoked) { // Tell the peer we're no longer interested to avoid // disconnects. We keep the connection in the queue so that // ChokeManager::cycle(...) can attempt to get us unchoked // again. m_sendInterested = m_downInterested; m_downInterested = false; } else { // Remove from queue so that an unchoke from the remote peer // will cause the connection to be unchoked immediately by the // choke manager. // // TODO: This doesn't seem safe... m_download->choke_group()->down_queue()->set_not_queued(this, &m_downChoke); return false; } } else { m_tryRequest = true; if (!m_downInterested) { // We were marked as not interested by the cycling choke and // kept in the queue, thus the peer should have some pieces of // interest. // // We have now been 'unchoked' by the choke manager, so tell the // peer that we're again interested. If the peer doesn't unchoke // us within a cycle or two we're likely to be choked and left // out of the queue. So if the peer unchokes us at a later time, // we skip the queue and unchoke immediately. m_sendInterested = !m_downInterested; m_downInterested = true; } } return true; } void PeerConnectionBase::load_up_chunk() { if (m_upChunk.is_valid() && m_upChunk.index() == m_upPiece.index()) { // Better checking needed. // m_upChunk.chunk()->preload(m_upPiece.offset(), m_upChunk.chunk()->size()); if (lt_log_is_valid(LOG_INSTRUMENTATION_MINCORE)) log_mincore_stats_func(m_upChunk.chunk()->is_incore(m_upPiece.offset(), m_upPiece.length()), false, m_incoreContinous); return; } up_chunk_release(); m_upChunk = m_download->chunk_list()->get(m_upPiece.index(), ChunkList::get_not_hashing); if (!m_upChunk.is_valid()) throw storage_error("File chunk read error: " + std::string(std::strerror(m_upChunk.error_number()))); if (is_encrypted() && m_encryptBuffer == nullptr) { m_encryptBuffer = std::make_unique(); m_encryptBuffer->reset(); } m_incoreContinous = false; if (lt_log_is_valid(LOG_INSTRUMENTATION_MINCORE)) log_mincore_stats_func(m_upChunk.chunk()->is_incore(m_upPiece.offset(), m_upPiece.length()), true, m_incoreContinous); m_incoreContinous = true; // Also check if we've already preloaded in the recent past, even // past unmaps. ChunkManager* cm = manager->chunk_manager(); uint32_t preloadSize = m_upChunk.chunk()->chunk_size() - m_upPiece.offset(); if (cm->preload_type() == 0 || m_upChunk.object()->time_preloaded() >= this_thread::cached_time() - 60s || preloadSize < cm->preload_min_size() || m_peerChunks.upload_throttle()->rate()->rate() < cm->preload_required_rate() * ((preloadSize + (2 << 20) - 1) / (2 << 20))) { cm->inc_stats_not_preloaded(); return; } cm->inc_stats_preloaded(); m_upChunk.object()->set_time_preloaded(this_thread::cached_time()); m_upChunk.chunk()->preload(m_upPiece.offset(), m_upChunk.chunk()->chunk_size(), cm->preload_type() == 1); } void PeerConnectionBase::cancel_transfer(BlockTransfer* transfer) { if (!is_open()) throw internal_error("PeerConnectionBase::cancel_transfer(...) !is_open()"); if (transfer->peer_info() != peer_info()) throw internal_error("PeerConnectionBase::cancel_transfer(...) peer info doesn't match"); // We don't send cancel messages if the transfer has already // started. if (transfer == m_request_list.transfer()) return; write_insert_poll_safe(); m_peerChunks.cancel_queue()->push_back(transfer->piece()); } void PeerConnectionBase::event_error() { m_download->connection_list()->erase(this, 0); } bool PeerConnectionBase::should_connection_unchoke(choke_queue* cq) const { if (cq == m_download->choke_group()->up_queue()) return m_download->info()->upload_unchoked() < m_download->up_group_entry()->max_slots(); if (cq == m_download->choke_group()->down_queue()) return m_download->info()->download_unchoked() < m_download->down_group_entry()->max_slots(); return true; } bool PeerConnectionBase::down_chunk_start(const Piece& piece) { if (!request_list()->downloading(piece)) { if (piece.length() == 0) { LT_LOG_PIECE_EVENTS("(down) skipping_empty %" PRIu32 " %" PRIu32 " %" PRIu32, piece.index(), piece.offset(), piece.length()); } else { LT_LOG_PIECE_EVENTS("(down) skipping_unneeded %" PRIu32 " %" PRIu32 " %" PRIu32, piece.index(), piece.offset(), piece.length()); } return false; } if (!m_download->file_list()->is_valid_piece(piece)) throw internal_error("Incoming pieces list contains a bad piece."); if (!m_downChunk.is_valid() || piece.index() != m_downChunk.index()) { down_chunk_release(); m_downChunk = m_download->chunk_list()->get(piece.index(), ChunkList::get_not_hashing | ChunkList::get_writable); if (!m_downChunk.is_valid()) throw storage_error("File chunk write error: " + std::string(std::strerror(m_downChunk.error_number()))); } LT_LOG_PIECE_EVENTS("(down) %s %" PRIu32 " %" PRIu32 " %" PRIu32, request_list()->transfer()->is_leader() ? "started_on" : "skipping_partial", piece.index(), piece.offset(), piece.length()); return request_list()->transfer()->is_leader(); } void PeerConnectionBase::down_chunk_finished() { if (!request_list()->transfer()->is_finished()) throw internal_error("PeerConnectionBase::down_chunk_finished() Transfer not finished."); BlockTransfer* transfer = request_list()->transfer(); LT_LOG_PIECE_EVENTS("(down) %s %" PRIu32 " %" PRIu32 " %" PRIu32, transfer->is_leader() ? "completed " : "skipped ", transfer->piece().index(), transfer->piece().offset(), transfer->piece().length()); if (transfer->is_leader()) { if (!m_downChunk.is_valid()) throw internal_error("PeerConnectionBase::down_chunk_finished() Transfer is the leader, but no chunk allocated."); request_list()->finished(); m_downChunk.object()->set_time_modified(this_thread::cached_time()); } else { request_list()->skipped(); } if (m_downStall > 0) m_downStall--; // We need to release chunks when we're not sure if they will be // used in the near future so as to avoid hitting the address space // limit in high-bandwidth situations. // // Some tweaking of the pipe size might be necessary if the queue // empties too often. if (m_downChunk.is_valid() && (request_list()->queued_empty() || m_downChunk.index() != request_list()->next_queued_piece().index())) down_chunk_release(); // If we were choked by choke_manager but still had queued pieces, // then we might still be in the throttle. if (m_downChoke.choked() && request_list()->queued_empty()) m_down->throttle()->erase(m_peerChunks.download_throttle()); write_insert_poll_safe(); } bool PeerConnectionBase::down_chunk() { if (!m_down->throttle()->is_throttled(m_peerChunks.download_throttle())) throw internal_error("PeerConnectionBase::down_chunk() tried to read a piece but is not in throttle list"); if (!m_downChunk.chunk()->is_writable()) throw internal_error("PeerConnectionBase::down_part() chunk not writable, permission denided"); uint32_t quota = m_down->throttle()->node_quota(m_peerChunks.download_throttle()); if (quota == 0) { this_thread::poll()->remove_read(this); m_down->throttle()->node_deactivate(m_peerChunks.download_throttle()); return false; } uint32_t bytesTransfered = 0; BlockTransfer* transfer = m_request_list.transfer(); Chunk::data_type data; ChunkIterator itr(m_downChunk.chunk(), transfer->piece().offset() + transfer->position(), transfer->piece().offset() + std::min(transfer->position() + quota, transfer->piece().length())); do { data = itr.data(); data.second = read_stream_throws(data.first, data.second); if (is_encrypted()) m_encryption.decrypt(data.first, data.second); bytesTransfered += data.second; } while (data.second != 0 && itr.forward(data.second)); transfer->adjust_position(bytesTransfered); m_down->throttle()->node_used(m_peerChunks.download_throttle(), bytesTransfered); m_download->info()->mutable_down_rate()->insert(bytesTransfered); return transfer->is_finished(); } bool PeerConnectionBase::down_chunk_from_buffer() { m_down->buffer()->consume(down_chunk_process(m_down->buffer()->position(), m_down->buffer()->remaining())); if (!m_request_list.transfer()->is_finished() && m_down->buffer()->remaining() != 0) throw internal_error("PeerConnectionBase::down_chunk_from_buffer() !transfer->is_finished() && m_down->buffer()->remaining() != 0."); return m_request_list.transfer()->is_finished(); } // When this transfer again becomes the leader, we just return false // and wait for the next polling. It is an exceptional case so we // don't really care that much about performance. bool PeerConnectionBase::down_chunk_skip() { ThrottleList* throttle = m_down->throttle(); if (!throttle->is_throttled(m_peerChunks.download_throttle())) throw internal_error("PeerConnectionBase::down_chunk_skip() tried to read a piece but is not in throttle list"); uint32_t quota = throttle->node_quota(m_peerChunks.download_throttle()); if (quota == 0) { this_thread::poll()->remove_read(this); throttle->node_deactivate(m_peerChunks.download_throttle()); return false; } uint32_t length = read_stream_throws(m_nullBuffer, std::min(quota, m_request_list.transfer()->piece().length() - m_request_list.transfer()->position())); throttle->node_used(m_peerChunks.download_throttle(), length); if (is_encrypted()) m_encryption.decrypt(m_nullBuffer, length); if (down_chunk_skip_process(m_nullBuffer, length) != length) throw internal_error("PeerConnectionBase::down_chunk_skip() down_chunk_skip_process(m_nullBuffer, length) != length."); return m_request_list.transfer()->is_finished(); } bool PeerConnectionBase::down_chunk_skip_from_buffer() { m_down->buffer()->consume(down_chunk_skip_process(m_down->buffer()->position(), m_down->buffer()->remaining())); return m_request_list.transfer()->is_finished(); } // Process data from a leading transfer. uint32_t PeerConnectionBase::down_chunk_process(const void* buffer, uint32_t length) { if (!m_downChunk.is_valid() || m_downChunk.index() != m_request_list.transfer()->index()) throw internal_error("PeerConnectionBase::down_chunk_process(...) !m_downChunk.is_valid() || m_downChunk.index() != m_request_list.transfer()->index()."); if (length == 0) return length; BlockTransfer* transfer = m_request_list.transfer(); length = std::min(transfer->piece().length() - transfer->position(), length); m_downChunk.chunk()->from_buffer(buffer, transfer->piece().offset() + transfer->position(), length); transfer->adjust_position(length); m_down->throttle()->node_used(m_peerChunks.download_throttle(), length); m_download->info()->mutable_down_rate()->insert(length); return length; } // Process data from non-leading transfer. If this transfer encounters // mismatching data with the leader then bork this transfer. If we get // ahead of the leader, we switch the leader. uint32_t PeerConnectionBase::down_chunk_skip_process(const void* buffer, uint32_t length) { BlockTransfer* transfer = m_request_list.transfer(); // Adjust 'length' to be less than or equal to what is remaining of // the block to simplify the rest of the function. length = std::min(length, transfer->piece().length() - transfer->position()); // Hmm, this might result in more bytes than nessesary being // counted. m_down->throttle()->node_used(m_peerChunks.download_throttle(), length); m_download->info()->mutable_down_rate()->insert(length); m_download->info()->mutable_skip_rate()->insert(length); if (!transfer->is_valid()) { transfer->adjust_position(length); return length; } if (!transfer->block()->is_transfering()) throw internal_error("PeerConnectionBase::down_chunk_skip_process(...) block is not transferring, yet we have non-leaders."); // Temporary test. if (transfer->position() > transfer->block()->leader()->position()) throw internal_error("PeerConnectionBase::down_chunk_skip_process(...) transfer is past the Block's position."); // If the transfer is valid, compare the downloaded data to the // leader. uint32_t compareLength = std::min(length, transfer->block()->leader()->position() - transfer->position()); // The data doesn't match with what has previously been downloaded, // bork this transfer. if (!m_downChunk.chunk()->compare_buffer(buffer, transfer->piece().offset() + transfer->position(), compareLength)) { LT_LOG_PIECE_EVENTS("(down) download_data_mismatch %" PRIu32 " %" PRIu32 " %" PRIu32, transfer->piece().index(), transfer->piece().offset(), transfer->piece().length()); m_request_list.transfer_dissimilar(); m_request_list.transfer()->adjust_position(length); return length; } transfer->adjust_position(compareLength); if (compareLength == length) return length; // Add another check here to see if we really want to be the new // leader. transfer->block()->change_leader(transfer); if (down_chunk_process(static_cast(buffer) + compareLength, length - compareLength) != length - compareLength) throw internal_error("PeerConnectionBase::down_chunk_skip_process(...) down_chunk_process(...) returned wrong value."); return length; } bool PeerConnectionBase::down_extension() { if (m_down->buffer()->remaining()) { uint32_t need = std::min(m_extensions->read_need(), static_cast(m_down->buffer()->remaining())); std::memcpy(m_extensions->read_position(), m_down->buffer()->position(), need); m_extensions->read_move(need); m_down->buffer()->consume(need); } if (!m_extensions->is_complete()) { uint32_t bytes = read_stream_throws(m_extensions->read_position(), m_extensions->read_need()); m_down->throttle()->node_used_unthrottled(bytes); if (is_encrypted()) m_encryption.decrypt(m_extensions->read_position(), bytes); m_extensions->read_move(bytes); } // If extension can't be processed yet (due to a pending write), // disable reads until the pending message is completely sent. if (m_extensions->is_complete() && !m_extensions->is_invalid() && !m_extensions->read_done()) { this_thread::poll()->remove_read(this); return false; } return m_extensions->is_complete(); } inline uint32_t PeerConnectionBase::up_chunk_encrypt(uint32_t quota) { if (m_encryptBuffer == nullptr) throw internal_error("PeerConnectionBase::up_chunk: m_encryptBuffer is NULL."); if (quota <= m_encryptBuffer->remaining()) return quota; // Also, consider checking here if the number of bytes remaining in // the buffer is small enought that the cost of moving them would // outweigh the extra context switches, etc. if (m_encryptBuffer->remaining() == 0) { // This handles reset also for new chunk transfers. m_encryptBuffer->reset(); quota = std::min(quota, m_encryptBuffer->reserved()); } else { quota = std::min(quota - m_encryptBuffer->remaining(), m_encryptBuffer->reserved_left()); } m_upChunk.chunk()->to_buffer(m_encryptBuffer->end(), m_upPiece.offset() + m_encryptBuffer->remaining(), quota); m_encryption.encrypt(m_encryptBuffer->end(), quota); m_encryptBuffer->move_end(quota); return m_encryptBuffer->remaining(); } bool PeerConnectionBase::up_chunk() { if (!m_up->throttle()->is_throttled(m_peerChunks.upload_throttle())) throw internal_error("PeerConnectionBase::up_chunk() tried to write a piece but is not in throttle list"); if (!m_upChunk.chunk()->is_readable()) throw internal_error("ProtocolChunk::write_part() chunk not readable, permission denided"); uint32_t quota = m_up->throttle()->node_quota(m_peerChunks.upload_throttle()); if (quota == 0) { this_thread::poll()->remove_write(this); m_up->throttle()->node_deactivate(m_peerChunks.upload_throttle()); return false; } uint32_t bytesTransfered = 0; if (is_encrypted()) { // Prepare as many bytes as quota specifies, up to end of piece or // buffer. Only bytes beyond remaining() are new and will be // encrypted. quota = up_chunk_encrypt(std::min(quota, m_upPiece.length())); bytesTransfered = write_stream_throws(m_encryptBuffer->position(), quota); m_encryptBuffer->consume(bytesTransfered); } else { Chunk::data_type data; ChunkIterator itr(m_upChunk.chunk(), m_upPiece.offset(), m_upPiece.offset() + std::min(quota, m_upPiece.length())); do { data = itr.data(); data.second = write_stream_throws(data.first, data.second); bytesTransfered += data.second; } while (data.second != 0 && itr.forward(data.second)); } m_up->throttle()->node_used(m_peerChunks.upload_throttle(), bytesTransfered); m_download->info()->mutable_up_rate()->insert(bytesTransfered); // Just modifying the piece to cover the remaining data ends up // being much cleaner and we avoid an unnessesary position variable. m_upPiece.set_offset(m_upPiece.offset() + bytesTransfered); m_upPiece.set_length(m_upPiece.length() - bytesTransfered); return m_upPiece.length() == 0; } bool PeerConnectionBase::up_extension() { if (m_extensionOffset == extension_must_encrypt) { if (m_extensionMessage.owned()) { m_encryption.encrypt(m_extensionMessage.data(), m_extensionMessage.length()); } else { auto buffer = new char[m_extensionMessage.length()]; m_encryption.encrypt(m_extensionMessage.data(), buffer, m_extensionMessage.length()); m_extensionMessage.set(buffer, buffer + m_extensionMessage.length(), true); } m_extensionOffset = 0; } if (m_extensionOffset >= m_extensionMessage.length()) throw internal_error("PeerConnectionBase::up_extension bad offset."); uint32_t written = write_stream_throws(m_extensionMessage.data() + m_extensionOffset, m_extensionMessage.length() - m_extensionOffset); m_up->throttle()->node_used_unthrottled(written); m_extensionOffset += written; if (m_extensionOffset < m_extensionMessage.length()) return false; m_extensionMessage.clear(); // If we have an unprocessed message, process it now and enable reads again. if (m_extensions->is_complete() && !m_extensions->is_invalid()) { // DEBUG: What, this should fail when we block, no? if (!m_extensions->read_done()) throw internal_error("PeerConnectionBase::up_extension could not process complete extension message."); this_thread::poll()->insert_read(this); } return true; } void PeerConnectionBase::down_chunk_release() { if (m_downChunk.is_valid()) m_download->chunk_list()->release(&m_downChunk, ChunkList::release_default); } void PeerConnectionBase::up_chunk_release() { if (m_upChunk.is_valid()) m_download->chunk_list()->release(&m_upChunk, ChunkList::release_default); } void PeerConnectionBase::read_request_piece(const Piece& p) { auto itr = std::find(m_peerChunks.upload_queue()->begin(), m_peerChunks.upload_queue()->end(), p); if (m_upChoke.choked() || itr != m_peerChunks.upload_queue()->end() || p.length() > (1 << 17)) { LT_LOG_PIECE_EVENTS("(up) request_ignored %" PRIu32 " %" PRIu32 " %" PRIu32, p.index(), p.offset(), p.length()); return; } m_peerChunks.upload_queue()->push_back(p); write_insert_poll_safe(); LT_LOG_PIECE_EVENTS("(up) request_added %" PRIu32 " %" PRIu32 " %" PRIu32, p.index(), p.offset(), p.length()); } void PeerConnectionBase::read_cancel_piece(const Piece& p) { auto itr = std::find(m_peerChunks.upload_queue()->begin(), m_peerChunks.upload_queue()->end(), p); if (itr != m_peerChunks.upload_queue()->end()) { m_peerChunks.upload_queue()->erase(itr); LT_LOG_PIECE_EVENTS("(up) cancel_requested %" PRIu32 " %" PRIu32 " %" PRIu32, p.index(), p.offset(), p.length()); } else { LT_LOG_PIECE_EVENTS("(up) cancel_ignored %" PRIu32 " %" PRIu32 " %" PRIu32, p.index(), p.offset(), p.length()); } } void PeerConnectionBase::write_prepare_piece() { m_upPiece = m_peerChunks.upload_queue()->front(); m_peerChunks.upload_queue()->pop_front(); // Move these checks somewhere else? if (!m_download->file_list()->is_valid_piece(m_upPiece) || !m_download->file_list()->bitfield()->get(m_upPiece.index())) { char buffer[128]; snprintf(buffer, 128, "Peer requested an invalid piece: %u %u %u", m_upPiece.index(), m_upPiece.length(), m_upPiece.offset()); LT_LOG_PIECE_EVENTS("(up) invalid_piece_in_upload_queue %" PRIu32 " %" PRIu32 " %" PRIu32, m_upPiece.index(), m_upPiece.length(), m_upPiece.offset()); throw communication_error(buffer); } m_up->write_piece(m_upPiece); LT_LOG_PIECE_EVENTS("(up) prepared %" PRIu32 " %" PRIu32 " %" PRIu32, m_upPiece.index(), m_upPiece.length(), m_upPiece.offset()); } void PeerConnectionBase::write_prepare_extension(int type, const DataBuffer& message) { m_up->write_extension(m_extensions->id(type), message.length()); m_extensionOffset = 0; m_extensionMessage = message; // Need to encrypt the buffer, but not until the m_up // write buffer has been flushed, so flag it for now. if (is_encrypted()) m_extensionOffset = extension_must_encrypt; } // High stall count peers should request if we're *not* in endgame, or // if we're in endgame and the download is too slow. Prefere not to request // from high stall counts when we are doing decent speeds. bool PeerConnectionBase::should_request() { if (m_downChoke.choked() || !m_downInterested || !m_downUnchoked) // || m_down->get_state() == ProtocolRead::READ_SKIP_PIECE) return false; else if (!m_download->delegator()->get_aggressive()) return true; else // We check if the peer is stalled, if it is not then we should // request. If the peer is stalled then we only request if the // download rate is below a certain value. return m_downStall <= 1 || m_download->info()->down_rate()->rate() < (10 << 10); } bool PeerConnectionBase::try_request_pieces() { if (request_list()->queued_empty()) m_downStall = 0; uint32_t pipeSize = request_list()->calculate_pipe_size(m_peerChunks.download_throttle()->rate()->rate()); // Don't start requesting if we can't do it in large enough chunks. if (request_list()->pipe_size() >= (pipeSize + 10) / 2) return false; bool success = false; while (request_list()->queued_size() < pipeSize && m_up->can_write_request()) { // It should get the right number the first time around, but loop just to be sure int maxRequests = m_up->max_write_request(); int maxQueued = pipeSize - request_list()->queued_size(); int maxPieces = std::max(std::min(maxRequests, maxQueued), 1); std::vector pieces = request_list()->delegate(maxPieces); if (pieces.empty()) { return false; } for (auto& p : pieces) { if (!m_download->file_list()->is_valid_piece(*p) || !m_peerChunks.bitfield()->get(p->index())) throw internal_error("PeerConnectionBase::try_request_pieces() tried to use an invalid piece."); m_up->write_request(*p); LT_LOG_PIECE_EVENTS("(down) requesting %" PRIu32 " %" PRIu32 " %" PRIu32, p->index(), p->offset(), p->length()); success = true; } } return success; } // Send one peer exchange message according to bits set in m_sendPEXMask. // We can only send one message at a time, because the derived class // needs to flush the buffer and call up_extension before the next one. bool PeerConnectionBase::send_pex_message() { if (!m_extensions->is_remote_supported(ProtocolExtension::UT_PEX)) { m_sendPEXMask = 0; return false; } // Message to tell peer to stop/start doing PEX is small so send it first. if (m_sendPEXMask & (PEX_ENABLE | PEX_DISABLE)) { if (!m_extensions->is_remote_supported(ProtocolExtension::UT_PEX)) throw internal_error("PeerConnectionBase::send_pex_message() Not supported by peer."); write_prepare_extension(ProtocolExtension::HANDSHAKE, ProtocolExtension::generate_toggle_message(ProtocolExtension::UT_PEX, (m_sendPEXMask & PEX_ENABLE) != 0)); m_sendPEXMask &= ~(PEX_ENABLE | PEX_DISABLE); } else if (m_sendPEXMask & PEX_DO && m_extensions->id(ProtocolExtension::UT_PEX)) { const DataBuffer& pexMessage = m_download->get_ut_pex(m_extensions->is_initial_pex()); m_extensions->clear_initial_pex(); m_sendPEXMask &= ~PEX_DO; if (pexMessage.empty()) return false; write_prepare_extension(ProtocolExtension::UT_PEX, pexMessage); } else { m_sendPEXMask = 0; } return true; } // Extension protocol needs to send a reply. bool PeerConnectionBase::send_ext_message() { write_prepare_extension(m_extensions->pending_message_type(), m_extensions->pending_message_data()); m_extensions->clear_pending_message(); return true; } void PeerConnectionBase::receive_metadata_piece([[maybe_unused]] uint32_t piece, [[maybe_unused]] const char* data, [[maybe_unused]] uint32_t length) { } } // namespace torrent libtorrent-0.16.11/src/protocol/initial_seed.h0000644000000000000000000000644415175073411014741 // libTorrent - BitTorrent library // Copyright (C) 2005-2011, Jari Sundell // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // In addition, as a special exception, the copyright holders give // permission to link the code of portions of this program with the // OpenSSL library under certain conditions as described in each // individual source file, and distribute linked combinations // including the two. // // You must obey the GNU General Public License in all respects for // all of the code used other than OpenSSL. If you modify file(s) // with this exception, you may extend this exception to your version // of the file(s), but you are not obligated to do so. If you do not // wish to do so, delete this exception statement from your version. // If you delete this exception statement from all source files in the // program, then also delete it here. // // Contact: Jari Sundell // // Skomakerveien 33 // 3185 Skoppum, NORWAY #ifndef LIBTORRENT_PROTOCOL_INITIAL_SEED_H #define LIBTORRENT_PROTOCOL_INITIAL_SEED_H #include "download/download_main.h" namespace torrent { class InitialSeeding { public: InitialSeeding(DownloadMain* download); ~InitialSeeding(); static constexpr uint32_t no_offer = ~uint32_t(); void new_peer(PeerConnectionBase* pcb); // Chunk was seen distributed to a peer in the swarm. void chunk_seen(uint32_t index, PeerConnectionBase* pcb); // Returns chunk we may offer the peer or no_offer if none. uint32_t chunk_offer(PeerConnectionBase* pcb, uint32_t indexDone); // During the second stage (seeding rare chunks), return // false if given chunk is already well-seeded now. True otherwise. bool should_upload(uint32_t index); private: InitialSeeding(const InitialSeeding&) = delete; InitialSeeding& operator=(const InitialSeeding&) = delete; static PeerInfo* const chunk_unsent; // Chunk never sent to anyone. static PeerInfo* const chunk_unknown; // Peer has chunk, we don't know who we sent it to. static PeerInfo* const chunk_done; // Chunk properly distributed by peer. uint32_t find_next(bool secondary, PeerConnectionBase* pcb); static bool valid_peer(PeerInfo* peer); static void clear_peer(PeerInfo* peer); void chunk_complete(uint32_t index, PeerConnectionBase* pcb); void complete(PeerConnectionBase* pcb); void unblock_all(); uint32_t m_nextChunk{0}; uint32_t m_chunksLeft; DownloadMain* m_download; std::unique_ptr m_peerChunks; }; } // namespace torrent #endif libtorrent-0.16.11/src/protocol/peer_factory.cc0000644000000000000000000000460615175073411015126 // libTorrent - BitTorrent library // Copyright (C) 2005-2011, Jari Sundell // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // In addition, as a special exception, the copyright holders give // permission to link the code of portions of this program with the // OpenSSL library under certain conditions as described in each // individual source file, and distribute linked combinations // including the two. // // You must obey the GNU General Public License in all respects for // all of the code used other than OpenSSL. If you modify file(s) // with this exception, you may extend this exception to your version // of the file(s), but you are not obligated to do so. If you do not // wish to do so, delete this exception statement from your version. // If you delete this exception statement from all source files in the // program, then also delete it here. // // Contact: Jari Sundell // // Skomakerveien 33 // 3185 Skoppum, NORWAY #include "config.h" #include "peer_factory.h" #include "peer_connection_leech.h" #include "peer_connection_metadata.h" namespace torrent { PeerConnectionBase* createPeerConnectionDefault(bool encrypted) { PeerConnectionBase* pc = new PeerConnection; return pc; } PeerConnectionBase* createPeerConnectionSeed(bool encrypted) { PeerConnectionBase* pc = new PeerConnection; return pc; } PeerConnectionBase* createPeerConnectionInitialSeed(bool encrypted) { PeerConnectionBase* pc = new PeerConnection; return pc; } PeerConnectionBase* createPeerConnectionMetadata(bool encrypted) { PeerConnectionBase* pc = new PeerConnectionMetadata; return pc; } } // namespace torrent libtorrent-0.16.11/src/protocol/initial_seed.cc0000644000000000000000000002360315175073411015073 // libTorrent - BitTorrent library // Copyright (C) 2005-2011, Jari Sundell // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // In addition, as a special exception, the copyright holders give // permission to link the code of portions of this program with the // OpenSSL library under certain conditions as described in each // individual source file, and distribute linked combinations // including the two. // // You must obey the GNU General Public License in all respects for // all of the code used other than OpenSSL. If you modify file(s) // with this exception, you may extend this exception to your version // of the file(s), but you are not obligated to do so. If you do not // wish to do so, delete this exception statement from your version. // If you delete this exception statement from all source files in the // program, then also delete it here. // // Contact: Jari Sundell // // Skomakerveien 33 // 3185 Skoppum, NORWAY #include "config.h" #include #include "download/chunk_statistics.h" #include "torrent/download/choke_group.h" #include "torrent/download/choke_queue.h" #include "torrent/peer/peer_info.h" #include "initial_seed.h" #include "peer_connection_base.h" namespace torrent { PeerInfo* const InitialSeeding::chunk_unsent = (PeerInfo*) 0; PeerInfo* const InitialSeeding::chunk_unknown = (PeerInfo*) 1; PeerInfo* const InitialSeeding::chunk_done = (PeerInfo*) 2; InitialSeeding::InitialSeeding(DownloadMain* download) : m_chunksLeft(download->file_list()->size_chunks()), m_download(download), m_peerChunks(new PeerInfo* [m_chunksLeft] {}) { } InitialSeeding::~InitialSeeding() { unblock_all(); } bool InitialSeeding::valid_peer(PeerInfo* peer) { return peer > chunk_done; } void InitialSeeding::clear_peer(PeerInfo* peer) { if (!valid_peer(peer)) return; peer->unset_flags(PeerInfo::flag_blocked); // If peer is still connected, offer new piece right away. if (peer->connection() != NULL) peer->connection()->write_insert_poll_safe(); } void InitialSeeding::chunk_seen(uint32_t index, PeerConnectionBase* pcb) { // When we have two other seeds, trust that the download will // be sufficiently seeded and switch to normal seeding. This is // mainly for when the user accidentally enables initial seeding. if (m_download->chunk_statistics()->complete() > 1) complete(pcb); PeerInfo* peer = pcb->mutable_peer_info(); PeerInfo* old = m_peerChunks[index]; // We didn't send this chunk. Is someone else initial seeding too? // Or maybe we restarted and the peer got this chunk from someone // we did send it to. Either way, we don't know who it belongs to. // Don't mark it done until we see it from someone else, though. if (old == chunk_unsent) { m_peerChunks[index] = chunk_unknown; return; } if (old == peer || old == chunk_done) return; // We've seen two peers on the swarm receive this chunk. m_peerChunks[index] = chunk_done; if (--m_chunksLeft == 0) complete(pcb); // The peer we sent it to originally may now receive another chunk. clear_peer(old); } void InitialSeeding::chunk_complete(uint32_t index, PeerConnectionBase* pcb) { clear_peer(m_peerChunks[index]); m_peerChunks[index] = chunk_unknown; chunk_seen(index, pcb); } void InitialSeeding::new_peer(PeerConnectionBase* pcb) { PeerInfo* peer = pcb->mutable_peer_info(); if (peer->is_blocked()) peer->set_flags(PeerInfo::flag_restart); // We don't go through the peer's entire bitfield here. This eliminates // cheating by sending a bogus bitfield if it figures out we are initial // seeding, to drop us out of it. We should see HAVE messages for pieces // it has that we were waiting for anyway. We will check individual chunks // as we are about to offer them, to avoid the overhead of checking each // peer's bitfield as well. If it really was cheating, the pieces it isn't // sharing will be sent during the second round of initial seeding. // If we're on the second round, don't check // it until we're about to offer a chunk. if (m_peerChunks[m_nextChunk] != chunk_unsent) return; // But during primary initial seeding (some chunks not sent at all), // check that nobody already has the next chunk we were going to send. while (m_peerChunks[m_nextChunk] == chunk_unsent && (*m_download->chunk_statistics())[m_nextChunk]) { // Could set to chunk_done if enough peers have it, but if that was the // last one it could cause initial seeding to end and all connections to // be closed, and now is a bad time for that (still being set up). Plus // this gives us the opportunity to wait for HAVE messages and resend // the chunk if it's not being shared. m_peerChunks[m_nextChunk] = chunk_unknown; find_next(false, pcb); } } uint32_t InitialSeeding::chunk_offer(PeerConnectionBase* pcb, uint32_t chunkDone) { PeerInfo* peer = pcb->mutable_peer_info(); // If this peer completely downloaded the chunk we offered and we have too // many unused upload slots, give it another chunk to download for free. if (peer->is_blocked() && chunkDone != no_offer && m_peerChunks[chunkDone] == peer && m_download->choke_group()->up_queue()->size_total() * 10 < 9 * m_download->choke_group()->up_queue()->max_unchoked()) { m_peerChunks[chunkDone] = chunk_unknown; peer->unset_flags(PeerInfo::flag_blocked); // Otherwise check if we can offer a chunk normally. } else if (peer->is_blocked()) { if (!peer->is_restart()) return no_offer; peer->unset_flags(PeerInfo::flag_restart); // Re-connection of a peer we already sent a chunk. // Offer the same chunk again. auto peerChunksEnd = m_peerChunks.get() + m_download->file_list()->size_chunks(); auto itr = std::find(m_peerChunks.get(), peerChunksEnd, peer); if (itr != peerChunksEnd) return itr - m_peerChunks.get(); // Couldn't find the chunk, we probably sent it to someone // else since the disconnection. So offer a new one. } uint32_t index = m_nextChunk; bool secondary = false; // If we already sent this chunk to someone else, we're on the second // (or more) round. We might have already found this chunk elsewhere on // the swarm since then and need to find a different one if so. if (m_peerChunks[index] != chunk_unsent) { secondary = true; // Accounting for peers whose bitfield we didn't check when connecting. // If the chunk stats say there are enough peers who have it, believe that. if (m_peerChunks[index] != chunk_done && (*m_download->chunk_statistics())[index] > 1) chunk_complete(index, pcb); if (m_peerChunks[index] == chunk_done) index = find_next(true, pcb); } // When we only have one chunk left and we already offered it // to someone who hasn't shared it yet, offer it to everyone // else. We do not override the peer we sent it to, so they // cannot be unblocked, but when initial seeding completes // everyone is unblocked anyway. if (m_chunksLeft == 1 && valid_peer(m_peerChunks[index])) { peer->set_flags(PeerInfo::flag_blocked); return index; } // Make sure we don't accidentally offer a chunk it has // already, or it would never even request it from us. // We'll just offer it to the next peer instead. if (pcb->bitfield()->get(index)) return no_offer; m_peerChunks[index] = peer; peer->set_flags(PeerInfo::flag_blocked); find_next(secondary, pcb); return index; } bool InitialSeeding::should_upload(uint32_t index) { return m_peerChunks[index] != chunk_done; } uint32_t InitialSeeding::find_next(bool secondary, PeerConnectionBase* pcb) { if (!secondary) { // Primary seeding: find next chunk not sent yet. while (++m_nextChunk < m_download->file_list()->size_chunks()) { if (m_peerChunks[m_nextChunk] == chunk_unsent) { if (!(*m_download->chunk_statistics())[m_nextChunk]) return m_nextChunk; // Someone has this one already. We don't know if we sent it or not. m_peerChunks[m_nextChunk] = chunk_unknown; } } // Went through all chunks. Continue with secondary seeding. m_nextChunk--; } // Secondary seeding: find next chunk that's not done yet. do { if (++m_nextChunk == m_download->file_list()->size_chunks()) m_nextChunk = 0; if (m_peerChunks[m_nextChunk] != chunk_done && (*m_download->chunk_statistics())[m_nextChunk] > 1) chunk_complete(m_nextChunk, pcb); } while (m_peerChunks[m_nextChunk] == chunk_done); return m_nextChunk; } void InitialSeeding::complete(PeerConnectionBase* pcb) { unblock_all(); m_chunksLeft = 0; m_nextChunk = no_offer; // We think all chunks should be well seeded now. Check to make sure. for (uint32_t i = 0; i < m_download->file_list()->size_chunks(); i++) { if (m_download->chunk_statistics()->complete() + (*m_download->chunk_statistics())[i] < 2) { // Chunk too rare, send it again before switching to normal seeding. m_chunksLeft++; m_peerChunks[i] = chunk_unsent; if (m_nextChunk == no_offer) m_nextChunk = i; } } if (m_chunksLeft) return; m_download->initial_seeding_done(pcb); } void InitialSeeding::unblock_all() { for (const auto& peer : *m_download->peer_list()) peer.second->unset_flags(PeerInfo::flag_blocked); } } // namespace torrent libtorrent-0.16.11/src/protocol/handshake_manager.cc0000644000000000000000000003073615175073411016067 #include "config.h" #include "handshake_manager.h" #include "handshake.h" #include "manager.h" #include "peer_connection_base.h" #include "download/download_main.h" #include "torrent/connection_manager.h" #include "torrent/download_info.h" #include "torrent/error.h" #include "torrent/exceptions.h" #include "torrent/net/fd.h" #include "torrent/net/network_config.h" #include "torrent/net/socket_address.h" #include "torrent/runtime/socket_manager.h" #include "torrent/peer/peer_info.h" #include "torrent/peer/client_list.h" #include "torrent/peer/connection_list.h" #include "torrent/utils/log.h" #include "torrent/utils/string_manip.h" #define LT_LOG_SA(sa, log_fmt, ...) \ lt_log_print(LOG_CONNECTION_HANDSHAKE, "handshake_manager->%s: " log_fmt, sa_addr_str(sa).c_str(), __VA_ARGS__); #define LT_LOG_SAP(sa, log_fmt, ...) \ lt_log_print(LOG_CONNECTION_HANDSHAKE, "handshake_manager->%s: " log_fmt, sap_addr_str(sa).c_str(), __VA_ARGS__); namespace torrent { ProtocolExtension HandshakeManager::DefaultExtensions = ProtocolExtension::make_default(); HandshakeManager::HandshakeManager() = default; HandshakeManager::~HandshakeManager() { clear(); } HandshakeManager::size_type HandshakeManager::size_info(DownloadMain* info) const { return std::count_if(base_type::begin(), base_type::end(), [info](auto& h) { return info == h->download(); }); } void HandshakeManager::clear() { for (auto& h : *this) { h->destroy_connection(); h.reset(); } base_type::clear(); } HandshakeManager::value_type HandshakeManager::find_and_erase(Handshake* handshake) { auto itr = std::find_if(base_type::begin(), base_type::end(), [handshake](auto& h) { return h.get() == handshake; }); if (itr == base_type::end()) throw internal_error("HandshakeManager::erase(...) could not find handshake."); auto tmp = std::move(*itr); base_type::erase(itr); return tmp; } bool HandshakeManager::find(const sockaddr* sa) { return std::any_of(base_type::begin(), base_type::end(), [sa](auto& p2) { return p2->peer_info() != nullptr && sa_equal(sa, p2->peer_info()->socket_address()); }); } void HandshakeManager::erase_download(DownloadMain* info) { auto split = std::partition(base_type::begin(), base_type::end(), [info](auto& h) { return info != h->download(); }); std::for_each(split, base_type::end(), [](auto& h) { h->destroy_connection(); h.reset(); }); base_type::erase(split, base_type::end()); } // TODO: Replace by Handshake::prepare_incoming(fd), and close here. void HandshakeManager::add_incoming(std::unique_ptr& handshake, int fd, const sockaddr* sa) { if (!manager->connection_manager()->can_connect()) { LT_LOG_SA(sa, "rejected incoming connection: fd:%i : rejected by connection manager", fd); fd_close(fd); return; } if (!manager->connection_manager()->filter(sa)) { LT_LOG_SA(sa, "rejected incoming connection: fd:%i : filtered", fd); fd_close(fd); return; } if (!fd_set_nonblock(fd)) throw internal_error("HandshakeManager::add_incoming() fd_set_nonblocking failed : " + std::string(strerror(errno))); if (!setup_socket(fd, sa->sa_family)) { LT_LOG_SA(sa, "rejected incoming connection: fd:%i : setup socket failed : %s", fd, std::strerror(errno)); fd_close(fd); return; } LT_LOG_SA(sa, "accepted incoming connection: fd:%i", fd); manager->connection_manager()->inc_socket_count(); if (sa_is_v4mapped(sa)) handshake->initialize_incoming(this, fd, sa_from_v4mapped(sa).get(), config::network_config()->encryption_options()); else handshake->initialize_incoming(this, fd, sa, config::network_config()->encryption_options()); base_type::push_back(std::move(handshake)); } void HandshakeManager::add_outgoing(const sockaddr* sa, DownloadMain* download) { if (!manager->connection_manager()->can_connect() || !manager->connection_manager()->filter(sa)) return; auto encryption_options = config::network_config()->encryption_options(); if (download->info()->is_meta_download()) { encryption_options &= ~net::NetworkConfig::encryption_try_outgoing; encryption_options &= ~net::NetworkConfig::encryption_require; encryption_options &= ~net::NetworkConfig::encryption_require_RC4; encryption_options &= ~net::NetworkConfig::encryption_enable_retry; } if (sa_is_v4mapped(sa)) create_outgoing(sa_from_v4mapped(sa).get(), download, encryption_options); else create_outgoing(sa, download, encryption_options); } void HandshakeManager::create_outgoing(const sockaddr* sa, DownloadMain* download, int encryption_options) { int connection_options = PeerList::connect_keep_handshakes; if (!(encryption_options & net::NetworkConfig::encryption_retrying)) connection_options |= PeerList::connect_filter_recent; PeerInfo* peer_info = download->peer_list()->connected(sa, connection_options); if (peer_info == NULL || peer_info->failed_counter() > max_failed) { LT_LOG_SA(sa, "rejected outgoing connection: no peer info or too many failures", 0); return; } auto connect_address = sa_copy(sa); auto proxy_address = config::network_config()->proxy_address(); if (proxy_address->sa_family != AF_UNSPEC) { connect_address = sa_copy(proxy_address.get()); encryption_options |= net::NetworkConfig::encryption_use_proxy; } auto handshake = std::make_unique(); auto open_func = [&]() { int fd = open_and_connect_socket(connect_address.get()); if (fd == -1) return; int message; if (encryption_options & net::NetworkConfig::encryption_use_proxy) message = ConnectionManager::handshake_outgoing_proxy; else if (encryption_options & (net::NetworkConfig::encryption_try_outgoing | net::NetworkConfig::encryption_require)) message = ConnectionManager::handshake_outgoing_encrypted; else message = ConnectionManager::handshake_outgoing; if (proxy_address->sa_family != AF_UNSPEC) { LT_LOG_SA(sa, "created outgoing connection via proxy: fd:%i proxy:%s encryption:%x message:%x", fd, sa_addr_str(proxy_address.get()).c_str(), encryption_options, message); } else { LT_LOG_SA(sa, "created outgoing connection: fd:%i encryption:%x message:%x", fd, encryption_options, message); } handshake->initialize_outgoing(this, fd, sa, encryption_options, download, peer_info); }; auto cleanup_func = [&]() { if (!handshake->is_open()) { LT_LOG_SA(sa, "failed to create outgoing connection: open failed", 0); download->peer_list()->disconnected(peer_info, 0); return; } LT_LOG_SA(sa, "failed to create outgoing connection : socket manager triggered cleanup", 0); handshake->destroy_connection(false); }; runtime::socket_manager()->open_event_or_cleanup(handshake.get(), open_func, cleanup_func); if (!handshake->is_open()) return; manager->connection_manager()->inc_socket_count(); base_type::push_back(std::move(handshake)); } void HandshakeManager::receive_succeeded(Handshake* ptr) { if (!ptr->is_active()) throw internal_error("HandshakeManager::receive_succeeded(...) called on an inactive handshake."); auto handshake = find_and_erase(ptr); auto download = handshake->download(); auto peer_type = handshake->bitfield()->is_all_set() ? "seed" : "leech"; auto hash_str = utils::copy_escape_html_str(handshake->peer_info()->id()); auto error_func = [&](uint32_t reason) { LT_LOG_SA(handshake->peer_info()->socket_address(), "handshake dropped: type:%s id:%s reason:'%s'", peer_type, hash_str.c_str(), strerror(reason)); }; if (!download->info()->is_active()) { error_func(e_handshake_inactive_download); handshake->destroy_connection(); return; } if (!download->connection_list()->want_connection(handshake->peer_info(), handshake->bitfield())) { error_func(e_handshake_unwanted_connection); handshake->destroy_connection(); return; } auto fd = handshake->file_descriptor(); auto peer_info = handshake->peer_info(); auto new_event = runtime::socket_manager()->transfer_event(handshake.get(), [&]() -> Event* { LT_LOG_SA(peer_info->socket_address(), "transfering handshake: type:%s id:%s", peer_type, hash_str.c_str()); handshake->release_connection(); return download->connection_list()->insert(peer_info, fd, handshake->bitfield(), handshake->encryption()->info(), handshake->extensions()); }); if (new_event == nullptr) { fd_close(fd); manager->connection_manager()->dec_socket_count(); download->peer_list()->disconnected(peer_info, 0); lt_log_print(LOG_CONNECTION_HANDSHAKE, "handshake_manager: duplicate peer: type:%s id:%s", peer_type, hash_str.c_str()); return; } auto pcb = static_cast(new_event); manager->client_list()->retrieve_id(&peer_info->mutable_client_info(), peer_info->id()); pcb->peer_chunks()->set_have_timer(handshake->initialized_time()); LT_LOG_SA(peer_info->socket_address(), "handshake success: type:%s id:%s", peer_type, hash_str.c_str()); if (handshake->unread_size() != 0) { if (handshake->unread_size() > PeerConnectionBase::ProtocolRead::buffer_size) throw internal_error("HandshakeManager::receive_succeeded(...) Unread data won't fit PCB's read buffer."); pcb->push_unread(handshake->unread_data(), handshake->unread_size()); pcb->event_read(); } } void HandshakeManager::receive_failed(Handshake* ptr, int message, int error) { if (!ptr->is_active()) throw internal_error("HandshakeManager::receive_failed(...) called on an inactive handshake."); auto handshake = find_and_erase(ptr); auto sa = handshake->socket_address(); handshake->destroy_connection(); LT_LOG_SA(sa, "Received error: message:%x %s.", message, strerror(error)); if (handshake->encryption()->should_retry()) { int retry_options = handshake->retry_options() | net::NetworkConfig::encryption_retrying; DownloadMain* download = handshake->download(); LT_LOG_SA(sa, "Retrying %s.", retry_options & net::NetworkConfig::encryption_try_outgoing ? "encrypted" : "plaintext"); create_outgoing(sa, download, retry_options); } } void HandshakeManager::receive_timeout(Handshake* h) { receive_failed(h, ConnectionManager::handshake_failed, h->state() == Handshake::CONNECTING ? e_handshake_network_unreachable : e_handshake_network_timeout); } int HandshakeManager::open_and_connect_socket(const sockaddr* connect_address) { auto bind_address = config::network_config()->bind_address_for_connect(connect_address->sa_family); if (bind_address == nullptr) { LT_LOG_SA(connect_address, "could not create outgoing connection: blocked or invalid bind address", 0); return -1; } int fd = fd_open_family(fd_flag_stream | fd_flag_nonblock, connect_address->sa_family); if (fd == -1) { LT_LOG_SA(connect_address, "could not create outgoing connection: open stream failed : fd:%i : %s", fd, std::strerror(errno)); return -1; } if (!setup_socket(fd, connect_address->sa_family)) { LT_LOG_SA(connect_address, "could not create outgoing connection: setup socket failed : fd:%i : %s", fd, std::strerror(errno)); fd_close(fd); return -1; } if (!sa_is_any(bind_address.get()) && !fd_bind(fd, bind_address.get())) { LT_LOG_SA(connect_address, "could not create outgoing connection: bind failed : fd:%i : %s", fd, std::strerror(errno)); fd_close(fd); return -1; } if (!fd_connect_with_family(fd, connect_address, bind_address->sa_family)) { LT_LOG_SA(connect_address, "could not create outgoing connection: connect failed : fd:%i : %s", fd, std::strerror(errno)); fd_close(fd); return -1; } return fd; } bool HandshakeManager::setup_socket(int fd, int family) { auto priority = config::network_config()->priority(); auto send_buffer_size = config::network_config()->send_buffer_size(); auto recv_buffer_size = config::network_config()->receive_buffer_size(); errno = 0; if (priority != net::NetworkConfig::iptos_default && !fd_set_priority(fd, family, priority)) return false; if (send_buffer_size != 0 && !fd_set_send_buffer_size(fd, send_buffer_size)) return false; if (recv_buffer_size != 0 && !fd_set_receive_buffer_size(fd, recv_buffer_size)) return false; return true; } } // namespace torrent libtorrent-0.16.11/src/protocol/handshake_encryption.h0000644000000000000000000000605615175073411016507 #ifndef LIBTORRENT_PROTOCOL_HANDSHAKE_ENCRYPTION_H #define LIBTORRENT_PROTOCOL_HANDSHAKE_ENCRYPTION_H #include #include #include "encryption_info.h" namespace torrent { class DiffieHellman; class HandshakeEncryption { public: enum Retry { RETRY_NONE, RETRY_PLAIN, RETRY_ENCRYPTED, }; static constexpr int crypto_plain = 1; static constexpr int crypto_rc4 = 2; static const unsigned char dh_prime[]; static constexpr unsigned int dh_prime_length = 96; static const unsigned char dh_generator[]; static constexpr unsigned int dh_generator_length = 1; static const unsigned char vc_data[]; static constexpr unsigned int vc_length = 8; HandshakeEncryption(int options); bool has_crypto_plain() const { return m_crypto & crypto_plain; } bool has_crypto_rc4() const { return m_crypto & crypto_rc4; } const auto& key() { return m_key; } EncryptionInfo* info() { return &m_info; } int options() const { return m_options; } int crypto() const { return m_crypto; } void set_crypto(int val) { m_crypto = val; } Retry retry() const { return m_retry; } void set_retry(Retry val) { m_retry = val; } bool should_retry() const; const char* sync() const { return m_sync; } unsigned int sync_length() const { return m_syncLength; } void set_sync(const char* src, unsigned int len) { std::memcpy(m_sync, src, (m_syncLength = len)); } char* modify_sync(unsigned int len) { m_syncLength = len; return m_sync; } unsigned int length_ia() const { return m_lengthIA; } void set_length_ia(unsigned int len) { m_lengthIA = len; } bool initialize(); void cleanup(); void initialize_decrypt(const char* origHash, bool incoming); void initialize_encrypt(const char* origHash, bool incoming); void deobfuscate_hash(char* src) const; void hash_req1_to_sync(); void encrypt_vc_to_sync(const char* origHash); static void copy_vc(void* dest) { std::memset(dest, 0, vc_length); } static bool compare_vc(const void* buf); private: std::unique_ptr m_key; // A pointer instead? EncryptionInfo m_info; int m_options; int m_crypto{0}; Retry m_retry{RETRY_NONE}; char m_sync[20]; unsigned int m_syncLength{0}; unsigned int m_lengthIA{0}; }; } // namespace torrent #endif libtorrent-0.16.11/src/protocol/handshake.cc0000644000000000000000000012016415175073411014370 #include "config.h" #include "handshake.h" #include #include #include "manager.h" #include "download/download_main.h" #include "net/throttle_list.h" #include "protocol/extensions.h" #include "protocol/handshake_manager.h" #include "torrent/download_info.h" #include "torrent/error.h" #include "torrent/exceptions.h" #include "torrent/throttle.h" #include "torrent/net/fd.h" #include "torrent/net/network_config.h" #include "torrent/net/poll.h" #include "torrent/runtime/network_manager.h" #include "torrent/runtime/socket_manager.h" #include "torrent/utils/log.h" #include "torrent/utils/string_manip.h" #include "utils/diffie_hellman.h" #include "utils/sha1.h" #if DISABLED__USE_EXTRA_DEBUG #define LT_LOG_EXTRA_DEBUG_SA(sa, log_fmt, ...) \ lt_log_print(LOG_CONNECTION_HANDSHAKE, "handshake->%s: " log_fmt, sap_pretty_str(m_address).c_str(), __VA_ARGS__); #else #define LT_LOG_EXTRA_DEBUG_SA(sa, log_fmt, ...) #endif namespace { class handshake_succeeded : public torrent::network_error { }; class handshake_error : public torrent::network_error { public: handshake_error(int type, int error) : m_type(type), m_error(error) {} const char* what() const noexcept override { return "Handshake error"; } int type() const noexcept { return m_type; } int error() const noexcept { return m_error; } private: int m_type; int m_error; }; } // namespace namespace torrent { Handshake::Handshake() : m_encryption(HandshakeEncryption::RETRY_NONE), m_extensions(HandshakeManager::default_extensions()) { m_readBuffer.reset(); m_writeBuffer.reset(); } Handshake::~Handshake() { assert(!m_task_timeout.is_scheduled()); assert(!is_open()); m_encryption.cleanup(); } void Handshake::set_manager(HandshakeManager* handshake_manager) { m_manager = handshake_manager; m_upload_throttle = manager->upload_throttle()->throttle_list(); m_download_throttle = manager->download_throttle()->throttle_list(); m_task_timeout.slot() = [this, handshake_manager] { handshake_manager->receive_timeout(this); }; } void Handshake::initialize_incoming(HandshakeManager* handshake_manager, int fd, const sockaddr* sa, int encryption_options) { set_manager(handshake_manager); m_incoming = true; m_address = sa_copy(sa); m_encryption = encryption_options; if (m_encryption.options() & (net::NetworkConfig::encryption_allow_incoming | net::NetworkConfig::encryption_require)) m_state = READ_ENC_KEY; else m_state = READ_INFO; set_file_descriptor(fd); this_thread::poll()->open(this); this_thread::poll()->insert_read(this); this_thread::poll()->insert_error(this); // Use lower timeout here. this_thread::scheduler()->wait_for_ceil_seconds(&m_task_timeout, 60s); } void Handshake::initialize_outgoing(HandshakeManager* handshake_manager, int fd, const sockaddr* sa, int encryption_options, DownloadMain* d, PeerInfo* peerInfo) { set_manager(handshake_manager); m_download = d; m_peerInfo = peerInfo; m_peerInfo->set_flags(PeerInfo::flag_handshake); m_incoming = false; m_address = sa_copy(sa); m_encryption = encryption_options; std::make_pair(m_upload_throttle, m_download_throttle) = m_download->throttles(m_address.get()); m_state = CONNECTING; set_file_descriptor(fd); this_thread::poll()->open(this); this_thread::poll()->insert_write(this); this_thread::poll()->insert_error(this); this_thread::scheduler()->wait_for_ceil_seconds(&m_task_timeout, 60s); } void Handshake::release_connection() { if (!is_open()) throw internal_error("Handshake::release_connection called but m_fd is not open."); this_thread::scheduler()->erase(&m_task_timeout); this_thread::poll()->remove_and_close(this); m_peerInfo->unset_flags(PeerInfo::flag_handshake); m_peerInfo = nullptr; m_state = INACTIVE; set_file_descriptor(-1); } void Handshake::destroy_connection(bool use_socket_manager) { this_thread::scheduler()->erase(&m_task_timeout); if (!is_open()) throw internal_error("Handshake::destroy_connection called but m_fd is not open."); m_state = INACTIVE; auto fn = [this]() { this_thread::poll()->remove_and_close(this); fd_close(m_fileDesc); set_file_descriptor(-1); }; try { if (use_socket_manager) runtime::socket_manager()->close_event_or_throw(this, fn); else fn(); } catch (...) { if (is_polling()) this_thread::poll()->remove_and_close(this); if (is_open()) { fd_close(m_fileDesc); set_file_descriptor(-1); } throw; } manager->connection_manager()->dec_socket_count(); if (m_peerInfo == NULL) return; // TODO: This should throw. m_download->peer_list()->disconnected(m_peerInfo, 0); m_peerInfo->unset_flags(PeerInfo::flag_handshake); m_peerInfo = NULL; if (!m_extensions->is_default()) { m_extensions->cleanup(); delete m_extensions; } } int Handshake::retry_options() { uint32_t options = m_encryption.options() & ~net::NetworkConfig::encryption_enable_retry; if (m_encryption.retry() == HandshakeEncryption::RETRY_PLAIN) options &= ~net::NetworkConfig::encryption_try_outgoing; else if (m_encryption.retry() == HandshakeEncryption::RETRY_ENCRYPTED) options |= net::NetworkConfig::encryption_try_outgoing; else throw internal_error("Invalid retry type."); return options; } inline uint32_t Handshake::read_unthrottled(void* buf, uint32_t length) { return m_download_throttle->node_used_unthrottled(read_stream_throws(buf, length)); } inline uint32_t Handshake::write_unthrottled(const void* buf, uint32_t length) { return m_upload_throttle->node_used_unthrottled(write_stream_throws(buf, length)); } // Handshake::read_proxy_connect() // Entry: 0, 0 // * 0, [0, 508> bool Handshake::read_proxy_connect() { // Being greedy for now. m_readBuffer.move_end(read_unthrottled(m_readBuffer.end(), 512)); const char* pattern = "\r\n\r\n"; const unsigned int patternLength = 4; if (m_readBuffer.remaining() < patternLength) return false; auto itr = std::search(m_readBuffer.begin(), m_readBuffer.end(), reinterpret_cast(pattern), reinterpret_cast(pattern) + patternLength); m_readBuffer.set_position_itr(itr != m_readBuffer.end() ? (itr + patternLength) : (itr - patternLength)); m_readBuffer.move_unused(); return itr != m_readBuffer.end(); } // Handshake::read_encryption_key() // Entry: * 0, [0, 508> // IU 20, [20, enc_pad_read_size> // *E 96, [96, enc_pad_read_size> bool Handshake::read_encryption_key() { if (m_incoming) { if (m_readBuffer.remaining() < 20) m_readBuffer.move_end(read_unthrottled(m_readBuffer.end(), 20 - m_readBuffer.remaining())); if (m_readBuffer.remaining() < 20) return false; if (m_readBuffer.peek_8() == 19 && std::memcmp(m_readBuffer.position() + 1, m_protocol, 19) == 0) { // got unencrypted BT handshake if (m_encryption.options() & net::NetworkConfig::encryption_require) throw handshake_error(ConnectionManager::handshake_dropped, e_handshake_unencrypted_rejected); m_state = READ_INFO; return true; } } // Read as much of key, pad and sync string as we can; this is safe // because peer can't send anything beyond the initial BT handshake // because it doesn't know our encryption choice yet. if (m_readBuffer.remaining() < enc_pad_read_size) m_readBuffer.move_end(read_unthrottled(m_readBuffer.end(), enc_pad_read_size - m_readBuffer.remaining())); // but we need at least the key at this point if (m_readBuffer.size_end() < 96) return false; // If the handshake fails after this, it wasn't because the peer // doesn't like encrypted connections, so don't retry unencrypted. m_encryption.set_retry(HandshakeEncryption::RETRY_NONE); if (m_incoming) prepare_key_plus_pad(); if(!m_encryption.key()->compute_secret(m_readBuffer.position(), 96)) throw handshake_error(ConnectionManager::handshake_failed, e_handshake_invalid_encryption); m_readBuffer.consume(96); // Determine the synchronisation string. if (m_incoming) m_encryption.hash_req1_to_sync(); else m_encryption.encrypt_vc_to_sync(m_download->info()->hash().c_str()); // also put as much as we can write so far in the buffer if (!m_incoming) prepare_enc_negotiation(); m_state = READ_ENC_SYNC; return true; } // Handshake::read_encryption_sync() // *E 96, [96, enc_pad_read_size> bool Handshake::read_encryption_sync() { // Check if we've read the sync string already in the previous // state. This is very likely and avoids an unneeded read. auto itr = std::search(m_readBuffer.position(), m_readBuffer.end(), reinterpret_cast(m_encryption.sync()), reinterpret_cast(m_encryption.sync()) + m_encryption.sync_length()); if (itr == m_readBuffer.end()) { // Otherwise read as many bytes as possible until we find the sync // string. int toRead = enc_pad_size + m_encryption.sync_length() - m_readBuffer.remaining(); if (toRead <= 0) throw handshake_error(ConnectionManager::handshake_failed, e_handshake_encryption_sync_failed); m_readBuffer.move_end(read_unthrottled(m_readBuffer.end(), toRead)); itr = std::search(m_readBuffer.position(), m_readBuffer.end(), reinterpret_cast(m_encryption.sync()), reinterpret_cast(m_encryption.sync()) + m_encryption.sync_length()); if (itr == m_readBuffer.end()) return false; } if (m_incoming) { // We've found HASH('req1' + S), skip that and go on reading the // SKEY hash. m_readBuffer.consume(std::distance(m_readBuffer.position(), itr) + 20); m_state = READ_ENC_SKEY; } else { m_readBuffer.consume(std::distance(m_readBuffer.position(), itr)); m_state = READ_ENC_NEGOT; } return true; } bool Handshake::read_encryption_skey() { LT_LOG_EXTRA_DEBUG_SA(m_address, "read_encryption_skey", 0) if (!fill_read_buffer(20)) return false; m_encryption.deobfuscate_hash(reinterpret_cast(m_readBuffer.position())); m_download = m_manager->download_info_obfuscated(reinterpret_cast(m_readBuffer.position())); m_readBuffer.consume(20); validate_download(); // We don't allow encrypted connections for meta-data downloads. if (m_download->info()->is_meta_download()) throw handshake_error(ConnectionManager::handshake_dropped, e_handshake_invalid_encryption); std::make_pair(m_upload_throttle, m_download_throttle) = m_download->throttles(m_address.get()); m_encryption.initialize_encrypt(m_download->info()->hash().c_str(), m_incoming); m_encryption.initialize_decrypt(m_download->info()->hash().c_str(), m_incoming); m_encryption.info()->decrypt(m_readBuffer.position(), m_readBuffer.remaining()); HandshakeEncryption::copy_vc(m_writeBuffer.end()); m_encryption.info()->encrypt(m_writeBuffer.end(), HandshakeEncryption::vc_length); m_writeBuffer.move_end(HandshakeEncryption::vc_length); m_state = READ_ENC_NEGOT; return true; } bool Handshake::read_encryption_negotiation() { LT_LOG_EXTRA_DEBUG_SA(m_address, "read_encryption_negotiation", 0) if (!fill_read_buffer(enc_negotiation_size)) return false; if (!m_incoming) { // Start decrypting, but don't decrypt beyond the initial // encrypted handshake and later the pad because we may have read // too much data which may be unencrypted if the peer chose that // option. m_encryption.initialize_decrypt(m_download->info()->hash().c_str(), m_incoming); m_encryption.info()->decrypt(m_readBuffer.position(), enc_negotiation_size); } if (!HandshakeEncryption::compare_vc(m_readBuffer.position())) throw handshake_error(ConnectionManager::handshake_failed, e_handshake_invalid_value); m_readBuffer.consume(HandshakeEncryption::vc_length); m_encryption.set_crypto(m_readBuffer.read_32()); m_readPos = m_readBuffer.read_16(); // length of padC/padD if (m_readPos > enc_pad_size) throw handshake_error(ConnectionManager::handshake_failed, e_handshake_invalid_value); // choose one of the offered encryptions, or check the chosen one is valid if (m_incoming) { if ((m_encryption.options() & net::NetworkConfig::encryption_prefer_plaintext) && m_encryption.has_crypto_plain()) { m_encryption.set_crypto(HandshakeEncryption::crypto_plain); } else if ((m_encryption.options() & net::NetworkConfig::encryption_require_RC4) && !m_encryption.has_crypto_rc4()) { throw handshake_error(ConnectionManager::handshake_dropped, e_handshake_unencrypted_rejected); } else if (m_encryption.has_crypto_rc4()) { m_encryption.set_crypto(HandshakeEncryption::crypto_rc4); } else if (m_encryption.has_crypto_plain()) { m_encryption.set_crypto(HandshakeEncryption::crypto_plain); } else { throw handshake_error(ConnectionManager::handshake_failed, e_handshake_invalid_encryption); } // at this point we can also write the rest of our negotiation reply m_writeBuffer.write_32(m_encryption.crypto()); m_writeBuffer.write_16(0); m_encryption.info()->encrypt(m_writeBuffer.end() - 4 - 2, 4 + 2); } else { if (m_encryption.crypto() != HandshakeEncryption::crypto_rc4 && m_encryption.crypto() != HandshakeEncryption::crypto_plain) throw handshake_error(ConnectionManager::handshake_failed, e_handshake_invalid_encryption); if ((m_encryption.options() & net::NetworkConfig::encryption_require_RC4) && (m_encryption.crypto() != HandshakeEncryption::crypto_rc4)) throw handshake_error(ConnectionManager::handshake_failed, e_handshake_invalid_encryption); } if (!m_incoming) { // decrypt appropriate part of buffer: only pad or all if (m_encryption.crypto() == HandshakeEncryption::crypto_plain) m_encryption.info()->decrypt(m_readBuffer.position(), std::min(m_readPos, m_readBuffer.remaining())); else m_encryption.info()->decrypt(m_readBuffer.position(), m_readBuffer.remaining()); } // next, skip padC/padD m_state = READ_ENC_PAD; return true; } bool Handshake::read_negotiation_reply() { if (!m_incoming) { if (m_encryption.crypto() != HandshakeEncryption::crypto_rc4) m_encryption.info()->set_obfuscated(); m_state = READ_INFO; return true; } LT_LOG_EXTRA_DEBUG_SA(m_address, "read_negotiation_reply", 0) if (!fill_read_buffer(2)) return false; // The peer may send initial payload that is RC4 encrypted even if // we have selected plaintext encryption, so read it ahead of BT // handshake. m_encryption.set_length_ia(m_readBuffer.read_16()); if (m_encryption.length_ia() > handshake_size) throw handshake_error(ConnectionManager::handshake_failed, e_handshake_invalid_value); m_state = READ_ENC_IA; return true; } bool Handshake::read_info() { LT_LOG_EXTRA_DEBUG_SA(m_address, "read_info", 0) fill_read_buffer(handshake_size); // Check the first byte as early as possible so we can // disconnect non-BT connections if they send less than 20 bytes. if ((m_readBuffer.remaining() >= 1 && m_readBuffer.peek_8() != 19) || (m_readBuffer.remaining() >= 20 && (std::memcmp(m_readBuffer.position() + 1, m_protocol, 19) != 0))) throw handshake_error(ConnectionManager::handshake_failed, e_handshake_not_bittorrent); if (m_readBuffer.remaining() < part1_size) return false; // If the handshake fails after this, it isn't being rejected because // it is unencrypted, so don't retry. m_encryption.set_retry(HandshakeEncryption::RETRY_NONE); m_readBuffer.consume(20); // Should do some option field stuff here, for now just copy. m_readBuffer.read_range(m_options, m_options + 8); // Check the info hash. if (m_incoming) { if (m_download != NULL) { // Have the download from the encrypted handshake, make sure it // matches the BT handshake. if (m_download->info()->hash().not_equal_to(reinterpret_cast(m_readBuffer.position()))) throw handshake_error(ConnectionManager::handshake_failed, e_handshake_invalid_value); } else { m_download = m_manager->download_info(reinterpret_cast(m_readBuffer.position())); } validate_download(); std::make_pair(m_upload_throttle, m_download_throttle) = m_download->throttles(m_address.get()); prepare_handshake(); } else { if (m_download->info()->hash().not_equal_to(reinterpret_cast(m_readBuffer.position()))) throw handshake_error(ConnectionManager::handshake_failed, e_handshake_invalid_value); } m_readBuffer.consume(20); m_state = READ_PEER; return true; } bool Handshake::read_peer() { LT_LOG_EXTRA_DEBUG_SA(m_address, "read_peer", 0) if (!fill_read_buffer(20)) return false; prepare_peer_info(); // Send EXTENSION_PROTOCOL handshake message if peer supports it. if (m_peerInfo->supports_extensions()) write_extension_handshake(); // Replay HAVE messages we receive after starting to send the bitfield. // This avoids replaying HAVEs for pieces received between starting the // handshake and now (e.g. when connecting takes longer). Ideally we // should make a snapshot of the bitfield here in case it changes while // we're sending it (if it can't be sent in one write() call). m_initialized_time = this_thread::cached_time(); // The download is just starting so we're not sending any // bitfield. Pretend we wrote it already. if (m_download->file_list()->bitfield()->is_all_unset() || m_download->initial_seeding() != NULL) { m_writePos = m_download->file_list()->bitfield()->size_bytes(); m_writeBuffer.write_32(0); if (m_encryption.info()->is_encrypted()) m_encryption.info()->encrypt(m_writeBuffer.end() - 4, 4); } else { prepare_bitfield(); } m_state = READ_MESSAGE; this_thread::poll()->insert_write(this); // Give some extra time for reading/writing the bitfield. this_thread::scheduler()->update_wait_for_ceil_seconds(&m_task_timeout, 120s); return true; } bool Handshake::read_bitfield() { LT_LOG_EXTRA_DEBUG_SA(m_address, "read_bitfield: size:%" PRIu32, m_bitfield.size_bytes()); if (m_readPos < m_bitfield.size_bytes()) { uint32_t length = read_unthrottled(m_bitfield.begin() + m_readPos, m_bitfield.size_bytes() - m_readPos); if (m_encryption.info()->decrypt_valid()) m_encryption.info()->decrypt(m_bitfield.begin() + m_readPos, length); m_readPos += length; } return m_readPos == m_bitfield.size_bytes(); } bool Handshake::read_extension() { if (m_readBuffer.peek_32() > m_readBuffer.reserved()) throw handshake_error(ConnectionManager::handshake_failed, e_handshake_invalid_value); int32_t need = m_readBuffer.peek_32() + 4 - m_readBuffer.remaining(); // We currently can't handle an extension handshake that doesn't // completely fit in the buffer. However these messages are usually // ~100 bytes large and the buffer holds over 1000 bytes so it // should be ok. Else maybe figure out how to disable extensions for // when peer connects next time. // // In addition, make sure there's at least 5 bytes available after // the PEX message has been read, so that we can fit the preamble of // the BITFIELD message. if (need + 5 > m_readBuffer.reserved_left()) { m_readBuffer.move_unused(); if (need + 5 > m_readBuffer.reserved_left()) throw handshake_error(ConnectionManager::handshake_failed, e_handshake_invalid_value); } LT_LOG_EXTRA_DEBUG_SA(m_address, "read_extension", 0) if (!fill_read_buffer(m_readBuffer.peek_32() + 4)) return false; uint32_t length = m_readBuffer.read_32() - 2; m_readBuffer.read_8(); m_extensions->read_start(m_readBuffer.read_8(), length, false); std::memcpy(m_extensions->read_position(), m_readBuffer.position(), length); m_extensions->read_move(length); // Does this check need to check if it is a handshake we read? if (!m_extensions->is_complete()) throw internal_error("Could not read extension handshake even though it should be in the read buffer."); m_extensions->read_done(); m_readBuffer.consume(length); return true; } bool Handshake::read_port() { if (m_readBuffer.peek_32() > m_readBuffer.reserved()) throw handshake_error(ConnectionManager::handshake_failed, e_handshake_invalid_value); int32_t need = m_readBuffer.peek_32() + 4 - m_readBuffer.remaining(); if (need + 5 > m_readBuffer.reserved_left()) { m_readBuffer.move_unused(); if (need + 5 > m_readBuffer.reserved_left()) throw handshake_error(ConnectionManager::handshake_failed, e_handshake_invalid_value); } LT_LOG_EXTRA_DEBUG_SA(m_address, "read_port", 0) if (!fill_read_buffer(m_readBuffer.peek_32() + 4)) return false; uint32_t length = m_readBuffer.read_32() - 1; m_readBuffer.read_8(); if (length == 2) runtime::dht_add_peer_node(m_address.get(), m_readBuffer.peek_16()); m_readBuffer.consume(length); return true; } void Handshake::read_done() { if (m_readDone != false) throw internal_error("Handshake::read_done() m_readDone != false."); // if (m_peerInfo->supports_extensions() && m_extensions->is_initial_handshake()) // throw handshake_error(ConnectionManager::handshake_failed, e_handshake_invalid_order); m_readDone = true; this_thread::poll()->remove_read(this); if (m_bitfield.empty()) { m_bitfield.set_size_bits(m_download->file_list()->bitfield()->size_bits()); m_bitfield.allocate(); m_bitfield.unset_all(); } else { m_bitfield.update(); } // Should've started to write post handshake data already, but we were // still reading the bitfield/extension and postponed it. If we had no // bitfield to send, we need to send a keep-alive now. if (m_writePos == m_download->file_list()->bitfield()->size_bytes()) prepare_post_handshake(m_download->file_list()->bitfield()->is_all_unset() || m_download->initial_seeding() != NULL); if (m_writeDone) throw handshake_succeeded(); } void Handshake::event_read() { try { restart: switch (m_state) { case PROXY_CONNECT: if (!read_proxy_connect()) break; m_state = PROXY_DONE; this_thread::poll()->insert_write(this); return event_write(); case READ_ENC_KEY: if (!read_encryption_key()) break; if (m_state != READ_ENC_SYNC) goto restart; [[fallthrough]]; case READ_ENC_SYNC: if (!read_encryption_sync()) break; if (m_state != READ_ENC_SKEY) goto restart; [[fallthrough]]; case READ_ENC_SKEY: if (!read_encryption_skey()) break; [[fallthrough]]; case READ_ENC_NEGOT: if (!read_encryption_negotiation()) break; if (m_state != READ_ENC_PAD) goto restart; [[fallthrough]]; case READ_ENC_PAD: if (m_readPos) { LT_LOG_EXTRA_DEBUG_SA(m_address, "event_read : READ_ENC_PAD : m_readPos:%" PRIu32, m_readPos) // Read padC + lenIA or padD; pad length in m_readPos. if (!fill_read_buffer(m_readPos + (m_incoming ? 2 : 0))) // This can be improved (consume as much as was read) break; m_readBuffer.consume(m_readPos); m_readPos = 0; } if (!read_negotiation_reply()) break; if (m_state != READ_ENC_IA) goto restart; [[fallthrough]]; case READ_ENC_IA: LT_LOG_EXTRA_DEBUG_SA(m_address, "event_read : READ_ENC_IA", 0) // Just read (and automatically decrypt) the initial payload // and leave it in the buffer for READ_INFO later. if (m_encryption.length_ia() > 0 && !fill_read_buffer(m_encryption.length_ia())) break; if (m_readBuffer.remaining() > m_encryption.length_ia()) throw handshake_error(ConnectionManager::handshake_failed, e_handshake_invalid_value); if (m_encryption.crypto() != HandshakeEncryption::crypto_rc4) m_encryption.info()->set_obfuscated(); m_state = READ_INFO; [[fallthrough]]; case READ_INFO: if (!read_info()) break; if (m_state != READ_PEER) goto restart; [[fallthrough]]; case READ_PEER: if (!read_peer()) break; // Is this correct? if (m_state != READ_MESSAGE) goto restart; [[fallthrough]]; case READ_MESSAGE: case POST_HANDSHAKE: // For meta-downloads, we aren't interested in the bitfield or // extension messages here, PCMetadata handles all that. The // bitfield only refers to the single-chunk meta-data, so fake that. if (m_download->info()->is_meta_download()) { m_bitfield.set_size_bits(1); m_bitfield.allocate(); m_bitfield.set(0); read_done(); break; } LT_LOG_EXTRA_DEBUG_SA(m_address, "event_read : READ_MESSAGE", 0); if (m_readBuffer.reserved_left() < 5) m_readBuffer.move_unused(); fill_read_buffer(5); // Received a keep-alive message which means we won't be // getting any bitfield. if (m_readBuffer.remaining() >= 4 && m_readBuffer.peek_32() == 0) { m_readBuffer.read_32(); read_done(); break; } if (m_readBuffer.remaining() < 5) break; m_readPos = 0; // Extension handshake was sent after BT handshake but before // bitfield, so handle that. If we've already received a message // of this type then we will assume the peer won't be sending a // bitfield, as the second extension message will be part of the // normal traffic, not the handshake. if (m_readBuffer.peek_8_at(4) == protocol_bitfield) { const Bitfield* bitfield = m_download->file_list()->bitfield(); if (!m_bitfield.empty() || m_readBuffer.read_32() != bitfield->size_bytes() + 1) throw handshake_error(ConnectionManager::handshake_failed, e_handshake_invalid_value); m_readBuffer.read_8(); m_bitfield.set_size_bits(bitfield->size_bits()); m_bitfield.allocate(); m_readPos = std::min(m_bitfield.size_bytes(), m_readBuffer.remaining()); std::memcpy(m_bitfield.begin(), m_readBuffer.position(), m_readPos); m_readBuffer.consume(m_readPos); m_state = READ_BITFIELD; } else if (m_readBuffer.peek_8_at(4) == protocol_extension && m_extensions->is_initial_handshake()) { m_readPos = 0; m_state = READ_EXT; } else if (m_readBuffer.peek_8_at(4) == protocol_port) { // Some peers seem to send the port message before handshake, // so handle it here. m_readPos = 0; m_state = READ_PORT; } else { read_done(); break; } [[fallthrough]]; case READ_BITFIELD: case READ_EXT: case READ_PORT: // Gather the different command types into the same case group // so that we don't need 'goto restart' above. if ((m_state == READ_BITFIELD && !read_bitfield()) || (m_state == READ_EXT && !read_extension()) || (m_state == READ_PORT && !read_port())) break; m_state = READ_MESSAGE; if (!m_bitfield.empty() && (!m_peerInfo->supports_extensions() || !m_extensions->is_initial_handshake())) { read_done(); break; } goto restart; default: throw internal_error("Handshake::event_read() called in invalid state."); } // Call event_write if we have any data to write. Make sure // event_write() doesn't get called twice in this function. if (m_writeBuffer.remaining() && !this_thread::poll()->in_write(this)) { this_thread::poll()->insert_write(this); return event_write(); } } catch (const handshake_succeeded&) { m_manager->receive_succeeded(this); } catch (const handshake_error& e) { m_manager->receive_failed(this, e.type(), e.error()); } catch (const network_error&) { m_manager->receive_failed(this, ConnectionManager::handshake_failed, e_handshake_network_read_error); } } bool Handshake::fill_read_buffer(int size) { LT_LOG_EXTRA_DEBUG_SA(m_address, "fill_read_buffer : size:%i remaining:%" PRIu16 " reserved_left:%" PRIu16, size, m_readBuffer.remaining(), m_readBuffer.reserved_left()) if (m_readBuffer.remaining() < size) { if (size - m_readBuffer.remaining() > m_readBuffer.reserved_left()) throw internal_error("Handshake::fill_read_buffer(...) Buffer overflow."); int read = m_readBuffer.move_end(read_unthrottled(m_readBuffer.end(), size - m_readBuffer.remaining())); if (m_encryption.info()->decrypt_valid()) m_encryption.info()->decrypt(m_readBuffer.end() - read, read); } return m_readBuffer.remaining() >= size; } inline void Handshake::validate_download() { if (m_download == NULL) throw handshake_error(ConnectionManager::handshake_dropped, e_handshake_unknown_download); if (!m_download->info()->is_active()) throw handshake_error(ConnectionManager::handshake_dropped, e_handshake_inactive_download); if (!m_download->info()->is_accepting_new_peers()) throw handshake_error(ConnectionManager::handshake_dropped, e_handshake_not_accepting_connections); } void Handshake::event_write() { int socket_error; try { switch (m_state) { case CONNECTING: if (!fd_get_socket_error(file_descriptor(), &socket_error)) throw internal_error("Handshake::event_write() fd_get_socket_error failed : " + std::string(strerror(errno))); if (socket_error != 0) throw handshake_error(ConnectionManager::handshake_failed, e_handshake_network_unreachable); this_thread::poll()->insert_read(this); if (m_encryption.options() & net::NetworkConfig::encryption_use_proxy) { prepare_proxy_connect(); m_state = PROXY_CONNECT; break; } [[fallthrough]]; case PROXY_DONE: // If there's any bytes remaining, it means we got a reply from // the other side before our proxy connect command was finished // written. This probably means the other side isn't a proxy. if (m_writeBuffer.remaining()) throw handshake_error(ConnectionManager::handshake_failed, e_handshake_not_bittorrent); m_writeBuffer.reset(); if (m_encryption.options() & (net::NetworkConfig::encryption_try_outgoing | net::NetworkConfig::encryption_require)) { prepare_key_plus_pad(); // if connection fails, peer probably closed it because it was encrypted, so retry encrypted if enabled if (!(m_encryption.options() & net::NetworkConfig::encryption_require)) m_encryption.set_retry(HandshakeEncryption::RETRY_PLAIN); m_state = READ_ENC_KEY; } else { // if connection is closed before we read the handshake, it might // be rejected because it is unencrypted, in that case retry encrypted m_encryption.set_retry(HandshakeEncryption::RETRY_ENCRYPTED); prepare_handshake(); if (m_incoming) m_state = READ_PEER; else m_state = READ_INFO; } break; case READ_MESSAGE: case READ_BITFIELD: case READ_EXT: write_bitfield(); return; default: break; } if (!m_writeBuffer.remaining()) throw internal_error("event_write called with empty write buffer."); if (m_writeBuffer.consume(write_unthrottled(m_writeBuffer.position(), m_writeBuffer.remaining()))) { if (m_state == POST_HANDSHAKE) write_done(); else this_thread::poll()->remove_write(this); } } catch (const handshake_succeeded&) { m_manager->receive_succeeded(this); } catch (const handshake_error& e) { m_manager->receive_failed(this, e.type(), e.error()); } catch (const network_error&) { m_manager->receive_failed(this, ConnectionManager::handshake_failed, e_handshake_network_write_error); } } void Handshake::prepare_proxy_connect() { int advance = snprintf(reinterpret_cast(m_writeBuffer.position()), m_writeBuffer.reserved_left(), "CONNECT %s:%hu HTTP/1.0\r\n\r\n", sap_addr_str(m_address).c_str(), sap_port(m_address)); if (advance == -1 || advance > m_writeBuffer.reserved_left()) throw internal_error("Handshake::prepare_proxy_connect() snprintf failed."); m_writeBuffer.move_end(advance); } void Handshake::prepare_key_plus_pad() { if (!m_encryption.initialize()) throw handshake_error(ConnectionManager::handshake_failed, e_handshake_invalid_value); m_encryption.key()->store_pub_key(m_writeBuffer.end(), 96); m_writeBuffer.move_end(96); const int length = random() % enc_pad_size; auto pad = std::make_unique(length); std::generate_n(pad.get(), length, &::random); m_writeBuffer.write_len(pad.get(), length); } void Handshake::prepare_enc_negotiation() { char hash[20]; // first piece, HASH('req1' + S) sha1_salt("req1", 4, m_encryption.key()->c_str(), m_encryption.key()->size(), m_writeBuffer.end()); m_writeBuffer.move_end(20); // second piece, HASH('req2' + SKEY) ^ HASH('req3' + S) m_writeBuffer.write_len(m_download->info()->hash_obfuscated().c_str(), 20); sha1_salt("req3", 4, m_encryption.key()->c_str(), m_encryption.key()->size(), hash); for (int i = 0; i < 20; i++) m_writeBuffer.end()[i - 20] ^= hash[i]; // last piece, ENCRYPT(VC, crypto_provide, len(PadC), PadC, len(IA)) m_encryption.initialize_encrypt(m_download->info()->hash().c_str(), m_incoming); Buffer::iterator old_end = m_writeBuffer.end(); HandshakeEncryption::copy_vc(m_writeBuffer.end()); m_writeBuffer.move_end(HandshakeEncryption::vc_length); if (m_encryption.options() & net::NetworkConfig::encryption_require_RC4) m_writeBuffer.write_32(HandshakeEncryption::crypto_rc4); else m_writeBuffer.write_32(HandshakeEncryption::crypto_plain | HandshakeEncryption::crypto_rc4); m_writeBuffer.write_16(0); m_writeBuffer.write_16(handshake_size); m_encryption.info()->encrypt(old_end, m_writeBuffer.end() - old_end); // write and encrypt BT handshake as initial payload IA prepare_handshake(); } void Handshake::prepare_handshake() { m_writeBuffer.write_8(19); m_writeBuffer.write_range(m_protocol, m_protocol + 19); std::memset(m_writeBuffer.end(), 0, 8); // Supports extension protocol. *(m_writeBuffer.end()+5) |= 0x10; // Send PORT message. if (runtime::network_manager()->is_dht_active()) *(m_writeBuffer.end()+7) |= 0x01; m_writeBuffer.move_end(8); m_writeBuffer.write_range(m_download->info()->hash().c_str(), m_download->info()->hash().c_str() + 20); m_writeBuffer.write_range(m_download->info()->local_id().c_str(), m_download->info()->local_id().c_str() + 20); if (m_encryption.info()->is_encrypted()) m_encryption.info()->encrypt(m_writeBuffer.end() - handshake_size, handshake_size); } void Handshake::prepare_peer_info() { if (std::memcmp(m_readBuffer.position(), m_download->info()->local_id().c_str(), 20) == 0) throw handshake_error(ConnectionManager::handshake_failed, e_handshake_is_self); // PeerInfo handling for outgoing connections needs to be moved to // HandshakeManager. if (m_peerInfo == NULL) { if (!m_incoming) throw internal_error("Handshake::prepare_peer_info() !m_incoming."); m_peerInfo = m_download->peer_list()->connected(m_address.get(), PeerList::connect_incoming); if (m_peerInfo == NULL) throw handshake_error(ConnectionManager::handshake_failed, e_handshake_no_peer_info); if (m_peerInfo->failed_counter() > torrent::HandshakeManager::max_failed) throw handshake_error(ConnectionManager::handshake_dropped, e_handshake_toomanyfailed); m_peerInfo->set_flags(PeerInfo::flag_handshake); } std::memcpy(m_peerInfo->set_options(), m_options, 8); m_peerInfo->mutable_id().assign(reinterpret_cast(m_readBuffer.position())); m_readBuffer.consume(20); utils::transform_to_hex(m_peerInfo->id(), m_peerInfo->mutable_id_hex(), m_peerInfo->mutable_id_hex() + 40); // For meta downloads, we require support of the extension protocol. if (m_download->info()->is_meta_download() && !m_peerInfo->supports_extensions()) throw handshake_error(ConnectionManager::handshake_dropped, e_handshake_unwanted_connection); } void Handshake::prepare_bitfield() { m_writeBuffer.write_32(m_download->file_list()->bitfield()->size_bytes() + 1); m_writeBuffer.write_8(protocol_bitfield); if (m_encryption.info()->is_encrypted()) m_encryption.info()->encrypt(m_writeBuffer.end() - 5, 5); m_writePos = 0; } void Handshake::prepare_post_handshake(bool must_write) { if (m_writePos != m_download->file_list()->bitfield()->size_bytes()) throw internal_error("Handshake::prepare_post_handshake called while bitfield not written completely."); m_state = POST_HANDSHAKE; Buffer::iterator old_end = m_writeBuffer.end(); // Send PORT message for DHT if enabled and peer supports it. if (m_peerInfo->supports_dht() && runtime::network_manager()->is_dht_active_and_receiving_requests()) { m_writeBuffer.write_32(3); m_writeBuffer.write_8(protocol_port); m_writeBuffer.write_16(runtime::network_manager()->dht_port()); } // Send a keep-alive if we still must send something. if (must_write && old_end == m_writeBuffer.end()) m_writeBuffer.write_32(0); if (m_encryption.info()->is_encrypted()) m_encryption.info()->encrypt(old_end, m_writeBuffer.end() - old_end); if (!m_writeBuffer.remaining()) write_done(); } void Handshake::write_done() { m_writeDone = true; this_thread::poll()->remove_write(this); // Ok to just check m_readDone as the call in event_read() won't // set it before the call. if (m_readDone) throw handshake_succeeded(); } void Handshake::write_extension_handshake() { DownloadInfo* info = m_download->info(); if (m_extensions->is_default()) { m_extensions = new ProtocolExtension; m_extensions->set_info(m_peerInfo, m_download); } // PEX may be disabled but still active if disabled since last download tick. if (info->is_pex_enabled() && info->is_pex_active() && info->size_pex() < info->max_size_pex()) m_extensions->set_local_enabled(ProtocolExtension::UT_PEX); DataBuffer message = m_extensions->generate_handshake_message(); m_writeBuffer.write_32(message.length() + 2); m_writeBuffer.write_8(protocol_extension); m_writeBuffer.write_8(ProtocolExtension::HANDSHAKE); m_writeBuffer.write_range(message.data(), message.end()); if (m_encryption.info()->is_encrypted()) m_encryption.info()->encrypt(m_writeBuffer.end() - message.length() - 2 - 4, message.length() + 2 + 4); message.clear(); } void Handshake::write_bitfield() { const Bitfield* bitfield = m_download->file_list()->bitfield(); if (m_writeDone != false) throw internal_error("Handshake::event_write() m_writeDone != false."); if (m_writeBuffer.remaining()) if (!m_writeBuffer.consume(write_unthrottled(m_writeBuffer.position(), m_writeBuffer.remaining()))) return; if (m_writePos != bitfield->size_bytes()) { if (m_encryption.info()->is_encrypted()) { if (m_writePos == 0) m_writeBuffer.reset(); // this should be unnecessary now uint32_t length = std::min(bitfield->size_bytes() - m_writePos, m_writeBuffer.reserved()) - m_writeBuffer.size_end(); if (length > 0) { std::memcpy(m_writeBuffer.end(), bitfield->begin() + m_writePos + m_writeBuffer.size_end(), length); m_encryption.info()->encrypt(m_writeBuffer.end(), length); m_writeBuffer.move_end(length); } length = write_unthrottled(m_writeBuffer.begin(), m_writeBuffer.size_end()); m_writePos += length; if (length != m_writeBuffer.size_end() && length > 0) std::memmove(m_writeBuffer.begin(), m_writeBuffer.begin() + length, m_writeBuffer.size_end() - length); m_writeBuffer.move_end(-length); } else { m_writePos += write_unthrottled(bitfield->begin() + m_writePos, bitfield->size_bytes() - m_writePos); } } // We can't call prepare_post_handshake until the read code is done reading // the bitfield, so if we get here before then, postpone the post handshake // data until reading is done. Since we're done writing, remove us from the // poll in that case. if (m_writePos == bitfield->size_bytes()) { if (!m_readDone) this_thread::poll()->remove_write(this); else prepare_post_handshake(false); } } void Handshake::event_error() { if (m_state == INACTIVE) throw internal_error("Handshake::event_error() called on an inactive handshake."); m_manager->receive_failed(this, ConnectionManager::handshake_failed, e_handshake_network_socket_error); } } // namespace torrent libtorrent-0.16.11/src/protocol/request_list.cc0000644000000000000000000002512415175073411015165 #include "config.h" #include "request_list.h" #include #include #include "download/delegator.h" #include "protocol/peer_chunks.h" #include "torrent/data/block.h" #include "torrent/data/block_list.h" #include "torrent/exceptions.h" #include "utils/instrumentation.h" namespace torrent { const instrumentation_enum request_list_constants::instrumentation_added[bucket_count] = { INSTRUMENTATION_TRANSFER_REQUESTS_QUEUED_ADDED, INSTRUMENTATION_TRANSFER_REQUESTS_UNORDERED_ADDED, INSTRUMENTATION_TRANSFER_REQUESTS_STALLED_ADDED, INSTRUMENTATION_TRANSFER_REQUESTS_CHOKED_ADDED }; const instrumentation_enum request_list_constants::instrumentation_moved[bucket_count] = { INSTRUMENTATION_TRANSFER_REQUESTS_QUEUED_MOVED, INSTRUMENTATION_TRANSFER_REQUESTS_UNORDERED_MOVED, INSTRUMENTATION_TRANSFER_REQUESTS_STALLED_MOVED, INSTRUMENTATION_TRANSFER_REQUESTS_CHOKED_MOVED }; const instrumentation_enum request_list_constants::instrumentation_removed[bucket_count] = { INSTRUMENTATION_TRANSFER_REQUESTS_QUEUED_REMOVED, INSTRUMENTATION_TRANSFER_REQUESTS_UNORDERED_REMOVED, INSTRUMENTATION_TRANSFER_REQUESTS_STALLED_REMOVED, INSTRUMENTATION_TRANSFER_REQUESTS_CHOKED_REMOVED }; const instrumentation_enum request_list_constants::instrumentation_total[bucket_count] = { INSTRUMENTATION_TRANSFER_REQUESTS_QUEUED_TOTAL, INSTRUMENTATION_TRANSFER_REQUESTS_UNORDERED_TOTAL, INSTRUMENTATION_TRANSFER_REQUESTS_STALLED_TOTAL, INSTRUMENTATION_TRANSFER_REQUESTS_CHOKED_TOTAL }; // Make inline... template <> void request_list_constants::destroy(BlockTransfer*& obj) { Block::release(obj); } // TODO: Add a to-be-cancelled list, timer, and use that to avoid // cancelling pieces on CHOKE->UNCHOKE weirdness in some clients. // // Right after this the client should always be allowed to queue more // pieces, perhaps add a timer for last choke and check the request // time on the queued pieces. This makes it possible to get going // again if the remote queue got cleared. // It is assumed invalid transfers have been removed. struct request_list_same_piece { request_list_same_piece(const Piece& p) : m_piece(p) {} bool operator () (const BlockTransfer* d) const { return m_piece.index() == d->piece().index() && m_piece.offset() == d->piece().offset(); } Piece m_piece; }; RequestList::~RequestList() { assert(m_transfer == nullptr); assert(m_queues.empty()); torrent::this_thread::scheduler()->erase(&m_delay_remove_choked); torrent::this_thread::scheduler()->erase(&m_delay_process_unordered); } std::vector RequestList::delegate(uint32_t maxPieces) { std::vector transfers = m_delegator->delegate(m_peerChunks, m_affinity, maxPieces); std::vector pieces; if (transfers.empty()) return pieces; instrumentation_update(INSTRUMENTATION_TRANSFER_REQUESTS_DELEGATED, transfers.size()); for (auto transfer : transfers) { m_queues.push_back(bucket_queued, transfer); pieces.push_back(&transfer->piece()); } // Use the last index returned for the next affinity m_affinity = transfers.back()->index(); return pieces; } void RequestList::stall_initial() { queue_bucket_for_all_in_queue(m_queues, bucket_queued, &Block::stalled); m_queues.move_all_to(bucket_queued, bucket_stalled); queue_bucket_for_all_in_queue(m_queues, bucket_unordered, &Block::stalled); m_queues.move_all_to(bucket_unordered, bucket_stalled); } void RequestList::stall_prolonged() { if (m_transfer != nullptr) Block::stalled(m_transfer); queue_bucket_for_all_in_queue(m_queues, bucket_queued, &Block::stalled); m_queues.move_all_to(bucket_queued, bucket_stalled); queue_bucket_for_all_in_queue(m_queues, bucket_unordered, &Block::stalled); m_queues.move_all_to(bucket_unordered, bucket_stalled); // Currently leave the the requests until the peer gets disconnected. (?) } void RequestList::choked() { // Check if we want to update the choke timer; if non-zero and // updated within a short timespan? m_last_choke = torrent::this_thread::cached_time(); if (m_queues.queue_empty(bucket_queued) && m_queues.queue_empty(bucket_unordered)) return; m_queues.move_all_to(bucket_queued, bucket_choked); m_queues.move_all_to(bucket_unordered, bucket_choked); m_queues.move_all_to(bucket_stalled, bucket_choked); torrent::this_thread::scheduler()->update_wait_for_ceil_seconds(&m_delay_remove_choked, timeout_remove_choked); } void RequestList::unchoked() { m_last_unchoke = torrent::this_thread::cached_time(); // Clear choked queue if the peer doesn't start sending previously // requested pieces. // // This handles the case where a peer does a choke immediately // followed unchoke before starting to send pieces. if (!m_queues.queue_empty(bucket_choked)) torrent::this_thread::scheduler()->update_wait_for_ceil_seconds(&m_delay_remove_choked, timeout_remove_choked); else torrent::this_thread::scheduler()->erase(&m_delay_remove_choked); } void RequestList::delay_remove_choked() { m_queues.clear(bucket_choked); } void RequestList::prepare_process_unordered(queues_type::iterator itr) { m_queues.move_to(bucket_queued, m_queues.begin(bucket_queued), itr, bucket_unordered); if (m_delay_process_unordered.is_scheduled()) return; torrent::this_thread::scheduler()->wait_for_ceil_seconds(&m_delay_process_unordered, timeout_process_unordered); // TODO: Review if this should always be updated. m_last_unordered_position = unordered_size(); } void RequestList::delay_process_unordered() { m_last_unordered_position = std::min(m_last_unordered_position, unordered_size()); instrumentation_update(INSTRUMENTATION_TRANSFER_REQUESTS_FINISHED, m_last_unordered_position); m_queues.destroy(bucket_unordered, m_queues.begin(bucket_unordered), m_queues.begin(bucket_unordered) + m_last_unordered_position); m_last_unordered_position = unordered_size(); if (m_last_unordered_position != 0) torrent::this_thread::scheduler()->wait_for_ceil_seconds(&m_delay_process_unordered, timeout_process_unordered); } void RequestList::clear() { if (is_downloading()) skipped(); m_queues.clear(bucket_queued); m_queues.clear(bucket_unordered); m_queues.clear(bucket_stalled); m_queues.clear(bucket_choked); } bool RequestList::downloading(const Piece& piece) { if (m_transfer != nullptr) throw internal_error("RequestList::downloading(...) m_transfer != nullptr."); instrumentation_update(INSTRUMENTATION_TRANSFER_REQUESTS_DOWNLOADING, 1); std::pair itr = queue_bucket_find_if_in_any(m_queues, request_list_same_piece(piece)); switch (itr.first) { case bucket_queued: if (itr.second != m_queues.begin(bucket_queued)) prepare_process_unordered(itr.second); m_transfer = m_queues.take(itr.first, itr.second); break; case bucket_unordered: // Do unordered take of element here to avoid copy shifting the whole deque. (?) // // Alternatively, move back some elements to bucket_queued. if (std::distance(m_queues.begin(itr.first), itr.second) < static_cast(m_last_unordered_position)) m_last_unordered_position--; m_transfer = m_queues.take(itr.first, itr.second); break; case bucket_stalled: // Do special handling of unordered pieces. m_transfer = m_queues.take(itr.first, itr.second); break; case bucket_choked: m_transfer = m_queues.take(itr.first, itr.second); // We make sure that the choked queue eventually gets cleared if // the peer has skipped sending some pieces from the choked queue. torrent::this_thread::scheduler()->update_wait_for_ceil_seconds(&m_delay_remove_choked, timeout_choked_received); break; default: goto downloading_error; } // We received an invalid piece length, propably zero length due to // the peer not being able to transfer the requested piece. // // We need to replace the current BlockTransfer so Block can keep // the unmodified BlockTransfer. if (piece.length() != m_transfer->piece().length()) { if (piece.length() != 0) throw communication_error("Peer sent a piece with wrong, non-zero, length."); Block::release(m_transfer); goto downloading_error; } // Check if piece isn't wanted anymore. Do this after the length // check to ensure we return a correct BlockTransfer. if (!m_transfer->is_valid()) return false; m_transfer->block()->transfering(m_transfer); return true; downloading_error: // Create a dummy BlockTransfer object to hold the piece // information. m_transfer = new BlockTransfer(); Block::create_dummy(m_transfer, m_peerChunks->peer_info(), piece); instrumentation_update(INSTRUMENTATION_TRANSFER_REQUESTS_UNKNOWN, 1); return false; } // Must clear the downloading piece. void RequestList::finished() { if (!is_downloading()) throw internal_error("RequestList::finished() called but no transfer is in progress."); if (!m_transfer->is_valid()) throw internal_error("RequestList::finished() called but transfer is invalid."); BlockTransfer* transfer = m_transfer; m_transfer = nullptr; m_delegator->transfer_list()->finished(transfer); instrumentation_update(INSTRUMENTATION_TRANSFER_REQUESTS_FINISHED, 1); } void RequestList::skipped() { if (!is_downloading()) throw internal_error("RequestList::skip() called but no transfer is in progress."); Block::release(m_transfer); m_transfer = nullptr; instrumentation_update(INSTRUMENTATION_TRANSFER_REQUESTS_SKIPPED, 1); } // Data downloaded by this non-leading transfer does not match what we // already have. void RequestList::transfer_dissimilar() { if (!is_downloading()) throw internal_error("RequestList::transfer_dissimilar() called but no transfer is in progress."); auto dummy = new BlockTransfer(); Block::create_dummy(dummy, m_peerChunks->peer_info(), m_transfer->piece()); dummy->set_position(m_transfer->position()); // TODO.... peer_info still on a block we no longer control?.. m_transfer->block()->transfer_dissimilar(m_transfer); m_transfer = dummy; } bool RequestList::is_interested_in_active() const { auto list = m_delegator->transfer_list(); return std::any_of(list->begin(), list->end(), [this](auto transfer) { return m_peerChunks->bitfield()->get(transfer->index()); }); } uint32_t RequestList::calculate_pipe_size(uint32_t rate) { // Change into KB. rate /= 1024; if (!m_delegator->get_aggressive()) { if (rate < 20) return rate + 2; else return rate / 5 + 18; } else { if (rate < 10) return rate / 5 + 1; else return rate / 10 + 2; } } } // namespace torrent libtorrent-0.16.11/src/protocol/handshake_encryption.cc0000644000000000000000000000610515175073411016640 #include "config.h" #include "handshake_encryption.h" #include "torrent/net/network_config.h" #include "utils/diffie_hellman.h" #include "utils/sha1.h" namespace torrent { const unsigned char HandshakeEncryption::dh_prime[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x3A, 0x36, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x05, 0x63, }; const unsigned char HandshakeEncryption::dh_generator[] = { 2 }; const unsigned char HandshakeEncryption::vc_data[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; bool HandshakeEncryption::should_retry() const { return (m_options & net::NetworkConfig::encryption_enable_retry) != 0 && m_retry != HandshakeEncryption::RETRY_NONE; } HandshakeEncryption::HandshakeEncryption(int options) : m_options(options) { } bool HandshakeEncryption::initialize() { m_key = std::make_unique(dh_prime, dh_prime_length, dh_generator, dh_generator_length); return m_key->is_valid(); } void HandshakeEncryption::cleanup() { m_key = nullptr; } bool HandshakeEncryption::compare_vc(const void* buf) { return std::memcmp(buf, vc_data, vc_length) == 0; } void HandshakeEncryption::initialize_decrypt(const char* origHash, bool incoming) { char hash[20]; unsigned char discard[1024]; sha1_salt(incoming ? "keyA" : "keyB", 4, m_key->c_str(), 96, origHash, 20, hash); m_info.set_decrypt(RC4(reinterpret_cast(hash), 20)); m_info.decrypt(discard, 1024); } void HandshakeEncryption::initialize_encrypt(const char* origHash, bool incoming) { char hash[20]; unsigned char discard[1024]; sha1_salt(incoming ? "keyB" : "keyA", 4, m_key->c_str(), 96, origHash, 20, hash); m_info.set_encrypt(RC4(reinterpret_cast(hash), 20)); m_info.encrypt(discard, 1024); } // Obfuscated hash is HASH('req2', download_hash), extract that from // HASH('req2', download_hash) ^ HASH('req3', S). void HandshakeEncryption::deobfuscate_hash(char* src) const { char tmp[20]; sha1_salt("req3", 4, m_key->c_str(), m_key->size(), tmp); for (int i = 0; i < 20; i++) src[i] ^= tmp[i]; } void HandshakeEncryption::hash_req1_to_sync() { sha1_salt("req1", 4, m_key->c_str(), m_key->size(), modify_sync(20)); } void HandshakeEncryption::encrypt_vc_to_sync(const char* origHash) { m_syncLength = vc_length; std::memcpy(m_sync, vc_data, vc_length); char hash[20]; char discard[1024]; sha1_salt("keyB", 4, m_key->c_str(), 96, origHash, 20, hash); RC4 peerEncrypt(reinterpret_cast(hash), 20); peerEncrypt.crypt(discard, 1024); peerEncrypt.crypt(m_sync, HandshakeEncryption::vc_length); } } // namespace torrent libtorrent-0.16.11/src/protocol/encryption_info.h0000644000000000000000000000611115175073411015504 // libTorrent - BitTorrent library // Copyright (C) 2005-2011, Jari Sundell // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // In addition, as a special exception, the copyright holders give // permission to link the code of portions of this program with the // OpenSSL library under certain conditions as described in each // individual source file, and distribute linked combinations // including the two. // // You must obey the GNU General Public License in all respects for // all of the code used other than OpenSSL. If you modify file(s) // with this exception, you may extend this exception to your version // of the file(s), but you are not obligated to do so. If you do not // wish to do so, delete this exception statement from your version. // If you delete this exception statement from all source files in the // program, then also delete it here. // // Contact: Jari Sundell // // Skomakerveien 33 // 3185 Skoppum, NORWAY #ifndef LIBTORRENT_PROTOCOL_ENCRYPTION_H #define LIBTORRENT_PROTOCOL_ENCRYPTION_H #include "utils/rc4.h" namespace torrent { class EncryptionInfo { public: void encrypt(const void *indata, void *outdata, unsigned int length) { m_encrypt.crypt(indata, outdata, length); } void encrypt(void *data, unsigned int length) { m_encrypt.crypt(data, length); } void decrypt(const void *indata, void *outdata, unsigned int length) { m_decrypt.crypt(indata, outdata, length); } void decrypt(void *data, unsigned int length) { m_decrypt.crypt(data, length); } bool is_encrypted() const { return m_encrypted; } bool is_obfuscated() const { return m_obfuscated; } bool decrypt_valid() const { return m_decryptValid; } void set_obfuscated() { m_obfuscated = true; m_encrypted = m_decryptValid = false; } void set_encrypt(const RC4& encrypt) { m_encrypt = encrypt; m_encrypted = m_obfuscated = true; } void set_decrypt(const RC4& decrypt) { m_decrypt = decrypt; m_decryptValid = true; } private: bool m_encrypted{false}; bool m_obfuscated{false}; bool m_decryptValid{false}; RC4 m_encrypt; RC4 m_decrypt; }; } // namespace torrent #endif libtorrent-0.16.11/src/protocol/peer_connection_metadata.h0000644000000000000000000000163215175073411017314 #ifndef LIBTORRENT_PROTOCOL_PEER_CONNECTION_METADATA_H #define LIBTORRENT_PROTOCOL_PEER_CONNECTION_METADATA_H #include "peer_connection_base.h" #include "torrent/download.h" namespace torrent { class PeerConnectionMetadata : public PeerConnectionBase { public: ~PeerConnectionMetadata() override; void initialize_custom() override; void update_interested() override; bool receive_keepalive() override; void event_read() override; void event_write() override; void receive_metadata_piece(uint32_t piece, const char* data, uint32_t length) override; private: inline bool read_message(); bool read_skip_bitfield(); bool try_request_metadata_pieces(); inline void fill_write_buffer(); uint32_t m_skipLength; }; } // namespace torrent #endif libtorrent-0.16.11/src/protocol/handshake_manager.h0000644000000000000000000000460015175073411015720 #ifndef LIBTORRENT_NET_HANDSHAKE_MANAGER_H #define LIBTORRENT_NET_HANDSHAKE_MANAGER_H #include #include #include "torrent/connection_manager.h" #include "torrent/utils/unordered_vector.h" namespace torrent { class HandshakeManager : private utils::unordered_vector> { public: using base_type = utils::unordered_vector>; using base_type::size; using slot_download = std::function; // Do not connect to peers with this many or more failed chunks. static constexpr unsigned int max_failed = 3; using base_type::empty; HandshakeManager(); ~HandshakeManager(); size_type size_info(DownloadMain* info) const; void clear(); bool find(const sockaddr* sa); void erase_download(DownloadMain* info); void add_incoming(std::unique_ptr& handshake, int fd, const sockaddr* sa); void add_outgoing(const sockaddr* sa, DownloadMain* info); slot_download& slot_download_id() { return m_slot_download_id; } slot_download& slot_download_obfuscated() { return m_slot_download_obfuscated; } // This needs to be filterable slot. DownloadMain* download_info(const char* hash) { return m_slot_download_id(hash); } DownloadMain* download_info_obfuscated(const char* hash) { return m_slot_download_obfuscated(hash); } void receive_succeeded(Handshake* h); void receive_failed(Handshake* h, int message, int error); void receive_timeout(Handshake* h); static ProtocolExtension* default_extensions() { return &DefaultExtensions; } private: HandshakeManager(const HandshakeManager&) = delete; HandshakeManager& operator=(const HandshakeManager&) = delete; void create_outgoing(const sockaddr* sa, DownloadMain* info, int encryptionOptions); value_type find_and_erase(Handshake* handshake); // TODO: Move to anonymous namespace. static int open_and_connect_socket(const sockaddr* connect_address); static bool setup_socket(int fd, int family); static ProtocolExtension DefaultExtensions; slot_download m_slot_download_id; slot_download m_slot_download_obfuscated; }; } // namespace torrent #endif libtorrent-0.16.11/src/protocol/extensions.h0000644000000000000000000001524315175073411014504 #ifndef LIBTORRENT_PROTOCOL_EXTENSIONS_H #define LIBTORRENT_PROTOCOL_EXTENSIONS_H #include #include #include "torrent/exceptions.h" #include "torrent/object.h" #include "torrent/object_static_map.h" #include "net/address_list.h" #include "net/data_buffer.h" namespace torrent { class ProtocolExtension { public: enum MessageType { HANDSHAKE = 0, UT_PEX, UT_METADATA, FIRST_INVALID, // first invalid message ID SKIP_EXTENSION, }; using PEXList = std::vector; static constexpr int flag_default = 1<<0; static constexpr int flag_initial_handshake = 1<<1; static constexpr int flag_initial_pex = 1<<2; static constexpr int flag_received_ext = 1<<3; // The base bit to shift by MessageType to check if the extension is // enabled locally or supported by the peer. static constexpr int flag_local_enabled_base = 1<<8; static constexpr int flag_remote_supported_base = 1<<16; // Number of extensions we support, not counting handshake. static constexpr int extension_count = FIRST_INVALID - HANDSHAKE - 1; // Fixed size of a metadata piece (16 KB). static constexpr size_t metadata_piece_shift = 14; static constexpr size_t metadata_piece_size = 1 << metadata_piece_shift; ProtocolExtension(); ~ProtocolExtension() { delete [] m_read; } ProtocolExtension(const ProtocolExtension&) = default; ProtocolExtension& operator=(const ProtocolExtension&) = default; void cleanup(); // Create default extension object, with all extensions disabled. // Useful for eliminating checks whether peer supports extensions at all. static ProtocolExtension make_default(); void set_info(PeerInfo* peerInfo, DownloadMain* download) { m_peerInfo = peerInfo; m_download = download; } void set_connection(PeerConnectionBase* c) { m_connection = c; } DataBuffer generate_handshake_message(); static DataBuffer generate_toggle_message(MessageType t, bool on); static DataBuffer generate_ut_pex_message(const PEXList& added, const PEXList& removed); // Return peer's extension ID for the given extension type, or 0 if // disabled by peer. uint8_t id(int t) const; bool is_local_enabled(int t) const { return m_flags & flag_local_enabled_base << t; } bool is_remote_supported(int t) const { return m_flags & flag_remote_supported_base << t; } void set_local_enabled(int t); void unset_local_enabled(int t); void set_remote_supported(int t) { m_flags |= flag_remote_supported_base << t; } // General information about peer from extension handshake. uint32_t max_queue_length() const { return m_maxQueueLength; } // Handle reading extension data from peer. void read_start(int type, uint32_t length, bool skip); bool read_done(); char* read_position() { return m_readPos; } bool read_move(uint32_t v) { m_readPos += v; return (m_readLeft -= v) == 0; } uint32_t read_need() const { return m_readLeft; } bool is_complete() const { return m_readLeft == 0; } bool is_invalid() const { return m_readType == FIRST_INVALID; } bool is_default() const { return m_flags & flag_default; } // Initial PEX message after peer enables PEX needs to send full list // of peers instead of the delta list, so keep track of that. bool is_initial_handshake() const { return m_flags & flag_initial_handshake; } bool is_initial_pex() const { return m_flags & flag_initial_pex; } bool is_received_ext() const { return m_flags & flag_received_ext; } void clear_initial_pex() { m_flags &= ~flag_initial_pex; } void reset() { std::memset(&m_idMap, 0, sizeof(m_idMap)); } bool request_metadata_piece(const Piece* p); // To handle cases where the extension protocol needs to send a reply. bool has_pending_message() const { return m_pendingType != HANDSHAKE; } MessageType pending_message_type() const { return m_pendingType; } DataBuffer pending_message_data() { return m_pending.release(); } void clear_pending_message() { if (m_pending.empty()) m_pendingType = HANDSHAKE; } private: bool parse_handshake(); bool parse_ut_pex(); bool parse_ut_metadata(); [[gnu::format(printf, 2, 3)]] static DataBuffer build_bencode(size_t maxLength, const char* format, ...); void peer_toggle_remote(int type, bool active); void send_metadata_piece(size_t piece); // Map of IDs peer uses for each extension message type, excluding // HANDSHAKE. uint8_t m_idMap[extension_count]; uint32_t m_maxQueueLength; // Set HANDSHAKE as enabled and supported. Those bits should not be // touched. int m_flags{flag_local_enabled_base | flag_remote_supported_base | flag_initial_handshake}; PeerInfo* m_peerInfo{}; DownloadMain* m_download{}; PeerConnectionBase* m_connection{}; uint8_t m_readType{FIRST_INVALID}; uint32_t m_readLeft; char* m_read{}; char* m_readPos; MessageType m_pendingType{HANDSHAKE}; DataBuffer m_pending; }; enum ext_handshake_keys { key_e, key_m_utMetadata, key_m_utPex, key_metadataSize, key_p, key_reqq, key_v, key_handshake_LAST }; enum ext_pex_keys { key_pex_added, key_pex_LAST }; enum ext_metadata_keys { key_msgType, key_piece, key_totalSize, key_metadata_LAST }; using ExtHandshakeMessage = static_map_type; using ExtPEXMessage = static_map_type; using ExtMetadataMessage = static_map_type; // // // inline ProtocolExtension::ProtocolExtension() { reset(); set_local_enabled(UT_METADATA); } inline ProtocolExtension ProtocolExtension::make_default() { ProtocolExtension extension; extension.m_flags |= flag_default; return extension; } inline uint8_t ProtocolExtension::id(int t) const { if (t == HANDSHAKE) return 0; if (t - 1 >= extension_count) throw internal_error("ProtocolExtension::id message type out of range."); return m_idMap[t - 1]; } } // namespace torrent #endif libtorrent-0.16.11/src/protocol/handshake.h0000644000000000000000000001275015175073411014233 #ifndef LIBTORRENT_HANDSHAKE_H #define LIBTORRENT_HANDSHAKE_H #include "net/protocol_buffer.h" #include "net/socket_stream.h" #include "torrent/bitfield.h" #include "torrent/net/socket_address.h" #include "torrent/peer/peer_info.h" #include "torrent/utils/scheduler.h" #include "handshake_encryption.h" namespace torrent { class HandshakeManager; class DownloadMain; class ThrottleList; class Handshake : public SocketStream { public: static constexpr uint32_t part1_size = 20 + 28; static constexpr uint32_t part2_size = 20; static constexpr uint32_t handshake_size = part1_size + part2_size; static constexpr uint32_t read_message_size = 2 * 5; static constexpr uint32_t protocol_bitfield = 5; static constexpr uint32_t protocol_port = 9; static constexpr uint32_t protocol_extension = 20; static constexpr uint32_t enc_negotiation_size = 8 + 4 + 2; static constexpr uint32_t enc_pad_size = 512; static constexpr uint32_t enc_pad_read_size = 96 + enc_pad_size + 20; static constexpr uint32_t buffer_size = enc_pad_read_size + 20 + enc_negotiation_size + enc_pad_size + 2 + handshake_size + read_message_size; using Buffer = ProtocolBuffer; enum State { INACTIVE, CONNECTING, POST_HANDSHAKE, PROXY_CONNECT, PROXY_DONE, READ_ENC_KEY, READ_ENC_SYNC, READ_ENC_SKEY, READ_ENC_NEGOT, READ_ENC_PAD, READ_ENC_IA, READ_INFO, READ_PEER, READ_MESSAGE, READ_BITFIELD, READ_EXT, READ_PORT }; Handshake(); ~Handshake() override; const char* type_name() const override { return "handshake"; } bool is_active() const { return m_state != INACTIVE; } State state() const { return m_state; } void initialize_incoming(HandshakeManager* handshake_manager, int fd, const sockaddr* sa, int encryption_options); void initialize_outgoing(HandshakeManager* handshake_manager, int fd, const sockaddr* sa, int encryption_options, DownloadMain* d, PeerInfo* peerInfo); PeerInfo* peer_info() { return m_peerInfo; } const PeerInfo* peer_info() const { return m_peerInfo; } void set_peer_info(PeerInfo* p) { m_peerInfo = p; } const sockaddr* socket_address() const { return m_address.get(); } DownloadMain* download() { return m_download; } Bitfield* bitfield() { return &m_bitfield; } void release_connection(); void destroy_connection(bool use_socket_manager = true); const void* unread_data() { return m_readBuffer.position(); } uint32_t unread_size() const { return m_readBuffer.remaining(); } std::chrono::microseconds initialized_time() const { return m_initialized_time; } void event_read() override; void event_write() override; void event_error() override; HandshakeEncryption* encryption() { return &m_encryption; } ProtocolExtension* extensions() { return m_extensions; } int retry_options(); protected: Handshake(const Handshake&) = delete; Handshake& operator=(const Handshake&) = delete; void set_manager(HandshakeManager* handshake_manager); void read_done(); void write_done(); bool fill_read_buffer(int size); // Check what is unnessesary. bool read_proxy_connect(); bool read_encryption_key(); bool read_encryption_sync(); bool read_encryption_skey(); bool read_encryption_negotiation(); bool read_negotiation_reply(); bool read_info(); bool read_peer(); bool read_bitfield(); bool read_extension(); bool read_port(); void prepare_proxy_connect(); void prepare_key_plus_pad(); void prepare_enc_negotiation(); void prepare_handshake(); void prepare_peer_info(); void prepare_bitfield(); void prepare_post_handshake(bool must_write); void write_extension_handshake(); void write_bitfield(); inline void validate_download(); uint32_t read_unthrottled(void* buf, uint32_t length); uint32_t write_unthrottled(const void* buf, uint32_t length); static constexpr auto m_protocol = "BitTorrent protocol"; State m_state{INACTIVE}; HandshakeManager* m_manager; PeerInfo* m_peerInfo{}; DownloadMain* m_download{}; Bitfield m_bitfield; ThrottleList* m_upload_throttle; ThrottleList* m_download_throttle; utils::SchedulerEntry m_task_timeout; std::chrono::microseconds m_initialized_time; uint32_t m_readPos; uint32_t m_writePos; bool m_readDone{false}; bool m_writeDone{false}; bool m_incoming; c_sa_unique_ptr m_address; char m_options[8]; HandshakeEncryption m_encryption; ProtocolExtension* m_extensions; // Put these last to keep variables closer to *this. Buffer m_readBuffer; Buffer m_writeBuffer; }; } // namespace torrent #endif libtorrent-0.16.11/src/protocol/peer_connection_metadata.cc0000644000000000000000000003221215175073411017450 #include "config.h" #include "protocol/peer_connection_metadata.h" #include #include #include "download/chunk_selector.h" #include "download/chunk_statistics.h" #include "download/download_main.h" #include "manager.h" #include "protocol/extensions.h" #include "torrent/download/choke_queue.h" #include "torrent/download_info.h" #include "torrent/peer/connection_list.h" #include "torrent/peer/peer_info.h" #include "torrent/utils/log.h" #define LT_LOG_METADATA_EVENTS(log_fmt, ...) \ lt_log_print_info(LOG_PROTOCOL_METADATA_EVENTS, this->download()->info(), "metadata_events", "%40s " log_fmt, this->peer_info()->id_hex(), __VA_ARGS__); #define LT_LOG_STORAGE_ERRORS(log_fmt, ...) \ lt_log_print_info(LOG_PROTOCOL_STORAGE_ERRORS, this->download()->info(), "storage_errors", "%40s " log_fmt, this->peer_info()->id_hex(), __VA_ARGS__); namespace torrent { PeerConnectionMetadata::~PeerConnectionMetadata() = default; void PeerConnectionMetadata::initialize_custom() { } void PeerConnectionMetadata::update_interested() { } bool PeerConnectionMetadata::receive_keepalive() { if (this_thread::cached_time() - m_time_last_read > 240s) return false; m_tryRequest = true; // There's no point in adding ourselves to the write poll if the // buffer is full, as that will already have been taken care of. if (m_up->get_state() == ProtocolWrite::IDLE && m_up->can_write_keepalive()) { write_insert_poll_safe(); ProtocolBuffer<512>::iterator old_end = m_up->buffer()->end(); m_up->write_keepalive(); if (is_encrypted()) m_encryption.encrypt(old_end, m_up->buffer()->end() - old_end); } return true; } // We keep the message in the buffer if it is incomplete instead of // keeping the state and remembering the read information. This // shouldn't happen very often compared to full reads. inline bool PeerConnectionMetadata::read_message() { ProtocolBuffer<512>* buf = m_down->buffer(); if (buf->remaining() < 4) return false; // Remember the start of the message so we may reset it if we don't // have the whole message. ProtocolBuffer<512>::iterator beginning = buf->position(); uint32_t length = buf->read_32(); if (length == 0) { // Keepalive message. m_down->set_last_command(ProtocolBase::KEEP_ALIVE); return true; } else if (buf->remaining() < 1) { buf->set_position_itr(beginning); return false; } else if (length > (1 << 20)) { throw communication_error("PeerConnection::read_message() got an invalid message length."); } m_down->set_last_command(static_cast(buf->peek_8())); // Ignore most messages, they aren't relevant for a metadata download. switch (buf->read_8()) { case ProtocolBase::CHOKE: case ProtocolBase::UNCHOKE: case ProtocolBase::INTERESTED: case ProtocolBase::NOT_INTERESTED: return true; case ProtocolBase::HAVE: if (!m_down->can_read_have_body()) break; buf->read_32(); return true; case ProtocolBase::REQUEST: if (!m_down->can_read_request_body()) break; m_down->read_request(); return true; case ProtocolBase::PIECE: throw communication_error("Received a piece but the connection is strictly for meta data."); case ProtocolBase::CANCEL: if (!m_down->can_read_cancel_body()) break; m_down->read_request(); return true; case ProtocolBase::PORT: if (!m_down->can_read_port_body()) break; runtime::dht_add_peer_node(m_peerInfo->socket_address(), m_down->buffer()->read_16()); return true; case ProtocolBase::EXTENSION_PROTOCOL: LT_LOG_METADATA_EVENTS("protocol extension message", 0); if (!m_down->can_read_extension_body()) break; if (m_extensions->is_default()) { m_extensions = new ProtocolExtension(); m_extensions->set_info(m_peerInfo, m_download); } { int extension = m_down->buffer()->read_8(); m_extensions->read_start(extension, length - 2, (extension == ProtocolExtension::UT_PEX) && !m_download->want_pex_msg()); m_down->set_state(ProtocolRead::READ_EXTENSION); } if (!down_extension()) return false; LT_LOG_METADATA_EVENTS("protocol extension done", 0); // Drop peer if it disabled the metadata extension. if (!m_extensions->is_remote_supported(ProtocolExtension::UT_METADATA)) throw close_connection(); m_down->set_state(ProtocolRead::IDLE); m_tryRequest = true; write_insert_poll_safe(); return true; case ProtocolBase::BITFIELD: // Discard the bitfield sent by the peer. m_skipLength = length - 1; m_down->set_state(ProtocolRead::READ_SKIP_PIECE); return false; default: throw communication_error("Received unsupported message type."); } // We were unsuccessfull in reading the message, need more data. buf->set_position_itr(beginning); return false; } void PeerConnectionMetadata::event_read() { m_time_last_read = this_thread::cached_time(); // Need to make sure ProtocolBuffer::end() is pointing to the end of // the unread data, and that the unread data starts from the // beginning of the buffer. Or do we use position? Propably best, // therefor ProtocolBuffer::position() points to the beginning of // the unused data. try { // Normal read. // // We rarely will read zero bytes as the read of 64 bytes will // almost always either not fill up or it will require additional // reads. // // Only loop when end hits 64. do { switch (m_down->get_state()) { case ProtocolRead::IDLE: if (m_down->buffer()->size_end() < read_size) { unsigned int length = read_stream_throws(m_down->buffer()->end(), read_size - m_down->buffer()->size_end()); m_down->throttle()->node_used_unthrottled(length); if (is_encrypted()) m_encryption.decrypt(m_down->buffer()->end(), length); m_down->buffer()->move_end(length); } while (read_message()) ; // Do nothing. if (m_down->buffer()->size_end() == read_size) { m_down->buffer()->move_unused(); break; } else { m_down->buffer()->move_unused(); return; } case ProtocolRead::READ_EXTENSION: if (!down_extension()) return; // Drop peer if it disabled the metadata extension. if (!m_extensions->is_remote_supported(ProtocolExtension::UT_METADATA)) throw close_connection(); LT_LOG_METADATA_EVENTS("reading extension message", 0); m_down->set_state(ProtocolRead::IDLE); m_tryRequest = true; write_insert_poll_safe(); break; // Actually skipping the bitfield. // We never receive normal piece messages anyway. case ProtocolRead::READ_SKIP_PIECE: if (!read_skip_bitfield()) return; m_down->set_state(ProtocolRead::IDLE); break; default: throw internal_error("PeerConnection::event_read() wrong state."); } // Figure out how to get rid of the shouldLoop boolean. } while (true); // Exception handlers: } catch (const close_connection&) { m_download->connection_list()->erase(this, 0); } catch (const blocked_connection&) { m_download->connection_list()->erase(this, 0); } catch (const network_error&) { m_download->connection_list()->erase(this, 0); } catch (const storage_error& e) { LT_LOG_STORAGE_ERRORS("read error: %s", e.what()); m_download->connection_list()->erase(this, 0); } catch (const base_error& e) { std::stringstream s; s << "Connection read fd(" << m_fileDesc << ',' << m_down->get_state() << ',' << m_down->last_command() << ") \"" << e.what() << '"'; throw internal_error(s.str()); } } inline void PeerConnectionMetadata::fill_write_buffer() { ProtocolBuffer<512>::iterator old_end = m_up->buffer()->end(); if (m_tryRequest) m_tryRequest = try_request_metadata_pieces(); if (m_sendPEXMask && m_up->can_write_extension() && send_pex_message()) { // Don't do anything else if send_pex_message() succeeded. } else if (m_extensions->has_pending_message() && m_up->can_write_extension() && send_ext_message()) { // Same. } if (is_encrypted()) m_encryption.encrypt(old_end, m_up->buffer()->end() - old_end); } void PeerConnectionMetadata::event_write() { try { do { switch (m_up->get_state()) { case ProtocolWrite::IDLE: fill_write_buffer(); if (m_up->buffer()->remaining() == 0) { this_thread::poll()->remove_write(this); return; } m_up->set_state(ProtocolWrite::MSG); [[fallthrough]]; case ProtocolWrite::MSG: if (!m_up->buffer()->consume(m_up->throttle()->node_used_unthrottled(write_stream_throws(m_up->buffer()->position(), m_up->buffer()->remaining())))) return; m_up->buffer()->reset(); if (m_up->last_command() != ProtocolBase::EXTENSION_PROTOCOL) { m_up->set_state(ProtocolWrite::IDLE); break; } m_up->set_state(ProtocolWrite::WRITE_EXTENSION); [[fallthrough]]; case ProtocolWrite::WRITE_EXTENSION: if (!up_extension()) return; m_up->set_state(ProtocolWrite::IDLE); break; default: throw internal_error("PeerConnection::event_write() wrong state."); } } while (true); } catch (const close_connection&) { m_download->connection_list()->erase(this, 0); } catch (const blocked_connection&) { m_download->connection_list()->erase(this, 0); } catch (const network_error&) { m_download->connection_list()->erase(this, 0); } catch (const storage_error& e) { LT_LOG_STORAGE_ERRORS("read error: %s", e.what()); m_download->connection_list()->erase(this, 0); } catch (const base_error& e) { std::stringstream s; s << "Connection write fd(" << m_fileDesc << ',' << m_up->get_state() << ',' << m_up->last_command() << ") \"" << e.what() << '"'; throw internal_error(s.str()); } } bool PeerConnectionMetadata::read_skip_bitfield() { if (m_down->buffer()->remaining()) { uint32_t length = std::min(m_skipLength, static_cast(m_down->buffer()->remaining())); m_down->buffer()->consume(length); m_skipLength -= length; } if (m_skipLength) { uint32_t length = std::min(m_skipLength, static_cast(null_buffer_size)); length = read_stream_throws(m_nullBuffer, length); if (!length) return false; m_skipLength -= length; } return !m_skipLength; } // Same as the PCB code, but only one at a time and with the extension protocol. bool PeerConnectionMetadata::try_request_metadata_pieces() { if (m_download->file_list()->chunk_size() == 1 || !m_extensions->is_remote_supported(ProtocolExtension::UT_METADATA)) return false; if (request_list()->queued_empty()) m_downStall = 0; uint32_t pipeSize = request_list()->calculate_pipe_size(m_peerChunks.download_throttle()->rate()->rate()); // Don't start requesting if we can't do it in large enough chunks. if (request_list()->pipe_size() >= (pipeSize + 10) / 2) return false; // DEBUG: // if (!request_list()->queued_size() < pipeSize || !m_up->can_write_extension() || if (!m_up->can_write_extension() || m_extensions->has_pending_message()) return false; std::vector pieces = request_list()->delegate(1); if (pieces.empty()) return false; const Piece* p = pieces.front(); if (!m_download->file_list()->is_valid_piece(*p) || !m_peerChunks.bitfield()->get(p->index())) throw internal_error("PeerConnectionMetadata::try_request_metadata_pieces() tried to use an invalid piece."); // DEBUG: if (m_extensions->request_metadata_piece(p)) { LT_LOG_METADATA_EVENTS("request metadata piece succeded", 0); return true; } else { LT_LOG_METADATA_EVENTS("request metadata piece failed", 0); return false; } } void PeerConnectionMetadata::receive_metadata_piece(uint32_t piece, const char* data, uint32_t length) { if (data == NULL) { // Length is not set in a reject message. length = ProtocolExtension::metadata_piece_size; if ((piece << ProtocolExtension::metadata_piece_shift) + ProtocolExtension::metadata_piece_size >= m_download->file_list()->size_bytes()) length = m_download->file_list()->chunk_size() % ProtocolExtension::metadata_piece_size; m_tryRequest = false; read_cancel_piece(Piece(0, piece << ProtocolExtension::metadata_piece_shift, length)); LT_LOG_METADATA_EVENTS("rejected metadata piece", 0); return; } if (!down_chunk_start(Piece(0, piece << ProtocolExtension::metadata_piece_shift, length))) { LT_LOG_METADATA_EVENTS("skipped metadata piece", 0); down_chunk_skip_process(data, length); } else { LT_LOG_METADATA_EVENTS("processed metadata piece", 0); down_chunk_process(data, length); } if (m_request_list.transfer() != NULL && !m_request_list.transfer()->is_finished()) throw internal_error("PeerConnectionMetadata::receive_metadata_piece did not have complete piece."); m_tryRequest = true; down_chunk_finished(); } } // namespace torrent libtorrent-0.16.11/src/protocol/peer_connection_leech.h0000644000000000000000000000253615175073411016620 #ifndef LIBTORRENT_PROTOCOL_PEER_CONNECTION_LEECH_H #define LIBTORRENT_PROTOCOL_PEER_CONNECTION_LEECH_H #include "peer_connection_base.h" #include "torrent/download.h" namespace torrent { // Type-specific data. template struct PeerConnectionData; template<> struct PeerConnectionData { }; template<> struct PeerConnectionData { }; template<> struct PeerConnectionData { uint32_t lastIndex{~uint32_t{}}; uint32_t bytesLeft; }; template class PeerConnection : public PeerConnectionBase { public: PeerConnection() = default; ~PeerConnection() override; void initialize_custom() override; void update_interested() override; bool receive_keepalive() override; void event_read() override; void event_write() override; private: PeerConnection(const PeerConnection&) = delete; PeerConnection& operator=(const PeerConnection&) = delete; inline bool read_message(); void read_have_chunk(uint32_t index); void offer_chunk(); bool should_upload(); inline void fill_write_buffer(); PeerConnectionData m_data; }; } // namespace torrent #endif libtorrent-0.16.11/src/protocol/protocol_base.h0000644000000000000000000001560215175073411015137 #ifndef LIBTORRENT_NET_PROTOCOL_BASE_H #define LIBTORRENT_NET_PROTOCOL_BASE_H #include "net/protocol_buffer.h" namespace torrent { class Piece; class ProtocolBase { public: using Buffer = ProtocolBuffer<512>; using size_type = uint32_t; static constexpr size_type buffer_size = 512; enum Protocol { CHOKE = 0, UNCHOKE, INTERESTED, NOT_INTERESTED, HAVE, BITFIELD, REQUEST, PIECE, CANCEL, PORT, // = 9 EXTENSION_PROTOCOL = 20, NONE, // These are not part of the protocol KEEP_ALIVE // Last command was a keep alive }; enum State { IDLE, MSG, READ_PIECE, READ_SKIP_PIECE, READ_EXTENSION, WRITE_PIECE, WRITE_EXTENSION, INTERNAL_ERROR }; ProtocolBase() { m_buffer.reset(); } Protocol last_command() const { return m_lastCommand; } void set_last_command(Protocol p) { m_lastCommand = p; } Buffer* buffer() { return &m_buffer; } ThrottleList* throttle() { return m_throttle; } void set_throttle(ThrottleList* t) { m_throttle = t; } State get_state() const { return m_state; } void set_state(State s) { m_state = s; } Piece read_request(); Piece read_piece(size_type length); void write_command(Protocol c) { m_buffer.write_8(m_lastCommand = c); } void write_keepalive(); void write_choke(bool s); void write_interested(bool s); void write_have(uint32_t index); void write_bitfield(size_type length); void write_request(const Piece& p); void write_cancel(const Piece& p); void write_piece(const Piece& p); void write_port(uint16_t port); void write_extension(uint8_t id, uint32_t length); static constexpr size_type sizeof_keepalive = 4; static constexpr size_type sizeof_choke = 5; static constexpr size_type sizeof_interested = 5; static constexpr size_type sizeof_have = 9; static constexpr size_type sizeof_have_body = 4; static constexpr size_type sizeof_bitfield = 5; static constexpr size_type sizeof_request = 17; static constexpr size_type sizeof_request_body = 12; static constexpr size_type sizeof_cancel = 17; static constexpr size_type sizeof_cancel_body = 12; static constexpr size_type sizeof_piece = 13; static constexpr size_type sizeof_piece_body = 8; static constexpr size_type sizeof_port = 7; static constexpr size_type sizeof_port_body = 2; static constexpr size_type sizeof_extension = 6; static constexpr size_type sizeof_extension_body=1; bool can_write_keepalive() const { return m_buffer.reserved_left() >= sizeof_keepalive; } bool can_write_choke() const { return m_buffer.reserved_left() >= sizeof_choke; } bool can_write_interested() const { return m_buffer.reserved_left() >= sizeof_interested; } bool can_write_have() const { return m_buffer.reserved_left() >= sizeof_have; } bool can_write_bitfield() const { return m_buffer.reserved_left() >= sizeof_bitfield; } bool can_write_request() const { return m_buffer.reserved_left() >= sizeof_request; } bool can_write_cancel() const { return m_buffer.reserved_left() >= sizeof_cancel; } bool can_write_piece() const { return m_buffer.reserved_left() >= sizeof_piece; } bool can_write_port() const { return m_buffer.reserved_left() >= sizeof_port; } bool can_write_extension() const { return m_buffer.reserved_left() >= sizeof_extension; } size_type max_write_request() const { return m_buffer.reserved_left() / sizeof_request; } bool can_read_have_body() const { return m_buffer.remaining() >= sizeof_have_body; } bool can_read_request_body() const { return m_buffer.remaining() >= sizeof_request_body; } bool can_read_cancel_body() const { return m_buffer.remaining() >= sizeof_request_body; } bool can_read_piece_body() const { return m_buffer.remaining() >= sizeof_piece_body; } bool can_read_port_body() const { return m_buffer.remaining() >= sizeof_port_body; } bool can_read_extension_body() const { return m_buffer.remaining() >= sizeof_extension_body; } protected: State m_state{IDLE}; Protocol m_lastCommand{NONE}; ThrottleList* m_throttle{}; Buffer m_buffer; }; inline Piece ProtocolBase::read_request() { uint32_t index = m_buffer.read_32(); uint32_t offset = m_buffer.read_32(); uint32_t length = m_buffer.read_32(); return Piece(index, offset, length); } inline Piece ProtocolBase::read_piece(size_type length) { uint32_t index = m_buffer.read_32(); uint32_t offset = m_buffer.read_32(); return Piece(index, offset, length); } inline void ProtocolBase::write_keepalive() { m_buffer.write_32(0); m_lastCommand = KEEP_ALIVE; } inline void ProtocolBase::write_choke(bool s) { m_buffer.write_32(1); write_command(s ? CHOKE : UNCHOKE); } inline void ProtocolBase::write_interested(bool s) { m_buffer.write_32(1); write_command(s ? INTERESTED : NOT_INTERESTED); } inline void ProtocolBase::write_have(uint32_t index) { m_buffer.write_32(5); write_command(HAVE); m_buffer.write_32(index); } inline void ProtocolBase::write_bitfield(size_type length) { m_buffer.write_32(1 + length); write_command(BITFIELD); } inline void ProtocolBase::write_request(const Piece& p) { m_buffer.write_32(13); write_command(REQUEST); m_buffer.write_32(p.index()); m_buffer.write_32(p.offset()); m_buffer.write_32(p.length()); } inline void ProtocolBase::write_cancel(const Piece& p) { m_buffer.write_32(13); write_command(CANCEL); m_buffer.write_32(p.index()); m_buffer.write_32(p.offset()); m_buffer.write_32(p.length()); } inline void ProtocolBase::write_piece(const Piece& p) { m_buffer.write_32(9 + p.length()); write_command(PIECE); m_buffer.write_32(p.index()); m_buffer.write_32(p.offset()); } inline void ProtocolBase::write_port(uint16_t port) { m_buffer.write_32(3); write_command(PORT); m_buffer.write_16(port); } inline void ProtocolBase::write_extension(uint8_t id, uint32_t length) { m_buffer.write_32(2 + length); write_command(EXTENSION_PROTOCOL); m_buffer.write_8(id); } } // namespace torrent #endif libtorrent-0.16.11/src/protocol/peer_connection_base.h0000644000000000000000000002017415175073411016450 #ifndef LIBTORRENT_PROTOCOL_PEER_CONNECTION_BASE_H #define LIBTORRENT_PROTOCOL_PEER_CONNECTION_BASE_H #include "thread_main.h" #include "data/chunk_handle.h" #include "net/socket_stream.h" #include "protocol/encryption_info.h" #include "protocol/extensions.h" #include "protocol/peer_chunks.h" #include "protocol/protocol_base.h" #include "protocol/request_list.h" #include "torrent/net/poll.h" #include "torrent/peer/choke_status.h" #include "torrent/peer/peer.h" namespace torrent { // Base class for peer connection classes. Rename to PeerConnection // when the migration is complete? // // This should really be modularized abit, there's too much stuff in // PeerConnectionBase and its children. Do we use additional layers of // inheritance or member instances? class choke_queue; class DownloadMain; class PeerConnectionBase : public Peer, public SocketStream { public: using ProtocolRead = ProtocolBase; using ProtocolWrite = ProtocolBase; #if USE_EXTRA_DEBUG == 666 // For testing, use a really small buffer. typedef ProtocolBuffer<256> EncryptBuffer; #else using EncryptBuffer = ProtocolBuffer<16384>; #endif // Find an optimal number for this. static constexpr uint32_t read_size = 64; // Bitmasks for peer exchange messages to send. static constexpr int PEX_DO = (1 << 0); static constexpr int PEX_ENABLE = (1 << 1); static constexpr int PEX_DISABLE = (1 << 2); PeerConnectionBase(); ~PeerConnectionBase() override; const char* type_name() const override { return "pcb"; } void initialize(DownloadMain* download, PeerInfo* p, int fd, Bitfield* bitfield, EncryptionInfo* encryptionInfo, ProtocolExtension* extensions); void cleanup(); bool is_up_choked() const { return m_upChoke.choked(); } bool is_up_interested() const { return m_upChoke.queued(); } bool is_up_snubbed() const { return m_upChoke.snubbed(); } bool is_down_queued() const { return m_downChoke.queued(); } bool is_down_local_unchoked() const { return m_downChoke.unchoked(); } bool is_down_remote_unchoked() const { return m_downUnchoked; } bool is_down_interested() const { return m_downInterested; } void set_upload_snubbed(bool v); bool is_seeder() const { return m_peerChunks.is_seeder(); } bool is_not_seeder() const { return !m_peerChunks.is_seeder(); } bool is_encrypted() const { return m_encryption.is_encrypted(); } bool is_obfuscated() const { return m_encryption.is_obfuscated(); } PeerInfo* mutable_peer_info() { return m_peerInfo; } PeerChunks* peer_chunks() { return &m_peerChunks; } const PeerChunks* c_peer_chunks() const { return &m_peerChunks; } choke_status* up_choke() { return &m_upChoke; } choke_status* down_choke() { return &m_downChoke; } DownloadMain* download() { return m_download; } RequestList* request_list() { return &m_request_list; } const RequestList* request_list() const { return &m_request_list; } ProtocolExtension* extensions() { return m_extensions; } DataBuffer* extension_message() { return &m_extensionMessage; } void do_peer_exchange() { m_sendPEXMask |= PEX_DO; } inline void set_peer_exchange(bool state); // These must be implemented by the child class. virtual void initialize_custom() = 0; virtual void update_interested() = 0; virtual bool receive_keepalive() = 0; bool receive_upload_choke(bool choke); bool receive_download_choke(bool choke); void event_error() override; void push_unread(const void* data, uint32_t size); void cancel_transfer(BlockTransfer* transfer); // Insert into the poll unless we're blocking for throttling etc. void read_insert_poll_safe(); void write_insert_poll_safe(); // Communication with the protocol extensions virtual void receive_metadata_piece(uint32_t piece, const char* data, uint32_t length); bool should_connection_unchoke(choke_queue* cq) const; protected: static constexpr uint32_t extension_must_encrypt = ~uint32_t(); inline bool read_remaining(); inline bool write_remaining(); void load_up_chunk(); void read_request_piece(const Piece& p); void read_cancel_piece(const Piece& p); void write_prepare_piece(); void write_prepare_extension(int type, const DataBuffer& message); bool down_chunk_start(const Piece& p); void down_chunk_finished(); bool down_chunk(); bool down_chunk_from_buffer(); bool down_chunk_skip(); bool down_chunk_skip_from_buffer(); uint32_t down_chunk_process(const void* buffer, uint32_t length); uint32_t down_chunk_skip_process(const void* buffer, uint32_t length); bool down_extension(); bool up_chunk(); inline uint32_t up_chunk_encrypt(uint32_t quota); bool up_extension(); void down_chunk_release(); void up_chunk_release(); bool should_request(); bool try_request_pieces(); bool send_pex_message(); bool send_ext_message(); DownloadMain* m_download{}; ProtocolRead* m_down; ProtocolWrite* m_up; PeerChunks m_peerChunks; RequestList m_request_list; ChunkHandle m_downChunk; uint32_t m_downStall{0}; Piece m_upPiece; ChunkHandle m_upChunk; // The interested state no longer follows the spec's wording as it // has been swapped. // // Thus the same ProtocolBase object now groups the same choke and // interested states togheter, thus for m_up 'interested' means the // remote peer wants upload and 'choke' means we've choked upload to // that peer. // // In the downlod object, 'queued' now means the same as the spec's // 'unchoked', while 'unchoked' means we start requesting pieces. choke_status m_upChoke; choke_status m_downChoke; bool m_downInterested{false}; bool m_downUnchoked{false}; bool m_sendChoked{false}; bool m_sendInterested{false}; bool m_tryRequest{true}; int m_sendPEXMask{0}; std::chrono::microseconds m_time_last_read{}; DataBuffer m_extensionMessage; uint32_t m_extensionOffset; std::unique_ptr m_encryptBuffer; EncryptionInfo m_encryption; ProtocolExtension* m_extensions{}; bool m_incoreContinous{false}; }; inline void PeerConnectionBase::set_peer_exchange(bool state) { if (m_extensions->is_default() || !m_extensions->is_remote_supported(ProtocolExtension::UT_PEX)) return; if (state) { m_sendPEXMask = PEX_ENABLE | (m_sendPEXMask & ~PEX_DISABLE); m_extensions->set_local_enabled(ProtocolExtension::UT_PEX); } else { m_sendPEXMask = PEX_DISABLE | (m_sendPEXMask & ~PEX_ENABLE); m_extensions->unset_local_enabled(ProtocolExtension::UT_PEX); } } inline void PeerConnectionBase::push_unread(const void* data, uint32_t size) { std::memcpy(m_down->buffer()->end(), data, size); m_down->buffer()->move_end(size); } inline void PeerConnectionBase::read_insert_poll_safe() { if (m_down->get_state() != ProtocolRead::IDLE) return; this_thread::poll()->insert_read(this); } inline void PeerConnectionBase::write_insert_poll_safe() { if (m_up->get_state() != ProtocolWrite::IDLE) return; this_thread::poll()->insert_write(this); } } // namespace torrent #endif libtorrent-0.16.11/src/protocol/peer_chunks.h0000644000000000000000000000477515175073411014623 #ifndef LIBTORRENT_PROTOCOL_PEER_CHUNKS_H #define LIBTORRENT_PROTOCOL_PEER_CHUNKS_H #include #include "net/throttle_node.h" #include "torrent/bitfield.h" #include "torrent/data/piece.h" #include "torrent/rate.h" #include "torrent/utils/scheduler.h" #include "utils/partial_queue.h" namespace torrent { class PeerInfo; class PeerChunks { public: using piece_list_type = std::list; bool is_seeder() const { return m_bitfield.is_all_set(); } PeerInfo* peer_info() { return m_peerInfo; } const PeerInfo* peer_info() const { return m_peerInfo; } void set_peer_info(PeerInfo* p) { m_peerInfo = p; } bool using_counter() const { return m_usingCounter; } void set_using_counter(bool state) { m_usingCounter = state; } Bitfield* bitfield() { return &m_bitfield; } const Bitfield* bitfield() const { return &m_bitfield; } auto* download_cache() { return &m_downloadCache; } auto* upload_queue() { return &m_uploadQueue; } const auto* upload_queue() const { return &m_uploadQueue; } auto* cancel_queue() { return &m_cancelQueue; } // Timer used to figure out what HAVE_PIECE messages have not been // sent. std::chrono::microseconds have_timer() const { return m_have_timer; } void set_have_timer(std::chrono::microseconds t) { m_have_timer = t; } Rate* peer_rate() { return &m_peerRate; } const Rate* peer_rate() const { return &m_peerRate; } ThrottleNode* download_throttle() { return &m_downloadThrottle; } const ThrottleNode* download_throttle() const { return &m_downloadThrottle; } ThrottleNode* upload_throttle() { return &m_uploadThrottle; } const ThrottleNode* upload_throttle() const { return &m_uploadThrottle; } private: PeerInfo* m_peerInfo{}; bool m_usingCounter{false}; Bitfield m_bitfield; utils::PartialQueue m_downloadCache; piece_list_type m_uploadQueue; piece_list_type m_cancelQueue; std::chrono::microseconds m_have_timer{}; Rate m_peerRate{600}; ThrottleNode m_downloadThrottle{30}; ThrottleNode m_uploadThrottle{30}; }; } // namespace torrent #endif libtorrent-0.16.11/src/protocol/peer_factory.h0000644000000000000000000000403215175073411014761 // libTorrent - BitTorrent library // Copyright (C) 2005-2011, Jari Sundell // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // In addition, as a special exception, the copyright holders give // permission to link the code of portions of this program with the // OpenSSL library under certain conditions as described in each // individual source file, and distribute linked combinations // including the two. // // You must obey the GNU General Public License in all respects for // all of the code used other than OpenSSL. If you modify file(s) // with this exception, you may extend this exception to your version // of the file(s), but you are not obligated to do so. If you do not // wish to do so, delete this exception statement from your version. // If you delete this exception statement from all source files in the // program, then also delete it here. // // Contact: Jari Sundell // // Skomakerveien 33 // 3185 Skoppum, NORWAY #ifndef LIBTORRENT_PEER_PEER_FACTORY_H #define LIBTORRENT_PEER_PEER_FACTORY_H namespace torrent { class PeerConnectionBase; PeerConnectionBase* createPeerConnectionDefault(bool encrypted); PeerConnectionBase* createPeerConnectionSeed(bool encrypted); PeerConnectionBase* createPeerConnectionInitialSeed(bool encrypted); PeerConnectionBase* createPeerConnectionMetadata(bool encrypted); } // namespace torrent #endif libtorrent-0.16.11/src/protocol/request_list.h0000644000000000000000000001117515175073411015030 #ifndef LIBTORRENT_REQUEST_LIST_H #define LIBTORRENT_REQUEST_LIST_H #include #include #include "torrent/data/block_transfer.h" #include "torrent/utils/scheduler.h" #include "utils/instrumentation.h" #include "utils/queue_buckets.h" namespace torrent { class PeerChunks; class Delegator; struct request_list_constants { static constexpr int bucket_count = 4; static const torrent::instrumentation_enum instrumentation_added[bucket_count]; static const torrent::instrumentation_enum instrumentation_moved[bucket_count]; static const torrent::instrumentation_enum instrumentation_removed[bucket_count]; static const torrent::instrumentation_enum instrumentation_total[bucket_count]; template static void destroy(Type& obj); }; class RequestList { public: using queues_type = torrent::queue_buckets; static constexpr int bucket_queued = 0; static constexpr int bucket_unordered = 1; static constexpr int bucket_stalled = 2; static constexpr int bucket_choked = 3; static constexpr std::chrono::microseconds timeout_remove_choked{6s}; static constexpr std::chrono::microseconds timeout_choked_received{60s}; static constexpr std::chrono::microseconds timeout_process_unordered{60s}; RequestList(); ~RequestList(); // Some parameters here, like how fast we are downloading and stuff // when we start considering those. std::vector delegate(uint32_t maxPieces); void stall_initial(); void stall_prolonged(); void choked(); void unchoked(); void clear(); // The returned transfer must still be valid. bool downloading(const Piece& piece); void finished(); void skipped(); void transfer_dissimilar(); bool is_downloading() { return m_transfer != NULL; } bool is_interested_in_active() const; const Piece& next_queued_piece() const { return m_queues.front(bucket_queued)->piece(); } bool queued_empty() const { return m_queues.queue_empty(bucket_queued); } size_t queued_size() const { return m_queues.queue_size(bucket_queued); } bool unordered_empty() const { return m_queues.queue_empty(bucket_unordered); } size_t unordered_size() const { return m_queues.queue_size(bucket_unordered); } bool stalled_empty() const { return m_queues.queue_empty(bucket_stalled); } size_t stalled_size() const { return m_queues.queue_size(bucket_stalled); } bool choked_empty() const { return m_queues.queue_empty(bucket_choked); } size_t choked_size() const { return m_queues.queue_size(bucket_choked); } uint32_t pipe_size() const; uint32_t calculate_pipe_size(uint32_t rate); Delegator* delegator() { return m_delegator; } void set_delegator(Delegator* d) { m_delegator = d; } PeerChunks* peer_chunks() { return m_peerChunks; } void set_peer_chunks(PeerChunks* b) { m_peerChunks = b; } BlockTransfer* transfer() { return m_transfer; } const BlockTransfer* transfer() const { return m_transfer; } const BlockTransfer* queued_front() const { return m_queues.front(bucket_queued); } private: void delay_remove_choked(); void prepare_process_unordered(queues_type::iterator itr); void delay_process_unordered(); Delegator* m_delegator{}; PeerChunks* m_peerChunks{}; BlockTransfer* m_transfer{}; queues_type m_queues; int32_t m_affinity{-1}; std::chrono::microseconds m_last_choke{}; std::chrono::microseconds m_last_unchoke{}; size_t m_last_unordered_position{0}; torrent::utils::SchedulerEntry m_delay_remove_choked; torrent::utils::SchedulerEntry m_delay_process_unordered; }; inline RequestList::RequestList() { m_delay_remove_choked.slot() = [this] { delay_remove_choked(); }; m_delay_process_unordered.slot() = [this] { delay_process_unordered(); }; } // TODO: Make sure queued_size is never too small. inline uint32_t RequestList::pipe_size() const { return queued_size() + stalled_size() + unordered_size() / 4; } } // namespace torrent #endif libtorrent-0.16.11/src/protocol/peer_connection_leech.cc0000644000000000000000000005532115175073411016756 #include "config.h" #include #include #include "download/chunk_selector.h" #include "download/chunk_statistics.h" #include "download/download_main.h" #include "manager.h" #include "torrent/download/choke_group.h" #include "torrent/download/choke_queue.h" #include "torrent/download_info.h" #include "torrent/net/socket_address.h" #include "torrent/peer/connection_list.h" #include "torrent/peer/peer_info.h" #include "torrent/utils/log.h" #include "torrent/utils/uri_parser.h" #include "extensions.h" #include "initial_seed.h" #include "peer_connection_leech.h" #define LT_LOG_NETWORK_ERRORS(log_fmt, ...) \ lt_log_print_info(LOG_PROTOCOL_NETWORK_ERRORS, this->download()->info(), "network_errors", "%40s " log_fmt, this->peer_info()->id_hex(), __VA_ARGS__); #define LT_LOG_STORAGE_ERRORS(log_fmt, ...) \ lt_log_print_info(LOG_PROTOCOL_STORAGE_ERRORS, this->download()->info(), "storage_errors", "%40s " log_fmt, this->peer_info()->id_hex(), __VA_ARGS__); namespace torrent { #if 0 template PeerConnection::~PeerConnection() { // if (m_download != NULL && m_down->get_state() != ProtocolRead::READ_BITFIELD) // m_download->bitfield_counter().dec(m_peerChunks.bitfield()->bitfield()); // priority_queue_erase(&taskScheduler, &m_taskSendChoke); } #else template PeerConnection::~PeerConnection() = default; #endif template void PeerConnection::initialize_custom() { if (type == Download::CONNECTION_INITIAL_SEED) { if (m_download->initial_seeding() == NULL) throw close_connection(); m_download->initial_seeding()->new_peer(this); } // if (m_download->content()->chunks_completed() != 0) { // m_up->write_bitfield(m_download->file_list()->bitfield()->size_bytes()); // m_up->buffer()->prepare_end(); // m_up->set_position(0); // m_up->set_state(ProtocolWrite::WRITE_BITFIELD_HEADER); // } } template void PeerConnection::update_interested() { if (type != Download::CONNECTION_LEECH) return; m_peerChunks.download_cache()->clear(); if (m_downInterested) return; // Consider just setting to interested without checking the // bitfield. The status might change by the time we get unchoked // anyway. m_sendInterested = !m_downInterested; m_downInterested = true; // Hmm... does this belong here, or should we insert ourselves into // the queue when we receive the unchoke? // m_download->choke_group()->down_queue()->set_queued(this, &m_downChoke); } template bool PeerConnection::receive_keepalive() { if (this_thread::cached_time() - m_time_last_read > 240s) return false; // There's no point in adding ourselves to the write poll if the // buffer is full, as that will already have been taken care of. if (m_up->get_state() == ProtocolWrite::IDLE && m_up->can_write_keepalive()) { write_insert_poll_safe(); ProtocolBuffer<512>::iterator old_end = m_up->buffer()->end(); m_up->write_keepalive(); if (is_encrypted()) m_encryption.encrypt(old_end, m_up->buffer()->end() - old_end); } if (type != Download::CONNECTION_LEECH) return true; m_tryRequest = true; // Stall pieces when more than one receive_keepalive() has been // called while a single piece is downloading. // // m_downStall is decremented for every successfull download, so it // should stay at zero or one when downloading at an acceptable // speed. Thus only when m_downStall >= 2 is the download actually // stalling. // // If more than 6 ticks have gone by, assume the peer forgot about // our requests or tried to cheat with empty piece messages, and try // again. // TODO: Do we need to remove from download throttle here? // // Do we also need to remove from download throttle? Check how it // worked again. // if (request_list()->empty()) // return true; if (m_downStall >= 2) request_list()->stall_prolonged(); else if (m_downStall++ != 0) request_list()->stall_initial(); return true; } // We keep the message in the buffer if it is incomplete instead of // keeping the state and remembering the read information. This // shouldn't happen very often compared to full reads. template inline bool PeerConnection::read_message() { ProtocolBuffer<512>* buf = m_down->buffer(); if (buf->remaining() < 4) return false; // Remember the start of the message so we may reset it if we don't // have the whole message. ProtocolBuffer<512>::iterator beginning = buf->position(); uint32_t length = buf->read_32(); if (length == 0) { // Keepalive message. m_down->set_last_command(ProtocolBase::KEEP_ALIVE); return true; } else if (buf->remaining() < 1) { buf->set_position_itr(beginning); return false; } else if (length > (1 << 20)) { throw communication_error("PeerConnection::read_message() got an invalid message length."); } // We do not verify the message length of those with static // length. A bug in the remote client causing the message start to // be unsyncronized would in practically all cases be caught with // the above test. // // Those that do in some weird way manage to produce a valid // command, will not be able to do any more damage than a malicious // peer. Those cases should be caught elsewhere in the code. // Temporary. m_down->set_last_command(static_cast(buf->peek_8())); switch (buf->read_8()) { case ProtocolBase::CHOKE: if (type != Download::CONNECTION_LEECH) return true; // Cancel before dequeueing so receive_download_choke knows if it // should remove us from throttle. // // Hmm... that won't work, as we arn't necessarily unchoked when // in throttle. // Which needs to be done before, and which after calling choke // manager? m_downUnchoked = false; down_chunk_release(); request_list()->choked(); m_download->choke_group()->down_queue()->set_not_queued(this, &m_downChoke); m_down->throttle()->erase(m_peerChunks.download_throttle()); return true; case ProtocolBase::UNCHOKE: if (type != Download::CONNECTION_LEECH) return true; m_downUnchoked = true; // Some peers unchoke us even though we're not interested, so we // need to ensure it doesn't get added to the queue. if (!m_downInterested) return true; request_list()->unchoked(); m_download->choke_group()->down_queue()->set_queued(this, &m_downChoke); return true; case ProtocolBase::INTERESTED: if (type == Download::CONNECTION_LEECH && m_peerChunks.bitfield()->is_all_set()) return true; m_download->choke_group()->up_queue()->set_queued(this, &m_upChoke); return true; case ProtocolBase::NOT_INTERESTED: m_download->choke_group()->up_queue()->set_not_queued(this, &m_upChoke); return true; case ProtocolBase::HAVE: if (!m_down->can_read_have_body()) break; read_have_chunk(buf->read_32()); return true; case ProtocolBase::REQUEST: if (!m_down->can_read_request_body()) break; if (!m_upChoke.choked()) { write_insert_poll_safe(); read_request_piece(m_down->read_request()); } else { m_down->read_request(); } return true; case ProtocolBase::PIECE: if (type != Download::CONNECTION_LEECH) throw communication_error("Received a piece but the connection is strictly for seeding."); if (!m_down->can_read_piece_body()) break; if (!down_chunk_start(m_down->read_piece(length - 9))) { // We don't want this chunk. if (down_chunk_skip_from_buffer()) { m_tryRequest = true; down_chunk_finished(); return true; } else { m_down->set_state(ProtocolRead::READ_SKIP_PIECE); m_down->throttle()->insert(m_peerChunks.download_throttle()); return false; } } else { if (down_chunk_from_buffer()) { m_tryRequest = true; down_chunk_finished(); return true; } else { m_down->set_state(ProtocolRead::READ_PIECE); m_down->throttle()->insert(m_peerChunks.download_throttle()); return false; } } case ProtocolBase::CANCEL: if (!m_down->can_read_cancel_body()) break; read_cancel_piece(m_down->read_request()); return true; case ProtocolBase::PORT: if (!m_down->can_read_port_body()) break; runtime::dht_add_peer_node(m_peerInfo->socket_address(), m_down->buffer()->read_16()); return true; case ProtocolBase::EXTENSION_PROTOCOL: if (!m_down->can_read_extension_body()) break; if (m_extensions->is_default()) { m_extensions = new ProtocolExtension(); m_extensions->set_info(m_peerInfo, m_download); } { int extension = m_down->buffer()->read_8(); m_extensions->read_start(extension, length - 2, (extension == ProtocolExtension::UT_PEX) && !m_download->want_pex_msg()); m_down->set_state(ProtocolRead::READ_EXTENSION); } if (!down_extension()) return false; if (m_extensions->has_pending_message()) write_insert_poll_safe(); m_down->set_state(ProtocolRead::IDLE); return true; default: throw communication_error("Received unsupported message type."); } // We were unsuccessfull in reading the message, need more data. buf->set_position_itr(beginning); return false; } template void PeerConnection::event_read() { m_time_last_read = this_thread::cached_time(); // Need to make sure ProtocolBuffer::end() is pointing to the end of // the unread data, and that the unread data starts from the // beginning of the buffer. Or do we use position? Propably best, // therefor ProtocolBuffer::position() points to the beginning of // the unused data. try { // Normal read. // // We rarely will read zero bytes as the read of 64 bytes will // almost always either not fill up or it will require additional // reads. // // Only loop when end hits 64. do { switch (m_down->get_state()) { case ProtocolRead::IDLE: if (m_down->buffer()->size_end() < read_size) { unsigned int length = read_stream_throws(m_down->buffer()->end(), read_size - m_down->buffer()->size_end()); m_down->throttle()->node_used_unthrottled(length); if (is_encrypted()) m_encryption.decrypt(m_down->buffer()->end(), length); m_down->buffer()->move_end(length); } while (read_message()) ; // Do nothing. if (m_down->buffer()->size_end() == read_size) { m_down->buffer()->move_unused(); break; } else { m_down->buffer()->move_unused(); return; } case ProtocolRead::READ_PIECE: if (type != Download::CONNECTION_LEECH) return; if (!request_list()->is_downloading()) throw internal_error("ProtocolRead::READ_PIECE state but RequestList is not downloading."); if (!m_request_list.transfer()->is_valid() || !m_request_list.transfer()->is_leader()) { m_down->set_state(ProtocolRead::READ_SKIP_PIECE); break; } if (!down_chunk()) return; m_tryRequest = true; m_down->set_state(ProtocolRead::IDLE); down_chunk_finished(); break; case ProtocolRead::READ_SKIP_PIECE: if (type != Download::CONNECTION_LEECH) return; if (request_list()->transfer()->is_leader()) { m_down->set_state(ProtocolRead::READ_PIECE); break; } if (!down_chunk_skip()) return; m_tryRequest = true; m_down->set_state(ProtocolRead::IDLE); down_chunk_finished(); break; case ProtocolRead::READ_EXTENSION: if (!down_extension()) return; if (m_extensions->has_pending_message()) write_insert_poll_safe(); m_down->set_state(ProtocolRead::IDLE); break; default: throw internal_error("PeerConnection::event_read() wrong state."); } // Figure out how to get rid of the shouldLoop boolean. } while (true); // Exception handlers: } catch (const close_connection&) { m_download->connection_list()->erase(this, 0); } catch (const blocked_connection&) { m_download->connection_list()->erase(this, 0); } catch (const network_error& e) { LT_LOG_NETWORK_ERRORS("network read error: %s : %s", sa_pretty_str(m_peerInfo->socket_address()).c_str(), e.what()); m_download->connection_list()->erase(this, 0); } catch (const storage_error& e) { LT_LOG_NETWORK_ERRORS("storage read error: %s", e.what()); m_download->connection_list()->erase(this, 0); } catch (const base_error& e) { std::stringstream s; s << "Connection read fd(" << m_fileDesc << ',' << m_down->get_state() << ',' << m_down->last_command() << ") \"" << e.what() << '"'; s << " '" << utils::uri_escape_html(reinterpret_cast(m_down->buffer()->begin()), reinterpret_cast(m_down->buffer()->position())) << "'"; throw internal_error(s.str()); } } template inline void PeerConnection::fill_write_buffer() { ProtocolBuffer<512>::iterator old_end = m_up->buffer()->end(); // No need to use delayed choke ever. if (m_sendChoked && m_up->can_write_choke()) { m_sendChoked = false; m_up->write_choke(m_upChoke.choked()); if (m_upChoke.choked()) { m_up->throttle()->erase(m_peerChunks.upload_throttle()); up_chunk_release(); m_peerChunks.upload_queue()->clear(); if (m_encryptBuffer != nullptr) { if (m_encryptBuffer->remaining()) throw internal_error("Deleting encryptBuffer with encrypted data remaining."); m_encryptBuffer = nullptr; } } else { m_up->throttle()->insert(m_peerChunks.upload_throttle()); } } // Send the interested state before any requests as some clients, // e.g. BitTornado 0.7.14 and uTorrent 0.3.0, disconnect if a // request has been received while uninterested. The problem arises // as they send unchoke before receiving interested. if (type == Download::CONNECTION_LEECH && m_sendInterested && m_up->can_write_interested()) { m_up->write_interested(m_downInterested); m_sendInterested = false; } if (type == Download::CONNECTION_LEECH && m_tryRequest) { if (!(m_tryRequest = !should_request()) && !(m_tryRequest = try_request_pieces()) && !request_list()->is_interested_in_active()) { m_sendInterested = true; m_downInterested = false; m_download->choke_group()->down_queue()->set_not_queued(this, &m_downChoke); } } DownloadMain::have_queue_type* haveQueue = m_download->have_queue(); if (type == Download::CONNECTION_LEECH && !haveQueue->empty() && m_peerChunks.have_timer() <= haveQueue->front().first && m_up->can_write_have()) { auto last = std::find_if(haveQueue->begin(), haveQueue->end(), [this](auto v) { return m_peerChunks.have_timer() > v.first; }); do { m_up->write_have((--last)->second); } while (last != haveQueue->begin() && m_up->can_write_have()); m_peerChunks.set_have_timer(last->first + 1us); } if (type == Download::CONNECTION_INITIAL_SEED && m_up->can_write_have()) offer_chunk(); while (type == Download::CONNECTION_LEECH && !m_peerChunks.cancel_queue()->empty() && m_up->can_write_cancel()) { m_up->write_cancel(m_peerChunks.cancel_queue()->front()); m_peerChunks.cancel_queue()->pop_front(); } if (m_sendPEXMask && m_up->can_write_extension() && send_pex_message()) { // Don't do anything else if send_pex_message() succeeded. } else if (m_extensions->has_pending_message() && m_up->can_write_extension() && send_ext_message()) { // Same. } else if (!m_upChoke.choked() && !m_peerChunks.upload_queue()->empty() && m_up->can_write_piece() && (type != Download::CONNECTION_INITIAL_SEED || should_upload())) { write_prepare_piece(); } if (is_encrypted()) m_encryption.encrypt(old_end, m_up->buffer()->end() - old_end); } template void PeerConnection::event_write() { try { do { switch (m_up->get_state()) { case ProtocolWrite::IDLE: fill_write_buffer(); if (m_up->buffer()->remaining() == 0) { this_thread::poll()->remove_write(this); return; } m_up->set_state(ProtocolWrite::MSG); [[fallthrough]]; case ProtocolWrite::MSG: if (!m_up->buffer()->consume(m_up->throttle()->node_used_unthrottled(write_stream_throws(m_up->buffer()->position(), m_up->buffer()->remaining())))) return; m_up->buffer()->reset(); if (m_up->last_command() == ProtocolBase::PIECE) { // We're uploading a piece. load_up_chunk(); m_up->set_state(ProtocolWrite::WRITE_PIECE); // fall through to WRITE_PIECE case below } else if (m_up->last_command() == ProtocolBase::EXTENSION_PROTOCOL) { m_up->set_state(ProtocolWrite::WRITE_EXTENSION); break; } else { // Break or loop? Might do an ifelse based on size of the // write buffer. Also the write buffer is relatively large. m_up->set_state(ProtocolWrite::IDLE); break; } [[fallthrough]]; case ProtocolWrite::WRITE_PIECE: if (!up_chunk()) return; m_up->set_state(ProtocolWrite::IDLE); break; case ProtocolWrite::WRITE_EXTENSION: if (!up_extension()) return; m_up->set_state(ProtocolWrite::IDLE); break; default: throw internal_error("PeerConnection::event_write() wrong state."); } } while (true); } catch (const close_connection&) { m_download->connection_list()->erase(this, 0); } catch (const blocked_connection&) { m_download->connection_list()->erase(this, 0); } catch (const network_error& e) { LT_LOG_NETWORK_ERRORS("network write error: %s : %s", sa_pretty_str(m_peerInfo->socket_address()).c_str(), e.what()); m_download->connection_list()->erase(this, 0); } catch (const storage_error& e) { LT_LOG_STORAGE_ERRORS("write error: %s", e.what()); m_download->connection_list()->erase(this, 0); } catch (const base_error& e) { std::stringstream s; s << "Connection write fd(" << m_fileDesc << ',' << m_up->get_state() << ',' << m_up->last_command() << ") \"" << e.what() << '"'; throw internal_error(s.str()); } } template void PeerConnection::read_have_chunk(uint32_t index) { if (index >= m_peerChunks.bitfield()->size_bits()) throw communication_error("Peer sent HAVE message with out-of-range index."); if (m_peerChunks.bitfield()->get(index)) return; m_download->chunk_statistics()->received_have_chunk(&m_peerChunks, index, m_download->file_list()->chunk_size()); if (type == Download::CONNECTION_INITIAL_SEED) m_download->initial_seeding()->chunk_seen(index, this); // Disconnect seeds when we are seeding (but not for initial seeding // so that we keep accurate chunk statistics until that is done). if (m_peerChunks.bitfield()->is_all_set()) { if (type == Download::CONNECTION_SEED || (type != Download::CONNECTION_INITIAL_SEED && m_download->file_list()->is_done())) throw close_connection(); m_download->choke_group()->up_queue()->set_not_queued(this, &m_upChoke); } if (type != Download::CONNECTION_LEECH || m_download->file_list()->is_done()) return; if (is_down_interested()) { if (!m_tryRequest && m_download->chunk_selector()->received_have_chunk(&m_peerChunks, index)) { m_tryRequest = true; write_insert_poll_safe(); } } else { if (m_download->chunk_selector()->received_have_chunk(&m_peerChunks, index)) { m_sendInterested = !m_downInterested; m_downInterested = true; // Ensure we get inserted into the choke manager queue in case // the peer keeps us unchoked even though we've said we're not // interested. if (m_downUnchoked) m_download->choke_group()->down_queue()->set_queued(this, &m_downChoke); // Is it enough to insert into write here? Make the interested // check branch to include insert_write, even when not sending // interested. m_tryRequest = true; write_insert_poll_safe(); } } } template<> void PeerConnection::offer_chunk() { // If bytes left to send in this chunk minus bytes about to be sent is zero, // assume the peer will have got the chunk completely. In that case we may // get another one to offer if not enough other peers are interested even // if the peer would otherwise still be blocked. uint32_t bytesLeft = m_data.bytesLeft; if (!m_peerChunks.upload_queue()->empty() && m_peerChunks.upload_queue()->front().index() == m_data.lastIndex) bytesLeft -= m_peerChunks.upload_queue()->front().length(); uint32_t index = m_download->initial_seeding()->chunk_offer(this, bytesLeft == 0 ? m_data.lastIndex : InitialSeeding::no_offer); if (index == InitialSeeding::no_offer || index == m_data.lastIndex) return; m_up->write_have(index); m_data.lastIndex = index; m_data.bytesLeft = m_download->file_list()->chunk_index_size(index); } template<> bool PeerConnection::should_upload() { // For initial seeding, check if chunk is well seeded now, and if so // remove it from the queue to better use our bandwidth on rare chunks. while (!m_peerChunks.upload_queue()->empty() && !m_download->initial_seeding()->should_upload(m_peerChunks.upload_queue()->front().index())) m_peerChunks.upload_queue()->pop_front(); // If queue ends up empty, choke peer to let it know that it // shouldn't wait for the cancelled pieces to be sent. if (m_peerChunks.upload_queue()->empty()) { m_download->choke_group()->up_queue()->set_not_queued(this, &m_upChoke); m_download->choke_group()->up_queue()->set_queued(this, &m_upChoke); // If we're sending the chunk we last offered, adjust bytes left in it. } else if (m_peerChunks.upload_queue()->front().index() == m_data.lastIndex) { m_data.bytesLeft -= m_peerChunks.upload_queue()->front().length(); if (!m_data.bytesLeft) m_data.lastIndex = InitialSeeding::no_offer; } return !m_peerChunks.upload_queue()->empty(); } // Explicit instantiation of the member functions and vtable. template class PeerConnection; template class PeerConnection; template class PeerConnection; } // namespace torrent libtorrent-0.16.11/src/net/0000755000000000000000000000000015175073434011141 5libtorrent-0.16.11/src/net/curl_get.h0000644000000000000000000001337215175073411013037 #ifndef LIBTORRENT_NET_CURL_GET_H #define LIBTORRENT_NET_CURL_GET_H #include #include #include #include #include #include #include #include "torrent/system/thread.h" namespace torrent::net { class CurlStack; class CurlGet { public: enum resolve_type { RESOLVE_NONE, RESOLVE_WHATEVER, RESOLVE_IPV4, RESOLVE_IPV6 }; CurlGet(std::string url = "", std::shared_ptr stream = nullptr); ~CurlGet(); static void start(const std::shared_ptr& curl_get, CurlStack* stack); static void close(const std::shared_ptr& curl_get, system::Thread* thread, bool wait); static void close_and_keep_callbacks(const std::shared_ptr& curl_get); static void close_and_cancel_callbacks(const std::shared_ptr& curl_get, system::Thread* callback_thread); static void close_and_wait(const std::shared_ptr& curl_get); bool is_stacked() const; bool is_active() const; bool is_closing() const; CurlStack* curl_stack() const; const std::string& url() const; uint32_t timeout() const; int64_t size_done(); int64_t size_total(); void reset(const std::string& url, std::shared_ptr str); void wait_for_close(); bool try_wait_for_close(); void set_timeout(uint32_t seconds); void set_initial_resolve(resolve_type type); void set_retry_resolve(resolve_type type); // The owner of the Http object must close it as soon as possible after receiving the signal, as // the implementation may allocate limited resources during its lifetime. // // These slots should not directly modify the CurlGet or CurlStack, and instead use callbacks, // etc, for such actions. // // The slots should be non-blocking and the CurlGet object will remain locked during the call, and // as such cannot be modified. // // The slots won't be called after set_was_closed() is called. void add_done_slot(const std::function& slot); void add_failed_slot(const std::function& slot); // TODO: Add add_deleted_slot, or a list of threads to remove callbacks from? protected: friend class CurlStack; // We need to lock when changing any of the values publically accessible. This means we don't need // to lock when changing the underlying vector. void lock() const { m_mutex.lock(); } auto lock_guard() const { return std::lock_guard(m_mutex); } void unlock() const { m_mutex.unlock(); } auto& mutex() const { return m_mutex; } bool is_active_unsafe() const { return m_active; } bool is_prepare_canceled_unsafe() const { return m_prepare_canceled; } bool is_closing_unsafe() const { return m_was_closed; } auto handle_unsafe() const { return m_handle; } [[nodiscard]] bool prepare_start_unsafe(CurlStack* stack); void activate_unsafe(); void deactivate_unsafe(); void cleanup_unsafe(); bool retry_resolve(); void notify_closed() { m_cond_closed.notify_all(); } void trigger_done(); void trigger_failed(const std::string& message); private: CurlGet(const CurlGet&) = delete; CurlGet& operator=(const CurlGet&) = delete; static size_t receive_write(const char* data, size_t size, size_t nmemb, CurlGet* handle); bool prepare_resolve_unsafe(resolve_type current_resolve); mutable std::mutex m_mutex; CURL* m_handle{}; CurlStack* m_stack{}; system::Thread* m_stack_thread{}; bool m_active{}; bool m_prepare_canceled{}; bool m_was_started{}; bool m_was_closed{}; resolve_type m_initial_resolve{RESOLVE_WHATEVER}; resolve_type m_retry_resolve{RESOLVE_NONE}; bool m_retrying_resolve{}; // When you change timeout to a different type, update curl_get.cc where it multiplies // 1s*m_timeout. std::string m_url; std::shared_ptr m_stream; uint32_t m_timeout{5 * 60}; std::condition_variable m_cond_closed; std::list> m_signal_done; std::list> m_signal_failed; }; inline void CurlGet::close_and_keep_callbacks(const std::shared_ptr& curl_get) { close(curl_get, nullptr, false); } inline void CurlGet::close_and_cancel_callbacks(const std::shared_ptr& curl_get, system::Thread* thread) { close(curl_get, thread, false); } inline void CurlGet::close_and_wait(const std::shared_ptr& curl_get) { close(curl_get, nullptr, true); } inline bool CurlGet::is_stacked() const { auto guard = lock_guard(); return m_handle != nullptr; } inline bool CurlGet::is_active() const { auto guard = lock_guard(); return m_active; } inline bool CurlGet::is_closing() const { auto guard = lock_guard(); return m_was_closed; } inline CurlStack* CurlGet::curl_stack() const { auto guard = lock_guard(); return m_stack; } inline const std::string& CurlGet::url() const { auto guard = lock_guard(); return m_url; } inline uint32_t CurlGet::timeout() const { auto guard = lock_guard(); return m_timeout; } } // namespace torrent::net #endif // LIBTORRENT_NET_CURL_GET_H libtorrent-0.16.11/src/net/thread_net.h0000644000000000000000000000327215175073411013346 #ifndef LIBTORRENT_NET_THREAD_NET_H #define LIBTORRENT_NET_THREAD_NET_H #include "torrent/common.h" #include "torrent/system/thread.h" namespace torrent { namespace net { class DnsBuffer; class DnsCache; class HttpStack; class UdnsResolver; } // namespace net class LIBTORRENT_EXPORT ThreadNet : public system::Thread { public: ~ThreadNet() override; static void create_thread(); static void destroy_thread(); static ThreadNet* thread_net(); const char* name() const override { return "rtorrent-net"; } void init_thread() override; void init_thread_post_local() override; void cleanup_thread() override; protected: friend class ThreadNetInternal; friend class torrent::net::DnsCache; friend class torrent::net::DnsBuffer; friend class torrent::net::HttpStack; friend class torrent::net::Resolver; ThreadNet() = default; static auto internal_thread_net() { return m_thread_net; } void call_events() override; std::chrono::microseconds next_timeout() override; net::HttpStack* http_stack() const { return m_http_stack.get(); } net::DnsBuffer* dns_buffer() const { return m_dns_buffer.get(); } net::DnsCache* dns_cache() const { return m_dns_cache.get(); } net::UdnsResolver* dns_resolver() const { return m_dns_resolver.get(); } private: static ThreadNet* m_thread_net; std::unique_ptr m_http_stack; std::unique_ptr m_dns_buffer; std::unique_ptr m_dns_cache; std::unique_ptr m_dns_resolver; }; } // namespace torrent #endif // LIBTORRENT_NET_THREAD_NET_H libtorrent-0.16.11/src/net/dns_cache.h0000644000000000000000000000445415175073411013143 #ifndef LIBTORRENT_NET_DNS_CACHE_H #define LIBTORRENT_NET_DNS_CACHE_H #include #include #include #include #include #include #include "torrent/net/types.h" namespace torrent::net { struct DnsCacheEntry; using DnsCacheEntries = std::unordered_map>; using DnsCacheStaleness = std::list; struct DnsCacheInfo { bool updating{}; bool no_record{}; std::chrono::minutes last_updated{}; std::chrono::minutes last_failed_update{}; DnsCacheEntries::iterator entry_itr{}; DnsCacheStaleness::iterator staleness_itr{}; }; struct DnsCacheEntry { sin_shared_ptr sin_addr; DnsCacheInfo sin_info; sin6_shared_ptr sin6_addr; DnsCacheInfo sin6_info; }; class DnsCache { public: // TODO: Add different types of resolve, e.g. force, in_error, etc. void resolve(void* requester, std::string hostname, int family, resolver_callback&& callback); protected: friend class DnsBuffer; void process_success(const std::string& hostname, int family, sin_shared_ptr result_sin, sin6_shared_ptr result_sin6); void process_failure(const std::string& hostname, int family, int error); private: void reset_sin_updated(DnsCacheEntry* entry, std::chrono::minutes current_time); void reset_sin6_updated(DnsCacheEntry* entry, std::chrono::minutes current_time); void reset_sin_failed(DnsCacheEntry* entry, std::chrono::minutes current_time); void reset_sin6_failed(DnsCacheEntry* entry, std::chrono::minutes current_time); void cull_stale_entries(); bool try_resolve_numeric(void* requester, const std::string& hostname, int family, resolver_callback&& callback); void queue_resolve(void* requester, const std::string& hostname, int family, DnsCacheInfo& info, resolver_callback&& callback); void update_stale_info(const char* reason, void* requester, const std::string& hostname, int family, DnsCacheInfo& info); DnsCacheEntries m_entries; DnsCacheStaleness m_sin_staleness; DnsCacheStaleness m_sin6_staleness; }; } // namespace torrent::net #endif // LIBTORRENT_NET_DNS_CACHE_H libtorrent-0.16.11/src/net/curl_get.cc0000644000000000000000000003022115175073411013165 #include "config.h" #include "net/curl_get.h" #include #include #include #include #include "net/curl_socket.h" #include "net/curl_stack.h" #include "torrent/exceptions.h" #include "torrent/net/network_config.h" #include "torrent/net/socket_address.h" #include "torrent/system/thread.h" #include "torrent/utils/uri_parser.h" #include "utils/functional.h" namespace torrent::net { CurlGet::CurlGet(std::string url, std::shared_ptr stream) : m_url(std::move(url)), m_stream(std::move(stream)) { } CurlGet::~CurlGet() { // CurlStack keeps a shared_ptr to this object, so it will only be destroyed once it is removed // from the stack. assert(!is_stacked() && "CurlGet::~CurlGet called while still in the stack."); } int64_t CurlGet::size_done() { auto guard = lock_guard(); if (m_handle == nullptr) return 0; curl_off_t d = 0; curl_easy_getinfo(m_handle, CURLINFO_SIZE_DOWNLOAD_T, &d); return d; } int64_t CurlGet::size_total() { auto guard = lock_guard(); if (m_handle == nullptr) return 0; curl_off_t d = 0; curl_easy_getinfo(m_handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, &d); return d; } void CurlGet::reset(const std::string& url, std::shared_ptr stream) { auto guard = lock_guard(); if (m_was_started) throw torrent::internal_error("CurlGet::reset() called on a started object."); if (m_handle != nullptr) throw torrent::internal_error("CurlGet::reset() called on a stacked object."); m_url = url; m_stream = std::move(stream); } void CurlGet::wait_for_close() { std::unique_lock guard(m_mutex); if (!m_was_closed) throw torrent::internal_error("CurlGet::wait_for_close() called on an object that is not closing."); if (m_handle != nullptr) m_cond_closed.wait(guard, [this] { return m_handle == nullptr; }); } bool CurlGet::try_wait_for_close() { std::unique_lock guard(m_mutex); if (!m_was_closed) return false; if (m_handle != nullptr) m_cond_closed.wait(guard, [this] { return m_handle == nullptr; }); return true; } void CurlGet::set_timeout(uint32_t seconds) { auto guard = lock_guard(); if (m_was_started) throw torrent::internal_error("CurlGet::set_timeout(...) called on a started object."); m_timeout = seconds; } void CurlGet::set_initial_resolve(resolve_type type) { auto guard = lock_guard(); if (m_was_started) throw torrent::internal_error("CurlGet::set_initial_resolve(...) called on a stacked or started object."); if (type == RESOLVE_NONE) throw torrent::internal_error("CurlGet::set_initial_resolve(...) called with RESOLVE_NONE, which is not allowed."); m_initial_resolve = type; } void CurlGet::set_retry_resolve(resolve_type type) { auto guard = lock_guard(); if (m_was_started) throw torrent::internal_error("CurlGet::set_retry_resolve(...) called on a stacked or started object."); m_retry_resolve = type; } void CurlGet::start(const std::shared_ptr& curl_get, CurlStack* stack) { auto self = curl_get.get(); std::unique_lock guard(self->m_mutex); if (self->m_was_started) throw torrent::internal_error("CurlGet::start() called on an already started object."); self->m_was_started = true; self->m_stack_thread = stack->thread(); stack->thread()->callback(self, [stack, curl_get]() { stack->start_get(curl_get); }); } void CurlGet::close(const std::shared_ptr& curl_get, system::Thread* callback_thread, bool wait) { auto self = curl_get.get(); std::unique_lock guard(self->m_mutex); if (!self->m_was_started) throw torrent::internal_error("CurlGet::close_and_cancel_callbacks() called on an object that was not started."); if (self->m_was_closed) throw torrent::internal_error("CurlGet::close_and_cancel_callbacks() called on an already closing object."); self->m_stack_thread->cancel_callback(self); if (callback_thread != nullptr) callback_thread->cancel_callback(self); if (self->m_stack == nullptr) { if (self->m_was_started) { self->m_stack_thread = nullptr; self->m_was_started = false; self->m_was_closed = false; self->m_prepare_canceled = false; self->m_retrying_resolve = false; } return; } assert(std::this_thread::get_id() != self->m_stack->thread()->thread_id()); assert(callback_thread != self->m_stack->thread()); self->m_was_closed = true; self->m_stack->thread()->callback_interrupt_polling(self, [curl_stack = self->m_stack, curl_get]() { curl_stack->close_get(curl_get); }); if (wait && self->m_handle == nullptr) self->m_cond_closed.wait(guard, [self] { return self->m_handle == nullptr; }); } bool CurlGet::prepare_start_unsafe(CurlStack* stack) { if (m_handle != nullptr) throw torrent::internal_error("CurlGet::prepare_start(...) called on a stacked object."); if (m_stream == nullptr) throw torrent::internal_error("CurlGet::prepare_start(...) called with a null stream."); if (!m_was_started) throw torrent::internal_error("CurlGet::prepare_start(...) called on an object that was not started."); if (m_was_closed) { m_prepare_canceled = true; return false; } m_handle = curl_easy_init(); m_stack = stack; m_retrying_resolve = false; if (m_handle == nullptr) throw torrent::internal_error("Call to curl_easy_init() failed."); curl_easy_setopt(m_handle, CURLOPT_URL, m_url.c_str()); curl_easy_setopt(m_handle, CURLOPT_WRITEFUNCTION, &CurlGet::receive_write); curl_easy_setopt(m_handle, CURLOPT_WRITEDATA, this); // Close function and data must be set before libcurl's create_conn() is called. // // TODO: Consier all libcurl sockets to be !m_properly_opened for now. // curl_easy_setopt(m_handle, CURLOPT_OPENSOCKETFUNCTION, &CurlSocket::open_socket); // curl_easy_setopt(m_handle, CURLOPT_CLOSESOCKETFUNCTION, &CurlSocket::close_socket); // curl_easy_setopt(m_handle, CURLOPT_OPENSOCKETDATA, stack); // curl_easy_setopt(m_handle, CURLOPT_CLOSESOCKETDATA, stack); // Disable connection reuse as libcurl doesn't provide proper API to handle idle connections being // closed/reused. // // TODO: Remove this when libcurl issues are resolved. // TODO: Make sure shutdown quickly cleans up idle connections. curl_easy_setopt(m_handle, CURLOPT_FORBID_REUSE, 1l); if (m_timeout != 0) { curl_easy_setopt(m_handle, CURLOPT_CONNECTTIMEOUT, 60l); curl_easy_setopt(m_handle, CURLOPT_TIMEOUT, static_cast(m_timeout)); } curl_easy_setopt(m_handle, CURLOPT_NOSIGNAL, 1l); curl_easy_setopt(m_handle, CURLOPT_FOLLOWLOCATION, 1l); curl_easy_setopt(m_handle, CURLOPT_MAXREDIRS, 5l); curl_easy_setopt(m_handle, CURLOPT_ENCODING, ""); // Note that if the url has a numeric IP address, libcurl will not respect the CURLOPT_IPRESOLVE // option. // // We need to make CurlGet fail on numeric urls which do not match the resolve type. if (m_initial_resolve == RESOLVE_NONE) throw torrent::internal_error("CurlGet::prepare_start_unsafe() called with m_initial_resolve set to RESOLVE_NONE."); if (m_initial_resolve == RESOLVE_WHATEVER) { curl_easy_setopt(m_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_WHATEVER); return true; } try { try { if (prepare_resolve_unsafe(m_initial_resolve)) return true; } catch (const torrent::input_error& e) { if (m_retry_resolve == RESOLVE_NONE) throw; // TODO: Save the error msg for later. } m_retrying_resolve = true; if (prepare_resolve_unsafe(m_retry_resolve)) return true; throw torrent::input_error("Exhausted all resolve options."); } catch (const torrent::input_error& e) { m_prepare_canceled = true; ::utils::slot_list_call(m_signal_failed, e.what()); return false; } } void CurlGet::activate_unsafe() { if (m_active) throw torrent::internal_error("CurlGet::activate() called on an already active handle."); CURLMcode code = curl_multi_add_handle(m_stack->handle(), m_handle); if (code != CURLM_OK) throw torrent::internal_error("CurlGet::activate() error calling curl_multi_add_handle: " + std::string(curl_multi_strerror(code))); m_active = true; } void CurlGet::deactivate_unsafe() { if (!m_active) throw torrent::internal_error("CurlGet::deactivate() called on an inactive handle."); CURLMcode code = curl_multi_remove_handle(m_stack->handle(), m_handle); if (code != CURLM_OK) throw torrent::internal_error("CurlGet::deactivate() error calling curl_multi_remove_handle: " + std::string(curl_multi_strerror(code))); m_active = false; } void CurlGet::cleanup_unsafe() { if (m_handle != nullptr) { if (m_active) deactivate_unsafe(); curl_easy_cleanup(m_handle); m_handle = nullptr; m_stack = nullptr; } else { if (!m_prepare_canceled) throw torrent::internal_error("CurlGet::cleanup() called on an object that has no m_handle yet m_prepare_canceled is false."); } m_stack_thread = nullptr; m_was_started = false; m_was_closed = false; m_prepare_canceled = false; m_retrying_resolve = false; } // Slots can be added at any time, however once trigger_* is called, it will make a copy of the // current list. void CurlGet::add_done_slot(const std::function& slot) { auto guard = lock_guard(); m_signal_done.push_back(slot); } void CurlGet::add_failed_slot(const std::function& slot) { auto guard = lock_guard(); m_signal_failed.push_back(slot); } bool CurlGet::retry_resolve() { auto guard = lock_guard(); if (m_handle == nullptr) throw torrent::internal_error("CurlGet::retry_ipv6() called on a null m_handle."); if (m_retrying_resolve || m_retry_resolve == RESOLVE_NONE) return false; deactivate_unsafe(); m_retrying_resolve = true; try { if (!prepare_resolve_unsafe(m_retry_resolve)) return false; activate_unsafe(); return true; } catch (const torrent::input_error& e) { // TODO: Consider adding to error message. return false; } } void CurlGet::trigger_done() { auto guard = lock_guard(); // Not really needed, but just in case. m_retrying_resolve = true; if (m_was_closed) return; ::utils::slot_list_call(m_signal_done); } void CurlGet::trigger_failed(const std::string& message) { auto guard = lock_guard(); m_retrying_resolve = true; if (m_was_closed) return; // If this is changed, verify RESOLVE_NONE handling is correct. ::utils::slot_list_call(m_signal_failed, message); } size_t CurlGet::receive_write(const char* data, size_t size, size_t nmemb, CurlGet* handle) { if (handle->m_stream->write(data, size * nmemb).fail()) return 0; return size * nmemb; } bool CurlGet::prepare_resolve_unsafe(resolve_type current_resolve) { auto [bind_inet_address, bind_inet6_address] = config::network_config()->bind_addresses_or_null(); int detected_family = utils::uri_detect_numeric(m_url); switch (current_resolve) { case RESOLVE_IPV4: if (bind_inet_address == nullptr) throw torrent::input_error("Bind address for requested IP protocol(s) not available."); if (detected_family == AF_INET6) throw torrent::input_error("Numeric IPv6 address in url, but IPv4 was requested."); if (bind_inet_address->sa_family != AF_UNSPEC) curl_easy_setopt(m_handle, CURLOPT_INTERFACE, sa_addr_str(bind_inet_address.get()).c_str()); curl_easy_setopt(m_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); return true; case RESOLVE_IPV6: if (bind_inet6_address == nullptr) throw torrent::input_error("Bind address for requested IP protocol(s) not available."); if (detected_family == AF_INET) throw torrent::input_error("Numeric IPv4 address in url, but IPv6 was requested."); if (bind_inet6_address->sa_family != AF_UNSPEC) curl_easy_setopt(m_handle, CURLOPT_INTERFACE, sa_addr_str(bind_inet6_address.get()).c_str()); curl_easy_setopt(m_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6); return true; case RESOLVE_NONE: return false; default: throw torrent::internal_error("CurlGet::prepare_resolve_unsafe() reached unreachable code with invalid current_resolve."); } } } // namespace torrent::net libtorrent-0.16.11/src/net/address_list.cc0000644000000000000000000000523715175073411014052 #include "config.h" #include "address_list.h" #include #include #include "torrent/net/socket_address.h" namespace torrent { void AddressList::sort() { std::sort(begin(), end(), [](auto& a, auto& b) { return sa_less(&a.sa, &b.sa); }); } void AddressList::sort_and_unique() { sort(); erase(std::unique(begin(), end(), [](auto& a, auto& b) { return sa_equal(&a.sa, &b.sa); }), end()); } void AddressList::parse_address_normal(const Object::list_type& b) { for (const auto& obj : b) { if (!obj.is_map()) continue; if (!obj.has_key_string("ip")) continue; if (!obj.has_key_value("port")) continue; auto& addr = obj.get_key_string("ip"); auto port = obj.get_key_value("port"); if (port <= 0 || port >= (1 << 16)) continue; sa_inet_union sa{}; if (inet_pton(AF_INET, addr.c_str(), &sa.inet.sin_addr)) { if (sa.inet.sin_addr.s_addr == htonl(INADDR_ANY)) continue; sa.inet.sin_family = AF_INET; sa.inet.sin_port = htons(port); } else if (inet_pton(AF_INET6, addr.c_str(), &sa.inet6.sin6_addr)) { if (IN6_IS_ADDR_UNSPECIFIED(&sa.inet6.sin6_addr)) continue; sa.inet6.sin6_family = AF_INET6; sa.inet6.sin6_port = htons(port); } else { continue; } this->push_back(sa); } } void AddressList::parse_address_compact(raw_string s) { if (sizeof(const SocketAddressCompact) != 6) throw internal_error("ConnectionList::AddressList::parse_address_compact(...) bad struct size."); std::copy(reinterpret_cast(s.data()), reinterpret_cast(s.data() + s.size() - s.size() % sizeof(SocketAddressCompact)), std::back_inserter(*this)); } void AddressList::parse_address_compact_ipv6(const std::string& s) { if (sizeof(const SocketAddressCompact6) != 18) throw internal_error("ConnectionList::AddressList::parse_address_compact_ipv6(...) bad struct size."); std::copy(reinterpret_cast(s.c_str()), reinterpret_cast(s.c_str() + s.size() - s.size() % sizeof(SocketAddressCompact6)), std::back_inserter(*this)); } void AddressList::parse_address_bencode(raw_list s) { if (sizeof(const SocketAddressCompact) != 6) throw internal_error("AddressList::parse_address_bencode(...) bad struct size."); for (auto itr = s.begin(); itr + 2 + sizeof(SocketAddressCompact) <= s.end(); itr += sizeof(SocketAddressCompact)) { if (*itr++ != '6' || *itr++ != ':') break; insert(end(), *reinterpret_cast(itr)); } } } // namespace torrent libtorrent-0.16.11/src/net/socket_stream.cc0000644000000000000000000000222115175073411014223 #include "config.h" #include "socket_stream.h" namespace torrent { char* SocketStream::m_nullBuffer = new char[SocketStream::null_buffer_size]; SocketStream::~SocketStream() = default; uint32_t SocketStream::read_stream_throws(void* buf, uint32_t length) { int r = read_stream(buf, length); if (r == 0) throw close_connection(); if (r < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) return 0; else if (errno == ECONNRESET || errno == ECONNABORTED) throw close_connection(); else if (errno == EDEADLK) throw blocked_connection(); else throw connection_error(errno); } return r; } uint32_t SocketStream::write_stream_throws(const void* buf, uint32_t length) { int r = write_stream(buf, length); if (r == 0) throw close_connection(); if (r < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) return 0; else if (errno == ECONNRESET || errno == ECONNABORTED) throw close_connection(); else if (errno == EDEADLK) throw blocked_connection(); else throw connection_error(errno); } return r; } } // namespace torrent libtorrent-0.16.11/src/net/dns_buffer.cc0000644000000000000000000002341715175073411013507 #include "config.h" #include "net/dns_buffer.h" #include #include #include #include "net/dns_cache.h" #include "net/thread_net.h" #include "net/udns_resolver.h" #include "torrent/exceptions.h" #include "torrent/net/socket_address.h" #include "torrent/utils/log.h" #define LT_LOG(log_fmt, ...) \ lt_log_print_subsystem(LOG_NET_DNS, "dns-buffer", log_fmt, __VA_ARGS__); #define LT_LOG_REQUESTER(log_fmt, ...) \ lt_log_print(LOG_NET_DNS, "%016p->dns-buffer : " log_fmt, requester, __VA_ARGS__); namespace torrent::net { DnsBuffer::~DnsBuffer() { // assert(std::this_thread::get_id() == ThreadNet::thread_net()->thread_id()); // if (m_active_query_count != 0) // throw internal_error("DnsBuffer::~DnsBuffer() m_active_query_count != 0"); // if (!m_pending_queries.empty()) // throw internal_error("DnsBuffer::~DnsBuffer() !m_pending_queries.empty()"); { // Lock to ensure cancel_safe() calls are not in progress. auto guard = std::lock_guard(m_requesters_mutex); m_requesters.clear(); } } // Numeric addresses are resolved in torrent/net/resolver, with no use of ThreadNet. void DnsBuffer::resolve(void* requester, const std::string& hostname, int family, resolver_callback&& fn) { assert(std::this_thread::get_id() == ThreadNet::thread_net()->thread_id()); auto initialize_fn = [this, requester, fn = std::move(fn)](bool is_active) mutable { auto guard = std::lock_guard(m_requesters_mutex); auto itr = m_requesters.find(requester); if (itr == m_requesters.end()) itr = m_requesters.emplace(requester, std::make_shared()).first; // TODO: Add sanity check for count during development. if (is_active) itr->second->active_query_count++; else itr->second->pending_query_count++; return DnsBufferCallback{itr->second, std::move(fn)}; }; // Check for existing active or pending query: if (m_active_query_count != 0) { for (auto& query : m_active_queries) { if (query.family == family && query.hostname == hostname) { query.callbacks.push_back(initialize_fn(true)); LT_LOG_REQUESTER("added to active query : name:%s family:%d", hostname.c_str(), family); return; } } for (auto& query : m_pending_queries) { if (query.family == family && query.hostname == hostname) { query.callbacks.push_back(initialize_fn(false)); LT_LOG_REQUESTER("added to pending query : name:%s family:%d", hostname.c_str(), family); return; } } } // No existing query, create a new one: if (m_active_query_count < max_requests) { LT_LOG_REQUESTER("added new active query : name:%s family:%d", hostname.c_str(), family); activate_and_resolve_query(DnsBufferQuery{family, hostname, {initialize_fn(true)}}); return; } LT_LOG_REQUESTER("added new pending query : name:%s family:%d", hostname.c_str(), family); m_pending_queries.insert(m_pending_queries.end(), DnsBufferQuery{family, hostname, {initialize_fn(false)}}); } // TODO: We're not flushing old m_requesters. (do we make calling cancel_safe() required for all requesters?) void DnsBuffer::cancel_safe(void* requester) { if (requester == nullptr) throw internal_error("DnsBuffer::cancel() called with null requester"); { auto guard = std::lock_guard(m_requesters_mutex); auto itr = m_requesters.find(requester); if (itr == m_requesters.end()) return; m_requesters.erase(itr); } LT_LOG_REQUESTER("canceled", 0); } void DnsBuffer::activate_pending_query() { while (!m_pending_queries.empty()) { if (m_active_query_count >= max_requests) throw internal_error("DnsBuffer::activate_pending_query() m_active_query_count >= max_requests"); auto query = std::move(m_pending_queries.front()); m_pending_queries.pop_front(); auto erase_itr = std::remove_if(query.callbacks.begin(), query.callbacks.end(), [](const auto& callback) { auto ptr = callback.requester.lock(); auto requester = ptr.get(); if (requester == nullptr) return true; if (requester->pending_query_count == 0) throw internal_error("DnsBuffer::activate_pending_query() requester pending_query_count is already 0"); requester->pending_query_count--; requester->active_query_count++; LT_LOG_REQUESTER("moved from pending to active query", 0); return false; }); query.callbacks.erase(erase_itr, query.callbacks.end()); if (query.callbacks.empty()) { LT_LOG("skipping pending query with no callbacks : name:%s family:%d", query.hostname.c_str(), query.family); continue; } activate_and_resolve_query(std::move(query)); return; } } void DnsBuffer::activate_and_resolve_query(DnsBufferQuery query) { assert(std::this_thread::get_id() == ThreadNet::thread_net()->thread_id()); if (m_active_query_count >= max_requests) throw internal_error("DnsBuffer::activate_query() m_active_query_count >= max_requests"); if (query.callbacks.empty()) throw internal_error("DnsBuffer::activate_query() called with empty callbacks"); auto itr = std::find_if(m_active_queries.begin(), m_active_queries.end(), [](const auto& query) { return query.family == -1; }); if (itr == m_active_queries.end()) throw internal_error("DnsBuffer::activate_query() itr == m_active_queries.end()"); *itr = std::move(query); m_active_query_count++; auto index = std::distance(m_active_queries.begin(), itr); auto fn = [this, index](sin_shared_ptr result_sin, int error_sin, sin6_shared_ptr result_sin6, int error_sin6) { this_thread::callback(this->requester_from_index(index), [=]() { this->process(index, std::move(result_sin), error_sin, std::move(result_sin6), error_sin6); }); }; // LT_LOG("activating query : requesters:%zu name:%s family:%d index:%u", // itr->callbacks.size(), itr->hostname.c_str(), itr->family, index); ThreadNet::thread_net()->dns_resolver()->resolve(requester_from_index(index), itr->hostname, itr->family, std::move(fn)); } void DnsBuffer::process(unsigned int index, sin_shared_ptr result_sin, int error_sin, sin6_shared_ptr result_sin6, int error_sin6) { assert(std::this_thread::get_id() == ThreadNet::thread_net()->thread_id()); if (index >= max_requests) throw internal_error("DnsBuffer::process() index out of bounds"); auto query = std::move(m_active_queries[index]); m_active_queries[index] = DnsBufferQuery{}; m_active_query_count--; if (query.family != AF_UNSPEC && query.family != AF_INET && query.family != AF_INET6) throw internal_error("DnsBuffer::process() query.family is invalid"); if (result_sin && error_sin != 0) throw internal_error("DnsBuffer::process() query has both result and error for A record"); if (result_sin6 && error_sin6 != 0) throw internal_error("DnsBuffer::process() query has both result and error for AAAA record"); if (query.family == AF_UNSPEC) { if (result_sin == nullptr && result_sin6 == nullptr && (error_sin == 0 || error_sin6 == 0)) throw internal_error("DnsBuffer::process() query has no result and no error for AF_UNSPEC"); } else if (query.family == AF_INET) { if (result_sin == nullptr && error_sin == 0) throw internal_error("DnsBuffer::process() query has no result and no error for AF_INET"); if (result_sin6 != nullptr || error_sin6 != 0) throw internal_error("DnsBuffer::process() query has result or error for AF_INET6 when family is AF_INET"); } else if (query.family == AF_INET6) { if (result_sin6 == nullptr && error_sin6 == 0) throw internal_error("DnsBuffer::process() query has no result and no error for AF_INET6"); if (result_sin != nullptr || error_sin != 0) throw internal_error("DnsBuffer::process() query has result or error for AF_INET when family is AF_INET6"); } if (result_sin) ThreadNet::thread_net()->dns_cache()->process_success(query.hostname, AF_INET, result_sin, nullptr); else if (error_sin != 0) ThreadNet::thread_net()->dns_cache()->process_failure(query.hostname, AF_INET, error_sin); if (result_sin6) ThreadNet::thread_net()->dns_cache()->process_success(query.hostname, AF_INET6, nullptr, result_sin6); else if (error_sin6 != 0) ThreadNet::thread_net()->dns_cache()->process_failure(query.hostname, AF_INET6, error_sin6); for (auto& callback : query.callbacks) process_callback(callback, result_sin, error_sin, result_sin6, error_sin6); activate_pending_query(); } void DnsBuffer::process_callback(DnsBufferCallback& callback, sin_shared_ptr result_sin, int error_sin, sin6_shared_ptr result_sin6, int error_sin6) { auto requester_ptr = callback.requester.lock(); auto requester = requester_ptr.get(); if (requester == nullptr) return; if (requester->active_query_count == 0) throw internal_error("DnsBuffer::process() requester active_query_count is already 0"); requester->active_query_count--; LT_LOG_REQUESTER("processing callback : inet:%s inet6:%s", (error_sin == 0) ? sin_pretty_or_empty(result_sin.get()).c_str() : gai_enum_error(error_sin), (error_sin6 == 0) ? sin6_pretty_or_empty(result_sin6.get()).c_str() : gai_enum_error(error_sin6)); { // Block cancel() until this is done to ensure callbacks for the requester are all canceled. auto guard = std::lock_guard(m_requesters_mutex); if (requester_ptr.use_count() > 1) callback.callback(result_sin, error_sin, result_sin6, error_sin6); } } void* DnsBuffer::requester_from_index(unsigned int index) { if (index >= max_requests) throw internal_error("DnsBuffer::requester_from_index() index out of bounds"); return m_active_queries.data() + index; } } // namespace torrent::net libtorrent-0.16.11/src/net/data_buffer.h0000644000000000000000000000606515175073411013476 // libTorrent - BitTorrent library // Copyright (C) 2005-2011, Jari Sundell // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // In addition, as a special exception, the copyright holders give // permission to link the code of portions of this program with the // OpenSSL library under certain conditions as described in each // individual source file, and distribute linked combinations // including the two. // // You must obey the GNU General Public License in all respects for // all of the code used other than OpenSSL. If you modify file(s) // with this exception, you may extend this exception to your version // of the file(s), but you are not obligated to do so. If you do not // wish to do so, delete this exception statement from your version. // If you delete this exception statement from all source files in the // program, then also delete it here. // // Contact: Jari Sundell // // Skomakerveien 33 // 3185 Skoppum, NORWAY #ifndef LIBTORRENT_NET_DATA_BUFFER_H #define LIBTORRENT_NET_DATA_BUFFER_H #include #include namespace torrent { // Recipient must call clear() when done with the buffer. struct DataBuffer { DataBuffer() = default; DataBuffer(char* data, char* end) : m_data(data), m_end(end) {} DataBuffer clone() const { DataBuffer d = *this; d.m_owned = false; return d; } DataBuffer release() { DataBuffer d = *this; set(NULL, NULL, false); return d; } char* data() const { return m_data; } char* end() const { return m_end; } bool owned() const { return m_owned; } bool empty() const { return m_data == NULL; } size_t length() const { return m_end - m_data; } void clear(); void set(char* data, char* end, bool owned); private: char* m_data{}; char* m_end{}; // Used to indicate if buffer held by PCB is its own and needs to be // deleted after transmission (false if shared with other connections). bool m_owned{true}; }; inline void DataBuffer::clear() { if (!empty() && m_owned) delete[] m_data; m_data = m_end = NULL; m_owned = false; } inline void DataBuffer::set(char* data, char* end, bool owned) { m_data = data; m_end = end; m_owned = owned; } } // namespace torrent #endif libtorrent-0.16.11/src/net/curl_socket.cc0000644000000000000000000004530615175073411013710 #include "config.h" #include "curl_socket.h" #include #include #include #include "net/curl_stack.h" #include "torrent/exceptions.h" #include "torrent/net/poll.h" #include "torrent/net/socket_address.h" #include "torrent/runtime/socket_manager.h" #include "torrent/utils/log.h" #if 0 #define LT_LOG_DEBUG(log_fmt, ...) #define LT_LOG_DEBUG_THIS(log_fmt, ...) #define LT_LOG_DEBUG_SOCKET(log_fmt, ...) #define LT_LOG_DEBUG_SOCKET_FD(log_fmt, ...) #define LT_LOG_DEBUG_SOCKET_FD_HANDLE(log_fmt, ...) #else #define LT_LOG_DEBUG(log_fmt, ...) \ lt_log_print(LOG_CONNECTION_FD, "curl_socket: " log_fmt, __VA_ARGS__) #define LT_LOG_DEBUG_THIS(log_fmt, ...) \ lt_log_print(LOG_CONNECTION_FD, "curl_socket->%p(%i): " log_fmt, this, this->m_fileDesc, __VA_ARGS__) #define LT_LOG_DEBUG_SOCKET(log_fmt, ...) \ lt_log_print(LOG_CONNECTION_FD, "curl_socket->%p(%i): " log_fmt, socket, socket != nullptr ? socket->m_fileDesc : 0, __VA_ARGS__) #define LT_LOG_DEBUG_SOCKET_FD(log_fmt, ...) \ lt_log_print(LOG_CONNECTION_FD, "curl_socket->%p(%i): fd:%i : " log_fmt, socket, socket != nullptr ? socket->m_fileDesc : 0, fd, __VA_ARGS__) #define LT_LOG_DEBUG_SOCKET_FD_HANDLE(log_fmt, ...) \ lt_log_print(LOG_CONNECTION_FD, "curl_socket->%p(%i): fd:%i easy_handle:%p : " log_fmt, socket, socket != nullptr ? socket->m_fileDesc : 0, fd, easy_handle, __VA_ARGS__) #endif // Use getsockopt(SO_TYPE), SOCK_STREAM, and getpeername() / getsockname() to verify the socket is // the same as when marking inactive. namespace torrent::net { CurlSocket::CurlSocket(int fd, CurlStack* stack, CURL* easy_handle) : m_stack(stack), m_easy_handle(easy_handle) { set_file_descriptor(fd); } CurlSocket::CurlSocket(CurlStack* stack) : m_stack(stack) { } CurlSocket::~CurlSocket() { assert(!is_open() && "CurlSocket::~CurlSocket() !is_open()"); m_self_exists = false; } int CurlSocket::receive_socket(CURL* easy_handle, curl_socket_t fd, int what, CurlStack* stack, CurlSocket* socket) { assert(this_thread::thread() == stack->thread()); // We always return 0, even when stack is not running, as we depend on these calls to delete // sockets. if (socket != nullptr) { if (!socket->m_self_exists) { LT_LOG_DEBUG_SOCKET_FD_HANDLE("receive_socket() : called on deleted CurlSocket, aborting", 0); throw internal_error("CurlSocket::receive_socket(fd:" + std::to_string(fd) + ") called on deleted CurlSocket"); } } if (what == CURL_POLL_REMOVE) { // When libcurl closes a socket in the idle connection poll, it calls receive_socket() with a // null socket. if (socket == nullptr) { // Assume libcurl calls this before closing the fd if it is in the idle connection pool. LT_LOG_DEBUG_SOCKET_FD_HANDLE("receive_socket(CURL_POLL_REMOVE) : null socket", 0); return 0; } if (!socket->is_open() || !socket->is_polling()) { LT_LOG_DEBUG_SOCKET_FD_HANDLE("receive_socket(CURL_POLL_REMOVE) : socket already closed, aborting", 0); throw internal_error("CurlSocket::receive_socket(fd:" + std::to_string(fd) + ") CURL_POLL_REMOVE called on closed socket"); } if (socket->m_fileDesc != fd) throw internal_error("CurlSocket::receive_socket(fd:" + std::to_string(fd) + ") CURL_POLL_REMOVE fd mismatch"); if (!socket->m_properly_opened) { // This is likely a socketpair created by libcurl directly, so we assume libcurl also handles // closing it. LT_LOG_DEBUG_SOCKET_FD_HANDLE("receive_socket(CURL_POLL_REMOVE) : socket never properly opened, removing from poll", 0); runtime::socket_manager()->unregister_event_or_throw(socket, [&]() { this_thread::poll()->remove_and_close(socket); }); socket->clear_and_erase_self_or_throw(); return 0; } LT_LOG_DEBUG_SOCKET_FD_HANDLE("receive_socket(CURL_POLL_REMOVE) : removing from read/write polling", 0); // TODO: Check m_uninterested flag? auto func = [socket]() { this_thread::poll()->remove_read(socket); this_thread::poll()->remove_write(socket); socket->m_easy_handle = nullptr; socket->m_uninterested = true; }; auto on_reuse = [socket]() { this_thread::poll()->remove_and_close(socket); socket->clear_and_erase_self_or_throw(); }; if (!runtime::socket_manager()->mark_stream_event_inactive(socket, func, on_reuse)) { // Socket was closed by the kernel, or reused. LT_LOG_DEBUG_SOCKET_FD_HANDLE("receive_socket(CURL_POLL_REMOVE) : socket was not connected, returning error", 0); return -1; } return 0; } if (socket == nullptr) { if (!stack->is_running()) return 0; auto itr = stack->socket_map()->find(fd); if (itr == stack->socket_map()->end()) { socket = new CurlSocket(fd, stack, easy_handle); socket->m_properly_opened = false; LT_LOG_DEBUG_SOCKET_FD_HANDLE("receive_socket() : unexpected fd encountered, creating new (not properly opened) CurlSocket", 0); runtime::socket_manager()->register_event_or_throw(socket, [&]() { this_thread::poll()->open(socket); this_thread::poll()->insert_error(socket); }); stack->socket_map()->emplace(fd, std::unique_ptr(socket)); curl_multi_assign(stack->handle(), fd, socket); } else { // LibCurl is reusing the fd for a new connection, and as such passed us null socketp. if (itr->second->m_easy_handle != nullptr) { LT_LOG_DEBUG_SOCKET_FD_HANDLE("receive_socket() : existing CurlSocket easy_handle not null, aborting", 0); throw internal_error("CurlSocket::receive_socket(fd:" + std::to_string(fd) + ") existing CurlSocket easy_handle not null"); } socket = itr->second.get(); socket->m_easy_handle = easy_handle; curl_multi_assign(stack->handle(), fd, socket); if (!socket->update_and_verify_socket_address()) { LT_LOG_DEBUG_SOCKET_FD_HANDLE("receive_socket() : existing socket address mismatch, aborting", 0); throw internal_error("CurlSocket::receive_socket(fd:" + std::to_string(fd) + "): existing socket address mismatch"); } if (!socket->update_and_verify_peer_address()) { LT_LOG_DEBUG_SOCKET_FD_HANDLE("receive_socket() : existing peer address mismatch, aborting", 0); throw internal_error("CurlSocket::receive_socket(fd:" + std::to_string(fd) + "): existing peer address mismatch"); } LT_LOG_DEBUG_SOCKET_FD_HANDLE("receive_socket() : existing socket found in map : socket:%s peer:%s", sa_pretty_str(socket->socket_address()).c_str(), sa_pretty_str(socket->peer_address()).c_str()); } } if (!stack->is_running()) { LT_LOG_DEBUG_SOCKET_FD_HANDLE("receive_socket() : CurlStack not running, aborting", 0); throw internal_error("CurlSocket::receive_socket(fd:" + std::to_string(fd) + ") called while CurlStack is not running"); } if (what != CURL_POLL_NONE && socket->m_uninterested) { // TODO: Do this in a func protected by SocketManager lock? if (!runtime::socket_manager()->mark_event_active_or_fail(socket)) { LT_LOG_DEBUG_SOCKET_FD_HANDLE("receive_socket() : socket fd was reused, aborting", 0); // TODO: This can cause libcurl to call close_socket() on a reused fd? // TODO: Need to check proper opened and remove from poll? // TODO: This fd has been reused, no need to do anything else. socket->clear_and_erase_self_or_throw(); return -1; } socket->m_uninterested = false; LT_LOG_DEBUG_SOCKET_FD_HANDLE("receive_socket() : marking socket as interested", 0); } // TODO: If this is a 'properly opened' socket, update and verify addresses. // TODO: This should be done other places also. // TODO: Should we also always check SocketManager? if (what == CURL_POLL_NONE) { // Handle uninterested sockets before checking addresses, as the server tends to close // connections right after completing requests. (which invalidates the peer name) LT_LOG_DEBUG_SOCKET_FD_HANDLE("receive_socket(CURL_POLL_NONE) : removing read and write", 0); socket->m_uninterested = true; auto func = [socket]() { this_thread::poll()->remove_read(socket); this_thread::poll()->remove_write(socket); }; auto on_reuse = [socket]() { this_thread::poll()->remove_and_close(socket); socket->clear_and_erase_self_or_throw(); }; if (!runtime::socket_manager()->mark_stream_event_inactive(socket, func, on_reuse)) { // Not connected... // throw internal_error("CurlSocket::receive_socket(fd:" + std::to_string(fd) + ") CURL_POLL_NONE: socket was not connected"); LT_LOG_DEBUG_SOCKET_FD_HANDLE("receive_socket(CURL_POLL_NONE) : socket was not connected, returning error", 0); return -1; } return 0; } if (socket->m_properly_opened) { if (!socket->update_and_verify_socket_address()) { LT_LOG_DEBUG_SOCKET_FD_HANDLE("receive_socket() : socket address mismatch on properly opened socket, returning error", 0); return -1; } if (!socket->update_and_verify_peer_address()) { LT_LOG_DEBUG_SOCKET_FD_HANDLE("receive_socket() : peer address mismatch on properly opened socket, returning error", 0); return -1; } } switch (what) { case CURL_POLL_IN: LT_LOG_DEBUG_SOCKET_FD_HANDLE("receive_socket(CURL_POLL_IN) : inserting read, removing write", 0); this_thread::poll()->insert_read(socket); this_thread::poll()->remove_write(socket); break; case CURL_POLL_OUT: LT_LOG_DEBUG_SOCKET_FD_HANDLE("receive_socket(CURL_POLL_OUT) : inserting write, removing read", 0); this_thread::poll()->insert_write(socket); this_thread::poll()->remove_read(socket); break; case CURL_POLL_INOUT: LT_LOG_DEBUG_SOCKET_FD_HANDLE("receive_socket(CURL_POLL_INOUT) : inserting read and write", 0); this_thread::poll()->insert_read(socket); this_thread::poll()->insert_write(socket); break; default: LT_LOG_DEBUG_SOCKET_FD_HANDLE("receive_socket() : unknown what value: %i, aborting", 0); throw internal_error("CurlSocket::receive_socket(fd:" + std::to_string(fd) + "): unknown what value: " + std::to_string(what)); } return 0; } // This is not called when libcurl creates socketpairs, yet it expects us to handle them in receive_socket(). curl_socket_t CurlSocket::open_socket(CurlStack *stack, [[maybe_unused]] curlsocktype purpose, struct curl_sockaddr *address) { assert(this_thread::thread() == stack->thread()); if (!stack->is_running()) { LT_LOG_DEBUG("open_socket() : curl stack not running, aborting", 0); return CURL_SOCKET_BAD; } auto event = std::make_unique(stack); event->m_properly_opened = true; auto open_func = [&]() { int fd = ::socket(address->family, address->socktype, address->protocol); if (fd == -1) { LT_LOG_DEBUG("open_socket() : error creating socket: %s", std::strerror(errno)); return -1; } // TODO: Fail if fd is already in use, especially if it is m_properly_opened. event->set_file_descriptor(fd); // TODO: We should add this to uninterested sockets until libcurl tells us to poll. this_thread::poll()->open(event.get()); this_thread::poll()->insert_error(event.get()); return fd; }; auto cleanup_func = [&]() { if (!event->is_open()) return; this_thread::poll()->remove_and_close(event.get()); if (::close(event->file_descriptor()) == -1) { LT_LOG_DEBUG("open_socket() : error closing socket during cleanup: %s", std::strerror(errno)); throw internal_error("CurlSocket::open_socket(): error closing socket during cleanup: " + std::string(std::strerror(errno))); } LT_LOG_DEBUG("open_socket() : socket manager requested cleanup: fd:%i", event->file_descriptor()); event->set_file_descriptor(-1); }; bool result = runtime::socket_manager()->open_event_or_cleanup(event.get(), open_func, cleanup_func); if (!result) { LT_LOG_DEBUG("open_socket() : error creating socket: %s", std::strerror(errno)); return CURL_SOCKET_BAD; } // Add to stack map if not already present. auto fd = event->file_descriptor(); auto itr = stack->socket_map()->find(fd); if (itr != stack->socket_map()->end()) { LT_LOG_DEBUG("open_socket() : fd:%i : socket already exists in stack", fd); // Shouldn't happen, but close the new socket and return the existing one. // runtime::socket_manager()->close_event(event.get()); // return itr->second->file_descriptor(); throw internal_error("CurlSocket::open_socket() : fd:%i : socket already exists in stack"); } LT_LOG_DEBUG("open_socket() : socket opened: fd:%i", fd); stack->socket_map()->emplace(fd, std::move(event)); return fd; } // When receive_socket() is called with CURL_POLL_REMOVE, we call CurlSocket::close() which // deregisters this callback. int CurlSocket::close_socket(CurlStack* stack, curl_socket_t fd) { assert(this_thread::thread() == stack->thread()); auto itr = stack->socket_map()->find(fd); // Socket won't exist if the only thing it called was receive_socket(CURL_POLL_REMOVE). // // LibCurl is randomly closing / not closing sockets that receive errors, so we need to handle it // in a graceful way. (Which isn't really strictly correct) if (itr == stack->socket_map()->end()) { // TODO: This needs to be changed to keep track of properly opened sockets. (it tries to close fd:0!!!) // bool result = runtime::socket_manager()->execute_if_not_present(fd, [&]() { // // TODO: This can cause issues if the fd was by something that doesn't register with SocketManager. // // TODO: Rewrite this to check fd's socket/peer address to verify it is the same socket. // // // // This requires not erasing properly opened CurlSockets on error, etc? // ::close(fd); // }); // replace with execute_if_matches // if (result) { // LT_LOG_DEBUG("close_socket() : fd:%i : socket not found in stack : closed directly", 0); // } else { // LT_LOG_DEBUG("close_socket() : fd:%i : socket not found in stack, but is in socket manager : assuming reuse", 0); // } LT_LOG_DEBUG("close_socket() : fd:%i : socket not found in stack, skipping", 0); throw internal_error("CurlSocket::close_socket(fd:" + std::to_string(fd) + "): socket not found in stack"); // return 0; } auto* socket = itr->second.get(); LT_LOG_DEBUG_SOCKET("close_socket()", 0); if (!socket->is_polling()) throw internal_error("CurlSocket::close_socket(fd:" + std::to_string(fd) + "): socket not in poll"); if (fd != socket->file_descriptor()) throw internal_error("CurlSocket::close_socket(): fd mismatch : curl:" + std::to_string(fd) + " self:" + std::to_string(socket->file_descriptor())); curl_multi_assign(stack->handle(), fd, nullptr); // TODO: Check if this is still the same socket? runtime::socket_manager()->close_event_or_throw(socket, [&]() { // TODO: Change handling of curl remove event / uninterested to closing socket polling? // TODO: This is getting called twice? this_thread::poll()->remove_and_close(socket); if (::close(fd) == -1) { LT_LOG_DEBUG_SOCKET_FD("close_socket() : error closing socket: %s", std::strerror(errno)); } socket->set_file_descriptor(-1); }); socket->clear_and_erase_self(itr); return 0; } void CurlSocket::event_read() { // TODO: Use MSG_PEEK to check if we're in idle connection poll and close this fd. handle_action(CURL_CSELECT_IN); } void CurlSocket::event_write() { handle_action(CURL_CSELECT_OUT); } // TODO: We need to figure out how to tell libcurl to not close an fd when it has been reused. // // Perhaps we just pretend it is open while in idle conection poll, and pretend to add it to read // just to get the CLOSEFUNCTION callback? // // Also, verify if reporting errors to libcurl actually closes the fd, doesn't seem like it should? // // Think it should be calling the callback. void CurlSocket::event_error() { LT_LOG_DEBUG_THIS("event_error()", 0); // LibCurl will close the socket, so remove it from polling prior to passing the error event. // if (m_properly_opened) { // LT_LOG_DEBUG_THIS("event_error() : properly opened socket, removing from socket manager", 0); // runtime::socket_manager()->close_event_or_throw(this, [this]() { // this_thread::poll()->remove_and_close(this); // // clear and erase self. // }); if (!m_properly_opened) { auto fd = file_descriptor(); auto stack = m_stack; runtime::socket_manager()->unregister_event_or_throw(this, [&]() { this_thread::poll()->remove_and_close(this); }); curl_multi_assign(m_stack->handle(), file_descriptor(), nullptr); clear_and_erase_self_or_throw(); CurlSocket::handle_action_simple(stack, fd, CURL_CSELECT_ERR); return; } throw internal_error("CurlSocket::event_error() : properly opened socket should not implement"); curl_multi_assign(m_stack->handle(), file_descriptor(), nullptr); handle_action(CURL_CSELECT_ERR); if (!m_self_exists) { LT_LOG_DEBUG_THIS("event_error() : self deleted during handle_action, aborting", 0); throw internal_error("CurlSocket::event_error() self deleted during handle_action."); } clear_and_erase_self_or_throw(); } void CurlSocket::handle_action(int ev_bitmask) { assert(is_open() && "CurlSocket::handle_action() is_open()"); assert(m_stack != nullptr && "CurlSocket::handle_action() m_stack != nullptr"); // Processing might deallocate this CurlSocket. auto stack = m_stack; CurlSocket::handle_action_simple(stack, file_descriptor(), ev_bitmask); // // TODO: Use Thread::call_events() to process this: ? // while (stack->process_done_handle()) ; // Do nothing. } void CurlSocket::handle_action_simple(CurlStack* stack, int fd, int ev_bitmask) { int count{}; auto code = curl_multi_socket_action(stack->handle(), fd, ev_bitmask, &count); if (code != CURLM_OK) throw internal_error("CurlSocket::handle_action_simple(...) error calling curl_multi_socket_action: " + std::string(curl_multi_strerror(code))); } void CurlSocket::clear_and_erase_self(CurlStack::socket_map_type::iterator itr) { auto socket_map = m_stack->socket_map(); m_fileDesc = -1; m_stack = nullptr; m_easy_handle = nullptr; socket_map->erase(itr); } void CurlSocket::clear_and_erase_self_or_throw() { auto socket_map = m_stack->socket_map(); auto itr = socket_map->find(m_fileDesc); if (itr == socket_map->end()) throw internal_error("CurlSocket::clear_and_erase_self_or_throw(): socket not found in stack map"); clear_and_erase_self(itr); } } // namespace torrent::net libtorrent-0.16.11/src/net/dns_buffer.h0000644000000000000000000000473315175073411013351 #ifndef LIBTORRENT_NET_DNS_BUFFER_H #define LIBTORRENT_NET_DNS_BUFFER_H // TODO: Review headers #include #include #include #include #include #include #include #include #include "torrent/net/types.h" namespace torrent::net { // It is assume that 'requester' does very few simultaneous requests, so searching for pending // queries is not too expensive. struct DnsBufferRequester; struct DnsBufferCallback { std::weak_ptr requester; resolver_callback callback; }; struct DnsBufferQuery { // Family set to '-1' indicates an empty query. int family{-1}; std::string hostname; std::vector callbacks; }; // TODO: Add sanity checks using resolve_unique() and resolve_multi() which checks to make sure we // don't get duplicate requests. struct DnsBufferRequester { unsigned int active_query_count{}; unsigned int pending_query_count{}; }; class DnsBuffer { public: constexpr static int max_requests = 8; ~DnsBuffer(); // The 'fn' callback must do work in the originating thread using callbacks with 'requester'. void resolve(void* requester, const std::string& hostname, int family, resolver_callback&& fn); // Calling thread must cancel callbacks with 'requester' afterwards. void cancel_safe(void* requester); // TODO: Add a slot for completed queries so we can add the entry to the cache before calling the // list of callbacks. private: using active_query_list = std::array; using requester_list = std::map>; void activate_pending_query(); void activate_and_resolve_query(DnsBufferQuery query); void process(unsigned int index, sin_shared_ptr result_sin, int error_sin, sin6_shared_ptr result_sin6, int error_sin6); void process_callback(DnsBufferCallback& callback, sin_shared_ptr result_sin, int error_sin, sin6_shared_ptr result_sin6, int error_sin6); void* requester_from_index(unsigned int index); unsigned int m_active_query_count{}; active_query_list m_active_queries; std::list m_pending_queries; std::mutex m_requesters_mutex; requester_list m_requesters; }; } // namespace torrent::net #endif // LIBTORRENT_NET_DNS_BUFFER_H libtorrent-0.16.11/src/net/throttle_node.h0000644000000000000000000000300115175073411014071 #ifndef LIBTORRENT_NET_THROTTLE_NODE_H #define LIBTORRENT_NET_THROTTLE_NODE_H #include #include "torrent/rate.h" #include "throttle_list.h" namespace torrent { class ThrottleNode { public: using iterator = ThrottleList::iterator; using const_iterator = ThrottleList::const_iterator; using slot_void = std::function; ThrottleNode(uint32_t rateSpan) : m_rate(rateSpan) { clear_quota(); } ~ThrottleNode() = default; Rate* rate() { return &m_rate; } const Rate* rate() const { return &m_rate; } uint32_t quota() const { return m_quota; } void clear_quota() { m_quota = 0; } void set_quota(uint32_t q) { m_quota = q; } iterator list_iterator() { return m_listIterator; } const_iterator list_iterator() const { return m_listIterator; } void set_list_iterator(iterator itr) { m_listIterator = itr; } void activate() { if (m_slot_activate) m_slot_activate(); } slot_void& slot_activate() { return m_slot_activate; } private: ThrottleNode(const ThrottleNode&) = delete; ThrottleNode& operator=(const ThrottleNode&) = delete; uint32_t m_quota; iterator m_listIterator; Rate m_rate; slot_void m_slot_activate; }; } // namespace torrent #endif libtorrent-0.16.11/src/net/curl_socket.h0000644000000000000000000000314215175073411013542 #ifndef LIBTORRENT_NET_CURL_SOCKET_H #define LIBTORRENT_NET_CURL_SOCKET_H #include #include "net/curl_stack.h" #include "torrent/event.h" namespace torrent::net { class CurlGet; class CurlSocket : public torrent::Event { public: // TODO: Deprecate. CurlSocket(int fd, CurlStack* stack, CURL* easy_handle); CurlSocket(CurlStack* stack); ~CurlSocket() override; const char* type_name() const override { return "curl_socket"; } void event_read() override; void event_write() override; void event_error() override; protected: friend class CurlGet; friend class CurlStack; static int receive_socket(CURL* easy_handle, curl_socket_t fd, int what, CurlStack* userp, CurlSocket* socketp); static curl_socket_t open_socket(CurlStack *stack, curlsocktype purpose, struct curl_sockaddr *address); static int close_socket(CurlStack* stack, curl_socket_t fd); private: CurlSocket(const CurlSocket&) = delete; CurlSocket& operator=(const CurlSocket&) = delete; void handle_action(int ev_bitmask); static void handle_action_simple(CurlStack* stack, int fd, int ev_bitmask); void clear_and_erase_self(CurlStack::socket_map_type::iterator itr); void clear_and_erase_self_or_throw(); CurlStack* m_stack{}; CURL* m_easy_handle{}; bool m_self_exists{true}; bool m_properly_opened{false}; bool m_uninterested{}; }; } // namespace torrent::net #endif // LIBTORRENT_NET_CURL_SOCKET_H libtorrent-0.16.11/src/net/listen.h0000644000000000000000000000254715175073411012533 #ifndef LIBTORRENT_LISTEN_H #define LIBTORRENT_LISTEN_H #include #include #include #include "torrent/event.h" namespace torrent { class Listen : public Event { public: ~Listen() override { close(); } const char* type_name() const override { return "listen"; } static bool open_single(Listen* listen, const sockaddr* bind_address, uint16_t first, uint16_t last, int backlog, bool block_ipv4in6); static bool open_both(Listen* listen_inet, Listen* listen_inet6, const sockaddr* bind_inet_address, const sockaddr* bind_inet6_address, uint16_t first, uint16_t last, int backlog, bool block_ipv4in6); void close(); uint16_t port() const { return m_port; } auto& slot_accepted() { return m_slot_accepted; } void event_read() override; void event_write() override; void event_error() override; private: using slot_accept_type = std::function& handshake, int, const sockaddr*)>; void open_done(int fd, uint16_t port, int backlog); uint16_t m_port{0}; slot_accept_type m_slot_accepted; }; } // namespace torrent #endif // LIBTORRENT_TORRENT_H libtorrent-0.16.11/src/net/listen.cc0000644000000000000000000002061015175073411012660 #include "config.h" #include "listen.h" #include "manager.h" #include "protocol/handshake.h" #include "torrent/connection_manager.h" #include "torrent/exceptions.h" #include "torrent/net/fd.h" #include "torrent/net/poll.h" #include "torrent/net/socket_address.h" #include "torrent/runtime/network_manager.h" #include "torrent/runtime/socket_manager.h" #include "torrent/utils/log.h" #define LT_LOG(log_fmt, ...) \ lt_log_print(torrent::LOG_CONNECTION_LISTEN, "listen: " log_fmt, __VA_ARGS__); namespace torrent { namespace { std::tuple listen_fd_open(const sockaddr* bind_address) { fd_flags open_flags = fd_flag_nonblock | fd_flag_reuse_address; if (bind_address->sa_family == AF_INET) open_flags |= fd_flag_v4only; int stream_fd = fd_open(fd_flag_stream | open_flags); if (stream_fd == -1) throw resource_error("Could not open stream socket for listening: " + std::string(strerror(errno))); int datagram_fd = fd_open(fd_flag_datagram | open_flags); if (datagram_fd == -1) { fd_close(stream_fd); throw resource_error("Could not open datagram socket for listening: " + std::string(strerror(errno))); } return std::make_tuple(stream_fd, datagram_fd); } std::tuple listen_open_range(uint16_t first, uint16_t last, const sockaddr* bind_address) { sa_unique_ptr try_address = sa_copy(bind_address); auto [stream_fd, datagram_fd] = listen_fd_open(bind_address); do { sa_set_port(try_address.get(), first); if (!fd_bind(stream_fd, try_address.get())) continue; // Try to bind the datagram socket to the same port to verify DHT availability. if (!fd_bind(datagram_fd, try_address.get())) { LT_LOG("failed to bind datagram socket on port %" PRIu16 " to verify DHT availability : %s", first, std::strerror(errno)); fd_close(stream_fd); fd_close(datagram_fd); std::tie(stream_fd, datagram_fd) = listen_fd_open(bind_address); continue; } fd_close(datagram_fd); return std::make_tuple(stream_fd, first); } while (first++ < last); fd_close(stream_fd); fd_close(datagram_fd); return std::make_tuple(-1, 0); } } bool Listen::open_single(Listen* listen, const sockaddr* bind_address, uint16_t first, uint16_t last, int backlog, bool block_ipv4in6) { listen->close(); if (first == 0 || first > last) throw input_error("Tried to open listening port with an invalid range"); if (bind_address->sa_family != AF_INET && bind_address->sa_family != AF_INET6) throw input_error("Listening socket must be inet or inet6 address type"); auto [listen_fd, listen_port] = listen_open_range(first, last, bind_address); if (listen_fd == -1) { LT_LOG("failed to find a suitable listen port : last error : %s", std::strerror(errno)); return false; } if (block_ipv4in6 && bind_address->sa_family == AF_INET6 && !fd_set_v6only(listen_fd, true)) { fd_close(listen_fd); LT_LOG("failed to set IPV6_V6ONLY on socket : %s", std::strerror(errno)); throw resource_error("Could not set IPV6_V6ONLY on socket: " + std::string(strerror(errno))); } if (!fd_listen(listen_fd, backlog)) { fd_close(listen_fd); LT_LOG("failed to listen on socket : %s", std::strerror(errno)); throw resource_error("Could not listen on socket: " + std::string(strerror(errno))); } listen->open_done(listen_fd, listen_port, backlog); return true; } bool Listen::open_both(Listen* listen_inet, Listen* listen_inet6, const sockaddr* bind_inet_address, const sockaddr* bind_inet6_address, uint16_t first, uint16_t last, int backlog, bool block_ipv4in6) { listen_inet->close(); listen_inet6->close(); if (first == 0 || first > last) throw input_error("Tried to open listening port with an invalid range"); if (bind_inet_address->sa_family != AF_INET) throw input_error("Listening ipv4 socket must be inet address type"); if (bind_inet6_address->sa_family != AF_INET6) throw input_error("Listening ipv6 socket must be inet6 address type"); int inet_fd{}, inet6_fd{}; uint16_t inet_port{}, inet6_port{}; while (true) { if (first > last) { LT_LOG("Unable to find suitable dual ipv4+6 listen ports in the given range", 0); return false; } std::tie(inet_fd, inet_port) = listen_open_range(first, last, bind_inet_address); if (inet_fd == -1) { LT_LOG("Unable to find a suitable ipv4 listen port : last error : %s", std::strerror(errno)); return false; } std::tie(inet6_fd, inet6_port) = listen_open_range(inet_port, inet_port, bind_inet6_address); if (inet6_fd != -1) break; fd_close(inet_fd); first = inet_port + 1; LT_LOG("Unable to find a suitable ipv6 listen port matching ipv4 port %" PRIu16 " : last error : %s", inet_port, std::strerror(errno)); } try { if (inet_port != inet6_port) throw internal_error("Listen::open_both(): ipv4 and ipv6 ports do not match."); if (!fd_listen(inet_fd, backlog)) { LT_LOG("failed to listen on ipv4 socket : %s", std::strerror(errno)); throw resource_error("Could not listen on ipv4 socket: " + std::string(strerror(errno))); } if (block_ipv4in6 && !fd_set_v6only(inet6_fd, true)) { LT_LOG("failed to set IPV6_V6ONLY on socket : %s", std::strerror(errno)); throw resource_error("Could not set IPV6_V6ONLY on socket: " + std::string(strerror(errno))); } if (!fd_listen(inet6_fd, backlog)) { LT_LOG("failed to listen on ipv6 socket : %s", std::strerror(errno)); throw resource_error("Could not listen on ipv6 socket: " + std::string(strerror(errno))); } } catch (...) { fd_close(inet_fd); fd_close(inet6_fd); throw; } listen_inet->open_done(inet_fd, inet_port, backlog); listen_inet6->open_done(inet6_fd, inet_port, backlog); return true; } void Listen::open_done(int fd, uint16_t port, int backlog) { set_file_descriptor(fd); m_port = port; manager->connection_manager()->inc_socket_count(); runtime::socket_manager()->register_event_or_throw(this, [this]() { this_thread::poll()->open(this); this_thread::poll()->insert_read(this); this_thread::poll()->insert_error(this); }); LT_LOG("listen opened: fd:%i port:%" PRIu16 " backlog:%i", file_descriptor(), m_port, backlog); } void Listen::close() { if (!is_open()) return; runtime::socket_manager()->unregister_event_or_throw(this, [this]() { this_thread::poll()->remove_and_close(this); fd_close(file_descriptor()); set_file_descriptor(-1); }); manager->connection_manager()->dec_socket_count(); m_port = 0; } void Listen::event_read() { while (true) { auto handshake = std::make_unique(); // TODO: Optimize this by adding handshake immediately to poll and put the slot_accepted() call // outside of open_func(). auto open_func = [&]() { int fd; sa_unique_ptr sa; std::tie(fd, sa) = fd_sap_accept(file_descriptor()); if (fd == -1) { if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) return; // Force a new event_read() call just to be sure we don't enter an infinite loop. if (errno == ECONNABORTED) return; throw resource_error("Listener port accept() failed: " + std::string(std::strerror(errno))); } m_slot_accepted(handshake, fd, sa.get()); }; auto cleanup_func = [&]() { LT_LOG("failed to accept incoming connection : socket manager triggered cleanup", 0); if (handshake && handshake->is_open()) handshake->destroy_connection(false); }; bool result = runtime::socket_manager()->open_event_or_cleanup(handshake.get(), open_func, cleanup_func); // If the handshake connection or socket manager failed, don't continue accepting connections. // // This allows the event loop a chance to clear out any conflicts with reused file descriptors. if (!result) return; } } void Listen::event_write() { throw internal_error("Listener does not support write()."); } void Listen::event_error() { int socket_error; if (!fd_get_socket_error(file_descriptor(), &socket_error)) throw internal_error("Listener port could not get socket error: " + std::string(std::strerror(errno))); if (socket_error != 0) throw internal_error("Listener port received an error event: " + std::string(std::strerror(socket_error))); } } // namespace torrent libtorrent-0.16.11/src/net/throttle_internal.cc0000644000000000000000000000731415175073411015131 #include "config.h" #include "net/throttle_internal.h" #include #include "net/throttle_list.h" #include "torrent/exceptions.h" namespace torrent { // Plans: // // Make ThrottleList do a callback when it needs more? This would // allow us to remove us from the task scheduler when we're full. Also // this would let us be abit more flexible with the interval. ThrottleInternal::ThrottleInternal(int flags) : m_flags(flags), m_next_slave(m_slave_list.end()), m_time_last_tick(torrent::this_thread::cached_time()) { if (is_root()) m_task_tick.slot() = [this] { receive_tick(); }; } ThrottleInternal::~ThrottleInternal() { if (is_root()) torrent::this_thread::scheduler()->erase(&m_task_tick); for (const auto& t : m_slave_list) delete t; } void ThrottleInternal::enable() { m_throttleList->enable(); for (auto t : m_slave_list) t->m_throttleList->enable(); if (is_root()) { // We need to start the ticks, and make sure we set timeLastTick // to a value that gives an reasonable initial quota. m_time_last_tick = std::max(torrent::this_thread::cached_time() - 1s, 0us); receive_tick(); } } void ThrottleInternal::disable() { for (auto t : m_slave_list) t->m_throttleList->disable(); m_throttleList->disable(); if (is_root()) torrent::this_thread::scheduler()->erase(&m_task_tick); } ThrottleInternal* ThrottleInternal::create_slave() { auto slave = new ThrottleInternal(flag_none); slave->m_maxRate = m_maxRate; slave->m_throttleList = new ThrottleList(); if (m_throttleList->is_enabled()) slave->enable(); m_slave_list.push_back(slave); m_next_slave = m_slave_list.end(); return slave; } void ThrottleInternal::receive_tick() { if (torrent::this_thread::cached_time() < m_time_last_tick + 90ms) throw internal_error("ThrottleInternal::receive_tick() called at a to short interval."); uint64_t count_usec = (torrent::this_thread::cached_time() - m_ptr()->m_time_last_tick).count(); uint32_t quota = count_usec * m_maxRate / 1000000; uint32_t fraction = count_usec * fraction_base / 1000000; receive_quota(quota, fraction); torrent::this_thread::scheduler()->wait_for_ceil_seconds(&m_task_tick, std::chrono::microseconds(calculate_interval())); m_time_last_tick = torrent::this_thread::cached_time(); } int32_t ThrottleInternal::receive_quota(uint32_t quota, uint32_t fraction) { m_unused_quota += quota; while (m_next_slave != m_slave_list.end()) { // TODO: Add logging and see if the use of 'quota' below is causing the quota to be // over-allocated to the next slave, instead of a smoother distribution. // // E.g. we might want to spread it over the next few slaves, especially if we have a very large // number. uint32_t need = std::min(quota, static_cast(fraction) * (*m_next_slave)->max_rate() >> fraction_bits); if (need > m_unused_quota) break; m_unused_quota -= (*m_next_slave)->receive_quota(need, fraction); m_throttleList->add_rate((*m_next_slave)->throttle_list()->rate_added()); ++m_next_slave; } uint32_t need = std::min(quota, static_cast(fraction) * m_maxRate >> fraction_bits); if (m_next_slave == m_slave_list.end() && need <= m_unused_quota) { m_unused_quota -= m_throttleList->update_quota(need); m_next_slave = m_slave_list.begin(); } // Return how much quota we used, but keep as much as one allocation's worth until the next tick // to avoid rounding errors. int32_t used = quota; if (quota < m_unused_quota) { used -= m_unused_quota - quota; m_unused_quota = quota; } // Amount used may be negative if rate changed between last tick and now. return used; } } // namespace torrent libtorrent-0.16.11/src/net/throttle_internal.h0000644000000000000000000000251715175073411014773 #ifndef LIBTORRENT_NET_THROTTLE_INTERNAL_H #define LIBTORRENT_NET_THROTTLE_INTERNAL_H #include #include "torrent/common.h" #include "torrent/throttle.h" #include "torrent/utils/scheduler.h" namespace torrent { class ThrottleInternal : public Throttle { public: static constexpr int flag_none = 0; static constexpr int flag_root = 1; ThrottleInternal(int flags); ~ThrottleInternal(); ThrottleInternal* create_slave(); bool is_root() const { return m_flags & flag_root; } void enable(); void disable(); private: // Fraction is a fixed-precision value with the given number of bits after the decimal point. static constexpr uint32_t fraction_bits = 16; static constexpr uint32_t fraction_base = (1 << fraction_bits); using SlaveList = std::vector; void receive_tick(); // Distribute quota, return amount of quota used. May be negative // if it had more unused quota than is now allowed. int32_t receive_quota(uint32_t quota, uint32_t fraction); int m_flags; SlaveList m_slave_list; SlaveList::iterator m_next_slave; uint32_t m_unused_quota{0}; std::chrono::microseconds m_time_last_tick; utils::SchedulerEntry m_task_tick; }; } // namespace torrent #endif libtorrent-0.16.11/src/net/udns_library.h0000644000000000000000000000015215175073411013720 #ifndef TORRENT_NET_UDNS_LIBRARY_H #define TORRENT_NET_UDNS_LIBRARY_H #include "net/udns/udns.h" #endif libtorrent-0.16.11/src/net/curl_stack.cc0000644000000000000000000001765015175073411013526 #include "config.h" #include "curl_stack.h" #include #include #include #include "net/curl_get.h" #include "net/curl_socket.h" #include "torrent/exceptions.h" #include "torrent/system/thread.h" namespace torrent::net { CurlStack::CurlStack(system::Thread* thread) : m_thread(thread), m_handle(curl_multi_init()) { m_task_timeout.slot() = [this]() { receive_timeout(); }; curl_multi_setopt(m_handle, CURLMOPT_TIMERDATA, this); curl_multi_setopt(m_handle, CURLMOPT_TIMERFUNCTION, &CurlStack::set_timeout); curl_multi_setopt(m_handle, CURLMOPT_SOCKETDATA, this); curl_multi_setopt(m_handle, CURLMOPT_SOCKETFUNCTION, &CurlSocket::receive_socket); curl_multi_setopt(m_handle, CURLMOPT_MAXCONNECTS, m_max_cache_connections); curl_multi_setopt(m_handle, CURLMOPT_MAX_HOST_CONNECTIONS, m_max_host_connections); curl_multi_setopt(m_handle, CURLMOPT_MAX_TOTAL_CONNECTIONS, m_max_total_connections); } CurlStack::~CurlStack() { assert(!is_running() && "CurlStack::~CurlStack() called while still running."); } void CurlStack::set_max_cache_connections(unsigned int value) { if (value > 1024) throw torrent::internal_error("CurlStack::set_max_cache_connections() called with a value greater than 1024."); auto guard = lock_guard(); m_max_cache_connections = value; if (curl_multi_setopt(m_handle, CURLMOPT_MAXCONNECTS, value) != CURLM_OK) throw torrent::internal_error("CurlStack::set_max_cache_connections() error calling curl_multi_setopt."); } void CurlStack::set_max_host_connections(unsigned int value) { if (value > 1024) throw torrent::internal_error("CurlStack::set_max_host_connections() called with a value greater than 1024."); auto guard = lock_guard(); m_max_host_connections = value; if (curl_multi_setopt(m_handle, CURLMOPT_MAX_HOST_CONNECTIONS, value) != CURLM_OK) throw torrent::internal_error("CurlStack::set_max_host_connections() error calling curl_multi_setopt."); } void CurlStack::set_max_total_connections(unsigned int value) { if (value > 4096) throw torrent::internal_error("CurlStack::set_max_total_connections() called with a value greater than 4096."); auto guard = lock_guard(); m_max_total_connections = value; if (curl_multi_setopt(m_handle, CURLMOPT_MAX_TOTAL_CONNECTIONS, value) != CURLM_OK) throw torrent::internal_error("CurlStack::set_max_total_connections() error calling curl_multi_setopt."); } void CurlStack::shutdown() { assert(std::this_thread::get_id() == m_thread->thread_id()); { auto guard = lock_guard(); assert(m_running && "CurlStack::shutdown() called while not running."); m_running = false; } while (!base_type::empty()) close_get(base_type::back()); curl_multi_cleanup(m_handle); m_handle = nullptr; torrent::this_thread::scheduler()->erase(&m_task_timeout); } void CurlStack::start_get(const std::shared_ptr& curl_get) { assert(std::this_thread::get_id() == m_thread->thread_id()); if (curl_get == nullptr) throw torrent::internal_error("CurlStack::start_get() called with a null curl_get."); { auto lock_main = std::unique_lock(m_mutex, std::defer_lock); auto lock_get = std::unique_lock(curl_get->mutex(), std::defer_lock); std::lock(lock_main, lock_get); // TODO: Check is_running, if not return error. Do not throw internal_error. if (!m_running) throw torrent::internal_error("CurlStack::start_get() called while not running."); // TODO: This might cause a race condition on cleanup_unsafe while not active? if (!curl_get->prepare_start_unsafe(this)) return; // CurlGet was already closed. if (!m_user_agent.empty()) curl_easy_setopt(curl_get->handle_unsafe(), CURLOPT_USERAGENT, m_user_agent.c_str()); if (!m_http_proxy.empty()) curl_easy_setopt(curl_get->handle_unsafe(), CURLOPT_PROXY, m_http_proxy.c_str()); if (!m_http_ca_path.empty()) curl_easy_setopt(curl_get->handle_unsafe(), CURLOPT_CAPATH, m_http_ca_path.c_str()); if (!m_http_ca_cert.empty()) curl_easy_setopt(curl_get->handle_unsafe(), CURLOPT_CAINFO, m_http_ca_cert.c_str()); curl_easy_setopt(curl_get->handle_unsafe(), CURLOPT_SSL_VERIFYHOST, m_ssl_verify_host ? 2l : 0l); curl_easy_setopt(curl_get->handle_unsafe(), CURLOPT_SSL_VERIFYPEER, m_ssl_verify_peer ? 1l : 0l); curl_easy_setopt(curl_get->handle_unsafe(), CURLOPT_DNS_CACHE_TIMEOUT, m_dns_timeout); base_type::push_back(curl_get); // Calling curl_multi_add_handle() can result in CurlSocket::receive_socket() being called, // which calls CurlStack::is_running(). lock_main.unlock(); curl_get->activate_unsafe(); } } void CurlStack::close_get(const std::shared_ptr& curl_get) { assert(std::this_thread::get_id() == m_thread->thread_id()); { auto guard_get = curl_get->lock_guard(); if (!curl_get->is_prepare_canceled_unsafe()) { auto itr = std::find(base_type::begin(), base_type::end(), curl_get); if (itr == base_type::end()) throw torrent::internal_error("CurlStack::close_get() called on a CurlGet that is not in the stack."); base_type::erase(itr); } curl_get->cleanup_unsafe(); } curl_get->notify_closed(); } CurlStack::base_type::iterator CurlStack::find_curl_handle(const CURL* curl_handle) { auto itr = std::find_if(base_type::begin(), base_type::end(), [curl_handle](auto& curl_get) { return curl_get->handle_unsafe() == curl_handle; }); if (itr == base_type::end()) throw torrent::internal_error("Could not find CurlGet with the right easy_handle."); return itr; } int CurlStack::set_timeout(void*, long timeout_ms, CurlStack* stack) { assert(std::this_thread::get_id() == stack->m_thread->thread_id()); if (timeout_ms == -1) torrent::this_thread::scheduler()->erase(&stack->m_task_timeout); else torrent::this_thread::scheduler()->update_wait_for_ceil_seconds(&stack->m_task_timeout, std::chrono::milliseconds(timeout_ms)); return 0; } void CurlStack::receive_timeout() { assert(std::this_thread::get_id() == m_thread->thread_id()); int count{}; auto code = curl_multi_socket_action(m_handle, CURL_SOCKET_TIMEOUT, 0, &count); if (code != CURLM_OK) throw torrent::internal_error("CurlStack::receive_timeout() error calling curl_multi_socket_action."); while (process_done_handle()) ; // Do nothing. if (base_type::empty()) { torrent::this_thread::scheduler()->erase(&m_task_timeout); return; } if (!m_task_timeout.is_scheduled()) { // Sometimes libcurl forgets to reset the timeout. Try to poll the value in that case, or use 10 // seconds max. long timeout_ms; curl_multi_timeout(m_handle, &timeout_ms); auto timeout = std::max(std::chrono::milliseconds(timeout_ms), 10s); torrent::this_thread::scheduler()->wait_for_ceil_seconds(&m_task_timeout, timeout); } } // TODO: Check if curl_get is still active. bool CurlStack::process_done_handle() { int remaining_msgs{}; CURLMsg* msg = curl_multi_info_read(m_handle, &remaining_msgs); if (msg == nullptr) return false; if (msg->msg != CURLMSG_DONE) throw torrent::internal_error("CurlStack::process_done_handle() msg->msg != CURLMSG_DONE."); // TODO: Search if handle is still in the stack, and if not, assume it was closed and clean up. (check is_active) auto itr = find_curl_handle(msg->easy_handle); // TODO: Lock CurlGet here, do the retry or retrieve the slots, instead of using trigger_*. // Strictly not needed as the following conditions will also return false if the handle is // closing. if ((*itr)->is_closing()) return remaining_msgs != 0; if (msg->data.result == CURLE_COULDNT_RESOLVE_HOST && (*itr)->retry_resolve()) return remaining_msgs != 0; if (msg->data.result == CURLE_OK) (*itr)->trigger_done(); else (*itr)->trigger_failed(curl_easy_strerror(msg->data.result)); // TODO: Should start next download here rather than in close_get. return remaining_msgs != 0; } } // namespace torrent::net libtorrent-0.16.11/src/net/throttle_list.h0000644000000000000000000000657715175073411014144 #ifndef LIBTORRENT_NET_THROTTLE_LIST_H #define LIBTORRENT_NET_THROTTLE_LIST_H #include #include "torrent/rate.h" // To allow conditional compilation depending on whether this patch is applied or not. #define LIBTORRENT_CUSTOM_THROTTLES 1 namespace torrent { class ThrottleNode; class ThrottleList : private std::list { public: using base_type = std::list; using base_type::iterator; using base_type::const_iterator; using base_type::reverse_iterator; using base_type::clear; using base_type::size; using base_type::begin; using base_type::end; using base_type::rbegin; using base_type::rend; bool is_enabled() const { return m_enabled; } bool is_active(const ThrottleNode* node) const; bool is_inactive(const ThrottleNode* node) const; bool is_throttled(const ThrottleNode* node) const; // When disabled all nodes are active at all times. void enable(); void disable(); // Returns the amount of quota used. May be negative if it had unused // quota left over from the last call that was more than is now allowed. int32_t update_quota(uint32_t quota); uint32_t size() const { return m_size; } uint32_t outstanding_quota() const { return m_outstandingQuota; } uint32_t unallocated_quota() const { return m_unallocatedQuota; } uint32_t min_chunk_size() const { return m_minChunkSize; } void set_min_chunk_size(uint32_t v) { m_minChunkSize = v; } uint32_t max_chunk_size() const { return m_maxChunkSize; } void set_max_chunk_size(uint32_t v) { m_maxChunkSize = v; } uint32_t node_quota(ThrottleNode* node) const; uint32_t node_used(ThrottleNode* node, uint32_t used); // both node_used functions uint32_t node_used_unthrottled(uint32_t used); // return the "used" argument void node_deactivate(ThrottleNode* node); const Rate* rate_slow() const { return &m_rateSlow; } void add_rate(uint32_t used); uint32_t rate_added() { uint32_t v = m_rateAdded; m_rateAdded = 0; return v; } // It is asumed that inserted nodes are currently active. It won't // matter if they do not get any initial quota as a later activation // of an active node should be safe. void insert(ThrottleNode* node); void erase(ThrottleNode* node); private: inline void allocate_quota(ThrottleNode* node); bool m_enabled{false}; uint32_t m_size{0}; uint32_t m_outstandingQuota{0}; uint32_t m_unallocatedQuota{0}; uint32_t m_unusedUnthrottledQuota{0}; uint32_t m_rateAdded{0}; uint32_t m_minChunkSize{2 << 10}; uint32_t m_maxChunkSize{16 << 10}; Rate m_rateSlow{60}; // [m_splitActive,end> contains nodes that are inactive and need // more quote, sorted from the most urgent // node. [begin,m_splitActive> holds nodes with a large enough quota // to transmit, but are blocking. These are sorted from the longest // blocking node. iterator m_splitActive{end()}; }; } // namespace torrent #endif libtorrent-0.16.11/src/net/dns_cache.cc0000644000000000000000000004741415175073411013304 #include "config.h" #include "net/dns_cache.h" #include #include "net/thread_net.h" #include "net/dns_buffer.h" #include "torrent/exceptions.h" #include "torrent/net/socket_address.h" #include "torrent/utils/log.h" #define LT_LOG(log_fmt, ...) \ lt_log_print(LOG_NET_DNS, "dns-cache : " log_fmt, __VA_ARGS__); #define LT_LOG_REQUESTER(log_fmt, ...) \ lt_log_print(LOG_NET_DNS, "%016p->dns-cache : " log_fmt, requester, __VA_ARGS__); namespace torrent::net { namespace { enum { DNS_EMPTY, DNS_VALID, DNS_TRY_AGAIN, DNS_NO_RECORD, }; int dns_error(int status) { switch (status) { case DNS_TRY_AGAIN: return EAI_AGAIN; case DNS_NO_RECORD: return EAI_NONAME; default: throw internal_error("dns_error() invalid status"); } } const char* dns_error_str(int status) { switch (status) { case DNS_TRY_AGAIN: return "EAI_AGAIN"; case DNS_NO_RECORD: return "EAI_NONAME"; default: return "invalid"; } } std::chrono::minutes last_update_or_failed(const DnsCacheInfo& info) { return std::max(info.last_updated, info.last_failed_update); } } // namespace void DnsCache::resolve(void* requester, std::string hostname, int family, resolver_callback&& callback) { cull_stale_entries(); if (hostname.empty()) throw internal_error("DnsCache::resolve() hostname is empty"); if (family != AF_INET && family != AF_INET6 && family != AF_UNSPEC) throw internal_error("DnsCache::resolve() invalid address family"); auto itr = m_entries.find(hostname); if (itr == m_entries.end()) { // No need to log. ThreadNet::thread_net()->dns_buffer()->resolve(requester, hostname, family, std::move(callback)); return; } auto& sin_addr = itr->second->sin_addr; auto& sin_info = itr->second->sin_info; auto& sin6_addr = itr->second->sin6_addr; auto& sin6_info = itr->second->sin6_info; auto current_time = std::chrono::duration_cast(this_thread::cached_time()); // We need to get the status of each address family (if they're wanted), then construct the callback last: auto fn = [&](bool has_addr, int family, DnsCacheInfo& info) { if (has_addr) { // This is currently just a staleness check, we should have logic to report back when addresses // are successfully connected to. // // Or rather, we should pass a 'failed' counter in the resolve to indicate how many failed // attempts have been made to connect to the address. if (current_time > last_update_or_failed(info) + 24h) update_stale_info("valid record", requester, hostname, family, info); return DNS_VALID; } if (last_update_or_failed(info) == std::chrono::minutes(0)) return DNS_EMPTY; if (info.updating) { // TODO: Add sanity check on 'updating' here? // TODO: When updating, we add ourselves to the request unless it's a stale update or we // have very many failures / recent retries. return DNS_TRY_AGAIN; } if (info.no_record) { // TODO: Change to consider no_record a success. if (current_time > last_update_or_failed(info) + 2h) update_stale_info("no record", requester, hostname, family, info); return DNS_NO_RECORD; } // Queue a background request if failed timeout has passed, but return EAI_AGAIN as we're in // failure mode and the caller is going to retry. // // If it's been very long since the last try, we will use a normal request. // // Make sure we don't keep trying to resolve if we don't get proper responses. // TODO: Replace with 'failed' counter, and use that to determine when to retry, when to give up, etc. if (current_time > last_update_or_failed(info) + 10min) update_stale_info("failed update", requester, hostname, family, info); // TODO: Have a special code for when we're in try-again and also want to force a new resolve // due to staleness. (DSN_TRY_AGAIN_STALE) return DNS_TRY_AGAIN; }; // TODO: Detect when either A or AAAA dns server isn't responding, and cut back on retries, etc. // AF_INET: if (family == AF_INET) { auto status_sin = fn(sin_addr != nullptr, AF_INET, sin_info); switch (status_sin) { case DNS_EMPTY: LT_LOG_REQUESTER("matched cache entry, resolving missing AF_INET : hostname:%s family:AF_INET", hostname.c_str()); return queue_resolve(requester, hostname, AF_INET, sin_info, std::move(callback)); case DNS_VALID: LT_LOG_REQUESTER("matched cache entry : hostname:%s family:AF_INET sin:%s", hostname.c_str(), sin_pretty_or_empty(sin_addr.get()).c_str()); return callback(sin_addr, 0, nullptr, 0); case DNS_NO_RECORD: case DNS_TRY_AGAIN: LT_LOG_REQUESTER("matched cache entry : hostname:%s family:AF_INET sin:%s", hostname.c_str(), dns_error_str(status_sin)); return callback(nullptr, dns_error(status_sin), nullptr, 0); } } // AF_INET6: if (family == AF_INET6) { auto status_sin6 = fn(sin6_addr != nullptr, AF_INET6, sin6_info); switch (status_sin6) { case DNS_EMPTY: LT_LOG_REQUESTER("matched cache entry, resolving missing AF_INET6 : hostname:%s family:AF_INET6", hostname.c_str()); return queue_resolve(requester, hostname, AF_INET6, sin6_info, std::move(callback)); case DNS_VALID: LT_LOG_REQUESTER("matched cache entry : hostname:%s family:AF_INET6 sin6:%s", hostname.c_str(), sin6_pretty_or_empty(sin6_addr.get()).c_str()); return callback(nullptr, 0, sin6_addr, 0); case DNS_NO_RECORD: case DNS_TRY_AGAIN: LT_LOG_REQUESTER("matched cache entry : hostname:%s family:AF_INET6 sin6:%s", hostname.c_str(), dns_error_str(status_sin6)); return callback(nullptr, 0, nullptr, dns_error(status_sin6)); } } // AF_UNSPEC: auto status_sin = fn(sin_addr != nullptr, AF_INET, sin_info); auto status_sin6 = fn(sin6_addr != nullptr, AF_INET6, sin6_info); if (status_sin == DNS_VALID) { switch (status_sin6) { case DNS_EMPTY: LT_LOG_REQUESTER("matched cache entry, resolving missing AF_INET6 : hostname:%s family:AF_UNSPEC sin:%s", hostname.c_str(), sin_pretty_or_empty(sin_addr.get()).c_str()); return queue_resolve(requester, hostname, AF_INET6, sin6_info, [sin_addr, callback = std::move(callback)](auto, int, auto sin6_addr, int sin6_error) mutable { return callback(sin_addr, 0, sin6_addr, sin6_error); }); case DNS_VALID: LT_LOG_REQUESTER("matched cache entry : hostname:%s family:AF_UNSPEC sin:%s sin6:%s", hostname.c_str(), sin_pretty_or_empty(sin_addr.get()).c_str(), sin6_pretty_or_empty(sin6_addr.get()).c_str()); return callback(sin_addr, 0, sin6_addr, 0); case DNS_NO_RECORD: case DNS_TRY_AGAIN: LT_LOG_REQUESTER("matched cache entry : hostname:%s family:AF_UNSPEC sin:%s sin6:%s", hostname.c_str(), sin_pretty_or_empty(sin_addr.get()).c_str(), dns_error_str(status_sin6)); return callback(sin_addr, 0, nullptr, dns_error(status_sin6)); }; } if (status_sin6 == DNS_VALID) { switch (status_sin) { case DNS_EMPTY: LT_LOG_REQUESTER("matched cache entry, resolving missing AF_INET : hostname:%s family:AF_UNSPEC sin6:%s", hostname.c_str(), sin6_pretty_or_empty(sin6_addr.get()).c_str()); return queue_resolve(requester, hostname, AF_INET, sin_info, [sin6_addr, callback = std::move(callback)](auto sin_addr, int error_sin, auto, int) mutable { return callback(sin_addr, error_sin, sin6_addr, 0); }); case DNS_NO_RECORD: case DNS_TRY_AGAIN: LT_LOG_REQUESTER("matched cache entry : hostname:%s family:AF_UNSPEC sin:%s sin6:%s", hostname.c_str(), dns_error_str(status_sin), sin6_pretty_or_empty(sin6_addr.get()).c_str()); return callback(nullptr, dns_error(status_sin), sin6_addr, 0); case DNS_VALID: throw internal_error("DnsCache::resolve() unreachable code : status_sin6 == DNS_VALID"); }; } if (status_sin == DNS_EMPTY) { switch (status_sin6) { case DNS_NO_RECORD: case DNS_TRY_AGAIN: LT_LOG_REQUESTER("matched cache entry, resolving missing AF_INET : hostname:%s family:AF_UNSPEC sin6:%s", hostname.c_str(), dns_error_str(status_sin6)); return queue_resolve(requester, hostname, AF_INET, sin_info, std::move(callback)); case DNS_EMPTY: case DNS_VALID: throw internal_error("DnsCache::resolve() unreachable code : status_sin == DNS_EMPTY"); }; } if (status_sin6 == DNS_EMPTY) { switch (status_sin) { case DNS_NO_RECORD: case DNS_TRY_AGAIN: LT_LOG_REQUESTER("matched cache entry, resolving missing AF_INET6 : hostname:%s family:AF_UNSPEC sin:%s", hostname.c_str(), dns_error_str(status_sin)); return queue_resolve(requester, hostname, AF_INET6, sin6_info, std::move(callback)); case DNS_EMPTY: case DNS_VALID: throw internal_error("DnsCache::resolve() unreachable code : status_sin6 == DNS_EMPTY"); }; } if (status_sin == DNS_NO_RECORD || status_sin6 == DNS_NO_RECORD) { LT_LOG_REQUESTER("matched cache entry, returning no record error : hostname:%s family:AF_UNSPEC sin:%s sin6:%s", hostname.c_str(), dns_error_str(status_sin), dns_error_str(status_sin6)); return callback(nullptr, dns_error(status_sin), nullptr, dns_error(status_sin6)); } if (status_sin == DNS_TRY_AGAIN && status_sin6 == DNS_TRY_AGAIN) { LT_LOG_REQUESTER("matched cache entry, returning try again error : hostname:%s family:AF_UNSPEC sin:EAI_AGAIN sin6:EAI_AGAIN", hostname.c_str()); return callback(nullptr, EAI_AGAIN, nullptr, EAI_AGAIN); } throw internal_error("DnsCache::resolve() unreachable code : end-of-function"); } // TODO: When we add per-family errors, change this to only handle AF_INET/AF_INET6. void DnsCache::process_success(const std::string& hostname, int family, sin_shared_ptr result_sin, sin6_shared_ptr result_sin6) { if (family != AF_INET && family != AF_INET6 && family != AF_UNSPEC) throw internal_error("DnsCache::process_success() invalid address family"); if (result_sin == nullptr && result_sin6 == nullptr) throw internal_error("DnsCache::process_success() both result_sin and result_sin6 are nullptr"); if (family == AF_INET && result_sin == nullptr) throw internal_error("DnsCache::process_success() result_sin is nullptr for AF_INET"); if (family == AF_INET6 && result_sin6 == nullptr) throw internal_error("DnsCache::process_success() result_sin6 is nullptr for AF_INET6"); auto [itr, inserted] = m_entries.try_emplace(hostname, nullptr); if (inserted) itr->second = std::make_unique(); auto& sin_addr = itr->second->sin_addr; auto& sin_info = itr->second->sin_info; auto& sin6_addr = itr->second->sin6_addr; auto& sin6_info = itr->second->sin6_info; auto current_time = std::chrono::duration_cast(this_thread::cached_time()); if (inserted) { sin_info.entry_itr = itr; sin6_info.entry_itr = itr; sin_info.staleness_itr = m_sin_staleness.end(); sin6_info.staleness_itr = m_sin6_staleness.end(); if (family == AF_INET) { sin_addr = std::move(result_sin); reset_sin_updated(itr->second.get(), current_time); LT_LOG("added new cache entry : hostname:%s family:AF_INET sin:%s", hostname.c_str(), sin_pretty_or_empty(sin_addr.get()).c_str()); return; } if (family == AF_INET6) { sin6_addr = std::move(result_sin6); reset_sin6_updated(itr->second.get(), current_time); LT_LOG("added new cache entry : hostname:%s family:AF_INET6 sin6:%s", hostname.c_str(), sin6_pretty_or_empty(sin6_addr.get()).c_str()); return; } throw internal_error("DnsCache::process_success() unreachable code : inserted"); } if (family == AF_INET) { sin_addr = std::move(result_sin); sin_info.no_record = false; reset_sin_updated(itr->second.get(), current_time); // TODO: Only log if address has changed? LT_LOG("updated cache entry : hostname:%s family:AF_INET sin:%s", hostname.c_str(), sin_pretty_or_empty(sin_addr.get()).c_str()); return; } if (family == AF_INET6) { sin6_addr = std::move(result_sin6); sin6_info.no_record = false; reset_sin6_updated(itr->second.get(), current_time); LT_LOG("updated cache entry : hostname:%s family:AF_INET6 sin6:%s", hostname.c_str(), sin6_pretty_or_empty(sin6_addr.get()).c_str()); return; } throw internal_error("DnsCache::process_success() unreachable code"); } void DnsCache::process_failure(const std::string& hostname, int family, int error) { if (family != AF_INET && family != AF_INET6 && family != AF_UNSPEC) throw internal_error("DnsCache::process_failure() invalid address family"); if (error == 0) throw internal_error("DnsCache::process_failure() error is 0, should be success"); // TODO: If 'updating', add to scheduled task? auto [itr, inserted] = m_entries.try_emplace(hostname, nullptr); if (inserted) itr->second = std::make_unique(); auto& sin_addr = itr->second->sin_addr; auto& sin_info = itr->second->sin_info; auto& sin6_addr = itr->second->sin6_addr; auto& sin6_info = itr->second->sin6_info; auto current_time = std::chrono::duration_cast(this_thread::cached_time()); if (inserted) { sin_info.entry_itr = itr; sin6_info.entry_itr = itr; sin_info.staleness_itr = m_sin_staleness.end(); sin6_info.staleness_itr = m_sin6_staleness.end(); if (family == AF_INET) { switch (error) { case EAI_NONAME: // TODO: Should NONAME set success time? sin_info.no_record = true; reset_sin_failed(itr->second.get(), current_time); LT_LOG("added new cache entry with no record : hostname:%s family:AF_INET", hostname.c_str()); return; default: reset_sin_failed(itr->second.get(), current_time); LT_LOG("added new cache entry with failed update : hostname:%s family:AF_INET error:%s", hostname.c_str(), gai_enum_error(error)); return; }; } if (family == AF_INET6) { switch (error) { case EAI_NONAME: sin6_info.no_record = true; reset_sin6_failed(itr->second.get(), current_time); LT_LOG("added new cache entry with no record : hostname:%s family:AF_INET6", hostname.c_str()); return; default: reset_sin6_failed(itr->second.get(), current_time); LT_LOG("added new cache entry with failed update : hostname:%s family:AF_INET6 error:%s", hostname.c_str(), gai_enum_error(error)); return; }; } throw internal_error("DnsCache::process_failure() unreachable code : inserted"); } // TODO: EAI_NONAME should check if we're already set to no_record before doing anything. if (family == AF_INET) { switch (error) { case EAI_NONAME: sin_addr = nullptr; sin_info.no_record = true; // TODO: Should NONAME set success time? reset_sin_failed(itr->second.get(), current_time); LT_LOG("updated cache entry with no record : hostname:%s family:AF_INET", hostname.c_str()); return; default: reset_sin_failed(itr->second.get(), current_time); LT_LOG("updated cache entry with failed update : hostname:%s family:AF_INET error:%s", hostname.c_str(), gai_enum_error(error)); return; }; } if (family == AF_INET6) { switch (error) { case EAI_NONAME: sin6_addr = nullptr; sin6_info.no_record = true; // TODO: Should NONAME set success time? reset_sin6_failed(itr->second.get(), current_time); LT_LOG("updated cache entry with no record : hostname:%s family:AF_INET6", hostname.c_str()); return; default: reset_sin6_failed(itr->second.get(), current_time); LT_LOG("updated cache entry with failed update : hostname:%s family:AF_INET6 error:%s", hostname.c_str(), gai_enum_error(error)); return; }; } throw internal_error("DnsCache::process_failure() unreachable code"); } void DnsCache::reset_sin_updated(DnsCacheEntry* entry, std::chrono::minutes current_time) { auto& info = entry->sin_info; info.updating = false; info.last_updated = current_time; info.last_failed_update = std::chrono::minutes{0}; if (info.staleness_itr != m_sin_staleness.end()) m_sin_staleness.erase(info.staleness_itr); info.staleness_itr = m_sin_staleness.insert(m_sin_staleness.end(), std::ref(entry)); } void DnsCache::reset_sin6_updated(DnsCacheEntry* entry, std::chrono::minutes current_time) { auto& info = entry->sin6_info; info.updating = false; info.last_updated = current_time; info.last_failed_update = std::chrono::minutes{0}; if (info.staleness_itr != m_sin6_staleness.end()) m_sin6_staleness.erase(info.staleness_itr); info.staleness_itr = m_sin6_staleness.insert(m_sin6_staleness.end(), std::ref(entry)); } void DnsCache::reset_sin_failed(DnsCacheEntry* entry, std::chrono::minutes current_time) { auto& info = entry->sin_info; info.updating = false; info.last_updated = std::chrono::minutes{0}; info.last_failed_update = current_time; if (info.staleness_itr != m_sin_staleness.end()) m_sin_staleness.erase(info.staleness_itr); info.staleness_itr = m_sin_staleness.insert(m_sin_staleness.end(), std::ref(entry)); } void DnsCache::reset_sin6_failed(DnsCacheEntry* entry, std::chrono::minutes current_time) { auto& info = entry->sin6_info; info.updating = false; info.last_updated = std::chrono::minutes{0}; info.last_failed_update = current_time; if (info.staleness_itr != m_sin6_staleness.end()) m_sin6_staleness.erase(info.staleness_itr); info.staleness_itr = m_sin6_staleness.insert(m_sin6_staleness.end(), std::ref(entry)); } void DnsCache::cull_stale_entries() { auto current_time = std::chrono::duration_cast(this_thread::cached_time()); while (!m_sin_staleness.empty()) { auto* entry = m_sin_staleness.front(); auto& info = entry->sin_info; if (current_time < last_update_or_failed(info) + 48h) break; LT_LOG("culling stale cache entry : hostname:%s family:AF_INET sin:%s", info.entry_itr->first.c_str(), sin_pretty_or_empty(entry->sin_addr.get()).c_str()); if (entry->sin6_info.staleness_itr != m_sin6_staleness.end()) m_sin6_staleness.erase(entry->sin6_info.staleness_itr); m_entries.erase(info.entry_itr); m_sin_staleness.pop_front(); } while (!m_sin6_staleness.empty()) { auto* entry = m_sin6_staleness.front(); auto& info = entry->sin6_info; if (current_time < last_update_or_failed(info) + 48h) break; LT_LOG("culling stale cache entry : hostname:%s family:AF_INET6 sin6:%s", info.entry_itr->first.c_str(), sin6_pretty_or_empty(entry->sin6_addr.get()).c_str()); if (entry->sin_info.staleness_itr != m_sin_staleness.end()) m_sin_staleness.erase(entry->sin_info.staleness_itr); m_entries.erase(info.entry_itr); m_sin6_staleness.pop_front(); } } void DnsCache::queue_resolve(void* requester, const std::string& hostname, int family, DnsCacheInfo& info, resolver_callback&& callback) { ThreadNet::thread_net()->dns_buffer()->resolve(requester, hostname, family, std::move(callback)); info.updating = true; } void DnsCache::update_stale_info(const char* reason, void* requester, const std::string& hostname, int family, DnsCacheInfo& info) { LT_LOG_REQUESTER("stale cache entry with %s, retrying in background : hostname:%s family:%s", reason, hostname.c_str(), family_str(family)); ThreadNet::thread_net()->dns_buffer()->resolve(this, hostname, family, []( auto, int, auto, int) {}); info.updating = true; } } // namespace torrent::net libtorrent-0.16.11/src/net/udns_resolver.h0000644000000000000000000000406615175073411014125 #ifndef LIBTORRENT_NET_UDNSEVENT_H #define LIBTORRENT_NET_UDNSEVENT_H #include #include #include #include "torrent/event.h" #include "torrent/net/types.h" #include "torrent/utils/scheduler.h" struct dns_ctx; namespace torrent::net { struct UdnsQuery; class UdnsResolverInternal; class UdnsResolver : public Event { public: using query_map = std::multimap>; UdnsResolver(); ~UdnsResolver() override; const char* type_name() const override { return "udns"; } void initialize(system::Thread* thread); void cleanup(); // Callback must happen in thread_net and cannot call back into the resolver. // // If the hostname is a numeric address, it will result in the callback being called immediately. void resolve(void* requester, const std::string& hostname, int family, resolver_callback&& callback); // Cancel may block if the resolver received the response and is calling the callback. void cancel(void* requester); void flush(); void event_read() override; void event_write() override; void event_error() override; protected: friend class UdnsResolverInternal; std::unique_ptr erase_query(query_map::iterator itr); query_map::iterator find_query_or_fail_unsafe(UdnsQuery* query); bool try_resolve_numeric(std::unique_ptr& query); void process_canceled(); void process_timeouts(); static void process_partial_result_unsafe(query_map::iterator itr); static void process_final_result_unsafe(std::unique_ptr&& query); static bool m_initialized; system::Thread* m_thread{}; ::dns_ctx* m_ctx{}; utils::SchedulerEntry m_task_timeout; std::mutex m_mutex; query_map m_queries_unsafe; query_map m_malformed_queries_unsafe; }; } // namespace torrent::net #endif // LIBTORRENT_NET_UDNSEVENT_H libtorrent-0.16.11/src/net/curl_stack.h0000644000000000000000000001403315175073411013360 #ifndef LIBTORRENT_NET_CURL_STACK_H #define LIBTORRENT_NET_CURL_STACK_H #include #include #include #include #include #include #include #include "torrent/utils/scheduler.h" namespace torrent::net { class CurlGet; class CurlSocket; // Since std::hardware_destructive_interference_size only got added in gcc 12.1 class alignas(LT_SMP_CACHE_BYTES) CurlStack : private std::vector> { public: using base_type = std::vector>; using socket_map_type = std::map>; CurlStack(system::Thread* thread); ~CurlStack(); bool is_running() const; unsigned int size() const; unsigned int max_cache_connections() const; unsigned int max_host_connections() const; unsigned int max_total_connections() const; void set_max_cache_connections(unsigned int value); void set_max_host_connections(unsigned int value); void set_max_total_connections(unsigned int value); const std::string& user_agent() const; const std::string& http_proxy() const; const std::string& http_capath() const; const std::string& http_cacert() const; void set_user_agent(const std::string& s); void set_http_proxy(const std::string& s); void set_http_capath(const std::string& s); void set_http_cacert(const std::string& s); bool ssl_verify_host() const; bool ssl_verify_peer() const; void set_ssl_verify_host(bool s); void set_ssl_verify_peer(bool s); long dns_timeout() const; void set_dns_timeout(long timeout); void shutdown(); void start_get(const std::shared_ptr& curl_get); void close_get(const std::shared_ptr& curl_get); bool process_done_handle(); system::Thread* thread() const { return m_thread; } protected: friend class CurlGet; friend class CurlSocket; CURLM* handle() const { return m_handle; } auto socket_map() { return &m_socket_map; } // We need to lock when changing any of the values publically accessible. void lock() const { m_mutex.lock(); } auto lock_guard() const { return std::scoped_lock(m_mutex); } void unlock() const { m_mutex.unlock(); } private: CurlStack(const CurlStack&) = delete; CurlStack operator=(const CurlStack&) = delete; base_type::iterator find_curl_handle(const CURL* curl_handle); static int set_timeout(void*, long timeout_ms, CurlStack* stack); void receive_timeout(); // Unprotected members (including base_type vector), only changed in ways that are implicitly // thread-safe. E.g. before any threads are started or only within the owning thread. system::Thread* m_thread{}; CURLM* m_handle{}; utils::SchedulerEntry m_task_timeout; socket_map_type m_socket_map; mutable std::mutex m_mutex; // Use lock guard when accessing these members, and when modifying the underlying vector. bool m_running{true}; unsigned int m_max_cache_connections{0}; unsigned int m_max_host_connections{0}; unsigned int m_max_total_connections{32}; std::string m_user_agent; std::string m_http_proxy; std::string m_http_ca_path; std::string m_http_ca_cert; bool m_ssl_verify_host{true}; bool m_ssl_verify_peer{true}; long m_dns_timeout{60}; }; inline bool CurlStack::is_running() const { auto guard = lock_guard(); return m_running; } inline unsigned int CurlStack::size() const { auto guard = lock_guard(); return base_type::size(); } inline unsigned int CurlStack::max_cache_connections() const { auto guard = lock_guard(); return m_max_cache_connections; } inline unsigned int CurlStack::max_host_connections() const { auto guard = lock_guard(); return m_max_host_connections; } inline unsigned int CurlStack::max_total_connections() const { auto guard = lock_guard(); return m_max_total_connections; } inline const std::string& CurlStack::user_agent() const { auto guard = lock_guard(); return m_user_agent; } inline const std::string& CurlStack::http_proxy() const { auto guard = lock_guard(); return m_http_proxy; } inline const std::string& CurlStack::http_capath() const { auto guard = lock_guard(); return m_http_ca_path; } inline const std::string& CurlStack::http_cacert() const { auto guard = lock_guard(); return m_http_ca_cert; } inline void CurlStack::set_user_agent(const std::string& s) { auto guard = lock_guard(); m_user_agent = s; } inline void CurlStack::set_http_proxy(const std::string& s) { auto guard = lock_guard(); m_http_proxy = s; } inline void CurlStack::set_http_capath(const std::string& s) { auto guard = lock_guard(); m_http_ca_path = s; } inline void CurlStack::set_http_cacert(const std::string& s) { auto guard = lock_guard(); m_http_ca_cert = s; } inline bool CurlStack::ssl_verify_host() const { auto guard = lock_guard(); return m_ssl_verify_host; } inline bool CurlStack::ssl_verify_peer() const { auto guard = lock_guard(); return m_ssl_verify_peer; } inline void CurlStack::set_ssl_verify_host(bool s) { auto guard = lock_guard(); m_ssl_verify_host = s; } inline void CurlStack::set_ssl_verify_peer(bool s) { auto guard = lock_guard(); m_ssl_verify_peer = s; } inline long CurlStack::dns_timeout() const { auto guard = lock_guard(); return m_dns_timeout; } inline void CurlStack::set_dns_timeout(long timeout) { auto guard = lock_guard(); m_dns_timeout = timeout; } } // namespace torrent::net #endif // LIBTORRENT_NET_CURL_STACK_H libtorrent-0.16.11/src/net/socket_datagram.cc0000644000000000000000000000254315175073411014517 #include "config.h" #include "socket_datagram.h" #include #include "torrent/exceptions.h" #include "torrent/net/socket_address.h" namespace torrent { SocketDatagram::~SocketDatagram() = default; int SocketDatagram::read_datagram(void* buffer, unsigned int length) { if (length == 0) throw internal_error("Tried to receive buffer length 0"); return ::recv(m_fileDesc, buffer, length, 0); } int SocketDatagram::write_datagram(const void* buffer, unsigned int length) { if (length == 0) throw internal_error("Tried to send buffer length 0"); return ::send(m_fileDesc, buffer, length, 0); } int SocketDatagram::read_datagram_sa(void* buffer, unsigned int length, sockaddr* from_sa, socklen_t from_length) { if (length == 0) throw internal_error("Tried to receive buffer length 0"); if (from_sa == nullptr) throw internal_error("Tried to receive datagram with NULL sockaddr pointer"); return ::recvfrom(m_fileDesc, buffer, length, 0, from_sa, &from_length); } int SocketDatagram::write_datagram_sa(const void* buffer, unsigned int length, sockaddr* sa) { if (length == 0) throw internal_error("Tried to send buffer length 0"); int r; if (sa != nullptr) r = ::sendto(m_fileDesc, buffer, length, 0, sa, sa_length(sa)); else r = ::send(m_fileDesc, buffer, length, 0); return r; } } // namespace torrent libtorrent-0.16.11/src/net/protocol_buffer.h0000644000000000000000000001610315175073411014420 #ifndef LIBTORRENT_NET_PROTOCOL_BUFFER_H #define LIBTORRENT_NET_PROTOCOL_BUFFER_H #include #include #include #include "torrent/exceptions.h" namespace torrent { template class ProtocolBuffer { public: using value_type = uint8_t; using iterator = value_type*; // TODO: Change to 32-bit, using size_type = uint16_t; using difference_type = int16_t; void reset() { m_position = m_end = begin(); } void reset_position() { m_position = m_buffer; } bool consume(difference_type v); void set_position_itr(iterator itr) { m_position = itr; } void set_end(size_type v) { m_end = m_buffer + v; } void set_end_itr(iterator itr) { m_end = itr; } difference_type move_end(difference_type v) { m_end += v; return v; } uint8_t read_8() { return *m_position++; } uint8_t peek_8() { return *m_position; } uint16_t read_16(); uint16_t peek_16(); uint32_t read_32(); uint32_t peek_32(); uint64_t read_64() { return read_int(); } uint64_t peek_64() { return peek_int(); } uint8_t peek_8_at(size_type pos) { return *(m_position + pos); } template void read_range(Out first, Out last); template void read_len(Out start, unsigned int len); template inline T read_int(); template inline T peek_int(); void write_8(uint8_t v) { *m_end++ = v; validate_end(); } void write_16(uint16_t v); void write_32(uint32_t v); void write_32_n(uint32_t v); void write_64(uint64_t v) { write_int(v); } template inline void write_int(T t); template void write_range(In first, In last); template void write_len(In start, unsigned int len); iterator begin() { return m_buffer; } iterator position() { return m_position; } iterator end() { return m_end; } size_type size_position() const { return m_position - m_buffer; } size_type size_end() const { return m_end - m_buffer; } size_type remaining() const { return m_end - m_position; } size_type reserved() const { return tmpl_size; } size_type reserved_left() const { return reserved() - size_end(); } void move_unused(); void validate_position() const { #ifdef USE_EXTRA_DEBUG if (m_position > m_buffer + tmpl_size) throw internal_error("ProtocolBuffer tried to read beyond scope of the buffer."); if (m_position > m_end) throw internal_error("ProtocolBuffer tried to read beyond end of the buffer."); #endif } void validate_end() const { #ifdef USE_EXTRA_DEBUG if (m_end > m_buffer + tmpl_size) throw internal_error("ProtocolBuffer tried to write beyond scope of the buffer."); #endif } private: iterator m_position; iterator m_end; value_type m_buffer[tmpl_size]; }; template inline bool ProtocolBuffer::consume(difference_type v) { m_position += v; if (remaining()) return false; return true; } template inline uint16_t ProtocolBuffer::read_16() { #ifndef USE_ALIGNED uint16_t t = ntohs(*reinterpret_cast(m_position)); m_position += sizeof(uint16_t); return t; #else return read_int(); #endif } template inline uint16_t ProtocolBuffer::peek_16() { #ifndef USE_ALIGNED return ntohs(*reinterpret_cast(m_position)); #else return peek_int(); #endif } template inline uint32_t ProtocolBuffer::read_32() { #ifndef USE_ALIGNED uint32_t t = ntohl(*reinterpret_cast(m_position)); m_position += sizeof(uint32_t); return t; #else return read_int(); #endif } template inline uint32_t ProtocolBuffer::peek_32() { #ifndef USE_ALIGNED return ntohl(*reinterpret_cast(m_position)); #else return peek_int(); #endif } template template inline T ProtocolBuffer::read_int() { T t = T(); for (iterator last = m_position + sizeof(T); m_position != last; ++m_position) t = (t << 8) + *m_position; return t; } template template inline T ProtocolBuffer::peek_int() { T t = T(); for (iterator itr = m_position, last = m_position + sizeof(T); itr != last; ++itr) t = (t << 8) + *itr; return t; } template inline void ProtocolBuffer::write_16(uint16_t v) { #ifndef USE_ALIGNED *reinterpret_cast(m_end) = htons(v); m_end += sizeof(uint16_t); validate_end(); #else write_int(v); #endif } template inline void ProtocolBuffer::write_32(uint32_t v) { #ifndef USE_ALIGNED *reinterpret_cast(m_end) = htonl(v); m_end += sizeof(uint32_t); validate_end(); #else write_int(v); #endif } template inline void ProtocolBuffer::write_32_n(uint32_t v) { *reinterpret_cast(m_end) = v; m_end += sizeof(uint32_t); validate_end(); } template template void ProtocolBuffer::read_range(Out first, Out last) { for ( ; first != last; ++m_position, ++first) *first = *m_position; validate_position(); } template template void ProtocolBuffer::read_len(Out start, unsigned int len) { for ( ; len > 0; ++m_position, ++start, --len) *start = *m_position; validate_position(); } template template inline void ProtocolBuffer::write_int(T v) { for (iterator itr = m_end + sizeof(T); itr != m_end; v >>= 8) *(--itr) = v; m_end += sizeof(T); validate_end(); } template template void ProtocolBuffer::write_range(In first, In last) { for ( ; first != last; ++m_end, ++first) *m_end = *first; validate_end(); } template template void ProtocolBuffer::write_len(In start, unsigned int len) { for ( ; len > 0; ++m_end, ++start, --len) *m_end = *start; validate_end(); } template void ProtocolBuffer::move_unused() { std::memmove(begin(), position(), remaining()); set_end(remaining()); reset_position(); } } // namespace torrent #endif libtorrent-0.16.11/src/net/udns_library.cc0000644000000000000000000000141115175073411014055 #include "config.h" #define HAVE_INET_PTON_NTOP 1 #define HAVE_IPv6 1 #define HAVE_POLL 1 #undef HAVE_CONFIG_H #define register // TODO: Check if we can remove extern "C" and put this in a namespace. extern "C" { #include "net/udns/udns.h" #include "net/udns/udns_XtoX.c" #include "net/udns/udns_bl.c" #include "net/udns/udns_codes.c" #include "net/udns/udns_dn.c" #include "net/udns/udns_dntosp.c" #include "net/udns/udns_init.c" #include "net/udns/udns_jran.c" #include "net/udns/udns_misc.c" #include "net/udns/udns_parse.c" #include "net/udns/udns_resolver.c" #include "net/udns/udns_rr_a.c" #include "net/udns/udns_rr_mx.c" #include "net/udns/udns_rr_naptr.c" #include "net/udns/udns_rr_ptr.c" #include "net/udns/udns_rr_srv.c" #include "net/udns/udns_rr_txt.c" } libtorrent-0.16.11/src/net/throttle_list.cc0000644000000000000000000001364615175073411014275 #include "config.h" #include #include #include #include "throttle_list.h" #include "throttle_node.h" namespace torrent { bool ThrottleList::is_active(const ThrottleNode* node) const { return std::find(begin(), const_iterator(m_splitActive), node) != m_splitActive; } bool ThrottleList::is_inactive(const ThrottleNode* node) const { return std::find(const_iterator(m_splitActive), end(), node) != end(); } bool ThrottleList::is_throttled(const ThrottleNode* node) const { return node->list_iterator() != end(); } // The quota already present in the node is preserved and unallocated // quota is transferred to the node. The node's quota will be less // than or equal to 'm_minChunkSize'. inline void ThrottleList::allocate_quota(ThrottleNode* node) { if (node->quota() >= m_minChunkSize) return; int quota = std::min(m_maxChunkSize - node->quota(), m_unallocatedQuota); node->set_quota(node->quota() + quota); m_outstandingQuota += quota; m_unallocatedQuota -= quota; } void ThrottleList::enable() { if (m_enabled) return; m_enabled = true; if (!empty() && m_splitActive == begin()) throw internal_error("ThrottleList::enable() m_splitActive is invalid."); } void ThrottleList::disable() { if (!m_enabled) return; m_enabled = false; m_outstandingQuota = 0; m_unallocatedQuota = 0; m_unusedUnthrottledQuota = 0; std::for_each(begin(), end(), std::mem_fn(&ThrottleNode::clear_quota)); std::for_each(m_splitActive, end(), std::mem_fn(&ThrottleNode::activate)); m_splitActive = end(); } int32_t ThrottleList::update_quota(uint32_t quota) { if (!m_enabled) throw internal_error("ThrottleList::update_quota(...) called but the object is not enabled."); // Distribute new quota to unthrottled quota first, and use // left-over unthrottled quota from last turn to be allocated // to throttled nodes this turn. // When distributing, we include the unallocated quota from the // previous turn. This will ensure that quota that was reclaimed // will have a chance of being used, even by those nodes that were // deactivated. m_unallocatedQuota += m_unusedUnthrottledQuota; m_unusedUnthrottledQuota = quota; // Add remaining to the next, even when less than activate border. while (m_splitActive != end()) { allocate_quota(*m_splitActive); if ((*m_splitActive)->quota() < m_minChunkSize) break; (*m_splitActive)->activate(); m_splitActive++; } // Use 'quota' as an upper bound to avoid accumulating unused quota // over time. Return actually used amount of quota. int32_t used = quota; if (m_unallocatedQuota > quota) { used -= m_unallocatedQuota - quota; m_unallocatedQuota = quota; } return used; } uint32_t ThrottleList::node_quota(ThrottleNode* node) const { if (!m_enabled) { // Returns max for signed integer to ensure we don't overflow // calculations. return std::numeric_limits::max(); } else if (!is_active(node)) { throw internal_error(is_inactive(node) ? "ThrottleList::node_quota(...) called on an inactive node." : "ThrottleList::node_quota(...) could not find node."); } else if (node->quota() + m_unallocatedQuota >= m_minChunkSize) { return node->quota() + m_unallocatedQuota; } else { return 0; } } void ThrottleList::add_rate(uint32_t used) { m_rateSlow.insert(used); m_rateAdded += used; } uint32_t ThrottleList::node_used(ThrottleNode* node, uint32_t used) { add_rate(used); node->rate()->insert(used); if (used == 0 || !m_enabled || node->list_iterator() == end()) return used; uint32_t quota = std::min(used, node->quota()); if (quota > m_outstandingQuota) throw internal_error("ThrottleList::node_used(...) used too much quota."); node->set_quota(node->quota() - quota); m_outstandingQuota -= quota; m_unallocatedQuota -= std::min(used - quota, m_unallocatedQuota); return used; } uint32_t ThrottleList::node_used_unthrottled(uint32_t used) { add_rate(used); // Use what we can from the unthrottled quota, // if node used too much borrow from throttled quota. uint32_t avail = std::min(used, m_unusedUnthrottledQuota); m_unusedUnthrottledQuota -= avail; m_unallocatedQuota -= std::min(used - avail, m_unallocatedQuota); return used; } void ThrottleList::node_deactivate(ThrottleNode* node) { if (!is_active(node)) throw internal_error(is_inactive(node) ? "ThrottleList::node_deactivate(...) called on an inactive node." : "ThrottleList::node_deactivate(...) could not find node."); base_type::splice(end(), *this, node->list_iterator()); if (m_splitActive == end()) m_splitActive = node->list_iterator(); } void ThrottleList::insert(ThrottleNode* node) { if (node->list_iterator() != end()) return; if (!m_enabled) { // Add to waiting queue. node->set_list_iterator(base_type::insert(end(), node)); node->clear_quota(); } else { // Add before the active split, so if we only need to decrement // m_splitActive to change the queue it is in. node->set_list_iterator(base_type::insert(m_splitActive, node)); allocate_quota(node); } m_size++; } void ThrottleList::erase(ThrottleNode* node) { if (node->list_iterator() == end()) return; if (m_size == 0) throw internal_error("ThrottleList::erase(...) called on an empty list."); // Do we need an if-statement here? if (node->quota() != 0) { if (node->quota() > m_outstandingQuota) throw internal_error("ThrottleList::erase(...) node->quota() > m_outstandingQuota."); m_outstandingQuota -= node->quota(); m_unallocatedQuota += node->quota(); } if (node->list_iterator() == m_splitActive) m_splitActive = base_type::erase(node->list_iterator()); else base_type::erase(node->list_iterator()); node->clear_quota(); node->set_list_iterator(end()); m_size--; } } // namespace torrent libtorrent-0.16.11/src/net/udns/0000755000000000000000000000000015175073434012112 5libtorrent-0.16.11/src/net/udns/udns_misc.c0000644000000000000000000000410215175073411014152 /* udns_misc.c miscellaneous routines Copyright (C) 2005 Michael Tokarev This file is part of UDNS library, an async DNS stub resolver. 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, in file named COPYING.LGPL; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "udns.h" int dns_findname(const struct dns_nameval *nv, const char *name) { register const char *a, *b; for(; nv->name; ++nv) for(a = name, b = nv->name; ; ++a, ++b) if (DNS_DNUC(*a) != *b) break; else if (!*a) return nv->val; return -1; } const char *_dns_format_code(char *buf, const char *prefix, int code) { char *bp = buf; unsigned c, n; do *bp++ = DNS_DNUC(*prefix); while(*++prefix); *bp++ = '#'; if (code < 0) code = -code, *bp++ = '-'; n = 0; c = code; do ++n; while((c /= 10)); c = code; bp[n--] = '\0'; do bp[n--] = c % 10 + '0'; while((c /= 10)); return buf; } const char *dns_strerror(int err) { if (err >= 0) return "successeful completion"; switch(err) { case DNS_E_TEMPFAIL: return "temporary failure in name resolution"; case DNS_E_PROTOCOL: return "protocol error"; case DNS_E_NXDOMAIN: return "domain name does not exist"; case DNS_E_NODATA: return "valid domain but no data of requested type"; case DNS_E_NOMEM: return "out of memory"; case DNS_E_BADQUERY: return "malformed query"; default: return "unknown error"; } } const char *dns_version(void) { return UDNS_VERSION; } libtorrent-0.16.11/src/net/udns/dnsget.c0000644000000000000000000005216715175073411013470 /* dnsget.c simple host/dig-like application using UDNS library Copyright (C) 2005 Michael Tokarev This file is part of UDNS library, an async DNS stub resolver. 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, in file named COPYING.LGPL; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #ifdef WINDOWS #include #include #else #include #include #include #include #include #endif #include #include #include #include #include #include #include "udns.h" #ifndef HAVE_GETOPT # include "getopt.c" #endif #ifndef AF_INET6 # define AF_INET6 10 #endif static char *progname; static int verbose = 1; static int errors; static int notfound; /* verbosity level: * <0 - bare result * 0 - bare result and error messages * 1 - readable result * 2 - received packet contents and `trying ...' stuff * 3 - sent and received packet contents */ static void die(int errnum, const char *fmt, ...) { va_list ap; fprintf(stderr, "%s: ", progname); va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); if (errnum) fprintf(stderr, ": %s\n", strerror(errnum)); else putc('\n', stderr); fflush(stderr); exit(1); } static const char *dns_xntop(int af, const void *src) { static char buf[6*5+4*4]; return dns_ntop(af, src, buf, sizeof(buf)); } struct query { const char *name; /* original query string */ unsigned char *dn; /* the DN being looked up */ enum dns_type qtyp; /* type of the query */ }; static void query_free(struct query *q) { free(q->dn); free(q); } static struct query * query_new(const char *name, const unsigned char *dn, enum dns_type qtyp) { struct query *q = malloc(sizeof(*q)); unsigned l = dns_dnlen(dn); unsigned char *cdn = malloc(l); if (!q || !cdn) die(0, "out of memory"); memcpy(cdn, dn, l); q->name = name; q->dn = cdn; q->qtyp = qtyp; return q; } static enum dns_class qcls = DNS_C_IN; static void dnserror(struct query *q, int errnum) { if (verbose >= 0) fprintf(stderr, "%s: unable to lookup %s record for %s: %s\n", progname, dns_typename(q->qtyp), dns_dntosp(q->dn), dns_strerror(errnum)); if (errnum == DNS_E_NXDOMAIN || errnum == DNS_E_NODATA) ++notfound; else ++errors; query_free(q); } static const unsigned char * printtxt(const unsigned char *c) { unsigned n = *c++; const unsigned char *e = c + n; if (verbose > 0) while(c < e) { if (*c < ' ' || *c >= 127) printf("\\%03u", *c); else if (*c == '\\' || *c == '"') printf("\\%c", *c); else putchar(*c); ++c; } else fwrite(c, n, 1, stdout); return e; } static void printhex(const unsigned char *c, const unsigned char *e) { while(c < e) printf("%02x", *c++); } static unsigned char to_b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; static void printb64(const unsigned char *c, const unsigned char *e) { while(c < e) { putchar(to_b64[c[0] >> 2]); if (c+1 < e) { putchar(to_b64[(c[0] & 0x3) << 4 | c[1] >> 4]); if (c+2 < e) { putchar(to_b64[(c[1] & 0xf) << 2 | c[2] >> 6]); putchar(to_b64[c[2] & 0x3f]); } else { putchar(to_b64[(c[1] & 0xf) << 2]); putchar('='); break; } } else { putchar(to_b64[(c[0] & 0x3) << 4]); putchar('='); putchar('='); break; } c += 3; } } static void printdate(time_t time) { struct tm *tm = gmtime(&time); printf("%04d%02d%02d%02d%02d%02d", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); } static void printrr(const struct dns_parse *p, struct dns_rr *rr) { const unsigned char *pkt = p->dnsp_pkt; const unsigned char *end = p->dnsp_end; const unsigned char *dptr = rr->dnsrr_dptr; const unsigned char *dend = rr->dnsrr_dend; unsigned char *dn = rr->dnsrr_dn; const unsigned char *c; unsigned n; if (verbose > 0) { if (verbose > 1) { if (!p->dnsp_rrl && !rr->dnsrr_dn[0] && rr->dnsrr_typ == DNS_T_OPT) { printf(";EDNS%d OPT record (UDPsize: %d, ERcode: %d, Flags: 0x%02x): %d bytes\n", (rr->dnsrr_ttl>>16) & 0xff, /* version */ rr->dnsrr_cls, /* udp size */ (rr->dnsrr_ttl>>24) & 0xff, /* extended rcode */ rr->dnsrr_ttl & 0xffff, /* flags */ rr->dnsrr_dsz); return; } n = printf("%s.", dns_dntosp(rr->dnsrr_dn)); printf("%s%u\t%s\t%s\t", n > 15 ? "\t" : n > 7 ? "\t\t" : "\t\t\t", rr->dnsrr_ttl, dns_classname(rr->dnsrr_cls), dns_typename(rr->dnsrr_typ)); } else printf("%s. %s ", dns_dntosp(rr->dnsrr_dn), dns_typename(rr->dnsrr_typ)); } switch(rr->dnsrr_typ) { case DNS_T_CNAME: case DNS_T_PTR: case DNS_T_NS: case DNS_T_MB: case DNS_T_MD: case DNS_T_MF: case DNS_T_MG: case DNS_T_MR: if (dns_getdn(pkt, &dptr, end, dn, DNS_MAXDN) <= 0) goto xperr; printf("%s.", dns_dntosp(dn)); break; case DNS_T_A: if (rr->dnsrr_dsz != 4) goto xperr; printf("%d.%d.%d.%d", dptr[0], dptr[1], dptr[2], dptr[3]); break; case DNS_T_AAAA: if (rr->dnsrr_dsz != 16) goto xperr; printf("%s", dns_xntop(AF_INET6, dptr)); break; case DNS_T_MX: c = dptr + 2; if (dns_getdn(pkt, &c, end, dn, DNS_MAXDN) <= 0 || c != dend) goto xperr; printf("%d %s.", dns_get16(dptr), dns_dntosp(dn)); break; case DNS_T_TXT: /* first verify it */ for(c = dptr; c < dend; c += n) { n = *c++; if (c + n > dend) goto xperr; } c = dptr; n = 0; while (c < dend) { if (verbose > 0) printf(n++ ? "\" \"":"\""); c = printtxt(c); } if (verbose > 0) putchar('"'); break; case DNS_T_HINFO: /* CPU, OS */ c = dptr; n = *c++; if ((c += n) >= dend) goto xperr; n = *c++; if ((c += n) != dend) goto xperr; c = dptr; if (verbose > 0) putchar('"'); c = printtxt(c); if (verbose > 0) printf("\" \""); else putchar(' '); printtxt(c); if (verbose > 0) putchar('"'); break; case DNS_T_WKS: c = dptr; if (dptr + 4 + 2 >= end) goto xperr; printf("%s %d", dns_xntop(AF_INET, dptr), dptr[4]); c = dptr + 5; for (n = 0; c < dend; ++c, n += 8) { if (*c) { unsigned b; for (b = 0; b < 8; ++b) if (*c & (1 << (7-b))) printf(" %d", n + b); } } break; case DNS_T_SRV: /* prio weight port targetDN */ c = dptr; c += 2 + 2 + 2; if (dns_getdn(pkt, &c, end, dn, DNS_MAXDN) <= 0 || c != dend) goto xperr; c = dptr; printf("%d %d %d %s.", dns_get16(c+0), dns_get16(c+2), dns_get16(c+4), dns_dntosp(dn)); break; case DNS_T_NAPTR: /* order pref flags serv regexp repl */ c = dptr; c += 4; /* order, pref */ for (n = 0; n < 3; ++n) if (c >= dend) goto xperr; else c += *c + 1; if (dns_getdn(pkt, &c, end, dn, DNS_MAXDN) <= 0 || c != dend) goto xperr; c = dptr; printf("%u %u", dns_get16(c+0), dns_get16(c+2)); c += 4; for(n = 0; n < 3; ++n) { putchar(' '); if (verbose > 0) putchar('"'); c = printtxt(c); if (verbose > 0) putchar('"'); } printf(" %s.", dns_dntosp(dn)); break; case DNS_T_KEY: case DNS_T_DNSKEY: /* flags(2) proto(1) algo(1) pubkey */ case DNS_T_DS: case DNS_T_DLV: /* ktag(2) proto(1) algo(1) pubkey */ c = dptr; if (c + 2 + 1 + 1 > dend) goto xperr; printf("%d %d %d", dns_get16(c), c[2], c[3]); c += 2 + 1 + 1; if (c < dend) { putchar(' '); printb64(c, dend); } break; case DNS_T_SIG: case DNS_T_RRSIG: /* type(2) algo(1) labels(1) ottl(4) sexp(4) sinc(4) tag(2) sdn sig */ c = dptr; c += 2 + 1 + 1 + 4 + 4 + 4 + 2; if (dns_getdn(pkt, &c, end, dn, DNS_MAXDN) <= 0) goto xperr; printf("%s %u %u %u ", dns_typename(dns_get16(dptr)), dptr[2], dptr[3], dns_get32(dptr+4)); printdate(dns_get32(dptr+8)); putchar(' '); printdate(dns_get32(dptr+12)); printf(" %d %s. ", dns_get16(dptr+10), dns_dntosp(dn)); printb64(c, dend); break; case DNS_T_SSHFP: /* algo(1), fp type(1), fp... */ if (dend < dptr + 3) goto xperr; printf("%u %u ", dptr[0], dptr[1]); /* algo, fp type */ printhex(dptr + 2, dend); break; #if 0 /* unused RR types? */ case DNS_T_NSEC: /* nextDN bitmaps */ c = dptr; if (dns_getdn(pkt, &c, end, dn, DNS_MAXDN) <= 0) goto xperr; printf("%s.", dns_dntosp(dn)); unfinished. break; #endif case DNS_T_SOA: c = dptr; if (dns_getdn(pkt, &c, end, dn, DNS_MAXDN) <= 0 || dns_getdn(pkt, &c, end, dn, DNS_MAXDN) <= 0 || c + 4*5 != dend) goto xperr; dns_getdn(pkt, &dptr, end, dn, DNS_MAXDN); printf("%s. ", dns_dntosp(dn)); dns_getdn(pkt, &dptr, end, dn, DNS_MAXDN); printf("%s. ", dns_dntosp(dn)); printf("%u %u %u %u %u", dns_get32(dptr), dns_get32(dptr+4), dns_get32(dptr+8), dns_get32(dptr+12), dns_get32(dptr+16)); break; case DNS_T_MINFO: c = dptr; if (dns_getdn(pkt, &c, end, dn, DNS_MAXDN) <= 0 || dns_getdn(pkt, &c, end, dn, DNS_MAXDN) <= 0 || c != dend) goto xperr; dns_getdn(pkt, &dptr, end, dn, DNS_MAXDN); printf("%s. ", dns_dntosp(dn)); dns_getdn(pkt, &dptr, end, dn, DNS_MAXDN); printf("%s.", dns_dntosp(dn)); break; case DNS_T_NULL: default: printhex(dptr, dend); break; } putchar('\n'); return; xperr: printf("\n"); ++errors; } static int printsection(struct dns_parse *p, int nrr, const char *sname) { struct dns_rr rr; int r; if (!nrr) return 0; if (verbose > 1) printf("\n;; %s section (%d):\n", sname, nrr); p->dnsp_rrl = nrr; while((r = dns_nextrr(p, &rr)) > 0) printrr(p, &rr); if (r < 0) printf("<>\n"); return r; } /* dbgcb will only be called if verbose > 1 */ static void dbgcb(int code, const struct sockaddr *sa, unsigned slen, const unsigned char *pkt, int r, const struct dns_query *unused_q, void *unused_data) { struct dns_parse p; const unsigned char *cur, *end; int numqd; (void)unused_q; (void)unused_data; /* avoid compiler warning */ if (code > 0) { printf(";; trying %s.\n", dns_dntosp(dns_payload(pkt))); printf(";; sending %d bytes query to ", r); } else printf(";; received %d bytes response from ", r); if (sa->sa_family == AF_INET && slen >= sizeof(struct sockaddr_in)) printf("%s port %d\n", dns_xntop(AF_INET, &((struct sockaddr_in*)sa)->sin_addr), htons(((struct sockaddr_in*)sa)->sin_port)); #ifdef HAVE_IPv6 else if (sa->sa_family == AF_INET6 && slen >= sizeof(struct sockaddr_in6)) printf("%s port %d\n", dns_xntop(AF_INET6, &((struct sockaddr_in6*)sa)->sin6_addr), htons(((struct sockaddr_in6*)sa)->sin6_port)); #endif else printf("<>\n", sa->sa_family); if (code > 0 && verbose < 3) { putchar('\n'); return; } if (code == -2) printf(";; reply from unexpected source\n"); if (code == -5) printf(";; reply to a query we didn't sent (or old)\n"); if (r < DNS_HSIZE) { printf(";; short packet (%d bytes)\n", r); return; } if (dns_opcode(pkt) != 0) printf(";; unexpected opcode %d\n", dns_opcode(pkt)); if (dns_tc(pkt) != 0) printf(";; warning: TC bit set, probably incomplete reply\n"); printf(";; ->>HEADER<<- opcode: "); switch(dns_opcode(pkt)) { case 0: printf("QUERY"); break; case 1: printf("IQUERY"); break; case 2: printf("STATUS"); break; default: printf("UNKNOWN(%u)", dns_opcode(pkt)); break; } printf(", status: %s, id: %d, size: %d\n;; flags:", dns_rcodename(dns_rcode(pkt)), dns_qid(pkt), r); if (dns_qr(pkt)) printf(" qr"); if (dns_aa(pkt)) printf(" aa"); if (dns_tc(pkt)) printf(" tc"); if (dns_rd(pkt)) printf(" rd"); if (dns_ra(pkt)) printf(" ra"); /* if (dns_z(pkt)) printf(" z"); only one reserved bit left */ if (dns_ad(pkt)) printf(" ad"); if (dns_cd(pkt)) printf(" cd"); numqd = dns_numqd(pkt); printf("; QUERY: %d, ANSWER: %d, AUTHORITY: %d, ADDITIONAL: %d\n", numqd, dns_numan(pkt), dns_numns(pkt), dns_numar(pkt)); if (numqd != 1) printf(";; unexpected number of entries in QUERY section: %d\n", numqd); printf("\n;; QUERY SECTION (%d):\n", numqd); cur = dns_payload(pkt); end = pkt + r; while(numqd--) { if (dns_getdn(pkt, &cur, end, p.dnsp_dnbuf, DNS_MAXDN) <= 0 || cur + 4 > end) { printf("; invalid query section\n"); return; } r = printf(";%s.", dns_dntosp(p.dnsp_dnbuf)); printf("%s%s\t%s\n", r > 23 ? "\t" : r > 15 ? "\t\t" : r > 7 ? "\t\t\t" : "\t\t\t\t", dns_classname(dns_get16(cur+2)), dns_typename(dns_get16(cur))); cur += 4; } p.dnsp_pkt = pkt; p.dnsp_cur = p.dnsp_ans = cur; p.dnsp_end = end; p.dnsp_qdn = NULL; p.dnsp_qcls = 0; p.dnsp_qtyp = 0; p.dnsp_ttl = 0xffffffffu; p.dnsp_nrr = 0; r = printsection(&p, dns_numan(pkt), "ANSWER"); if (r == 0) r = printsection(&p, dns_numns(pkt), "AUTHORITY"); if (r == 0) r = printsection(&p, dns_numar(pkt), "ADDITIONAL"); putchar('\n'); } static void dnscb(struct dns_ctx *ctx, void *result, void *data) { int r = dns_status(ctx); struct query *q = data; struct dns_parse p; struct dns_rr rr; unsigned nrr; unsigned char dn[DNS_MAXDN]; const unsigned char *pkt, *cur, *end; if (!result) { dnserror(q, r); return; } pkt = result; end = pkt + r; cur = dns_payload(pkt); dns_getdn(pkt, &cur, end, dn, sizeof(dn)); dns_initparse(&p, NULL, pkt, cur, end); p.dnsp_qcls = 0; p.dnsp_qtyp = 0; nrr = 0; while((r = dns_nextrr(&p, &rr)) > 0) { if (!dns_dnequal(dn, rr.dnsrr_dn)) continue; if ((qcls == DNS_C_ANY || qcls == rr.dnsrr_cls) && (q->qtyp == DNS_T_ANY || q->qtyp == rr.dnsrr_typ)) ++nrr; else if (rr.dnsrr_typ == DNS_T_CNAME && !nrr) { if (dns_getdn(pkt, &rr.dnsrr_dptr, end, p.dnsp_dnbuf, sizeof(p.dnsp_dnbuf)) <= 0 || rr.dnsrr_dptr != rr.dnsrr_dend) { r = DNS_E_PROTOCOL; break; } else { if (verbose == 1) { printf("%s.", dns_dntosp(dn)); printf(" CNAME %s.\n", dns_dntosp(p.dnsp_dnbuf)); } dns_dntodn(p.dnsp_dnbuf, dn, sizeof(dn)); } } } if (!r && !nrr) r = DNS_E_NODATA; if (r < 0) { dnserror(q, r); free(result); return; } if (verbose < 2) { /* else it is already printed by dbgfn */ dns_rewind(&p, NULL); p.dnsp_qtyp = q->qtyp == DNS_T_ANY ? 0 : q->qtyp; p.dnsp_qcls = qcls == DNS_C_ANY ? 0 : qcls; while(dns_nextrr(&p, &rr)) printrr(&p, &rr); } free(result); query_free(q); } int main(int argc, char **argv) { int i; int fd; fd_set fds; struct timeval tv; time_t now; char *ns[DNS_MAXSERV]; int nns = 0; struct query *q; enum dns_type qtyp = 0; struct dns_ctx *nctx = NULL; int flags = 0; if (!(progname = strrchr(argv[0], '/'))) progname = argv[0]; else argv[0] = ++progname; if (argc <= 1) die(0, "try `%s -h' for help", progname); if (dns_init(NULL, 0) < 0 || !(nctx = dns_new(NULL))) die(errno, "unable to initialize dns library"); /* we keep two dns contexts: one may be needed to resolve * nameservers if given as names, using default options. */ while((i = getopt(argc, argv, "vqt:c:an:o:f:h")) != EOF) switch(i) { case 'v': ++verbose; break; case 'q': --verbose; break; case 't': if (optarg[0] == '*' && !optarg[1]) i = DNS_T_ANY; else if ((i = dns_findtypename(optarg)) <= 0) die(0, "unrecognized query type `%s'", optarg); qtyp = i; break; case 'c': if (optarg[0] == '*' && !optarg[1]) i = DNS_C_ANY; else if ((i = dns_findclassname(optarg)) < 0) die(0, "unrecognized query class `%s'", optarg); qcls = i; break; case 'a': qtyp = DNS_T_ANY; ++verbose; break; case 'n': if (nns >= DNS_MAXSERV) die(0, "too many nameservers, %d max", DNS_MAXSERV); ns[nns++] = optarg; break; case 'o': case 'f': { char *opt; const char *const delim = " \t,;"; for(opt = strtok(optarg, delim); opt != NULL; opt = strtok(NULL, delim)) { if (dns_set_opts(NULL, optarg) == 0) ; else if (strcmp(opt, "aa") == 0) flags |= DNS_AAONLY; else if (strcmp(optarg, "nord") == 0) flags |= DNS_NORD; else if (strcmp(optarg, "dnssec") == 0) flags |= DNS_SET_DO; else if (strcmp(optarg, "do") == 0) flags |= DNS_SET_DO; else if (strcmp(optarg, "cd") == 0) flags |= DNS_SET_CD; else die(0, "invalid option: `%s'", opt); } break; } case 'h': printf( "%s: simple DNS query tool (using udns version %s)\n" "Usage: %s [options] domain-name...\n" "where options are:\n" " -h - print this help and exit\n" " -v - be more verbose\n" " -q - be less verbose\n" " -t type - set query type (A, AAAA, PTR etc)\n" " -c class - set query class (IN (default), CH, HS, *)\n" " -a - equivalent to -t ANY -v\n" " -n ns - use given nameserver(s) instead of default\n" " (may be specified multiple times)\n" " -o opt,opt,... (comma- or space-separated list,\n" " may be specified more than once):\n" " set resovler options (the same as setting $RES_OPTIONS):\n" " timeout:sec - initial query timeout\n" " attempts:num - number of attempt to resovle a query\n" " ndots:num - if name has more than num dots, lookup it before search\n" " port:num - port number for queries instead of default 53\n" " udpbuf:num - size of UDP buffer (use EDNS0 if >512)\n" " or query flags:\n" " aa,nord,dnssec,do,cd - set query flag (auth-only, no recursion,\n" " enable DNSSEC (DNSSEC Ok), check disabled)\n" , progname, dns_version(), progname); return 0; default: die(0, "try `%s -h' for help", progname); } argc -= optind; argv += optind; if (!argc) die(0, "no name(s) to query specified"); if (nns) { /* if nameservers given as names, resolve them. * We only allow IPv4 nameservers as names for now. * Ok, it is easy enouth to try both AAAA and A, * but the question is what to do by default. */ struct sockaddr_in sin; int j, r = 0, opened = 0; memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons(dns_set_opt(NULL, DNS_OPT_PORT, -1)); dns_add_serv(NULL, NULL); for(i = 0; i < nns; ++i) { if (dns_pton(AF_INET, ns[i], &sin.sin_addr) <= 0) { struct dns_rr_a4 *rr; if (!opened) { if (dns_open(nctx) < 0) die(errno, "unable to initialize dns context"); opened = 1; } rr = dns_resolve_a4(nctx, ns[i], 0); if (!rr) die(0, "unable to resolve nameserver %s: %s", ns[i], dns_strerror(dns_status(nctx))); for(j = 0; j < rr->dnsa4_nrr; ++j) { sin.sin_addr = rr->dnsa4_addr[j]; if ((r = dns_add_serv_s(NULL, (struct sockaddr *)&sin)) < 0) break; } free(rr); } else r = dns_add_serv_s(NULL, (struct sockaddr *)&sin); if (r < 0) die(errno, "unable to add nameserver %s", dns_xntop(AF_INET, &sin.sin_addr)); } } dns_free(nctx); fd = dns_open(NULL); if (fd < 0) die(errno, "unable to initialize dns context"); if (verbose > 1) dns_set_dbgfn(NULL, dbgcb); if (flags) dns_set_opt(NULL, DNS_OPT_FLAGS, flags); for (i = 0; i < argc; ++i) { char *name = argv[i]; union { struct in_addr addr; struct in6_addr addr6; } a; unsigned char dn[DNS_MAXDN]; enum dns_type l_qtyp = 0; int abs; if (dns_pton(AF_INET, name, &a.addr) > 0) { dns_a4todn(&a.addr, 0, dn, sizeof(dn)); l_qtyp = DNS_T_PTR; abs = 1; } #ifdef HAVE_IPv6 else if (dns_pton(AF_INET6, name, &a.addr6) > 0) { dns_a6todn(&a.addr6, 0, dn, sizeof(dn)); l_qtyp = DNS_T_PTR; abs = 1; } #endif else if (!dns_ptodn(name, strlen(name), dn, sizeof(dn), &abs)) die(0, "invalid name `%s'\n", name); else l_qtyp = DNS_T_A; if (qtyp) l_qtyp = qtyp; q = query_new(name, dn, l_qtyp); if (abs) abs = DNS_NOSRCH; if (!dns_submit_dn(NULL, dn, qcls, l_qtyp, abs, 0, dnscb, q)) dnserror(q, dns_status(NULL)); } FD_ZERO(&fds); now = 0; while((i = dns_timeouts(NULL, -1, now)) > 0) { FD_SET(fd, &fds); tv.tv_sec = i; tv.tv_usec = 0; i = select(fd+1, &fds, 0, 0, &tv); now = time(NULL); if (i > 0) dns_ioevent(NULL, now); } return errors ? 1 : notfound ? 100 : 0; } libtorrent-0.16.11/src/net/udns/udns_rr_naptr.c0000644000000000000000000000763615175073411015065 /* udns_rr_naptr.c parse/query NAPTR IN records Copyright (C) 2005 Michael Tokarev Copyright (C) 2006 Mikael Magnusson This file is part of UDNS library, an async DNS stub resolver. 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, in file named COPYING.LGPL; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include "udns.h" /* Get a single string for NAPTR record, pretty much like a DN label. * String length is in first byte in *cur, so it can't be >255. */ static int dns_getstr(dnscc_t **cur, dnscc_t *ep, char *buf) { unsigned l; dnscc_t *cp = *cur; l = *cp++; if (cp + l > ep) return DNS_E_PROTOCOL; if (buf) { memcpy(buf, cp, l); buf[l] = '\0'; } cp += l; *cur = cp; return l + 1; } int dns_parse_naptr(dnscc_t *qdn, dnscc_t *pkt, dnscc_t *cur, dnscc_t *end, void **result) { struct dns_rr_naptr *ret; struct dns_parse p; struct dns_rr rr; int r, l; char *sp; dnsc_t dn[DNS_MAXDN]; assert(dns_get16(cur+2) == DNS_C_IN && dns_get16(cur+0) == DNS_T_NAPTR); /* first, validate the answer and count size of the result */ l = 0; dns_initparse(&p, qdn, pkt, cur, end); while((r = dns_nextrr(&p, &rr)) > 0) { int i; dnscc_t *ep = rr.dnsrr_dend; /* first 4 bytes: order & preference */ cur = rr.dnsrr_dptr + 4; /* flags, services and regexp */ for (i = 0; i < 3; i++) { r = dns_getstr(&cur, ep, NULL); if (r < 0) return r; l += r; } /* replacement */ r = dns_getdn(pkt, &cur, end, dn, sizeof(dn)); if (r <= 0 || cur != rr.dnsrr_dend) return DNS_E_PROTOCOL; l += dns_dntop_size(dn); } if (r < 0) return DNS_E_PROTOCOL; if (!p.dnsp_nrr) return DNS_E_NODATA; /* next, allocate and set up result */ l += dns_stdrr_size(&p); ret = (struct dns_rr_naptr *)malloc(sizeof(*ret) + sizeof(struct dns_naptr) * p.dnsp_nrr + l); if (!ret) return DNS_E_NOMEM; ret->dnsnaptr_nrr = p.dnsp_nrr; ret->dnsnaptr_naptr = (struct dns_naptr *)(ret+1); /* and 3rd, fill in result, finally */ sp = (char*)(&ret->dnsnaptr_naptr[p.dnsp_nrr]); for (dns_rewind(&p, qdn), r = 0; dns_nextrr(&p, &rr); ++r) { cur = rr.dnsrr_dptr; ret->dnsnaptr_naptr[r].order = dns_get16(cur); cur += 2; ret->dnsnaptr_naptr[r].preference = dns_get16(cur); cur += 2; sp += dns_getstr(&cur, end, (ret->dnsnaptr_naptr[r].flags = sp)); sp += dns_getstr(&cur, end, (ret->dnsnaptr_naptr[r].service = sp)); sp += dns_getstr(&cur, end, (ret->dnsnaptr_naptr[r].regexp = sp)); dns_getdn(pkt, &cur, end, dn, sizeof(dn)); sp += dns_dntop(dn, (ret->dnsnaptr_naptr[r].replacement = sp), DNS_MAXNAME); } dns_stdrr_finish((struct dns_rr_null *)ret, sp, &p); *result = ret; return 0; } struct dns_query * dns_submit_naptr(struct dns_ctx *ctx, const char *name, int flags, dns_query_naptr_fn *cbck, void *data) { return dns_submit_p(ctx, name, DNS_C_IN, DNS_T_NAPTR, flags, dns_parse_naptr, (dns_query_fn *)cbck, data); } struct dns_rr_naptr * dns_resolve_naptr(struct dns_ctx *ctx, const char *name, int flags) { return (struct dns_rr_naptr *) dns_resolve_p(ctx, name, DNS_C_IN, DNS_T_NAPTR, flags, dns_parse_naptr); } libtorrent-0.16.11/src/net/udns/udns_jran.c0000644000000000000000000000275115175073411014161 /* udns_jran.c: small non-cryptographic random number generator * taken from http://burtleburtle.net/bob/rand/smallprng.html * by Bob Jenkins, Public domain. */ #include "udns.h" #define rot32(x,k) (((x) << (k)) | ((x) >> (32-(k)))) #define rot64(x,k) (((x) << (k)) | ((x) >> (64-(k)))) #define tr32(x) ((x)&0xffffffffu) unsigned udns_jranval(struct udns_jranctx *x) { /* This routine can be made to work with either 32 or 64bit words - * if JRAN_32_64 is defined when compiling the file. * We use if() instead of #if since there's no good * portable way to check sizeof() in preprocessor without * introducing some ugly configure-time checks. * Most compilers will optimize the wrong branches away anyway. * By default it assumes 32bit integers */ #ifdef JRAN_32_64 if (sizeof(unsigned) == 4) { #endif unsigned e = tr32(x->a - rot32(x->b, 27)); x->a = tr32(x->b ^ rot32(x->c, 17)); x->b = tr32(x->c + x->d); x->c = tr32(x->d + e); x->d = tr32(e + x->a); #ifdef JRAN_32_64 } else if (sizeof(unsigned) == 8) { /* assuming it's 64bits */ unsigned e = x->a - rot64(x->b, 7); x->a = x->b ^ rot64(x->c, 13); x->b = x->c + rot64(x->d, 37); x->c = x->d + e; x->d = e + x->a; } else { unsigned e = 0; x->d = 1/e; /* bail */ } #endif return x->d; } void udns_jraninit(struct udns_jranctx *x, unsigned seed) { unsigned i; x->a = 0xf1ea5eed; x->b = x->c = x->d = seed; for (i = 0; i < 20; ++i) (void)udns_jranval(x); } libtorrent-0.16.11/src/net/udns/udns_resolver.c0000644000000000000000000012266515175073411015077 /* udns_resolver.c resolver stuff (main module) Copyright (C) 2005 Michael Tokarev This file is part of UDNS library, an async DNS stub resolver. 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, in file named COPYING.LGPL; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #ifdef WINDOWS # include /* includes */ # include /* needed for struct in6_addr */ #else # include # include # include # include # include # include # ifdef HAVE_POLL # include # else # ifdef HAVE_SYS_SELECT_H # include # endif # endif # ifdef HAVE_TIMES # include # endif # define closesocket(sock) close(sock) #endif /* !WINDOWS */ #include #include #include #include #include #include #include "udns.h" #ifndef EAFNOSUPPORT # define EAFNOSUPPORT EINVAL #endif #ifndef MSG_DONTWAIT # define MSG_DONTWAIT 0 #endif struct dns_qlist { struct dns_query *head, *tail; }; struct dns_query { struct dns_query *dnsq_next; /* double-linked list */ struct dns_query *dnsq_prev; unsigned dnsq_origdnl0; /* original query DN len w/o last 0 */ unsigned dnsq_flags; /* control flags for this query */ unsigned dnsq_servi; /* index of next server to try */ unsigned dnsq_servwait; /* bitmask: servers left to wait */ unsigned dnsq_servskip; /* bitmask: servers to skip */ unsigned dnsq_servnEDNS0; /* bitmask: servers refusing EDNS0 */ unsigned dnsq_try; /* number of tries made so far */ dnscc_t *dnsq_nxtsrch; /* next search pointer @dnsc_srchbuf */ time_t dnsq_deadline; /* when current try will expire */ dns_parse_fn *dnsq_parse; /* parse: raw => application */ dns_query_fn *dnsq_cbck; /* the callback to call when done */ void *dnsq_cbdata; /* user data for the callback */ #ifndef NDEBUG struct dns_ctx *dnsq_ctx; /* the resolver context */ #endif /* char fields at the end to avoid padding */ dnsc_t dnsq_id[2]; /* query ID */ dnsc_t dnsq_typcls[4]; /* requested RR type+class */ dnsc_t dnsq_dn[DNS_MAXDN+DNS_DNPAD]; /* the query DN +alignment */ }; /* working with dns_query lists */ static __inline void qlist_init(struct dns_qlist *list) { list->head = list->tail = NULL; } static __inline void qlist_remove(struct dns_qlist *list, struct dns_query *q) { if (q->dnsq_prev) q->dnsq_prev->dnsq_next = q->dnsq_next; else list->head = q->dnsq_next; if (q->dnsq_next) q->dnsq_next->dnsq_prev = q->dnsq_prev; else list->tail = q->dnsq_prev; } static __inline void qlist_add_head(struct dns_qlist *list, struct dns_query *q) { q->dnsq_next = list->head; if (list->head) list->head->dnsq_prev = q; else list->tail = q; list->head = q; q->dnsq_prev = NULL; } static __inline void qlist_insert_after(struct dns_qlist *list, struct dns_query *q, struct dns_query *prev) { if ((q->dnsq_prev = prev) != NULL) { if ((q->dnsq_next = prev->dnsq_next) != NULL) q->dnsq_next->dnsq_prev = q; else list->tail = q; prev->dnsq_next = q; } else qlist_add_head(list, q); } union sockaddr_ns { struct sockaddr sa; struct sockaddr_in sin; #ifdef HAVE_IPv6 struct sockaddr_in6 sin6; #endif }; #define sin_eq(a,b) \ ((a).sin_port == (b).sin_port && \ (a).sin_addr.s_addr == (b).sin_addr.s_addr) #define sin6_eq(a,b) \ ((a).sin6_port == (b).sin6_port && \ memcmp(&(a).sin6_addr, &(b).sin6_addr, sizeof(struct in6_addr)) == 0) struct dns_ctx { /* resolver context */ /* settings */ unsigned dnsc_flags; /* various flags */ unsigned dnsc_timeout; /* timeout (base value) for queries */ unsigned dnsc_ntries; /* number of retries */ unsigned dnsc_ndots; /* ndots to assume absolute name */ unsigned dnsc_port; /* default port (DNS_PORT) */ unsigned dnsc_udpbuf; /* size of UDP buffer */ /* array of nameserver addresses */ union sockaddr_ns dnsc_serv[DNS_MAXSERV]; unsigned dnsc_nserv; /* number of nameservers */ unsigned dnsc_salen; /* length of socket addresses */ dnsc_t dnsc_srchbuf[1024]; /* buffer for searchlist */ dnsc_t *dnsc_srchend; /* current end of srchbuf */ dns_utm_fn *dnsc_utmfn; /* register/cancel timer events */ void *dnsc_utmctx; /* user timer context for utmfn() */ time_t dnsc_utmexp; /* when user timer expires */ dns_dbgfn *dnsc_udbgfn; /* debugging function */ /* dynamic data */ struct udns_jranctx dnsc_jran; /* random number generator state */ unsigned dnsc_nextid; /* next queue ID to use if !0 */ int dnsc_udpsock; /* UDP socket */ struct dns_qlist dnsc_qactive; /* active list sorted by deadline */ int dnsc_nactive; /* number entries in dnsc_qactive */ dnsc_t *dnsc_pbuf; /* packet buffer (udpbuf size) */ int dnsc_qstatus; /* last query status value */ }; static const struct { const char *name; enum dns_opt opt; unsigned offset; unsigned min, max; } dns_opts[] = { #define opt(name,opt,field,min,max) \ {name,opt,offsetof(struct dns_ctx,field),min,max} opt("retrans", DNS_OPT_TIMEOUT, dnsc_timeout, 1,300), opt("timeout", DNS_OPT_TIMEOUT, dnsc_timeout, 1,300), opt("retry", DNS_OPT_NTRIES, dnsc_ntries, 1,50), opt("attempts", DNS_OPT_NTRIES, dnsc_ntries, 1,50), opt("ndots", DNS_OPT_NDOTS, dnsc_ndots, 0,1000), opt("port", DNS_OPT_PORT, dnsc_port, 1,0xffff), opt("udpbuf", DNS_OPT_UDPSIZE, dnsc_udpbuf, DNS_MAXPACKET,65536), #undef opt }; #define dns_ctxopt(ctx,idx) (*((unsigned*)(((char*)ctx)+dns_opts[idx].offset))) #define ISSPACE(x) (x == ' ' || x == '\t' || x == '\r' || x == '\n') struct dns_ctx dns_defctx; #define SETCTX(ctx) if (!ctx) ctx = &dns_defctx #define SETCTXINITED(ctx) SETCTX(ctx); assert(CTXINITED(ctx)) #define CTXINITED(ctx) (ctx->dnsc_flags & DNS_INITED) #define SETCTXFRESH(ctx) SETCTXINITED(ctx); assert(!CTXOPEN(ctx)) #define SETCTXINACTIVE(ctx) \ SETCTXINITED(ctx); assert(!ctx->dnsc_nactive) #define SETCTXOPEN(ctx) SETCTXINITED(ctx); assert(CTXOPEN(ctx)) #define CTXOPEN(ctx) (ctx->dnsc_udpsock >= 0) #if defined(NDEBUG) || !defined(DEBUG) #define dns_assert_ctx(ctx) #else static void dns_assert_ctx(const struct dns_ctx *ctx) { int nactive = 0; const struct dns_query *q; for(q = ctx->dnsc_qactive.head; q; q = q->dnsq_next) { assert(q->dnsq_ctx == ctx); assert(q == (q->dnsq_next ? q->dnsq_next->dnsq_prev : ctx->dnsc_qactive.tail)); assert(q == (q->dnsq_prev ? q->dnsq_prev->dnsq_next : ctx->dnsc_qactive.head)); ++nactive; } assert(nactive == ctx->dnsc_nactive); } #endif enum { DNS_INTERNAL = 0xffff, /* internal flags mask */ DNS_INITED = 0x0001, /* the context is initialized */ DNS_ASIS_DONE = 0x0002, /* search: skip the last as-is query */ DNS_SEEN_NODATA = 0x0004, /* search: NODATA has been received */ }; int dns_add_serv(struct dns_ctx *ctx, const char *serv) { union sockaddr_ns *sns; SETCTXFRESH(ctx); if (!serv) return (ctx->dnsc_nserv = 0); if (ctx->dnsc_nserv >= DNS_MAXSERV) return errno = ENFILE, -1; sns = &ctx->dnsc_serv[ctx->dnsc_nserv]; memset(sns, 0, sizeof(*sns)); if (dns_pton(AF_INET, serv, &sns->sin.sin_addr) > 0) { sns->sin.sin_family = AF_INET; return ++ctx->dnsc_nserv; } #ifdef HAVE_IPv6 if (dns_pton(AF_INET6, serv, &sns->sin6.sin6_addr) > 0) { sns->sin6.sin6_family = AF_INET6; return ++ctx->dnsc_nserv; } #endif errno = EINVAL; return -1; } int dns_add_serv_s(struct dns_ctx *ctx, const struct sockaddr *sa) { SETCTXFRESH(ctx); if (!sa) return (ctx->dnsc_nserv = 0); if (ctx->dnsc_nserv >= DNS_MAXSERV) return errno = ENFILE, -1; #ifdef HAVE_IPv6 else if (sa->sa_family == AF_INET6) ctx->dnsc_serv[ctx->dnsc_nserv].sin6 = *(struct sockaddr_in6*)sa; #endif else if (sa->sa_family == AF_INET) ctx->dnsc_serv[ctx->dnsc_nserv].sin = *(struct sockaddr_in*)sa; else return errno = EAFNOSUPPORT, -1; return ++ctx->dnsc_nserv; } int dns_set_opts(struct dns_ctx *ctx, const char *opts) { unsigned i, v; int err = 0; SETCTXINACTIVE(ctx); for(;;) { while(ISSPACE(*opts)) ++opts; if (!*opts) break; for(i = 0; ; ++i) { if (i >= sizeof(dns_opts)/sizeof(dns_opts[0])) { ++err; break; } v = strlen(dns_opts[i].name); if (strncmp(dns_opts[i].name, opts, v) != 0 || (opts[v] != ':' && opts[v] != '=')) continue; opts += v + 1; v = 0; if (*opts < '0' || *opts > '9') { ++err; break; } do v = v * 10 + (*opts++ - '0'); while (*opts >= '0' && *opts <= '9'); if (v < dns_opts[i].min) v = dns_opts[i].min; if (v > dns_opts[i].max) v = dns_opts[i].max; dns_ctxopt(ctx, i) = v; break; } while(*opts && !ISSPACE(*opts)) ++opts; } return err; } int dns_set_opt(struct dns_ctx *ctx, enum dns_opt opt, int val) { int prev; unsigned i; SETCTXINACTIVE(ctx); for(i = 0; i < sizeof(dns_opts)/sizeof(dns_opts[0]); ++i) { if (dns_opts[i].opt != opt) continue; prev = dns_ctxopt(ctx, i); if (val >= 0) { unsigned v = val; if (v < dns_opts[i].min || v > dns_opts[i].max) { errno = EINVAL; return -1; } dns_ctxopt(ctx, i) = v; } return prev; } if (opt == DNS_OPT_FLAGS) { prev = ctx->dnsc_flags & ~DNS_INTERNAL; if (val >= 0) ctx->dnsc_flags = (ctx->dnsc_flags & DNS_INTERNAL) | (val & ~DNS_INTERNAL); return prev; } errno = ENOSYS; return -1; } int dns_add_srch(struct dns_ctx *ctx, const char *srch) { int dnl; SETCTXINACTIVE(ctx); if (!srch) { memset(ctx->dnsc_srchbuf, 0, sizeof(ctx->dnsc_srchbuf)); ctx->dnsc_srchend = ctx->dnsc_srchbuf; return 0; } dnl = sizeof(ctx->dnsc_srchbuf) - (ctx->dnsc_srchend - ctx->dnsc_srchbuf) - 1; dnl = dns_sptodn(srch, ctx->dnsc_srchend, dnl); if (dnl > 0) ctx->dnsc_srchend += dnl; ctx->dnsc_srchend[0] = '\0'; /* we ensure the list is always ends at . */ if (dnl > 0) return 0; errno = EINVAL; return -1; } static void dns_drop_utm(struct dns_ctx *ctx) { if (ctx->dnsc_utmfn) ctx->dnsc_utmfn(NULL, -1, ctx->dnsc_utmctx); ctx->dnsc_utmctx = NULL; ctx->dnsc_utmexp = -1; } static void _dns_request_utm(struct dns_ctx *ctx, time_t now) { struct dns_query *q; time_t deadline; int timeout; q = ctx->dnsc_qactive.head; if (!q) deadline = -1, timeout = -1; else if (!now || q->dnsq_deadline <= now) deadline = 0, timeout = 0; else deadline = q->dnsq_deadline, timeout = (int)(deadline - now); if (ctx->dnsc_utmexp == deadline) return; ctx->dnsc_utmfn(ctx, timeout, ctx->dnsc_utmctx); ctx->dnsc_utmexp = deadline; } static __inline void dns_request_utm(struct dns_ctx *ctx, time_t now) { if (ctx->dnsc_utmfn) _dns_request_utm(ctx, now); } void dns_set_dbgfn(struct dns_ctx *ctx, dns_dbgfn *dbgfn) { SETCTXINITED(ctx); ctx->dnsc_udbgfn = dbgfn; } void dns_set_tmcbck(struct dns_ctx *ctx, dns_utm_fn *fn, void *data) { SETCTXINITED(ctx); dns_drop_utm(ctx); ctx->dnsc_utmfn = fn; ctx->dnsc_utmctx = data; if (CTXOPEN(ctx)) dns_request_utm(ctx, 0); } static unsigned dns_nonrandom_32(void) { #ifdef WINDOWS FILETIME ft; GetSystemTimeAsFileTime(&ft); return ft.dwLowDateTime; #else struct timeval tv; gettimeofday(&tv, NULL); return tv.tv_usec; #endif } /* This is historic deprecated API */ UDNS_API unsigned dns_random16(void); unsigned dns_random16(void) { unsigned x = dns_nonrandom_32(); return (x ^ (x >> 16)) & 0xffff; } static void dns_init_rng(struct dns_ctx *ctx) { udns_jraninit(&ctx->dnsc_jran, dns_nonrandom_32()); ctx->dnsc_nextid = 0; } void dns_close(struct dns_ctx *ctx) { struct dns_query *q, *p; SETCTX(ctx); if (CTXINITED(ctx)) { if (ctx->dnsc_udpsock >= 0) closesocket(ctx->dnsc_udpsock); ctx->dnsc_udpsock = -1; if (ctx->dnsc_pbuf) free(ctx->dnsc_pbuf); ctx->dnsc_pbuf = NULL; q = ctx->dnsc_qactive.head; while((p = q) != NULL) { q = q->dnsq_next; free(p); } qlist_init(&ctx->dnsc_qactive); ctx->dnsc_nactive = 0; dns_drop_utm(ctx); } } void dns_reset(struct dns_ctx *ctx) { SETCTX(ctx); dns_close(ctx); memset(ctx, 0, sizeof(*ctx)); ctx->dnsc_timeout = 4; ctx->dnsc_ntries = 3; ctx->dnsc_ndots = 1; ctx->dnsc_udpbuf = DNS_EDNS0PACKET; ctx->dnsc_port = DNS_PORT; ctx->dnsc_udpsock = -1; ctx->dnsc_srchend = ctx->dnsc_srchbuf; qlist_init(&ctx->dnsc_qactive); dns_init_rng(ctx); ctx->dnsc_flags = DNS_INITED; } struct dns_ctx *dns_new(const struct dns_ctx *copy) { struct dns_ctx *ctx; SETCTXINITED(copy); dns_assert_ctx(copy); ctx = (struct dns_ctx *)malloc(sizeof(*ctx)); if (!ctx) return NULL; *ctx = *copy; ctx->dnsc_udpsock = -1; qlist_init(&ctx->dnsc_qactive); ctx->dnsc_nactive = 0; ctx->dnsc_pbuf = NULL; ctx->dnsc_qstatus = 0; ctx->dnsc_srchend = ctx->dnsc_srchbuf + (copy->dnsc_srchend - copy->dnsc_srchbuf); ctx->dnsc_utmfn = NULL; ctx->dnsc_utmctx = NULL; dns_init_rng(ctx); return ctx; } void dns_free(struct dns_ctx *ctx) { assert(ctx != NULL && ctx != &dns_defctx); dns_reset(ctx); free(ctx); } int dns_open(struct dns_ctx *ctx) { int sock; unsigned i; int port; union sockaddr_ns *sns; #ifdef HAVE_IPv6 unsigned have_inet6 = 0; #endif SETCTXINITED(ctx); assert(!CTXOPEN(ctx)); port = htons((unsigned short)ctx->dnsc_port); /* ensure we have at least one server */ if (!ctx->dnsc_nserv) { sns = ctx->dnsc_serv; sns->sin.sin_family = AF_INET; sns->sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); ctx->dnsc_nserv = 1; } for (i = 0; i < ctx->dnsc_nserv; ++i) { sns = &ctx->dnsc_serv[i]; /* set port for each sockaddr */ #ifdef HAVE_IPv6 if (sns->sa.sa_family == AF_INET6) { if (!sns->sin6.sin6_port) sns->sin6.sin6_port = (unsigned short)port; ++have_inet6; } else #endif { assert(sns->sa.sa_family == AF_INET); if (!sns->sin.sin_port) sns->sin.sin_port = (unsigned short)port; } } #ifdef HAVE_IPv6 if (have_inet6 && have_inet6 < ctx->dnsc_nserv) { /* convert all IPv4 addresses to IPv6 V4MAPPED */ struct sockaddr_in6 sin6; memset(&sin6, 0, sizeof(sin6)); sin6.sin6_family = AF_INET6; /* V4MAPPED: ::ffff:1.2.3.4 */ sin6.sin6_addr.s6_addr[10] = 0xff; sin6.sin6_addr.s6_addr[11] = 0xff; for(i = 0; i < ctx->dnsc_nserv; ++i) { sns = &ctx->dnsc_serv[i]; if (sns->sa.sa_family == AF_INET) { sin6.sin6_port = sns->sin.sin_port; memcpy(sin6.sin6_addr.s6_addr + 4*3, &sns->sin.sin_addr, 4); sns->sin6 = sin6; } } } ctx->dnsc_salen = have_inet6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in); if (have_inet6) sock = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP); else sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); #else /* !HAVE_IPv6 */ sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); ctx->dnsc_salen = sizeof(struct sockaddr_in); #endif /* HAVE_IPv6 */ if (sock < 0) { ctx->dnsc_qstatus = DNS_E_TEMPFAIL; return -1; } #ifdef WINDOWS { unsigned long on = 1; if (ioctlsocket(sock, FIONBIO, &on) == SOCKET_ERROR) { closesocket(sock); ctx->dnsc_qstatus = DNS_E_TEMPFAIL; return -1; } } #else /* !WINDOWS */ if (fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_NONBLOCK) < 0 || fcntl(sock, F_SETFD, FD_CLOEXEC) < 0) { closesocket(sock); ctx->dnsc_qstatus = DNS_E_TEMPFAIL; return -1; } #endif /* WINDOWS */ /* allocate the packet buffer */ if ((ctx->dnsc_pbuf = (dnsc_t*)malloc(ctx->dnsc_udpbuf)) == NULL) { closesocket(sock); ctx->dnsc_qstatus = DNS_E_NOMEM; errno = ENOMEM; return -1; } ctx->dnsc_udpsock = sock; dns_request_utm(ctx, 0); return sock; } int dns_sock(const struct dns_ctx *ctx) { SETCTXINITED(ctx); return ctx->dnsc_udpsock; } int dns_active(const struct dns_ctx *ctx) { SETCTXINITED(ctx); dns_assert_ctx(ctx); return ctx->dnsc_nactive; } int dns_status(const struct dns_ctx *ctx) { SETCTX(ctx); return ctx->dnsc_qstatus; } void dns_setstatus(struct dns_ctx *ctx, int status) { SETCTX(ctx); ctx->dnsc_qstatus = status; } /* End the query: disconnect it from the active list, free it, * and return the result to the caller. */ static void dns_end_query(struct dns_ctx *ctx, struct dns_query *q, int status, void *result) { dns_query_fn *cbck = q->dnsq_cbck; void *cbdata = q->dnsq_cbdata; ctx->dnsc_qstatus = status; assert((status < 0 && result == 0) || (status >= 0 && result != 0)); assert(cbck != 0); /*XXX callback may be NULL */ assert(ctx->dnsc_nactive > 0); --ctx->dnsc_nactive; qlist_remove(&ctx->dnsc_qactive, q); /* force the query to be unconnected */ /*memset(q, 0, sizeof(*q));*/ #ifndef NDEBUG q->dnsq_ctx = NULL; #endif free(q); cbck(ctx, result, cbdata); } #define DNS_DBG(ctx, code, sa, slen, pkt, plen) \ do { \ if (ctx->dnsc_udbgfn) \ ctx->dnsc_udbgfn(code, (sa), slen, pkt, plen, 0, 0); \ } while(0) #define DNS_DBGQ(ctx, q, code, sa, slen, pkt, plen) \ do { \ if (ctx->dnsc_udbgfn) \ ctx->dnsc_udbgfn(code, (sa), slen, pkt, plen, q, q->dnsq_cbdata); \ } while(0) static void dns_newid(struct dns_ctx *ctx, struct dns_query *q) { /* this is how we choose an identifier for a new query (qID). * For now, it's just sequential number, incremented for every query, and * thus obviously trivial to guess. * There are two choices: * a) use sequential numbers. It is plain insecure. In DNS, there are two * places where random numbers are (or can) be used to increase security: * random qID and random source port number. Without this randomness * (udns uses fixed port for all queries), or when the randomness is weak, * it's trivial to spoof query replies. With randomness however, it * becomes a bit more difficult task. Too bad we only have 16 bits for * our security, as qID is only two bytes. It isn't a security per se, * to rely on those 16 bits - an attacker can just flood us with fake * replies with all possible qIDs (only 65536 of them), and in this case, * even if we'll use true random qIDs, we'll be in trouble (not protected * against spoofing). Yes, this is only possible on a high-speed network * (probably on the LAN only, since usually a border router for a LAN * protects internal machines from packets with spoofed local addresses * from outside, and usually a nameserver resides on LAN), but it's * still very well possible to send us fake replies. * In other words: there's nothing a DNS (stub) resolver can do against * spoofing attacks, unless DNSSEC is in use, which helps here alot. * Too bad that DNSSEC isn't widespread, so relying on it isn't an * option in almost all cases... * b) use random qID, based on some random-number generation mechanism. * This way, we increase our protection a bit (see above - it's very weak * still), but we also increase risk of qID reuse and matching late replies * that comes to queries we've sent before against new queries. There are * some more corner cases around that, as well - for example, normally, * udns tries to find the query for a given reply by qID, *and* by * verifying that the query DN and other parameters are also the same * (so if the new query is against another domain name, old reply will * be ignored automatically). But certain types of replies which we now * handle - for example, FORMERR reply from servers which refuses to * process EDNS0-enabled packets - comes without all the query parameters * but the qID - so we're forced to use qID only when determining which * query the given reply corresponds to. This makes us even more * vulnerable to spoofing attacks, because an attacker don't even need to * know which queries we perform to spoof the replies - he only needs to * flood us with fake FORMERR "replies". * * That all to say: using sequential (or any other trivially guessable) * numbers for qIDs is insecure, but the whole thing is inherently insecure * as well, and this "extra weakness" that comes from weak qID choosing * algorithm adds almost nothing to the underlying problem. * * It CAN NOT be made secure. Period. That's it. * Unless we choose to implement DNSSEC, which is a whole different story. * Forcing TCP mode makes it better, but who uses TCP for DNS anyway? * (and it's hardly possible because of huge impact on the recursive * nameservers). * * Note that ALL stub resolvers (again, unless they implement and enforce * DNSSEC) suffers from this same problem. * * Here, I use a pseudo-random number generator for qIDs, instead of a * simpler sequential IDs. This is _not_ more secure than sequential * ID, but some found random IDs more enjoyeable for some reason. So * here it goes. */ /* Use random number and check if it's unique. * If it's not, try again up to 5 times. */ unsigned loop; dnsc_t c0, c1; for(loop = 0; loop < 5; ++loop) { const struct dns_query *c; if (!ctx->dnsc_nextid) ctx->dnsc_nextid = udns_jranval(&ctx->dnsc_jran); c0 = ctx->dnsc_nextid & 0xff; c1 = (ctx->dnsc_nextid >> 8) & 0xff; ctx->dnsc_nextid >>= 16; for(c = ctx->dnsc_qactive.head; c; c = c->dnsq_next) if (c->dnsq_id[0] == c0 && c->dnsq_id[1] == c1) break; /* found such entry, try again */ if (!c) break; } q->dnsq_id[0] = c0; q->dnsq_id[1] = c1; /* reset all parameters relevant for previous query lifetime */ q->dnsq_try = 0; q->dnsq_servi = 0; /*XXX probably should keep dnsq_servnEDNS0 bits? * See also comments in dns_ioevent() about FORMERR case */ q->dnsq_servwait = q->dnsq_servskip = q->dnsq_servnEDNS0 = 0; } /* Find next search suffix and fills in q->dnsq_dn. * Return 0 if no more to try. */ static int dns_next_srch(struct dns_ctx *ctx, struct dns_query *q) { unsigned dnl; for(;;) { if (q->dnsq_nxtsrch > ctx->dnsc_srchend) return 0; dnl = dns_dnlen(q->dnsq_nxtsrch); if (dnl + q->dnsq_origdnl0 <= DNS_MAXDN && (*q->dnsq_nxtsrch || !(q->dnsq_flags & DNS_ASIS_DONE))) break; q->dnsq_nxtsrch += dnl; } memcpy(q->dnsq_dn + q->dnsq_origdnl0, q->dnsq_nxtsrch, dnl); if (!*q->dnsq_nxtsrch) q->dnsq_flags |= DNS_ASIS_DONE; q->dnsq_nxtsrch += dnl; dns_newid(ctx, q); /* new ID for new qDN */ return 1; } /* find the server to try for current iteration. * Note that current dnsq_servi may point to a server we should skip -- * in that case advance to the next server. * Return true if found, false if all tried. */ static int dns_find_serv(const struct dns_ctx *ctx, struct dns_query *q) { while(q->dnsq_servi < ctx->dnsc_nserv) { if (!(q->dnsq_servskip & (1 << q->dnsq_servi))) return 1; ++q->dnsq_servi; } return 0; } /* format and send the query to a given server. * In case of network problem (sendto() fails), return -1, * else return 0. */ static int dns_send_this(struct dns_ctx *ctx, struct dns_query *q, unsigned servi, time_t now) { unsigned qlen; unsigned tries; { /* format the query buffer */ dnsc_t *p = ctx->dnsc_pbuf; memset(p, 0, DNS_HSIZE); if (!(q->dnsq_flags & DNS_NORD)) p[DNS_H_F1] |= DNS_HF1_RD; if (q->dnsq_flags & DNS_AAONLY) p[DNS_H_F1] |= DNS_HF1_AA; if (q->dnsq_flags & DNS_SET_CD) p[DNS_H_F2] |= DNS_HF2_CD; p[DNS_H_QDCNT2] = 1; memcpy(p + DNS_H_QID, q->dnsq_id, 2); p = dns_payload(p); /* copy query dn */ p += dns_dntodn(q->dnsq_dn, p, DNS_MAXDN); /* query type and class */ memcpy(p, q->dnsq_typcls, 4); p += 4; /* add EDNS0 record. DO flag requires it */ if (q->dnsq_flags & DNS_SET_DO || (ctx->dnsc_udpbuf > DNS_MAXPACKET && !(q->dnsq_servnEDNS0 & (1 << servi)))) { *p++ = 0; /* empty (root) DN */ p = dns_put16(p, DNS_T_OPT); p = dns_put16(p, ctx->dnsc_udpbuf); /* EDNS0 RCODE & VERSION; rest of the TTL field; RDLEN */ memset(p, 0, 2+2+2); if (q->dnsq_flags & DNS_SET_DO) p[2] |= DNS_EF1_DO; p += 2+2+2; ctx->dnsc_pbuf[DNS_H_ARCNT2] = 1; } qlen = p - ctx->dnsc_pbuf; assert(qlen <= ctx->dnsc_udpbuf); } /* send the query */ tries = 10; while (sendto(ctx->dnsc_udpsock, (void*)ctx->dnsc_pbuf, qlen, 0, &ctx->dnsc_serv[servi].sa, ctx->dnsc_salen) < 0) { /*XXX just ignore the sendto() error for now and try again. * In the future, it may be possible to retrieve the error code * and find which operation/query failed. *XXX try the next server too? (if ENETUNREACH is returned immediately) */ if (--tries) continue; /* if we can't send the query, fail it. */ dns_end_query(ctx, q, DNS_E_TEMPFAIL, 0); return -1; } DNS_DBGQ(ctx, q, 1, &ctx->dnsc_serv[servi].sa, sizeof(union sockaddr_ns), ctx->dnsc_pbuf, qlen); q->dnsq_servwait |= 1 << servi; /* expect reply from this ns */ q->dnsq_deadline = now + (dns_find_serv(ctx, q) ? 1 : ctx->dnsc_timeout << q->dnsq_try); /* move the query to the proper place, according to the new deadline */ qlist_remove(&ctx->dnsc_qactive, q); { /* insert from the tail */ struct dns_query *p; for(p = ctx->dnsc_qactive.tail; p; p = p->dnsq_prev) if (p->dnsq_deadline <= q->dnsq_deadline) break; qlist_insert_after(&ctx->dnsc_qactive, q, p); } return 0; } /* send the query out using next available server * and add it to the active list, or, if no servers available, * end it. */ static void dns_send(struct dns_ctx *ctx, struct dns_query *q, time_t now) { /* if we can't send the query, return TEMPFAIL even when searching: * we can't be sure whenever the name we tried to search exists or not, * so don't continue searching, or we may find the wrong name. */ if (!dns_find_serv(ctx, q)) { /* no more servers in this iteration. Try the next cycle */ q->dnsq_servi = 0; /* reset */ q->dnsq_try++; /* next try */ if (q->dnsq_try >= ctx->dnsc_ntries || !dns_find_serv(ctx, q)) { /* no more servers and tries, fail the query */ /* return TEMPFAIL even when searching: no more tries for this * searchlist, and no single definitive reply (handled in dns_ioevent() * in NOERROR or NXDOMAIN cases) => all nameservers failed to process * current search list element, so we don't know whenever the name exists. */ dns_end_query(ctx, q, DNS_E_TEMPFAIL, 0); return; } } dns_send_this(ctx, q, q->dnsq_servi++, now); } static void dns_dummy_cb(struct dns_ctx *unused_ctx, void *result, void *unused_data) { if (result) free(result); (void)unused_ctx; (void)unused_data; /* avoid warning */ } /* The (only, main, real) query submission routine. * Allocate new query structure, initialize it, check validity of * parameters, and add it to the head of the active list, without * trying to send it (to be picked up on next event). * Error return (without calling the callback routine) - * no memory or wrong parameters. *XXX The `no memory' case probably should go to the callback anyway... */ struct dns_query * dns_submit_dn(struct dns_ctx *ctx, dnscc_t *dn, int qcls, int qtyp, int flags, dns_parse_fn *parse, dns_query_fn *cbck, void *data) { struct dns_query *q; SETCTXOPEN(ctx); dns_assert_ctx(ctx); q = (struct dns_query *)calloc(1, sizeof(*q)); if (!q) { ctx->dnsc_qstatus = DNS_E_NOMEM; return NULL; } #ifndef NDEBUG q->dnsq_ctx = ctx; #endif q->dnsq_parse = parse; q->dnsq_cbck = cbck ? cbck : dns_dummy_cb; q->dnsq_cbdata = data; q->dnsq_origdnl0 = dns_dntodn(dn, q->dnsq_dn, sizeof(q->dnsq_dn)); assert(q->dnsq_origdnl0 > 0); --q->dnsq_origdnl0; /* w/o the trailing 0 */ dns_put16(q->dnsq_typcls+0, qtyp); dns_put16(q->dnsq_typcls+2, qcls); q->dnsq_flags = (flags | ctx->dnsc_flags) & ~DNS_INTERNAL; if (flags & DNS_NOSRCH || dns_dnlabels(q->dnsq_dn) > ctx->dnsc_ndots) { q->dnsq_nxtsrch = flags & DNS_NOSRCH ? ctx->dnsc_srchend /* end of the search list if no search requested */ : ctx->dnsc_srchbuf /* beginning of the list, but try as-is first */; q->dnsq_flags |= DNS_ASIS_DONE; dns_newid(ctx, q); } else { q->dnsq_nxtsrch = ctx->dnsc_srchbuf; dns_next_srch(ctx, q); } /* q->dnsq_deadline is set to 0 (calloc above): the new query is * "already expired" when first inserted into queue, so it's safe * to insert it into the head of the list. Next call to dns_timeouts() * will actually send it. */ qlist_add_head(&ctx->dnsc_qactive, q); ++ctx->dnsc_nactive; dns_request_utm(ctx, 0); return q; } struct dns_query * dns_submit_p(struct dns_ctx *ctx, const char *name, int qcls, int qtyp, int flags, dns_parse_fn *parse, dns_query_fn *cbck, void *data) { int isabs; SETCTXOPEN(ctx); if (dns_ptodn(name, 0, ctx->dnsc_pbuf, DNS_MAXDN, &isabs) <= 0) { ctx->dnsc_qstatus = DNS_E_BADQUERY; return NULL; } if (isabs) flags |= DNS_NOSRCH; return dns_submit_dn(ctx, ctx->dnsc_pbuf, qcls, qtyp, flags, parse, cbck, data); } /* process readable fd condition. * To be usable in edge-triggered environment, the routine * should consume all input so it should loop over. * Note it isn't really necessary to loop here, because * an application may perform the loop just fine by it's own, * but in this case we should return some sensitive result, * to indicate when to stop calling and error conditions. * Note also we may encounter all sorts of recvfrom() * errors which aren't fatal, and at the same time we may * loop forever if an error IS fatal. */ void dns_ioevent(struct dns_ctx *ctx, time_t now) { int r; unsigned servi; struct dns_query *q; dnsc_t *pbuf; dnscc_t *pend, *pcur; void *result; union sockaddr_ns sns; socklen_t slen; SETCTX(ctx); if (!CTXOPEN(ctx)) return; dns_assert_ctx(ctx); pbuf = ctx->dnsc_pbuf; if (!now) now = time(NULL); again: /* receive the reply */ slen = sizeof(sns); r = recvfrom(ctx->dnsc_udpsock, (void*)pbuf, ctx->dnsc_udpbuf, MSG_DONTWAIT, &sns.sa, &slen); if (r < 0) { /*XXX just ignore recvfrom() errors for now. * in the future it may be possible to determine which * query failed and requeue it. * Note there may be various error conditions, triggered * by both local problems and remote problems. It isn't * quite trivial to determine whenever an error is local * or remote. On local errors, we should stop, while * remote errors should be ignored (for now anyway). */ #ifdef WINDOWS if (WSAGetLastError() == WSAEWOULDBLOCK) #else if (errno == EAGAIN) #endif { dns_request_utm(ctx, now); return; } goto again; } pend = pbuf + r; pcur = dns_payload(pbuf); /* check reply header */ if (pcur > pend || dns_numqd(pbuf) > 1 || dns_opcode(pbuf) != 0) { DNS_DBG(ctx, -1/*bad reply*/, &sns.sa, slen, pbuf, r); goto again; } /* find the matching query, by qID */ for (q = ctx->dnsc_qactive.head; ; q = q->dnsq_next) { if (!q) { /* no more requests: old reply? */ DNS_DBG(ctx, -5/*no matching query*/, &sns.sa, slen, pbuf, r); goto again; } if (pbuf[DNS_H_QID1] == q->dnsq_id[0] && pbuf[DNS_H_QID2] == q->dnsq_id[1]) break; } /* if we have numqd, compare with our query qDN */ if (dns_numqd(pbuf)) { /* decode the qDN */ dnsc_t dn[DNS_MAXDN]; if (dns_getdn(pbuf, &pcur, pend, dn, sizeof(dn)) < 0 || pcur + 4 > pend) { DNS_DBG(ctx, -1/*bad reply*/, &sns.sa, slen, pbuf, r); goto again; } if (!dns_dnequal(dn, q->dnsq_dn) || memcmp(pcur, q->dnsq_typcls, 4) != 0) { /* not this query */ DNS_DBG(ctx, -5/*no matching query*/, &sns.sa, slen, pbuf, r); goto again; } /* here, query match, and pcur points past qDN in query section in pbuf */ } /* if no numqd, we only allow FORMERR rcode */ else if (dns_rcode(pbuf) != DNS_R_FORMERR) { /* treat it as bad reply if !FORMERR */ DNS_DBG(ctx, -1/*bad reply*/, &sns.sa, slen, pbuf, r); goto again; } else { /* else it's FORMERR, handled below */ } /* find server */ #ifdef HAVE_IPv6 if (sns.sa.sa_family == AF_INET6 && slen >= sizeof(sns.sin6)) { for(servi = 0; servi < ctx->dnsc_nserv; ++servi) if (sin6_eq(ctx->dnsc_serv[servi].sin6, sns.sin6)) break; } else #endif if (sns.sa.sa_family == AF_INET && slen >= sizeof(sns.sin)) { for(servi = 0; servi < ctx->dnsc_nserv; ++servi) if (sin_eq(ctx->dnsc_serv[servi].sin, sns.sin)) break; } else servi = ctx->dnsc_nserv; /* check if we expect reply from this server. * Note we can receive reply from first try if we're already at next */ if (!(q->dnsq_servwait & (1 << servi))) { /* if ever asked this NS */ DNS_DBG(ctx, -2/*wrong server*/, &sns.sa, slen, pbuf, r); goto again; } /* we got (some) reply for our query */ DNS_DBGQ(ctx, q, 0, &sns.sa, slen, pbuf, r); q->dnsq_servwait &= ~(1 << servi); /* don't expect reply from this serv */ /* process the RCODE */ switch(dns_rcode(pbuf)) { case DNS_R_NOERROR: if (dns_tc(pbuf)) { /* possible truncation. We can't deal with it. */ /*XXX for now, treat TC bit the same as SERVFAIL. * It is possible to: * a) try to decode the reply - may be ANSWER section is ok; * b) check if server understands EDNS0, and if it is, and * answer still don't fit, end query. */ break; } if (!dns_numan(pbuf)) { /* no data of requested type */ if (dns_next_srch(ctx, q)) { /* if we're searching, try next searchlist element, * but remember NODATA reply. */ q->dnsq_flags |= DNS_SEEN_NODATA; dns_send(ctx, q, now); } else /* else - nothing to search any more - finish the query. * It will be NODATA since we've seen a NODATA reply. */ dns_end_query(ctx, q, DNS_E_NODATA, 0); } /* we've got a positive reply here */ else if (q->dnsq_parse) { /* if we have parsing routine, call it and return whatever it returned */ /* don't try to re-search if NODATA here. For example, * if we asked for A but only received CNAME. Unless we'll * someday do recursive queries. And that's problematic too, since * we may be dealing with specific AA-only nameservers for a given * domain, but CNAME points elsewhere... */ r = q->dnsq_parse(q->dnsq_dn, pbuf, pcur, pend, &result); dns_end_query(ctx, q, r, r < 0 ? NULL : result); } /* else just malloc+copy the raw DNS reply */ else if ((result = malloc(r)) == NULL) dns_end_query(ctx, q, DNS_E_NOMEM, NULL); else { memcpy(result, pbuf, r); dns_end_query(ctx, q, r, result); } goto again; case DNS_R_NXDOMAIN: /* Non-existing domain. */ if (dns_next_srch(ctx, q)) /* more search entries exists, try them. */ dns_send(ctx, q, now); else /* nothing to search anymore. End the query, returning either NODATA * if we've seen it before, or NXDOMAIN if not. */ dns_end_query(ctx, q, q->dnsq_flags & DNS_SEEN_NODATA ? DNS_E_NODATA : DNS_E_NXDOMAIN, 0); goto again; case DNS_R_FORMERR: case DNS_R_NOTIMPL: /* for FORMERR and NOTIMPL rcodes, if we tried EDNS0-enabled query, * try w/o EDNS0. */ if (ctx->dnsc_udpbuf > DNS_MAXPACKET && !(q->dnsq_servnEDNS0 & (1 << servi))) { /* we always trying EDNS0 first if enabled, and retry a given query * if not available. Maybe it's better to remember inavailability of * EDNS0 in ctx as a per-NS flag, and never try again for this NS. * For long-running applications.. maybe they will change the nameserver * while we're running? :) Also, since FORMERR is the only rcode we * allow to be header-only, and in this case the only check we do to * find a query it belongs to is qID (not qDN+qCLS+qTYP), it's much * easier to spoof and to force us to perform non-EDNS0 queries only... */ q->dnsq_servnEDNS0 |= 1 << servi; dns_send_this(ctx, q, servi, now); goto again; } /* else we handle it the same as SERVFAIL etc */ case DNS_R_SERVFAIL: case DNS_R_REFUSED: /* for these rcodes, advance this request * to the next server and reschedule */ default: /* unknown rcode? hmmm... */ break; } /* here, we received unexpected reply */ q->dnsq_servskip |= (1 << servi); /* don't retry this server */ /* we don't expect replies from this server anymore. * But there may be other servers. Some may be still processing our * query, and some may be left to try. * We just ignore this reply and wait a bit more if some NSes haven't * replied yet (dnsq_servwait != 0), and let the situation to be handled * on next event processing. Timeout for this query is set correctly, * if not taking into account the one-second difference - we can try * next server in the same iteration sooner. */ /* try next server */ if (!q->dnsq_servwait) { /* next retry: maybe some other servers will reply next time. * dns_send() will end the query for us if no more servers to try. * Note we can't continue with the next searchlist element here: * we don't know if the current qdn exists or not, there's no definitive * answer yet (which is seen in cases above). *XXX standard resolver also tries as-is query in case all nameservers * failed to process our query and if not tried before. We don't do it. */ dns_send(ctx, q, now); } else { /* else don't do anything - not all servers replied yet */ } goto again; } /* handle all timeouts */ int dns_timeouts(struct dns_ctx *ctx, int maxwait, time_t now) { /* this is a hot routine */ struct dns_query *q; SETCTX(ctx); dns_assert_ctx(ctx); /* Pick up first entry from query list. * If its deadline has passed, (re)send it * (dns_send() will move it next in the list). * If not, this is the query which determines the closest deadline. */ q = ctx->dnsc_qactive.head; if (!q) return maxwait; if (!now) now = time(NULL); // Just in case, to avoid infinite loop when e.g. callbacks might add new queries with expired // deadlines. int loop = 128; while (true) { if (--loop <= 0) { maxwait = 0; break; } if (q->dnsq_deadline > now) { /* first non-expired query */ int w = (int)(q->dnsq_deadline - now); if (maxwait < 0 || maxwait > w) maxwait = w; break; } else { /* process expired deadline */ dns_send(ctx, q, now); } if ((q = ctx->dnsc_qactive.head) == NULL) break; } dns_request_utm(ctx, now); /* update timer with new deadline */ return maxwait; } struct dns_resolve_data { int dnsrd_done; void *dnsrd_result; }; static void dns_resolve_cb(__attribute__((unused)) struct dns_ctx *ctx, void *result, void *data) { struct dns_resolve_data *d = (struct dns_resolve_data *)data; d->dnsrd_result = result; d->dnsrd_done = 1; // Unused: ctx = ctx; /* ctx = ctx; */ } void *dns_resolve(struct dns_ctx *ctx, struct dns_query *q) { time_t now; struct dns_resolve_data d; int n; SETCTXOPEN(ctx); if (!q) return NULL; assert(ctx == q->dnsq_ctx); dns_assert_ctx(ctx); /* do not allow re-resolving synchronous queries */ assert(q->dnsq_cbck != dns_resolve_cb && "can't resolve synchronous query"); if (q->dnsq_cbck == dns_resolve_cb) { ctx->dnsc_qstatus = DNS_E_BADQUERY; return NULL; } q->dnsq_cbck = dns_resolve_cb; q->dnsq_cbdata = &d; d.dnsrd_done = 0; now = time(NULL); while(!d.dnsrd_done && (n = dns_timeouts(ctx, -1, now)) >= 0) { #ifdef HAVE_POLL struct pollfd pfd; pfd.fd = ctx->dnsc_udpsock; pfd.events = POLLIN; n = poll(&pfd, 1, n * 1000); #else fd_set rfd; struct timeval tv; FD_ZERO(&rfd); FD_SET(ctx->dnsc_udpsock, &rfd); tv.tv_sec = n; tv.tv_usec = 0; n = select(ctx->dnsc_udpsock + 1, &rfd, NULL, NULL, &tv); #endif now = time(NULL); if (n > 0) dns_ioevent(ctx, now); } return d.dnsrd_result; } void *dns_resolve_dn(struct dns_ctx *ctx, dnscc_t *dn, int qcls, int qtyp, int flags, dns_parse_fn *parse) { return dns_resolve(ctx, dns_submit_dn(ctx, dn, qcls, qtyp, flags, parse, NULL, NULL)); } void *dns_resolve_p(struct dns_ctx *ctx, const char *name, int qcls, int qtyp, int flags, dns_parse_fn *parse) { return dns_resolve(ctx, dns_submit_p(ctx, name, qcls, qtyp, flags, parse, NULL, NULL)); } int dns_cancel(struct dns_ctx *ctx, struct dns_query *q) { SETCTX(ctx); dns_assert_ctx(ctx); assert(q->dnsq_ctx == ctx); /* do not allow cancelling synchronous queries */ assert(q->dnsq_cbck != dns_resolve_cb && "can't cancel synchronous query"); if (q->dnsq_cbck == dns_resolve_cb) return (ctx->dnsc_qstatus = DNS_E_BADQUERY); qlist_remove(&ctx->dnsc_qactive, q); --ctx->dnsc_nactive; dns_request_utm(ctx, 0); return 0; } libtorrent-0.16.11/src/net/udns/getopt.c0000644000000000000000000000755415175073411013506 /* getopt.c * Simple getopt() implementation. * * Standard interface: * extern int getopt(int argc, char *const *argv, const char *opts); * extern int optind; current index in argv[] * extern char *optarg; argument for the current option * extern int optopt; the current option * extern int opterr; to control error printing * * Some minor extensions: * ignores leading `+' sign in opts[] (unemplemented GNU extension) * handles optional arguments, in form "x::" in opts[] * if opts[] starts with `:', will return `:' in case of missing required * argument, instead of '?'. * * Compile with -DGETOPT_NO_OPTERR to never print errors internally. * Compile with -DGETOPT_NO_STDIO to use write() calls instead of fprintf() for * error reporting (ignored with -DGETOPT_NO_OPTERR). * Compile with -DGETOPT_CLASS=static to get static linkage. * Compile with -DGETOPT_MY to redefine all visible symbols to be prefixed * with "my_", like my_getopt instead of getopt. * Compile with -DTEST to get a test executable. * * Written by Michael Tokarev. Public domain. */ #include #ifndef GETOPT_CLASS # define GETOPT_CLASS #endif #ifdef GETOPT_MY # define optarg my_optarg # define optind my_optind # define opterr my_opterr # define optopt my_optopt # define getopt my_getopt #endif GETOPT_CLASS char *optarg /* = NULL */; GETOPT_CLASS int optind = 1; GETOPT_CLASS int opterr = 1; GETOPT_CLASS int optopt; static char *nextc /* = NULL */; #if defined(GETOPT_NO_OPTERR) #define printerr(argv, msg) #elif defined(GETOPT_NO_STDIO) extern int write(int, void *, int); static void printerr(char *const *argv, const char *msg) { if (opterr) { char buf[64]; unsigned pl = strlen(argv[0]); unsigned ml = strlen(msg); char *p; if (pl + /*": "*/2 + ml + /*" -- c\n"*/6 > sizeof(buf)) { write(2, argv[0], pl); p = buf; } else { memcpy(buf, argv[0], ml); p = buf + pl; } *p++ = ':'; *p++ = ' '; memcpy(p, msg, ml); p += ml; *p++ = ' '; *p++ = '-'; *p++ = '-'; *p++ = ' '; *p++ = optopt; *p++ = '\n'; write(2, buf, p - buf); } } #else #include static void printerr(char *const *argv, const char *msg) { if (opterr) fprintf(stderr, "%s: %s -- %c\n", argv[0], msg, optopt); } #endif GETOPT_CLASS int getopt(int argc, char *const *argv, const char *opts) { char *p; optarg = 0; if (*opts == '+') /* GNU extension (permutation) - isn't supported */ ++opts; if (!optind) { /* a way to reset things */ nextc = 0; optind = 1; } if (!nextc || !*nextc) { /* advance to the next argv element */ /* done scanning? */ if (optind >= argc) return -1; /* not an optional argument */ if (argv[optind][0] != '-') return -1; /* bare `-' */ if (argv[optind][1] == '\0') return -1; /* special case `--' argument */ if (argv[optind][1] == '-' && argv[optind][2] == '\0') { ++optind; return -1; } nextc = argv[optind] + 1; } optopt = *nextc++; if (!*nextc) ++optind; p = strchr(opts, optopt); if (!p || optopt == ':') { printerr(argv, "illegal option"); return '?'; } if (p[1] == ':') { if (*nextc) { optarg = nextc; nextc = NULL; ++optind; } else if (p[2] != ':') { /* required argument */ if (optind >= argc) { printerr(argv, "option requires an argument"); return *opts == ':' ? ':' : '?'; } else optarg = argv[optind++]; } } return optopt; } #ifdef TEST #include int main(int argc, char **argv) { int c; while((c = getopt(argc, argv, "ab:c::")) != -1) switch(c) { case 'a': case 'b': case 'c': printf("option %c %s\n", c, optarg ? optarg : "(none)"); break; default: return -1; } for(c = optind; c < argc; ++c) printf("non-opt: %s\n", argv[c]); return 0; } #endif libtorrent-0.16.11/src/net/udns/inet_XtoX.c0000644000000000000000000001740215175073411014116 /* inet_XtoX.c * Simple implementation of the following functions: * inet_ntop(), inet_ntoa(), inet_pton(), inet_aton(). * * Differences from traditional implementaitons: * o modifies destination buffers even on error return. * o no fancy (hex, or 1.2) input support in inet_aton() * o inet_aton() does not accept junk after an IP address. * o inet_ntop(AF_INET) requires at least 16 bytes in dest, * and inet_ntop(AF_INET6) at least 40 bytes * (traditional inet_ntop() will try to fit anyway) * * Compile with -Dinet_XtoX_prefix=pfx_ to have pfx_*() instead of inet_*() * Compile with -Dinet_XtoX_no_ntop or -Dinet_XtoX_no_pton * to disable net2str or str2net conversions. * * #define inet_XtoX_prototypes and #include "this_file.c" * to get function prototypes only (but not for inet_ntoa()). * #define inet_XtoX_decl to be `static' for static visibility, * or use __declspec(dllexport) or somesuch... * * Compile with -DTEST to test against stock implementation. * * Written by Michael Tokarev. Public domain. */ #ifdef inet_XtoX_prototypes struct in_addr; #else #include #ifdef TEST # include # include # include # include # include # include # include # undef inet_XtoX_prefix # define inet_XtoX_prefix mjt_inet_ # undef inet_XtoX_no_ntop # undef inet_XtoX_no_pton #else /* !TEST */ struct in_addr { /* declare it here to avoid messing with headers */ unsigned char x[4]; }; #endif /* TEST */ #endif /* inet_XtoX_prototypes */ #ifndef inet_XtoX_prefix # define inet_XtoX_prefix inet_ #endif #ifndef inet_XtoX_decl # define inet_XtoX_decl /*empty*/ #endif #define cc2_(x,y) cc2__(x,y) #define cc2__(x,y) x##y #define fn(x) cc2_(inet_XtoX_prefix,x) #ifndef inet_XtoX_no_ntop inet_XtoX_decl const char * fn(ntop)(int af, const void *src, char *dst, unsigned size); #ifndef inet_XtoX_prototypes static int mjt_ntop4(const void *_src, char *dst, int size) { unsigned i, x, r; char *p; const unsigned char *s = _src; if (size < 4*4) /* for simplicity, disallow non-max-size buffer */ return 0; for (i = 0, p = dst; i < 4; ++i) { if (i) *p++ = '.'; x = r = s[i]; if (x > 99) { *p++ = (char)(r / 100 + '0'); r %= 100; } if (x > 9) { *p++ = (char)(r / 10 + '0'); r %= 10; } *p++ = (char)(r + '0'); } *p = '\0'; return 1; } static char *hexc(char *p, unsigned x) { static char hex[16] = "0123456789abcdef"; if (x > 0x0fff) *p++ = hex[(x >>12) & 15]; if (x > 0x00ff) *p++ = hex[(x >> 8) & 15]; if (x > 0x000f) *p++ = hex[(x >> 4) & 15]; *p++ = hex[x & 15]; return p; } static int mjt_ntop6(const void *_src, char *dst, int size) { unsigned i; unsigned short w[8]; unsigned bs = 0, cs = 0; unsigned bl = 0, cl = 0; char *p; const unsigned char *s = _src; if (size < 40) /* for simplicity, disallow non-max-size buffer */ return 0; for(i = 0; i < 8; ++i, s += 2) { w[i] = (((unsigned short)(s[0])) << 8) | s[1]; if (!w[i]) { if (!cl++) cs = i; } else { if (cl > bl) bl = cl, bs = cs; } } if (cl > bl) bl = cl, bs = cs; p = dst; if (bl == 1) bl = 0; if (bl) { for(i = 0; i < bs; ++i) { if (i) *p++ = ':'; p = hexc(p, w[i]); } *p++ = ':'; i += bl; if (i == 8) *p++ = ':'; } else i = 0; for(; i < 8; ++i) { if (i) *p++ = ':'; if (i == 6 && !bs && (bl == 6 || (bl == 5 && w[5] == 0xffff))) return mjt_ntop4(s - 4, p, size - (p - dst)); p = hexc(p, w[i]); } *p = '\0'; return 1; } inet_XtoX_decl const char * fn(ntop)(int af, const void *src, char *dst, unsigned size) { switch(af) { /* don't use AF_*: don't mess with headers */ case 2: /* AF_INET */ if (mjt_ntop4(src, dst, size)) return dst; break; case 10: /* AF_INET6 */ if (mjt_ntop6(src, dst, size)) return dst; break; default: errno = EAFNOSUPPORT; return (char*)0; } errno = ENOSPC; return (char*)0; } inet_XtoX_decl const char * fn(ntoa)(struct in_addr addr) { static char buf[4*4]; mjt_ntop4(&addr, buf, sizeof(buf)); return buf; } #endif /* inet_XtoX_prototypes */ #endif /* inet_XtoX_no_ntop */ #ifndef inet_XtoX_no_pton inet_XtoX_decl int fn(pton)(int af, const char *src, void *dst); inet_XtoX_decl int fn(aton)(const char *src, struct in_addr *addr); #ifndef inet_XtoX_prototypes static int mjt_pton4(const char *c, void *dst) { unsigned char *a = dst; unsigned n, o; for (n = 0; n < 4; ++n) { if (*c < '0' || *c > '9') return 0; o = *c++ - '0'; while(*c >= '0' && *c <= '9') if ((o = o * 10 + (*c++ - '0')) > 255) return 0; if (*c++ != (n == 3 ? '\0' : '.')) return 0; *a++ = (unsigned char)o; } return 1; } static int mjt_pton6(const char *c, void *dst) { unsigned short w[8], *a = w, *z, *i; unsigned v, o; const char *sc; unsigned char *d = dst; if (*c != ':') z = (unsigned short*)0; else if (*++c != ':') return 0; else ++c, z = a; i = 0; for(;;) { v = 0; sc = c; for(;;) { if (*c >= '0' && *c <= '9') o = *c - '0'; else if (*c >= 'a' && *c <= 'f') o = *c - 'a' + 10; else if (*c >= 'A' && *c <= 'F') o = *c - 'A' + 10; else break; v = (v << 4) | o; if (v > 0xffff) return 0; ++c; } if (sc == c) { if (z == a && !*c) break; else return 0; } if (*c == ':') { if (a >= w + 8) return 0; *a++ = v; if (*++c == ':') { if (z) return 0; z = a; if (!*++c) break; } } else if (!*c) { if (a >= w + 8) return 0; *a++ = v; break; } else if (*c == '.') { if (a > w + 6) return 0; if (!mjt_pton4(sc, d)) return 0; *a++ = ((unsigned)(d[0]) << 8) | d[1]; *a++ = ((unsigned)(d[2]) << 8) | d[3]; break; } else return 0; } v = w + 8 - a; if ((v && !z) || (!v && z)) return 0; for(i = w; ; ++i) { if (i == z) while(v--) { *d++ = '\0'; *d++ = '\0'; } if (i >= a) break; *d++ = (unsigned char)((*i >> 8) & 255); *d++ = (unsigned char)(*i & 255); } return 1; } inet_XtoX_decl int fn(pton)(int af, const char *src, void *dst) { switch(af) { /* don't use AF_*: don't mess with headers */ case 2 /* AF_INET */: return mjt_pton4(src, dst); case 10 /* AF_INET6 */: return mjt_pton6(src, dst); default: errno = EAFNOSUPPORT; return -1; } } inet_XtoX_decl int fn(aton)(const char *src, struct in_addr *addr) { return mjt_pton4(src, addr); } #endif /* inet_XtoX_prototypes */ #endif /* inet_XtoX_no_pton */ #ifdef TEST int main(int argc, char **argv) { int i; char n0[16], n1[16]; char p0[64], p1[64]; int af = AF_INET; int pl = sizeof(p0); int r0, r1; const char *s0, *s1; while((i = getopt(argc, argv, "46a:p:")) != EOF) switch(i) { case '4': af = AF_INET; break; case '6': af = AF_INET6; break; case 'a': case 'p': pl = atoi(optarg); break; default: return 1; } for(i = optind; i < argc; ++i) { char *a = argv[i]; printf("%s:\n", a); r0 = inet_pton(af, a, n0); printf(" p2n stock: %s\n", (r0 < 0 ? "(notsupp)" : !r0 ? "(inval)" : fn(ntop)(af,n0,p0,sizeof(p0)))); r1 = fn(pton)(af, a, n1); printf(" p2n this : %s\n", (r1 < 0 ? "(notsupp)" : !r1 ? "(inval)" : fn(ntop)(af,n1,p1,sizeof(p1)))); if ((r0 > 0) != (r1 > 0) || (r0 > 0 && r1 > 0 && memcmp(n0, n1, af == AF_INET ? 4 : 16) != 0)) printf(" DIFFER!\n"); s0 = inet_ntop(af, n1, p0, pl); printf(" n2p stock: %s\n", s0 ? s0 : "(inval)"); s1 = fn(ntop)(af, n1, p1, pl); printf(" n2p this : %s\n", s1 ? s1 : "(inval)"); if ((s0 != 0) != (s1 != 0) || (s0 && s1 && strcmp(s0, s1) != 0)) printf(" DIFFER!\n"); } return 0; } #endif /* TEST */ libtorrent-0.16.11/src/net/udns/rblcheck.c0000644000000000000000000002375115175073411013756 /* rblcheck.c dnsbl (rbl) checker application Copyright (C) 2005 Michael Tokarev This file is part of UDNS library, an async DNS stub resolver. 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, in file named COPYING.LGPL; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #ifdef WINDOWS # include #else # include # include # include # include #endif #include #include #include #include "udns.h" #ifndef HAVE_GETOPT # include "getopt.c" #endif static constexpr auto version = "udns-rblcheck " UDNS_VERSION; static char *progname; static void error(int die, const char *fmt, ...) { va_list ap; fprintf(stderr, "%s: ", progname); va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); putc('\n', stderr); fflush(stderr); if (die) exit(1); } struct rblookup { struct ipcheck *parent; struct in_addr key; const char *zone; struct dns_rr_a4 *addr; struct dns_rr_txt *txt; }; struct ipcheck { const char *name; int naddr; int listed; struct rblookup *lookup; }; #define notlisted ((void*)1) static int nzones, nzalloc; static const char **zones; static int do_txt; static int stopfirst; static int verbose = 1; /* verbosity level: * <0 - only bare As/TXTs * 0 - what RBL result * 1(default) - what is listed by RBL: result * 2 - what is[not ]listed by RBL: result, name lookups */ static int listed; static int failures; static void *ecalloc(int size, int cnt) { void *t = calloc(size, cnt); if (!t) error(1, "out of memory"); return t; } static void addzone(const char *zone) { if (nzones >= nzalloc) { const char **zs = (const char**)ecalloc(sizeof(char*), (nzalloc += 16)); if (zones) { memcpy(zs, zones, nzones * sizeof(char*)); free(zones); } zones = zs; } zones[nzones++] = zone; } static int addzonefile(const char *fname) { FILE *f = fopen(fname, "r"); char linebuf[2048]; if (!f) return 0; while(fgets(linebuf, sizeof(linebuf), f)) { char *p = linebuf, *e; while(*p == ' ' || *p == '\t') ++p; if (*p == '#' || *p == '\n') continue; e = p; while(*e && *e != ' ' && *e != '\t' && *e != '\n') ++e; *e++ = '\0'; p = memcpy(ecalloc(e - p, 1), p, e - p); // strdup addzone(p); } fclose(f); return 1; } static void dnserror(struct rblookup *ipl, const char *what) { char buf[4*4]; error(0, "unable to %s for %s (%s): %s", what, dns_ntop(AF_INET, &ipl->key, buf, sizeof(buf)), ipl->zone, dns_strerror(dns_status(0))); ++failures; } static void display_result(struct ipcheck *ipc) { int j; struct rblookup *l, *le; char buf[4*4]; if (!ipc->naddr) return; for (l = ipc->lookup, le = l + nzones * ipc->naddr; l < le; ++l) { if (!l->addr) continue; if (verbose < 2 && l->addr == notlisted) continue; if (verbose >= 0) { dns_ntop(AF_INET, &l->key, buf, sizeof(buf)); if (ipc->name) printf("%s[%s]", ipc->name, buf); else printf("%s", buf); } if (l->addr == notlisted) { printf(" is NOT listed by %s\n", l->zone); continue; } else if (verbose >= 1) printf(" is listed by %s: ", l->zone); else if (verbose >= 0) printf(" %s ", l->zone); if (verbose >= 1 || !do_txt) for (j = 0; j < l->addr->dnsa4_nrr; ++j) printf("%s%s", j ? " " : "", dns_ntop(AF_INET, &l->addr->dnsa4_addr[j], buf, sizeof(buf))); if (!do_txt) ; else if (l->txt) { for(j = 0; j < l->txt->dnstxt_nrr; ++j) { unsigned char *t = l->txt->dnstxt_txt[j].txt; unsigned char *e = t + l->txt->dnstxt_txt[j].len; printf("%s\"", verbose > 0 ? "\n\t" : j ? " " : ""); while(t < e) { if (*t < ' ' || *t >= 127) printf("\\x%02x", *t); else if (*t == '\\' || *t == '"') printf("\\%c", *t); else putchar(*t); ++t; } putchar('"'); } free(l->txt); } else printf("%s", verbose > 0 ? "\n\t" : ""); free(l->addr); putchar('\n'); } free(ipc->lookup); } static void txtcb(struct dns_ctx *ctx, struct dns_rr_txt *r, void *data) { struct rblookup *ipl = data; if (r) { ipl->txt = r; ++ipl->parent->listed; } else if (dns_status(ctx) != DNS_E_NXDOMAIN) dnserror(ipl, "lookup DNSBL TXT record"); } static void a4cb(struct dns_ctx *ctx, struct dns_rr_a4 *r, void *data) { struct rblookup *ipl = data; if (r) { ipl->addr = r; ++listed; if (do_txt) { if (dns_submit_a4dnsbl_txt(0, &ipl->key, ipl->zone, txtcb, ipl)) return; dnserror(ipl, "submit DNSBL TXT record"); } ++ipl->parent->listed; } else if (dns_status(ctx) != DNS_E_NXDOMAIN) dnserror(ipl, "lookup DNSBL A record"); else ipl->addr = notlisted; } static int submit_a_queries(struct ipcheck *ipc, int naddr, const struct in_addr *addr) { int z, a; struct rblookup *rl = ecalloc(sizeof(*rl), nzones * naddr); ipc->lookup = rl; ipc->naddr = naddr; for(a = 0; a < naddr; ++a) { for(z = 0; z < nzones; ++z) { rl->key = addr[a]; rl->zone = zones[z]; rl->parent = ipc; if (!dns_submit_a4dnsbl(0, &rl->key, rl->zone, a4cb, rl)) dnserror(rl, "submit DNSBL A query"); ++rl; } } return 0; } static void namecb(struct dns_ctx *ctx, struct dns_rr_a4 *rr, void *data) { struct ipcheck *ipc = data; if (rr) { submit_a_queries(ipc, rr->dnsa4_nrr, rr->dnsa4_addr); free(rr); } else { error(0, "unable to lookup `%s': %s", ipc->name, dns_strerror(dns_status(ctx))); ++failures; } } static int submit(struct ipcheck *ipc) { struct in_addr addr; if (dns_pton(AF_INET, ipc->name, &addr) > 0) { submit_a_queries(ipc, 1, &addr); ipc->name = NULL; } else if (!dns_submit_a4(0, ipc->name, 0, namecb, ipc)) { error(0, "unable to submit name query for %s: %s\n", ipc->name, dns_strerror(dns_status(0))); ++failures; } return 0; } static void waitdns(struct ipcheck *ipc) { struct timeval tv; fd_set fds; int c; int fd = dns_sock(NULL); time_t now = 0; FD_ZERO(&fds); while((c = dns_timeouts(NULL, -1, now)) > 0) { FD_SET(fd, &fds); tv.tv_sec = c; tv.tv_usec = 0; c = select(fd+1, &fds, NULL, NULL, &tv); now = time(NULL); if (c > 0) dns_ioevent(NULL, now); if (stopfirst && ipc->listed) break; } } int main(int argc, char **argv) { int c; struct ipcheck ipc; char *nameserver = NULL; int zgiven = 0; if (!(progname = strrchr(argv[0], '/'))) progname = argv[0]; else argv[0] = ++progname; while((c = getopt(argc, argv, "hqtvms:S:cn:")) != EOF) switch(c) { case 's': ++zgiven; addzone(optarg); break; case 'S': ++zgiven; if (addzonefile(optarg)) break; error(1, "unable to read zonefile `%s'", optarg); break; /* avoid warning */ case 'c': ++zgiven; nzones = 0; break; case 'q': --verbose; break; case 'v': ++verbose; break; case 't': do_txt = 1; break; case 'n': nameserver = optarg; break; case 'm': ++stopfirst; break; case 'h': printf("%s: %s (udns library version %s).\n", progname, version, dns_version()); printf("Usage is: %s [options] address..\n", progname); printf( "Where options are:\n" " -h - print this help and exit\n" " -s service - add the service (DNSBL zone) to the serice list\n" " -S service-file - add the DNSBL zone(s) read from the given file\n" " -c - clear service list\n" " -v - increase verbosity level (more -vs => more verbose)\n" " -q - decrease verbosity level (opposite of -v)\n" " -t - obtain and print TXT records if any\n" " -m - stop checking after first address match in any list\n" " -n ipaddr - use the given nameserver instead of the default\n" "(if no -s or -S option is given, use $RBLCHECK_ZONES, ~/.rblcheckrc\n" "or /etc/rblcheckrc in that order)\n" ); return 0; default: error(1, "use `%s -h' for help", progname); } if (!zgiven) { char *s = getenv("RBLCHECK_ZONES"); if (s) { char *k; s = strdup(s); for(k = strtok(s, " \t"); k; k = strtok(NULL, " \t")) addzone(k); free(s); } else { /* probably worthless on windows? */ char *path; char *home = getenv("HOME"); if (!home) home = "."; path = malloc(strlen(home) + 1 + sizeof(".rblcheckrc")); sprintf(path, "%s/.rblcheckrc", home); if (!addzonefile(path)) addzonefile("/etc/rblcheckrc"); free(path); } } if (!nzones) error(1, "no service (zone) list specified (-s or -S option)"); argv += optind; argc -= optind; if (!argc) return 0; if (dns_init(NULL, 0) < 0) error(1, "unable to initialize DNS library: %s", strerror(errno)); if (nameserver) { dns_add_serv(NULL, NULL); if (dns_add_serv(NULL, nameserver) < 0) error(1, "wrong IP address for a nameserver: `%s'", nameserver); } if (dns_open(NULL) < 0) error(1, "unable to initialize DNS library: %s", strerror(errno)); for (c = 0; c < argc; ++c) { if (c && (verbose > 1 || (verbose == 1 && do_txt))) putchar('\n'); memset(&ipc, 0, sizeof(ipc)); ipc.name = argv[c]; submit(&ipc); waitdns(&ipc); display_result(&ipc); if (stopfirst > 1 && listed) break; } return listed ? 100 : failures ? 2 : 0; } libtorrent-0.16.11/src/net/udns/udns_codes.c0000644000000000000000000001464115175073411014325 /* Automatically generated. */ #include "udns.h" const struct dns_nameval dns_typetab[] = { {DNS_T_INVALID,"INVALID"}, {DNS_T_A,"A"}, {DNS_T_NS,"NS"}, {DNS_T_MD,"MD"}, {DNS_T_MF,"MF"}, {DNS_T_CNAME,"CNAME"}, {DNS_T_SOA,"SOA"}, {DNS_T_MB,"MB"}, {DNS_T_MG,"MG"}, {DNS_T_MR,"MR"}, {DNS_T_NULL,"NULL"}, {DNS_T_WKS,"WKS"}, {DNS_T_PTR,"PTR"}, {DNS_T_HINFO,"HINFO"}, {DNS_T_MINFO,"MINFO"}, {DNS_T_MX,"MX"}, {DNS_T_TXT,"TXT"}, {DNS_T_RP,"RP"}, {DNS_T_AFSDB,"AFSDB"}, {DNS_T_X25,"X25"}, {DNS_T_ISDN,"ISDN"}, {DNS_T_RT,"RT"}, {DNS_T_NSAP,"NSAP"}, {DNS_T_NSAP_PTR,"NSAP_PTR"}, {DNS_T_SIG,"SIG"}, {DNS_T_KEY,"KEY"}, {DNS_T_PX,"PX"}, {DNS_T_GPOS,"GPOS"}, {DNS_T_AAAA,"AAAA"}, {DNS_T_LOC,"LOC"}, {DNS_T_NXT,"NXT"}, {DNS_T_EID,"EID"}, {DNS_T_NIMLOC,"NIMLOC"}, {DNS_T_SRV,"SRV"}, {DNS_T_ATMA,"ATMA"}, {DNS_T_NAPTR,"NAPTR"}, {DNS_T_KX,"KX"}, {DNS_T_CERT,"CERT"}, {DNS_T_A6,"A6"}, {DNS_T_DNAME,"DNAME"}, {DNS_T_SINK,"SINK"}, {DNS_T_OPT,"OPT"}, {DNS_T_DS,"DS"}, {DNS_T_SSHFP,"SSHFP"}, {DNS_T_IPSECKEY,"IPSECKEY"}, {DNS_T_RRSIG,"RRSIG"}, {DNS_T_NSEC,"NSEC"}, {DNS_T_DNSKEY,"DNSKEY"}, {DNS_T_DHCID,"DHCID"}, {DNS_T_NSEC3,"NSEC3"}, {DNS_T_NSEC3PARAMS,"NSEC3PARAMS"}, {DNS_T_TALINK,"TALINK"}, {DNS_T_SPF,"SPF"}, {DNS_T_UINFO,"UINFO"}, {DNS_T_UID,"UID"}, {DNS_T_GID,"GID"}, {DNS_T_UNSPEC,"UNSPEC"}, {DNS_T_TSIG,"TSIG"}, {DNS_T_IXFR,"IXFR"}, {DNS_T_AXFR,"AXFR"}, {DNS_T_MAILB,"MAILB"}, {DNS_T_MAILA,"MAILA"}, {DNS_T_ANY,"ANY"}, {DNS_T_ZXFR,"ZXFR"}, {DNS_T_DLV,"DLV"}, {DNS_T_MAX,"MAX"}, {0,0}}; const char *dns_typename(enum dns_type code) { static char nm[20]; switch(code) { case DNS_T_INVALID: return dns_typetab[0].name; case DNS_T_A: return dns_typetab[1].name; case DNS_T_NS: return dns_typetab[2].name; case DNS_T_MD: return dns_typetab[3].name; case DNS_T_MF: return dns_typetab[4].name; case DNS_T_CNAME: return dns_typetab[5].name; case DNS_T_SOA: return dns_typetab[6].name; case DNS_T_MB: return dns_typetab[7].name; case DNS_T_MG: return dns_typetab[8].name; case DNS_T_MR: return dns_typetab[9].name; case DNS_T_NULL: return dns_typetab[10].name; case DNS_T_WKS: return dns_typetab[11].name; case DNS_T_PTR: return dns_typetab[12].name; case DNS_T_HINFO: return dns_typetab[13].name; case DNS_T_MINFO: return dns_typetab[14].name; case DNS_T_MX: return dns_typetab[15].name; case DNS_T_TXT: return dns_typetab[16].name; case DNS_T_RP: return dns_typetab[17].name; case DNS_T_AFSDB: return dns_typetab[18].name; case DNS_T_X25: return dns_typetab[19].name; case DNS_T_ISDN: return dns_typetab[20].name; case DNS_T_RT: return dns_typetab[21].name; case DNS_T_NSAP: return dns_typetab[22].name; case DNS_T_NSAP_PTR: return dns_typetab[23].name; case DNS_T_SIG: return dns_typetab[24].name; case DNS_T_KEY: return dns_typetab[25].name; case DNS_T_PX: return dns_typetab[26].name; case DNS_T_GPOS: return dns_typetab[27].name; case DNS_T_AAAA: return dns_typetab[28].name; case DNS_T_LOC: return dns_typetab[29].name; case DNS_T_NXT: return dns_typetab[30].name; case DNS_T_EID: return dns_typetab[31].name; case DNS_T_NIMLOC: return dns_typetab[32].name; case DNS_T_SRV: return dns_typetab[33].name; case DNS_T_ATMA: return dns_typetab[34].name; case DNS_T_NAPTR: return dns_typetab[35].name; case DNS_T_KX: return dns_typetab[36].name; case DNS_T_CERT: return dns_typetab[37].name; case DNS_T_A6: return dns_typetab[38].name; case DNS_T_DNAME: return dns_typetab[39].name; case DNS_T_SINK: return dns_typetab[40].name; case DNS_T_OPT: return dns_typetab[41].name; case DNS_T_DS: return dns_typetab[42].name; case DNS_T_SSHFP: return dns_typetab[43].name; case DNS_T_IPSECKEY: return dns_typetab[44].name; case DNS_T_RRSIG: return dns_typetab[45].name; case DNS_T_NSEC: return dns_typetab[46].name; case DNS_T_DNSKEY: return dns_typetab[47].name; case DNS_T_DHCID: return dns_typetab[48].name; case DNS_T_NSEC3: return dns_typetab[49].name; case DNS_T_NSEC3PARAMS: return dns_typetab[50].name; case DNS_T_TALINK: return dns_typetab[51].name; case DNS_T_SPF: return dns_typetab[52].name; case DNS_T_UINFO: return dns_typetab[53].name; case DNS_T_UID: return dns_typetab[54].name; case DNS_T_GID: return dns_typetab[55].name; case DNS_T_UNSPEC: return dns_typetab[56].name; case DNS_T_TSIG: return dns_typetab[57].name; case DNS_T_IXFR: return dns_typetab[58].name; case DNS_T_AXFR: return dns_typetab[59].name; case DNS_T_MAILB: return dns_typetab[60].name; case DNS_T_MAILA: return dns_typetab[61].name; case DNS_T_ANY: return dns_typetab[62].name; case DNS_T_ZXFR: return dns_typetab[63].name; case DNS_T_DLV: return dns_typetab[64].name; case DNS_T_MAX: return dns_typetab[65].name; } return _dns_format_code(nm,"type",code); } const struct dns_nameval dns_classtab[] = { {DNS_C_INVALID,"INVALID"}, {DNS_C_IN,"IN"}, {DNS_C_CH,"CH"}, {DNS_C_HS,"HS"}, {DNS_C_ANY,"ANY"}, {0,0}}; const char *dns_classname(enum dns_class code) { static char nm[20]; switch(code) { case DNS_C_INVALID: return dns_classtab[0].name; case DNS_C_IN: return dns_classtab[1].name; case DNS_C_CH: return dns_classtab[2].name; case DNS_C_HS: return dns_classtab[3].name; case DNS_C_ANY: return dns_classtab[4].name; } return _dns_format_code(nm,"class",code); } const struct dns_nameval dns_rcodetab[] = { {DNS_R_NOERROR,"NOERROR"}, {DNS_R_FORMERR,"FORMERR"}, {DNS_R_SERVFAIL,"SERVFAIL"}, {DNS_R_NXDOMAIN,"NXDOMAIN"}, {DNS_R_NOTIMPL,"NOTIMPL"}, {DNS_R_REFUSED,"REFUSED"}, {DNS_R_YXDOMAIN,"YXDOMAIN"}, {DNS_R_YXRRSET,"YXRRSET"}, {DNS_R_NXRRSET,"NXRRSET"}, {DNS_R_NOTAUTH,"NOTAUTH"}, {DNS_R_NOTZONE,"NOTZONE"}, {DNS_R_BADSIG,"BADSIG"}, {DNS_R_BADKEY,"BADKEY"}, {DNS_R_BADTIME,"BADTIME"}, {0,0}}; const char *dns_rcodename(enum dns_rcode code) { static char nm[20]; switch(code) { case DNS_R_NOERROR: return dns_rcodetab[0].name; case DNS_R_FORMERR: return dns_rcodetab[1].name; case DNS_R_SERVFAIL: return dns_rcodetab[2].name; case DNS_R_NXDOMAIN: return dns_rcodetab[3].name; case DNS_R_NOTIMPL: return dns_rcodetab[4].name; case DNS_R_REFUSED: return dns_rcodetab[5].name; case DNS_R_YXDOMAIN: return dns_rcodetab[6].name; case DNS_R_YXRRSET: return dns_rcodetab[7].name; case DNS_R_NXRRSET: return dns_rcodetab[8].name; case DNS_R_NOTAUTH: return dns_rcodetab[9].name; case DNS_R_NOTZONE: return dns_rcodetab[10].name; case DNS_R_BADSIG: return dns_rcodetab[11].name; case DNS_R_BADKEY: return dns_rcodetab[12].name; case DNS_R_BADTIME: return dns_rcodetab[13].name; } return _dns_format_code(nm,"rcode",code); } libtorrent-0.16.11/src/net/udns/ex-rdns.c0000644000000000000000000000620215175073411013551 /* ex-rdns.c parallel rDNS resolver example - read IP addresses from stdin, write domain names to stdout Copyright (C) 2005 Michael Tokarev This file is part of UDNS library, an async DNS stub resolver. 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, in file named COPYING.LGPL; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include "udns.h" static int curq; static const char *n2ip(const unsigned char *c) { static char b[sizeof("255.255.255.255")]; sprintf(b, "%u.%u.%u.%u", c[0], c[1], c[2], c[3]); return b; } static void dnscb(struct dns_ctx *ctx, struct dns_rr_ptr *rr, void *data) { const char *ip = n2ip((unsigned char *)&data); int i; --curq; if (rr) { printf("%s", ip); for(i = 0; i < rr->dnsptr_nrr; ++i) printf(" %s", rr->dnsptr_ptr[i]); putchar('\n'); free(rr); } else fprintf(stderr, "%s: %s\n", ip, dns_strerror(dns_status(ctx))); } int main(int argc, char **argv) { int c; time_t now; int maxq = 10; struct pollfd pfd; char linebuf[1024]; char *eol; int eof; if (dns_init(NULL, 1) < 0) { fprintf(stderr, "unable to initialize dns library\n"); return 1; } while((c = getopt(argc, argv, "m:r")) != EOF) switch(c) { case 'm': maxq = atoi(optarg); break; case 'r': dns_set_opt(0, DNS_OPT_FLAGS, dns_set_opt(0, DNS_OPT_FLAGS, -1) | DNS_NORD); break; default: return 1; } if (argc != optind) return 1; pfd.fd = dns_sock(0); pfd.events = POLLIN; now = time(NULL); c = optind; eof = 0; while(curq || !eof) { if (!eof && curq < maxq) { union { struct in_addr a; void *p; } pa; if (!fgets(linebuf, sizeof(linebuf), stdin)) { eof = 1; continue; } eol = strchr(linebuf, '\n'); if (eol) *eol = '\0'; if (!linebuf[0]) continue; if (dns_pton(AF_INET, linebuf, &pa.a) <= 0) fprintf(stderr, "%s: invalid address\n", linebuf); else if (dns_submit_a4ptr(0, &pa.a, dnscb, pa.p) == 0) fprintf(stderr, "%s: unable to submit query: %s\n", linebuf, dns_strerror(dns_status(0))); else ++curq; continue; } if (curq) { c = dns_timeouts(0, -1, now); c = poll(&pfd, 1, c < 0 ? -1 : c * 1000); now = time(NULL); if (c) dns_ioevent(0, now); } } return 0; } libtorrent-0.16.11/src/net/udns/udns.h0000644000000000000000000006516315175073411013162 /* udns.h header file for the UDNS library. Copyright (C) 2005 Michael Tokarev This file is part of UDNS library, an async DNS stub resolver. 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, in file named COPYING.LGPL; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef UDNS_VERSION /* include guard */ #define UDNS_VERSION "0.6" #ifdef WINDOWS # ifdef UDNS_DYNAMIC_LIBRARY # ifdef DNS_LIBRARY_BUILD # define UDNS_API __declspec(dllexport) # define UDNS_DATA_API __declspec(dllexport) # else # define UDNS_API __declspec(dllimport) # define UDNS_DATA_API __declspec(dllimport) # endif # endif #endif #ifndef UDNS_API # define UDNS_API #endif #ifndef UDNS_DATA_API # define UDNS_DATA_API #endif #include /* for time_t */ #ifdef __cplusplus extern "C" { #endif /* forward declarations if sockets stuff isn't #include'd */ struct in_addr; struct in6_addr; struct sockaddr; /**************************************************************************/ /**************** Common definitions **************************************/ UDNS_API const char * dns_version(void); struct dns_ctx; struct dns_query; /* shorthand for [const] unsigned char */ typedef unsigned char dnsc_t; typedef const unsigned char dnscc_t; #define DNS_MAXDN 255 /* max DN length */ #define DNS_DNPAD 1 /* padding for DN buffers */ #define DNS_MAXLABEL 63 /* max DN label length */ #define DNS_MAXNAME 1024 /* max asciiz domain name length */ #define DNS_HSIZE 12 /* DNS packet header size */ #define DNS_PORT 53 /* default domain port */ #define DNS_MAXSERV 6 /* max servers to consult */ #define DNS_MAXPACKET 512 /* max traditional-DNS UDP packet size */ #define DNS_EDNS0PACKET 4096 /* EDNS0 packet size to use */ enum dns_class { /* DNS RR Classes */ DNS_C_INVALID = 0, /* invalid class */ DNS_C_IN = 1, /* Internet */ DNS_C_CH = 3, /* CHAOS */ DNS_C_HS = 4, /* HESIOD */ DNS_C_ANY = 255 /* wildcard */ }; enum dns_type { /* DNS RR Types */ DNS_T_INVALID = 0, /* Cookie. */ DNS_T_A = 1, /* Host address. */ DNS_T_NS = 2, /* Authoritative server. */ DNS_T_MD = 3, /* Mail destination. */ DNS_T_MF = 4, /* Mail forwarder. */ DNS_T_CNAME = 5, /* Canonical name. */ DNS_T_SOA = 6, /* Start of authority zone. */ DNS_T_MB = 7, /* Mailbox domain name. */ DNS_T_MG = 8, /* Mail group member. */ DNS_T_MR = 9, /* Mail rename name. */ DNS_T_NULL = 10, /* Null resource record. */ DNS_T_WKS = 11, /* Well known service. */ DNS_T_PTR = 12, /* Domain name pointer. */ DNS_T_HINFO = 13, /* Host information. */ DNS_T_MINFO = 14, /* Mailbox information. */ DNS_T_MX = 15, /* Mail routing information. */ DNS_T_TXT = 16, /* Text strings. */ DNS_T_RP = 17, /* Responsible person. */ DNS_T_AFSDB = 18, /* AFS cell database. */ DNS_T_X25 = 19, /* X_25 calling address. */ DNS_T_ISDN = 20, /* ISDN calling address. */ DNS_T_RT = 21, /* Router. */ DNS_T_NSAP = 22, /* NSAP address. */ DNS_T_NSAP_PTR = 23, /* Reverse NSAP lookup (deprecated). */ DNS_T_SIG = 24, /* Security signature. */ DNS_T_KEY = 25, /* Security key. */ DNS_T_PX = 26, /* X.400 mail mapping. */ DNS_T_GPOS = 27, /* Geographical position (withdrawn). */ DNS_T_AAAA = 28, /* Ip6 Address. */ DNS_T_LOC = 29, /* Location Information. */ DNS_T_NXT = 30, /* Next domain (security). */ DNS_T_EID = 31, /* Endpoint identifier. */ DNS_T_NIMLOC = 32, /* Nimrod Locator. */ DNS_T_SRV = 33, /* Server Selection. */ DNS_T_ATMA = 34, /* ATM Address */ DNS_T_NAPTR = 35, /* Naming Authority PoinTeR */ DNS_T_KX = 36, /* Key Exchange */ DNS_T_CERT = 37, /* Certification record */ DNS_T_A6 = 38, /* IPv6 address (deprecates AAAA) */ DNS_T_DNAME = 39, /* Non-terminal DNAME (for IPv6) */ DNS_T_SINK = 40, /* Kitchen sink (experimentatl) */ DNS_T_OPT = 41, /* EDNS0 option (meta-RR) */ DNS_T_DS = 43, /* DNSSEC */ DNS_T_SSHFP = 44, DNS_T_IPSECKEY = 45, DNS_T_RRSIG = 46, /* DNSSEC */ DNS_T_NSEC = 47, /* DNSSEC */ DNS_T_DNSKEY = 48, DNS_T_DHCID = 49, DNS_T_NSEC3 = 50, DNS_T_NSEC3PARAMS = 51, DNS_T_TALINK = 58, /* draft-ietf-dnsop-trust-history */ DNS_T_SPF = 99, DNS_T_UINFO = 100, DNS_T_UID = 101, DNS_T_GID = 102, DNS_T_UNSPEC = 103, DNS_T_TSIG = 250, /* Transaction signature. */ DNS_T_IXFR = 251, /* Incremental zone transfer. */ DNS_T_AXFR = 252, /* Transfer zone of authority. */ DNS_T_MAILB = 253, /* Transfer mailbox records. */ DNS_T_MAILA = 254, /* Transfer mail agent records. */ DNS_T_ANY = 255, /* Wildcard match. */ DNS_T_ZXFR = 256, /* BIND-specific, nonstandard. */ DNS_T_DLV = 32769, /* RFC 4431, 5074, DNSSEC Lookaside Validation */ DNS_T_MAX = 65536 }; /**************************************************************************/ /**************** Domain Names (DNs) **************************************/ /* return length of the DN */ UDNS_API unsigned dns_dnlen(dnscc_t *dn); /* return #of labels in a DN */ UDNS_API unsigned dns_dnlabels(dnscc_t *dn); /* lower- and uppercase single DN char */ #define DNS_DNLC(c) ((c) >= 'A' && (c) <= 'Z' ? (c) - 'A' + 'a' : (c)) #define DNS_DNUC(c) ((c) >= 'a' && (c) <= 'z' ? (c) - 'a' + 'A' : (c)) /* compare the DNs, return dnlen of equal or 0 if not */ UDNS_API unsigned dns_dnequal(dnscc_t *dn1, dnscc_t *dn2); /* copy one DN to another, size checking */ UDNS_API unsigned dns_dntodn(dnscc_t *sdn, dnsc_t *ddn, unsigned ddnsiz); /* convert asciiz string of length namelen (0 to use strlen) to DN */ UDNS_API int dns_ptodn(const char *name, unsigned namelen, dnsc_t *dn, unsigned dnsiz, int *isabs); /* simpler form of dns_ptodn() */ #define dns_sptodn(name,dn,dnsiz) dns_ptodn((name),0,(dn),(dnsiz),0) UDNS_DATA_API extern dnscc_t dns_inaddr_arpa_dn[14]; #define DNS_A4RSIZE 30 UDNS_API int dns_a4todn(const struct in_addr *addr, dnscc_t *tdn, dnsc_t *dn, unsigned dnsiz); UDNS_API int dns_a4ptodn(const struct in_addr *addr, const char *tname, dnsc_t *dn, unsigned dnsiz); UDNS_API dnsc_t * dns_a4todn_(const struct in_addr *addr, dnsc_t *dn, dnsc_t *dne); UDNS_DATA_API extern dnscc_t dns_ip6_arpa_dn[10]; #define DNS_A6RSIZE 74 UDNS_API int dns_a6todn(const struct in6_addr *addr, dnscc_t *tdn, dnsc_t *dn, unsigned dnsiz); UDNS_API int dns_a6ptodn(const struct in6_addr *addr, const char *tname, dnsc_t *dn, unsigned dnsiz); UDNS_API dnsc_t * dns_a6todn_(const struct in6_addr *addr, dnsc_t *dn, dnsc_t *dne); /* convert DN into asciiz string */ UDNS_API int dns_dntop(dnscc_t *dn, char *name, unsigned namesiz); /* convert DN into asciiz string, using static buffer (NOT thread-safe!) */ UDNS_API const char * dns_dntosp(dnscc_t *dn); /* return buffer size (incl. null byte) required for asciiz form of a DN */ UDNS_API unsigned dns_dntop_size(dnscc_t *dn); /* either wrappers or reimplementations for inet_ntop() and inet_pton() */ UDNS_API const char *dns_ntop(int af, const void *src, char *dst, unsigned size); UDNS_API int dns_pton(int af, const char *src, void *dst); /**************************************************************************/ /**************** DNS raw packet layout ***********************************/ enum dns_rcode { /* reply codes */ DNS_R_NOERROR = 0, /* ok, no error */ DNS_R_FORMERR = 1, /* format error */ DNS_R_SERVFAIL = 2, /* server failed */ DNS_R_NXDOMAIN = 3, /* domain does not exists */ DNS_R_NOTIMPL = 4, /* not implemented */ DNS_R_REFUSED = 5, /* query refused */ /* these are for BIND_UPDATE */ DNS_R_YXDOMAIN = 6, /* Name exists */ DNS_R_YXRRSET = 7, /* RRset exists */ DNS_R_NXRRSET = 8, /* RRset does not exist */ DNS_R_NOTAUTH = 9, /* Not authoritative for zone */ DNS_R_NOTZONE = 10, /* Zone of record different from zone section */ /*ns_r_max = 11,*/ /* The following are TSIG extended errors */ DNS_R_BADSIG = 16, DNS_R_BADKEY = 17, DNS_R_BADTIME = 18 }; static __inline unsigned dns_get16(dnscc_t *s) { return ((unsigned)s[0]<<8) | s[1]; } static __inline unsigned dns_get32(dnscc_t *s) { return ((unsigned)s[0]<<24) | ((unsigned)s[1]<<16) | ((unsigned)s[2]<<8) | s[3]; } static __inline dnsc_t *dns_put16(dnsc_t *d, unsigned n) { *d++ = (dnsc_t)((n >> 8) & 255); *d++ = (dnsc_t)(n & 255); return d; } static __inline dnsc_t *dns_put32(dnsc_t *d, unsigned n) { *d++ = (dnsc_t)((n >> 24) & 255); *d++ = (dnsc_t)((n >> 16) & 255); *d++ = (dnsc_t)((n >> 8) & 255); *d++ = (dnsc_t)(n & 255); return d; } /* DNS Header layout */ enum { /* bytes 0:1 - query ID */ DNS_H_QID1 = 0, DNS_H_QID2 = 1, DNS_H_QID = DNS_H_QID1, #define dns_qid(pkt) dns_get16((pkt)+DNS_H_QID) /* byte 2: flags1 */ DNS_H_F1 = 2, DNS_HF1_QR = 0x80, /* query response flag */ #define dns_qr(pkt) ((pkt)[DNS_H_F1]&DNS_HF1_QR) DNS_HF1_OPCODE = 0x78, /* opcode, 0 = query */ #define dns_opcode(pkt) (((pkt)[DNS_H_F1]&DNS_HF1_OPCODE)>>3) DNS_HF1_AA = 0x04, /* auth answer */ #define dns_aa(pkt) ((pkt)[DNS_H_F1]&DNS_HF1_AA) DNS_HF1_TC = 0x02, /* truncation flag */ #define dns_tc(pkt) ((pkt)[DNS_H_F1]&DNS_HF1_TC) DNS_HF1_RD = 0x01, /* recursion desired (may be set in query) */ #define dns_rd(pkt) ((pkt)[DNS_H_F1]&DNS_HF1_RD) /* byte 3: flags2 */ DNS_H_F2 = 3, DNS_HF2_RA = 0x80, /* recursion available */ #define dns_ra(pkt) ((pkt)[DNS_H_F2]&DNS_HF2_RA) DNS_HF2_Z = 0x40, /* reserved */ DNS_HF2_AD = 0x20, /* DNSSEC: authentic data */ #define dns_ad(pkt) ((pkt)[DNS_H_F2]&DNS_HF2_AD) DNS_HF2_CD = 0x10, /* DNSSEC: checking disabled */ #define dns_cd(pkt) ((pkt)[DNS_H_F2]&DNS_HF2_CD) DNS_HF2_RCODE = 0x0f, /* response code, DNS_R_XXX above */ #define dns_rcode(pkt) ((pkt)[DNS_H_F2]&DNS_HF2_RCODE) /* bytes 4:5: qdcount, numqueries */ DNS_H_QDCNT1 = 4, DNS_H_QDCNT2 = 5, DNS_H_QDCNT = DNS_H_QDCNT1, #define dns_numqd(pkt) dns_get16((pkt)+4) /* bytes 6:7: ancount, numanswers */ DNS_H_ANCNT1 = 6, DNS_H_ANCNT2 = 7, DNS_H_ANCNT = DNS_H_ANCNT1, #define dns_numan(pkt) dns_get16((pkt)+6) /* bytes 8:9: nscount, numauthority */ DNS_H_NSCNT1 = 8, DNS_H_NSCNT2 = 9, DNS_H_NSCNT = DNS_H_NSCNT1, #define dns_numns(pkt) dns_get16((pkt)+8) /* bytes 10:11: arcount, numadditional */ DNS_H_ARCNT1 = 10, DNS_H_ARCNT2 = 11, DNS_H_ARCNT = DNS_H_ARCNT1, #define dns_numar(pkt) dns_get16((pkt)+10) #define dns_payload(pkt) ((pkt)+DNS_HSIZE) /* EDNS0 (OPT RR) flags (Ext. Flags) */ DNS_EF1_DO = 0x80, /* DNSSEC OK */ }; /* packet buffer: start at pkt, end before pkte, current pos *curp. * extract a DN and set *curp to the next byte after DN in packet. * return -1 on error, 0 if dnsiz is too small, or dnlen on ok. */ UDNS_API int dns_getdn(dnscc_t *pkt, dnscc_t **curp, dnscc_t *end, dnsc_t *dn, unsigned dnsiz); /* skip the DN at position cur in packet ending before pkte, * return pointer to the next byte after the DN or NULL on error */ UDNS_API dnscc_t * dns_skipdn(dnscc_t *end, dnscc_t *cur); struct dns_rr { /* DNS Resource Record */ dnsc_t dnsrr_dn[DNS_MAXDN]; /* the DN of the RR */ enum dns_class dnsrr_cls; /* Class */ enum dns_type dnsrr_typ; /* Type */ unsigned dnsrr_ttl; /* Time-To-Live (TTL) */ unsigned dnsrr_dsz; /* data size */ dnscc_t *dnsrr_dptr; /* pointer to start of data */ dnscc_t *dnsrr_dend; /* past end of data */ }; struct dns_parse { /* RR/packet parsing state */ dnscc_t *dnsp_pkt; /* start of the packet */ dnscc_t *dnsp_end; /* end of the packet */ dnscc_t *dnsp_cur; /* current packet position */ dnscc_t *dnsp_ans; /* start of answer section */ int dnsp_rrl; /* number of RRs left to go */ int dnsp_nrr; /* RR count so far */ unsigned dnsp_ttl; /* TTL value so far */ dnscc_t *dnsp_qdn; /* the RR DN we're looking for */ enum dns_class dnsp_qcls; /* RR class we're looking for or 0 */ enum dns_type dnsp_qtyp; /* RR type we're looking for or 0 */ dnsc_t dnsp_dnbuf[DNS_MAXDN]; /* domain buffer */ }; /* initialize the parse structure */ UDNS_API void dns_initparse(struct dns_parse *p, dnscc_t *qdn, dnscc_t *pkt, dnscc_t *cur, dnscc_t *end); /* search next RR, <0=error, 0=no more RRs, >0 = found. */ UDNS_API int dns_nextrr(struct dns_parse *p, struct dns_rr *rr); UDNS_API void dns_rewind(struct dns_parse *p, dnscc_t *qdn); /**************************************************************************/ /**************** Resolver Context ****************************************/ /* default resolver context */ UDNS_DATA_API extern struct dns_ctx dns_defctx; /* reset resolver context to default state, close it if open, drop queries */ UDNS_API void dns_reset(struct dns_ctx *ctx); /* reset resolver context and read in system configuration */ UDNS_API int dns_init(struct dns_ctx *ctx, int do_open); /* return new resolver context with the same settings as copy */ UDNS_API struct dns_ctx * dns_new(const struct dns_ctx *copy); /* free resolver context returned by dns_new(); all queries are dropped */ UDNS_API void dns_free(struct dns_ctx *ctx); /* add nameserver for a resolver context (or reset nslist if serv==NULL) */ UDNS_API int dns_add_serv(struct dns_ctx *ctx, const char *serv); /* add nameserver using struct sockaddr structure (with ports) */ UDNS_API int dns_add_serv_s(struct dns_ctx *ctx, const struct sockaddr *sa); /* add search list element for a resolver context (or reset it if srch==NULL) */ UDNS_API int dns_add_srch(struct dns_ctx *ctx, const char *srch); /* set options for a resolver context */ UDNS_API int dns_set_opts(struct dns_ctx *ctx, const char *opts); enum dns_opt { /* options */ DNS_OPT_FLAGS, /* flags, DNS_F_XXX */ DNS_OPT_TIMEOUT, /* timeout in secounds */ DNS_OPT_NTRIES, /* number of retries */ DNS_OPT_NDOTS, /* ndots */ DNS_OPT_UDPSIZE, /* EDNS0 UDP size */ DNS_OPT_PORT, /* port to use */ }; /* set or get (if val<0) an option */ UDNS_API int dns_set_opt(struct dns_ctx *ctx, enum dns_opt opt, int val); enum dns_flags { DNS_NOSRCH = 0x00010000, /* do not perform search */ DNS_NORD = 0x00020000, /* request no recursion */ DNS_AAONLY = 0x00040000, /* set AA flag in queries */ DNS_SET_DO = 0x00080000, /* set EDNS0 "DO" bit (DNSSEC OK) */ DNS_SET_CD = 0x00100000, /* set CD bit (DNSSEC: checking disabled) */ }; /* set the debug function pointer */ typedef void (dns_dbgfn)(int code, const struct sockaddr *sa, unsigned salen, dnscc_t *pkt, int plen, const struct dns_query *q, void *data); UDNS_API void dns_set_dbgfn(struct dns_ctx *ctx, dns_dbgfn *dbgfn); /* open and return UDP socket */ UDNS_API int dns_open(struct dns_ctx *ctx); /* return UDP socket or -1 if not open */ UDNS_API int dns_sock(const struct dns_ctx *ctx); /* close the UDP socket */ UDNS_API void dns_close(struct dns_ctx *ctx); /* return number of requests queued */ UDNS_API int dns_active(const struct dns_ctx *ctx); /* return status of the last operation */ UDNS_API int dns_status(const struct dns_ctx *ctx); UDNS_API void dns_setstatus(struct dns_ctx *ctx, int status); /* handle I/O event on UDP socket */ UDNS_API void dns_ioevent(struct dns_ctx *ctx, time_t now); /* process any timeouts, return time in secounds to the * next timeout (or -1 if none) but not greather than maxwait */ UDNS_API int dns_timeouts(struct dns_ctx *ctx, int maxwait, time_t now); /* define timer requesting routine to use */ typedef void dns_utm_fn(struct dns_ctx *ctx, int timeout, void *data); UDNS_API void dns_set_tmcbck(struct dns_ctx *ctx, dns_utm_fn *fn, void *data); /**************************************************************************/ /**************** Making Queries ******************************************/ /* query callback routine */ typedef void dns_query_fn(struct dns_ctx *ctx, void *result, void *data); /* query parse routine: raw DNS => application structure */ typedef int dns_parse_fn(dnscc_t *qdn, dnscc_t *pkt, dnscc_t *cur, dnscc_t *end, void **res); enum dns_status { DNS_E_NOERROR = 0, /* ok, not an error */ DNS_E_TEMPFAIL = -1, /* timeout, SERVFAIL or similar */ DNS_E_PROTOCOL = -2, /* got garbled reply */ DNS_E_NXDOMAIN = -3, /* domain does not exists */ DNS_E_NODATA = -4, /* domain exists but no data of reqd type */ DNS_E_NOMEM = -5, /* out of memory while processing */ DNS_E_BADQUERY = -6 /* the query is malformed */ }; /* submit generic DN query */ UDNS_API struct dns_query * dns_submit_dn(struct dns_ctx *ctx, dnscc_t *dn, int qcls, int qtyp, int flags, dns_parse_fn *parse, dns_query_fn *cbck, void *data); /* submit generic name query */ UDNS_API struct dns_query * dns_submit_p(struct dns_ctx *ctx, const char *name, int qcls, int qtyp, int flags, dns_parse_fn *parse, dns_query_fn *cbck, void *data); /* cancel the given async query in progress */ UDNS_API int dns_cancel(struct dns_ctx *ctx, struct dns_query *q); /* resolve a generic query, return the answer */ UDNS_API void * dns_resolve_dn(struct dns_ctx *ctx, dnscc_t *qdn, int qcls, int qtyp, int flags, dns_parse_fn *parse); UDNS_API void * dns_resolve_p(struct dns_ctx *ctx, const char *qname, int qcls, int qtyp, int flags, dns_parse_fn *parse); UDNS_API void * dns_resolve(struct dns_ctx *ctx, struct dns_query *q); /* Specific RR handlers */ #define dns_rr_common(prefix) \ char *prefix##_cname; /* canonical name */ \ char *prefix##_qname; /* original query name */ \ unsigned prefix##_ttl; /* TTL value */ \ int prefix##_nrr /* number of records */ struct dns_rr_null { /* NULL RRset, aka RRset template */ dns_rr_common(dnsn); }; UDNS_API int dns_stdrr_size(const struct dns_parse *p); UDNS_API void * dns_stdrr_finish(struct dns_rr_null *ret, char *cp, const struct dns_parse *p); struct dns_rr_a4 { /* the A RRset */ dns_rr_common(dnsa4); struct in_addr *dnsa4_addr; /* array of addresses, naddr elements */ }; UDNS_API dns_parse_fn dns_parse_a4; /* A RR parsing routine */ typedef void /* A query callback routine */ dns_query_a4_fn(struct dns_ctx *ctx, struct dns_rr_a4 *result, void *data); /* submit A IN query */ UDNS_API struct dns_query * dns_submit_a4(struct dns_ctx *ctx, const char *name, int flags, dns_query_a4_fn *cbck, void *data); /* resolve A IN query */ UDNS_API struct dns_rr_a4 * dns_resolve_a4(struct dns_ctx *ctx, const char *name, int flags); struct dns_rr_a6 { /* the AAAA RRset */ dns_rr_common(dnsa6); struct in6_addr *dnsa6_addr; /* array of addresses, naddr elements */ }; UDNS_API dns_parse_fn dns_parse_a6; /* A RR parsing routine */ typedef void /* A query callback routine */ dns_query_a6_fn(struct dns_ctx *ctx, struct dns_rr_a6 *result, void *data); /* submit AAAA IN query */ UDNS_API struct dns_query * dns_submit_a6(struct dns_ctx *ctx, const char *name, int flags, dns_query_a6_fn *cbck, void *data); /* resolve AAAA IN query */ UDNS_API struct dns_rr_a6 * dns_resolve_a6(struct dns_ctx *ctx, const char *name, int flags); struct dns_rr_ptr { /* the PTR RRset */ dns_rr_common(dnsptr); char **dnsptr_ptr; /* array of PTRs */ }; UDNS_API dns_parse_fn dns_parse_ptr; /* PTR RR parsing routine */ typedef void /* PTR query callback */ dns_query_ptr_fn(struct dns_ctx *ctx, struct dns_rr_ptr *result, void *data); /* submit PTR IN in-addr.arpa query */ UDNS_API struct dns_query * dns_submit_a4ptr(struct dns_ctx *ctx, const struct in_addr *addr, dns_query_ptr_fn *cbck, void *data); /* resolve PTR IN in-addr.arpa query */ UDNS_API struct dns_rr_ptr * dns_resolve_a4ptr(struct dns_ctx *ctx, const struct in_addr *addr); /* the same as above, but for ip6.arpa */ UDNS_API struct dns_query * dns_submit_a6ptr(struct dns_ctx *ctx, const struct in6_addr *addr, dns_query_ptr_fn *cbck, void *data); UDNS_API struct dns_rr_ptr * dns_resolve_a6ptr(struct dns_ctx *ctx, const struct in6_addr *addr); struct dns_mx { /* single MX RR */ int priority; /* MX priority */ char *name; /* MX name */ }; struct dns_rr_mx { /* the MX RRset */ dns_rr_common(dnsmx); struct dns_mx *dnsmx_mx; /* array of MXes */ }; UDNS_API dns_parse_fn dns_parse_mx; /* MX RR parsing routine */ typedef void /* MX RR callback */ dns_query_mx_fn(struct dns_ctx *ctx, struct dns_rr_mx *result, void *data); /* submit MX IN query */ UDNS_API struct dns_query * dns_submit_mx(struct dns_ctx *ctx, const char *name, int flags, dns_query_mx_fn *cbck, void *data); /* resolve MX IN query */ UDNS_API struct dns_rr_mx * dns_resolve_mx(struct dns_ctx *ctx, const char *name, int flags); struct dns_txt { /* single TXT record */ int len; /* length of the text */ dnsc_t *txt; /* pointer to text buffer. May contain nulls. */ }; struct dns_rr_txt { /* the TXT RRset */ dns_rr_common(dnstxt); struct dns_txt *dnstxt_txt; /* array of TXT records */ }; UDNS_API dns_parse_fn dns_parse_txt; /* TXT RR parsing routine */ typedef void /* TXT RR callback */ dns_query_txt_fn(struct dns_ctx *ctx, struct dns_rr_txt *result, void *data); /* submit TXT query */ UDNS_API struct dns_query * dns_submit_txt(struct dns_ctx *ctx, const char *name, int qcls, int flags, dns_query_txt_fn *cbck, void *data); /* resolve TXT query */ UDNS_API struct dns_rr_txt * dns_resolve_txt(struct dns_ctx *ctx, const char *name, int qcls, int flags); struct dns_srv { /* single SRV RR */ int priority; /* SRV priority */ int weight; /* SRV weight */ int port; /* SRV port */ char *name; /* SRV name */ }; struct dns_rr_srv { /* the SRV RRset */ dns_rr_common(dnssrv); struct dns_srv *dnssrv_srv; /* array of SRVes */ }; UDNS_API dns_parse_fn dns_parse_srv; /* SRV RR parsing routine */ typedef void /* SRV RR callback */ dns_query_srv_fn(struct dns_ctx *ctx, struct dns_rr_srv *result, void *data); /* submit SRV IN query */ UDNS_API struct dns_query * dns_submit_srv(struct dns_ctx *ctx, const char *name, const char *srv, const char *proto, int flags, dns_query_srv_fn *cbck, void *data); /* resolve SRV IN query */ UDNS_API struct dns_rr_srv * dns_resolve_srv(struct dns_ctx *ctx, const char *name, const char *srv, const char *proto, int flags); /* NAPTR (RFC3403) RR type */ struct dns_naptr { /* single NAPTR RR */ int order; /* NAPTR order */ int preference; /* NAPTR preference */ char *flags; /* NAPTR flags */ char *service; /* NAPTR service */ char *regexp; /* NAPTR regexp */ char *replacement; /* NAPTR replacement */ }; struct dns_rr_naptr { /* the NAPTR RRset */ dns_rr_common(dnsnaptr); struct dns_naptr *dnsnaptr_naptr; /* array of NAPTRes */ }; UDNS_API dns_parse_fn dns_parse_naptr; /* NAPTR RR parsing routine */ typedef void /* NAPTR RR callback */ dns_query_naptr_fn(struct dns_ctx *ctx, struct dns_rr_naptr *result, void *data); /* submit NAPTR IN query */ UDNS_API struct dns_query * dns_submit_naptr(struct dns_ctx *ctx, const char *name, int flags, dns_query_naptr_fn *cbck, void *data); /* resolve NAPTR IN query */ UDNS_API struct dns_rr_naptr * dns_resolve_naptr(struct dns_ctx *ctx, const char *name, int flags); UDNS_API struct dns_query * dns_submit_a4dnsbl(struct dns_ctx *ctx, const struct in_addr *addr, const char *dnsbl, dns_query_a4_fn *cbck, void *data); UDNS_API struct dns_query * dns_submit_a4dnsbl_txt(struct dns_ctx *ctx, const struct in_addr *addr, const char *dnsbl, dns_query_txt_fn *cbck, void *data); UDNS_API struct dns_rr_a4 * dns_resolve_a4dnsbl(struct dns_ctx *ctx, const struct in_addr *addr, const char *dnsbl); UDNS_API struct dns_rr_txt * dns_resolve_a4dnsbl_txt(struct dns_ctx *ctx, const struct in_addr *addr, const char *dnsbl); UDNS_API struct dns_query * dns_submit_a6dnsbl(struct dns_ctx *ctx, const struct in6_addr *addr, const char *dnsbl, dns_query_a4_fn *cbck, void *data); UDNS_API struct dns_query * dns_submit_a6dnsbl_txt(struct dns_ctx *ctx, const struct in6_addr *addr, const char *dnsbl, dns_query_txt_fn *cbck, void *data); UDNS_API struct dns_rr_a4 * dns_resolve_a6dnsbl(struct dns_ctx *ctx, const struct in6_addr *addr, const char *dnsbl); UDNS_API struct dns_rr_txt * dns_resolve_a6dnsbl_txt(struct dns_ctx *ctx, const struct in6_addr *addr, const char *dnsbl); UDNS_API struct dns_query * dns_submit_rhsbl(struct dns_ctx *ctx, const char *name, const char *rhsbl, dns_query_a4_fn *cbck, void *data); UDNS_API struct dns_query * dns_submit_rhsbl_txt(struct dns_ctx *ctx, const char *name, const char *rhsbl, dns_query_txt_fn *cbck, void *data); UDNS_API struct dns_rr_a4 * dns_resolve_rhsbl(struct dns_ctx *ctx, const char *name, const char *rhsbl); UDNS_API struct dns_rr_txt * dns_resolve_rhsbl_txt(struct dns_ctx *ctx, const char *name, const char *rhsbl); /**************************************************************************/ /**************** Names, Names ********************************************/ struct dns_nameval { int val; const char *name; }; UDNS_DATA_API extern const struct dns_nameval dns_classtab[]; UDNS_DATA_API extern const struct dns_nameval dns_typetab[]; UDNS_DATA_API extern const struct dns_nameval dns_rcodetab[]; UDNS_API int dns_findname(const struct dns_nameval *nv, const char *name); #define dns_findclassname(cls) dns_findname(dns_classtab, (cls)) #define dns_findtypename(type) dns_findname(dns_typetab, (type)) #define dns_findrcodename(rcode) dns_findname(dns_rcodetab, (rcode)) UDNS_API const char *dns_classname(enum dns_class cls); UDNS_API const char *dns_typename(enum dns_type type); UDNS_API const char *dns_rcodename(enum dns_rcode rcode); const char *_dns_format_code(char *buf, const char *prefix, int code); UDNS_API const char *dns_strerror(int errnum); /* simple pseudo-random number generator, code by Bob Jenkins */ struct udns_jranctx { /* the context */ unsigned a, b, c, d; }; /* initialize the RNG with a given seed */ UDNS_API void udns_jraninit(struct udns_jranctx *x, unsigned seed); /* return next random number. 32bits on most platforms so far. */ UDNS_API unsigned udns_jranval(struct udns_jranctx *x); #ifdef __cplusplus } /* extern "C" */ #endif #endif /* include guard */ libtorrent-0.16.11/src/net/udns/udns_parse.c0000644000000000000000000001267515175073411014347 /* udns_parse.c raw DNS packet parsing routines Copyright (C) 2005 Michael Tokarev This file is part of UDNS library, an async DNS stub resolver. 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, in file named COPYING.LGPL; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include "udns.h" dnscc_t *dns_skipdn(dnscc_t *cur, dnscc_t *end) { unsigned c; for(;;) { if (cur >= end) return NULL; c = *cur++; if (!c) return cur; if (c & 192) /* jump */ return cur + 1 >= end ? NULL : cur + 1; cur += c; } } int dns_getdn(dnscc_t *pkt, dnscc_t **cur, dnscc_t *end, dnsc_t *dn, unsigned dnsiz) { unsigned c; dnscc_t *pp = *cur; /* current packet pointer */ dnsc_t *dp = dn; /* current dn pointer */ dnsc_t *const de /* end of the DN dest */ = dn + (dnsiz < DNS_MAXDN ? dnsiz : DNS_MAXDN); dnscc_t *jump = NULL; /* ptr after first jump if any */ unsigned loop = 100; /* jump loop counter */ for(;;) { /* loop by labels */ if (pp >= end) /* reached end of packet? */ return -1; c = *pp++; /* length of the label */ if (!c) { /* empty label: terminate */ if (dn >= de) /* can't fit terminator */ goto noroom; *dp++ = 0; /* return next pos: either after the first jump or current */ *cur = jump ? jump : pp; return dp - dn; } if (c & 192) { /* jump */ if (pp >= end) /* eop instead of jump pos */ return -1; if (!jump) jump = pp + 1; /* remember first jump */ else if (!--loop) return -1; /* too many jumps */ c = ((c & ~192) << 8) | *pp; /* new pos */ if (c < DNS_HSIZE) /* don't allow jump into the header */ return -1; pp = pkt + c; continue; } if (c > DNS_MAXLABEL) /* too long label? */ return -1; if (pp + c > end) /* label does not fit in packet? */ return -1; if (dp + c + 1 > de) /* if enouth room for the label */ goto noroom; *dp++ = c; /* label length */ memcpy(dp, pp, c); /* and the label itself */ dp += c; pp += c; /* advance to the next label */ } noroom: return dnsiz < DNS_MAXDN ? 0 : -1; } void dns_rewind(struct dns_parse *p, dnscc_t *qdn) { p->dnsp_qdn = qdn; p->dnsp_cur = p->dnsp_ans; p->dnsp_rrl = dns_numan(p->dnsp_pkt); p->dnsp_ttl = 0xffffffffu; p->dnsp_nrr = 0; } void dns_initparse(struct dns_parse *p, dnscc_t *qdn, dnscc_t *pkt, dnscc_t *cur, dnscc_t *end) { p->dnsp_pkt = pkt; p->dnsp_end = end; p->dnsp_rrl = dns_numan(pkt); p->dnsp_qdn = qdn; assert(cur + 4 <= end); if ((p->dnsp_qtyp = (enum dns_type)dns_get16(cur+0)) == DNS_T_ANY) p->dnsp_qtyp = (enum dns_type)0; if ((p->dnsp_qcls = (enum dns_class)dns_get16(cur+2)) == DNS_C_ANY) p->dnsp_qcls = (enum dns_class)0; p->dnsp_cur = p->dnsp_ans = cur + 4; p->dnsp_ttl = 0xffffffffu; p->dnsp_nrr = 0; } int dns_nextrr(struct dns_parse *p, struct dns_rr *rr) { dnscc_t *cur = p->dnsp_cur; while(p->dnsp_rrl > 0) { --p->dnsp_rrl; if (dns_getdn(p->dnsp_pkt, &cur, p->dnsp_end, rr->dnsrr_dn, sizeof(rr->dnsrr_dn)) <= 0) return -1; if (cur + 10 > p->dnsp_end) return -1; rr->dnsrr_typ = (enum dns_type)dns_get16(cur); rr->dnsrr_cls = (enum dns_class)dns_get16(cur+2); rr->dnsrr_ttl = dns_get32(cur+4); rr->dnsrr_dsz = dns_get16(cur+8); rr->dnsrr_dptr = cur = cur + 10; rr->dnsrr_dend = cur = cur + rr->dnsrr_dsz; if (cur > p->dnsp_end) return -1; if (p->dnsp_qdn && !dns_dnequal(p->dnsp_qdn, rr->dnsrr_dn)) continue; if ((!p->dnsp_qcls || p->dnsp_qcls == rr->dnsrr_cls) && (!p->dnsp_qtyp || p->dnsp_qtyp == rr->dnsrr_typ)) { p->dnsp_cur = cur; ++p->dnsp_nrr; if (p->dnsp_ttl > rr->dnsrr_ttl) p->dnsp_ttl = rr->dnsrr_ttl; return 1; } if (p->dnsp_qdn && rr->dnsrr_typ == DNS_T_CNAME && !p->dnsp_nrr) { if (dns_getdn(p->dnsp_pkt, &rr->dnsrr_dptr, p->dnsp_end, p->dnsp_dnbuf, sizeof(p->dnsp_dnbuf)) <= 0 || rr->dnsrr_dptr != rr->dnsrr_dend) return -1; p->dnsp_qdn = p->dnsp_dnbuf; if (p->dnsp_ttl > rr->dnsrr_ttl) p->dnsp_ttl = rr->dnsrr_ttl; } } p->dnsp_cur = cur; return 0; } int dns_stdrr_size(const struct dns_parse *p) { return dns_dntop_size(p->dnsp_qdn) + (p->dnsp_qdn == dns_payload(p->dnsp_pkt) ? 0 : dns_dntop_size(dns_payload(p->dnsp_pkt))); } void *dns_stdrr_finish(struct dns_rr_null *ret, char *cp, const struct dns_parse *p) { cp += dns_dntop(p->dnsp_qdn, (ret->dnsn_cname = cp), DNS_MAXNAME); if (p->dnsp_qdn == dns_payload(p->dnsp_pkt)) ret->dnsn_qname = ret->dnsn_cname; else dns_dntop(dns_payload(p->dnsp_pkt), (ret->dnsn_qname = cp), DNS_MAXNAME); ret->dnsn_ttl = p->dnsp_ttl; return ret; } libtorrent-0.16.11/src/net/udns/udns_rr_srv.c0000644000000000000000000001134215175073411014540 /* udns_rr_srv.c parse/query SRV IN (rfc2782) records Copyright (C) 2005 Michael Tokarev This file is part of UDNS library, an async DNS stub resolver. 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, in file named COPYING.LGPL; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Copyright 2005 Thadeu Lima de Souza Cascardo 2005-09-11: Changed MX parser file into a SRV parser file */ #include #include #include #include "udns.h" int dns_parse_srv(dnscc_t *qdn, dnscc_t *pkt, dnscc_t *cur, dnscc_t *end, void **result) { struct dns_rr_srv *ret; struct dns_parse p; struct dns_rr rr; int r, l; char *sp; dnsc_t srv[DNS_MAXDN]; assert(dns_get16(cur+2) == DNS_C_IN && dns_get16(cur+0) == DNS_T_SRV); /* first, validate the answer and count size of the result */ l = 0; dns_initparse(&p, qdn, pkt, cur, end); while((r = dns_nextrr(&p, &rr)) > 0) { cur = rr.dnsrr_dptr + 6; r = dns_getdn(pkt, &cur, end, srv, sizeof(srv)); if (r <= 0 || cur != rr.dnsrr_dend) return DNS_E_PROTOCOL; l += dns_dntop_size(srv); } if (r < 0) return DNS_E_PROTOCOL; if (!p.dnsp_nrr) return DNS_E_NODATA; /* next, allocate and set up result */ l += dns_stdrr_size(&p); ret = (struct dns_rr_srv *)malloc(sizeof(*ret) + sizeof(struct dns_srv) * p.dnsp_nrr + l); if (!ret) return DNS_E_NOMEM; ret->dnssrv_nrr = p.dnsp_nrr; ret->dnssrv_srv = (struct dns_srv *)(ret+1); /* and 3rd, fill in result, finally */ sp = (char*)(ret->dnssrv_srv + p.dnsp_nrr); for (dns_rewind(&p, qdn), r = 0; dns_nextrr(&p, &rr); ++r) { ret->dnssrv_srv[r].name = sp; cur = rr.dnsrr_dptr; ret->dnssrv_srv[r].priority = dns_get16(cur); ret->dnssrv_srv[r].weight = dns_get16(cur+2); ret->dnssrv_srv[r].port = dns_get16(cur+4); cur += 6; dns_getdn(pkt, &cur, end, srv, sizeof(srv)); sp += dns_dntop(srv, sp, DNS_MAXNAME); } dns_stdrr_finish((struct dns_rr_null *)ret, sp, &p); *result = ret; return 0; } /* Add a single service or proto name prepending an undescore (_), * according to rfc2782 rules. * Return 0 or the label length. * Routing assumes dn holds enouth space for a single DN label. */ static int add_sname(dnsc_t *dn, const char *sn) { int l = dns_ptodn(sn, 0, dn + 1, DNS_MAXLABEL-1, NULL); if (l <= 1 || l - 2 != dn[1]) /* Should we really check if sn is exactly one label? Do we care? */ return 0; dn[0] = l - 1; dn[1] = '_'; return l; } /* Construct a domain name for SRV query from the given name, service and proto. * The code allows any combinations of srv and proto (both are non-NULL, * both NULL, or either one is non-NULL). Whenever it makes any sense or not * is left as an exercise to programmer. * Return negative value on error (malformed query) or addition query flag(s). */ static int build_srv_dn(dnsc_t *dn, const char *name, const char *srv, const char *proto) { int p = 0, l, isabs; if (srv) { l = add_sname(dn + p, srv); if (!l) return -1; p += l; } if (proto) { l = add_sname(dn + p, proto); if (!l) return -1; p += l; } l = dns_ptodn(name, 0, dn + p, DNS_MAXDN - p, &isabs); if (l < 0) return -1; return isabs ? DNS_NOSRCH : 0; } struct dns_query * dns_submit_srv(struct dns_ctx *ctx, const char *name, const char *srv, const char *proto, int flags, dns_query_srv_fn *cbck, void *data) { dnsc_t dn[DNS_MAXDN]; int r = build_srv_dn(dn, name, srv, proto); if (r < 0) { dns_setstatus (ctx, DNS_E_BADQUERY); return NULL; } return dns_submit_dn(ctx, dn, DNS_C_IN, DNS_T_SRV, flags | r, dns_parse_srv, (dns_query_fn *)cbck, data); } struct dns_rr_srv * dns_resolve_srv(struct dns_ctx *ctx, const char *name, const char *srv, const char *proto, int flags) { dnsc_t dn[DNS_MAXDN]; int r = build_srv_dn(dn, name, srv, proto); if (r < 0) { dns_setstatus(ctx, DNS_E_BADQUERY); return NULL; } return (struct dns_rr_srv *) dns_resolve_dn(ctx, dn, DNS_C_IN, DNS_T_SRV, flags | r, dns_parse_srv); } libtorrent-0.16.11/src/net/udns/udns_rr_txt.c0000644000000000000000000000561115175073411014547 /* udns_rr_txt.c parse/query TXT records Copyright (C) 2005 Michael Tokarev This file is part of UDNS library, an async DNS stub resolver. 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, in file named COPYING.LGPL; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include "udns.h" int dns_parse_txt(dnscc_t *qdn, dnscc_t *pkt, dnscc_t *cur, dnscc_t *end, void **result) { struct dns_rr_txt *ret; struct dns_parse p; struct dns_rr rr; int r, l; dnsc_t *sp; dnscc_t *cp, *ep; assert(dns_get16(cur+0) == DNS_T_TXT); /* first, validate the answer and count size of the result */ l = 0; dns_initparse(&p, qdn, pkt, cur, end); while((r = dns_nextrr(&p, &rr)) > 0) { cp = rr.dnsrr_dptr; ep = rr.dnsrr_dend; while(cp < ep) { r = *cp++; if (cp + r > ep) return DNS_E_PROTOCOL; l += r; cp += r; } } if (r < 0) return DNS_E_PROTOCOL; if (!p.dnsp_nrr) return DNS_E_NODATA; /* next, allocate and set up result */ l += (sizeof(struct dns_txt) + 1) * p.dnsp_nrr + dns_stdrr_size(&p); ret = (struct dns_rr_txt *)malloc(sizeof(*ret) + l); if (!ret) return DNS_E_NOMEM; ret->dnstxt_nrr = p.dnsp_nrr; ret->dnstxt_txt = (struct dns_txt *)(ret+1); /* and 3rd, fill in result, finally */ sp = (dnsc_t*)(ret->dnstxt_txt + p.dnsp_nrr); for(dns_rewind(&p, qdn), r = 0; dns_nextrr(&p, &rr) > 0; ++r) { ret->dnstxt_txt[r].txt = sp; cp = rr.dnsrr_dptr; ep = rr.dnsrr_dend; while(cp < ep) { l = *cp++; memcpy(sp, cp, l); sp += l; cp += l; } ret->dnstxt_txt[r].len = sp - ret->dnstxt_txt[r].txt; *sp++ = '\0'; } dns_stdrr_finish((struct dns_rr_null *)ret, (char*)sp, &p); *result = ret; return 0; } struct dns_query * dns_submit_txt(struct dns_ctx *ctx, const char *name, int qcls, int flags, dns_query_txt_fn *cbck, void *data) { return dns_submit_p(ctx, name, qcls, DNS_T_TXT, flags, dns_parse_txt, (dns_query_fn *)cbck, data); } struct dns_rr_txt * dns_resolve_txt(struct dns_ctx *ctx, const char *name, int qcls, int flags) { return (struct dns_rr_txt *) dns_resolve_p(ctx, name, qcls, DNS_T_TXT, flags, dns_parse_txt); } libtorrent-0.16.11/src/net/udns/udns_rr_mx.c0000644000000000000000000000552215175073411014355 /* udns_rr_mx.c parse/query MX IN records Copyright (C) 2005 Michael Tokarev This file is part of UDNS library, an async DNS stub resolver. 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, in file named COPYING.LGPL; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include "udns.h" int dns_parse_mx(dnscc_t *qdn, dnscc_t *pkt, dnscc_t *cur, dnscc_t *end, void **result) { struct dns_rr_mx *ret; struct dns_parse p; struct dns_rr rr; int r, l; char *sp; dnsc_t mx[DNS_MAXDN]; assert(dns_get16(cur+2) == DNS_C_IN && dns_get16(cur+0) == DNS_T_MX); /* first, validate the answer and count size of the result */ l = 0; dns_initparse(&p, qdn, pkt, cur, end); while((r = dns_nextrr(&p, &rr)) > 0) { cur = rr.dnsrr_dptr + 2; r = dns_getdn(pkt, &cur, end, mx, sizeof(mx)); if (r <= 0 || cur != rr.dnsrr_dend) return DNS_E_PROTOCOL; l += dns_dntop_size(mx); } if (r < 0) return DNS_E_PROTOCOL; if (!p.dnsp_nrr) return DNS_E_NODATA; /* next, allocate and set up result */ l += dns_stdrr_size(&p); ret = (struct dns_rr_mx *)malloc(sizeof(*ret) + sizeof(struct dns_mx) * p.dnsp_nrr + l); if (!ret) return DNS_E_NOMEM; ret->dnsmx_nrr = p.dnsp_nrr; ret->dnsmx_mx = (struct dns_mx *)(ret+1); /* and 3rd, fill in result, finally */ sp = (char*)(ret->dnsmx_mx + p.dnsp_nrr); for (dns_rewind(&p, qdn), r = 0; dns_nextrr(&p, &rr); ++r) { ret->dnsmx_mx[r].name = sp; cur = rr.dnsrr_dptr; ret->dnsmx_mx[r].priority = dns_get16(cur); cur += 2; dns_getdn(pkt, &cur, end, mx, sizeof(mx)); sp += dns_dntop(mx, sp, DNS_MAXNAME); } dns_stdrr_finish((struct dns_rr_null *)ret, sp, &p); *result = ret; return 0; } struct dns_query * dns_submit_mx(struct dns_ctx *ctx, const char *name, int flags, dns_query_mx_fn *cbck, void *data) { return dns_submit_p(ctx, name, DNS_C_IN, DNS_T_MX, flags, dns_parse_mx, (dns_query_fn *)cbck, data); } struct dns_rr_mx * dns_resolve_mx(struct dns_ctx *ctx, const char *name, int flags) { return (struct dns_rr_mx *) dns_resolve_p(ctx, name, DNS_C_IN, DNS_T_MX, flags, dns_parse_mx); } libtorrent-0.16.11/src/net/udns/udns_XtoX.c0000644000000000000000000000273215175073411014130 /* udns_XtoX.c dns_ntop() and dns_pton() routines, which are either - wrappers for inet_ntop() and inet_pton() or - reimplementations of those routines. Copyright (C) 2005 Michael Tokarev This file is part of UDNS library, an async DNS stub resolver. 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, in file named COPYING.LGPL; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include "udns.h" #ifdef HAVE_INET_PTON_NTOP #include #include #include const char *dns_ntop(int af, const void *src, char *dst, unsigned size) { return inet_ntop(af, src, dst, size); } int dns_pton(int af, const char *src, void *dst) { return inet_pton(af, src, dst); } #else #define inet_XtoX_prefix dns_ #include "inet_XtoX.c" #endif libtorrent-0.16.11/src/net/udns/udns_init.c0000644000000000000000000001527315175073411014175 /* udns_init.c resolver initialisation stuff Copyright (C) 2006 Michael Tokarev This file is part of UDNS library, an async DNS stub resolver. 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, in file named COPYING.LGPL; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #ifdef WINDOWS # include /* includes */ # include /* for dns server addresses etc */ #else # include # include # include #endif /* !WINDOWS */ #include #include #include "udns.h" #define ISSPACE(x) (x == ' ' || x == '\t' || x == '\r' || x == '\n') static const char space[] = " \t\r\n"; static void dns_set_serv_internal(struct dns_ctx *ctx, char *serv) { dns_add_serv(ctx, NULL); for(serv = strtok(serv, space); serv; serv = strtok(NULL, space)) dns_add_serv(ctx, serv); } static void dns_set_srch_internal(struct dns_ctx *ctx, char *srch) { dns_add_srch(ctx, NULL); for(srch = strtok(srch, space); srch; srch = strtok(NULL, space)) dns_add_srch(ctx, srch); } #ifdef WINDOWS #ifndef NO_IPHLPAPI /* Apparently, some systems does not have proper headers for IPHLPAIP to work. * The best is to upgrade headers, but here's another, ugly workaround for * this: compile with -DNO_IPHLPAPI. */ typedef DWORD (WINAPI *GetAdaptersAddressesFunc)( ULONG Family, DWORD Flags, PVOID Reserved, PIP_ADAPTER_ADDRESSES pAdapterAddresses, PULONG pOutBufLen); static int dns_initns_iphlpapi(struct dns_ctx *ctx) { HANDLE h_iphlpapi; GetAdaptersAddressesFunc pfnGetAdAddrs; PIP_ADAPTER_ADDRESSES pAddr, pAddrBuf; PIP_ADAPTER_DNS_SERVER_ADDRESS pDnsAddr; ULONG ulOutBufLen; DWORD dwRetVal; int ret = -1; h_iphlpapi = LoadLibrary("iphlpapi.dll"); if (!h_iphlpapi) return -1; pfnGetAdAddrs = (GetAdaptersAddressesFunc) GetProcAddress(h_iphlpapi, "GetAdaptersAddresses"); if (!pfnGetAdAddrs) goto freelib; ulOutBufLen = 0; dwRetVal = pfnGetAdAddrs(AF_UNSPEC, 0, NULL, NULL, &ulOutBufLen); if (dwRetVal != ERROR_BUFFER_OVERFLOW) goto freelib; pAddrBuf = malloc(ulOutBufLen); if (!pAddrBuf) goto freelib; dwRetVal = pfnGetAdAddrs(AF_UNSPEC, 0, NULL, pAddrBuf, &ulOutBufLen); if (dwRetVal != ERROR_SUCCESS) goto freemem; for (pAddr = pAddrBuf; pAddr; pAddr = pAddr->Next) for (pDnsAddr = pAddr->FirstDnsServerAddress; pDnsAddr; pDnsAddr = pDnsAddr->Next) dns_add_serv_s(ctx, pDnsAddr->Address.lpSockaddr); ret = 0; freemem: free(pAddrBuf); freelib: FreeLibrary(h_iphlpapi); return ret; } #else /* NO_IPHLPAPI */ #define dns_initns_iphlpapi(ctx) (-1) #endif /* NO_IPHLPAPI */ static int dns_initns_registry(struct dns_ctx *ctx) { LONG res; HKEY hk; DWORD type = REG_EXPAND_SZ | REG_SZ; DWORD len; char valBuf[1024]; #define REGKEY_WINNT "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters" #define REGKEY_WIN9x "SYSTEM\\CurrentControlSet\\Services\\VxD\\MSTCP" res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_WINNT, 0, KEY_QUERY_VALUE, &hk); if (res != ERROR_SUCCESS) res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_WIN9x, 0, KEY_QUERY_VALUE, &hk); if (res != ERROR_SUCCESS) return -1; len = sizeof(valBuf) - 1; res = RegQueryValueEx(hk, "NameServer", NULL, &type, (BYTE*)valBuf, &len); if (res != ERROR_SUCCESS || !len || !valBuf[0]) { len = sizeof(valBuf) - 1; res = RegQueryValueEx(hk, "DhcpNameServer", NULL, &type, (BYTE*)valBuf, &len); } RegCloseKey(hk); if (res != ERROR_SUCCESS || !len || !valBuf[0]) return -1; valBuf[len] = '\0'; /* nameservers are stored as a whitespace-seperate list: * "192.168.1.1 123.21.32.12" */ dns_set_serv_internal(ctx, valBuf); return 0; } #else /* !WINDOWS */ static int dns_init_resolvconf(struct dns_ctx *ctx) { char *v; char buf[2049]; /* this buffer is used to hold /etc/resolv.conf */ int has_srch = 0; /* read resolv.conf... */ { int fd = open("/etc/resolv.conf", O_RDONLY); if (fd >= 0) { int l = read(fd, buf, sizeof(buf) - 1); close(fd); buf[l < 0 ? 0 : l] = '\0'; } else buf[0] = '\0'; } if (buf[0]) { /* ...and parse it */ char *line, *nextline; line = buf; do { nextline = strchr(line, '\n'); if (nextline) *nextline++ = '\0'; v = line; while(*v && !ISSPACE(*v)) ++v; if (!*v) continue; *v++ = '\0'; while(ISSPACE(*v)) ++v; if (!*v) continue; if (strcmp(line, "domain") == 0) { dns_set_srch_internal(ctx, strtok(v, space)); has_srch = 1; } else if (strcmp(line, "search") == 0) { dns_set_srch_internal(ctx, v); has_srch = 1; } else if (strcmp(line, "nameserver") == 0) dns_add_serv(ctx, strtok(v, space)); else if (strcmp(line, "options") == 0) dns_set_opts(ctx, v); } while((line = nextline) != NULL); } buf[sizeof(buf)-1] = '\0'; /* get list of nameservers from env. vars. */ if ((v = getenv("NSCACHEIP")) != NULL || (v = getenv("NAMESERVERS")) != NULL) { strncpy(buf, v, sizeof(buf) - 1); dns_set_serv_internal(ctx, buf); } /* if $LOCALDOMAIN is set, use it for search list */ if ((v = getenv("LOCALDOMAIN")) != NULL) { strncpy(buf, v, sizeof(buf) - 1); dns_set_srch_internal(ctx, buf); has_srch = 1; } if ((v = getenv("RES_OPTIONS")) != NULL) dns_set_opts(ctx, v); /* if still no search list, use local domain name */ if (!has_srch && gethostname(buf, sizeof(buf) - 1) == 0 && (v = strchr(buf, '.')) != NULL && *++v != '\0') dns_add_srch(ctx, v); return 0; } #endif /* !WINDOWS */ int dns_init(struct dns_ctx *ctx, int do_open) { if (!ctx) ctx = &dns_defctx; dns_reset(ctx); #ifdef WINDOWS if (dns_initns_iphlpapi(ctx) != 0) dns_initns_registry(ctx); /*XXX WINDOWS: probably good to get default domain and search list too... * And options. Something is in registry. */ /*XXX WINDOWS: maybe environment variables are also useful? */ #else dns_init_resolvconf(ctx); #endif return do_open ? dns_open(ctx) : 0; } libtorrent-0.16.11/src/net/udns/config.h0000644000000000000000000000021115175073411013435 /* automatically generated by configure. */ #define HAVE_GETOPT 1 #define HAVE_INET_PTON_NTOP 1 #define HAVE_IPv6 1 #define HAVE_POLL 1 libtorrent-0.16.11/src/net/udns/udns_dn.c0000644000000000000000000002324215175073411013626 /* udns_dn.c domain names manipulation routines Copyright (C) 2005 Michael Tokarev This file is part of UDNS library, an async DNS stub resolver. 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, in file named COPYING.LGPL; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include "udns.h" unsigned dns_dnlen(dnscc_t *dn) { register dnscc_t *d = dn; while(*d) d += 1 + *d; return (unsigned)(d - dn) + 1; } unsigned dns_dnlabels(register dnscc_t *dn) { register unsigned l = 0; while(*dn) ++l, dn += 1 + *dn; return l; } unsigned dns_dnequal(register dnscc_t *dn1, register dnscc_t *dn2) { register unsigned c; dnscc_t *dn = dn1; for(;;) { if ((c = *dn1++) != *dn2++) return 0; if (!c) return (unsigned)(dn1 - dn); while(c--) { if (DNS_DNLC(*dn1) != DNS_DNLC(*dn2)) return 0; ++dn1; ++dn2; } } } unsigned dns_dntodn(dnscc_t *sdn, dnsc_t *ddn, unsigned ddnsiz) { unsigned sdnlen = dns_dnlen(sdn); if (ddnsiz < sdnlen) return 0; memcpy(ddn, sdn, sdnlen); return sdnlen; } int dns_ptodn(const char *name, unsigned namelen, dnsc_t *dn, unsigned dnsiz, int *isabs) { dnsc_t *dp; /* current position in dn (len byte first) */ dnsc_t *const de /* end of dn: last byte that can be filled up */ = dn + (dnsiz >= DNS_MAXDN ? DNS_MAXDN : dnsiz) - 1; dnscc_t *np = (dnscc_t *)name; dnscc_t *ne = np + (namelen ? namelen : strlen((char*)np)); dnsc_t *llab; /* start of last label (llab[-1] will be length) */ unsigned c; /* next input character, or length of last label */ if (!dnsiz) return 0; dp = llab = dn + 1; while(np < ne) { if (*np == '.') { /* label delimiter */ c = dp - llab; /* length of the label */ if (!c) { /* empty label */ if (np == (dnscc_t *)name && np + 1 == ne) { /* special case for root dn, aka `.' */ ++np; break; } return -1; /* zero label */ } if (c > DNS_MAXLABEL) return -1; /* label too long */ llab[-1] = (dnsc_t)c; /* update len of last label */ llab = ++dp; /* start new label, llab[-1] will be len of it */ ++np; continue; } /* check whenever we may put out one more byte */ if (dp >= de) /* too long? */ return dnsiz >= DNS_MAXDN ? -1 : 0; if (*np != '\\') { /* non-escape, simple case */ *dp++ = *np++; continue; } /* handle \-style escape */ /* note that traditionally, domain names (gethostbyname etc) * used decimal \dd notation, not octal \ooo (RFC1035), so * we're following this tradition here. */ if (++np == ne) return -1; /* bad escape */ else if (*np >= '0' && *np <= '9') { /* decimal number */ /* we allow not only exactly 3 digits as per RFC1035, * but also 2 or 1, for better usability. */ c = *np++ - '0'; if (np < ne && *np >= '0' && *np <= '9') { /* 2digits */ c = c * 10 + *np++ - '0'; if (np < ne && *np >= '0' && *np <= '9') { c = c * 10 + *np++ - '0'; if (c > 255) return -1; /* bad escape */ } } } else c = *np++; *dp++ = (dnsc_t)c; /* place next out byte */ } if ((c = dp - llab) > DNS_MAXLABEL) return -1; /* label too long */ if ((llab[-1] = (dnsc_t)c) != 0) { *dp++ = 0; if (isabs) *isabs = 0; } else if (isabs) *isabs = 1; return dp - dn; } dnscc_t dns_inaddr_arpa_dn[14] = "\07in-addr\04arpa"; dnsc_t * dns_a4todn_(const struct in_addr *addr, dnsc_t *dn, dnsc_t *dne) { const unsigned char *s = ((const unsigned char *)addr) + 4; while(s > (const unsigned char *)addr) { unsigned n = *--s; dnsc_t *p = dn + 1; if (n > 99) { if (p + 2 > dne) return 0; *p++ = n / 100 + '0'; *p++ = (n % 100 / 10) + '0'; *p = n % 10 + '0'; } else if (n > 9) { if (p + 1 > dne) return 0; *p++ = n / 10 + '0'; *p = n % 10 + '0'; } else { if (p > dne) return 0; *p = n + '0'; } *dn = p - dn; dn = p + 1; } return dn; } int dns_a4todn(const struct in_addr *addr, dnscc_t *tdn, dnsc_t *dn, unsigned dnsiz) { dnsc_t *dne = dn + (dnsiz > DNS_MAXDN ? DNS_MAXDN : dnsiz); dnsc_t *p; unsigned l; p = dns_a4todn_(addr, dn, dne); if (!p) return 0; if (!tdn) tdn = dns_inaddr_arpa_dn; l = dns_dnlen(tdn); if (p + l > dne) return dnsiz >= DNS_MAXDN ? -1 : 0; memcpy(p, tdn, l); return (p + l) - dn; } int dns_a4ptodn(const struct in_addr *addr, const char *tname, dnsc_t *dn, unsigned dnsiz) { dnsc_t *p; int r; if (!tname) return dns_a4todn(addr, NULL, dn, dnsiz); p = dns_a4todn_(addr, dn, dn + dnsiz); if (!p) return 0; r = dns_sptodn(tname, p, dnsiz - (p - dn)); return r != 0 ? r : dnsiz >= DNS_MAXDN ? -1 : 0; } dnscc_t dns_ip6_arpa_dn[10] = "\03ip6\04arpa"; dnsc_t * dns_a6todn_(const struct in6_addr *addr, dnsc_t *dn, dnsc_t *dne) { const unsigned char *s = ((const unsigned char *)addr) + 16; if (dn + 64 > dne) return 0; while(s > (const unsigned char *)addr) { unsigned n = *--s & 0x0f; *dn++ = 1; *dn++ = n > 9 ? n + 'a' - 10 : n + '0'; *dn++ = 1; n = *s >> 4; *dn++ = n > 9 ? n + 'a' - 10 : n + '0'; } return dn; } int dns_a6todn(const struct in6_addr *addr, dnscc_t *tdn, dnsc_t *dn, unsigned dnsiz) { dnsc_t *dne = dn + (dnsiz > DNS_MAXDN ? DNS_MAXDN : dnsiz); dnsc_t *p; unsigned l; p = dns_a6todn_(addr, dn, dne); if (!p) return 0; if (!tdn) tdn = dns_ip6_arpa_dn; l = dns_dnlen(tdn); if (p + l > dne) return dnsiz >= DNS_MAXDN ? -1 : 0; memcpy(p, tdn, l); return (p + l) - dn; } int dns_a6ptodn(const struct in6_addr *addr, const char *tname, dnsc_t *dn, unsigned dnsiz) { dnsc_t *p; int r; if (!tname) return dns_a6todn(addr, NULL, dn, dnsiz); p = dns_a6todn_(addr, dn, dn + dnsiz); if (!p) return 0; r = dns_sptodn(tname, p, dnsiz - (p - dn)); return r != 0 ? r : dnsiz >= DNS_MAXDN ? -1 : 0; } /* return size of buffer required to convert the dn into asciiz string. * Keep in sync with dns_dntop() below. */ unsigned dns_dntop_size(dnscc_t *dn) { unsigned size = 0; /* the size reqd */ dnscc_t *le; /* label end */ while(*dn) { /* *dn is the length of the next label, non-zero */ if (size) ++size; /* for the dot */ le = dn + *dn + 1; ++dn; do { switch(*dn) { case '.': case '\\': /* Special modifiers in zone files. */ case '"': case ';': case '@': case '$': size += 2; break; default: if (*dn <= 0x20 || *dn >= 0x7f) /* \ddd decimal notation */ size += 4; else size += 1; } } while(++dn < le); } size += 1; /* zero byte at the end - string terminator */ return size > DNS_MAXNAME ? 0 : size; } /* Convert the dn into asciiz string. * Keep in sync with dns_dntop_size() above. */ int dns_dntop(dnscc_t *dn, char *name, unsigned namesiz) { char *np = name; /* current name ptr */ char *const ne = name + namesiz; /* end of name */ dnscc_t *le; /* label end */ while(*dn) { /* *dn is the length of the next label, non-zero */ if (np != name) { if (np >= ne) goto toolong; *np++ = '.'; } le = dn + *dn + 1; ++dn; do { switch(*dn) { case '.': case '\\': /* Special modifiers in zone files. */ case '"': case ';': case '@': case '$': if (np + 2 > ne) goto toolong; *np++ = '\\'; *np++ = *dn; break; default: if (*dn <= 0x20 || *dn >= 0x7f) { /* \ddd decimal notation */ if (np + 4 >= ne) goto toolong; *np++ = '\\'; *np++ = '0' + (*dn / 100); *np++ = '0' + ((*dn % 100) / 10); *np++ = '0' + (*dn % 10); } else { if (np >= ne) goto toolong; *np++ = *dn; } } } while(++dn < le); } if (np >= ne) goto toolong; *np++ = '\0'; return np - name; toolong: return namesiz >= DNS_MAXNAME ? -1 : 0; } #ifdef TEST #include #include int main(int argc, char **argv) { int i; int sz; dnsc_t dn[DNS_MAXDN+10]; dnsc_t *dl, *dp; int isabs; sz = (argc > 1) ? atoi(argv[1]) : 0; for(i = 2; i < argc; ++i) { int r = dns_ptodn(argv[i], 0, dn, sz, &isabs); printf("%s: ", argv[i]); if (r < 0) printf("error\n"); else if (!r) printf("buffer too small\n"); else { printf("len=%d dnlen=%d size=%d name:", r, dns_dnlen(dn), dns_dntop_size(dn)); dl = dn; while(*dl) { printf(" %d=", *dl); dp = dl + 1; dl = dp + *dl; while(dp < dl) { if (*dp <= ' ' || *dp >= 0x7f) printf("\\%03d", *dp); else if (*dp == '.' || *dp == '\\') printf("\\%c", *dp); else putchar(*dp); ++dp; } } if (isabs) putchar('.'); putchar('\n'); } } return 0; } #endif /* TEST */ libtorrent-0.16.11/src/net/udns/udns_rr_ptr.c0000644000000000000000000000651515175073411014541 /* udns_rr_ptr.c parse/query PTR records Copyright (C) 2005 Michael Tokarev This file is part of UDNS library, an async DNS stub resolver. 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, in file named COPYING.LGPL; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include "udns.h" int dns_parse_ptr(dnscc_t *qdn, dnscc_t *pkt, dnscc_t *cur, dnscc_t *end, void **result) { struct dns_rr_ptr *ret; struct dns_parse p; struct dns_rr rr; int r, l, c; char *sp; dnsc_t ptr[DNS_MAXDN]; assert(dns_get16(cur+2) == DNS_C_IN && dns_get16(cur+0) == DNS_T_PTR); /* first, validate the answer and count size of the result */ l = c = 0; dns_initparse(&p, qdn, pkt, cur, end); while((r = dns_nextrr(&p, &rr)) > 0) { cur = rr.dnsrr_dptr; r = dns_getdn(pkt, &cur, end, ptr, sizeof(ptr)); if (r <= 0 || cur != rr.dnsrr_dend) return DNS_E_PROTOCOL; l += dns_dntop_size(ptr); ++c; } if (r < 0) return DNS_E_PROTOCOL; if (!c) return DNS_E_NODATA; /* next, allocate and set up result */ ret = (struct dns_rr_ptr *)malloc(sizeof(*ret) + sizeof(char **) * c + l + dns_stdrr_size(&p)); if (!ret) return DNS_E_NOMEM; ret->dnsptr_nrr = c; ret->dnsptr_ptr = (char **)(ret+1); /* and 3rd, fill in result, finally */ sp = (char*)(ret->dnsptr_ptr + c); c = 0; dns_rewind(&p, qdn); while((r = dns_nextrr(&p, &rr)) > 0) { ret->dnsptr_ptr[c] = sp; cur = rr.dnsrr_dptr; dns_getdn(pkt, &cur, end, ptr, sizeof(ptr)); sp += dns_dntop(ptr, sp, DNS_MAXNAME); ++c; } dns_stdrr_finish((struct dns_rr_null *)ret, sp, &p); *result = ret; return 0; } struct dns_query * dns_submit_a4ptr(struct dns_ctx *ctx, const struct in_addr *addr, dns_query_ptr_fn *cbck, void *data) { dnsc_t dn[DNS_A4RSIZE]; dns_a4todn(addr, 0, dn, sizeof(dn)); return dns_submit_dn(ctx, dn, DNS_C_IN, DNS_T_PTR, DNS_NOSRCH, dns_parse_ptr, (dns_query_fn *)cbck, data); } struct dns_rr_ptr * dns_resolve_a4ptr(struct dns_ctx *ctx, const struct in_addr *addr) { return (struct dns_rr_ptr *) dns_resolve(ctx, dns_submit_a4ptr(ctx, addr, NULL, NULL)); } struct dns_query * dns_submit_a6ptr(struct dns_ctx *ctx, const struct in6_addr *addr, dns_query_ptr_fn *cbck, void *data) { dnsc_t dn[DNS_A6RSIZE]; dns_a6todn(addr, 0, dn, sizeof(dn)); return dns_submit_dn(ctx, dn, DNS_C_IN, DNS_T_PTR, DNS_NOSRCH, dns_parse_ptr, (dns_query_fn *)cbck, data); } struct dns_rr_ptr * dns_resolve_a6ptr(struct dns_ctx *ctx, const struct in6_addr *addr) { return (struct dns_rr_ptr *) dns_resolve(ctx, dns_submit_a6ptr(ctx, addr, NULL, NULL)); } libtorrent-0.16.11/src/net/udns/udns_rr_a.c0000644000000000000000000000725515175073411014156 /* udns_rr_a.c parse/query A/AAAA IN records Copyright (C) 2005 Michael Tokarev This file is part of UDNS library, an async DNS stub resolver. 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, in file named COPYING.LGPL; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #ifndef WINDOWS # include # include #endif #include "udns.h" /* here, we use common routine to parse both IPv4 and IPv6 addresses. */ /* this structure should match dns_rr_a[46] */ struct dns_rr_a { dns_rr_common(dnsa); unsigned char *dnsa_addr; }; static int dns_parse_a(dnscc_t *qdn, dnscc_t *pkt, dnscc_t *cur, dnscc_t *end, void **result, unsigned dsize) { struct dns_rr_a *ret; struct dns_parse p; struct dns_rr rr; int r; /* first, validate and count number of addresses */ dns_initparse(&p, qdn, pkt, cur, end); while((r = dns_nextrr(&p, &rr)) > 0) if (rr.dnsrr_dsz != dsize) return DNS_E_PROTOCOL; if (r < 0) return DNS_E_PROTOCOL; else if (!p.dnsp_nrr) return DNS_E_NODATA; ret = (struct dns_rr_a *)malloc(sizeof(*ret) + dsize * p.dnsp_nrr + dns_stdrr_size(&p)); if (!ret) return DNS_E_NOMEM; ret->dnsa_nrr = p.dnsp_nrr; ret->dnsa_addr = (unsigned char*)(ret+1); /* copy the RRs */ for (dns_rewind(&p, qdn), r = 0; dns_nextrr(&p, &rr); ++r) memcpy(ret->dnsa_addr + dsize * r, rr.dnsrr_dptr, dsize); dns_stdrr_finish((struct dns_rr_null *)ret, (char *)(ret->dnsa_addr + dsize * p.dnsp_nrr), &p); *result = ret; return 0; } int dns_parse_a4(dnscc_t *qdn, dnscc_t *pkt, dnscc_t *cur, dnscc_t *end, void **result) { #ifdef AF_INET assert(sizeof(struct in_addr) == 4); #endif assert(dns_get16(cur+2) == DNS_C_IN && dns_get16(cur+0) == DNS_T_A); return dns_parse_a(qdn, pkt, cur, end, result, 4); } struct dns_query * dns_submit_a4(struct dns_ctx *ctx, const char *name, int flags, dns_query_a4_fn *cbck, void *data) { return dns_submit_p(ctx, name, DNS_C_IN, DNS_T_A, flags, dns_parse_a4, (dns_query_fn*)cbck, data); } struct dns_rr_a4 * dns_resolve_a4(struct dns_ctx *ctx, const char *name, int flags) { return (struct dns_rr_a4 *) dns_resolve_p(ctx, name, DNS_C_IN, DNS_T_A, flags, dns_parse_a4); } int dns_parse_a6(dnscc_t *qdn, dnscc_t *pkt, dnscc_t *cur, dnscc_t *end, void **result) { #ifdef AF_INET6 assert(sizeof(struct in6_addr) == 16); #endif assert(dns_get16(cur+2) == DNS_C_IN && dns_get16(cur+0) == DNS_T_AAAA); return dns_parse_a(qdn, pkt, cur, end, result, 16); } struct dns_query * dns_submit_a6(struct dns_ctx *ctx, const char *name, int flags, dns_query_a6_fn *cbck, void *data) { return dns_submit_p(ctx, name, DNS_C_IN, DNS_T_AAAA, flags, dns_parse_a6, (dns_query_fn*)cbck, data); } struct dns_rr_a6 * dns_resolve_a6(struct dns_ctx *ctx, const char *name, int flags) { return (struct dns_rr_a6 *) dns_resolve_p(ctx, name, DNS_C_IN, DNS_T_AAAA, flags, dns_parse_a6); } libtorrent-0.16.11/src/net/udns/udns_dntosp.c0000644000000000000000000000214515175073411014533 /* udns_dntosp.c dns_dntosp() = convert DN to asciiz string using static buffer Copyright (C) 2005 Michael Tokarev This file is part of UDNS library, an async DNS stub resolver. 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, in file named COPYING.LGPL; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "udns.h" static char name[DNS_MAXNAME]; const char *dns_dntosp(dnscc_t *dn) { return dns_dntop(dn, name, sizeof(name)) > 0 ? name : 0; } libtorrent-0.16.11/src/net/udns/udns_bl.c0000644000000000000000000001213215175073411013616 /* udns_bl.c DNSBL stuff Copyright (C) 2005 Michael Tokarev This file is part of UDNS library, an async DNS stub resolver. 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, in file named COPYING.LGPL; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "udns.h" #ifndef NULL # define NULL 0 #endif struct dns_query * dns_submit_a4dnsbl(struct dns_ctx *ctx, const struct in_addr *addr, const char *dnsbl, dns_query_a4_fn *cbck, void *data) { dnsc_t dn[DNS_MAXDN]; if (dns_a4ptodn(addr, dnsbl, dn, sizeof(dn)) <= 0) { dns_setstatus(ctx, DNS_E_BADQUERY); return NULL; } return dns_submit_dn(ctx, dn, DNS_C_IN, DNS_T_A, DNS_NOSRCH, dns_parse_a4, (dns_query_fn*)cbck, data); } struct dns_query * dns_submit_a4dnsbl_txt(struct dns_ctx *ctx, const struct in_addr *addr, const char *dnsbl, dns_query_txt_fn *cbck, void *data) { dnsc_t dn[DNS_MAXDN]; if (dns_a4ptodn(addr, dnsbl, dn, sizeof(dn)) <= 0) { dns_setstatus(ctx, DNS_E_BADQUERY); return NULL; } return dns_submit_dn(ctx, dn, DNS_C_IN, DNS_T_TXT, DNS_NOSRCH, dns_parse_txt, (dns_query_fn*)cbck, data); } struct dns_rr_a4 * dns_resolve_a4dnsbl(struct dns_ctx *ctx, const struct in_addr *addr, const char *dnsbl) { return (struct dns_rr_a4 *) dns_resolve(ctx, dns_submit_a4dnsbl(ctx, addr, dnsbl, 0, 0)); } struct dns_rr_txt * dns_resolve_a4dnsbl_txt(struct dns_ctx *ctx, const struct in_addr *addr, const char *dnsbl) { return (struct dns_rr_txt *) dns_resolve(ctx, dns_submit_a4dnsbl_txt(ctx, addr, dnsbl, 0, 0)); } struct dns_query * dns_submit_a6dnsbl(struct dns_ctx *ctx, const struct in6_addr *addr, const char *dnsbl, dns_query_a4_fn *cbck, void *data) { dnsc_t dn[DNS_MAXDN]; if (dns_a6ptodn(addr, dnsbl, dn, sizeof(dn)) <= 0) { dns_setstatus(ctx, DNS_E_BADQUERY); return NULL; } return dns_submit_dn(ctx, dn, DNS_C_IN, DNS_T_A, DNS_NOSRCH, dns_parse_a4, (dns_query_fn*)cbck, data); } struct dns_query * dns_submit_a6dnsbl_txt(struct dns_ctx *ctx, const struct in6_addr *addr, const char *dnsbl, dns_query_txt_fn *cbck, void *data) { dnsc_t dn[DNS_MAXDN]; if (dns_a6ptodn(addr, dnsbl, dn, sizeof(dn)) <= 0) { dns_setstatus(ctx, DNS_E_BADQUERY); return NULL; } return dns_submit_dn(ctx, dn, DNS_C_IN, DNS_T_TXT, DNS_NOSRCH, dns_parse_txt, (dns_query_fn*)cbck, data); } struct dns_rr_a4 * dns_resolve_a6dnsbl(struct dns_ctx *ctx, const struct in6_addr *addr, const char *dnsbl) { return (struct dns_rr_a4 *) dns_resolve(ctx, dns_submit_a6dnsbl(ctx, addr, dnsbl, 0, 0)); } struct dns_rr_txt * dns_resolve_a6dnsbl_txt(struct dns_ctx *ctx, const struct in6_addr *addr, const char *dnsbl) { return (struct dns_rr_txt *) dns_resolve(ctx, dns_submit_a6dnsbl_txt(ctx, addr, dnsbl, 0, 0)); } static int dns_rhsbltodn(const char *name, const char *rhsbl, dnsc_t dn[DNS_MAXDN]) { int l = dns_sptodn(name, dn, DNS_MAXDN); if (l <= 0) return 0; l = dns_sptodn(rhsbl, dn+l-1, DNS_MAXDN-l+1); if (l <= 0) return 0; return 1; } struct dns_query * dns_submit_rhsbl(struct dns_ctx *ctx, const char *name, const char *rhsbl, dns_query_a4_fn *cbck, void *data) { dnsc_t dn[DNS_MAXDN]; if (!dns_rhsbltodn(name, rhsbl, dn)) { dns_setstatus(ctx, DNS_E_BADQUERY); return NULL; } return dns_submit_dn(ctx, dn, DNS_C_IN, DNS_T_A, DNS_NOSRCH, dns_parse_a4, (dns_query_fn*)cbck, data); } struct dns_query * dns_submit_rhsbl_txt(struct dns_ctx *ctx, const char *name, const char *rhsbl, dns_query_txt_fn *cbck, void *data) { dnsc_t dn[DNS_MAXDN]; if (!dns_rhsbltodn(name, rhsbl, dn)) { dns_setstatus(ctx, DNS_E_BADQUERY); return NULL; } return dns_submit_dn(ctx, dn, DNS_C_IN, DNS_T_TXT, DNS_NOSRCH, dns_parse_txt, (dns_query_fn*)cbck, data); } struct dns_rr_a4 * dns_resolve_rhsbl(struct dns_ctx *ctx, const char *name, const char *rhsbl) { return (struct dns_rr_a4*) dns_resolve(ctx, dns_submit_rhsbl(ctx, name, rhsbl, 0, 0)); } struct dns_rr_txt * dns_resolve_rhsbl_txt(struct dns_ctx *ctx, const char *name, const char *rhsbl) { return (struct dns_rr_txt*) dns_resolve(ctx, dns_submit_rhsbl_txt(ctx, name, rhsbl, 0, 0)); } libtorrent-0.16.11/src/net/address_list.h0000644000000000000000000000403115175073411013703 #ifndef LIBTORRENT_DOWNLOAD_ADDRESS_LIST_H #define LIBTORRENT_DOWNLOAD_ADDRESS_LIST_H #include #include #include "torrent/object.h" #include "torrent/object_raw_bencode.h" #include "torrent/net/types.h" namespace torrent { class AddressList : public std::vector { public: void sort(); void sort_and_unique(); // Parse normal or compact list of addresses and add to AddressList void parse_address_normal(const Object::list_type& b); void parse_address_bencode(raw_list s); void parse_address_compact(raw_string s); void parse_address_compact(const std::string& s); void parse_address_compact_ipv6(const std::string& s); }; inline void AddressList::parse_address_compact(const std::string& s) { return parse_address_compact(raw_string(s.data(), s.size())); } // Move somewhere else. struct [[gnu::packed]] SocketAddressCompact { SocketAddressCompact() = default; SocketAddressCompact(uint32_t a, uint16_t p) : addr(a), port(p) {} SocketAddressCompact(const sockaddr_in* sin) : addr(sin->sin_addr.s_addr), port(sin->sin_port) {} operator sa_inet_union () const { sa_inet_union su{}; su.inet.sin_family = AF_INET; su.inet.sin_addr.s_addr = addr; su.inet.sin_port = port; return su; } uint32_t addr; uint16_t port; const char* c_str() const { return reinterpret_cast(this); } std::string str() const { return std::string(c_str(), sizeof(*this)); } }; struct [[gnu::packed]] SocketAddressCompact6 { SocketAddressCompact6() = default; SocketAddressCompact6(in6_addr a, uint16_t p) : addr(a), port(p) {} operator sa_inet_union () const { sa_inet_union su{}; su.inet6.sin6_family = AF_INET6; su.inet6.sin6_addr = addr; su.inet6.sin6_port = port; return su; } in6_addr addr; uint16_t port; const char* c_str() const { return reinterpret_cast(this); } }; } // namespace torrent #endif libtorrent-0.16.11/src/net/thread_net.cc0000644000000000000000000000643615175073411013511 #include "config.h" #include "net/thread_net.h" #include "net/curl_stack.h" #include "net/dns_buffer.h" #include "net/dns_cache.h" #include "net/udns_resolver.h" #include "torrent/exceptions.h" #include "torrent/net/http_stack.h" #include "utils/instrumentation.h" namespace torrent { class ThreadNetInternal { public: static ThreadNet* thread_net() { return ThreadNet::internal_thread_net(); } static net::HttpStack* http_stack() { return ThreadNet::internal_thread_net()->http_stack(); } }; namespace net_thread { torrent::system::Thread* thread() { return ThreadNetInternal::thread_net(); } std::thread::id thread_id() { return ThreadNetInternal::thread_net()->thread_id(); } void callback(void* target, std::function&& fn) { ThreadNetInternal::thread_net()->callback(target, std::move(fn)); } void callback_interrupt_polling(void* target, std::function&& fn) { ThreadNetInternal::thread_net()->callback_interrupt_polling(target, std::move(fn)); } void callback_interrupt_polling_and_wait(void* target, std::function&& fn) { ThreadNetInternal::thread_net()->callback_interrupt_polling_and_wait(target, std::move(fn)); } void cancel_callback(void* target) { ThreadNetInternal::thread_net()->cancel_callback(target); } void cancel_callback_and_wait(void* target) { ThreadNetInternal::thread_net()->cancel_callback_and_wait(target); } torrent::net::HttpStack* http_stack() { return ThreadNetInternal::http_stack(); } } // namespace net_thread ThreadNet* ThreadNet::m_thread_net{nullptr}; ThreadNet::~ThreadNet() = default; void ThreadNet::create_thread() { auto thread = new ThreadNet; thread->m_http_stack = std::make_unique(thread); thread->m_dns_buffer = std::make_unique(); thread->m_dns_cache = std::make_unique(); thread->m_dns_resolver = std::make_unique(); m_thread_net = thread; } void ThreadNet::destroy_thread() { delete m_thread_net; m_thread_net = nullptr; } ThreadNet* ThreadNet::thread_net() { return m_thread_net; } void ThreadNet::init_thread() { m_state = STATE_INITIALIZED; m_instrumentation_index = INSTRUMENTATION_POLLING_DO_POLL_NET - INSTRUMENTATION_POLLING_DO_POLL; } void ThreadNet::init_thread_post_local() { m_dns_resolver->initialize(this); } void ThreadNet::cleanup_thread() { m_http_stack->shutdown(); m_dns_resolver->cleanup(); } void ThreadNet::call_events() { // lt_log_print_locked(torrent::LOG_THREAD_NOTICE, "Got thread_disk tick."); while (m_http_stack->curl_stack()->process_done_handle()) ; // Do nothing. // TODO: Consider moving this into timer events instead. if ((m_flags & flag_do_shutdown)) { if ((m_flags & flag_did_shutdown)) throw internal_error("Already trigged shutdown."); m_flags |= flag_did_shutdown; throw shutdown_exception(); } process_callbacks(); m_dns_resolver->flush(); process_callbacks(); } std::chrono::microseconds ThreadNet::next_timeout() { return std::chrono::microseconds(10s); } } // namespace torrent libtorrent-0.16.11/src/net/socket_datagram.h0000644000000000000000000000116415175073411014357 #ifndef LIBTORRENT_NET_SOCKET_DGRAM_H #define LIBTORRENT_NET_SOCKET_DGRAM_H #include #include "torrent/event.h" namespace torrent { class SocketDatagram : public Event { public: ~SocketDatagram() override; int read_datagram(void* buffer, unsigned int length); int write_datagram(const void* buffer, unsigned int length); int read_datagram_sa(void* buffer, unsigned int length, sockaddr* from_sa, socklen_t from_length); int write_datagram_sa(const void* buffer, unsigned int length, sockaddr* sa); }; } // namespace torrent #endif libtorrent-0.16.11/src/net/udns_resolver.cc0000644000000000000000000003660415175073411014266 #include "config.h" #include "net/udns_resolver.h" #include #include #include #include #include "net/udns/udns.h" #include "torrent/common.h" #include "torrent/exceptions.h" #include "torrent/net/poll.h" #include "torrent/net/socket_address.h" #include "torrent/utils/log.h" #include "torrent/system/thread.h" #define LT_LOG(log_fmt, ...) \ lt_log_print_subsystem(LOG_NET_DNS, "dns-resolver", log_fmt, __VA_ARGS__); #define LT_LOG_QUERY(log_fmt, ...) \ lt_log_print(LOG_NET_DNS, "%016p->dns-resolver : " log_fmt, query->requester, __VA_ARGS__); #define LT_LOG_REQUESTER(log_fmt, ...) \ lt_log_print(LOG_NET_DNS, "%016p->dns-resolver : " log_fmt, requester, __VA_ARGS__); namespace torrent::net { struct UdnsQuery { // TODO: We already use deleted. ~UdnsQuery() { parent = nullptr; } void* requester{}; std::string hostname; int family{}; resolver_callback callback; // TODO: Verify canceled and deleted atomicity. UdnsResolver* parent{}; bool canceled{}; bool deleted{}; ::dns_query* a4_query{}; ::dns_query* a6_query{}; sin_shared_ptr result_sin; sin6_shared_ptr result_sin6; int error_sin{}; int error_sin6{}; std::string cname4_name; std::string cname6_name; unsigned int cname4_depth{}; unsigned int cname6_depth{}; }; class UdnsResolverInternal { public: static void a4_callback_wrapper(::dns_ctx *ctx, ::dns_rr_a4 *result, void *data); static void a6_callback_wrapper(::dns_ctx *ctx, ::dns_rr_a6 *result, void *data); }; bool UdnsResolver::m_initialized = false; static int udnserror_to_gaierror(int udnserror) { switch (udnserror) { case DNS_E_TEMPFAIL: return EAI_AGAIN; case DNS_E_PROTOCOL: // this isn't quite right return EAI_FAIL; case DNS_E_NXDOMAIN: return EAI_NONAME; case DNS_E_NODATA: return EAI_ADDRFAMILY; case DNS_E_NOMEM: return EAI_MEMORY; case DNS_E_BADQUERY: return EAI_NONAME; default: return EAI_ADDRFAMILY; } } UdnsResolver::UdnsResolver() { if (!m_initialized) { LT_LOG("initializing udns", 0); ::dns_init(nullptr, 0); m_initialized = true; } m_task_timeout.slot() = [this]() { process_timeouts(); }; } UdnsResolver::~UdnsResolver() { assert(!is_open() && "UdnsResolver::~UdnsResolver() is_open()."); } void UdnsResolver::initialize(system::Thread* thread) { assert(std::this_thread::get_id() == thread->thread_id()); LT_LOG("initializing udns resolver: thread:%s", thread->name()); m_thread = thread; m_ctx = ::dns_new(nullptr); m_fileDesc = ::dns_open(m_ctx); if (!is_open()) throw internal_error("UdnsResolver::initialize() dns_open failed"); torrent::this_thread::poll()->open(this); } void UdnsResolver::cleanup() { assert(std::this_thread::get_id() == m_thread->thread_id()); this_thread::scheduler()->erase(&m_task_timeout); if (!is_open()) { LT_LOG("cleanup not needed, not initialized: thread:%s", m_thread->name()); return; } LT_LOG("cleaning up: thread:%s", m_thread->name()); this_thread::poll()->remove_and_close(this); ::dns_close(m_ctx); ::dns_free(m_ctx); m_fileDesc = -1; } void UdnsResolver::resolve(void* requester, const std::string& hostname, int family, resolver_callback&& callback) { assert(std::this_thread::get_id() == m_thread->thread_id()); assert(family == AF_INET || family == AF_INET6 || family == AF_UNSPEC); auto query = std::make_unique(); query->requester = requester; query->hostname = hostname; query->family = family; query->callback = std::move(callback); query->parent = this; if (try_resolve_numeric(query)) return; if (family == AF_INET || family == AF_UNSPEC) { query->a4_query = ::dns_submit_a4(m_ctx, hostname.c_str(), 0, UdnsResolverInternal::a4_callback_wrapper, query.get()); if (query->a4_query == nullptr) { LT_LOG_REQUESTER("malformed A query : name:%s", hostname.c_str()); // Unrecoverable errors, like ENOMEM. if (::dns_status(m_ctx) != DNS_E_BADQUERY) throw new internal_error("dns_submit_a4 failed"); // UDNS will fail immediately during submission of malformed domain names, // e.g., `..`. In order to maintain a clean interface, keep track of this // query internally so we can call the callback later with a failure code. query->error_sin = EAI_NONAME; { auto lock = std::lock_guard(m_mutex); m_malformed_queries_unsafe.emplace(requester, std::move(query)); } process_timeouts(); return; } } if (family == AF_INET6 || family == AF_UNSPEC) { query->a6_query = ::dns_submit_a6(m_ctx, hostname.c_str(), 0, UdnsResolverInternal::a6_callback_wrapper, query.get()); // It should be impossible for dns_submit_a6 to fail if dns_submit_a4 // succeeded, but just in case, make it a hard failure. if (query->a6_query == nullptr) { LT_LOG_REQUESTER("malformed AAAA query : name:%s", hostname.c_str()); if (query->a4_query != nullptr) { ::dns_cancel(m_ctx, query->a4_query); query->a4_query = nullptr; } if (::dns_status(m_ctx) != DNS_E_BADQUERY) throw new internal_error("dns_submit_a6 failed"); query->error_sin = EAI_NONAME; { auto lock = std::lock_guard(m_mutex); m_malformed_queries_unsafe.emplace(requester, std::move(query)); } process_timeouts(); return; } } LT_LOG_REQUESTER("resolving : name:%s family:%d", hostname.c_str(), family); { auto lock = std::lock_guard(m_mutex); m_queries_unsafe.emplace(requester, std::move(query)); } process_timeouts(); } bool UdnsResolver::try_resolve_numeric(std::unique_ptr& query) { assert(std::this_thread::get_id() == m_thread->thread_id()); addrinfo hints{}; addrinfo* result{}; hints.ai_family = query->family; hints.ai_socktype = SOCK_STREAM; // Not used, but required. hints.ai_flags = AI_NUMERICHOST; int ret = ::getaddrinfo(query->hostname.c_str(), nullptr, &hints, &result); if (ret == EAI_NONAME || ret == EAI_ADDRFAMILY) return false; // No numeric address found. if (ret != 0) throw internal_error("getaddrinfo failed: " + std::string(gai_enum_error(ret))); LT_LOG_QUERY("resolving : numeric found : name:%s family:%d", query->hostname.c_str(), query->family); if (result->ai_family == AF_INET) { query->result_sin = sin_copy(reinterpret_cast(result->ai_addr)); query->error_sin = 0; } else if (result->ai_family == AF_INET6) { query->result_sin6 = sin6_copy(reinterpret_cast(result->ai_addr)); query->error_sin6 = 0; } else { ::freeaddrinfo(result); throw internal_error("getaddrinfo returned unsupported family"); } if (query->family != AF_UNSPEC && query->family != result->ai_family) throw internal_error("getaddrinfo returned address with unexpected family"); ::freeaddrinfo(result); { auto lock = std::lock_guard(m_mutex); process_final_result_unsafe(std::move(query)); } return true; } void UdnsResolver::cancel(void* requester) { auto lock = std::lock_guard(m_mutex); auto cancel_fn = [](std::pair range) { unsigned int count = 0; for (auto itr = range.first; itr != range.second; ++itr) { if (itr->second->canceled) continue; itr->second->canceled = true; ++count; } return count; }; unsigned int query_count = cancel_fn(m_queries_unsafe.equal_range(requester)); unsigned int malformed_count = cancel_fn(m_malformed_queries_unsafe.equal_range(requester)); LT_LOG_REQUESTER("canceled : queries:%d malformed:%d", query_count, malformed_count); } void UdnsResolver::flush() { assert(std::this_thread::get_id() == m_thread->thread_id()); // Keep lock to ensure cancel() calls do not return until after flushing is complete. auto lock = std::lock_guard(m_mutex); auto malformed_queries = std::move(m_malformed_queries_unsafe); for (auto& malformed : malformed_queries) { auto query = malformed.second.get(); if (query->canceled) continue; LT_LOG_QUERY("flushing malformed query : name:%s", query->hostname.c_str()); if (query->error_sin == 0 && query->error_sin6 == 0) throw internal_error("attempting to flush malformed query with no error"); query->callback(nullptr, query->error_sin, nullptr, query->error_sin6); } } void UdnsResolver::event_read() { ::dns_ioevent(m_ctx, 0); process_timeouts(); } void UdnsResolver::event_write() { throw internal_error("UdnsResolver::event_write() called"); } void UdnsResolver::event_error() { throw internal_error("UdnsResolver::event_error() called"); } UdnsResolver::query_map::iterator UdnsResolver::find_query_or_fail_unsafe(UdnsQuery* query) { auto range = m_queries_unsafe.equal_range(query->requester); for (auto itr = range.first; itr != range.second; ++itr) { if (itr->second.get() == query) return itr; } throw internal_error("UdnsResolver::find_query_or_fail_unsafe() called with invalid query"); } // Do not call recursively. void UdnsResolver::process_timeouts() { assert(std::this_thread::get_id() == m_thread->thread_id()); int timeout = ::dns_timeouts(m_ctx, -1, 0); if (timeout == -1) { this_thread::poll()->remove_read(this); this_thread::poll()->remove_error(this); this_thread::scheduler()->erase(&m_task_timeout); LT_LOG("processing timeouts, no pending queries", 0); return; } if (timeout < 0) throw internal_error("UdnsResolver::process_timeouts() dns_timeouts returned invalid timeout: " + std::to_string(timeout)); LT_LOG("processing timeouts, next in %d seconds", timeout); this_thread::poll()->insert_read(this); this_thread::poll()->insert_error(this); this_thread::scheduler()->update_wait_for_ceil_seconds(&m_task_timeout, timeout * 1s); } void UdnsResolverInternal::a4_callback_wrapper(::dns_ctx *ctx, ::dns_rr_a4 *result, void *data) { auto query = static_cast(data); auto lock = std::lock_guard(query->parent->m_mutex); if (query->deleted) { LT_LOG_QUERY("A records received, but query was deleted : name:%s", query->requester, query->hostname.c_str()); throw internal_error("UdnsResolver::a4_callback_wrapper called with deleted query"); } auto itr = query->parent->find_query_or_fail_unsafe(query); query->a4_query = nullptr; if (result == nullptr) { query->error_sin = udnserror_to_gaierror(::dns_status(ctx)); LT_LOG_QUERY("no A records received, calling back with error : name:%s error:%s", query->hostname.c_str(), gai_enum_error(query->error_sin)); UdnsResolver::process_partial_result_unsafe(itr); return; } if (result->dnsa4_nrr > 0) { query->result_sin = sin_make(); query->result_sin->sin_addr = result->dnsa4_addr[0]; LT_LOG_QUERY("A records received : name:%s nrr:%d", query->hostname.c_str(), result->dnsa4_nrr); UdnsResolver::process_partial_result_unsafe(itr); return; } if (result->dnsa4_cname != nullptr) { if (query->cname4_depth++ >= 8) { query->error_sin = EAI_FAIL; LT_LOG_QUERY("A CNAME depth exceeded : original:%s current:%s", query->hostname.c_str(), query->cname4_name.c_str()); UdnsResolver::process_partial_result_unsafe(itr); return; } query->cname4_name = result->dnsa4_cname; query->a4_query = ::dns_submit_a4(ctx, query->cname4_name.c_str(), 0, &UdnsResolverInternal::a4_callback_wrapper, query); LT_LOG_QUERY("A CNAME encountered, retrying : original:%s cname:%s depth:%u", query->hostname.c_str(), query->cname4_name.c_str(), query->cname4_depth); return; } query->error_sin = udnserror_to_gaierror(::dns_status(ctx)); if (query->error_sin6 == 0) query->error_sin6 = EAI_NODATA; LT_LOG_QUERY("No A records found : name:%s error:%s", query->hostname.c_str(), gai_enum_error(query->error_sin)); UdnsResolver::process_partial_result_unsafe(itr); } void UdnsResolverInternal::a6_callback_wrapper(::dns_ctx *ctx, ::dns_rr_a6 *result, void *data) { auto query = static_cast(data); auto lock = std::lock_guard(query->parent->m_mutex); if (query->deleted) { LT_LOG_QUERY("AAAA records received, but query was deleted : name:%s", query->hostname.c_str()); throw internal_error("UdnsResolver::a6_callback_wrapper called with deleted query"); } auto itr = query->parent->find_query_or_fail_unsafe(query); query->a6_query = nullptr; if (result == nullptr) { query->error_sin6 = udnserror_to_gaierror(::dns_status(ctx)); LT_LOG_QUERY("no AAAA records received, calling back with error : name:%s error:%s", query->hostname.c_str(), gai_enum_error(query->error_sin6)); UdnsResolver::process_partial_result_unsafe(itr); return; } if (result->dnsa6_nrr > 0) { query->result_sin6 = sin6_make(); query->result_sin6->sin6_addr = result->dnsa6_addr[0]; LT_LOG_QUERY("AAAA records received : name:%s nrr:%d", query->hostname.c_str(), result->dnsa6_nrr); UdnsResolver::process_partial_result_unsafe(itr); return; } if (result->dnsa6_cname != nullptr) { if (query->cname6_depth++ >= 8) { query->error_sin6 = EAI_FAIL; LT_LOG_QUERY("AAAA CNAME depth exceeded : original:%s current:%s", query->hostname.c_str(), query->cname6_name.c_str()); UdnsResolver::process_partial_result_unsafe(itr); return; } query->cname6_name = result->dnsa6_cname; query->a6_query = ::dns_submit_a6(ctx, query->cname6_name.c_str(), 0, &UdnsResolverInternal::a6_callback_wrapper, query); LT_LOG_QUERY("AAAA CNAME encountered, retrying : original:%s cname:%s depth:%u", query->hostname.c_str(), query->cname6_name.c_str(), query->cname6_depth); return; } query->error_sin6 = udnserror_to_gaierror(::dns_status(ctx)); if (query->error_sin6 == 0) query->error_sin6 = EAI_NODATA; LT_LOG_QUERY("No AAAA records found : name:%s error:%s", query->hostname.c_str(), gai_enum_error(query->error_sin6)); UdnsResolver::process_partial_result_unsafe(itr); } void UdnsResolver::process_partial_result_unsafe(query_map::iterator itr) { auto& query = itr->second; if (query->a4_query != nullptr || query->a6_query != nullptr) { LT_LOG_QUERY("processing results, waiting for other queries : name:%s", query->hostname.c_str()); return; } auto tmp = std::move(itr->second); tmp->deleted = true; tmp->parent->m_queries_unsafe.erase(itr); process_final_result_unsafe(std::move(tmp)); } void UdnsResolver::process_final_result_unsafe(std::unique_ptr&& query) { if (query->canceled) { LT_LOG_QUERY("processing results, canceled : name:%s", query->hostname.c_str()); return; } LT_LOG_QUERY("processing results, calling back : name:%s", query->hostname.c_str()); if (query->result_sin && query->error_sin != 0) throw internal_error("UdnsResolver::process_final_result_unsafe() query has both result and error for A record"); if (query->result_sin6 && query->error_sin6 != 0) throw internal_error("UdnsResolver::process_final_result_unsafe() query has both result and error for AAAA record"); query->callback(query->result_sin, query->error_sin, query->result_sin6, query->error_sin6); } } // namespace torrent::net libtorrent-0.16.11/src/net/socket_stream.h0000644000000000000000000000365215175073411014076 #ifndef LIBTORRENT_NET_SOCKET_STREAM_H #define LIBTORRENT_NET_SOCKET_STREAM_H #include #include #include "torrent/event.h" #include "torrent/exceptions.h" namespace torrent { class SocketStream : public Event { public: ~SocketStream() override; int read_stream(void* buf, uint32_t length); int write_stream(const void* buf, uint32_t length); // Returns the number of bytes read, or zero if the socket is // blocking. On errors or closed sockets it will throw an // appropriate exception. uint32_t read_stream_throws(void* buf, uint32_t length); uint32_t write_stream_throws(const void* buf, uint32_t length); // Handles all the error catching etc. Returns true if the buffer is // finished reading/writing. bool read_buffer(void* buf, uint32_t length, uint32_t& pos); bool write_buffer(const void* buf, uint32_t length, uint32_t& pos); uint32_t ignore_stream_throws(uint32_t length) { return read_stream_throws(m_nullBuffer, length); } protected: static constexpr size_t null_buffer_size = 1 << 17; static char* m_nullBuffer; }; inline bool SocketStream::read_buffer(void* buf, uint32_t length, uint32_t& pos) { pos += read_stream_throws(buf, length - pos); return pos == length; } inline bool SocketStream::write_buffer(const void* buf, uint32_t length, uint32_t& pos) { pos += write_stream_throws(buf, length - pos); return pos == length; } inline int SocketStream::read_stream(void* buf, uint32_t length) { if (length == 0) throw internal_error("Tried to read to buffer length 0."); return ::recv(m_fileDesc, buf, length, 0); } inline int SocketStream::write_stream(const void* buf, uint32_t length) { if (length == 0) throw internal_error("Tried to write to buffer length 0."); return ::send(m_fileDesc, buf, length, 0); } } // namespace torrent #endif libtorrent-0.16.11/src/manager.cc0000644000000000000000000001370515175073411012215 #include "config.h" #include "manager.h" #include "runtime.h" #include "data/chunk_list.h" #include "data/hash_torrent.h" #include "download/download_main.h" #include "download/download_wrapper.h" #include "net/listen.h" #include "protocol/handshake_manager.h" #include "torrent/chunk_manager.h" #include "torrent/connection_manager.h" #include "torrent/throttle.h" #include "torrent/data/file_manager.h" #include "torrent/download/choke_group.h" #include "torrent/download/choke_queue.h" #include "torrent/download/download_manager.h" #include "torrent/download/resource_manager.h" #include "torrent/net/network_config.h" #include "torrent/net/poll.h" #include "torrent/peer/client_list.h" #include "torrent/runtime/network_manager.h" #include "torrent/runtime/socket_manager.h" #include "utils/instrumentation.h" #include "utils/thread_internal.h" namespace torrent { Manager* manager = nullptr; namespace config { net::NetworkConfig* network_config() { return manager->network_config(); } } // namespace config namespace this_thread { // TODO: Deprecate these. void event_open(Event* event) { system::ThreadInternal::poll()->open(event); } void event_open_and_count(Event* event) { system::ThreadInternal::poll()->open(event); manager->connection_manager()->inc_socket_count(); } void event_close_and_count(Event* event) { system::ThreadInternal::poll()->close(event); manager->connection_manager()->dec_socket_count(); } void event_insert_read(Event* event) { system::ThreadInternal::poll()->insert_read(event); } void event_insert_write(Event* event) { system::ThreadInternal::poll()->insert_write(event); } void event_insert_error(Event* event) { system::ThreadInternal::poll()->insert_error(event); } void event_remove_read(Event* event) { system::ThreadInternal::poll()->remove_read(event); } void event_remove_write(Event* event) { system::ThreadInternal::poll()->remove_write(event); } void event_remove_error(Event* event) { system::ThreadInternal::poll()->remove_error(event); } void event_remove_and_close(Event* event) { system::ThreadInternal::poll()->remove_and_close(event); } } // namespace this_thread Manager::Manager() : m_network_config(new net::NetworkConfig), m_chunk_manager(new ChunkManager), m_connection_manager(new ConnectionManager), m_download_manager(new DownloadManager), m_file_manager(new FileManager), m_handshake_manager(new HandshakeManager), m_resource_manager(new ResourceManager), m_client_list(new ClientList), m_uploadThrottle(Throttle::create_throttle()), m_downloadThrottle(Throttle::create_throttle()) { Runtime::initialize(torrent::this_thread::thread()); m_task_tick.slot() = [this] { receive_tick(); }; torrent::this_thread::scheduler()->wait_for_ceil_seconds(&m_task_tick, 1s); m_handshake_manager->slot_download_id() = [this](auto hash) { return m_download_manager->find_main(hash); }; m_handshake_manager->slot_download_obfuscated() = [this](auto hash) { return m_download_manager->find_main_obfuscated(hash); }; network_manager()->listen_inet_unsafe()->slot_accepted() = [this](auto& handshake, auto fd, auto sa) { return m_handshake_manager->add_incoming(handshake, fd, sa); }; network_manager()->listen_inet6_unsafe()->slot_accepted() = [this](auto& handshake, auto fd, auto sa) { return m_handshake_manager->add_incoming(handshake, fd, sa); }; m_resource_manager->push_group("default"); m_resource_manager->group_back()->up_queue()->set_heuristics(choke_queue::HEURISTICS_UPLOAD_LEECH); m_resource_manager->group_back()->down_queue()->set_heuristics(choke_queue::HEURISTICS_DOWNLOAD_LEECH); } Manager::~Manager() { torrent::this_thread::scheduler()->erase(&m_task_tick); network_manager()->listen_close(); m_handshake_manager->clear(); m_download_manager->clear(); Throttle::destroy_throttle(m_uploadThrottle); Throttle::destroy_throttle(m_downloadThrottle); instrumentation_tick(); Runtime::cleanup(); } void Manager::initialize_download(DownloadWrapper* d) { d->main()->slot_count_handshakes([this](DownloadMain* download) { return m_handshake_manager->size_info(download); }); d->main()->slot_start_handshake([this](const sockaddr* sa, DownloadMain* download) { return m_handshake_manager->add_outgoing(sa, download); }); d->main()->slot_stop_handshakes([this](DownloadMain* download) { return m_handshake_manager->erase_download(download); }); // TODO: The resource manager doesn't need to know about this // download until we start/stop the torrent. m_download_manager->insert(d); m_resource_manager->insert(d->main(), 1); m_chunk_manager->insert(d->main()->chunk_list()); d->main()->chunk_list()->set_chunk_size(d->main()->file_list()->chunk_size()); d->main()->set_upload_throttle(m_uploadThrottle->throttle_list()); d->main()->set_download_throttle(m_downloadThrottle->throttle_list()); } void Manager::cleanup_download(DownloadWrapper* d) { d->main()->stop(); d->close(); m_resource_manager->erase(d->main()); m_chunk_manager->erase(d->main()->chunk_list()); m_download_manager->erase(d); } void Manager::receive_tick() { m_ticks++; if (m_ticks % 2 == 0) instrumentation_tick(); m_resource_manager->receive_tick(); m_chunk_manager->periodic_sync(); // To ensure the downloads get equal chance over time at using // various limited resources, like sockets for handshakes, cycle the // group in reverse order. if (!m_download_manager->empty()) { auto split = m_download_manager->end() - m_ticks % m_download_manager->size() - 1; std::for_each(split, m_download_manager->end(), [this](auto wrapper) { return wrapper->receive_tick(m_ticks); }); std::for_each(m_download_manager->begin(), split, [this](auto wrapper) { return wrapper->receive_tick(m_ticks); }); } // If you change the interval, make sure the keepalives gets // triggered every 120 seconds. torrent::this_thread::scheduler()->wait_for_ceil_seconds(&m_task_tick, 30s); } } // namespace torrent libtorrent-0.16.11/src/thread_main.h0000644000000000000000000000203715175073411012714 #ifndef LIBTORRENT_THREAD_MAIN_H #define LIBTORRENT_THREAD_MAIN_H #include #include "torrent/common.h" #include "torrent/system/thread.h" namespace torrent { class HashQueue; class LIBTORRENT_EXPORT ThreadMain : public system::Thread { public: ~ThreadMain() override; static void create_thread(); static ThreadMain* thread_main(); const char* name() const override { return "rtorrent main"; } void init_thread() override; void cleanup_thread() override; HashQueue* hash_queue() { return m_hash_queue.get(); } auto& slot_do_work() { return m_slot_do_work; } protected: friend class ThreadMainInternal; ThreadMain() = default; void call_events() override; std::chrono::microseconds next_timeout() override; static ThreadMain* m_thread_main; std::unique_ptr m_hash_queue; std::function m_slot_do_work; }; } // namespace torrent #endif // LIBTORRENT_THREAD_MAIN_H libtorrent-0.16.11/src/runtime.cc0000644000000000000000000000227615175073411012267 #include "config.h" #include "runtime.h" #include "torrent/runtime/network_manager.h" #include "torrent/runtime/socket_manager.h" namespace torrent { Runtime* g_runtime{}; namespace runtime { NetworkManager* network_manager() { return g_runtime->network_manager(); } SocketManager* socket_manager() { return g_runtime->socket_manager(); } void dht_add_peer_node(const sockaddr* sa, uint16_t port) { g_runtime->network_manager()->dht_add_peer_node(sa, port); } uint16_t listen_port() { return g_runtime->network_manager()->listen_port(); } } // namespace runtime Runtime::Runtime(system::Thread* main_thread) : m_main_thread(main_thread), m_network_manager(new runtime::NetworkManager(main_thread)), m_socket_manager(new runtime::SocketManager) { } Runtime::~Runtime() { // Order matters for destruction. m_network_manager.reset(); m_socket_manager.reset(); } void Runtime::initialize(system::Thread* main_thread) { g_runtime = new Runtime(main_thread); } void Runtime::cleanup() { delete g_runtime; g_runtime = nullptr; } } // namespace torrent libtorrent-0.16.11/src/dht/0000755000000000000000000000000015175073434011132 5libtorrent-0.16.11/src/dht/dht_router.cc0000644000000000000000000004466015175073411013545 #include "config.h" #include "dht_router.h" #include #include "dht_bucket.h" #include "dht_tracker.h" #include "dht_transaction.h" #include "torrent/exceptions.h" #include "torrent/net/resolver.h" #include "torrent/net/socket_address.h" #include "torrent/tracker/dht_controller.h" #include "torrent/utils/log.h" #include "utils/sha1.h" #define LT_LOG_THIS(log_fmt, ...) \ lt_log_print_hash(torrent::LOG_DHT_ROUTER, this->id(), "dht_router", log_fmt, __VA_ARGS__); namespace torrent { HashString DhtRouter::zero_id; DhtRouter::DhtRouter(const Object& cache) : DhtNode(zero_id, sa_make_inet_any().get()), // actual ID is set later m_server(this), m_curToken(random()), m_prevToken(random()) { HashString ones_id; zero_id.clear(); ones_id.clear(0xFF); if (cache.has_key("self_id")) { const std::string& id = cache.get_key_string("self_id"); if (id.length() != HashString::size_data) throw bencode_error("Loading cache: Invalid ID."); assign(id.c_str()); } else { long buffer[size_data]; for (long* itr = buffer; itr != buffer + size_data; ++itr) *itr = random(); Sha1 sha; sha.init(); sha.update(buffer, sizeof(buffer)); sha.final_c(data()); } LT_LOG_THIS("creating", 0); set_bucket(new DhtBucket(zero_id, ones_id)); m_routingTable.emplace(bucket()->id_range_end(), bucket()); if (cache.has_key("nodes")) { const Object::map_type& nodes = cache.get_key_map("nodes"); LT_LOG_THIS("adding nodes : size:%zu", nodes.size()); for (const auto& [id, node] : nodes) { if (id.length() != HashString::size_data) throw bencode_error("Loading cache: Invalid node hash."); add_node_to_bucket(m_nodes.add_node(new DhtNode(id, node))); } } if (m_nodes.size() < num_bootstrap_complete) { m_contacts.emplace(); if (cache.has_key("contacts")) { for (const auto& contact : cache.get_key_list("contacts")) { auto litr = contact.as_list().begin(); auto host = litr->as_string(); auto port = std::next(litr)->as_value(); m_contacts->emplace_back(std::move(host), port); } } } } DhtRouter::~DhtRouter() { assert(!is_active() && "DhtRouter::~DhtRouter() called while still active."); for (auto& route : m_routingTable) delete route.second; for (auto& tracker : m_trackers) delete tracker.second; for (auto& node : m_nodes) delete node.second; } void DhtRouter::start(int port) { LT_LOG_THIS("starting: port:%d", port); m_server.start(port); // Set timeout slot and schedule it to be called immediately for initial bootstrapping if // necessary. m_task_timeout.slot() = [this] { receive_timeout_bootstrap(); }; this_thread::scheduler()->wait_for_ceil_seconds(&m_task_timeout, 1s); } void DhtRouter::stop() { if (!is_active()) return; LT_LOG_THIS("stopping", 0); this_thread::resolver()->cancel(this); this_thread::scheduler()->erase(&m_task_timeout); m_server.stop(); } // Start a DHT get_peers and announce_peer request. void DhtRouter::announce(const HashString& info_hash, TrackerDht* tracker) { m_server.announce(*find_bucket(info_hash)->second, info_hash, tracker); } // Cancel any running requests from the given tracker. // If info or tracker is not NULL, only cancel matching requests. void DhtRouter::cancel_announce(const HashString* info_hash, const TrackerDht* tracker) { m_server.cancel_announce(info_hash, tracker); } DhtTracker* DhtRouter::get_tracker(const HashString& hash, bool create) { auto itr = m_trackers.find(hash); if (itr != m_trackers.end()) return itr->second; if (!create) return NULL; auto [tr, ins] = m_trackers.emplace(hash, new DhtTracker()); if (!ins) throw internal_error("DhtRouter::get_tracker did not actually insert tracker."); return tr->second; } bool DhtRouter::want_node(const HashString& id) { // We don't want to add ourself. Also, too many broken implementations // advertise an ID of 0, which causes collisions, so reject that. if (id == this->id() || id == zero_id) return false; // We are always interested in more nodes for our own bucket (causing it // to be split if full); in other buckets only if there's space. DhtBucket* b = find_bucket(id)->second; return b == bucket() || b->has_space(); } DhtNode* DhtRouter::get_node(const HashString& id) { DhtNodeList::accessor itr = m_nodes.find(&id); if (itr == m_nodes.end()) { if (id == this->id()) return this; else return NULL; } return itr.node(); } DhtRouter::DhtBucketList::iterator DhtRouter::find_bucket(const HashString& id) { auto itr = m_routingTable.lower_bound(id); #ifdef USE_EXTRA_DEBUG if (itr == m_routingTable.end()) throw internal_error("DHT Buckets not covering entire ID space."); if (!itr->second->is_in_range(id)) throw internal_error("DhtRouter::find_bucket, m_routingTable.lower_bound did not find correct bucket."); #endif return itr; } void DhtRouter::add_bootstrap_contact(const std::string& host, int port) { if (!m_contacts.has_value()) { LT_LOG_THIS("ignoring bootstrap contact : %s:%d", host.c_str(), port); return; } // Externally obtained nodes are added to the contact list, but only if // we're still bootstrapping. We don't contact external nodes after that. if (m_contacts->size() >= num_bootstrap_contacts) m_contacts->pop_front(); m_contacts->emplace_back(host, port); LT_LOG_THIS("added bootstrap contact : %s:%d", host.c_str(), port); } void DhtRouter::contact(const sockaddr* sa, int port) { if (!is_active()) return; auto sa_tmp = sa_copy_unmapped(sa); if (sa_tmp->sa_family != AF_INET && sa_tmp->sa_family != AF_INET6) throw input_error("DhtRouter::contact() called with non-inet/inet6 address."); // Currently only IPv4 is supported. if (sa_tmp->sa_family != AF_INET) return; if (sap_is_any(sa_tmp)) throw input_error("DhtRouter::contact() called with any address."); sap_set_port(sa_tmp, port); LT_LOG_THIS("contacting node : %s:%d", sa_addr_str(sa_tmp.get()).c_str(), port); m_server.ping(zero_id, sa_tmp.get()); } // Received a query from the given node. If it has previously replied // to one of our queries, consider it alive and update the bucket mtime, // otherwise if we could use it in a bucket, try contacting it. DhtNode* DhtRouter::node_queried(const HashString& id, const sockaddr* sa) { DhtNode* node = get_node(id); if (node == nullptr) { if (want_node(id)) m_server.ping(id, sa); return nullptr; } // If we know the ID but the address is different, don't set the original node // active, but neither use this new address to prevent rogue nodes from polluting // our routing table with fake source addresses. if (!sa_equal_addr(node->address(), sa)) return nullptr; node->queried(); if (node->is_good()) node->bucket()->touch(); return node; } // Received a reply from a node we queried. // Check that it matches the information we have, set that it has replied // and update the bucket mtime. DhtNode* DhtRouter::node_replied(const HashString& id, const sockaddr* sa) { DhtNode* node = get_node(id); if (node == NULL) { if (!want_node(id)) return NULL; // New node, create it. It's a good node (it replied!) so add it to a bucket. node = m_nodes.add_node(new DhtNode(id, sa)); if (!add_node_to_bucket(node)) // deletes the node if it fails return NULL; } if (!sa_equal_addr(node->address(), sa)) return NULL; node->replied(); node->bucket()->touch(); return node; } // A node has not replied to one of our queries. DhtNode* DhtRouter::node_inactive(const HashString& id, const sockaddr* sa) { DhtNodeList::accessor itr = m_nodes.find(&id); // If not found add it to some blacklist so we won't try contacting it again immediately? if (itr == m_nodes.end()) return NULL; // Check source address. Normally node_inactive is called if we DON'T receive a reply, // however it can also be called if a node replied with an malformed response packet, // so check that the address matches so that a rogue node cannot cause other nodes // to be considered bad by sending malformed packets. if (!sa_equal_addr(itr.node()->address(), sa)) return NULL; itr.node()->inactive(); // Old node age normally implies no replies for many consecutive queries, however // after loading the node cache after a day or more we want to give each node a few // chances to reply again instead of removing all nodes instantly. if (itr.node()->is_bad() && itr.node()->age() >= timeout_remove_node) { delete_node(itr); return NULL; } return itr.node(); } // We sent a query to the given node ID, but received a reply from a different // node ID, that means the address of the original ID is invalid now. void DhtRouter::node_invalid(const HashString& id) { DhtNode* node = get_node(id); if (node == NULL || node == this) return; delete_node(m_nodes.find(&node->id())); } Object* DhtRouter::store_cache(Object* container) const { container->insert_key("self_id", str()); // Insert all nodes. Object& nodes = container->insert_key("nodes", Object::create_map()); for (const auto& [id, node] : m_nodes) { if (!node->is_bad()) node->store_cache(&nodes.insert_key(id->str(), Object::create_map())); } // Insert contacts, if we have any. if (m_contacts.has_value()) { Object& contacts = container->insert_key("contacts", Object::create_list()); for (const auto& m_contact : *m_contacts) { Object::list_type& list = contacts.insert_back(Object::create_list()).as_list(); list.emplace_back(m_contact.first); list.emplace_back(m_contact.second); } } return container; } tracker::DhtController::statistics_type DhtRouter::get_statistics() const { tracker::DhtController::statistics_type stats; if (!m_server.is_active()) stats.cycle = 0; else if (m_numRefresh < 2) // still bootstrapping stats.cycle = 1; else stats.cycle = m_numRefresh; stats.queries_received = m_server.queries_received(); stats.queries_sent = m_server.queries_sent(); stats.replies_received = m_server.replies_received(); stats.errors_received = m_server.errors_received(); stats.errors_caught = m_server.errors_caught(); stats.num_nodes = m_nodes.size(); stats.num_buckets = m_routingTable.size(); stats.num_peers = 0; stats.max_peers = 0; stats.num_trackers = m_trackers.size(); for (const auto& [_, tracker] : m_trackers) { unsigned int peers = tracker->size(); stats.num_peers += peers; stats.max_peers = std::max(peers, stats.max_peers); } return stats; } void DhtRouter::receive_timeout_bootstrap() { // If we're still bootstrapping, restart the process every 60 seconds until // we have enough nodes in our routing table. After we have 32 nodes, we switch // to a less aggressive non-bootstrap mode of collecting nodes that contact us // and through doing normal torrent announces. if (m_nodes.size() < num_bootstrap_complete) { if (!m_contacts.has_value()) throw internal_error("DhtRouter::receive_timeout_bootstrap called without contact list."); if (!m_nodes.empty() || !m_contacts->empty()) bootstrap(); // Retry in 60 seconds. this_thread::scheduler()->wait_for_ceil_seconds(&m_task_timeout, std::chrono::seconds(timeout_bootstrap_retry)); m_numRefresh = 1; // still bootstrapping } else { // We won't be needing external contacts after this. m_contacts.reset(); m_task_timeout.slot() = [this] { receive_timeout(); }; if (!m_numRefresh) { // If we're still in the startup, do the usual refreshing too. receive_timeout(); } else { // Otherwise just set the 15 minute timer. this_thread::scheduler()->wait_for_ceil_seconds(&m_task_timeout, std::chrono::seconds(timeout_update)); } m_numRefresh = 2; } } void DhtRouter::receive_timeout() { this_thread::scheduler()->wait_for_ceil_seconds(&m_task_timeout, std::chrono::seconds(timeout_update)); m_prevToken = m_curToken; m_curToken = random(); // Do some periodic accounting, refreshing buckets and marking // bad nodes. // Update nodes. for (const auto& [id, node] : m_nodes) { if (!node->bucket()) throw internal_error("DhtRouter::receive_timeout has node without bucket."); node->update(); // Try contacting nodes we haven't received anything from for a while. // Don't contact repeatedly unresponsive nodes; we keep them in case they // do send a query, until we find a better node. However, give it a last // chance just before deleting it. if (node->is_questionable() && (!node->is_bad() || node->age() >= timeout_remove_node)) m_server.ping(node->id(), node->address()); } // If bucket isn't full yet or hasn't received replies/queries from // its nodes for a while, try to find new nodes now. for (const auto& route : m_routingTable) { route.second->update(); if (!route.second->is_full() || route.second == bucket() || route.second->age() > timeout_bucket_bootstrap) bootstrap_bucket(route.second); } // Remove old peers and empty torrents from the tracker. for (auto itr = m_trackers.begin(); itr != m_trackers.end();) { auto tracker = itr->second; tracker->prune(timeout_peer_announce); if (tracker->empty()) { delete tracker; itr = m_trackers.erase(itr); continue; } ++itr; } m_server.update(); m_numRefresh++; } char* DhtRouter::generate_token(const sockaddr* sa, int token, char buffer[20]) { if (!sa_is_inet(sa)) throw internal_error("DhtRouter::generate_token called with non-inet address."); uint32_t key = reinterpret_cast(sa)->sin_addr.s_addr; Sha1 sha; sha.init(); sha.update(&token, sizeof(token)); sha.update(&key, 4); sha.final_c(buffer); return buffer; } bool DhtRouter::token_valid(raw_string token, const sockaddr* sa) const { if (token.size() != size_token) return false; // Compare given token to the reference token. char reference[20]; // First try current token. // // Else if token recently changed, some clients may be using the older one. // That way a token is valid for 15-30 minutes, instead of 0-15. return token == raw_string(generate_token(sa, m_curToken, reference), size_token) || token == raw_string(generate_token(sa, m_prevToken, reference), size_token); } DhtNode* DhtRouter::find_node(const sockaddr* sa) { for (const auto& [id, node] : m_nodes) { if (sa_equal_addr(node->address(), sa)) return node; } return nullptr; } DhtRouter::DhtBucketList::iterator DhtRouter::split_bucket(const DhtBucketList::iterator& itr, DhtNode* node) { // Split bucket. Current bucket keeps the upper half thus keeping the // map key valid, new bucket is the lower half of the original bucket. DhtBucket* newBucket = itr->second->split(id()); // If our bucket has a child now (the new bucket), move ourself into it. if (bucket()->child() != NULL) set_bucket(bucket()->child()); if (!bucket()->is_in_range(id())) throw internal_error("DhtRouter::split_bucket router ID ended up in wrong bucket."); // Insert new bucket with iterator hint = just before current bucket. auto other = m_routingTable.emplace_hint(itr, newBucket->id_range_end(), newBucket); // Check that the bucket we're not adding the node to isn't empty. if (other->second->is_in_range(node->id())) { if (itr->second->empty()) bootstrap_bucket(itr->second); } else { if (other->second->empty()) bootstrap_bucket(other->second); other = itr; } return other; } bool DhtRouter::add_node_to_bucket(DhtNode* node) { auto itr = find_bucket(node->id()); while (itr->second->is_full()) { // Bucket is full. If there are any bad nodes, remove the oldest. DhtBucket::iterator nodeItr = itr->second->find_replacement_candidate(); if (nodeItr == itr->second->end()) throw internal_error("DhtBucket::find_candidate returned no node."); if ((*nodeItr)->is_bad()) { delete_node(m_nodes.find(&(*nodeItr)->id())); } else { // Bucket is full of good nodes; if our own ID falls in // range then split the bucket else discard new node. if (itr->second != bucket()) { delete_node(m_nodes.find(&node->id())); return false; } itr = split_bucket(itr, node); } } itr->second->add_node(node); node->set_bucket(itr->second); return true; } void DhtRouter::delete_node(const DhtNodeList::accessor& itr) { if (itr == m_nodes.end()) throw internal_error("DhtRouter::delete_node called with invalid iterator."); if (itr.node()->bucket() != NULL) itr.node()->bucket()->remove_node(itr.node()); delete itr.node(); m_nodes.erase(itr); } void DhtRouter::bootstrap() { if (!m_contacts.has_value()) return; // Contact up to 8 nodes from the contact list (newest first). for (int count = 0; count < 8 && !m_contacts->empty(); count++) { int port = m_contacts->back().second; // Currently discarding SOCK_DGRAM. auto f = [this, port](const auto& sa, int) { if (sa != nullptr) contact(sa.get(), port); }; this_thread::resolver()->resolve_specific(this, m_contacts->back().first, AF_INET, f); m_contacts->pop_back(); } // Abort unless we already found some nodes for a search. if (m_nodes.empty()) return; bootstrap_bucket(bucket()); // Aggressively ping all questionable nodes in our own bucket to weed // out bad nodes as early as possible and make room for fresh nodes. for (auto node : *bucket()) { if (!node->is_good()) m_server.ping(node->id(), node->address()); } // Also bootstrap a random bucket, if there are others. if (m_routingTable.size() < 2) return; auto itr = m_routingTable.begin(); std::advance(itr, random() % m_routingTable.size()); if (itr->second != bucket() && itr != m_routingTable.end()) bootstrap_bucket(itr->second); } void DhtRouter::bootstrap_bucket(const DhtBucket* bucket) { if (!m_server.is_active()) return; // Do a search for a random ID, or the ID adjacent to our // own when bootstrapping our own bucket. We don't search for // our own exact ID to avoid receiving only our own node info // instead of closest nodes, from nodes that know us already. if (bucket == this->bucket()) { m_contactId = id(); m_contactId[torrent::HashString::size() - 1] ^= 1; } else { bucket->get_random_id(&m_contactId); } m_server.find_node(*bucket, m_contactId); } } // namespace torrent libtorrent-0.16.11/src/dht/dht_node.cc0000644000000000000000000000505615175073411013146 #include "config.h" #include "dht/dht_node.h" #include "torrent/object.h" #include "torrent/net/socket_address.h" #include "torrent/utils/log.h" #include "net/address_list.h" #define LT_LOG_THIS(log_fmt, ...) \ lt_log_print_hash(torrent::LOG_DHT_NODE, this->id(), "dht_node", log_fmt, __VA_ARGS__); namespace torrent { DhtNode::DhtNode(const HashString& id, const sockaddr* sa) : HashString(id), m_socket_address(sa_copy(sa)) { // TODO: Change this to use the id hash similar to how peer info // hash'es are logged. LT_LOG_THIS("created node : %s", sa_pretty_str(sa).c_str()); // if (sa->family() != AF_INET && // (sa->family() != AF_INET6 || !sa->sa_inet6()->is_any())) // throw resource_error("Address not af_inet or in6addr_any"); } DhtNode::DhtNode(const std::string& id, const Object& cache) : HashString(*HashString::cast_from(id.c_str())), m_last_seen(cache.get_key_value("t")) { // TODO: Check how DHT handles inet6. m_socket_address = sa_make_inet_h(cache.get_key_value("i"), cache.get_key_value("p")); LT_LOG_THIS("initializing node : %s", sap_pretty_str(m_socket_address).c_str()); update(); } void DhtNode::set_address(const sockaddr* sa) { m_socket_address = sa_copy(sa); } char* DhtNode::store_compact(char* buffer) const { HashString::cast_from(buffer)->assign(data()); if (m_socket_address->sa_family != AF_INET) throw internal_error("DhtNode::store_compact called with non-inet address."); auto sin = reinterpret_cast(m_socket_address.get()); SocketAddressCompact compact(sin); std::memcpy(buffer + 20, compact.c_str(), 6); return buffer + 26; } Object* DhtNode::store_cache(Object* container) const { if (m_socket_address->sa_family == AF_INET6) { // Currently, all we support is in6addr_any (checked in the constructor), // which is effectively equivalent to this. Note that we need to specify // int64_t explicitly here because a zero constant is special in C++ and // thus we need an explicit match. container->insert_key("i", int64_t{0}); container->insert_key("p", sap_port(m_socket_address)); } else if (m_socket_address->sa_family == AF_INET) { auto sin = reinterpret_cast(m_socket_address.get()); container->insert_key("i", ntohl(sin->sin_addr.s_addr)); container->insert_key("p", ntohs(sin->sin_port)); } else { throw internal_error("DhtNode::store_cache called with non-inet/inet6 address."); } container->insert_key("t", m_last_seen); return container; } } // namespace torrent libtorrent-0.16.11/src/dht/dht_hash_map.h0000644000000000000000000001067015175073411013641 // libTorrent - BitTorrent library // Copyright (C) 2005-2011, Jari Sundell // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // In addition, as a special exception, the copyright holders give // permission to link the code of portions of this program with the // OpenSSL library under certain conditions as described in each // individual source file, and distribute linked combinations // including the two. // // You must obey the GNU General Public License in all respects for // all of the code used other than OpenSSL. If you modify file(s) // with this exception, you may extend this exception to your version // of the file(s), but you are not obligated to do so. If you do not // wish to do so, delete this exception statement from your version. // If you delete this exception statement from all source files in the // program, then also delete it here. // // Contact: Jari Sundell // // Skomakerveien 33 // 3185 Skoppum, NORWAY #ifndef LIBTORRENT_DHT_HASH_MAP_H #define LIBTORRENT_DHT_HASH_MAP_H #include "config.h" #include #include "dht_node.h" #include "dht_tracker.h" #include "torrent/hash_string.h" namespace torrent { // Hash functions for HashString keys, and dereferencing HashString pointers. // Since the first few bits are very similar if not identical (since the IDs // will be close to our own node ID), we use an offset of 64 bits in the hash // string. These bits will be uniformly distributed until the number of DHT // nodes on the planet approaches 2^64 which is... unlikely. // An offset of 64 bits provides 96 significant bits which is fine as long as // the size of size_t does not exceed 12 bytes, while still having correctly // aligned 64-bit access. static constexpr unsigned int hashstring_hash_ofs = 8; struct hashstring_ptr_hash { size_t operator () (const HashString* n) const { #if USE_ALIGNED size_t result = 0; const char *first = n->data() + hashstring_hash_ofs; const char *last = first + sizeof(size_t); while (first != last) result = (result << 8) + *first++; return result; #else return *reinterpret_cast(n->data() + hashstring_hash_ofs); #endif } }; struct hashstring_hash { size_t operator () (const HashString& n) const { #if USE_ALIGNED size_t result = 0; const char *first = n.data() + hashstring_hash_ofs; const char *last = first + sizeof(size_t); while (first != last) result = (result << 8) + *first++; return result; #else return *reinterpret_cast(n.data() + hashstring_hash_ofs); #endif } }; // Compare HashString pointers by dereferencing them. struct hashstring_ptr_equal { size_t operator () (const HashString* one, const HashString* two) const { return *one == *two; } }; class DhtNodeList : public std::unordered_map { public: using base_type = std::unordered_map; // Define accessor iterator with more convenient access to the key and // element values. Allows changing the map definition more easily if needed. template struct accessor_wrapper : public T { accessor_wrapper(const T& itr) : T(itr) { } const HashString& id() const { return *(**this).first; } DhtNode* node() const { return (**this).second; } }; using const_accessor = accessor_wrapper; using accessor = accessor_wrapper; DhtNode* add_node(DhtNode* n); }; using DhtTrackerList = std::unordered_map; inline DhtNode* DhtNodeList::add_node(DhtNode* n) { emplace(reinterpret_cast(n), n); return n; } } // namespace torrent #endif libtorrent-0.16.11/src/dht/dht_router.h0000644000000000000000000001346615175073411013407 #ifndef LIBTORRENT_DHT_DHT_ROUTER_H #define LIBTORRENT_DHT_DHT_ROUTER_H #include "dht/dht_node.h" #include "dht/dht_hash_map.h" #include "dht/dht_server.h" #include "torrent/hash_string.h" #include "torrent/object.h" #include "torrent/net/types.h" #include "torrent/tracker/dht_controller.h" #include "torrent/utils/scheduler.h" #include namespace torrent { class DhtBucket; class DhtTracker; class TrackerDht; // Main DHT class, maintains the routing table of known nodes and talks to the // DhtServer object that handles the actual communication. class DhtRouter : public DhtNode { public: // How many bytes to return and verify from the 20-byte SHA token. static constexpr unsigned int size_token = 8; static constexpr unsigned int timeout_bootstrap_retry = 60; // Retry initial bootstrapping every minute. static constexpr unsigned int timeout_update = 15 * 60; // Regular housekeeping updates every 15 minutes. static constexpr unsigned int timeout_bucket_bootstrap = 15 * 60; // Bootstrap idle buckets after 15 minutes. static constexpr unsigned int timeout_remove_node = 4 * 60 * 60; // Remove unresponsive nodes after 4 hours. static constexpr unsigned int timeout_peer_announce = 30 * 60; // Remove peers which haven't reannounced for 30 minutes. // A node ID of all zero. static HashString zero_id; DhtRouter(const Object& cache); ~DhtRouter(); void start(int port); void stop(); bool is_active() { return m_server.is_active(); } // Pass NULL to cancel_announce to cancel all announces for the tracker. void announce(const HashString& info_hash, TrackerDht* tracker); void cancel_announce(const HashString* info_hash, const TrackerDht* tracker); // Returns NULL if not tracking the torrent unless create is true. DhtTracker* get_tracker(const HashString& hash, bool create); // Check if we are interested in inserting a new node of the given ID // into our table (i.e. if we have space or bad nodes in the corresponding bucket). bool want_node(const HashString& id); // Add the given host to the list of potential contacts if we haven't // completed the bootstrap process, or contact the given address directly. // TODO: Remoce add_contact.... And make it check that sa is inet. void add_bootstrap_contact(const std::string& host, int port); void contact(const sockaddr* sa, int port); // Retrieve node of given ID in constant time. Return NULL if not found, unless // it's our own ID in which case it returns the DhtRouter object. DhtNode* get_node(const HashString& id); // Search for node with given address in O(n), disregarding the port. DhtNode* find_node(const sockaddr* sa); // Whenever a node queries us, replies, or is confirmed inactive (no reply) or // invalid (reply with wrong ID), we need to update its status. DhtNode* node_queried(const HashString& id, const sockaddr* sa); DhtNode* node_replied(const HashString& id, const sockaddr* sa); DhtNode* node_inactive(const HashString& id, const sockaddr* sa); void node_invalid(const HashString& id); // Store compact node information (26 bytes) for nodes closest to the // given ID in the given buffer, return new buffer end. raw_string get_closest_nodes(const HashString& id) { return find_bucket(id)->second->full_bucket(); } // Store DHT cache in the given container. Object* store_cache(Object* container) const; // Create and verify a token. Tokens are valid between 15-30 minutes from creation. raw_string make_token(const sockaddr* sa, char* buffer) const; bool token_valid(raw_string token, const sockaddr* sa) const; tracker::DhtController::statistics_type get_statistics() const; void reset_statistics() { m_server.reset_statistics(); } private: // Hostname and port of potential bootstrap nodes. using contact_t = std::pair; // Number of nodes we need to consider the bootstrap process complete. static constexpr unsigned int num_bootstrap_complete = 32; // Maximum number of potential contacts to keep until bootstrap complete. static constexpr unsigned int num_bootstrap_contacts = 64; using DhtBucketList = std::map; DhtBucketList::iterator find_bucket(const HashString& id); bool add_node_to_bucket(DhtNode* node); void delete_node(const DhtNodeList::accessor& itr); void store_closest_nodes(const HashString& id, DhtBucket* bucket); DhtBucketList::iterator split_bucket(const DhtBucketList::iterator& itr, DhtNode* node); void bootstrap(); void bootstrap_bucket(const DhtBucket* bucket); void receive_timeout(); void receive_timeout_bootstrap(); // buffer needs to hold an SHA1 hash (20 bytes), not just the token (8 bytes) static char* generate_token(const sockaddr* sa, int token, char buffer[20]); utils::SchedulerEntry m_task_timeout; DhtServer m_server{nullptr}; DhtNodeList m_nodes; DhtBucketList m_routingTable; DhtTrackerList m_trackers; HashString m_contactId; std::optional> m_contacts; int m_numRefresh{0}; bool m_networkUp; // Secret keys used for generating announce tokens. int m_curToken; int m_prevToken; }; inline raw_string DhtRouter::make_token(const sockaddr* sa, char* buffer) const { return raw_string(generate_token(sa, m_curToken, buffer), size_token); } } // namespace torrent #endif libtorrent-0.16.11/src/dht/dht_transaction.h0000644000000000000000000001767315175073411014420 #ifndef LIBTORRENT_DHT_TRANSACTION_H #define LIBTORRENT_DHT_TRANSACTION_H #include #include #include "dht/dht_node.h" #include "dht/transactions/dht_search.h" #include "torrent/hash_string.h" #include "torrent/object_static_map.h" #include "torrent/net/types.h" #include "tracker/tracker_dht.h" namespace torrent::dht { class DhtSearch; } namespace torrent { class TrackerDht; class DhtBucket; class DhtTransactionSearch; class DhtTransaction; class DhtTransactionPing; class DhtTransactionFindNode; class DhtTransactionFindNodeAnnounce; class DhtTransactionGetPeers; class DhtTransactionAnnouncePeer; // Possible bencode keys in a DHT message. enum dht_keys { key_a_id, key_a_infoHash, key_a_port, key_a_target, key_a_token, key_e_0, key_e_1, key_q, key_r_id, key_r_nodes, key_r_token, key_r_values, key_t, key_v, key_y, key_LAST, }; class DhtMessage : public static_map_type { public: using base_type = static_map_type; // Must be big enough to hold one of the possible variable-sized reply data. // Currently either: // - error message (size doesn't really matter, it'll be truncated at worst) // - announce token (8 bytes, needs 20 bytes buffer to build) // Never more than one of the above. // And additionally for queries we send: // - transaction ID (3 bytes) static constexpr size_t data_size = 64; char data[data_size]; char* data_end{data}; }; // Class holding transaction data to be transmitted. class DhtTransactionPacket { public: // transaction packet DhtTransactionPacket(const sockaddr* s, const DhtMessage& d, unsigned int id, std::shared_ptr t); // non-transaction packet DhtTransactionPacket(const sockaddr* s, const DhtMessage& d); ~DhtTransactionPacket() = default; bool has_transaction() const { return m_id >= -1; } bool has_failed() const { return m_id == -1; } void set_failed() { m_id = -1; } const auto* address() const { return m_socket_address.get(); } auto* address() { return m_socket_address.get(); } const char* c_str() const { return m_data.get(); } size_t length() const { return m_length; } int id() const { return m_id; } int age() const { return has_transaction() ? 0 : this_thread::cached_seconds().count() + m_id; } const auto* transaction() const { return m_transaction.get(); } auto* transaction() { return m_transaction.get(); } private: DhtTransactionPacket(const DhtTransactionPacket&) = delete; DhtTransactionPacket& operator=(const DhtTransactionPacket&) = delete; void build_buffer(const DhtMessage& data); sa_unique_ptr m_socket_address; std::unique_ptr m_data; size_t m_length{}; int m_id{}; std::shared_ptr m_transaction; }; // DHT Transaction classes. DhtTransaction and DhtTransactionSearch // are not directly usable with no public constructor, since type() // is a pure virtual function. class DhtTransaction { public: virtual ~DhtTransaction(); enum transaction_type { DHT_PING, DHT_FIND_NODE, DHT_GET_PEERS, DHT_ANNOUNCE_PEER, }; // Key to uniquely identify a transaction with given per-node transaction id. using key_type = uint64_t; virtual transaction_type type() const = 0; virtual bool is_search() { return false; } key_type key(int id) const { return key(m_socket_address.get(), id); } static key_type key(const sockaddr* sa, int id); static bool key_match(key_type key, const sockaddr* sa); const HashString& id() { return m_id; } const auto* address() { return m_socket_address.get(); } int timeout() const { return m_timeout; } int quick_timeout() const { return m_quickTimeout; } bool has_quick_timeout() const { return m_hasQuickTimeout; } auto& packet() const { return m_packet; } void set_packet(std::shared_ptr& p) { m_packet = p; } void reset_packet() { m_packet.reset(); } DhtTransactionSearch* as_search(); DhtTransactionPing* as_ping(); DhtTransactionFindNode* as_find_node(); DhtTransactionGetPeers* as_get_peers(); DhtTransactionAnnouncePeer* as_announce_peer(); protected: DhtTransaction(int quick_timeout, int timeout, const HashString& id, const sockaddr* sa); // m_id must be the first element to ensure it is aligned properly, // because we later read a size_t value from it. const HashString m_id; bool m_hasQuickTimeout; private: DhtTransaction(const DhtTransaction&) = delete; DhtTransaction& operator=(const DhtTransaction&) = delete; sa_unique_ptr m_socket_address; int m_timeout; int m_quickTimeout; std::shared_ptr m_packet; }; class DhtTransactionSearch : public DhtTransaction { public: ~DhtTransactionSearch() override; bool is_search() override { return true; } auto node() { return m_node; } auto& search() { return m_search; } void set_stalled(); void complete(bool success); protected: DhtTransactionSearch(int quick_timeout, int timeout, dht::DhtSearch::const_accessor& node); private: dht::DhtSearch::const_accessor m_node; std::shared_ptr m_search; }; // Actual transaction classes. class DhtTransactionPing : public DhtTransaction { public: DhtTransactionPing(const HashString& id, const sockaddr* sa) : DhtTransaction(-1, 30, id, sa) { } transaction_type type() const override; }; class DhtTransactionFindNode : public DhtTransactionSearch { public: DhtTransactionFindNode(dht::DhtSearch::const_accessor& node) : DhtTransactionSearch(4, 30, node) { } transaction_type type() const override; }; class DhtTransactionGetPeers : public DhtTransactionSearch { public: DhtTransactionGetPeers(dht::DhtSearch::const_accessor& node) : DhtTransactionSearch(-1, 30, node) { } transaction_type type() const override; }; class DhtTransactionAnnouncePeer : public DhtTransaction { public: DhtTransactionAnnouncePeer(const HashString& id, const sockaddr* sa, const HashString& infoHash, raw_string token) : DhtTransaction(-1, 30, id, sa), m_infoHash(infoHash), m_token(token) { } transaction_type type() const override; const HashString& info_hash() { return m_infoHash; } raw_string info_hash_raw_string() const { return raw_string(m_infoHash.data(), HashString::size_data); } raw_string token() { return m_token; } private: HashString m_infoHash; raw_string m_token; }; // These could (should?) check that the type matches, or use dynamic_cast if we have RTTI. inline DhtTransactionSearch* DhtTransaction::as_search() { return static_cast(this); } inline DhtTransactionPing* DhtTransaction::as_ping() { return static_cast(this); } inline DhtTransactionFindNode* DhtTransaction::as_find_node() { return static_cast(this); } inline DhtTransactionGetPeers* DhtTransaction::as_get_peers() { return static_cast(this); } inline DhtTransactionAnnouncePeer* DhtTransaction::as_announce_peer() { return static_cast(this); } } // namespace torrent #endif libtorrent-0.16.11/src/dht/dht_node.h0000644000000000000000000000647015175073411013011 #ifndef LIBTORRENT_DHT_NODE_H #define LIBTORRENT_DHT_NODE_H #include "dht/dht_bucket.h" #include "torrent/hash_string.h" #include "torrent/object_raw_bencode.h" #include "torrent/net/types.h" namespace torrent::dht { class DhtSearch; } namespace torrent { class DhtBucket; class DhtNode : public HashString { public: // A node is considered bad if it failed to reply to this many queries. static constexpr unsigned int max_failed_replies = 5; DhtNode(const HashString& id, const sockaddr* sa); DhtNode(const std::string& id, const Object& cache); ~DhtNode() = default; const HashString& id() const { return *this; } raw_string id_raw_string() const { return raw_string(data(), size_data); } const sockaddr* address() const { return m_socket_address.get(); } void set_address(const sockaddr* sa); // For determining node quality. unsigned int last_seen() const { return m_last_seen; } unsigned int age() const { return this_thread::cached_seconds().count() - m_last_seen; } bool is_good() const { return m_recently_active; } bool is_questionable() const { return !m_recently_active; } bool is_bad() const { return m_recently_inactive >= max_failed_replies; } bool is_active() const { return m_last_seen; } // Update is called once every 15 minutes. void update() { m_recently_active = age() < 15 * 60; } // Called when node replies to us, queries us, or fails to reply. void replied() { set_good(); } void queried() { if (m_last_seen) set_good(); } void inactive(); DhtBucket* bucket() const { return m_bucket; } DhtBucket* set_bucket(DhtBucket* b) { m_bucket = b; return b; } bool is_in_range(const DhtBucket* b) { return b->is_in_range(*this); } // Store compact node information (26 bytes address, port and ID) in the given // buffer and return pointer to end of stored information. char* store_compact(char* buffer) const; // Store node cache in the given container object and return it. Object* store_cache(Object* container) const; protected: DhtNode(const DhtNode&) = delete; DhtNode& operator=(const DhtNode&) = delete; friend class dht::DhtSearch; void set_good(); void set_bad(); private: sa_unique_ptr m_socket_address; unsigned int m_last_seen{}; bool m_recently_active{}; unsigned int m_recently_inactive{}; DhtBucket* m_bucket{}; }; inline void DhtNode::set_good() { if (m_bucket != NULL && !is_good()) m_bucket->node_now_good(is_bad()); m_last_seen = this_thread::cached_seconds().count(); m_recently_inactive = 0; m_recently_active = true; } inline void DhtNode::set_bad() { if (m_bucket != NULL && !is_bad()) m_bucket->node_now_bad(is_good()); m_recently_inactive = max_failed_replies; m_recently_active = false; } inline void DhtNode::inactive() { if (m_recently_inactive + 1 == max_failed_replies) set_bad(); else m_recently_inactive++; } } // namespace torrent #endif libtorrent-0.16.11/src/dht/dht_transaction.cc0000644000000000000000000001001615175073411014536 #include "config.h" #include "dht/dht_transaction.h" #include #include "dht/dht_bucket.h" #include "dht/dht_server.h" #include "torrent/exceptions.h" #include "torrent/object_stream.h" #include "torrent/net/socket_address.h" #include "tracker/tracker_dht.h" namespace torrent { template<> const DhtMessage::key_list_type DhtMessage::base_type::keys; // // DhtTransactionPacket: // DhtTransactionPacket::DhtTransactionPacket(const sockaddr* s, const DhtMessage& d, unsigned int id, std::shared_ptr t) : m_socket_address(sa_copy(s)), m_id(id), m_transaction(std::move(t)) { build_buffer(d); } DhtTransactionPacket::DhtTransactionPacket(const sockaddr* s, const DhtMessage& d) : m_socket_address(sa_copy(s)), m_id(-this_thread::cached_seconds().count()) { build_buffer(d); } void DhtTransactionPacket::build_buffer(const DhtMessage& msg) { char buffer[1500]; // If the message would exceed an Ethernet frame, something went very wrong. object_buffer_t result = static_map_write_bencode_c(object_write_to_buffer, NULL, std::make_pair(buffer, buffer + sizeof(buffer)), msg); m_length = result.second - buffer; m_data = std::make_unique(m_length); memcpy(m_data.get(), buffer, m_length); } DhtTransaction::DhtTransaction(int quick_timeout, int timeout, const HashString& id, const sockaddr* sa) : m_id(id), m_hasQuickTimeout(quick_timeout > 0), m_socket_address(sa_copy(sa)), m_timeout(this_thread::cached_seconds().count() + timeout), m_quickTimeout(this_thread::cached_seconds().count() + quick_timeout) { } DhtTransaction::~DhtTransaction() { if (m_packet != NULL) m_packet->set_failed(); } DhtTransaction::key_type DhtTransaction::key(const sockaddr* sa, int id) { if (sa_is_inet(sa)) return (static_cast(reinterpret_cast(sa)->sin_addr.s_addr) << 32) + id; else if (sa_is_inet6(sa)) throw internal_error("DhtTransaction::key() called with inet6 address."); else throw internal_error("DhtTransaction::key() called with non-inet address."); } bool DhtTransaction::key_match(key_type key, const sockaddr* sa) { if (sa_is_inet(sa)) return (key >> 32) == static_cast(reinterpret_cast(sa)->sin_addr.s_addr); else if (sa_is_inet6(sa)) throw internal_error("DhtTransaction::key_match() called with inet6 address."); else throw internal_error("DhtTransaction::key_match() called with non-inet address."); } // // DhtTransactionSearch: // DhtTransactionSearch::DhtTransactionSearch(int quick_timeout, int timeout, dht::DhtSearch::const_accessor& node) : DhtTransaction(quick_timeout, timeout, node.node()->id(), node.node()->address()), m_node(node), m_search(node.search()) { if (!m_hasQuickTimeout) m_search->m_concurrency++; } DhtTransactionSearch::~DhtTransactionSearch() { if (m_node != m_search->end()) complete(false); m_search->server()->check_search_completed(std::move(m_search)); } void DhtTransactionSearch::set_stalled() { if (!m_hasQuickTimeout) throw internal_error("DhtTransactionSearch::set_stalled() called on already stalled transaction."); m_hasQuickTimeout = false; m_search->m_concurrency++; } void DhtTransactionSearch::complete(bool success) { if (m_node == m_search->end()) throw internal_error("DhtTransactionSearch::complete() called multiple times."); if (m_node.search() != m_search) throw internal_error("DhtTransactionSearch::complete() called for node from wrong search."); if (!m_hasQuickTimeout) m_search->m_concurrency--; m_search->node_status(m_node.node(), success); m_node = m_search->end(); } DhtTransaction::transaction_type DhtTransactionPing::type() const { return DHT_PING; } DhtTransaction::transaction_type DhtTransactionFindNode::type() const { return DHT_FIND_NODE; } DhtTransaction::transaction_type DhtTransactionGetPeers::type() const { return DHT_GET_PEERS; } DhtTransaction::transaction_type DhtTransactionAnnouncePeer::type() const { return DHT_ANNOUNCE_PEER; } } // namespace torrent libtorrent-0.16.11/src/dht/dht_server.cc0000644000000000000000000007372315175073411013535 #include "config.h" #include "dht/dht_server.h" #include #include #include "manager.h" #include "dht/dht_bucket.h" #include "dht/dht_router.h" #include "dht/dht_transaction.h" #include "dht/transactions/dht_announce.h" #include "torrent/connection_manager.h" #include "torrent/exceptions.h" #include "torrent/object.h" #include "torrent/object_static_map.h" #include "torrent/object_stream.h" #include "torrent/net/fd.h" #include "torrent/net/poll.h" #include "torrent/net/socket_address.h" #include "torrent/net/network_config.h" #include "torrent/runtime/network_manager.h" #include "torrent/runtime/socket_manager.h" #include "torrent/utils/log.h" #include "tracker/tracker_dht.h" #define LT_LOG_THIS(log_fmt, ...) \ lt_log_print_subsystem(torrent::LOG_DHT_SERVER, "dht_server", log_fmt, __VA_ARGS__); namespace { // Error in DHT protocol, avoids std::string ctor from communication_error class dht_error : public torrent::network_error { public: dht_error(int code, const char* message) : m_message(message), m_code(code) {} int code() const noexcept { return m_code; } const char* what() const noexcept override { return m_message; } private: const char* m_message; int m_code; }; } // namespace namespace torrent { // List of all possible keys we need/support in a DHT message. // Unsupported keys we receive are dropped (ignored) while decoding. // See torrent/object_static_map.h for how this works. template <> const DhtMessage::key_list_type DhtMessage::base_type::keys = { { key_a_id, "a::id*S" }, { key_a_infoHash, "a::info_hash*S" }, { key_a_port, "a::port", }, { key_a_target, "a::target*S" }, { key_a_token, "a::token*S" }, { key_e_0, "e[]*" }, { key_e_1, "e[]*" }, { key_q, "q*S" }, { key_r_id, "r::id*S" }, { key_r_nodes, "r::nodes*S" }, { key_r_token, "r::token*S" }, { key_r_values, "r::values*L" }, { key_t, "t*S" }, { key_v, "v*" }, { key_y, "y*S" }, }; DhtServer::DhtServer(DhtRouter* router) : m_router(router) { m_fileDesc = -1; reset_statistics(); // Reserve a socket for the DHT server, even though we don't // actually open it until the server is started, which may not // happen until the first non-private torrent is started. manager->connection_manager()->inc_socket_count(); m_task_timeout.slot() = [this] { receive_timeout(); }; } DhtServer::~DhtServer() { stop(); manager->connection_manager()->dec_socket_count(); } void DhtServer::start(int port) { auto [bind_inet_address, bind_inet6_address] = config::network_config()->bind_addresses_or_null(); if (bind_inet_address == nullptr) throw resource_error("no valid bind address for DHT server"); sa_unique_ptr bind_address; switch (bind_inet_address->sa_family) { case AF_INET: bind_address = sa_copy(bind_inet_address.get()); break; case AF_UNSPEC: bind_address = sa_make_inet_any(); break; default: throw resource_error("invalid address family for DHT server"); } m_router->set_address(bind_inet_address.get()); sap_set_port(bind_address, port); LT_LOG_THIS("starting server : %s", sap_pretty_str(bind_address).c_str()); fd_flags open_flags = fd_flag_datagram | fd_flag_nonblock | fd_flag_reuse_address; if (bind_address->sa_family == AF_INET) open_flags |= fd_flag_v4; // TODO: This throws internal_error on failure. runtime::socket_manager()->open_event_or_throw(this, [&]() { int fd = fd_open(open_flags); if (fd == -1) { LT_LOG_THIS("could not open datagram socket : %s", std::strerror(errno)); throw resource_error("could not open datagram socket : " + std::string(strerror(errno))); } // Figure out how to bind to both inet and inet6. if (!fd_bind(fd, bind_address.get())) { LT_LOG_THIS("could not bind datagram socket : %s", std::strerror(errno)); fd_close(fd); throw resource_error("could not bind datagram socket : " + std::string(strerror(errno))); } set_file_descriptor(fd); this_thread::poll()->open(this); this_thread::poll()->insert_read(this); this_thread::poll()->insert_error(this); return file_descriptor(); }); } void DhtServer::stop() { if (!is_active()) return; LT_LOG_THIS("stopping", 0); LT_LOG_THIS("searches : count:%zu", m_searches.size()); clear_transactions(); this_thread::scheduler()->erase(&m_task_timeout); runtime::socket_manager()->close_event_or_throw(this, [this]() { this_thread::poll()->remove_and_close(this); fd_close(file_descriptor()); set_file_descriptor(-1); }); m_networkUp = false; } void DhtServer::reset_statistics() { m_queriesReceived = 0; m_queriesSent = 0; m_repliesReceived = 0; m_errorsReceived = 0; m_errorsCaught = 0; } // Ping a node whose ID we know. void DhtServer::ping(const HashString& id, const sockaddr* sa) { // No point pinging a node that we're already contacting otherwise. auto itr = m_transactions.lower_bound(DhtTransaction::key(sa, 0)); if (itr == m_transactions.end() || !DhtTransaction::key_match(itr->first, sa)) add_transaction(std::unique_ptr(new DhtTransactionPing(id, sa)), packet_prio_low); } // Contact nodes in given bucket and ask for their nodes closest to target. void DhtServer::find_node(const DhtBucket& contacts, const HashString& target) { auto search = std::make_shared(this, target); search->add_contacts(contacts); auto n = search->get_contact(); while (n != search->end()) { add_transaction(std::unique_ptr(new DhtTransactionFindNode(n)), packet_prio_low); n = search->get_contact(); } // This shouldn't happen, it means we had no contactable nodes at all. if (!search->start()) return; // throw internal_error("DhtServer::find_node search start failed, no contactable nodes."); ///////////////// TMP m_searches.insert(search); } void DhtServer::announce(const DhtBucket& contacts, const HashString& infoHash, TrackerDht* tracker) { auto announce = std::make_shared(this, infoHash, tracker); announce->add_contacts(contacts); auto n = announce->get_contact(); while (n != announce->end()) { add_transaction(std::unique_ptr(new DhtTransactionFindNode(n)), packet_prio_high); n = announce->get_contact(); } // This can only happen if all nodes we know are bad. if (!announce->start()) return; // throw internal_error("DhtServer::announce search start failed, no contactable nodes."); ///////////////// TMP m_searches.insert(announce); announce->update_status(); } void DhtServer::cancel_announce(const HashString* info_hash, const TrackerDht* tracker) { auto itr = m_transactions.begin(); // TODO: Verify this removes us from m_searches. while (itr != m_transactions.end()) { if (itr->second->is_search() && itr->second->as_search()->search()->is_announce()) { auto announce = dynamic_cast(itr->second->as_search()->search().get()); if (announce == nullptr) throw internal_error("DhtServer::cancel_announce dynamic_cast to DhtAnnounce failed."); if ((info_hash == nullptr || announce->target() == *info_hash) && (tracker == nullptr || announce->tracker() == tracker)) { drop_packet(itr->second->packet().get()); m_transactions.erase(itr++); continue; } } ++itr; } } void DhtServer::update() { // Reset this every 15 minutes. It'll get set back to true if we receive // any valid packets. This allows detecting when the entire network goes // down, and prevents all nodes from getting removed as unresponsive. m_networkUp = false; } void DhtServer::check_search_completed(std::shared_ptr search) { if (!search->complete()) return; // Removing search if has completed. auto itr = m_searches.find(search); if (itr == m_searches.end()) return; // throw internal_error("DhtServer::mark_search_completed search not found."); // TODO: Verify we got ref_count == 2. m_searches.erase(itr); } void DhtServer::check_search_trimming(std::shared_ptr search) { // Make sure trimming search does not delete searches that have not completed. if (search->complete()) return; // TODO: Should we erase if complete? auto itr = m_searches.lower_bound(search); if (itr != m_searches.end() && *itr == search) return; m_searches.insert(itr, search); } void DhtServer::process_query(const HashString& id, const sockaddr* sa, const DhtMessage& msg) { m_queriesReceived++; m_networkUp = true; raw_string query = msg[key_q].as_raw_string(); // Construct reply. DhtMessage reply; if (query == raw_string::from_c_str("find_node")) create_find_node_response(msg, reply); else if (query == raw_string::from_c_str("get_peers")) create_get_peers_response(msg, sa, reply); else if (query == raw_string::from_c_str("announce_peer")) create_announce_peer_response(msg, sa, reply); else if (query != raw_string::from_c_str("ping")) throw dht_error(dht_error_bad_method, "Unknown query type."); m_router->node_queried(id, sa); create_response(msg, sa, reply); } void DhtServer::create_find_node_response(const DhtMessage& req, DhtMessage& reply) { raw_string target = req[key_a_target].as_raw_string(); if (target.size() < HashString::size_data) throw dht_error(dht_error_protocol, "target string too short"); reply[key_r_nodes] = m_router->get_closest_nodes(*HashString::cast_from(target.data())); if (reply[key_r_nodes].as_raw_string().empty()) throw dht_error(dht_error_generic, "No nodes"); } void DhtServer::create_get_peers_response(const DhtMessage& req, const sockaddr* sa, DhtMessage& reply) { reply[key_r_token] = m_router->make_token(sa, reply.data_end); reply.data_end += reply[key_r_token].as_raw_string().size(); raw_string info_hash_str = req[key_a_infoHash].as_raw_string(); if (info_hash_str.size() < HashString::size_data) throw dht_error(dht_error_protocol, "info hash too short"); const HashString* info_hash = HashString::cast_from(info_hash_str.data()); DhtTracker* tracker = m_router->get_tracker(*info_hash, false); // If we're not tracking or have no peers, send closest nodes. if (!tracker || tracker->empty()) { raw_string nodes = m_router->get_closest_nodes(*info_hash); if (nodes.empty()) throw dht_error(dht_error_generic, "No peers nor nodes"); reply[key_r_nodes] = nodes; } else { reply[key_r_values] = tracker->get_peers(); } } void DhtServer::create_announce_peer_response(const DhtMessage& req, const sockaddr* sa, [[maybe_unused]] DhtMessage& reply) { raw_string info_hash = req[key_a_infoHash].as_raw_string(); if (info_hash.size() < HashString::size_data) throw dht_error(dht_error_protocol, "info hash too short"); if (!m_router->token_valid(req[key_a_token].as_raw_string(), sa)) throw dht_error(dht_error_protocol, "Token invalid."); if (!sa_is_inet(sa)) throw internal_error("DhtServer::create_announce_peer_response called with non-inet address."); DhtTracker* tracker = m_router->get_tracker(*HashString::cast_from(info_hash.data()), true); tracker->add_peer(reinterpret_cast(sa)->sin_addr.s_addr, req[key_a_port].as_value()); } void DhtServer::process_response(const HashString& id, const sockaddr* sa, const DhtMessage& response) { int transactionId = static_cast(response[key_t].as_raw_string().data()[0]); auto itr = m_transactions.find(DhtTransaction::key(sa, transactionId)); // Response to a transaction we don't have in our table. At this point it's // impossible to tell whether it used to be a valid transaction but timed out // the node did not return the ID we sent it, or it returned it with a // different address than we sent it o. Best we can do is ignore the reply, // since the protocol doesn't call for returning errors in responses. if (itr == m_transactions.end()) return; m_repliesReceived++; m_networkUp = true; // Make sure transaction is erased even if an exception is thrown. try { auto& transaction = itr->second; #ifdef USE_EXTRA_DEBUG if (DhtTransaction::key(sa, transactionId) != transaction->key(transactionId)) throw internal_error("DhtServer::process_response key mismatch."); #endif // If we contact a node but its ID is not the one we expect, ignore the reply // to prevent interference from rogue nodes. if ((id != transaction->id() && transaction->id() != torrent::DhtRouter::zero_id)) return; switch (transaction->type()) { case DhtTransaction::DHT_FIND_NODE: parse_find_node_reply(transaction->as_find_node(), response[key_r_nodes].as_raw_string()); break; case DhtTransaction::DHT_GET_PEERS: parse_get_peers_reply(transaction->as_get_peers(), response); break; // Nothing to do for DHT_PING and DHT_ANNOUNCE_PEER default: break; } // Mark node responsive only if all processing was successful, without errors. m_router->node_replied(id, sa); } catch (const std::exception&) { drop_packet(itr->second->packet().get()); m_transactions.erase(itr); m_errorsCaught++; throw; } drop_packet(itr->second->packet().get()); m_transactions.erase(itr); } void DhtServer::process_error(const sockaddr* sa, const DhtMessage& error) { int transactionId = static_cast(error[key_t].as_raw_string().data()[0]); auto itr = m_transactions.find(DhtTransaction::key(sa, transactionId)); if (itr == m_transactions.end()) return; m_repliesReceived++; m_errorsReceived++; m_networkUp = true; // Don't mark node as good (because it replied) or bad (because it returned an error). // If it consistently returns errors for valid queries it's probably broken. But a // few error messages are acceptable. So we do nothing and pretend the query never happened. drop_packet(itr->second->packet().get()); m_transactions.erase(itr); } void DhtServer::parse_find_node_reply(DhtTransactionSearch* transaction, raw_string nodes) { transaction->complete(true); if (sizeof(const compact_node_info) != 26) throw internal_error("DhtServer::parse_find_node_reply(...) bad struct size."); node_info_list list; std::copy(reinterpret_cast(nodes.data()), reinterpret_cast(nodes.data() + nodes.size() - nodes.size() % sizeof(compact_node_info)), std::back_inserter(list)); for (auto& node : list) { if (node.id() != m_router->id()) transaction->search()->add_contact(node.id(), sa_make_inet_n(node._addr.addr, node._addr.port).get()); } find_node_next(transaction); } void DhtServer::parse_get_peers_reply(DhtTransactionGetPeers* transaction, const DhtMessage& response) { auto announce = dynamic_cast(transaction->as_search()->search().get()); if (announce == nullptr) throw internal_error("DhtServer::parse_get_peers_reply dynamic_cast to DhtAnnounce failed."); transaction->complete(true); if (response[key_r_values].is_raw_list()) announce->receive_peers(response[key_r_values].as_raw_list()); if (response[key_r_token].is_raw_string()) add_transaction(std::unique_ptr(new DhtTransactionAnnouncePeer(transaction->id(), transaction->address(), announce->target(), response[key_r_token].as_raw_string())), packet_prio_low); announce->update_status(); } void DhtServer::find_node_next(DhtTransactionSearch* transaction) { int priority = packet_prio_low; if (transaction->search()->is_announce()) priority = packet_prio_high; auto node = transaction->search()->get_contact(); while (node != transaction->search()->end()) { add_transaction(std::unique_ptr(new DhtTransactionFindNode(node)), priority); node = transaction->search()->get_contact(); } if (!transaction->search()->is_announce()) return; auto announce = dynamic_cast(transaction->search().get()); if (announce == nullptr) throw internal_error("DhtServer::find_node_next dynamic_cast to DhtAnnounce failed."); if (announce->complete()) { // We have found the 8 closest nodes to the info hash. Retrieve peers // from them and announce to them. for (node = announce->start_announce(); node != announce->end(); ++node) add_transaction(std::unique_ptr(new DhtTransactionGetPeers(node)), packet_prio_high); } announce->update_status(); } void DhtServer::add_packet(std::shared_ptr packet, int priority) { switch (priority) { // High priority packets are for important queries, and quite small. // They're added to front of high priority queue and thus will be the // next packets sent. case packet_prio_high: m_highQueue.push_front(std::move(packet)); break; // Low priority query packets are added to the back of the high priority // queue and will be sent when all high priority packets have been transmitted. case packet_prio_low: m_highQueue.push_back(std::move(packet)); break; // Reply packets will be processed after all of our own packets have been send. case packet_prio_reply: m_lowQueue.push_back(std::move(packet)); break; default: throw internal_error("DhtServer::add_packet called with invalid priority."); } } void DhtServer::drop_packet(const DhtTransactionPacket* packet) { m_highQueue.erase(std::remove_if(m_highQueue.begin(), m_highQueue.end(), [packet](auto& p) { return p.get() == packet; }), m_highQueue.end()); m_lowQueue.erase(std::remove_if(m_lowQueue.begin(), m_lowQueue.end(), [packet](auto& p) { return p.get() == packet; }), m_lowQueue.end()); if (m_highQueue.empty() && m_lowQueue.empty()) this_thread::poll()->remove_write(this); } void DhtServer::create_query(transaction_itr itr, int tID, [[maybe_unused]] const sockaddr* sa, int priority) { if (itr->second->id() == m_router->id()) throw internal_error("DhtServer::create_query trying to send to itself."); DhtMessage query; // Transaction ID is a bencode string. query[key_t] = raw_bencode(query.data_end, 3); *query.data_end++ = '1'; *query.data_end++ = ':'; *query.data_end++ = tID; auto& transaction = itr->second; query[key_q] = raw_string::from_c_str(queries[transaction->type()]); query[key_y] = raw_bencode::from_c_str("1:q"); query[key_v] = raw_bencode("4:" PEER_VERSION, 6); query[key_a_id] = m_router->id_raw_string(); switch (transaction->type()) { case DhtTransaction::DHT_PING: // nothing to do break; case DhtTransaction::DHT_FIND_NODE: query[key_a_target] = transaction->as_find_node()->search()->target_raw_string(); break; case DhtTransaction::DHT_GET_PEERS: query[key_a_infoHash] = transaction->as_get_peers()->search()->target_raw_string(); break; case DhtTransaction::DHT_ANNOUNCE_PEER: query[key_a_infoHash] = transaction->as_announce_peer()->info_hash_raw_string(); query[key_a_token] = transaction->as_announce_peer()->token(); query[key_a_port] = runtime::listen_port(); break; } auto packet = std::make_shared(transaction->address(), query, tID, transaction); transaction->set_packet(packet); add_packet(packet, priority); m_queriesSent++; } void DhtServer::create_response(const DhtMessage& req, const sockaddr* sa, DhtMessage& reply) { reply[key_r_id] = m_router->id_raw_string(); reply[key_t] = req[key_t]; reply[key_y] = raw_bencode::from_c_str("1:r"); reply[key_v] = raw_bencode("4:" PEER_VERSION, 6); add_packet(std::make_shared(sa, reply), packet_prio_reply); } void DhtServer::create_error(const DhtMessage& req, const sockaddr* sa, int num, const char* msg) { DhtMessage error; if (req[key_t].is_raw_string() && req[key_t].as_raw_string().size() < 67) error[key_t] = req[key_t]; error[key_y] = raw_bencode::from_c_str("1:e"); error[key_v] = raw_bencode("4:" PEER_VERSION, 6); error[key_e_0] = num; error[key_e_1] = raw_string::from_c_str(msg); add_packet(std::make_shared(sa, error), packet_prio_reply); } int DhtServer::add_transaction(std::shared_ptr transaction, int priority) { // Try random transaction ID. This is to make it less likely that we reuse // a transaction ID from an earlier transaction which timed out and we forgot // about it, so that if the node replies after the timeout it's less likely // that we match the reply to the wrong transaction. // // If there's an existing transaction with the random ID we search for the next // unused one. Since normally only one or two transactions will be active per // node, a collision is extremely unlikely, and a linear search for the first // open one is the most efficient. unsigned int rnd = static_cast(random()); unsigned int id = rnd; auto insertItr = m_transactions.lower_bound(transaction->key(rnd)); // If key matches, keep trying successive IDs. while (insertItr != m_transactions.end() && insertItr->first == transaction->key(id)) { ++insertItr; id = static_cast(id + 1); // Give up after trying all possible IDs. This should never happen. if (id == rnd) return -1; // Transaction ID wrapped around, reset iterator. if (id == 0) insertItr = m_transactions.lower_bound(transaction->key(id)); } // We know where to insert it, so pass that as hint. insertItr = m_transactions.insert(insertItr, std::make_pair(transaction->key(id), transaction)); create_query(insertItr, id, transaction->address(), priority); start_write(); return id; } // Transaction received no reply and timed out. Mark node as bad and remove // transaction (except if it was only the quick timeout). DhtServer::transaction_itr DhtServer::failed_transaction(transaction_itr itr, bool quick) { auto transaction = itr->second; // If it was a known node, remember that it didn't reply, unless the transaction // is only stalled (had quick timeout, but not full timeout). Also if the // transaction still has an associated packet, the packet never got sent due to // throttling, so don't blame the remote node for not replying. // Finally, if we haven't received anything whatsoever so far, assume the entire // network is down and so we can't blame the node either. if (!quick && m_networkUp && transaction->packet() == NULL && transaction->id() != torrent::DhtRouter::zero_id) m_router->node_inactive(transaction->id(), transaction->address()); if (transaction->type() == DhtTransaction::DHT_FIND_NODE) { if (quick) transaction->as_find_node()->set_stalled(); else transaction->as_find_node()->complete(false); try { find_node_next(transaction->as_find_node()); } catch (const std::exception&) { if (!quick) { drop_packet(transaction->packet().get()); m_transactions.erase(itr); } throw; } } // don't actually delete the transaction until the final timeout if (quick) return ++itr; drop_packet(transaction->packet().get()); m_transactions.erase(itr++); return itr; } void DhtServer::clear_transactions() { for (auto& transaction : m_transactions) drop_packet(transaction.second->packet().get()); m_transactions.clear(); } void DhtServer::event_read() { while (true) { Object request; int type = '?'; DhtMessage message; raw_string nodeIdStr; const HashString* nodeId = NULL; char buffer[2048]; sockaddr_in6 sa_raw{}; sockaddr* sa = reinterpret_cast(&sa_raw); try { int32_t read = read_datagram_sa(buffer, sizeof(buffer), sa, sizeof(sa_raw)); if (read < 0) break; // We can currently only process mapped-IPv4 addresses, not real IPv6. // Translate them to an af_inet socket_address. if (sa_is_v4mapped(sa)) { auto sa_unmapped = sin_from_v4mapped_in6(&sa_raw); *reinterpret_cast(&sa_raw) = *sa_unmapped.get(); } if (sa->sa_family != AF_INET) continue; // If it's not a valid bencode dictionary at all, it's probably not a DHT // packet at all, so we don't throw an error to prevent bounce loops. try { static_map_read_bencode(buffer, buffer + read, message); } catch (const bencode_error&) { continue; } if (!message[key_t].is_raw_string()) throw dht_error(dht_error_protocol, "No transaction ID"); // Restrict the length of Transaction IDs. We echo them in our replies. if(message[key_t].as_raw_string().size() > 20) { throw dht_error(dht_error_protocol, "Transaction ID length too long"); } if (!message[key_y].is_raw_string()) throw dht_error(dht_error_protocol, "No message type"); if (message[key_y].as_raw_string().size() != 1) throw dht_error(dht_error_bad_method, "Unsupported message type"); type = message[key_y].as_raw_string().data()[0]; // Queries and replies have node ID in different dictionaries. if (type == 'r' || type == 'q') { if (!message[type == 'q' ? key_a_id : key_r_id].is_raw_string()) throw dht_error(dht_error_protocol, "Invalid `id' value"); nodeIdStr = message[type == 'q' ? key_a_id : key_r_id].as_raw_string(); if (nodeIdStr.size() < HashString::size_data) throw dht_error(dht_error_protocol, "`id' value too short"); nodeId = HashString::cast_from(nodeIdStr.data()); } // Sanity check the returned transaction ID. if ((type == 'r' || type == 'e') && (!message[key_t].is_raw_string() || message[key_t].as_raw_string().size() != 1)) throw dht_error(dht_error_protocol, "Invalid transaction ID type/length."); // Stupid broken implementations. if (nodeId != NULL && *nodeId == m_router->id()) throw dht_error(dht_error_protocol, "Send your own ID, not mine"); switch (type) { case 'q': process_query(*nodeId, sa, message); break; case 'r': process_response(*nodeId, sa, message); break; case 'e': process_error(sa, message); break; default: throw dht_error(dht_error_bad_method, "Unknown message type."); } // If node was querying us, reply with error packet, otherwise mark the node as "query failed", // so that if it repeatedly sends malformed replies we will drop it instead of propagating it // to other nodes. } catch (const bencode_error& e) { if ((type == 'r' || type == 'e') && nodeId != NULL) { m_router->node_inactive(*nodeId, sa); } else { snprintf(message.data_end, message.data + torrent::DhtMessage::data_size - message.data_end - 1, "Malformed packet: %s", e.what()); message.data[torrent::DhtMessage::data_size - 1] = '\0'; create_error(message, sa, dht_error_protocol, message.data_end); } } catch (const dht_error& e) { if ((type == 'r' || type == 'e') && nodeId != NULL) m_router->node_inactive(*nodeId, sa); else create_error(message, sa, e.code(), e.what()); } catch (const network_error&) { } } start_write(); } void DhtServer::process_queue(packet_queue& queue) { while (!queue.empty()) { auto packet = queue.front(); DhtTransaction::key_type transactionKey = 0; if(packet->has_transaction()) transactionKey = packet->transaction()->key(packet->id()); // Make sure its transaction hasn't timed out yet, if it has/had one // and don't bother sending non-transaction packets (replies) after // more than 15 seconds in the queue. if (packet->has_failed() || packet->age() > 15) { queue.pop_front(); continue; } queue.pop_front(); try { int written = write_datagram_sa(packet->c_str(), packet->length(), packet->address()); if (written == -1) throw network_error(); if (static_cast(written) != packet->length()) throw network_error(); } catch (const network_error&) { // Couldn't write packet, maybe something wrong with node address or routing, so mark node as bad. if (packet->has_transaction()) { auto itr = m_transactions.find(transactionKey); if (itr == m_transactions.end()) throw internal_error("DhtServer::process_queue could not find transaction."); failed_transaction(itr, false); } } if (packet->has_transaction()) { // here transaction can be already deleted by failed_transaction. auto itr = m_transactions.find(transactionKey); if (itr != m_transactions.end()) packet->transaction()->reset_packet(); } } } void DhtServer::event_write() { if (m_highQueue.empty() && m_lowQueue.empty()) throw internal_error("DhtServer::event_write called but both write queues are empty."); process_queue(m_highQueue); process_queue(m_lowQueue); if (m_highQueue.empty() && m_lowQueue.empty()) this_thread::poll()->remove_write(this); } void DhtServer::event_error() { } void DhtServer::start_write() { if (!m_highQueue.empty() || !m_lowQueue.empty()) this_thread::poll()->insert_write(this); if (!m_task_timeout.is_scheduled() && !m_transactions.empty()) this_thread::scheduler()->wait_for_ceil_seconds(&m_task_timeout, 5s); } void DhtServer::receive_timeout() { auto itr = m_transactions.begin(); while (itr != m_transactions.end()) { if (itr->second->has_quick_timeout() && itr->second->quick_timeout() < this_thread::cached_seconds().count()) { itr = failed_transaction(itr, true); } else if (itr->second->timeout() < this_thread::cached_seconds().count()) { itr = failed_transaction(itr, false); } else { ++itr; } } start_write(); } } // namespace torrent libtorrent-0.16.11/src/dht/dht_tracker.cc0000644000000000000000000000517515175073411013656 #include "config.h" #include "dht_tracker.h" namespace torrent { void DhtTracker::add_peer(uint32_t addr_n, uint16_t port) { if (port == 0) return; SocketAddressCompact compact(addr_n, port); unsigned int oldest = 0; uint32_t minSeen = ~uint32_t(); // Check if peer exists. If not, find oldest peer. for (unsigned int i = 0; i < size(); i++) { if (m_peers[i].peer.addr == compact.addr) { m_peers[i].peer.port = compact.port; m_lastSeen[i] = this_thread::cached_seconds().count(); return; } if (m_lastSeen[i] < minSeen) { minSeen = m_lastSeen[i]; oldest = i; } } // If peer doesn't exist, append to list if the table is not full. if (size() < max_size) { m_peers.emplace_back(compact); m_lastSeen.push_back(this_thread::cached_seconds().count()); return; } // Peer doesn't exist and table is full: replace oldest peer. m_peers[oldest] = compact; m_lastSeen[oldest] = this_thread::cached_seconds().count(); } // Return compact info as bencoded string (8 bytes per peer) for up to 30 peers, // returning different peers for each call if there are more. raw_list DhtTracker::get_peers(unsigned int maxPeers) { if (sizeof(BencodeAddress) != 8) throw internal_error("DhtTracker::BencodeAddress is packed incorrectly."); auto first = m_peers.begin(); auto last = m_peers.end(); // If we have more than max_peers, randomly return block of peers. // The peers in overlapping blocks get picked twice as often, but // that's better than returning fewer peers. if (m_peers.size() > maxPeers) { unsigned int blocks = (m_peers.size() + maxPeers - 1) / maxPeers; first += (random() % blocks) * (m_peers.size() - maxPeers) / (blocks - 1); last = first + maxPeers; } return raw_list(first->bencode(), last->bencode() - first->bencode()); } // Remove old announces. void DhtTracker::prune(uint32_t maxAge) { uint32_t minSeen = this_thread::cached_seconds().count() - maxAge; for (unsigned int i = 0; i < m_lastSeen.size(); i++) if (m_lastSeen[i] < minSeen) m_peers[i].peer.port = 0; m_peers.erase(std::remove_if(m_peers.begin(), m_peers.end(), std::mem_fn(&BencodeAddress::empty)), m_peers.end()); m_lastSeen.erase(std::remove_if(m_lastSeen.begin(), m_lastSeen.end(), [minSeen](auto seen) { return seen < minSeen; }), m_lastSeen.end()); if (m_peers.size() != m_lastSeen.size()) throw internal_error("DhtTracker::prune did inconsistent peer pruning."); } } // namespace torrent libtorrent-0.16.11/src/dht/dht_server.h0000644000000000000000000001336315175073411013371 #ifndef LIBTORRENT_DHT_SERVER_H #define LIBTORRENT_DHT_SERVER_H #include #include #include #include #include "dht/dht_transaction.h" #include "net/socket_datagram.h" #include "torrent/hash_string.h" #include "torrent/object_raw_bencode.h" #include "torrent/utils/scheduler.h" namespace torrent { class DhtBucket; class DhtNode; class DhtRouter; class DownloadInfo; class DhtMessage; class TrackerDht; // UDP server that handles the DHT node communications. class DhtServer : public SocketDatagram { public: DhtServer(DhtRouter* self); ~DhtServer() override; const char* type_name() const override { return "dht"; } bool is_active() const { return is_open(); } void start(int port); void stop(); unsigned int queries_received() const { return m_queriesReceived; } unsigned int queries_sent() const { return m_queriesSent; } unsigned int replies_received() const { return m_repliesReceived; } unsigned int errors_received() const { return m_errorsReceived; } unsigned int errors_caught() const { return m_errorsCaught; } void reset_statistics(); // Contact a node to see if it replies. Set id=0 if unknown. void ping(const HashString& id, const sockaddr* sa); // Do a find_node search with the given contacts as starting point for the // search. void find_node(const DhtBucket& contacts, const HashString& target); // Do DHT announce, starting with the given contacts. void announce(const DhtBucket& contacts, const HashString& infoHash, TrackerDht* tracker); // Cancel given announce for given tracker, or all matching announces if info/tracker NULL. void cancel_announce(const HashString* info_hash, const TrackerDht* tracker); // Called every 15 minutes. void update(); void check_search_completed(std::shared_ptr search); void check_search_trimming(std::shared_ptr search); void event_read() override; void event_write() override; void event_error() override; private: // DHT error codes. static constexpr int dht_error_generic = 201; static constexpr int dht_error_server = 202; static constexpr int dht_error_protocol = 203; static constexpr int dht_error_bad_method = 204; struct [[gnu::packed]] compact_node_info { char _id[20]; SocketAddressCompact _addr; HashString& id() { return *HashString::cast_from(_id); } }; using packet_queue = std::deque>; using node_info_list = std::list; using search_set = std::set>; // Pending transactions. using transaction_map = std::map>; using transaction_itr = transaction_map::iterator; // DHT transaction names for given transaction type. static constexpr std::array queries{ "ping", "find_node", "get_peers", "announce_peer", }; // Priorities for the outgoing packets. static constexpr int packet_prio_high = 2; // For important queries we send (announces). static constexpr int packet_prio_low = 1; // For (relatively) unimportant queries we send. static constexpr int packet_prio_reply = 0; // For replies to peer queries. void start_write(); void process_query(const HashString& id, const sockaddr* sa, const DhtMessage& req); void process_response(const HashString& id, const sockaddr* sa, const DhtMessage& req); void process_error(const sockaddr* sa, const DhtMessage& error); void parse_find_node_reply(DhtTransactionSearch* t, raw_string nodes); void parse_get_peers_reply(DhtTransactionGetPeers* t, const DhtMessage& res); void find_node_next(DhtTransactionSearch* t); void add_packet(std::shared_ptr packet, int priority); void drop_packet(const DhtTransactionPacket* packet); void create_query(transaction_itr itr, int tID, const sockaddr* sa, int priority); void create_response(const DhtMessage& req, const sockaddr* sa, DhtMessage& reply); void create_error(const DhtMessage& req, const sockaddr* sa, int num, const char* msg); void create_find_node_response(const DhtMessage& arg, DhtMessage& reply); void create_get_peers_response(const DhtMessage& arg, const sockaddr* sa, DhtMessage& reply); void create_announce_peer_response(const DhtMessage& arg, const sockaddr* sa, DhtMessage& reply); int add_transaction(std::shared_ptr transaction, int priority); // This returns the iterator after the given one or end() transaction_itr failed_transaction(transaction_itr itr, bool quick); void clear_transactions(); void process_queue(packet_queue& queue); void receive_timeout(); DhtRouter* m_router{}; search_set m_searches; packet_queue m_highQueue; packet_queue m_lowQueue; transaction_map m_transactions; utils::SchedulerEntry m_task_timeout; unsigned int m_queriesReceived{}; unsigned int m_queriesSent{}; unsigned int m_repliesReceived{}; unsigned int m_errorsReceived{}; unsigned int m_errorsCaught{}; bool m_networkUp{false}; }; } // namespace torrent #endif libtorrent-0.16.11/src/dht/dht_bucket.cc0000644000000000000000000001020215175073411013463 #include "config.h" #include "dht_bucket.h" #include #include "dht_node.h" #include "torrent/exceptions.h" namespace torrent { DhtBucket::DhtBucket(const HashString& begin, const HashString& end) : m_begin(begin), m_end(end) { reserve(num_nodes); } void DhtBucket::add_node(DhtNode* n) { push_back(n); touch(); if (n->is_good()) m_good++; else if (n->is_bad()) m_bad++; m_fullCacheLength = 0; } void DhtBucket::remove_node(DhtNode* n) { auto itr = std::find(begin(), end(), n); if (itr == end()) throw internal_error("DhtBucket::remove_node called for node not in bucket."); erase(itr); if (n->is_good()) m_good--; else if (n->is_bad()) m_bad--; m_fullCacheLength = 0; } void DhtBucket::count() { m_good = std::count_if(begin(), end(), std::mem_fn(&DhtNode::is_good)); m_bad = std::count_if(begin(), end(), std::mem_fn(&DhtNode::is_bad)); } // Called every 15 minutes for housekeeping. void DhtBucket::update() { count(); // In case adjacent buckets whose nodes we borrowed have changed, // we force an update of the cache. m_fullCacheLength = 0; } DhtBucket::iterator DhtBucket::find_replacement_candidate(bool onlyOldest) { auto oldest = end(); auto oldestTime = std::numeric_limits::max(); for (auto itr = begin(); itr != end(); ++itr) { if ((*itr)->is_bad() && !onlyOldest) return itr; if ((*itr)->last_seen() < oldestTime) { oldestTime = (*itr)->last_seen(); oldest = itr; } } return oldest; } void DhtBucket::get_mid_point(HashString* middle) const { *middle = m_end; for (unsigned int i=0; i(m_begin[i]) + static_cast(m_end[i])) / 2; break; } } void DhtBucket::get_random_id(HashString* rand_id) const { // Generate a random ID between m_begin and m_end. // Since m_end - m_begin = 2^n - 1, we can do a bitwise AND operation. for (unsigned int i=0; i0; i--) { unsigned int sum = static_cast(mid_range[i - 1]) + carry; m_begin[i - 1] = static_cast(sum); carry = sum >> 8; } // Move nodes over to other bucket if they fall in its range, then // delete them from this one. auto split = std::partition(begin(), end(), [this](auto dht) { return dht->is_in_range(this); }); other->insert(other->end(), split, end()); for (auto& dht : *other) { dht->set_bucket(other); } erase(split, end()); other->set_time(m_last_changed); other->count(); count(); // Maintain child (adjacent narrower bucket) and parent (adjacent wider bucket) // so that given router ID is in child. if (other->is_in_range(id)) { // Make other become our new child. m_child = other; other->m_parent = this; } else { // We become other's child, other becomes our parent's child. if (parent() != NULL) { parent()->m_child = other; other->m_parent = parent(); } m_parent = other; other->m_child = this; } return other; } void DhtBucket::build_full_cache() { DhtBucketChain chain(this); char* pos = m_fullCache; do { for (auto itr = chain.bucket()->begin(); itr != chain.bucket()->end() && pos < m_fullCache + sizeof(m_fullCache); ++itr) { if (!(*itr)->is_bad()) { pos = (*itr)->store_compact(pos); if (pos > m_fullCache + sizeof(m_fullCache)) throw internal_error("DhtRouter::store_closest_nodes wrote past buffer end."); } } } while (pos < m_fullCache + sizeof(m_fullCache) && chain.next() != NULL); m_fullCacheLength = pos - m_fullCache; } } // namespace torrent libtorrent-0.16.11/src/dht/dht_tracker.h0000644000000000000000000000350015175073411013506 #ifndef LIBTORRENT_DHT_TRACKER_H #define LIBTORRENT_DHT_TRACKER_H #include #include "net/address_list.h" // For SA. #include "torrent/object_raw_bencode.h" namespace torrent { // Container for peers tracked in a torrent. class DhtTracker { public: // Maximum number of peers we return for a GET_PEERS query (default value only). // Needs to be small enough so that a packet with a payload of num_peers*6 bytes // does not need fragmentation. Value chosen so that the size is approximately // equal to a FIND_NODE reply (8*26 bytes). static constexpr unsigned int max_peers = 32; // Maximum number of peers we keep track of. For torrents with more peers, // we replace the oldest peer with each new announce to avoid excessively // large peer tables for very active torrents. static constexpr unsigned int max_size = 128; bool empty() const { return m_peers.empty(); } size_t size() const { return m_peers.size(); } void add_peer(uint32_t addr_n, uint16_t port); raw_list get_peers(unsigned int maxPeers = max_peers); // Remove old announces from the tracker that have not reannounced for // more than the given number of seconds. void prune(uint32_t maxAge); private: // We need to store the address as a bencoded string. struct [[gnu::packed]] BencodeAddress { char header[2]; SocketAddressCompact peer; BencodeAddress(const SocketAddressCompact& p) : peer(p) { header[0] = '6'; header[1] = ':'; } const char* bencode() const { return header; } bool empty() const { return !peer.port; } }; using PeerList = std::vector; PeerList m_peers; std::vector m_lastSeen; }; } // namespace torrent #endif libtorrent-0.16.11/src/dht/transactions/0000755000000000000000000000000015175073434013642 5libtorrent-0.16.11/src/dht/transactions/dht_announce.h0000644000000000000000000000211015175073411016365 #ifndef LIBTORRENT_DHT_TRANSACTIONS_DHT_ANNOUNCE_H #define LIBTORRENT_DHT_TRANSACTIONS_DHT_ANNOUNCE_H #include #include "dht/transactions/dht_search.h" #include "torrent/common.h" // DhtAnnounce is a derived class used for searches that will eventually lead to an announce to the // closest nodes. namespace torrent { class DhtBucket; class TrackerDht; } namespace torrent::dht { class DhtAnnounce : public DhtSearch { public: DhtAnnounce(DhtServer* server, const HashString& infoHash, TrackerDht* tracker); ~DhtAnnounce() override; bool is_announce() const override { return true; } const TrackerDht* tracker() const { return m_tracker; } // Start announce and return final set of nodes in get_contact() calls. // This resets DhtSearch's completed() function, which now // counts announces instead. const_accessor start_announce(); void receive_peers(raw_list peers); void update_status(); private: TrackerDht* m_tracker; }; } // namespace torrent::dht #endif libtorrent-0.16.11/src/dht/transactions/dht_search.h0000644000000000000000000001212515175073411016033 #ifndef LIBTORRENT_DHT_TRANSACTIONS_DHT_SEARCH_H #define LIBTORRENT_DHT_TRANSACTIONS_DHT_SEARCH_H #include #include "torrent/common.h" #include "torrent/hash_string.h" #include "torrent/object_static_map.h" // DhtSearch implements the DHT search algorithm and holds search data that needs to be persistent // across multiple find_node transactions. // // DhtSearch contains a list of nodes sorted by closeness to the given target, and returns what // nodes to contact with up to three concurrent transactions pending. // // The map element is the DhtSearch object itself to allow the returned accessors to know which // search a given node belongs to. // TODO: Consider moving this to dht/ namespace torrent { class DhtBucket; class DhtNode; class DhtServer; class DhtTransactionSearch; class TrackerDht; } namespace torrent::dht { // Compare predicate for ID closeness. struct dht_compare_closer { dht_compare_closer(const HashString& target) : m_target(target) { } const HashString& target() const { return m_target; } raw_string target_raw_string() const { return raw_string(m_target.data(), HashString::size_data); } bool operator () (const std::unique_ptr& one, const std::unique_ptr& two) const; private: const HashString& m_target; }; // Use std::enable_shared_from_this as a temporary hack. class DhtSearch : public std::enable_shared_from_this, protected std::map, std::shared_ptr, dht_compare_closer> { public: using base_type = std::map, std::shared_ptr, dht_compare_closer>; // max_contacts: Number of closest potential contact nodes to keep. // max_announce: Number of closest nodes we actually announce to. static constexpr unsigned int max_contacts = 18; static constexpr unsigned int max_announce = 3; DhtSearch(DhtServer* server, const HashString& target); virtual ~DhtSearch(); // Wrapper for iterators, allowing more convenient access to the key // and element values, which also makes it easier to change the container // without having to modify much code using iterators. template struct accessor_wrapper : public T { accessor_wrapper() = default; accessor_wrapper(const T& itr) : T(itr) { } const auto& node() const { return (**this).first; } const std::shared_ptr& search() const { return (**this).second; } }; using const_accessor = accessor_wrapper; using accessor = accessor_wrapper; // Add a potential node to contact for the search. bool add_contact(const HashString& id, const sockaddr* sa); void add_contacts(const DhtBucket& contacts); // Return next node to contact. Up to concurrent_searches nodes are returned, // and end() after that. Don't advance the accessor to get further contacts! const_accessor get_contact(); // Search statistics. int num_contacted() const { return m_contacted; } int num_replied() const { return m_replied; } bool start() { m_started = true; return m_pending; } bool complete() const { return m_started && !m_pending; } const HashString& target() const { return m_target; } raw_string target_raw_string() const { return raw_string(m_target.data(), HashString::size_data); } virtual bool is_announce() const { return false; } // Expose the otherwise private end() function but return an accessor, // to allow code checking whether get_contact returned a valid accessor. const_accessor end() const { return base_type::end(); } // Used by the sorting/comparison predicate to see which node is closer. static bool is_closer(const HashString& one, const HashString& two, const HashString& target); protected: friend class torrent::DhtTransactionSearch; DhtServer* server() const { return m_server; } void trim(bool is_final); void node_status(const std::unique_ptr& n, bool success); static void set_node_active(const std::unique_ptr& n, bool active); // Statistics about contacted nodes. unsigned int m_pending{0}; unsigned int m_contacted{0}; unsigned int m_replied{0}; unsigned int m_concurrency{3}; bool m_restart{false}; // If true, trim nodes and reset m_next on the following get_contact call. bool m_started{false}; // Next node to return in get_contact, is end() if we have no more contactable nodes. const_accessor m_next; private: DhtSearch(const DhtSearch&) = delete; DhtSearch& operator=(const DhtSearch&) = delete; static bool node_uncontacted(const std::unique_ptr& node); DhtServer* m_server; HashString m_target; }; } // namespace torrent::dht #endif libtorrent-0.16.11/src/dht/transactions/dht_search.cc0000644000000000000000000001327515175073411016200 #include "config.h" #include "dht/transactions/dht_search.h" #include #include "dht/dht_node.h" #include "dht/dht_server.h" namespace torrent::dht { bool dht_compare_closer::operator () (const std::unique_ptr& one, const std::unique_ptr& two) const { return DhtSearch::is_closer(one->id(), two->id(), m_target); } DhtSearch::DhtSearch(DhtServer* server, const HashString& target) : base_type(dht_compare_closer(target)), m_next(end()), m_server(server), m_target(target) { // TODO: Must be done manually to ensure we got a shared_ptr. // add_contacts(contacts); } DhtSearch::~DhtSearch() { // Make sure transactions were destructed first. Since it is the destruction // of a transaction that triggers this destructor, that should always be the // case. assert(!m_pending && "DhtSearch::~DhtSearch called with pending transactions."); assert(m_concurrency == 3 && "DhtSearch::~DhtSearch called with invalid concurrency limit."); // TODO: Hack. // for (auto& itr : *this) // itr.second->server()->check_search_trimming(itr.second); } // TODO: Check if DhtSearch gets stored somewhere, and DhtBucket seems the most likely candidate. // // This seems to be storing self in the map. // // TODO: Remove self stored in the map, and when getting accessor from map, also pass the (self) DhtSearch. // bool DhtSearch::add_contact(const HashString& id, const sockaddr* sa) { auto n = std::make_unique(id, sa); bool added = emplace(std::move(n), shared_from_this()).second; if (added) m_restart = true; return added; } void DhtSearch::add_contacts(const DhtBucket& contacts) { DhtBucketChain chain(&contacts); // Add max_contacts=18 closest nodes, and fill up so we also have at least 8 good nodes. int needClosest = max_contacts - size(); int needGood = DhtBucket::num_nodes; for (auto itr = chain.bucket()->begin(); needClosest > 0 || needGood > 0; ++itr) { while (itr == chain.bucket()->end()) { if (!chain.next()) return; itr = chain.bucket()->begin(); } if ((!(*itr)->is_bad() || needClosest > 0) && add_contact((*itr)->id(), (*itr)->address())) { needGood -= !(*itr)->is_bad(); needClosest--; } } } // Check if a node has been contacted yet. This is the case if it is not currently // being contacted, nor has it been found to be good or bad. bool DhtSearch::node_uncontacted(const std::unique_ptr& node) { return !node->is_active() && !node->is_good() && !node->is_bad(); } // After more contacts have been added, discard least closest nodes // except if node has a transaction pending. void DhtSearch::trim(bool is_final) { // We keep: // - the max_contacts=18 closest good or unknown nodes and all nodes closer // than them (to see if further searches find closer ones) // - for announces, also the 3 closest good nodes (i.e. nodes that have // replied) to have at least that many for the actual announce // - any node that currently has transactions pending // // However, after exhausting all search nodes, we only keep good nodes. // // For our purposes, the node status is as follows: // node is bad (contacted but hasn't replied) if is_bad() // node is good (contacted and replied) if is_good() // node is currently being contacted if is_active() // node is new and unknown otherwise int needClosest = is_final ? 0 : max_contacts; int needGood = is_announce() ? max_announce : 0; // We're done if we can't find any more nodes to contact. m_next = end(); for (accessor itr = base_type::begin(); itr != end(); ) { // If we have all we need, delete current node unless it is // currently being contacted. if (!itr.node()->is_active() && needClosest <= 0 && (!itr.node()->is_good() || needGood <= 0)) { // TODO: Temporary hack. // TODO: Add server function to add it to m_search if not complete. // TODO: We should replace m_pending with a vector of txs. // TODO: We're somehow storying self in the map, and erasing causes crash as m_pending == 2. // itr.search()->server()->check_search_trimming(itr.search()); erase(itr++); continue; } // Otherwise adjust needed counts appropriately. needClosest--; needGood -= itr.node()->is_good(); // Remember the first uncontacted node as the closest one to contact next. if (m_next == end() && node_uncontacted(itr.node())) m_next = const_accessor(itr); ++itr; } m_restart = false; } bool DhtSearch::is_closer(const HashString& one, const HashString& two, const HashString& target) { for (unsigned int i=0; i(one[i] ^ target[i]) < static_cast(two[i] ^ target[i]); return false; } // TODO: Change m_pending to a vector of weak_ref. DhtSearch::const_accessor DhtSearch::get_contact() { if (m_pending >= m_concurrency) return end(); if (m_restart) trim(false); auto ret = m_next; if (ret == end()) return ret; set_node_active(ret.node(), true); m_pending++; m_contacted++; // Find next node to contact: any node we haven't contacted yet. while (++m_next != end()) { if (node_uncontacted(m_next.node())) break; } return ret; } void DhtSearch::node_status(const std::unique_ptr& n, bool success) { if (!n->is_active()) throw internal_error("DhtSearch::node_status called for invalid/inactive node."); if (success) { n->set_good(); m_replied++; } else { n->set_bad(); } m_pending--; set_node_active(n, false); } void DhtSearch::set_node_active(const std::unique_ptr& n, bool active) { n->m_last_seen = active; } } // namespace torrent::dht libtorrent-0.16.11/src/dht/transactions/dht_announce.cc0000644000000000000000000000322215175073411016530 #include "config.h" #include "dht/transactions/dht_announce.h" #include #include "dht/dht_bucket.h" #include "dht/dht_node.h" #include "tracker/tracker_dht.h" namespace torrent::dht { DhtAnnounce::DhtAnnounce(DhtServer* server, const HashString& infoHash, TrackerDht* tracker) : DhtSearch(server, infoHash), m_tracker(tracker) { } DhtAnnounce::~DhtAnnounce() { assert(complete() && "DhtAnnounce::~DhtAnnounce called while announce not complete."); const char* failure = NULL; if (m_tracker->get_dht_state() != TrackerDht::state_announcing) { if (!m_contacted) failure = "No DHT nodes available for peer search."; else failure = "DHT search unsuccessful."; } else { if (!m_contacted) failure = "DHT search unsuccessful."; else if (m_replied == 0 && !m_tracker->has_peers()) failure = "Announce failed"; } if (failure != NULL) m_tracker->receive_failed(failure); else m_tracker->receive_success(); } DhtSearch::const_accessor DhtAnnounce::start_announce() { trim(true); if (empty()) return end(); if (!complete() || m_next != end() || size() > DhtBucket::num_nodes) throw internal_error("DhtSearch::start_announce called in inconsistent state."); m_contacted = m_pending = size(); m_replied = 0; m_tracker->set_dht_state(TrackerDht::state_announcing); for (const auto& [node, _] : *this) set_node_active(node, true); return const_accessor(begin()); } void DhtAnnounce::receive_peers(raw_list peers) { m_tracker->receive_peers(peers); } void DhtAnnounce::update_status() { m_tracker->receive_progress(m_replied, m_contacted); } } // namespace torrent::dht libtorrent-0.16.11/src/dht/dht_bucket.h0000644000000000000000000001252715175073411013341 #ifndef LIBTORRENT_DHT_BUCKET_H #define LIBTORRENT_DHT_BUCKET_H #include #include #include "torrent/hash_string.h" #include "torrent/object_raw_bencode.h" namespace torrent { class DhtNode; // A container holding a small number of nodes that fall in a given binary // partition of the 160-bit ID space (i.e. the range ID1..ID2 where ID2-ID1+1 is // a power of 2.) class DhtBucket : private std::vector { public: static constexpr unsigned int num_nodes = 8; using base_type = std::vector; using base_type::const_iterator; using base_type::iterator; using base_type::begin; using base_type::end; using base_type::size; using base_type::empty; DhtBucket(const HashString& begin, const HashString& end); // Add new node. Does NOT set node's bucket automatically (to allow adding a // node to multiple buckets, with only one "main" bucket.) void add_node(DhtNode* n); void remove_node(DhtNode* n); // Bucket's ID range functions. const HashString& id_range_begin() const { return m_begin; } HashString& id_range_begin() { return m_begin; } const HashString& id_range_end() const { return m_end; } bool is_in_range(const HashString& id) const { return m_begin <= id && id <= m_end; } // Find middle or random ID in bucket. void get_mid_point(HashString* middle) const; void get_random_id(HashString* rand_id) const; // Node counts and bucket stats. bool is_full() const { return size() >= num_nodes; } bool has_space() const { return !is_full() || num_bad() > 0; } unsigned int num_good() const { return m_good; } unsigned int num_bad() const { return m_bad; } unsigned int age() const { return this_thread::cached_seconds().count() - m_last_changed; } void touch() { m_last_changed = this_thread::cached_seconds().count(); } void set_time(int32_t time) { m_last_changed = time; } // Called every 15 minutes after updating nodes. void update(); // Return candidate for replacement (a bad node or the oldest node); may // return end() unless has_space() is true. iterator find_replacement_candidate(bool onlyOldest = false); // Split the bucket in two and redistribute nodes. Returned bucket is the // lower half, "this" bucket keeps the upper half. Sets parent/child so // that the bucket the given ID falls in is the child. DhtBucket* split(const HashString& id); // Parent and child buckets. Parent is the adjacent bucket with double the // ID width, child the adjacent bucket with half the width (except the very // last child which has the same width.) DhtBucket* parent() const { return m_parent; } DhtBucket* child() const { return m_child; } // Return a full bucket's worth of compact node data. If this bucket is not // full, it uses nodes from the child/parent buckets until we have enough. raw_string full_bucket(); // Called by the DhtNode on its bucket to update good/bad node counts. void node_now_good(bool was_bad); void node_now_bad(bool was_good); private: void count(); void build_full_cache(); DhtBucket* m_parent{}; DhtBucket* m_child{}; int64_t m_last_changed{this_thread::cached_seconds().count()}; unsigned int m_good{0}; unsigned int m_bad{0}; size_t m_fullCacheLength{0}; // These are 40 bytes together, so might as well put them last. // m_end is const because it is used as key for the DhtRouter routing table // map, which would be inconsistent if m_end were changed carelessly. HashString m_begin; HashString m_end; char m_fullCache[num_nodes * 26]; }; // Helper class to recursively follow a chain of buckets. It first recurses // into the bucket's children since they are by definition closer to the bucket, // then continues with the bucket's parents. class DhtBucketChain { public: DhtBucketChain(const DhtBucket* b) : m_restart(b), m_cur(b) { } const DhtBucket* bucket() { return m_cur; } const DhtBucket* next(); private: const DhtBucket* m_restart; const DhtBucket* m_cur; }; inline void DhtBucket::node_now_good(bool was_bad) { m_bad -= was_bad; m_good++; } inline void DhtBucket::node_now_bad(bool was_good) { m_good -= was_good; m_bad++; } inline raw_string DhtBucket::full_bucket() { if (!m_fullCacheLength) build_full_cache(); return raw_string(m_fullCache, m_fullCacheLength); } inline const DhtBucket* DhtBucketChain::next() { // m_restart is clear when we're done recursing into the children and // follow the parents instead. if (m_restart == NULL) { m_cur = m_cur->parent(); } else { m_cur = m_cur->child(); if (m_cur == NULL) { m_cur = m_restart->parent(); m_restart = NULL; } } return m_cur; } } // namespace torrent #endif libtorrent-0.16.11/src/Makefile.in0000644000000000000000000015452415175073426012354 # Makefile.in generated by automake 1.17 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2024 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) am__rm_f = rm -f $(am__rm_f_notfound) am__rm_rf = rm -rf $(am__rm_f_notfound) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = src ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/scripts/attributes.m4 \ $(top_srcdir)/scripts/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/scripts/ax_execinfo.m4 \ $(top_srcdir)/scripts/ax_pthread.m4 \ $(top_srcdir)/scripts/check_atomic.m4 \ $(top_srcdir)/scripts/checks.m4 \ $(top_srcdir)/scripts/common.m4 \ $(top_srcdir)/scripts/libtool.m4 \ $(top_srcdir)/scripts/ltoptions.m4 \ $(top_srcdir)/scripts/ltsugar.m4 \ $(top_srcdir)/scripts/ltversion.m4 \ $(top_srcdir)/scripts/lt~obsolete.m4 \ $(top_srcdir)/scripts/rak_compiler.m4 \ $(top_srcdir)/scripts/ssl.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && echo $$files | $(am__xargs_n) 40 $(am__rm_f); }; \ } am__installdirs = "$(DESTDIR)$(libdir)" LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES) libtorrent_la_DEPENDENCIES = torrent/libtorrent_torrent.la \ libtorrent_other.la am_libtorrent_la_OBJECTS = manager.lo runtime.lo thread_main.lo libtorrent_la_OBJECTS = $(am_libtorrent_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libtorrent_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(AM_CXXFLAGS) $(CXXFLAGS) $(libtorrent_la_LDFLAGS) $(LDFLAGS) \ -o $@ libtorrent_other_la_LIBADD = am__dirstamp = $(am__leading_dot)dirstamp am_libtorrent_other_la_OBJECTS = data/chunk.lo data/chunk_list.lo \ data/chunk_part.lo data/hash_check_queue.lo data/hash_chunk.lo \ data/hash_queue.lo data/hash_queue_node.lo \ data/hash_torrent.lo data/memory_chunk.lo data/socket_file.lo \ data/thread_disk.lo dht/dht_bucket.lo dht/dht_node.lo \ dht/dht_router.lo dht/dht_server.lo dht/dht_tracker.lo \ dht/dht_transaction.lo dht/transactions/dht_announce.lo \ dht/transactions/dht_search.lo download/available_list.lo \ download/chunk_selector.lo download/chunk_statistics.lo \ download/delegator.lo download/download_constructor.lo \ download/download_main.lo download/download_wrapper.lo \ net/address_list.lo net/curl_get.lo net/curl_socket.lo \ net/curl_stack.lo net/dns_cache.lo net/dns_buffer.lo \ net/listen.lo net/socket_datagram.lo net/socket_stream.lo \ net/thread_net.lo net/throttle_internal.lo \ net/throttle_list.lo net/udns_resolver.lo net/udns_library.lo \ protocol/extensions.lo protocol/handshake.lo \ protocol/handshake_encryption.lo protocol/handshake_manager.lo \ protocol/initial_seed.lo protocol/peer_connection_base.lo \ protocol/peer_connection_leech.lo \ protocol/peer_connection_metadata.lo protocol/peer_factory.lo \ protocol/request_list.lo tracker/thread_tracker.lo \ tracker/tracker_controller.lo tracker/tracker_dht.lo \ tracker/tracker_http.lo tracker/tracker_list.lo \ tracker/tracker_udp.lo tracker/tracker_worker.lo \ utils/diffie_hellman.lo utils/instrumentation.lo \ utils/signal_interrupt.lo libtorrent_other_la_OBJECTS = $(am_libtorrent_other_la_OBJECTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/manager.Plo ./$(DEPDIR)/runtime.Plo \ ./$(DEPDIR)/thread_main.Plo data/$(DEPDIR)/chunk.Plo \ data/$(DEPDIR)/chunk_list.Plo data/$(DEPDIR)/chunk_part.Plo \ data/$(DEPDIR)/hash_check_queue.Plo \ data/$(DEPDIR)/hash_chunk.Plo data/$(DEPDIR)/hash_queue.Plo \ data/$(DEPDIR)/hash_queue_node.Plo \ data/$(DEPDIR)/hash_torrent.Plo \ data/$(DEPDIR)/memory_chunk.Plo data/$(DEPDIR)/socket_file.Plo \ data/$(DEPDIR)/thread_disk.Plo dht/$(DEPDIR)/dht_bucket.Plo \ dht/$(DEPDIR)/dht_node.Plo dht/$(DEPDIR)/dht_router.Plo \ dht/$(DEPDIR)/dht_server.Plo dht/$(DEPDIR)/dht_tracker.Plo \ dht/$(DEPDIR)/dht_transaction.Plo \ dht/transactions/$(DEPDIR)/dht_announce.Plo \ dht/transactions/$(DEPDIR)/dht_search.Plo \ download/$(DEPDIR)/available_list.Plo \ download/$(DEPDIR)/chunk_selector.Plo \ download/$(DEPDIR)/chunk_statistics.Plo \ download/$(DEPDIR)/delegator.Plo \ download/$(DEPDIR)/download_constructor.Plo \ download/$(DEPDIR)/download_main.Plo \ download/$(DEPDIR)/download_wrapper.Plo \ net/$(DEPDIR)/address_list.Plo net/$(DEPDIR)/curl_get.Plo \ net/$(DEPDIR)/curl_socket.Plo net/$(DEPDIR)/curl_stack.Plo \ net/$(DEPDIR)/dns_buffer.Plo net/$(DEPDIR)/dns_cache.Plo \ net/$(DEPDIR)/listen.Plo net/$(DEPDIR)/socket_datagram.Plo \ net/$(DEPDIR)/socket_stream.Plo net/$(DEPDIR)/thread_net.Plo \ net/$(DEPDIR)/throttle_internal.Plo \ net/$(DEPDIR)/throttle_list.Plo net/$(DEPDIR)/udns_library.Plo \ net/$(DEPDIR)/udns_resolver.Plo \ protocol/$(DEPDIR)/extensions.Plo \ protocol/$(DEPDIR)/handshake.Plo \ protocol/$(DEPDIR)/handshake_encryption.Plo \ protocol/$(DEPDIR)/handshake_manager.Plo \ protocol/$(DEPDIR)/initial_seed.Plo \ protocol/$(DEPDIR)/peer_connection_base.Plo \ protocol/$(DEPDIR)/peer_connection_leech.Plo \ protocol/$(DEPDIR)/peer_connection_metadata.Plo \ protocol/$(DEPDIR)/peer_factory.Plo \ protocol/$(DEPDIR)/request_list.Plo \ tracker/$(DEPDIR)/thread_tracker.Plo \ tracker/$(DEPDIR)/tracker_controller.Plo \ tracker/$(DEPDIR)/tracker_dht.Plo \ tracker/$(DEPDIR)/tracker_http.Plo \ tracker/$(DEPDIR)/tracker_list.Plo \ tracker/$(DEPDIR)/tracker_udp.Plo \ tracker/$(DEPDIR)/tracker_worker.Plo \ utils/$(DEPDIR)/diffie_hellman.Plo \ utils/$(DEPDIR)/instrumentation.Plo \ utils/$(DEPDIR)/signal_interrupt.Plo am__mv = mv -f CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) AM_V_CXX = $(am__v_CXX_@AM_V@) am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) am__v_CXX_0 = @echo " CXX " $@; am__v_CXX_1 = CXXLD = $(CXX) CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libtorrent_la_SOURCES) $(libtorrent_other_la_SOURCES) DIST_SOURCES = $(libtorrent_la_SOURCES) $(libtorrent_other_la_SOURCES) RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir distdir-am am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ ATOMIC_LIBS = @ATOMIC_LIBS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPUNIT_CFLAGS = @CPPUNIT_CFLAGS@ CPPUNIT_LIBS = @CPPUNIT_LIBS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FILECMD = @FILECMD@ GREP = @GREP@ HAVE_CXX17 = @HAVE_CXX17@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBCURL = @LIBCURL@ LIBCURL_CFLAGS = @LIBCURL_CFLAGS@ LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@ LIBCURL_LIBS = @LIBCURL_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTORRENT_CFLAGS = @LIBTORRENT_CFLAGS@ LIBTORRENT_CURRENT = @LIBTORRENT_CURRENT@ LIBTORRENT_INTERFACE_VERSION_INFO = @LIBTORRENT_INTERFACE_VERSION_INFO@ LIBTORRENT_INTERFACE_VERSION_NO = @LIBTORRENT_INTERFACE_VERSION_NO@ LIBTORRENT_LIBS = @LIBTORRENT_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_CXX = @PTHREAD_CXX@ PTHREAD_LIBS = @PTHREAD_LIBS@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ _libcurl_config = @_libcurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__rm_f_notfound = @am__rm_f_notfound@ am__tar = @am__tar@ am__untar = @am__untar@ am__xargs_n = @am__xargs_n@ ax_pthread_config = @ax_pthread_config@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = torrent lib_LTLIBRARIES = libtorrent.la noinst_LTLIBRARIES = \ libtorrent_other.la libtorrent_la_LDFLAGS = -version-info $(LIBTORRENT_INTERFACE_VERSION_INFO) libtorrent_la_LIBADD = \ torrent/libtorrent_torrent.la \ libtorrent_other.la libtorrent_la_SOURCES = \ manager.cc \ manager.h \ runtime.cc \ runtime.h \ thread_main.cc \ thread_main.h libtorrent_other_la_SOURCES = \ data/chunk.cc \ data/chunk.h \ data/chunk_handle.h \ data/chunk_iterator.h \ data/chunk_list.cc \ data/chunk_list.h \ data/chunk_list_node.h \ data/chunk_part.cc \ data/chunk_part.h \ data/hash_check_queue.cc \ data/hash_check_queue.h \ data/hash_chunk.cc \ data/hash_chunk.h \ data/hash_queue.cc \ data/hash_queue.h \ data/hash_queue_node.cc \ data/hash_queue_node.h \ data/hash_torrent.cc \ data/hash_torrent.h \ data/memory_chunk.cc \ data/memory_chunk.h \ data/socket_file.cc \ data/socket_file.h \ data/thread_disk.cc \ data/thread_disk.h \ \ dht/dht_bucket.cc \ dht/dht_bucket.h \ dht/dht_hash_map.h \ dht/dht_node.cc \ dht/dht_node.h \ dht/dht_router.cc \ dht/dht_router.h \ dht/dht_server.cc \ dht/dht_server.h \ dht/dht_tracker.cc \ dht/dht_tracker.h \ dht/dht_transaction.cc \ dht/dht_transaction.h \ \ dht/transactions/dht_announce.cc \ dht/transactions/dht_announce.h \ dht/transactions/dht_search.cc \ dht/transactions/dht_search.h \ \ download/available_list.cc \ download/available_list.h \ download/chunk_selector.cc \ download/chunk_selector.h \ download/chunk_statistics.cc \ download/chunk_statistics.h \ download/delegator.cc \ download/delegator.h \ download/download_constructor.cc \ download/download_constructor.h \ download/download_main.cc \ download/download_main.h \ download/download_wrapper.cc \ download/download_wrapper.h \ \ net/address_list.cc \ net/address_list.h \ net/data_buffer.h \ net/curl_get.cc \ net/curl_get.h \ net/curl_socket.cc \ net/curl_socket.h \ net/curl_stack.cc \ net/curl_stack.h \ net/dns_cache.cc \ net/dns_cache.h \ net/dns_buffer.cc \ net/dns_buffer.h \ net/listen.cc \ net/listen.h \ net/protocol_buffer.h \ net/socket_datagram.cc \ net/socket_datagram.h \ net/socket_stream.cc \ net/socket_stream.h \ net/thread_net.cc \ net/thread_net.h \ net/throttle_internal.cc \ net/throttle_internal.h \ net/throttle_list.cc \ net/throttle_list.h \ net/throttle_node.h \ net/udns_resolver.cc \ net/udns_resolver.h \ net/udns_library.cc \ net/udns_library.h \ \ net/udns/config.h \ net/udns/udns.h \ \ protocol/encryption_info.h \ protocol/extensions.cc \ protocol/extensions.h \ protocol/handshake.cc \ protocol/handshake.h \ protocol/handshake_encryption.cc \ protocol/handshake_encryption.h \ protocol/handshake_manager.cc \ protocol/handshake_manager.h \ protocol/initial_seed.cc \ protocol/initial_seed.h \ protocol/peer_chunks.h \ protocol/peer_connection_base.cc \ protocol/peer_connection_base.h \ protocol/peer_connection_leech.cc \ protocol/peer_connection_leech.h \ protocol/peer_connection_metadata.cc \ protocol/peer_connection_metadata.h \ protocol/peer_factory.cc \ protocol/peer_factory.h \ protocol/protocol_base.h \ protocol/request_list.cc \ protocol/request_list.h \ \ tracker/thread_tracker.cc \ tracker/thread_tracker.h \ tracker/tracker_controller.cc \ tracker/tracker_controller.h \ tracker/tracker_dht.cc \ tracker/tracker_dht.h \ tracker/tracker_http.cc \ tracker/tracker_http.h \ tracker/tracker_list.cc \ tracker/tracker_list.h \ tracker/tracker_udp.cc \ tracker/tracker_udp.h \ tracker/tracker_worker.cc \ tracker/tracker_worker.h \ \ utils/diffie_hellman.cc \ utils/diffie_hellman.h \ utils/functional.h \ utils/instrumentation.cc \ utils/instrumentation.h \ utils/partial_queue.h \ utils/rc4.h \ utils/sha1.h \ utils/signal_interrupt.cc \ utils/signal_interrupt.h \ utils/thread_internal.h \ utils/queue_buckets.h AM_CPPFLAGS = -I$(srcdir) -I$(top_srcdir) EXTRA_DIST = \ net/udns/dnsget.c \ net/udns/ex-rdns.c \ net/udns/getopt.c \ net/udns/inet_XtoX.c \ net/udns/rblcheck.c \ net/udns/udns.h \ net/udns/udns_XtoX.c \ net/udns/udns_bl.c \ net/udns/udns_codes.c \ net/udns/udns_dn.c \ net/udns/udns_dntosp.c \ net/udns/udns_init.c \ net/udns/udns_jran.c \ net/udns/udns_misc.c \ net/udns/udns_parse.c \ net/udns/udns_resolver.c \ net/udns/udns_rr_a.c \ net/udns/udns_rr_mx.c \ net/udns/udns_rr_naptr.c \ net/udns/udns_rr_ptr.c \ net/udns/udns_rr_srv.c \ net/udns/udns_rr_txt.c all: all-recursive .SUFFIXES: .SUFFIXES: .cc .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -$(am__rm_f) $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ echo rm -f $${locs}; \ $(am__rm_f) $${locs} clean-noinstLTLIBRARIES: -$(am__rm_f) $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ echo rm -f $${locs}; \ $(am__rm_f) $${locs} libtorrent.la: $(libtorrent_la_OBJECTS) $(libtorrent_la_DEPENDENCIES) $(EXTRA_libtorrent_la_DEPENDENCIES) $(AM_V_CXXLD)$(libtorrent_la_LINK) -rpath $(libdir) $(libtorrent_la_OBJECTS) $(libtorrent_la_LIBADD) $(LIBS) data/$(am__dirstamp): @$(MKDIR_P) data @: >>data/$(am__dirstamp) data/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) data/$(DEPDIR) @: >>data/$(DEPDIR)/$(am__dirstamp) data/chunk.lo: data/$(am__dirstamp) data/$(DEPDIR)/$(am__dirstamp) data/chunk_list.lo: data/$(am__dirstamp) \ data/$(DEPDIR)/$(am__dirstamp) data/chunk_part.lo: data/$(am__dirstamp) \ data/$(DEPDIR)/$(am__dirstamp) data/hash_check_queue.lo: data/$(am__dirstamp) \ data/$(DEPDIR)/$(am__dirstamp) data/hash_chunk.lo: data/$(am__dirstamp) \ data/$(DEPDIR)/$(am__dirstamp) data/hash_queue.lo: data/$(am__dirstamp) \ data/$(DEPDIR)/$(am__dirstamp) data/hash_queue_node.lo: data/$(am__dirstamp) \ data/$(DEPDIR)/$(am__dirstamp) data/hash_torrent.lo: data/$(am__dirstamp) \ data/$(DEPDIR)/$(am__dirstamp) data/memory_chunk.lo: data/$(am__dirstamp) \ data/$(DEPDIR)/$(am__dirstamp) data/socket_file.lo: data/$(am__dirstamp) \ data/$(DEPDIR)/$(am__dirstamp) data/thread_disk.lo: data/$(am__dirstamp) \ data/$(DEPDIR)/$(am__dirstamp) dht/$(am__dirstamp): @$(MKDIR_P) dht @: >>dht/$(am__dirstamp) dht/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) dht/$(DEPDIR) @: >>dht/$(DEPDIR)/$(am__dirstamp) dht/dht_bucket.lo: dht/$(am__dirstamp) dht/$(DEPDIR)/$(am__dirstamp) dht/dht_node.lo: dht/$(am__dirstamp) dht/$(DEPDIR)/$(am__dirstamp) dht/dht_router.lo: dht/$(am__dirstamp) dht/$(DEPDIR)/$(am__dirstamp) dht/dht_server.lo: dht/$(am__dirstamp) dht/$(DEPDIR)/$(am__dirstamp) dht/dht_tracker.lo: dht/$(am__dirstamp) dht/$(DEPDIR)/$(am__dirstamp) dht/dht_transaction.lo: dht/$(am__dirstamp) \ dht/$(DEPDIR)/$(am__dirstamp) dht/transactions/$(am__dirstamp): @$(MKDIR_P) dht/transactions @: >>dht/transactions/$(am__dirstamp) dht/transactions/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) dht/transactions/$(DEPDIR) @: >>dht/transactions/$(DEPDIR)/$(am__dirstamp) dht/transactions/dht_announce.lo: dht/transactions/$(am__dirstamp) \ dht/transactions/$(DEPDIR)/$(am__dirstamp) dht/transactions/dht_search.lo: dht/transactions/$(am__dirstamp) \ dht/transactions/$(DEPDIR)/$(am__dirstamp) download/$(am__dirstamp): @$(MKDIR_P) download @: >>download/$(am__dirstamp) download/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) download/$(DEPDIR) @: >>download/$(DEPDIR)/$(am__dirstamp) download/available_list.lo: download/$(am__dirstamp) \ download/$(DEPDIR)/$(am__dirstamp) download/chunk_selector.lo: download/$(am__dirstamp) \ download/$(DEPDIR)/$(am__dirstamp) download/chunk_statistics.lo: download/$(am__dirstamp) \ download/$(DEPDIR)/$(am__dirstamp) download/delegator.lo: download/$(am__dirstamp) \ download/$(DEPDIR)/$(am__dirstamp) download/download_constructor.lo: download/$(am__dirstamp) \ download/$(DEPDIR)/$(am__dirstamp) download/download_main.lo: download/$(am__dirstamp) \ download/$(DEPDIR)/$(am__dirstamp) download/download_wrapper.lo: download/$(am__dirstamp) \ download/$(DEPDIR)/$(am__dirstamp) net/$(am__dirstamp): @$(MKDIR_P) net @: >>net/$(am__dirstamp) net/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) net/$(DEPDIR) @: >>net/$(DEPDIR)/$(am__dirstamp) net/address_list.lo: net/$(am__dirstamp) net/$(DEPDIR)/$(am__dirstamp) net/curl_get.lo: net/$(am__dirstamp) net/$(DEPDIR)/$(am__dirstamp) net/curl_socket.lo: net/$(am__dirstamp) net/$(DEPDIR)/$(am__dirstamp) net/curl_stack.lo: net/$(am__dirstamp) net/$(DEPDIR)/$(am__dirstamp) net/dns_cache.lo: net/$(am__dirstamp) net/$(DEPDIR)/$(am__dirstamp) net/dns_buffer.lo: net/$(am__dirstamp) net/$(DEPDIR)/$(am__dirstamp) net/listen.lo: net/$(am__dirstamp) net/$(DEPDIR)/$(am__dirstamp) net/socket_datagram.lo: net/$(am__dirstamp) \ net/$(DEPDIR)/$(am__dirstamp) net/socket_stream.lo: net/$(am__dirstamp) \ net/$(DEPDIR)/$(am__dirstamp) net/thread_net.lo: net/$(am__dirstamp) net/$(DEPDIR)/$(am__dirstamp) net/throttle_internal.lo: net/$(am__dirstamp) \ net/$(DEPDIR)/$(am__dirstamp) net/throttle_list.lo: net/$(am__dirstamp) \ net/$(DEPDIR)/$(am__dirstamp) net/udns_resolver.lo: net/$(am__dirstamp) \ net/$(DEPDIR)/$(am__dirstamp) net/udns_library.lo: net/$(am__dirstamp) net/$(DEPDIR)/$(am__dirstamp) protocol/$(am__dirstamp): @$(MKDIR_P) protocol @: >>protocol/$(am__dirstamp) protocol/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) protocol/$(DEPDIR) @: >>protocol/$(DEPDIR)/$(am__dirstamp) protocol/extensions.lo: protocol/$(am__dirstamp) \ protocol/$(DEPDIR)/$(am__dirstamp) protocol/handshake.lo: protocol/$(am__dirstamp) \ protocol/$(DEPDIR)/$(am__dirstamp) protocol/handshake_encryption.lo: protocol/$(am__dirstamp) \ protocol/$(DEPDIR)/$(am__dirstamp) protocol/handshake_manager.lo: protocol/$(am__dirstamp) \ protocol/$(DEPDIR)/$(am__dirstamp) protocol/initial_seed.lo: protocol/$(am__dirstamp) \ protocol/$(DEPDIR)/$(am__dirstamp) protocol/peer_connection_base.lo: protocol/$(am__dirstamp) \ protocol/$(DEPDIR)/$(am__dirstamp) protocol/peer_connection_leech.lo: protocol/$(am__dirstamp) \ protocol/$(DEPDIR)/$(am__dirstamp) protocol/peer_connection_metadata.lo: protocol/$(am__dirstamp) \ protocol/$(DEPDIR)/$(am__dirstamp) protocol/peer_factory.lo: protocol/$(am__dirstamp) \ protocol/$(DEPDIR)/$(am__dirstamp) protocol/request_list.lo: protocol/$(am__dirstamp) \ protocol/$(DEPDIR)/$(am__dirstamp) tracker/$(am__dirstamp): @$(MKDIR_P) tracker @: >>tracker/$(am__dirstamp) tracker/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) tracker/$(DEPDIR) @: >>tracker/$(DEPDIR)/$(am__dirstamp) tracker/thread_tracker.lo: tracker/$(am__dirstamp) \ tracker/$(DEPDIR)/$(am__dirstamp) tracker/tracker_controller.lo: tracker/$(am__dirstamp) \ tracker/$(DEPDIR)/$(am__dirstamp) tracker/tracker_dht.lo: tracker/$(am__dirstamp) \ tracker/$(DEPDIR)/$(am__dirstamp) tracker/tracker_http.lo: tracker/$(am__dirstamp) \ tracker/$(DEPDIR)/$(am__dirstamp) tracker/tracker_list.lo: tracker/$(am__dirstamp) \ tracker/$(DEPDIR)/$(am__dirstamp) tracker/tracker_udp.lo: tracker/$(am__dirstamp) \ tracker/$(DEPDIR)/$(am__dirstamp) tracker/tracker_worker.lo: tracker/$(am__dirstamp) \ tracker/$(DEPDIR)/$(am__dirstamp) utils/$(am__dirstamp): @$(MKDIR_P) utils @: >>utils/$(am__dirstamp) utils/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) utils/$(DEPDIR) @: >>utils/$(DEPDIR)/$(am__dirstamp) utils/diffie_hellman.lo: utils/$(am__dirstamp) \ utils/$(DEPDIR)/$(am__dirstamp) utils/instrumentation.lo: utils/$(am__dirstamp) \ utils/$(DEPDIR)/$(am__dirstamp) utils/signal_interrupt.lo: utils/$(am__dirstamp) \ utils/$(DEPDIR)/$(am__dirstamp) libtorrent_other.la: $(libtorrent_other_la_OBJECTS) $(libtorrent_other_la_DEPENDENCIES) $(EXTRA_libtorrent_other_la_DEPENDENCIES) $(AM_V_CXXLD)$(CXXLINK) $(libtorrent_other_la_OBJECTS) $(libtorrent_other_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) -rm -f data/*.$(OBJEXT) -rm -f data/*.lo -rm -f dht/*.$(OBJEXT) -rm -f dht/*.lo -rm -f dht/transactions/*.$(OBJEXT) -rm -f dht/transactions/*.lo -rm -f download/*.$(OBJEXT) -rm -f download/*.lo -rm -f net/*.$(OBJEXT) -rm -f net/*.lo -rm -f protocol/*.$(OBJEXT) -rm -f protocol/*.lo -rm -f tracker/*.$(OBJEXT) -rm -f tracker/*.lo -rm -f utils/*.$(OBJEXT) -rm -f utils/*.lo distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/manager.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/runtime.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thread_main.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@data/$(DEPDIR)/chunk.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@data/$(DEPDIR)/chunk_list.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@data/$(DEPDIR)/chunk_part.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@data/$(DEPDIR)/hash_check_queue.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@data/$(DEPDIR)/hash_chunk.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@data/$(DEPDIR)/hash_queue.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@data/$(DEPDIR)/hash_queue_node.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@data/$(DEPDIR)/hash_torrent.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@data/$(DEPDIR)/memory_chunk.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@data/$(DEPDIR)/socket_file.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@data/$(DEPDIR)/thread_disk.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@dht/$(DEPDIR)/dht_bucket.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@dht/$(DEPDIR)/dht_node.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@dht/$(DEPDIR)/dht_router.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@dht/$(DEPDIR)/dht_server.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@dht/$(DEPDIR)/dht_tracker.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@dht/$(DEPDIR)/dht_transaction.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@dht/transactions/$(DEPDIR)/dht_announce.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@dht/transactions/$(DEPDIR)/dht_search.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@download/$(DEPDIR)/available_list.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@download/$(DEPDIR)/chunk_selector.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@download/$(DEPDIR)/chunk_statistics.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@download/$(DEPDIR)/delegator.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@download/$(DEPDIR)/download_constructor.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@download/$(DEPDIR)/download_main.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@download/$(DEPDIR)/download_wrapper.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@net/$(DEPDIR)/address_list.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@net/$(DEPDIR)/curl_get.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@net/$(DEPDIR)/curl_socket.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@net/$(DEPDIR)/curl_stack.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@net/$(DEPDIR)/dns_buffer.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@net/$(DEPDIR)/dns_cache.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@net/$(DEPDIR)/listen.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@net/$(DEPDIR)/socket_datagram.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@net/$(DEPDIR)/socket_stream.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@net/$(DEPDIR)/thread_net.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@net/$(DEPDIR)/throttle_internal.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@net/$(DEPDIR)/throttle_list.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@net/$(DEPDIR)/udns_library.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@net/$(DEPDIR)/udns_resolver.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@protocol/$(DEPDIR)/extensions.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@protocol/$(DEPDIR)/handshake.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@protocol/$(DEPDIR)/handshake_encryption.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@protocol/$(DEPDIR)/handshake_manager.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@protocol/$(DEPDIR)/initial_seed.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@protocol/$(DEPDIR)/peer_connection_base.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@protocol/$(DEPDIR)/peer_connection_leech.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@protocol/$(DEPDIR)/peer_connection_metadata.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@protocol/$(DEPDIR)/peer_factory.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@protocol/$(DEPDIR)/request_list.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@tracker/$(DEPDIR)/thread_tracker.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@tracker/$(DEPDIR)/tracker_controller.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@tracker/$(DEPDIR)/tracker_dht.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@tracker/$(DEPDIR)/tracker_http.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@tracker/$(DEPDIR)/tracker_list.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@tracker/$(DEPDIR)/tracker_udp.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@tracker/$(DEPDIR)/tracker_worker.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@utils/$(DEPDIR)/diffie_hellman.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@utils/$(DEPDIR)/instrumentation.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@utils/$(DEPDIR)/signal_interrupt.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @: >>$@ am--depfiles: $(am__depfiles_remade) .cc.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cc.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cc.lo: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs -rm -rf data/.libs data/_libs -rm -rf dht/.libs dht/_libs -rm -rf dht/transactions/.libs dht/transactions/_libs -rm -rf download/.libs download/_libs -rm -rf net/.libs net/_libs -rm -rf protocol/.libs protocol/_libs -rm -rf tracker/.libs tracker/_libs -rm -rf utils/.libs utils/_libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile $(LTLIBRARIES) installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(libdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -$(am__rm_f) $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || $(am__rm_f) $(CONFIG_CLEAN_VPATH_FILES) -$(am__rm_f) data/$(DEPDIR)/$(am__dirstamp) -$(am__rm_f) data/$(am__dirstamp) -$(am__rm_f) dht/$(DEPDIR)/$(am__dirstamp) -$(am__rm_f) dht/$(am__dirstamp) -$(am__rm_f) dht/transactions/$(DEPDIR)/$(am__dirstamp) -$(am__rm_f) dht/transactions/$(am__dirstamp) -$(am__rm_f) download/$(DEPDIR)/$(am__dirstamp) -$(am__rm_f) download/$(am__dirstamp) -$(am__rm_f) net/$(DEPDIR)/$(am__dirstamp) -$(am__rm_f) net/$(am__dirstamp) -$(am__rm_f) protocol/$(DEPDIR)/$(am__dirstamp) -$(am__rm_f) protocol/$(am__dirstamp) -$(am__rm_f) tracker/$(DEPDIR)/$(am__dirstamp) -$(am__rm_f) tracker/$(am__dirstamp) -$(am__rm_f) utils/$(DEPDIR)/$(am__dirstamp) -$(am__rm_f) utils/$(am__dirstamp) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ clean-noinstLTLIBRARIES mostlyclean-am distclean: distclean-recursive -rm -f ./$(DEPDIR)/manager.Plo -rm -f ./$(DEPDIR)/runtime.Plo -rm -f ./$(DEPDIR)/thread_main.Plo -rm -f data/$(DEPDIR)/chunk.Plo -rm -f data/$(DEPDIR)/chunk_list.Plo -rm -f data/$(DEPDIR)/chunk_part.Plo -rm -f data/$(DEPDIR)/hash_check_queue.Plo -rm -f data/$(DEPDIR)/hash_chunk.Plo -rm -f data/$(DEPDIR)/hash_queue.Plo -rm -f data/$(DEPDIR)/hash_queue_node.Plo -rm -f data/$(DEPDIR)/hash_torrent.Plo -rm -f data/$(DEPDIR)/memory_chunk.Plo -rm -f data/$(DEPDIR)/socket_file.Plo -rm -f data/$(DEPDIR)/thread_disk.Plo -rm -f dht/$(DEPDIR)/dht_bucket.Plo -rm -f dht/$(DEPDIR)/dht_node.Plo -rm -f dht/$(DEPDIR)/dht_router.Plo -rm -f dht/$(DEPDIR)/dht_server.Plo -rm -f dht/$(DEPDIR)/dht_tracker.Plo -rm -f dht/$(DEPDIR)/dht_transaction.Plo -rm -f dht/transactions/$(DEPDIR)/dht_announce.Plo -rm -f dht/transactions/$(DEPDIR)/dht_search.Plo -rm -f download/$(DEPDIR)/available_list.Plo -rm -f download/$(DEPDIR)/chunk_selector.Plo -rm -f download/$(DEPDIR)/chunk_statistics.Plo -rm -f download/$(DEPDIR)/delegator.Plo -rm -f download/$(DEPDIR)/download_constructor.Plo -rm -f download/$(DEPDIR)/download_main.Plo -rm -f download/$(DEPDIR)/download_wrapper.Plo -rm -f net/$(DEPDIR)/address_list.Plo -rm -f net/$(DEPDIR)/curl_get.Plo -rm -f net/$(DEPDIR)/curl_socket.Plo -rm -f net/$(DEPDIR)/curl_stack.Plo -rm -f net/$(DEPDIR)/dns_buffer.Plo -rm -f net/$(DEPDIR)/dns_cache.Plo -rm -f net/$(DEPDIR)/listen.Plo -rm -f net/$(DEPDIR)/socket_datagram.Plo -rm -f net/$(DEPDIR)/socket_stream.Plo -rm -f net/$(DEPDIR)/thread_net.Plo -rm -f net/$(DEPDIR)/throttle_internal.Plo -rm -f net/$(DEPDIR)/throttle_list.Plo -rm -f net/$(DEPDIR)/udns_library.Plo -rm -f net/$(DEPDIR)/udns_resolver.Plo -rm -f protocol/$(DEPDIR)/extensions.Plo -rm -f protocol/$(DEPDIR)/handshake.Plo -rm -f protocol/$(DEPDIR)/handshake_encryption.Plo -rm -f protocol/$(DEPDIR)/handshake_manager.Plo -rm -f protocol/$(DEPDIR)/initial_seed.Plo -rm -f protocol/$(DEPDIR)/peer_connection_base.Plo -rm -f protocol/$(DEPDIR)/peer_connection_leech.Plo -rm -f protocol/$(DEPDIR)/peer_connection_metadata.Plo -rm -f protocol/$(DEPDIR)/peer_factory.Plo -rm -f protocol/$(DEPDIR)/request_list.Plo -rm -f tracker/$(DEPDIR)/thread_tracker.Plo -rm -f tracker/$(DEPDIR)/tracker_controller.Plo -rm -f tracker/$(DEPDIR)/tracker_dht.Plo -rm -f tracker/$(DEPDIR)/tracker_http.Plo -rm -f tracker/$(DEPDIR)/tracker_list.Plo -rm -f tracker/$(DEPDIR)/tracker_udp.Plo -rm -f tracker/$(DEPDIR)/tracker_worker.Plo -rm -f utils/$(DEPDIR)/diffie_hellman.Plo -rm -f utils/$(DEPDIR)/instrumentation.Plo -rm -f utils/$(DEPDIR)/signal_interrupt.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-libLTLIBRARIES install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f ./$(DEPDIR)/manager.Plo -rm -f ./$(DEPDIR)/runtime.Plo -rm -f ./$(DEPDIR)/thread_main.Plo -rm -f data/$(DEPDIR)/chunk.Plo -rm -f data/$(DEPDIR)/chunk_list.Plo -rm -f data/$(DEPDIR)/chunk_part.Plo -rm -f data/$(DEPDIR)/hash_check_queue.Plo -rm -f data/$(DEPDIR)/hash_chunk.Plo -rm -f data/$(DEPDIR)/hash_queue.Plo -rm -f data/$(DEPDIR)/hash_queue_node.Plo -rm -f data/$(DEPDIR)/hash_torrent.Plo -rm -f data/$(DEPDIR)/memory_chunk.Plo -rm -f data/$(DEPDIR)/socket_file.Plo -rm -f data/$(DEPDIR)/thread_disk.Plo -rm -f dht/$(DEPDIR)/dht_bucket.Plo -rm -f dht/$(DEPDIR)/dht_node.Plo -rm -f dht/$(DEPDIR)/dht_router.Plo -rm -f dht/$(DEPDIR)/dht_server.Plo -rm -f dht/$(DEPDIR)/dht_tracker.Plo -rm -f dht/$(DEPDIR)/dht_transaction.Plo -rm -f dht/transactions/$(DEPDIR)/dht_announce.Plo -rm -f dht/transactions/$(DEPDIR)/dht_search.Plo -rm -f download/$(DEPDIR)/available_list.Plo -rm -f download/$(DEPDIR)/chunk_selector.Plo -rm -f download/$(DEPDIR)/chunk_statistics.Plo -rm -f download/$(DEPDIR)/delegator.Plo -rm -f download/$(DEPDIR)/download_constructor.Plo -rm -f download/$(DEPDIR)/download_main.Plo -rm -f download/$(DEPDIR)/download_wrapper.Plo -rm -f net/$(DEPDIR)/address_list.Plo -rm -f net/$(DEPDIR)/curl_get.Plo -rm -f net/$(DEPDIR)/curl_socket.Plo -rm -f net/$(DEPDIR)/curl_stack.Plo -rm -f net/$(DEPDIR)/dns_buffer.Plo -rm -f net/$(DEPDIR)/dns_cache.Plo -rm -f net/$(DEPDIR)/listen.Plo -rm -f net/$(DEPDIR)/socket_datagram.Plo -rm -f net/$(DEPDIR)/socket_stream.Plo -rm -f net/$(DEPDIR)/thread_net.Plo -rm -f net/$(DEPDIR)/throttle_internal.Plo -rm -f net/$(DEPDIR)/throttle_list.Plo -rm -f net/$(DEPDIR)/udns_library.Plo -rm -f net/$(DEPDIR)/udns_resolver.Plo -rm -f protocol/$(DEPDIR)/extensions.Plo -rm -f protocol/$(DEPDIR)/handshake.Plo -rm -f protocol/$(DEPDIR)/handshake_encryption.Plo -rm -f protocol/$(DEPDIR)/handshake_manager.Plo -rm -f protocol/$(DEPDIR)/initial_seed.Plo -rm -f protocol/$(DEPDIR)/peer_connection_base.Plo -rm -f protocol/$(DEPDIR)/peer_connection_leech.Plo -rm -f protocol/$(DEPDIR)/peer_connection_metadata.Plo -rm -f protocol/$(DEPDIR)/peer_factory.Plo -rm -f protocol/$(DEPDIR)/request_list.Plo -rm -f tracker/$(DEPDIR)/thread_tracker.Plo -rm -f tracker/$(DEPDIR)/tracker_controller.Plo -rm -f tracker/$(DEPDIR)/tracker_dht.Plo -rm -f tracker/$(DEPDIR)/tracker_http.Plo -rm -f tracker/$(DEPDIR)/tracker_list.Plo -rm -f tracker/$(DEPDIR)/tracker_udp.Plo -rm -f tracker/$(DEPDIR)/tracker_worker.Plo -rm -f utils/$(DEPDIR)/diffie_hellman.Plo -rm -f utils/$(DEPDIR)/instrumentation.Plo -rm -f utils/$(DEPDIR)/signal_interrupt.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-libLTLIBRARIES .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ am--depfiles check check-am clean clean-generic \ clean-libLTLIBRARIES clean-libtool clean-noinstLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-libLTLIBRARIES \ install-man install-pdf install-pdf-am install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs installdirs-am maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-libLTLIBRARIES .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: # Tell GNU make to disable its built-in pattern rules. %:: %,v %:: RCS/%,v %:: RCS/% %:: s.% %:: SCCS/s.% libtorrent-0.16.11/src/utils/0000755000000000000000000000000015175073434011513 5libtorrent-0.16.11/src/utils/diffie_hellman.cc0000644000000000000000000000364615175073411014674 #include "config.h" #include "diffie_hellman.h" #include "torrent/exceptions.h" #include #include #include #pragma GCC diagnostic ignored "-Wdeprecated-declarations" namespace { void dh_free(void* dh) { DH_free(static_cast(dh)); } auto dh_get(const torrent::DiffieHellman::dh_ptr& dh) { return static_cast(dh.get()); } bool dh_set_pg(torrent::DiffieHellman::dh_ptr& dh, BIGNUM* dh_p, BIGNUM* dh_g) { return DH_set0_pqg(static_cast(dh.get()), dh_p, nullptr, dh_g); } const BIGNUM* dh_get_pub_key(const torrent::DiffieHellman::dh_ptr& dh) { const BIGNUM *pub_key; DH_get0_key(dh_get(dh), &pub_key, nullptr); return pub_key; } } // namespace namespace torrent { DiffieHellman::DiffieHellman(const unsigned char *prime, int primeLength, const unsigned char *generator, int generatorLength) : m_dh(DH_new(), &dh_free) { BIGNUM* dh_p = BN_bin2bn(prime, primeLength, nullptr); BIGNUM* dh_g = BN_bin2bn(generator, generatorLength, nullptr); if (dh_p == nullptr || dh_g == nullptr || !dh_set_pg(m_dh, dh_p, dh_g)) throw internal_error("Could not generate Diffie-Hellman parameters"); DH_generate_key(dh_get(m_dh)); } bool DiffieHellman::is_valid() const { return dh_get_pub_key(m_dh) != nullptr; } bool DiffieHellman::compute_secret(const unsigned char *pubkey, unsigned int length) { BIGNUM* k = BN_bin2bn(pubkey, length, nullptr); m_secret = std::make_unique(DH_size(dh_get(m_dh))); m_size = DH_compute_key(reinterpret_cast(m_secret.get()), k, dh_get(m_dh)); BN_free(k); return m_size != -1; } void DiffieHellman::store_pub_key(unsigned char* dest, unsigned int length) { std::memset(dest, 0, length); const BIGNUM *pub_key = dh_get_pub_key(m_dh); if (static_cast(length) >= BN_num_bytes(pub_key)) BN_bn2bin(pub_key, dest + length - BN_num_bytes(pub_key)); } } // namespace torrent libtorrent-0.16.11/src/utils/thread_internal.h0000644000000000000000000000253715175073411014751 #ifndef LIBTORRENT_UTILS_THREAD_INTERNAL_H #define LIBTORRENT_UTILS_THREAD_INTERNAL_H #include "torrent/common.h" #include "torrent/system/thread.h" namespace torrent::system { class ThreadInternal { public: static auto* thread() { return Thread::m_self; } static auto thread_id() { return Thread::m_self->thread_id(); } static std::chrono::microseconds cached_time() { return Thread::m_self->m_cached_time; } static std::chrono::seconds cached_seconds() { return utils::cast_seconds(Thread::m_self->m_cached_time); } static void callback(void* target, std::function&& fn) { Thread::m_self->callback(target, std::move(fn)); } static void cancel_callback(void* target) { Thread::m_self->cancel_callback(target); } static void cancel_callback_and_wait(void* target) { Thread::m_self->cancel_callback_and_wait(target); } static net::Poll* poll() { return Thread::m_self->m_poll.get(); } static auto* scheduler() { return Thread::m_self->m_scheduler.get(); } static net::Resolver* resolver() { return Thread::m_self->m_resolver.get(); } }; } // namespace torrent::utils #endif // LIBTORRENT_UTILS_THREAD_INTERNAL_H libtorrent-0.16.11/src/utils/partial_queue.h0000644000000000000000000001057415175073411014446 #ifndef LIBTORRENT_UTILS_PARTIAL_QUEUE_H #define LIBTORRENT_UTILS_PARTIAL_QUEUE_H #include #include #include #include #include namespace torrent::utils { // First step, don't allow overflowing to the next layer. Only disable // the above layers for now. // We also include 0 in a single layer as some chunk may be available // only through seeders. class PartialQueue { public: typedef uint8_t key_type; typedef uint32_t mapped_type; typedef uint16_t size_type; typedef std::pair size_pair_type; static constexpr size_type num_layers = 8; PartialQueue() = default; ~PartialQueue() = default; bool is_full() const { return m_ceiling == 0; } bool is_layer_full(size_type l) const { return m_layers[l].second >= m_max_layer_size; } bool is_enabled() const { return m_data != NULL; } // Add check to see if we can add more. Also make it possible to // check how full we are in the lower parts so the caller knows when // he can stop searching. // // Though propably not needed, as we must continue til the first // layer is full. size_type max_size() const { return m_max_layer_size * num_layers; } size_type max_layer_size() const { return m_max_layer_size; } // Must be less that or equal to (max size_type) / num_layers. void enable(size_type ls); void disable(); void clear(); // Safe to call while pop'ing and it will not reuse pop'ed indices // so it is guaranteed to reach max_size at some point. This will // ensure that the user needs to refill with new data at regular // intervals. bool insert(key_type key, mapped_type value); // Only call this when pop'ing as it moves the index. bool prepare_pop(); mapped_type pop(); private: PartialQueue(const PartialQueue&) = delete; PartialQueue& operator=(const PartialQueue&) = delete; static size_type ceiling(size_type layer) { return (2 << layer) - 1; } std::unique_ptr m_data; size_type m_max_layer_size{}; size_type m_index{}; size_type m_ceiling{}; std::array m_layers; }; inline void PartialQueue::enable(size_type ls) { if (ls == 0) throw std::logic_error("PartialQueue::enable(...) ls == 0."); m_data.reset(new mapped_type[ls * num_layers]); m_max_layer_size = ls; } inline void PartialQueue::disable() { m_data.reset(); m_max_layer_size = 0; } inline void PartialQueue::clear() { if (m_data == NULL) return; m_index = 0; m_ceiling = ceiling(num_layers - 1); m_layers = {}; } inline bool PartialQueue::insert(key_type key, mapped_type value) { if (key >= m_ceiling) return false; size_type idx = 0; // Hmm... since we already check the 'm_ceiling' above, we only need // to find the target layer. Could this be calculated directly? while (key >= ceiling(idx)) ++idx; m_index = std::min(m_index, idx); // Currently don't allow overflow. if (is_layer_full(idx)) throw std::logic_error("PartialQueue::insert(...) layer already full."); //return false; m_data.get()[m_max_layer_size * idx + m_layers[idx].second] = value; m_layers[idx].second++; if (is_layer_full(idx)) // Set the ceiling to 0 when layer 0 is full so no more values can // be inserted. m_ceiling = idx > 0 ? ceiling(idx - 1) : 0; return true; } // is_empty() will iterate to the first layer with un-popped elements // and return true, else return false when it reaches a overflowed or // the last layer. inline bool PartialQueue::prepare_pop() { while (m_layers[m_index].first == m_layers[m_index].second) { if (is_layer_full(m_index) || m_index + 1 == num_layers) return false; m_index++; } return true; } inline PartialQueue::mapped_type PartialQueue::pop() { if (m_index >= num_layers || m_layers[m_index].first >= m_layers[m_index].second) throw std::logic_error("PartialQueue::pop() bad state."); return m_data.get()[m_index * m_max_layer_size + m_layers[m_index].first++]; } } // namespace torrent::utils #endif // LIBTORRENT_UTILS_PARTIAL_QUEUE_H libtorrent-0.16.11/src/utils/instrumentation.h0000644000000000000000000000642215175073411015046 #ifndef LIBTORRENT_UTILS_INSTRUMENTATION_H #define LIBTORRENT_UTILS_INSTRUMENTATION_H #include #include #include #include "torrent/common.h" #include "torrent/utils/log.h" namespace torrent { enum instrumentation_enum { INSTRUMENTATION_MEMORY_BITFIELDS, INSTRUMENTATION_MEMORY_CHUNK_USAGE, INSTRUMENTATION_MEMORY_CHUNK_COUNT, INSTRUMENTATION_MEMORY_HASHING_CHUNK_USAGE, INSTRUMENTATION_MEMORY_HASHING_CHUNK_COUNT, INSTRUMENTATION_MINCORE_INCORE_TOUCHED, INSTRUMENTATION_MINCORE_INCORE_NEW, INSTRUMENTATION_MINCORE_NOT_INCORE_TOUCHED, INSTRUMENTATION_MINCORE_NOT_INCORE_NEW, INSTRUMENTATION_MINCORE_INCORE_BREAK, INSTRUMENTATION_MINCORE_SYNC_SUCCESS, INSTRUMENTATION_MINCORE_SYNC_FAILED, INSTRUMENTATION_MINCORE_SYNC_NOT_SYNCED, INSTRUMENTATION_MINCORE_SYNC_NOT_DEALLOCATED, INSTRUMENTATION_MINCORE_ALLOC_FAILED, INSTRUMENTATION_MINCORE_ALLOCATIONS, INSTRUMENTATION_MINCORE_DEALLOCATIONS, INSTRUMENTATION_POLLING_INTERRUPT_POKE, INSTRUMENTATION_POLLING_INTERRUPT_READ_EVENT, INSTRUMENTATION_POLLING_DO_POLL, INSTRUMENTATION_POLLING_DO_POLL_MAIN, INSTRUMENTATION_POLLING_DO_POLL_DISK, INSTRUMENTATION_POLLING_DO_POLL_NET, INSTRUMENTATION_POLLING_DO_POLL_OTHERS, INSTRUMENTATION_POLLING_DO_POLL_TRACKER, INSTRUMENTATION_POLLING_EVENTS, INSTRUMENTATION_POLLING_EVENTS_MAIN, INSTRUMENTATION_POLLING_EVENTS_DISK, INSTRUMENTATION_POLLING_EVENTS_NET, INSTRUMENTATION_POLLING_EVENTS_OTHERS, INSTRUMENTATION_POLLING_EVENTS_TRACKER, INSTRUMENTATION_TRANSFER_REQUESTS_DELEGATED, INSTRUMENTATION_TRANSFER_REQUESTS_DOWNLOADING, INSTRUMENTATION_TRANSFER_REQUESTS_FINISHED, INSTRUMENTATION_TRANSFER_REQUESTS_SKIPPED, INSTRUMENTATION_TRANSFER_REQUESTS_UNKNOWN, INSTRUMENTATION_TRANSFER_REQUESTS_UNORDERED, INSTRUMENTATION_TRANSFER_REQUESTS_QUEUED_ADDED, INSTRUMENTATION_TRANSFER_REQUESTS_QUEUED_MOVED, INSTRUMENTATION_TRANSFER_REQUESTS_QUEUED_REMOVED, INSTRUMENTATION_TRANSFER_REQUESTS_QUEUED_TOTAL, INSTRUMENTATION_TRANSFER_REQUESTS_UNORDERED_ADDED, INSTRUMENTATION_TRANSFER_REQUESTS_UNORDERED_MOVED, INSTRUMENTATION_TRANSFER_REQUESTS_UNORDERED_REMOVED, INSTRUMENTATION_TRANSFER_REQUESTS_UNORDERED_TOTAL, INSTRUMENTATION_TRANSFER_REQUESTS_STALLED_ADDED, INSTRUMENTATION_TRANSFER_REQUESTS_STALLED_MOVED, INSTRUMENTATION_TRANSFER_REQUESTS_STALLED_REMOVED, INSTRUMENTATION_TRANSFER_REQUESTS_STALLED_TOTAL, INSTRUMENTATION_TRANSFER_REQUESTS_CHOKED_ADDED, INSTRUMENTATION_TRANSFER_REQUESTS_CHOKED_MOVED, INSTRUMENTATION_TRANSFER_REQUESTS_CHOKED_REMOVED, INSTRUMENTATION_TRANSFER_REQUESTS_CHOKED_TOTAL, INSTRUMENTATION_TRANSFER_PEER_INFO_UNACCOUNTED, INSTRUMENTATION_MAX_SIZE }; extern std::array instrumentation_values; void instrumentation_initialize(); void instrumentation_update(instrumentation_enum type, int64_t change); void instrumentation_tick(); void instrumentation_reset(); // // Implementation: // inline void instrumentation_initialize() { std::fill(instrumentation_values.begin(), instrumentation_values.end(), int64_t()); } inline void instrumentation_update([[maybe_unused]] instrumentation_enum type, [[maybe_unused]] int64_t change) { #ifdef LT_INSTRUMENTATION instrumentation_values[type] += change; #endif } } // namespace torrent #endif libtorrent-0.16.11/src/utils/sha1.h0000644000000000000000000000346015175073411012436 #ifndef LIBTORRENT_HASH_COMPUTE_H #define LIBTORRENT_HASH_COMPUTE_H #include #include #include #include "torrent/exceptions.h" namespace torrent { struct sha1_deleter { constexpr sha1_deleter() noexcept = default; void operator()(const EVP_MD_CTX* ctx) const { EVP_MD_CTX_free(const_cast(ctx)); } }; class Sha1 { public: void init(); void update(const void* data, unsigned int length); void final_c(void* buffer); private: std::unique_ptr m_ctx; }; inline void Sha1::init() { if (m_ctx == nullptr) m_ctx.reset(EVP_MD_CTX_new()); else EVP_MD_CTX_reset(m_ctx.get()); if (EVP_DigestInit(m_ctx.get(), EVP_sha1()) == 0) throw internal_error("Sha1::init() failed to initialize SHA-1 context."); } inline void Sha1::update(const void* data, unsigned int length) { if (EVP_DigestUpdate(m_ctx.get(), data, length) == 0) throw internal_error("Sha1::update() failed to update SHA-1 context."); } inline void Sha1::final_c(void* buffer) { if (EVP_DigestFinal(m_ctx.get(), static_cast(buffer), nullptr) == 0) throw internal_error("Sha1::final_c() failed to finalize SHA-1 context."); } inline void sha1_salt(const char* salt, unsigned int saltLength, const char* key, unsigned int keyLength, void* out) { Sha1 sha1; sha1.init(); sha1.update(salt, saltLength); sha1.update(key, keyLength); sha1.final_c(static_cast(out)); } inline void sha1_salt(const char* salt, unsigned int saltLength, const char* key1, unsigned int key1Length, const char* key2, unsigned int key2Length, void* out) { Sha1 sha1; sha1.init(); sha1.update(salt, saltLength); sha1.update(key1, key1Length); sha1.update(key2, key2Length); sha1.final_c(static_cast(out)); } } // namespace torrent #endif libtorrent-0.16.11/src/utils/instrumentation.cc0000644000000000000000000002157415175073411015211 #include "config.h" #include "instrumentation.h" namespace torrent { std::array instrumentation_values; static int64_t instrumentation_fetch_and_clear(instrumentation_enum type) { #ifdef LT_INSTRUMENTATION return instrumentation_values[type].exchange(0); #else return 0; #endif } void instrumentation_tick() { lt_log_print(LOG_INSTRUMENTATION_MEMORY, "%" PRIi64 " %" PRIi64 " %" PRIi64 " %" PRIi64 " %" PRIi64, instrumentation_values[INSTRUMENTATION_MEMORY_CHUNK_USAGE].load(), instrumentation_values[INSTRUMENTATION_MEMORY_CHUNK_COUNT].load(), instrumentation_values[INSTRUMENTATION_MEMORY_HASHING_CHUNK_USAGE].load(), instrumentation_values[INSTRUMENTATION_MEMORY_HASHING_CHUNK_COUNT].load(), instrumentation_values[INSTRUMENTATION_MEMORY_BITFIELDS].load()); lt_log_print(LOG_INSTRUMENTATION_MINCORE, "%" PRIi64 " %" PRIi64 " %" PRIi64 " %" PRIi64 " %" PRIi64 " %" PRIi64 " %" PRIi64 " %" PRIi64 " %" PRIi64 " %" PRIi64 " %" PRIi64 " %" PRIi64, instrumentation_fetch_and_clear(INSTRUMENTATION_MINCORE_INCORE_TOUCHED), instrumentation_fetch_and_clear(INSTRUMENTATION_MINCORE_INCORE_NEW), instrumentation_fetch_and_clear(INSTRUMENTATION_MINCORE_NOT_INCORE_TOUCHED), instrumentation_fetch_and_clear(INSTRUMENTATION_MINCORE_NOT_INCORE_NEW), instrumentation_fetch_and_clear(INSTRUMENTATION_MINCORE_INCORE_BREAK), instrumentation_fetch_and_clear(INSTRUMENTATION_MINCORE_SYNC_SUCCESS), instrumentation_fetch_and_clear(INSTRUMENTATION_MINCORE_SYNC_FAILED), instrumentation_fetch_and_clear(INSTRUMENTATION_MINCORE_SYNC_NOT_SYNCED), instrumentation_fetch_and_clear(INSTRUMENTATION_MINCORE_SYNC_NOT_DEALLOCATED), instrumentation_fetch_and_clear(INSTRUMENTATION_MINCORE_ALLOC_FAILED), instrumentation_fetch_and_clear(INSTRUMENTATION_MINCORE_ALLOCATIONS), instrumentation_fetch_and_clear(INSTRUMENTATION_MINCORE_DEALLOCATIONS)); lt_log_print(LOG_INSTRUMENTATION_POLLING, "%" PRIi64 " %" PRIi64 " %" PRIi64 " %" PRIi64 " %" PRIi64 " %" PRIi64 " %" PRIi64 " %" PRIi64 " %" PRIi64 " %" PRIi64, instrumentation_fetch_and_clear(INSTRUMENTATION_POLLING_INTERRUPT_POKE), instrumentation_fetch_and_clear(INSTRUMENTATION_POLLING_INTERRUPT_READ_EVENT), instrumentation_fetch_and_clear(INSTRUMENTATION_POLLING_DO_POLL), instrumentation_fetch_and_clear(INSTRUMENTATION_POLLING_DO_POLL_MAIN), instrumentation_fetch_and_clear(INSTRUMENTATION_POLLING_DO_POLL_DISK), instrumentation_fetch_and_clear(INSTRUMENTATION_POLLING_DO_POLL_OTHERS), instrumentation_fetch_and_clear(INSTRUMENTATION_POLLING_EVENTS), instrumentation_fetch_and_clear(INSTRUMENTATION_POLLING_EVENTS_MAIN), instrumentation_fetch_and_clear(INSTRUMENTATION_POLLING_EVENTS_DISK), instrumentation_fetch_and_clear(INSTRUMENTATION_POLLING_EVENTS_OTHERS)); lt_log_print(LOG_INSTRUMENTATION_TRANSFERS, "%" PRIi64 " %" PRIi64 " %" PRIi64 " %" PRIi64 " %" PRIi64 " %" PRIi64 " %" PRIi64 " %" PRIi64 " %" PRIi64 " %" PRIi64 " %" PRIi64 " %" PRIi64 " %" PRIi64 " %" PRIi64 " %" PRIi64 " %" PRIi64 " %" PRIi64 " %" PRIi64 " %" PRIi64 " %" PRIi64 " %" PRIi64 " %" PRIi64 " %" PRIi64, instrumentation_fetch_and_clear(INSTRUMENTATION_TRANSFER_REQUESTS_DELEGATED), instrumentation_fetch_and_clear(INSTRUMENTATION_TRANSFER_REQUESTS_DOWNLOADING), instrumentation_fetch_and_clear(INSTRUMENTATION_TRANSFER_REQUESTS_FINISHED), instrumentation_fetch_and_clear(INSTRUMENTATION_TRANSFER_REQUESTS_SKIPPED), instrumentation_fetch_and_clear(INSTRUMENTATION_TRANSFER_REQUESTS_UNKNOWN), instrumentation_fetch_and_clear(INSTRUMENTATION_TRANSFER_REQUESTS_UNORDERED), instrumentation_fetch_and_clear(INSTRUMENTATION_TRANSFER_REQUESTS_QUEUED_ADDED), instrumentation_fetch_and_clear(INSTRUMENTATION_TRANSFER_REQUESTS_QUEUED_MOVED), instrumentation_fetch_and_clear(INSTRUMENTATION_TRANSFER_REQUESTS_QUEUED_REMOVED), instrumentation_values[INSTRUMENTATION_TRANSFER_REQUESTS_QUEUED_TOTAL].load(), instrumentation_fetch_and_clear(INSTRUMENTATION_TRANSFER_REQUESTS_UNORDERED_ADDED), instrumentation_fetch_and_clear(INSTRUMENTATION_TRANSFER_REQUESTS_UNORDERED_MOVED), instrumentation_fetch_and_clear(INSTRUMENTATION_TRANSFER_REQUESTS_UNORDERED_REMOVED), instrumentation_values[INSTRUMENTATION_TRANSFER_REQUESTS_UNORDERED_TOTAL].load(), instrumentation_fetch_and_clear(INSTRUMENTATION_TRANSFER_REQUESTS_STALLED_ADDED), instrumentation_fetch_and_clear(INSTRUMENTATION_TRANSFER_REQUESTS_STALLED_MOVED), instrumentation_fetch_and_clear(INSTRUMENTATION_TRANSFER_REQUESTS_STALLED_REMOVED), instrumentation_values[INSTRUMENTATION_TRANSFER_REQUESTS_STALLED_TOTAL].load(), instrumentation_fetch_and_clear(INSTRUMENTATION_TRANSFER_REQUESTS_CHOKED_ADDED), instrumentation_fetch_and_clear(INSTRUMENTATION_TRANSFER_REQUESTS_CHOKED_MOVED), instrumentation_fetch_and_clear(INSTRUMENTATION_TRANSFER_REQUESTS_CHOKED_REMOVED), instrumentation_values[INSTRUMENTATION_TRANSFER_REQUESTS_CHOKED_TOTAL].load(), instrumentation_values[INSTRUMENTATION_TRANSFER_PEER_INFO_UNACCOUNTED].load()); } void instrumentation_reset() { instrumentation_fetch_and_clear(INSTRUMENTATION_MINCORE_INCORE_TOUCHED); instrumentation_fetch_and_clear(INSTRUMENTATION_MINCORE_INCORE_NEW); instrumentation_fetch_and_clear(INSTRUMENTATION_MINCORE_NOT_INCORE_TOUCHED); instrumentation_fetch_and_clear(INSTRUMENTATION_MINCORE_NOT_INCORE_NEW); instrumentation_fetch_and_clear(INSTRUMENTATION_MINCORE_INCORE_BREAK); instrumentation_fetch_and_clear(INSTRUMENTATION_MINCORE_SYNC_SUCCESS); instrumentation_fetch_and_clear(INSTRUMENTATION_MINCORE_SYNC_FAILED); instrumentation_fetch_and_clear(INSTRUMENTATION_MINCORE_SYNC_NOT_SYNCED); instrumentation_fetch_and_clear(INSTRUMENTATION_MINCORE_SYNC_NOT_DEALLOCATED); instrumentation_fetch_and_clear(INSTRUMENTATION_MINCORE_ALLOC_FAILED); instrumentation_fetch_and_clear(INSTRUMENTATION_MINCORE_ALLOCATIONS); instrumentation_fetch_and_clear(INSTRUMENTATION_MINCORE_DEALLOCATIONS); instrumentation_fetch_and_clear(INSTRUMENTATION_POLLING_INTERRUPT_POKE); instrumentation_fetch_and_clear(INSTRUMENTATION_POLLING_INTERRUPT_READ_EVENT); instrumentation_fetch_and_clear(INSTRUMENTATION_POLLING_DO_POLL); instrumentation_fetch_and_clear(INSTRUMENTATION_POLLING_DO_POLL_MAIN); instrumentation_fetch_and_clear(INSTRUMENTATION_POLLING_DO_POLL_DISK); instrumentation_fetch_and_clear(INSTRUMENTATION_POLLING_DO_POLL_OTHERS); instrumentation_fetch_and_clear(INSTRUMENTATION_POLLING_EVENTS); instrumentation_fetch_and_clear(INSTRUMENTATION_POLLING_EVENTS_MAIN); instrumentation_fetch_and_clear(INSTRUMENTATION_POLLING_EVENTS_DISK); instrumentation_fetch_and_clear(INSTRUMENTATION_POLLING_EVENTS_OTHERS); instrumentation_fetch_and_clear(INSTRUMENTATION_TRANSFER_REQUESTS_DELEGATED); instrumentation_fetch_and_clear(INSTRUMENTATION_TRANSFER_REQUESTS_DOWNLOADING); instrumentation_fetch_and_clear(INSTRUMENTATION_TRANSFER_REQUESTS_FINISHED); instrumentation_fetch_and_clear(INSTRUMENTATION_TRANSFER_REQUESTS_SKIPPED); instrumentation_fetch_and_clear(INSTRUMENTATION_TRANSFER_REQUESTS_UNKNOWN); instrumentation_fetch_and_clear(INSTRUMENTATION_TRANSFER_REQUESTS_UNORDERED); instrumentation_fetch_and_clear(INSTRUMENTATION_TRANSFER_REQUESTS_QUEUED_ADDED); instrumentation_fetch_and_clear(INSTRUMENTATION_TRANSFER_REQUESTS_QUEUED_MOVED); instrumentation_fetch_and_clear(INSTRUMENTATION_TRANSFER_REQUESTS_QUEUED_REMOVED); instrumentation_fetch_and_clear(INSTRUMENTATION_TRANSFER_REQUESTS_UNORDERED_ADDED); instrumentation_fetch_and_clear(INSTRUMENTATION_TRANSFER_REQUESTS_UNORDERED_MOVED); instrumentation_fetch_and_clear(INSTRUMENTATION_TRANSFER_REQUESTS_UNORDERED_REMOVED); instrumentation_fetch_and_clear(INSTRUMENTATION_TRANSFER_REQUESTS_STALLED_ADDED); instrumentation_fetch_and_clear(INSTRUMENTATION_TRANSFER_REQUESTS_STALLED_MOVED); instrumentation_fetch_and_clear(INSTRUMENTATION_TRANSFER_REQUESTS_STALLED_REMOVED); instrumentation_fetch_and_clear(INSTRUMENTATION_TRANSFER_REQUESTS_CHOKED_ADDED); instrumentation_fetch_and_clear(INSTRUMENTATION_TRANSFER_REQUESTS_CHOKED_MOVED); instrumentation_fetch_and_clear(INSTRUMENTATION_TRANSFER_REQUESTS_CHOKED_REMOVED); } } // namespace torrent libtorrent-0.16.11/src/utils/queue_buckets.h0000644000000000000000000002371015175073411014446 // libTorrent - BitTorrent library // Copyright (C) 2005-2011, Jari Sundell // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // In addition, as a special exception, the copyright holders give // permission to link the code of portions of this program with the // OpenSSL library under certain conditions as described in each // individual source file, and distribute linked combinations // including the two. // // You must obey the GNU General Public License in all respects for // all of the code used other than OpenSSL. If you modify file(s) // with this exception, you may extend this exception to your version // of the file(s), but you are not obligated to do so. If you do not // wish to do so, delete this exception statement from your version. // If you delete this exception statement from all source files in the // program, then also delete it here. // // Contact: Jari Sundell // // Skomakerveien 33 // 3185 Skoppum, NORWAY #ifndef LIBTORRENT_QUEUE_BUCKETS_H #define LIBTORRENT_QUEUE_BUCKETS_H #include #include #include #include namespace torrent { template class queue_buckets : private std::array, Constants::bucket_count> { public: using queue_type = std::deque; using base_type = std::array; using constants = Constants; using value_type = typename queue_type::value_type; using size_type = typename queue_type::size_type; using difference_type = typename queue_type::difference_type; using iterator = typename queue_type::iterator; using const_iterator = typename queue_type::const_iterator; size_type queue_size(int idx) const { return queue_at(idx).size(); } bool queue_empty(int idx) const { return queue_at(idx).empty(); } bool empty() const; iterator begin(int idx) { return queue_at(idx).begin(); } iterator end(int idx) { return queue_at(idx).end(); } const_iterator begin(int idx) const { return queue_at(idx).begin(); } const_iterator end(int idx) const { return queue_at(idx).end(); } value_type front(int idx) { return queue_at(idx).front(); } value_type back(int idx) { return queue_at(idx).back(); } value_type front(int idx) const { return queue_at(idx).front(); } value_type back(int idx) const { return queue_at(idx).back(); } void pop_front(int idx); void pop_back(int idx); value_type pop_and_front(int idx); value_type pop_and_back(int idx); void push_front(int idx, const value_type& value_type); void push_back(int idx, const value_type& value_type); value_type take(int idx, iterator itr); void clear(int idx); void destroy(int idx, iterator begin, iterator end); void move_to(int src_idx, iterator src_begin, iterator src_end, int dst_idx); void move_all_to(int src_idx, int dst_idx); private: queue_type& queue_at(int idx) { return base_type::operator[](idx); } const queue_type& queue_at(int idx) const { return base_type::operator[](idx); } }; // // Helper methods: // template void queue_bucket_for_all_in_queue(QueueBucket& queues, int idx, Ftor ftor) { std::for_each(queues.begin(idx), queues.end(idx), ftor); } template void queue_bucket_for_all_in_queue(const QueueBucket& queues, int idx, Ftor ftor) { std::for_each(queues.begin(idx), queues.end(idx), ftor); } template inline typename QueueBucket::iterator queue_bucket_find_if_in_queue(QueueBucket& queues, int idx, Ftor ftor) { return std::find_if(queues.begin(idx), queues.end(idx), ftor); } template inline typename QueueBucket::const_iterator queue_bucket_find_if_in_queue(const QueueBucket& queues, int idx, Ftor ftor) { return std::find_if(queues.begin(idx), queues.end(idx), ftor); } template inline std::pair queue_bucket_find_if_in_any(QueueBucket& queues, Ftor ftor) { for (int i = 0; i < QueueBucket::constants::bucket_count; i++) { auto itr = std::find_if(queues.begin(i), queues.end(i), ftor); if (itr != queues.end(i)) return std::make_pair(i, itr); } return std::make_pair(QueueBucket::constants::bucket_count, queues.end(QueueBucket::constants::bucket_count - 1)); } template inline std::pair queue_bucket_find_if_in_any(const QueueBucket& queues, Ftor ftor) { for (int i = 0; i < QueueBucket::constants::bucket_count; i++) { typename QueueBucket::const_iterator itr = std::find_if(queues.begin(i), queues.end(i), ftor); if (itr != queues.end(i)) return std::make_pair(i, itr); } return std::make_pair(QueueBucket::constants::bucket_count, queues.end(QueueBucket::constants::bucket_count - 1)); } // // Implementation: // // TODO: Consider renaming bucket to queue. // TODO: when adding removal/etc of element or ranges do logging on if // it hit the first element or had to search. template inline bool queue_buckets::empty() const { for (int i = 0; i < constants::bucket_count; i++) if (!queue_empty(i)) return false; return true; } template inline void queue_buckets::pop_front(int idx) { queue_at(idx).pop_front(); instrumentation_update(constants::instrumentation_removed[idx], 1); instrumentation_update(constants::instrumentation_total[idx], -1); } template inline void queue_buckets::pop_back(int idx) { queue_at(idx).pop_back(); instrumentation_update(constants::instrumentation_removed[idx], 1); instrumentation_update(constants::instrumentation_total[idx], -1); } template inline typename queue_buckets::value_type queue_buckets::pop_and_front(int idx) { value_type v = queue_at(idx).front(); pop_front(idx); return v; } template inline typename queue_buckets::value_type queue_buckets::pop_and_back(int idx) { value_type v = queue_at(idx).back(); pop_back(idx); return v; } template inline void queue_buckets::push_front(int idx, const value_type& value) { queue_at(idx).push_front(value); instrumentation_update(constants::instrumentation_added[idx], 1); instrumentation_update(constants::instrumentation_total[idx], 1); } template inline void queue_buckets::push_back(int idx, const value_type& value) { queue_at(idx).push_back(value); instrumentation_update(constants::instrumentation_added[idx], 1); instrumentation_update(constants::instrumentation_total[idx], 1); } template inline typename queue_buckets::value_type queue_buckets::take(int idx, iterator itr) { value_type v = *itr; queue_at(idx).erase(itr); instrumentation_update(constants::instrumentation_removed[idx], 1); instrumentation_update(constants::instrumentation_total[idx], -1); // TODO: Add 'taken' instrumentation. return v; } template inline void queue_buckets::clear(int idx) { destroy(idx, begin(idx), end(idx)); } template inline void queue_buckets::destroy(int idx, iterator begin, iterator end) { difference_type difference = std::distance(begin, end); instrumentation_update(constants::instrumentation_removed[idx], difference); instrumentation_update(constants::instrumentation_total[idx], -difference); // Consider moving these to a temporary dequeue before releasing: std::for_each(begin, end, std::function(&constants::template destroy)); queue_at(idx).erase(begin, end); } template inline void queue_buckets::move_to(int src_idx, iterator src_begin, iterator src_end, int dst_idx) { difference_type difference = std::distance(src_begin, src_end); instrumentation_update(constants::instrumentation_moved[src_idx], difference); instrumentation_update(constants::instrumentation_total[src_idx], -difference); instrumentation_update(constants::instrumentation_added[dst_idx], difference); instrumentation_update(constants::instrumentation_total[dst_idx], difference); // TODO: Check for better move operations: if (queue_at(dst_idx).empty() && src_begin == queue_at(src_idx).begin() && src_end == queue_at(src_idx).end()) { queue_at(dst_idx).swap(queue_at(src_idx)); } else { queue_at(dst_idx).insert(queue_at(dst_idx).end(), src_begin, src_end); queue_at(src_idx).erase(src_begin, src_end); } } template inline void queue_buckets::move_all_to(int src_idx, int dst_idx) { move_to(src_idx, queue_at(src_idx).begin(), queue_at(src_idx).end(), dst_idx); } } // namespace torrent #endif // LIBTORRENT_QUEUE_BUCKETS_H libtorrent-0.16.11/src/utils/signal_interrupt.cc0000644000000000000000000000527215175073411015334 #include "config.h" #include "utils/signal_interrupt.h" #include #include #include #include "torrent/exceptions.h" #include "utils/instrumentation.h" namespace torrent { SignalInterrupt::SignalInterrupt(int fd) { m_fileDesc = fd; if (::fcntl(fd, F_SETFL, O_NONBLOCK) == -1) throw internal_error("Could not set non-blocking mode for SignalInterrupt socket: " + std::string(std::strerror(errno))); // Not supported on socketpair on MacOS. (TODO: Check if this is true on other platforms.) // if (!fd_set_tcp_nodelay(fd)) // throw internal_error("Could not set TCP_NODELAY for SignalInterrupt socket: " + std::string(std::strerror(errno))); } SignalInterrupt::~SignalInterrupt() { if (!is_open()) return; ::close(m_fileDesc); m_fileDesc = -1; } SignalInterrupt::pair_type SignalInterrupt::create_pair() { // int fd1, fd2; // TODO: Use pipe instead? // fd_open_socket_pair(fd1, fd2); // fd_open_pipe(fd1, fd2); // Open explicitly here to avoid mock fd_* functions interferring with thread interrupts and // cached_time access during main thread ctor. int fds[2]; if (::socketpair(AF_LOCAL, SOCK_STREAM, 0, fds) == -1) throw internal_error("torrent::fd_open_socket_pair failed: " + std::string(strerror(errno))); pair_type result{new SignalInterrupt(fds[0]), new SignalInterrupt(fds[1])}; result.first->m_other = result.second.get(); result.second->m_other = result.first.get(); return result; } void SignalInterrupt::poke() { bool expected = false; if (!m_other->m_poking.compare_exchange_strong(expected, true)) return; int result = ::send(m_fileDesc, "a", 1, 0); if (result == 0) throw internal_error("Could not send to SignalInterrupt socket, result is 0."); if (result == -1) throw internal_error("Could not send to SignalInterrupt socket: " + std::string(std::strerror(errno))); instrumentation_update(INSTRUMENTATION_POLLING_INTERRUPT_POKE, 1); } const char* SignalInterrupt::type_name() const { return "signal_interrupt"; } void SignalInterrupt::event_read() { char buffer[256]; int result = ::recv(m_fileDesc, buffer, 256, 0); if (result == 0) throw internal_error("SignalInterrupt socket closed."); if (result == -1) throw internal_error("SignalInterrupt socket error: " + std::string(std::strerror(errno))); instrumentation_update(INSTRUMENTATION_POLLING_INTERRUPT_READ_EVENT, 1); m_poking = false; } void SignalInterrupt::event_write() { throw internal_error("SignalInterrupt::event_write() called, but not expected."); } void SignalInterrupt::event_error() { throw internal_error("SignalInterrupt::event_error() called, but not expected."); } } // namespace torrent libtorrent-0.16.11/src/utils/rc4.h0000644000000000000000000000456415175073411012300 // libTorrent - BitTorrent library // Copyright (C) 2005-2011, Jari Sundell // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // In addition, as a special exception, the copyright holders give // permission to link the code of portions of this program with the // OpenSSL library under certain conditions as described in each // individual source file, and distribute linked combinations // including the two. // // You must obey the GNU General Public License in all respects for // all of the code used other than OpenSSL. If you modify file(s) // with this exception, you may extend this exception to your version // of the file(s), but you are not obligated to do so. If you do not // wish to do so, delete this exception statement from your version. // If you delete this exception statement from all source files in the // program, then also delete it here. // // Contact: Jari Sundell // // Skomakerveien 33 // 3185 Skoppum, NORWAY #ifndef LIBTORRENT_RC4_H #define LIBTORRENT_RC4_H #include "config.h" #include namespace torrent { class RC4 { public: RC4() { } #pragma GCC diagnostic ignored "-Wdeprecated-declarations" RC4(const unsigned char key[], int len) { RC4_set_key(&m_key, len, key); } void crypt(const void* indata, void* outdata, unsigned int length) { ::RC4(&m_key, length, static_cast(indata), static_cast(outdata)); } void crypt(void* data, unsigned int length) { ::RC4(&m_key, length, static_cast(data), static_cast(data)); } private: RC4_KEY m_key; }; }; #endif libtorrent-0.16.11/src/utils/diffie_hellman.h0000644000000000000000000000205615175073411014530 #ifndef LIBTORRENT_DIFFIE_HELLMAN_H #define LIBTORRENT_DIFFIE_HELLMAN_H #include "config.h" #include #include namespace torrent { class DiffieHellman { public: using secret_ptr = std::unique_ptr; using dh_ptr = std::unique_ptr; DiffieHellman(const unsigned char prime[], int primeLength, const unsigned char generator[], int generatorLength); ~DiffieHellman() = default; DiffieHellman(const DiffieHellman&) = delete; DiffieHellman& operator=(const DiffieHellman&) = delete; bool is_valid() const; bool compute_secret(const unsigned char pubkey[], unsigned int length); void store_pub_key(unsigned char* dest, unsigned int length); unsigned int size() const { return m_size; } const char* c_str() const { return m_secret.get(); } std::string secret_str() const { return std::string(m_secret.get(), m_size); } private: dh_ptr m_dh; secret_ptr m_secret; int m_size{0}; }; } // namespace torrent #endif libtorrent-0.16.11/src/utils/functional.h0000644000000000000000000000364715175073411013753 #ifndef LIBTORRENT_UTILS_FUNCTIONAL_H #define LIBTORRENT_UTILS_FUNCTIONAL_H #include #include #include namespace utils { // Container must be a list as the entries may be removed during the call. template inline void slot_list_call(const Container& slot_list, Args&&... args) { if (slot_list.empty()) return; auto first = slot_list.begin(); auto next = slot_list.begin(); auto args_tuple = std::forward_as_tuple(std::forward(args)...); while (++next != slot_list.end()) { std::apply(*first, args_tuple); first = next; } std::apply(*first, args_tuple); } // // Count the number of elements from the start of the containers to the first inequal element. // template struct compare_base { bool operator () (const _Value& complete, const _Value& base) const { return !complete.compare(0, base.size(), base); } }; template typename std::iterator_traits<_InputIter1>::difference_type count_base(_InputIter1 __first1, _InputIter1 __last1, _InputIter2 __first2, _InputIter2 __last2) { typename std::iterator_traits<_InputIter1>::difference_type __n = 0; for ( ;__first1 != __last1 && __first2 != __last2; ++__first1, ++__first2, ++__n) if (*__first1 != *__first2) return __n; return __n; } template _Return make_base(_InputIter __first, _InputIter __last, _Ftor __ftor) { if (__first == __last) return ""; _Return __base = __ftor(*__first++); for ( ;__first != __last; ++__first) { auto __pos = count_base(__base.begin(), __base.end(), __ftor(*__first).begin(), __ftor(*__first).end()); if (__pos < (typename std::iterator_traits<_InputIter>::difference_type)__base.size()) __base.resize(__pos); } return __base; } } // namespace utils #endif libtorrent-0.16.11/src/utils/signal_interrupt.h0000644000000000000000000000176515175073411015201 #ifndef LIBTORRENT_UTILS_SIGNAL_INTERRUPT_H #define LIBTORRENT_UTILS_SIGNAL_INTERRUPT_H #include #include #include #include namespace torrent { class LIBTORRENT_EXPORT SignalInterrupt : public Event { public: using pair_type = std::pair, std::unique_ptr>; ~SignalInterrupt() override; static pair_type create_pair(); bool is_poking() const { return m_poking.load(); } void poke(); const char* type_name() const override; void event_read() override; void event_write() override; void event_error() override; private: SignalInterrupt(const SignalInterrupt&) = delete; SignalInterrupt& operator=(const SignalInterrupt&) = delete; SignalInterrupt(int fd); SignalInterrupt* m_other; std::atomic_bool m_poking{false}; }; } // namespace torrent #endif // LIBTORRENT_UTILS_SIGNAL_INTERRUPT_H libtorrent-0.16.11/src/tracker/0000755000000000000000000000000015175073434012006 5libtorrent-0.16.11/src/tracker/tracker_controller.cc0000644000000000000000000004252015175073411016131 #include "config.h" #include "tracker/tracker_controller.h" #include "torrent/exceptions.h" #include "torrent/download_info.h" #include "torrent/utils/log.h" #include "torrent/utils/chrono.h" #include "tracker/tracker_list.h" #define LT_LOG_TRACKER_EVENTS(log_fmt, ...) \ lt_log_print_info(LOG_TRACKER_EVENTS, m_tracker_list->info(), "tracker_controller", log_fmt, __VA_ARGS__); namespace torrent { // End temp hacks... void TrackerController::update_timeout(uint32_t seconds_to_next) { if (!(m_flags & flag_active)) throw internal_error("TrackerController cannot set timeout when inactive."); if (seconds_to_next == 0) { this_thread::scheduler()->update_wait_for(&m_task_timeout, 0s); return; } this_thread::scheduler()->update_wait_for_ceil_seconds(&m_task_timeout, std::chrono::seconds(seconds_to_next)); } inline tracker::TrackerState::event_enum TrackerController::current_send_event() const { switch ((m_flags & mask_send)) { case flag_send_start: return tracker::TrackerState::EVENT_STARTED; case flag_send_stop: return tracker::TrackerState::EVENT_STOPPED; case flag_send_completed: return tracker::TrackerState::EVENT_COMPLETED; case flag_send_update: default: return tracker::TrackerState::EVENT_NONE; } } TrackerController::TrackerController(TrackerList* trackers) : m_tracker_list(trackers) { m_task_timeout.slot() = [this] { do_timeout(); }; m_task_scrape.slot() = [this] { do_scrape(); }; } TrackerController::~TrackerController() { this_thread::scheduler()->erase(&m_task_timeout); this_thread::scheduler()->erase(&m_task_scrape); } bool TrackerController::is_timeout_queued() const { return m_task_timeout.is_scheduled(); } bool TrackerController::is_scrape_queued() const { return m_task_scrape.is_scheduled(); } int64_t TrackerController::next_timeout() const { return m_task_timeout.time().count(); } int64_t TrackerController::next_scrape() const { return m_task_scrape.time().count(); } uint32_t TrackerController::seconds_to_next_timeout() const { auto timeout = m_task_timeout.time() - this_thread::cached_time(); // LT_LOG_TRACKER_EVENTS("seconds_to_next_timeout() : %" PRId64, timeout.count()); if (timeout <= 0s) return 0; // LT_LOG_TRACKER_EVENTS("seconds_to_next_timeout() : %" PRId64, utils::ceil_cast_seconds(timeout).count()); return utils::ceil_cast_seconds(timeout).count(); } uint32_t TrackerController::seconds_to_next_scrape() const { auto timeout = m_task_scrape.time() - this_thread::cached_time(); if (timeout <= 0s) return 0; return utils::ceil_cast_seconds(timeout).count(); } void TrackerController::manual_request([[maybe_unused]] bool request_now) { if (!m_task_timeout.is_scheduled()) return; // Add functions to get the lowest timeout, etc... send_update_event(); } void TrackerController::scrape_request(uint32_t seconds_to_request) { if (seconds_to_request == 0) { this_thread::scheduler()->update_wait_for(&m_task_scrape, 0s); return; } this_thread::scheduler()->update_wait_for_ceil_seconds(&m_task_scrape, std::chrono::seconds(seconds_to_request)); } // The send_*_event() functions tries to ensure the relevant trackers // receive the event. // // When we just want more peers the start_requesting() function is // used. This is all independent of the regular updates sent to the // trackers. void TrackerController::send_start_event() { // This will now be 'lazy', rather than a definite event. We tell // the controller that a 'start' event should be sent, and it will // send it when the tracker controller get's enabled. // If the controller is already running, we insert this new event. // Return, or something, if already active and sending? if (m_flags & flag_send_start) { // Do we just return, or bork? At least we need to check to see // that there's something requesting 'start' event or fail hard. } m_flags &= ~mask_send; m_flags |= flag_send_start; if (!(m_flags & flag_active) || !m_tracker_list->has_usable()) { LT_LOG_TRACKER_EVENTS("sending start event : queued", 0); return; } // Start with requesting from the first tracker. Add timer to // catch when we don't get any response within the first few // seconds, at which point we go promiscious. // Do we use the old 'focus' thing?... Rather react on no reply, // go into promiscious. LT_LOG_TRACKER_EVENTS("sending start event : requesting", 0); close(); // std::any_of(m_tracker_list->begin(), m_tracker_list->end(), [&](tracker::Tracker& tracker) { // if (!tracker.is_usable()) // return false; // m_tracker_list->send_event(tracker, tracker::TrackerState::EVENT_STARTED); // return true; // }); bool found_usable = false; for (auto tracker : *m_tracker_list) { if (!tracker.is_usable()) continue; if (found_usable) { m_flags |= flag_promiscuous_mode; update_timeout(3); break; } m_tracker_list->send_event(tracker, tracker::TrackerState::EVENT_STARTED); found_usable = true; } } void TrackerController::send_stop_event() { if (m_flags & flag_send_stop) { // Do we just return, or bork? At least we need to check to see // that there's something requesting 'start' event or fail hard. } m_flags &= ~mask_send; if (!(m_flags & flag_active) || !m_tracker_list->has_usable()) { LT_LOG_TRACKER_EVENTS("sending stop event : skipped stopped event as no tracker needs it", 0); return; } m_flags |= flag_send_stop; LT_LOG_TRACKER_EVENTS("sending stop event : requesting", 0); close(); for (auto tracker : *m_tracker_list) { if (!tracker.is_in_use()) continue; m_tracker_list->send_event(tracker, tracker::TrackerState::EVENT_STOPPED); } // Timer... } void TrackerController::send_completed_event() { if (m_flags & flag_send_completed) { // Do we just return, or bork? At least we need to check to see // that there's something requesting 'start' event or fail hard. } m_flags &= ~mask_send; m_flags |= flag_send_completed; if (!(m_flags & flag_active) || !m_tracker_list->has_usable()) { LT_LOG_TRACKER_EVENTS("sending completed event : queued", 0); return; } LT_LOG_TRACKER_EVENTS("sending completed event : requesting", 0); close(); for (auto tracker : *m_tracker_list) { if (!tracker.is_in_use()) continue; m_tracker_list->send_event(tracker, tracker::TrackerState::EVENT_COMPLETED); } // Timer... } void TrackerController::send_update_event() { if (!(m_flags & flag_active) || !m_tracker_list->has_usable()) return; if ((m_flags & mask_send) && m_tracker_list->has_active()) return; // We can lose a state here... if (!(m_flags & mask_send)) m_flags |= flag_send_update; LT_LOG_TRACKER_EVENTS("sending update event : requesting", 0); for (auto tracker : *m_tracker_list) { if (!tracker.is_usable()) continue; m_tracker_list->send_event(tracker, tracker::TrackerState::EVENT_NONE); break; } } // Currently being used by send_event, fixme. void TrackerController::close() { m_flags &= ~(flag_requesting | flag_promiscuous_mode); m_tracker_list->close_all(); this_thread::scheduler()->erase(&m_task_timeout); } void TrackerController::enable(int enable_flags) { if ((m_flags & flag_active)) return; // Clearing send stop here in case we cycle disable/enable too // fast. In the future do this based on flags passed. m_flags |= flag_active; m_flags &= ~flag_send_stop; m_tracker_list->close_all_excluding((1 << tracker::TrackerState::EVENT_COMPLETED)); if (!(enable_flags & enable_dont_reset_stats)) m_tracker_list->clear_stats(); LT_LOG_TRACKER_EVENTS("enabled : trackers:%zu", m_tracker_list->size()); // Adding of the tracker requests gets done after the caller has had // a chance to override the default behavior. update_timeout(0); } void TrackerController::disable() { if (!(m_flags & flag_active)) return; // Disable other flags?... m_flags &= ~(flag_active | flag_requesting | flag_promiscuous_mode); m_tracker_list->close_all_excluding((1 << tracker::TrackerState::EVENT_STOPPED) | (1 << tracker::TrackerState::EVENT_COMPLETED)); this_thread::scheduler()->erase(&m_task_timeout); LT_LOG_TRACKER_EVENTS("disabled : trackers:%zu", m_tracker_list->size()); } void TrackerController::start_requesting() { if ((m_flags & flag_requesting)) return; m_flags |= flag_requesting; if ((m_flags & flag_active)) update_timeout(0); LT_LOG_TRACKER_EVENTS("started requesting", 0); } void TrackerController::stop_requesting() { if (!(m_flags & flag_requesting)) return; m_flags &= ~flag_requesting; LT_LOG_TRACKER_EVENTS("stopped requesting", 0); } uint32_t tracker_next_timeout(const tracker::Tracker& tracker, int controller_flags) { if ((controller_flags & TrackerController::flag_requesting)) return tracker_next_timeout_promiscuous(tracker); int32_t activity_time_last; tracker::TrackerState::event_enum latest_event; int32_t normal_interval; tracker.lock_and_call_state([&](const tracker::TrackerState& state) { activity_time_last = state.activity_time_last(); latest_event = state.latest_event(); normal_interval = state.normal_interval(); }); if ((tracker.is_busy() && latest_event != tracker::TrackerState::EVENT_SCRAPE) || !tracker.is_usable()) return ~uint32_t(); if ((controller_flags & TrackerController::flag_promiscuous_mode)) return 0; if ((controller_flags & TrackerController::flag_send_update)) return tracker_next_timeout_update(tracker); // if (tracker.success_counter() == 0 && tracker.failed_counter() == 0) // return 0; int32_t last_activity = this_thread::cached_seconds().count() - activity_time_last; // TODO: Use min interval if we're requesting manual update. return normal_interval - std::min(last_activity, normal_interval); } uint32_t tracker_next_timeout_update(const tracker::Tracker& tracker) { // TODO: Rewrite to be in tracker thread or atomic tracker state. auto tracker_state = tracker.state(); if ((tracker.is_busy() && tracker_state.latest_event() != tracker::TrackerState::EVENT_SCRAPE) || !tracker.is_usable()) return ~uint32_t(); // Make sure we don't request _too_ often, check last activity. // int32_t last_activity = this_thread::cached_seconds().count() - tracker.activity_time_last(); return 0; } uint32_t tracker_next_timeout_promiscuous(const tracker::Tracker& tracker) { // TODO: Rewrite to be in tracker thread or atomic tracker state. auto tracker_state = tracker.state(); if ((tracker.is_busy() && tracker_state.latest_event() != tracker::TrackerState::EVENT_SCRAPE) || !tracker.is_usable()) return ~uint32_t(); int32_t interval; if (tracker_state.failed_counter()) { interval = tracker_state.failed_time_next() - tracker_state.failed_time_last(); } else { interval = tracker_state.normal_interval(); } int32_t min_interval = std::max(tracker_state.min_interval(), uint32_t{300}); int32_t use_interval = std::min(interval, min_interval); int32_t since_last = this_thread::cached_seconds().count() - static_cast(tracker_state.activity_time_last()); lt_log_print(LOG_TRACKER_EVENTS, "tracker_next_timeout_promiscuous: min_interval:%d use_interval:%d since_last:%d", min_interval, use_interval, since_last); return std::max(use_interval - since_last, 0); } static TrackerList::iterator tracker_find_preferred(TrackerList::iterator first, TrackerList::iterator last, uint32_t* next_timeout) { auto preferred = last; uint32_t preferred_time_last = ~uint32_t(); for (; first != last; first++) { uint32_t tracker_timeout = tracker_next_timeout_promiscuous(*first); if (tracker_timeout != 0) { *next_timeout = std::min(tracker_timeout, *next_timeout); continue; } uint32_t activity_time_last; first->lock_and_call_state([&](const tracker::TrackerState& state) { activity_time_last = state.activity_time_last(); }); if (activity_time_last < preferred_time_last) { preferred = first; preferred_time_last = activity_time_last; } } return preferred; } void TrackerController::do_timeout() { this_thread::scheduler()->erase(&m_task_timeout); if (!(m_flags & flag_active) || !m_tracker_list->has_usable()) return; tracker::TrackerState::event_enum send_event = current_send_event(); if ((m_flags & (flag_promiscuous_mode | flag_requesting))) { uint32_t next_timeout = ~uint32_t(); auto itr = m_tracker_list->begin(); while (itr != m_tracker_list->end()) { uint32_t group = itr->group(); if (m_tracker_list->has_active_not_scrape_in_group(group)) { itr = m_tracker_list->end_group(group); continue; } auto group_end = m_tracker_list->end_group(itr->group()); auto preferred = itr; // TODO: Rewrite to be in tracker thread or atomic tracker state. auto tracker_state = itr->state(); if (!itr->is_usable() || tracker_state.failed_counter()) { // The selected tracker in the group is either disabled or not // reachable, try the others to find a new one to use. preferred = tracker_find_preferred(preferred, group_end, &next_timeout); } else { uint32_t tracker_timeout = tracker_next_timeout_promiscuous(*preferred); if (tracker_timeout != 0) { next_timeout = std::min(tracker_timeout, next_timeout); preferred = group_end; } } if (preferred != group_end) m_tracker_list->send_event(*preferred, send_event); itr = group_end; } if (next_timeout != ~uint32_t()) update_timeout(next_timeout); // TODO: Send for start/completed also? } else { auto itr = m_tracker_list->find_next_to_request(m_tracker_list->begin()); if (itr == m_tracker_list->end()) return; // TODO: Rewrite to be in tracker thread or atomic tracker state. auto tracker_state = itr->state(); int32_t next_timeout = tracker_state.activity_time_next(); int32_t cached_seconds = this_thread::cached_seconds().count(); if (next_timeout <= cached_seconds) m_tracker_list->send_event(*itr, send_event); else update_timeout(next_timeout - cached_seconds); } if (m_slot_timeout) m_slot_timeout(); } void TrackerController::do_scrape() { auto itr = m_tracker_list->begin(); while (itr != m_tracker_list->end()) { uint32_t group = itr->group(); if (m_tracker_list->has_active_in_group(group)) { itr = m_tracker_list->end_group(group); continue; } auto group_end = m_tracker_list->end_group(itr->group()); while (itr != group_end) { if (itr->is_scrapable() && itr->is_usable()) { m_tracker_list->send_scrape(*itr); break; } itr++; } itr = group_end; } } uint32_t TrackerController::receive_success(const tracker::Tracker& tracker, TrackerController::address_list* l) { if (!(m_flags & flag_active)) return m_slot_success(l); // if () { m_flags &= ~(mask_send | flag_promiscuous_mode | flag_failure_mode); // } // If we still have active trackers, skip the timeout. // Calculate the next timeout according to a list of in-use // trackers, with the first timeout as the interval. if ((m_flags & flag_requesting)) update_timeout(30); else if (!m_tracker_list->has_active()) { uint32_t normal_interval; tracker.lock_and_call_state([&](const tracker::TrackerState& state) { normal_interval = state.normal_interval(); }); // TODO: Instead find the lowest timeout, correct timeout? update_timeout(normal_interval); } return m_slot_success(l); } void TrackerController::receive_failure(const tracker::Tracker& tracker, const std::string& msg) { if (!(m_flags & flag_active)) { m_slot_failure(msg); return; } // if (tracker == nullptr) { // m_slot_failure(msg); // return; // } int32_t failed_counter; int32_t success_counter; tracker.lock_and_call_state([&](const tracker::TrackerState& state) { failed_counter = state.failed_counter(); success_counter = state.success_counter(); }); if (failed_counter == 1 && success_counter > 0) m_flags |= flag_failure_mode; do_timeout(); m_slot_failure(msg); } void TrackerController::receive_scrape([[maybe_unused]] const tracker::Tracker& tracker) const { if (!(m_flags & flag_active)) { return; } } uint32_t TrackerController::receive_new_peers(address_list* l) { return m_slot_success(l); } void TrackerController::receive_tracker_enabled(const tracker::Tracker& tb) { // TODO: This won't be needed if we rely only on Tracker::m_enable, // rather than a virtual function. if (!m_tracker_list->has_usable()) return; if ((m_flags & flag_active)) { if (!m_task_timeout.is_scheduled() && !m_tracker_list->has_active()) { // TODO: Figure out the proper timeout to use here based on when the // tracker last connected, etc. update_timeout(0); } } if (m_slot_tracker_enabled) m_slot_tracker_enabled(tb); } void TrackerController::receive_tracker_disabled(const tracker::Tracker& tb) { if ((m_flags & flag_active) && !m_task_timeout.is_scheduled()) update_timeout(0); if (m_slot_tracker_disabled) m_slot_tracker_disabled(tb); } } // namespace torrent libtorrent-0.16.11/src/tracker/tracker_worker.h0000644000000000000000000001013515175073411015116 // TrackerWorker is the base class for trackers and should be thread-safe. #ifndef LIBTORRENT_TRACKER_TRACKER_WORKER_H #define LIBTORRENT_TRACKER_TRACKER_WORKER_H #include #include #include #include #include "torrent/common.h" #include "torrent/hash_string.h" #include "torrent/tracker/tracker_state.h" class TrackerTest; namespace torrent { struct TrackerInfo { HashString info_hash{HashString::new_zero()}; HashString obfuscated_hash{HashString::new_zero()}; HashString local_id{HashString::new_zero()}; std::string url; uint32_t key{0}; }; struct TrackerParameters { int32_t numwant{-1}; uint64_t uploaded_adjusted{0}; uint64_t completed_adjusted{0}; uint64_t download_left{0}; }; class TrackerWorker { public: TrackerWorker(TrackerInfo info, int flags = 0); virtual ~TrackerWorker(); // Public members do not require locking: const TrackerInfo& info() const { return m_info; } virtual tracker_enum type() const = 0; virtual std::string lock_and_status() const { return ""; } virtual void send_event(tracker::TrackerState::event_enum state) = 0; virtual void send_scrape() = 0; protected: friend class TrackerList; friend class tracker::Tracker; friend class ::TrackerTest; void lock_and_clear_intervals(); void lock_and_clear_stats(); void lock_and_set_latest_event(tracker::TrackerState::event_enum new_state); void lock() const { m_mutex.lock(); } auto lock_guard() const { return std::scoped_lock(m_mutex); } void unlock() const { m_mutex.unlock(); } // Protected members that require locking: virtual bool is_busy() const = 0; virtual bool is_usable() const { return m_state.is_enabled(); } bool is_busy_not_scrape() const; std::string tracker_id() const { return m_tracker_id; } void set_tracker_id(const std::string& id) { m_tracker_id = id; } uint32_t group() const { return m_group; } void set_group(uint32_t v) { m_group = v; } tracker::TrackerState& state() { return m_state; } const tracker::TrackerState& state() const { return m_state; } // Do not lock when calling these functions/slots: // // TODO: Review, these should be called locked? Yes. // // The slots should put a work order into the tracker controller thread, which will be correctly // ordered as it pertains to a single tracker's slot calls. virtual void close() = 0; std::function m_slot_enabled; std::function m_slot_disabled; std::function m_slot_close; std::function m_slot_success; std::function m_slot_failure; std::function m_slot_scrape_success; std::function m_slot_scrape_failure; std::function m_slot_new_peers; std::function m_slot_parameters; private: TrackerWorker(const TrackerWorker&) = delete; TrackerWorker& operator=(const TrackerWorker&) = delete; mutable std::mutex m_mutex; TrackerInfo m_info; tracker::TrackerState m_state{}; std::string m_tracker_id; uint32_t m_group{0}; }; inline void TrackerWorker::lock_and_clear_intervals() { auto guard = lock_guard(); m_state.clear_intervals(); } inline void TrackerWorker::lock_and_clear_stats() { auto guard = lock_guard(); m_state.clear_stats(); } inline void TrackerWorker::lock_and_set_latest_event(tracker::TrackerState::event_enum new_state) { auto guard = lock_guard(); m_state.m_latest_event = new_state; } inline bool TrackerWorker::is_busy_not_scrape() const { return is_busy() && state().latest_event() != tracker::TrackerState::EVENT_SCRAPE; } } // namespace torrent #endif // LIBTORRENT_TRACKER_TRACKER_WORKER_H libtorrent-0.16.11/src/tracker/tracker_dht.cc0000644000000000000000000001075015175073411014525 #include "config.h" #include "tracker/tracker_dht.h" #include "dht/dht_router.h" #include "manager.h" #include "torrent/exceptions.h" #include "torrent/runtime/network_manager.h" #include "torrent/tracker/dht_controller.h" #include "torrent/utils/log.h" #include "torrent/utils/option_strings.h" #define LT_LOG(log_fmt, ...) \ lt_log_print_hash(LOG_TRACKER_REQUESTS, info().info_hash, "tracker_dht", "%p : " log_fmt, static_cast(this), __VA_ARGS__); namespace torrent { TrackerDht::TrackerDht(const TrackerInfo& info, int flags) : TrackerWorker(info, flags) { if (!runtime::network_manager()->dht_controller()->is_valid()) throw internal_error("Trying to add DHT tracker with no DHT manager."); } TrackerDht::~TrackerDht() { if (m_dht_state != state_idle) runtime::network_manager()->dht_controller()->cancel_announce(NULL, this); } bool TrackerDht::is_allowed() { return runtime::network_manager()->dht_controller()->is_valid(); } bool TrackerDht::is_busy() const { return m_dht_state != state_idle; } bool TrackerDht::is_usable() const { return state().is_enabled() && runtime::network_manager()->dht_controller()->is_active(); } std::string TrackerDht::lock_and_status() const { auto guard = lock_guard(); if (m_dht_state == state_idle) return "[idle]"; return "[" + std::string(states[m_dht_state]) + ": " + std::to_string(m_replied) + "/" + std::to_string(m_contacted) + " nodes replied]"; } void TrackerDht::send_event(tracker::TrackerState::event_enum new_state) { LT_LOG("sending event : state:%s dht_state:%s replied:%d contacted:%d", option_as_string(OPTION_TRACKER_EVENT, new_state), states[m_dht_state], m_replied, m_contacted); close(); if (m_dht_state != state_idle) { runtime::network_manager()->dht_controller()->cancel_announce(&info().info_hash, this); if (m_dht_state != state_idle) throw internal_error("TrackerDht::send_state cancel_announce did not cancel announce."); } lock_and_set_latest_event(new_state); if (new_state == tracker::TrackerState::EVENT_STOPPED) return; m_dht_state = state_searching; if (!runtime::network_manager()->dht_controller()->is_active()) return receive_failed("DHT server not active."); runtime::network_manager()->dht_controller()->announce(info().info_hash, this); state().set_normal_interval(20 * 60); state().set_min_interval(0); } void TrackerDht::send_scrape() { throw internal_error("Tracker type DHT does not support scrape."); } void TrackerDht::close() { LT_LOG("closing event : dht_state:%s replied:%d contacted:%d", states[m_dht_state], m_replied, m_contacted); m_slot_close(); if (m_dht_state != state_idle) runtime::network_manager()->dht_controller()->cancel_announce(&info().info_hash, this); } tracker_enum TrackerDht::type() const { return TRACKER_DHT; } void TrackerDht::receive_peers(raw_list peers) { LT_LOG("received peers : dht_state:%s replied:%d contacted:%d raw_peers_size:%" PRIu32, states[m_dht_state], m_replied, m_contacted, peers.size()); if (m_dht_state == state_idle) throw internal_error("TrackerDht::receive_peers called while not busy."); // The final success event will resend all peers for now. m_peers.parse_address_bencode(peers); AddressList address_list; address_list.parse_address_bencode(peers); m_slot_new_peers(std::move(address_list)); } void TrackerDht::receive_success() { LT_LOG("received success : dht_state:%s replied:%d contacted:%d peers:%zu", states[m_dht_state], m_replied, m_contacted, m_peers.size()); if (m_dht_state == state_idle) throw internal_error("TrackerDht::receive_success called while not busy."); m_dht_state = state_idle; m_slot_success(std::move(m_peers)); } void TrackerDht::receive_failed(const char* msg) { LT_LOG("received failure : dht_state:%s replied:%d contacted:%d msg:%s", states[m_dht_state], m_replied, m_contacted, msg); if (m_dht_state == state_idle) throw internal_error("TrackerDht::receive_failed called while not busy."); m_dht_state = state_idle; m_slot_failure(msg); m_peers.clear(); } void TrackerDht::receive_progress(int replied, int contacted) { LT_LOG("received progress : dht_state:%s replied:%d contacted:%d", states[m_dht_state], replied, contacted); if (m_dht_state == state_idle) throw internal_error("TrackerDht::receive_status called while not busy."); m_replied = replied; m_contacted = contacted; } } // namespace torrent libtorrent-0.16.11/src/tracker/tracker_udp.h0000644000000000000000000000445315175073411014403 #ifndef LIBTORRENT_TRACKER_TRACKER_UDP_H #define LIBTORRENT_TRACKER_TRACKER_UDP_H #include #include #include "net/protocol_buffer.h" #include "net/socket_datagram.h" #include "torrent/net/types.h" #include "torrent/utils/scheduler.h" #include "tracker/tracker_worker.h" namespace torrent { class TrackerUdp : public SocketDatagram, public TrackerWorker { public: using ReadBuffer = ProtocolBuffer<512>; using WriteBuffer = ProtocolBuffer<512>; static constexpr uint64_t magic_connection_id = 0x0000041727101980ll; static constexpr uint32_t udp_timeout = 30; static constexpr uint32_t udp_tries = 2; TrackerUdp(const TrackerInfo& info, int flags = 0); ~TrackerUdp() override; const char* type_name() const override { return "tracker_udp"; } bool is_busy() const override; void send_event(tracker::TrackerState::event_enum new_state) override; void send_scrape() override; void close() override; tracker_enum type() const override; void event_read() override; void event_write() override; void event_error() override; private: void close_directly(); void receive_failed(const std::string& msg); void receive_resolved(c_sin_shared_ptr& sin, int err, c_sin6_shared_ptr& sin6, int err6); void receive_timeout(); void start_announce(); void prepare_connect_input(); void prepare_announce_input(); bool process_connect_output(); bool process_announce_output(); bool process_error_output(); bool m_resolver_requesting{}; bool m_sending_announce{}; sockaddr* m_current_address{}; sin_unique_ptr m_inet_address; sin6_unique_ptr m_inet6_address; int m_port{}; int m_send_state{}; uint32_t m_action{}; uint64_t m_connection_id{}; uint32_t m_transaction_id{}; std::unique_ptr m_read_buffer; std::unique_ptr m_write_buffer; uint32_t m_tries{}; utils::SchedulerEntry m_task_timeout; }; } // namespace torrent #endif libtorrent-0.16.11/src/tracker/tracker_controller.h0000644000000000000000000001070415175073411015772 #ifndef LIBTORRENT_TRACKER_CONTROLLER_H #define LIBTORRENT_TRACKER_CONTROLLER_H #include #include #include "torrent/tracker/tracker_state.h" #include "torrent/utils/scheduler.h" // TODO: Remove all unused functions and slots, move to src/tracker. Then add a // TrackerControllerWrapper that download and api uses. namespace torrent { class TrackerController { public: using address_list = AddressList; using slot_void = std::function; using slot_string = std::function; using slot_address_list = std::function; using slot_tracker = std::function; static constexpr int flag_send_update = 0x1; static constexpr int flag_send_completed = 0x2; static constexpr int flag_send_start = 0x4; static constexpr int flag_send_stop = 0x8; static constexpr int flag_active = 0x10; static constexpr int flag_requesting = 0x20; static constexpr int flag_failure_mode = 0x40; static constexpr int flag_promiscuous_mode = 0x80; static constexpr int mask_send = flag_send_update | flag_send_start | flag_send_stop | flag_send_completed; static constexpr int enable_dont_reset_stats = 0x1; TrackerController(TrackerList* trackers); ~TrackerController(); int flags() const { return m_flags; } bool is_active() const { return m_flags & flag_active; } bool is_requesting() const { return m_flags & flag_requesting; } bool is_failure_mode() const { return m_flags & flag_failure_mode; } bool is_promiscuous_mode() const { return m_flags & flag_promiscuous_mode; } bool is_timeout_queued() const; bool is_scrape_queued() const; TrackerList* tracker_list() { return m_tracker_list; } TrackerList* tracker_list() const { return m_tracker_list; } int64_t next_timeout() const; int64_t next_scrape() const; uint32_t seconds_to_next_timeout() const; uint32_t seconds_to_next_scrape() const; void manual_request(bool request_now); void scrape_request(uint32_t seconds_to_request); void send_start_event(); void send_stop_event(); void send_completed_event(); void send_update_event(); void close(); void enable(int enable_flags = 0); void disable(); void start_requesting(); void stop_requesting(); uint32_t receive_success(const tracker::Tracker& tracker, address_list* l); void receive_failure(const tracker::Tracker& tracker, const std::string& msg); void receive_scrape(const tracker::Tracker& tracker) const; uint32_t receive_new_peers(address_list* l); void receive_tracker_enabled(const tracker::Tracker& tb); void receive_tracker_disabled(const tracker::Tracker& tb); slot_void& slot_timeout() { return m_slot_timeout; } slot_address_list& slot_success() { return m_slot_success; } slot_string& slot_failure() { return m_slot_failure; } slot_tracker& slot_tracker_enabled() { return m_slot_tracker_enabled; } slot_tracker& slot_tracker_disabled() { return m_slot_tracker_disabled; } private: TrackerController(const TrackerController&) = delete; TrackerController& operator=(const TrackerController&) = delete; void do_timeout(); void do_scrape(); void update_timeout(uint32_t seconds_to_next); inline tracker::TrackerState::event_enum current_send_event() const; int m_flags{0}; TrackerList* m_tracker_list; slot_void m_slot_timeout; slot_address_list m_slot_success; slot_string m_slot_failure; slot_tracker m_slot_tracker_enabled; slot_tracker m_slot_tracker_disabled; utils::SchedulerEntry m_task_timeout; utils::SchedulerEntry m_task_scrape; }; uint32_t tracker_next_timeout(const tracker::Tracker& tracker, int controller_flags); uint32_t tracker_next_timeout_update(const tracker::Tracker& tracker); uint32_t tracker_next_timeout_promiscuous(const tracker::Tracker& tracker); } // namespace torrent #endif libtorrent-0.16.11/src/tracker/tracker_udp.cc0000644000000000000000000003525415175073411014544 #include "config.h" #include "tracker_udp.h" #include #include #include "manager.h" #include "net/address_list.h" #include "torrent/connection_manager.h" #include "torrent/net/fd.h" #include "torrent/net/network_config.h" #include "torrent/net/resolver.h" #include "torrent/net/socket_address.h" #include "torrent/runtime/socket_manager.h" #include "torrent/utils/log.h" #include "torrent/utils/option_strings.h" #define LT_LOG(log_fmt, ...) \ lt_log_print_hash(LOG_TRACKER_REQUESTS, info().info_hash, "tracker_udp", "%p : " log_fmt, static_cast(this), __VA_ARGS__); #define LT_LOG_DUMP(log_dump_data, log_dump_size, log_fmt, ...) \ lt_log_print_hash_dump(LOG_TRACKER_DUMP, log_dump_data, log_dump_size, info().info_hash, \ "tracker_udp", "%p : " log_fmt, static_cast(this), __VA_ARGS__); namespace torrent { // TODO: Rewrite this to do resolve every time, since we now have a cache? // TODO: Add UDP listening socket used by all UDP trackers, make it handle retries and timeouts. It waits for reply. TrackerUdp::TrackerUdp(const TrackerInfo& info, int flags) : TrackerWorker(info, flags) { m_task_timeout.slot() = [this] { receive_timeout(); }; } TrackerUdp::~TrackerUdp() { close_directly(); } bool TrackerUdp::is_busy() const { return is_open(); } void TrackerUdp::send_event(tracker::TrackerState::event_enum new_state) { LT_LOG("sending event : state:%s url:%s", option_as_string(OPTION_TRACKER_EVENT, new_state), info().url.c_str()); // TODO: Don't close fd for every new request. close_directly(); auto [hostname, port] = net::parse_uri_host_port(info().url); if (hostname.empty()) return receive_failed("could not parse hostname from url"); if (port == 0) return receive_failed("could not parse port from url"); lock_and_set_latest_event(new_state); m_port = port; m_send_state = new_state; m_sending_announce = true; LT_LOG("resolving hostname : address:%s", hostname.data()); // TODO: Also check failed counter.... // TODO: Check for changes to block (NC should instead clear us on network changes) int family = AF_UNSPEC; bool block_ipv4 = config::network_config()->is_block_ipv4(); bool block_ipv6 = config::network_config()->is_block_ipv6(); if (block_ipv4 && block_ipv6) return receive_failed("cannot send tracker event, both IPv4 and IPv6 are blocked"); else if (block_ipv4) family = AF_INET6; else if (block_ipv6) family = AF_INET; m_resolver_requesting = true; auto fn = [this](c_sin_shared_ptr sin, int err, c_sin6_shared_ptr sin6, int err6) { receive_resolved(sin, err, sin6, err6); }; // Currently discarding SOCK_DGRAM filter. this_thread::resolver()->resolve_both(static_cast(this), hostname.data(), family, std::move(fn)); } void TrackerUdp::send_scrape() { throw internal_error("Tracker type UDP does not support scrape."); } // TODO: Controller should not need to close the tracker when starting a new request. void TrackerUdp::close() { LT_LOG("closing event : state:%s url:%s", option_as_string(OPTION_TRACKER_EVENT, state().latest_event()), info().url.c_str()); close_directly(); } void TrackerUdp::close_directly() { LT_LOG("closing directly : state:%s url:%s", option_as_string(OPTION_TRACKER_EVENT, state().latest_event()), info().url.c_str()); m_slot_close(); this_thread::resolver()->cancel(static_cast(this)); this_thread::scheduler()->erase(&m_task_timeout); m_resolver_requesting = false; m_sending_announce = false; m_read_buffer.reset(); m_write_buffer.reset(); if (!is_open()) return; runtime::socket_manager()->close_event_or_throw(this, [this]() { this_thread::event_remove_and_close(this); fd_close(file_descriptor()); set_file_descriptor(-1); }); } tracker_enum TrackerUdp::type() const { return TRACKER_UDP; } void TrackerUdp::receive_failed(const std::string& msg) { LT_LOG("received failure : hostname:%s port:%u msg:'%s'", sa_pretty_str(m_current_address).c_str(), m_port, msg.c_str()); close_directly(); m_slot_failure(msg); } void TrackerUdp::receive_resolved(c_sin_shared_ptr& sin, int err, c_sin6_shared_ptr& sin6, int err6) { if (std::this_thread::get_id() != torrent::main_thread::thread_id()) throw internal_error("TrackerUdp::receive_resolved() called from a different thread."); LT_LOG("received resolved", 0); if (!m_resolver_requesting) throw internal_error("TrackerUdp::receive_resolved() called but m_resolver_requesting is false."); m_resolver_requesting = false; if (err != 0 && err6 != 0) { // TODO: Replace with error codes. LT_LOG("could not resolve hostname : sin_error:'%s' sin6_error:'%s'", gai_strerror(err), gai_strerror(err6)); return receive_failed("could not resolve hostname : sin_error:'" + std::string(gai_strerror(err)) + "' sin6_error:'" + std::string(gai_strerror(err6)) + "'"); } m_inet_address = nullptr; m_inet6_address = nullptr; if (sin != nullptr) { m_inet_address = sin_copy(sin.get()); sa_set_port(reinterpret_cast(m_inet_address.get()), m_port); } if (sin6 != nullptr) { m_inet6_address = sin6_copy(sin6.get()); sa_set_port(reinterpret_cast(m_inet6_address.get()), m_port); } start_announce(); } void TrackerUdp::receive_timeout() { if (m_task_timeout.is_scheduled()) throw internal_error("TrackerUdp::receive_timeout() called but m_task_timeout is still scheduled."); if (--m_tries == 0) { receive_failed("unable to connect to UDP tracker"); return; } this_thread::scheduler()->wait_for_ceil_seconds(&m_task_timeout, std::chrono::seconds(udp_timeout)); this_thread::event_insert_write(this); } void TrackerUdp::start_announce() { if (!m_sending_announce) throw internal_error("TrackerUdp::start_announce() called but m_sending_announce is false."); if (is_open()) throw internal_error("TrackerUdp::start_announce() called but m_fileDesc is already open."); m_sending_announce = false; c_sa_shared_ptr bind_address; // TODO: This does not properly handle blocked protocols. if (m_inet_address != nullptr && m_inet6_address != nullptr) { bind_address = config::network_config()->bind_address_or_any_and_null(); if (bind_address != nullptr) { if (bind_address->sa_family == AF_INET6) m_current_address = reinterpret_cast(m_inet6_address.get()); else m_current_address = reinterpret_cast(m_inet_address.get()); } } else if (m_inet_address != nullptr) { bind_address = config::network_config()->bind_address_for_connect(AF_INET); m_current_address = reinterpret_cast(m_inet_address.get()); } else if (m_inet6_address != nullptr) { bind_address = config::network_config()->bind_address_for_connect(AF_INET6); m_current_address = reinterpret_cast(m_inet6_address.get()); } else { throw internal_error("TrackerUdp::start_announce() called but both m_inet_address and m_inet6_address are nullptr."); } if (bind_address == nullptr) { LT_LOG("could not create outgoing connection: blocked or invalid bind address", 0); return receive_failed("could not create outgoing connection: blocked or invalid bind address"); } if (bind_address->sa_family != m_current_address->sa_family) throw internal_error("TrackerUdp::start_announce() bind address family does not match connect address family."); // TODO: Properly handle retry with failover to other protocol, and check prefer_ipv6. LT_LOG("starting announce : connect_address:%s bind_address:%s", sa_pretty_str(m_current_address).c_str(), sa_pretty_str(bind_address.get()).c_str()); auto open_fd = [this, &bind_address]() { int fd = fd_open_family(fd_flag_datagram | fd_flag_nonblock, bind_address->sa_family); if (fd == -1) return; set_file_descriptor(fd); // TODO: Add socket counting. this_thread::event_open(this); this_thread::event_insert_read(this); this_thread::event_insert_write(this); this_thread::event_insert_error(this); }; auto cleanup_func = [this]() { if (!is_open()) { LT_LOG("failed to open UDP socket : open failed", 0); return; } LT_LOG("failed to open UDP socket : socket manager triggered cleanup", 0); this_thread::event_remove_and_close(this); fd_close(file_descriptor()); set_file_descriptor(-1); }; runtime::socket_manager()->open_event_or_cleanup(this, open_fd, cleanup_func); if (!is_open()) { LT_LOG("could not open UDP socket: fd:%i error:'%s'", m_fileDesc, std::strerror(errno)); return receive_failed("could not open UDP socket: " + std::string(std::strerror(errno))); } if (!sa_is_any(bind_address.get()) && !fd_bind(m_fileDesc, bind_address.get())) { auto pretty_addr = sa_pretty_str(bind_address.get()); auto error_str = std::strerror(errno); LT_LOG("failed to bind socket to udp address : address:%s error:'%s'", pretty_addr.c_str(), error_str); return receive_failed("failed to bind socket to udp address '" + pretty_addr + "' with error '" + error_str + "'"); } m_read_buffer = std::make_unique(); m_write_buffer = std::make_unique(); prepare_connect_input(); m_tries = udp_tries; this_thread::scheduler()->wait_for_ceil_seconds(&m_task_timeout, std::chrono::seconds(udp_timeout)); } void TrackerUdp::event_read() { auto read_size = read_datagram(m_read_buffer->begin(), m_read_buffer->reserved()); if (read_size < 0) return; m_read_buffer->reset_position(); m_read_buffer->set_end(read_size); LT_LOG("received reply : size:%d", read_size); LT_LOG_DUMP(reinterpret_cast(m_read_buffer->begin()), read_size, "received reply", 0); if (read_size < 4) return; // Do something with the content here. switch (m_read_buffer->read_32()) { case 0: if (m_action != 0 || !process_connect_output()) return; prepare_announce_input(); this_thread::scheduler()->update_wait_for_ceil_seconds(&m_task_timeout, std::chrono::seconds(udp_timeout)); m_tries = udp_tries; this_thread::event_insert_write(this); return; case 1: if (m_action != 1 || !process_announce_output()) return; return; case 3: if (!process_error_output()) return; return; default: return; } } void TrackerUdp::event_write() { if (m_write_buffer->size_end() == 0) throw internal_error("TrackerUdp::write() called but the write buffer is empty."); [[maybe_unused]] int s = write_datagram_sa(m_write_buffer->begin(), m_write_buffer->size_end(), m_current_address); this_thread::event_remove_write(this); } void TrackerUdp::event_error() { } void TrackerUdp::prepare_connect_input() { m_write_buffer->reset(); m_write_buffer->write_64(m_connection_id = magic_connection_id); m_write_buffer->write_32(m_action = 0); m_write_buffer->write_32(m_transaction_id = random()); LT_LOG_DUMP(m_write_buffer->begin(), m_write_buffer->size_end(), "prepare connect (id:%" PRIx32 ")", m_transaction_id); } void TrackerUdp::prepare_announce_input() { m_write_buffer->reset(); m_write_buffer->write_64(m_connection_id); m_write_buffer->write_32(m_action = 1); m_write_buffer->write_32(m_transaction_id = random()); m_write_buffer->write_range(info().info_hash.begin(), info().info_hash.end()); m_write_buffer->write_range(info().local_id.begin(), info().local_id.end()); auto parameters = m_slot_parameters(); m_write_buffer->write_64(parameters.completed_adjusted); m_write_buffer->write_64(parameters.download_left); m_write_buffer->write_64(parameters.uploaded_adjusted); m_write_buffer->write_32(m_send_state); auto local_address = config::network_config()->local_inet_address(); if (local_address->sa_family == AF_INET) m_write_buffer->write_32_n(reinterpret_cast(local_address.get())->sin_addr.s_addr); else m_write_buffer->write_32_n(0); m_write_buffer->write_32(info().key); m_write_buffer->write_32(parameters.numwant); m_write_buffer->write_16(runtime::listen_port()); if (m_write_buffer->size_end() != 98) throw internal_error("TrackerUdp::prepare_announce_input() ended up with the wrong size"); LT_LOG_DUMP(m_write_buffer->begin(), m_write_buffer->size_end(), "prepare announce (state:%s id:%" PRIx32 " up_adj:%" PRIu64 " completed_adj:%" PRIu64 " left_adj:%" PRIu64 ")", option_as_string(OPTION_TRACKER_EVENT, m_send_state), m_transaction_id, parameters.uploaded_adjusted, parameters.completed_adjusted, parameters.download_left); } bool TrackerUdp::process_connect_output() { if (m_read_buffer->size_end() < 16 || m_read_buffer->read_32() != m_transaction_id) return false; m_connection_id = m_read_buffer->read_64(); return true; } bool TrackerUdp::process_announce_output() { if (m_read_buffer->size_end() < 20 || m_read_buffer->read_32() != m_transaction_id) return false; { auto guard = lock_guard(); state().set_normal_interval(m_read_buffer->read_32()); state().set_min_interval(tracker::TrackerState::default_min_interval); state().m_scrape_incomplete = m_read_buffer->read_32(); // leechers state().m_scrape_complete = m_read_buffer->read_32(); // seeders state().m_scrape_time_last = this_thread::cached_seconds().count(); } AddressList l; // TODO: This might not handle IPv4-mapped IPv6 addresses correctly. switch (m_current_address->sa_family) { case AF_INET: std::copy(reinterpret_cast(m_read_buffer->position()), reinterpret_cast(m_read_buffer->end() - m_read_buffer->remaining() % sizeof(SocketAddressCompact)), std::back_inserter(l)); break; case AF_INET6: std::copy(reinterpret_cast(m_read_buffer->position()), reinterpret_cast(m_read_buffer->end() - m_read_buffer->remaining() % sizeof(SocketAddressCompact6)), std::back_inserter(l)); break; default: throw internal_error("TrackerUdp::process_announce_output() m_current_address is not inet or inet6."); } // Some logic here to decided on whetever we're going to close the // connection or not? close_directly(); m_slot_success(std::move(l)); return true; } bool TrackerUdp::process_error_output() { if (m_read_buffer->size_end() < 8 || m_read_buffer->read_32() != m_transaction_id) return false; receive_failed("received error message: " + std::string(m_read_buffer->position(), m_read_buffer->end())); return true; } } // namespace torrent libtorrent-0.16.11/src/tracker/tracker_http.cc0000644000000000000000000003473715175073411014740 #include "config.h" #include "tracker/tracker_http.h" #include #include #include #include "net/address_list.h" #include "torrent/connection_manager.h" #include "torrent/exceptions.h" #include "torrent/net/http_stack.h" #include "torrent/net/network_config.h" #include "torrent/net/socket_address.h" #include "torrent/object_stream.h" #include "torrent/utils/log.h" #include "torrent/utils/option_strings.h" #include "torrent/utils/string_manip.h" #include "torrent/utils/uri_parser.h" #include "manager.h" #define LT_LOG(log_fmt, ...) \ lt_log_print_hash(LOG_TRACKER_REQUESTS, info().info_hash, "tracker_http", "%p : " log_fmt, static_cast(this), __VA_ARGS__); #define LT_LOG_DUMP(log_dump_data, log_dump_size, log_fmt, ...) \ lt_log_print_hash_dump(LOG_TRACKER_DUMP, log_dump_data, log_dump_size, info().info_hash, \ "tracker_http", "%p : " log_fmt, static_cast(this), __VA_ARGS__); namespace torrent { TrackerHttp::TrackerHttp(const TrackerInfo& info, int flags) : TrackerWorker(info, utils::uri_can_scrape(info.url) ? (flags | tracker::TrackerState::flag_scrapable) : flags), m_drop_deliminator(utils::uri_has_query(info.url)) { m_get.reset(info.url, nullptr); m_get.add_done_slot([this] { receive_done(); }); m_get.add_failed_slot([this](const auto& str) { receive_signal_failed(str); }); m_delay_scrape.slot() = [this] { delayed_send_scrape(); }; } TrackerHttp::~TrackerHttp() { close_directly(); this_thread::scheduler()->erase(&m_delay_scrape); } tracker_enum TrackerHttp::type() const { return TRACKER_HTTP; } bool TrackerHttp::is_busy() const { return m_data != nullptr; } void TrackerHttp::send_event(tracker::TrackerState::event_enum new_state) { LT_LOG("sending event : state:%s url:%s", option_as_string(OPTION_TRACKER_EVENT, new_state), info().url.c_str()); close_directly(); this_thread::scheduler()->erase(&m_delay_scrape); lock_and_set_latest_event(new_state); // TODO: Move to network config and add simple retry other AF logic. // TODO: We need to handle retry logic here, not in http stack, as we need to change the bind // address? Or is this handled by the http stack? // // TODO: We need to include ipv4/ipv6 param in tracker requests if we bind to the other, so it // needs to be handled here. bool is_block_ipv4 = config::network_config()->is_block_ipv4(); bool is_block_ipv6 = config::network_config()->is_block_ipv6(); bool is_prefer_ipv6 = config::network_config()->is_prefer_ipv6(); int family{}; // If both IPv4 and IPv6 are blocked, we cannot send the request. // // TODO: Properly handle this case without throwing an error. if (is_block_ipv4 && is_block_ipv6) { throw torrent::internal_error("Cannot send tracker event, both IPv4 and IPv6 are blocked."); } else if (is_block_ipv4) { family = AF_INET6; } else if (is_block_ipv6) { family = AF_INET; } else if (is_prefer_ipv6) { family = AF_INET6; } else { family = AF_INET; } auto params = m_slot_parameters(); auto request_url = request_announce_url(new_state, params, family); m_data = std::make_unique(); m_get.try_wait_for_close(); m_get.reset(request_url, m_data); // TODO: Should bind address here... if (is_block_ipv4 && is_block_ipv6) { throw torrent::internal_error("Cannot send tracker event, both IPv4 and IPv6 are blocked."); } else if (is_block_ipv4) { m_get.use_ipv6(); } else if (is_block_ipv6) { m_get.use_ipv4(); } else if (is_prefer_ipv6) { m_get.prefer_ipv6(); } else { m_get.prefer_ipv4(); } LT_LOG_DUMP(request_url.c_str(), request_url.size(), "sending event : state:%s up_adj:%" PRIu64 " completed_adj:%" PRIu64 " left_adj:%" PRIu64, option_as_string(OPTION_TRACKER_EVENT, new_state), params.uploaded_adjusted, params.completed_adjusted, params.download_left); torrent::net_thread::http_stack()->start_get(m_get); } void TrackerHttp::send_scrape() { if (m_requested_scrape) { LT_LOG("scrape already requested : url:%s", info().url.c_str()); return; } m_requested_scrape = true; if (is_busy()) { LT_LOG("scrape requested, but tracker is busy : url:%s", info().url.c_str()); return; } LT_LOG("scrape requested : url:%s", info().url.c_str()); this_thread::scheduler()->update_wait_for_ceil_seconds(&m_delay_scrape, 10s); } void TrackerHttp::request_prefix(std::stringstream* stream, const std::string& url) { *stream << url << (m_drop_deliminator ? '&' : '?') << "info_hash=" << utils::copy_escape_html_str(info().info_hash); } std::string TrackerHttp::request_announce_url(tracker::TrackerState::event_enum state, TrackerParameters params, int family) { std::stringstream s; s.imbue(std::locale::classic()); auto tracker_id = this->tracker_id(); auto local_id = utils::copy_escape_html_str(info().local_id); request_prefix(&s, info().url); s << "&peer_id=" << local_id << "&compact=1"; if (info().key) s << "&key=" << std::hex << std::setw(8) << std::setfill('0') << info().key << std::dec; if (!tracker_id.empty()) s << "&trackerid=" << utils::copy_escape_html_str(tracker_id); auto local_inet_address = config::network_config()->local_inet_address_or_null(); auto local_inet6_address = config::network_config()->local_inet6_address_or_null(); if (local_inet_address != nullptr) { if (family == AF_INET6) s << "&ip=" << sa_addr_str(local_inet_address.get()); s << "&ipv4=" << sa_addr_str(local_inet_address.get()); } if (local_inet6_address != nullptr) { if (family == AF_INET) s << "&ip=" << sa_addr_str(local_inet6_address.get()); s << "&ipv6=" << sa_addr_str(local_inet6_address.get()); } if (params.numwant >= 0 && state != tracker::TrackerState::EVENT_STOPPED) s << "&numwant=" << params.numwant; s << "&port=" << runtime::listen_port() << "&uploaded=" << params.uploaded_adjusted << "&downloaded=" << params.completed_adjusted << "&left=" << params.download_left; switch (state) { case tracker::TrackerState::EVENT_STARTED: s << "&event=started"; break; case tracker::TrackerState::EVENT_STOPPED: s << "&event=stopped"; break; case tracker::TrackerState::EVENT_COMPLETED: s << "&event=completed"; break; default: break; } return s.str(); } // We delay scrape for 10 seconds after any tracker activity to ensure all callbacks are process // before starting. void TrackerHttp::delayed_send_scrape() { if (is_busy()) throw internal_error("TrackerHttp::delayed_send_scrape() called while busy"); LT_LOG("sending delayed scrape request : url:%s", info().url.c_str()); close_directly(); lock_and_set_latest_event(tracker::TrackerState::EVENT_SCRAPE); std::stringstream s; s.imbue(std::locale::classic()); request_prefix(&s, utils::uri_generate_scrape_url(info().url)); std::string request_url = s.str(); m_data = std::make_unique(); m_get.try_wait_for_close(); m_get.reset(request_url, m_data); LT_LOG_DUMP(request_url.c_str(), request_url.size(), "tracker scrape", 0); torrent::net_thread::http_stack()->start_get(m_get); } void TrackerHttp::close() { LT_LOG("closing event : state:%s url:%s", option_as_string(OPTION_TRACKER_EVENT, state().latest_event()), info().url.c_str()); this_thread::scheduler()->erase(&m_delay_scrape); m_requested_scrape = false; close_directly(); } void TrackerHttp::close_directly() { if (m_data == nullptr) { LT_LOG("closing directly (already closed) : state:%s url:%s", option_as_string(OPTION_TRACKER_EVENT, state().latest_event()), info().url.c_str()); m_slot_close(); return; } LT_LOG("closing directly : state:%s url:%s", option_as_string(OPTION_TRACKER_EVENT, state().latest_event()), info().url.c_str()); m_slot_close(); m_get.close_and_cancel_callbacks(this_thread::thread()); m_data.reset(); } void TrackerHttp::receive_done() { if (m_data == nullptr) throw internal_error("TrackerHttp::receive_done() called on an invalid object"); LT_LOG("received reply", 0); if (lt_log_is_valid(LOG_TRACKER_DUMP)) { std::string dump = m_data->str(); LT_LOG_DUMP(dump.c_str(), dump.size(), "tracker reply", 0); } Object b; *m_data >> b; // Temporarily reset the interval // // TODO: This might be causing an issue with too frequent tracker requests. lock_and_clear_intervals(); if (m_data->fail()) { auto dump = utils::sanitize_string_with_tags(m_data->str()); if (dump.empty()) return receive_failed("Could not parse bencoded data, empty reply"); return receive_failed("Could not parse bencoded data: " + dump.substr(0,99)); } if (!b.is_map()) return receive_failed("Root not a bencoded map"); if (b.has_key("failure reason")) { if (state().latest_event() != tracker::TrackerState::EVENT_SCRAPE) process_failure(b); return receive_failed("Failure reason \"" + (b.get_key("failure reason").is_string() ? b.get_key_string("failure reason") : std::string("failure reason not a string")) + "\""); } // If no failures, set intervals to defaults prior to processing if (state().latest_event() == tracker::TrackerState::EVENT_SCRAPE) { m_requested_scrape = false; process_scrape(b); return; } process_success(b); if (m_requested_scrape && !is_busy()) this_thread::scheduler()->update_wait_for_ceil_seconds(&m_delay_scrape, 10s); } void TrackerHttp::receive_signal_failed(const std::string& msg) { lock_and_clear_intervals(); return receive_failed(msg); } void TrackerHttp::receive_failed(const std::string& msg) { if (m_data == nullptr) throw internal_error("TrackerHttp::receive_failed() called on an invalid object"); LT_LOG("received failure : msg:%s", msg.c_str()); if (lt_log_is_valid(LOG_TRACKER_DUMP)) { std::string dump = m_data->str(); LT_LOG_DUMP(dump.c_str(), dump.size(), "received failure", 0); } close_directly(); if (state().latest_event() == tracker::TrackerState::EVENT_SCRAPE) { m_requested_scrape = false; m_slot_scrape_failure(msg); return; } m_slot_failure(msg); if (m_requested_scrape && !is_busy()) this_thread::scheduler()->wait_for_ceil_seconds(&m_delay_scrape, 10s); } void TrackerHttp::process_failure(const Object& object) { auto guard = lock_guard(); if (object.has_key_string("tracker id")) update_tracker_id(object.get_key_string("tracker id")); if (object.has_key_value("interval")) state().set_normal_interval(object.get_key_value("interval")); if (object.has_key_value("min interval")) state().set_min_interval(object.get_key_value("min interval")); if (object.has_key_value("complete") && object.has_key_value("incomplete")) { state().m_scrape_complete = std::max(object.get_key_value("complete"), 0); state().m_scrape_incomplete = std::max(object.get_key_value("incomplete"), 0); state().m_scrape_time_last = this_thread::cached_seconds().count(); } if (object.has_key_value("downloaded")) state().m_scrape_downloaded = std::max(object.get_key_value("downloaded"), 0); } void TrackerHttp::process_success(const Object& object) { { auto guard = lock_guard(); if (object.has_key_string("tracker id")) update_tracker_id(object.get_key_string("tracker id")); if (object.has_key_value("interval")) state().set_normal_interval(object.get_key_value("interval")); else state().set_normal_interval(tracker::TrackerState::default_normal_interval); if (object.has_key_value("min interval")) state().set_min_interval(object.get_key_value("min interval")); else state().set_min_interval(tracker::TrackerState::default_min_interval); if (object.has_key_value("complete") && object.has_key_value("incomplete")) { state().m_scrape_complete = std::max(object.get_key_value("complete"), 0); state().m_scrape_incomplete = std::max(object.get_key_value("incomplete"), 0); state().m_scrape_time_last = this_thread::cached_seconds().count(); } if (object.has_key_value("downloaded")) state().m_scrape_downloaded = std::max(object.get_key_value("downloaded"), 0); } if (!object.has_key("peers") && !object.has_key("peers6")) { if (state().latest_event() != tracker::TrackerState::EVENT_STOPPED) return receive_failed("No peers returned"); close_directly(); m_slot_success(AddressList()); } AddressList l; if (object.has_key("peers")) { try { // Due to some trackers sending the wrong type when no peers are // available, don't bork on it. if (object.get_key("peers").is_string()) l.parse_address_compact(object.get_key_string("peers")); else if (object.get_key("peers").is_list()) l.parse_address_normal(object.get_key_list("peers")); } catch (const bencode_error& e) { return receive_failed(e.what()); } } if (object.has_key_string("peers6")) l.parse_address_compact_ipv6(object.get_key_string("peers6")); close_directly(); m_slot_success(std::move(l)); } void TrackerHttp::process_scrape(const Object& object) { if (!object.has_key_map("files")) return receive_failed("Tracker scrape does not have files entry."); // Add better validation here... const Object& files = object.get_key("files"); if (!files.has_key_map(info().info_hash.str())) return receive_failed("Tracker scrape replay did not contain infohash."); const Object& stats = files.get_key(info().info_hash.str()); { auto guard = lock_guard(); if (stats.has_key_value("complete")) state().m_scrape_complete = std::max(stats.get_key_value("complete"), 0); if (stats.has_key_value("incomplete")) state().m_scrape_incomplete = std::max(stats.get_key_value("incomplete"), 0); if (stats.has_key_value("downloaded")) state().m_scrape_downloaded = std::max(stats.get_key_value("downloaded"), 0); LT_LOG("tracker scrape for %zu torrents : complete:%u incomplete:%u downloaded:%u", files.as_map().size(), state().m_scrape_complete, state().m_scrape_incomplete, state().m_scrape_downloaded); } close_directly(); m_slot_scrape_success(); } void TrackerHttp::update_tracker_id(const std::string& id) { if (id.empty()) return; if (m_current_tracker_id == id) return; set_tracker_id(id); } } // namespace torrent libtorrent-0.16.11/src/tracker/thread_tracker.cc0000644000000000000000000000634615175073411015223 #include "config.h" #include "thread_tracker.h" #include #include "torrent/exceptions.h" #include "torrent/tracker/manager.h" #include "utils/instrumentation.h" namespace torrent { std::atomic ThreadTracker::m_thread_tracker{nullptr}; ThreadTracker::~ThreadTracker() = default; void ThreadTracker::create_thread(system::Thread* main_thread) { assert(m_thread_tracker == nullptr); m_thread_tracker = new ThreadTracker(); m_thread_tracker.load()->m_tracker_manager = std::make_unique(main_thread, m_thread_tracker); } void ThreadTracker::destroy_thread() { delete m_thread_tracker; m_thread_tracker = nullptr; } ThreadTracker* ThreadTracker::thread_tracker() { return m_thread_tracker; } void ThreadTracker::init_thread() { m_state = STATE_INITIALIZED; m_instrumentation_index = INSTRUMENTATION_POLLING_DO_POLL_TRACKER - INSTRUMENTATION_POLLING_DO_POLL; // m_signal_send_event = system::Thread::self()->signal_bitfield()->add_signal([this]() { // process_send_events(); // }); } void ThreadTracker::cleanup_thread() { m_tracker_manager.reset(); } // void // ThreadTracker::send_event(tracker::Tracker& tracker, tracker::TrackerState::event_enum event) { // { // std::scoped_lock lock(m_send_events_lock); // m_send_events.erase(std::remove_if(m_send_events.begin(), m_send_events.end(), // [&tracker](const TrackerSendEvent& e) { // return e.tracker == tracker; // }), // m_send_events.end()); // m_send_events.push_back(TrackerSendEvent{tracker, event}); // } // send_event_signal(m_signal_send_event); // } void ThreadTracker::call_events() { // lt_log_print_locked(torrent::LOG_THREAD_NOTICE, "Got ThreadTracker tick."); // TODO: Consider moving this into timer events instead. if ((m_flags & flag_do_shutdown)) { if ((m_flags & flag_did_shutdown)) throw internal_error("Already trigged shutdown."); m_flags |= flag_did_shutdown; throw shutdown_exception(); } // TODO: Do we need to process scheduled events here? process_callbacks(); } std::chrono::microseconds ThreadTracker::next_timeout() { return std::chrono::microseconds(10s); } // void // ThreadTracker::process_send_events() { // std::vector events; // // TODO: Do we properly handle if the tracker is deleted? // // // // Should be, as we use weak_ptrs to the tracker objects, and check them before calling. // // // // However this should be possible to implement as a straight up callback, no need for special // // event handling. // // TODO: Make sure this is called in the right thread, currently main thread. // // TODO: Review this for proper close: // { // auto lock = std::scoped_lock(m_send_events_lock); // events.swap(m_send_events); // } // // TODO: Currently running send_* in main thread, should be in the tracker thread. // for (auto& event : events) { // if (event.event == tracker::TrackerState::EVENT_SCRAPE) // event.tracker.get_worker()->send_scrape(); // else // event.tracker.get_worker()->send_event(event.event); // } // } } // namespace torrent libtorrent-0.16.11/src/tracker/thread_tracker.h0000644000000000000000000000321415175073411015054 #ifndef LIBTORRENT_THREAD_TRACKER_H #define LIBTORRENT_THREAD_TRACKER_H #include #include "torrent/common.h" #include "torrent/tracker/tracker.h" #include "torrent/system/thread.h" namespace torrent { namespace tracker { class Manager; } // namespace tracker struct TrackerSendEvent { tracker::Tracker tracker; tracker::TrackerState::event_enum event; }; class LIBTORRENT_EXPORT ThreadTracker : public system::Thread { public: ~ThreadTracker() override; static void create_thread(system::Thread* main_thread); static void destroy_thread(); static ThreadTracker* thread_tracker(); const char* name() const override { return "rtorrent tracker"; } void init_thread() override; void cleanup_thread() override; tracker::Manager* tracker_manager() { return m_tracker_manager.get(); } // void send_event(tracker::Tracker& tracker, tracker::TrackerState::event_enum new_event); protected: friend class Manager; void call_events() override; std::chrono::microseconds next_timeout() override; private: ThreadTracker() = default; // void process_send_events(); static std::atomic m_thread_tracker; std::unique_ptr m_tracker_manager; unsigned int m_signal_send_event{~0u}; // std::mutex m_send_events_lock; // std::vector m_send_events; }; inline ThreadTracker* thread_tracker() { return ThreadTracker::thread_tracker(); } } // namespace torrent #endif // LIBTORRENT_THREAD_TRACKER_H libtorrent-0.16.11/src/tracker/tracker_http.h0000644000000000000000000000337715175073411014576 #ifndef LIBTORRENT_TRACKER_TRACKER_HTTP_H #define LIBTORRENT_TRACKER_TRACKER_HTTP_H #include #include #include "tracker/tracker_worker.h" #include "torrent/net/http_get.h" #include "torrent/tracker/tracker_state.h" #include "torrent/utils/scheduler.h" namespace torrent { class Http; class TrackerHttp : public TrackerWorker { public: static constexpr uint32_t http_timeout = 60; TrackerHttp(const TrackerInfo& info, int flags = 0); ~TrackerHttp() override; tracker_enum type() const override; bool is_busy() const override; void send_event(tracker::TrackerState::event_enum new_state) override; void send_scrape() override; void close() override; private: void close_directly(); void request_prefix(std::stringstream* stream, const std::string& url); std::string request_announce_url(tracker::TrackerState::event_enum state, TrackerParameters params, int family); void delayed_send_scrape(); void receive_done(); void receive_signal_failed(const std::string& msg); void receive_failed(const std::string& msg); void process_failure(const Object& object); void process_success(const Object& object); void process_scrape(const Object& object); void update_tracker_id(const std::string& id); net::HttpGet m_get; std::shared_ptr m_data; bool m_drop_deliminator{}; std::string m_current_tracker_id; bool m_requested_scrape{}; utils::SchedulerEntry m_delay_scrape; }; } // namespace torrent #endif libtorrent-0.16.11/src/tracker/tracker_worker.cc0000644000000000000000000000036715175073411015262 #include "config.h" #include "tracker_worker.h" namespace torrent { TrackerWorker::TrackerWorker(TrackerInfo info, int flags) : m_info(info) { m_state.m_flags = flags; } TrackerWorker::~TrackerWorker() = default; } // namespace torrent libtorrent-0.16.11/src/tracker/tracker_dht.h0000644000000000000000000000337515175073411014374 #ifndef LIBTORRENT_TRACKER_TRACKER_DHT_H #define LIBTORRENT_TRACKER_TRACKER_DHT_H #include #include "net/address_list.h" #include "torrent/object.h" #include "tracker/tracker_worker.h" namespace torrent { // Until we make throttle and rate thread-safe, we keep dht router in main thread. // // Both implemenation will require that interacting with dht router is thread safe, so we still need // to lock dht router. class TrackerDht : public TrackerWorker { public: TrackerDht(const TrackerInfo& info, int flags = 0); ~TrackerDht() override; enum state_type { state_idle, state_searching, state_announcing, }; static constexpr std::array states{ "Idle", "Searching", "Announcing" }; static bool is_allowed(); bool is_busy() const override; bool is_usable() const override; std::string lock_and_status() const override; void send_event(tracker::TrackerState::event_enum new_state) override; void send_scrape() override; void close() override; tracker_enum type() const override; state_type get_dht_state() const { return m_dht_state; } void set_dht_state(state_type state) { m_dht_state = state; } bool has_peers() const { return !m_peers.empty(); } void receive_peers(raw_list peers); void receive_success(); void receive_failed(const char* msg); void receive_progress(int replied, int contacted); private: AddressList m_peers; state_type m_dht_state{state_idle}; int m_replied; int m_contacted; }; } // namespace torrent #endif libtorrent-0.16.11/src/tracker/tracker_list.cc0000644000000000000000000004002015175073411014712 #include "config.h" #include "tracker/tracker_list.h" #include #include #include "torrent/exceptions.h" #include "torrent/download_info.h" #include "torrent/tracker/manager.h" #include "torrent/tracker/tracker.h" #include "torrent/utils/log.h" #include "torrent/utils/option_strings.h" #include "tracker/thread_tracker.h" #include "tracker/tracker_dht.h" #include "tracker/tracker_http.h" #include "tracker/tracker_udp.h" #define LT_LOG(log_fmt, ...) \ lt_log_print_hash(LOG_TRACKER_EVENTS, info()->info_hash(), "tracker_list", log_fmt, __VA_ARGS__); namespace torrent { TrackerList::TrackerList() : m_state(DownloadInfo::STOPPED) { } TrackerList::~TrackerList() { m_slot_success = nullptr; m_slot_failed = nullptr; m_slot_scrape_success = nullptr; m_slot_scrape_failed = nullptr; m_slot_tracker_enabled = nullptr; m_slot_tracker_disabled = nullptr; } bool TrackerList::has_active() const { return std::any_of(begin(), end(), std::mem_fn(&tracker::Tracker::is_busy)); } bool TrackerList::has_active_not_dht() const { return std::any_of(begin(), end(), [](const tracker::Tracker& tracker) { return tracker.is_busy() && tracker.type() != tracker_enum::TRACKER_DHT; }); } bool TrackerList::has_active_not_scrape() const { return std::any_of(begin(), end(), std::mem_fn(&tracker::Tracker::is_busy_not_scrape)); } bool TrackerList::has_active_in_group(uint32_t group) const { return std::any_of(begin_group(group), end_group(group), std::mem_fn(&tracker::Tracker::is_busy)); } bool TrackerList::has_active_not_scrape_in_group(uint32_t group) const { return std::any_of(begin_group(group), end_group(group), std::mem_fn(&tracker::Tracker::is_busy_not_scrape)); } bool TrackerList::has_usable() const { return std::any_of(begin(), end(), std::mem_fn(&tracker::Tracker::is_usable)); } void TrackerList::close_all_excluding(int event_bitmap) { LT_LOG("closing all trackers with event bitmap: 0x%x", event_bitmap); for (auto tracker : *this) { if ((event_bitmap & (1 << tracker.state().latest_event()))) continue; tracker.get_worker()->close(); } } void TrackerList::clear() { // Make sure the tracker_list is cleared before the trackers are deleted. auto list = std::move(*static_cast(this)); } void TrackerList::clear_stats() { std::for_each(begin(), end(), std::mem_fn(&tracker::Tracker::clear_stats)); } void TrackerList::send_event(tracker::Tracker& tracker, tracker::TrackerState::event_enum event) { if (!tracker.is_valid()) throw internal_error("TrackerList::send_event(...) tracker is invalid."); if (find(tracker) == end()) throw internal_error("TrackerList::send_event(...) tracker not found."); if (!tracker.is_usable() || event == tracker::TrackerState::EVENT_SCRAPE) return; // TODO: Should always send if we are trying to send a started/completed event. if (tracker.is_busy() && tracker.state().latest_event() != tracker::TrackerState::EVENT_SCRAPE) return; LT_LOG("sending %s : requester:%p url:%s", option_as_string(OPTION_TRACKER_EVENT, event), tracker.get_worker(), tracker.url().c_str()); thread_tracker()->tracker_manager()->send_event(tracker, event); } void TrackerList::send_scrape(tracker::Tracker& tracker) { if (!tracker.is_valid()) throw internal_error("TrackerList::send_scrape(...) tracker is invalid."); if (find(tracker) == end()) throw internal_error("TrackerList::send_scrape(...) tracker not found."); if (tracker.is_busy() || !tracker.is_usable()) return; if (!tracker.is_scrapable()) return; auto timeout = std::chrono::seconds(tracker.state().scrape_time_last()) + 600s; if (timeout > this_thread::cached_time()) return; LT_LOG("sending scrape : requester:%p url:%s", tracker.get_worker(), tracker.url().c_str()); thread_tracker()->tracker_manager()->send_scrape(tracker); } TrackerList::iterator TrackerList::insert(unsigned int group, const tracker::Tracker& tracker) { auto itr = base_type::insert(end_group(group), tracker); // These slots are called from within the worker thread, so we need to // use proper signal passing to the main thread. // TODO: When a tracker is sent to tracker thread to do a request, it needs to hold the shared_ptr // for the duration of the request. // TODO: TrackerList should be a shared_ptr held by DownloadMain, and send_* should pass through // tracker::Manager, which will hold the weak_ptr and collect results. It should poke signal main // thread it has work and if weak_ptr locks it performs the work. // // This means we can remove the slots below and tracker just need to have tracker::Manager*. // The weak_ptr should always return a valid shared_ptr, as the tracker thread will hold a // shared_ptr. auto weak_tracker = std::weak_ptr(itr->m_worker); auto worker = itr->get_worker(); worker->set_group(group); worker->m_slot_enabled = [this, weak_tracker, worker]() { thread_tracker()->tracker_manager()->add_event(worker, [this, weak_tracker]() { if (!m_slot_tracker_enabled) return; auto tracker_shared_ptr = weak_tracker.lock(); if (tracker_shared_ptr) m_slot_tracker_enabled(tracker::Tracker(std::move(tracker_shared_ptr))); }); }; worker->m_slot_disabled = [this, weak_tracker, worker]() { thread_tracker()->tracker_manager()->add_event(worker, [this, weak_tracker]() { if (!m_slot_tracker_disabled) return; auto tracker_shared_ptr = weak_tracker.lock(); if (tracker_shared_ptr) m_slot_tracker_disabled(tracker::Tracker(std::move(tracker_shared_ptr))); }); }; worker->m_slot_close = [worker]() { thread_tracker()->tracker_manager()->remove_events(worker); }; worker->m_slot_success = [this, weak_tracker, worker](AddressList&& l) { thread_tracker()->tracker_manager()->add_event(worker, [this, weak_tracker, l = std::move(l)]() { if (!m_slot_success) return; auto tracker_shared_ptr = weak_tracker.lock(); if (tracker_shared_ptr) receive_success(tracker::Tracker(std::move(tracker_shared_ptr)), const_cast(&l)); }); }; worker->m_slot_failure = [this, weak_tracker, worker](const std::string& msg) { thread_tracker()->tracker_manager()->add_event(worker, [this, weak_tracker, msg]() { if (!m_slot_failed) return; auto tracker_shared_ptr = weak_tracker.lock(); if (tracker_shared_ptr) receive_failed(tracker::Tracker(std::move(tracker_shared_ptr)), msg); }); }; worker->m_slot_scrape_success = [this, weak_tracker, worker]() { thread_tracker()->tracker_manager()->add_event(worker, [this, weak_tracker]() { if (!m_slot_scrape_success) return; auto tracker_shared_ptr = weak_tracker.lock(); if (tracker_shared_ptr) receive_scrape_success(tracker::Tracker(std::move(tracker_shared_ptr))); }); }; worker->m_slot_scrape_failure = [this, weak_tracker, worker](const std::string& msg) { thread_tracker()->tracker_manager()->add_event(worker, [this, weak_tracker, msg]() { if (!m_slot_scrape_failed) return; auto tracker_shared_ptr = weak_tracker.lock(); if (tracker_shared_ptr) receive_scrape_failed(tracker::Tracker(std::move(tracker_shared_ptr)), msg); }); }; worker->m_slot_new_peers = [this, weak_tracker, worker](AddressList&& l) { thread_tracker()->tracker_manager()->add_event(worker, [this, weak_tracker, l = std::move(l)]() { if (!m_slot_new_peers) return; auto tracker_shared_ptr = weak_tracker.lock(); if (tracker_shared_ptr) receive_new_peers(tracker::Tracker(std::move(tracker_shared_ptr)), const_cast(&l)); }); }; worker->m_slot_parameters = [this]() { // TODO: Lock here! TrackerParameters tp; tp.numwant = m_numwant; tp.uploaded_adjusted = m_info->uploaded_adjusted(); tp.completed_adjusted = m_info->completed_adjusted(); tp.download_left = m_info->slot_left()(); return tp; }; LT_LOG("added tracker : requester:%p group:%u url:%s", worker, itr->group(), itr->url().c_str()); if (m_slot_tracker_enabled) m_slot_tracker_enabled(tracker); return itr; } // TODO: Use proper flags for insert options. void TrackerList::insert_url(unsigned int group, const std::string& url, bool extra_tracker) { TrackerWorker* worker{}; int flags = tracker::TrackerState::flag_enabled; if (extra_tracker) flags |= tracker::TrackerState::flag_extra_tracker; TrackerInfo tracker_info; tracker_info.info_hash = m_info->hash(); tracker_info.obfuscated_hash = m_info->hash_obfuscated(); tracker_info.local_id = m_info->local_id(); tracker_info.url = url; tracker_info.key = m_key; if (std::strncmp("http://", url.c_str(), 7) == 0 || std::strncmp("https://", url.c_str(), 8) == 0) { worker = new TrackerHttp(tracker_info, flags); } else if (std::strncmp("udp://", url.c_str(), 6) == 0) { worker = new TrackerUdp(tracker_info, flags); } else if (std::strncmp("dht://", url.c_str(), 6) == 0 && TrackerDht::is_allowed()) { worker = new TrackerDht(tracker_info, flags); } else { LT_LOG("could find matching tracker protocol : url:%s", url.c_str()); if (extra_tracker) throw torrent::input_error("could find matching tracker protocol (url:" + url + ")"); return; } insert(group, tracker::Tracker(std::shared_ptr(worker))); } TrackerList::iterator TrackerList::find_url(const std::string& url) { return std::find_if(begin(), end(), [&url](const auto& tracker) { return tracker.url() == url; }); } TrackerList::iterator TrackerList::find_next_to_request(iterator itr) { auto preferred = itr = std::find_if(itr, end(), std::mem_fn(&tracker::Tracker::can_request_state)); if (preferred == end()) return end(); // TODO: Get only the required state values. auto preferred_state = (*preferred).state(); if (preferred_state.failed_counter() == 0) return preferred; while (++itr != end()) { if (!(*itr).can_request_state()) continue; auto itr_state = (*itr).state(); if (itr_state.failed_counter() != 0) { if (itr_state.failed_time_next() < preferred_state.failed_time_next()) { preferred = itr; preferred_state = (*preferred).state(); } } else { if (itr_state.success_time_next() < preferred_state.failed_time_next()) { preferred = itr; preferred_state = (*preferred).state(); } break; } } return preferred; } TrackerList::iterator TrackerList::begin_group(unsigned int group) { return std::find_if(begin(), end(), [group](const tracker::Tracker& t) { return group <= t.group(); }); } TrackerList::const_iterator TrackerList::begin_group(unsigned int group) const { return std::find_if(begin(), end(), [group](const tracker::Tracker& t) { return group <= t.group(); }); } TrackerList::size_type TrackerList::size_group() const { return !empty() ? back().group() + 1 : 0; } void TrackerList::cycle_group(unsigned int group) { auto first = begin_group(group); if (first == end() || first->group() != group) return; auto last = first; while (last != end() && last->group() == group) ++last; std::rotate(first, std::next(first), last); } TrackerList::iterator TrackerList::promote(iterator itr) { auto first = begin_group((*itr).group()); if (first == end()) throw internal_error("torrent::TrackerList::promote(...) Could not find beginning of group."); std::iter_swap(first, itr); return first; } void TrackerList::randomize_group_entries() { static std::random_device rd; static std::mt19937 rng(rd()); auto itr = begin(); while (itr != end()) { auto tmp = end_group((*itr).group()); std::shuffle(itr, tmp, rng); itr = tmp; } } void TrackerList::receive_success(tracker::Tracker tracker, AddressList* l) { LT_LOG("received %zu peers : requester:%p group:%u url:%s", l->size(), tracker.get_worker(), tracker.group(), tracker.url().c_str()); auto itr = find(tracker); if (itr == end()) throw internal_error("TrackerList::receive_success(...) called but the iterator is invalid."); if (tracker.is_busy()) throw internal_error("TrackerList::receive_success(...) called but the tracker is still busy."); // Promote the tracker to the front of the group since it was // successfull. promote(itr); l->sort_and_unique(); // TODO: Update staate in TrackerWorker. { auto guard = tracker.get_worker()->lock_guard(); tracker.get_worker()->state().m_success_time_last = this_thread::cached_seconds().count(); tracker.get_worker()->state().m_success_counter++; tracker.get_worker()->state().m_failed_counter = 0; tracker.get_worker()->state().m_latest_sum_peers = l->size(); } if (!m_slot_success) return; auto new_peers = m_slot_success(tracker, l); { auto guard = tracker.get_worker()->lock_guard(); tracker.get_worker()->state().m_latest_new_peers = new_peers + tracker.get_worker()->state().m_latest_new_peers_delta; tracker.get_worker()->state().m_latest_new_peers_delta = 0; } } void TrackerList::receive_failed(tracker::Tracker tracker, const std::string& msg) { LT_LOG("received failure : requester:%p group:%u url:%s msg:'%s'", tracker.get_worker(), tracker.group(), tracker.url().c_str(), msg.c_str()); auto itr = find(tracker); if (itr == end()) throw internal_error("TrackerList::receive_failed(...) called but the iterator is invalid."); if (tracker.is_busy()) throw internal_error("TrackerList::receive_failed(...) called but the tracker is still busy."); { auto guard = tracker.get_worker()->lock_guard(); tracker.get_worker()->state().m_failed_time_last = this_thread::cached_seconds().count(); tracker.get_worker()->state().m_failed_counter++; tracker.get_worker()->state().m_latest_new_peers_delta = 0; } if (m_slot_failed) m_slot_failed(tracker, msg); } void TrackerList::receive_scrape_success(tracker::Tracker tracker) { LT_LOG("received scrape success : requester:%p group:%u url:%s", tracker.get_worker(), tracker.group(), tracker.url().c_str()); auto itr = find(tracker); if (itr == end()) throw internal_error("TrackerList::receive_scrape_success(...) called but the iterator is invalid."); if (tracker.is_busy()) throw internal_error("TrackerList::receive_scrape_success(...) called but the tracker is still busy."); { auto guard = tracker.get_worker()->lock_guard(); tracker.get_worker()->state().m_scrape_time_last = this_thread::cached_seconds().count(); tracker.get_worker()->state().m_scrape_counter++; } if (m_slot_scrape_success) m_slot_scrape_success(tracker); } void TrackerList::receive_scrape_failed(tracker::Tracker tracker, const std::string& msg) { LT_LOG("received scrape failure : requester:%p group:%u url:%s msg:'%s'", tracker.get_worker(), tracker.group(), tracker.url().c_str(), msg.c_str()); auto itr = find(tracker); if (itr == end()) throw internal_error("TrackerList::receive_scrape_failed(...) called but the iterator is invalid."); if (tracker.is_busy()) throw internal_error("TrackerList::receive_scrape_failed(...) called but the tracker is still busy."); if (m_slot_scrape_failed) m_slot_scrape_failed(tracker, msg); } void TrackerList::receive_new_peers(tracker::Tracker tracker, AddressList* l) { LT_LOG("received %zu new peers : requester:%p group:%u url:%s", l->size(), tracker.get_worker(), tracker.group(), tracker.url().c_str()); auto itr = find(tracker); if (itr == end()) throw internal_error("TrackerList::receive_new_peers(...) called but the iterator is invalid."); l->sort_and_unique(); auto new_peers = m_slot_new_peers(l); { auto guard = tracker.get_worker()->lock_guard(); tracker.get_worker()->state().m_latest_new_peers_delta += new_peers; } } } // namespace torrent libtorrent-0.16.11/src/tracker/tracker_list.h0000644000000000000000000001302715175073411014563 #ifndef LIBTORRENT_TRACKER_LIST_H #define LIBTORRENT_TRACKER_LIST_H // TODO: Reduce includes, don't inline everything. #include #include #include #include struct TestTrackerListWrapper; namespace torrent { // The tracker list will contain a list of tracker, divided into subgroups. // // Each group must be randomized before we start. // // When starting the tracker request, always start from the beginning and iterate if the request // failed. // // Upon request success move the tracker to the beginning of the subgroup and start from the // beginning of the whole list. class LIBTORRENT_EXPORT TrackerList : private std::vector { public: using base_type = std::vector; using base_type::value_type; using base_type::iterator; using base_type::const_iterator; using base_type::reverse_iterator; using base_type::const_reverse_iterator; using base_type::size; using base_type::empty; using base_type::begin; using base_type::end; using base_type::rbegin; using base_type::rend; using base_type::front; using base_type::back; using base_type::at; TrackerList(); ~TrackerList(); bool has_active() const; bool has_active_not_dht() const; bool has_active_not_scrape() const; bool has_active_in_group(uint32_t group) const; bool has_active_not_scrape_in_group(uint32_t group) const; bool has_usable() const; void close_all() { close_all_excluding(0); } void close_all_excluding(int event_bitmap); void clear(); void clear_stats(); iterator insert(unsigned int group, const tracker::Tracker& tracker); void insert_url(unsigned int group, const std::string& url, bool extra_tracker = false); // TODO: Move these to controller / tracker. // TODO: CHECK PEX CAUSES PEER CONNECTS. void send_event(tracker::Tracker& tracker, tracker::TrackerState::event_enum new_event); void send_scrape(tracker::Tracker& tracker); const DownloadInfo* info() const { return m_info; } int state() const { return m_state; } uint32_t key() const { return m_key; } int32_t numwant() const { return m_numwant; } void set_numwant(int32_t n) { m_numwant = n; } iterator find(const tracker::Tracker& tb) { return std::find(begin(), end(), tb); } iterator find_url(const std::string& url); iterator find_next_to_request(iterator itr); iterator begin_group(unsigned int group); const_iterator begin_group(unsigned int group) const; iterator end_group(unsigned int group) { return begin_group(group + 1); } const_iterator end_group(unsigned int group) const { return begin_group(group + 1); } size_type size_group() const; void cycle_group(unsigned int group); iterator promote(iterator itr); void randomize_group_entries(); // TODO: Make protected. void receive_success(tracker::Tracker tracker, AddressList* l); void receive_failed(tracker::Tracker tracker, const std::string& msg); void receive_scrape_success(tracker::Tracker tracker); void receive_scrape_failed(tracker::Tracker tracker, const std::string& msg); void receive_new_peers(tracker::Tracker tracker, AddressList* l); auto& slot_success() { return m_slot_success; } auto& slot_failure() { return m_slot_failed; } auto& slot_scrape_success() { return m_slot_scrape_success; } auto& slot_scrape_failure() { return m_slot_scrape_failed; } auto& slot_new_peers() { return m_slot_new_peers; } auto& slot_tracker_enabled() { return m_slot_tracker_enabled; } auto& slot_tracker_disabled() { return m_slot_tracker_disabled; } protected: friend class DownloadWrapper; friend struct ::TestTrackerListWrapper; void set_info(DownloadInfo* info) { m_info = info; } void set_state(int s) { m_state = s; } void set_key(uint32_t k) { m_key = k; } private: TrackerList(const TrackerList&) = delete; TrackerList& operator=(const TrackerList&) = delete; DownloadInfo* m_info{}; int m_state{}; // TODO: Key should be part of download static info. uint32_t m_key{0}; int32_t m_numwant{-1}; std::function m_slot_success; std::function m_slot_failed; std::function m_slot_scrape_success; std::function m_slot_scrape_failed; std::function m_slot_new_peers; std::function m_slot_tracker_enabled; std::function m_slot_tracker_disabled; }; } // namespace torrent #endif libtorrent-0.16.11/src/thread_main.cc0000644000000000000000000000453515175073411013057 #include "config.h" #include "thread_main.h" #include "data/hash_queue.h" #include "torrent/net/resolver.h" #include "utils/instrumentation.h" namespace torrent { class ThreadMainInternal { public: static ThreadMain* thread_main() { return ThreadMain::m_thread_main; } }; namespace main_thread { torrent::system::Thread* thread() { return torrent::ThreadMainInternal::thread_main(); } std::thread::id thread_id() { return torrent::ThreadMainInternal::thread_main()->thread_id(); } void callback(void* target, std::function&& fn) { ThreadMainInternal::thread_main()->callback(target, std::move(fn)); } void cancel_callback(void* target) { ThreadMainInternal::thread_main()->cancel_callback(target); } void cancel_callback_and_wait(void* target) { ThreadMainInternal::thread_main()->cancel_callback_and_wait(target); } // TODO: Not thread safe. uint32_t hash_queue_size() { return torrent::ThreadMainInternal::thread_main()->hash_queue()->size(); } } // namespace main_thread ThreadMain* ThreadMain::m_thread_main{nullptr}; ThreadMain::~ThreadMain() { cleanup_thread(); } void ThreadMain::create_thread() { m_thread_main = new ThreadMain; m_thread_main->m_hash_queue = std::make_unique(); } ThreadMain* ThreadMain::thread_main() { return m_thread_main; } void ThreadMain::init_thread() { m_resolver = std::make_unique(); m_state = STATE_INITIALIZED; m_instrumentation_index = INSTRUMENTATION_POLLING_DO_POLL_MAIN - INSTRUMENTATION_POLLING_DO_POLL; init_thread_local(); // We should only initialize things here that depend on main thread, as we want to call // 'init_thread()' before 'torrent::initalize()'. auto hash_work_signal = m_signal_bitfield.add_signal([this]() { return m_hash_queue->work(); }); m_hash_queue->slot_has_work() = [this, hash_work_signal](bool is_done) { send_event_signal(hash_work_signal, is_done); }; } void ThreadMain::cleanup_thread() { m_hash_queue.reset(); m_thread_main = nullptr; m_self = nullptr; } void ThreadMain::call_events() { if (m_slot_do_work) m_slot_do_work(); process_callbacks(); } std::chrono::microseconds ThreadMain::next_timeout() { return std::chrono::microseconds(10s); } } // namespace torrent libtorrent-0.16.11/src/runtime.h0000644000000000000000000000130515175073411012121 #ifndef LIBTORRENT_RUNTIME_H #define LIBTORRENT_RUNTIME_H #include #include "torrent/common.h" namespace torrent { class LIBTORRENT_EXPORT Runtime { public: static void initialize(system::Thread* main_thread); static void cleanup(); auto* network_manager() { return m_network_manager.get(); } auto* socket_manager() { return m_socket_manager.get(); } private: Runtime(system::Thread* main_thread); ~Runtime(); system::Thread* m_main_thread; std::unique_ptr m_network_manager; std::unique_ptr m_socket_manager; }; } // namespace torrent #endif // LIBTORRENT_RUNTIME_H libtorrent-0.16.11/src/manager.h0000644000000000000000000000435115175073411012054 #ifndef LIBTORRENT_MANAGER_H #define LIBTORRENT_MANAGER_H #include #include #include #include "torrent/common.h" #include "torrent/utils/scheduler.h" namespace torrent { class DownloadManager; class FileManager; class ResourceManager; using EncodingList = std::list; class Manager { public: Manager(); ~Manager(); auto* network_config() { return m_network_config.get(); } // TODO: Remove. auto* network_manager() { return runtime::network_manager(); } auto* socket_manager() { return runtime::socket_manager(); } auto* chunk_manager() { return m_chunk_manager.get(); } auto* connection_manager() { return m_connection_manager.get(); } auto* download_manager() { return m_download_manager.get(); } auto* file_manager() { return m_file_manager.get(); } auto* handshake_manager() { return m_handshake_manager.get(); } auto* resource_manager() { return m_resource_manager.get(); } auto* client_list() { return m_client_list.get(); } EncodingList* encoding_list() { return &m_encodingList; } Throttle* upload_throttle() { return m_uploadThrottle; } Throttle* download_throttle() { return m_downloadThrottle; } void initialize_download(DownloadWrapper* d); void cleanup_download(DownloadWrapper* d); void receive_tick(); private: std::unique_ptr m_network_config; std::unique_ptr m_chunk_manager; std::unique_ptr m_connection_manager; std::unique_ptr m_download_manager; std::unique_ptr m_file_manager; std::unique_ptr m_handshake_manager; std::unique_ptr m_resource_manager; std::unique_ptr m_client_list; EncodingList m_encodingList; Throttle* m_uploadThrottle; Throttle* m_downloadThrottle; unsigned int m_ticks{0}; utils::SchedulerEntry m_task_tick; }; extern Manager* manager; } // namespace torrent #endif libtorrent-0.16.11/src/data/0000755000000000000000000000000015175073434011264 5libtorrent-0.16.11/src/data/chunk_list.cc0000644000000000000000000003112315175073411013651 #include "config.h" #include "chunk_list.h" #include "data/chunk.h" #include "torrent/exceptions.h" #include "torrent/chunk_manager.h" #include "torrent/data/download_data.h" #include "torrent/utils/log.h" #include "utils/instrumentation.h" #define LT_LOG_THIS(log_level, log_fmt, ...) \ lt_log_print_data(LOG_STORAGE_##log_level, m_data, "chunk_list", log_fmt, __VA_ARGS__); namespace torrent { struct chunk_list_earliest_modified { void operator () (ChunkListNode* node) { if (node->time_modified() < m_time && node->time_modified() != 0us) m_time = node->time_modified(); } std::chrono::microseconds m_time{this_thread::cached_time()}; }; inline bool ChunkList::is_queued(ChunkListNode* node) { return std::find(m_queue.begin(), m_queue.end(), node) != m_queue.end(); } bool ChunkList::has_chunk(size_type index, int prot) const { return base_type::at(index).is_valid() && base_type::at(index).chunk()->has_permissions(prot); } void ChunkList::resize(size_type to_size) { LT_LOG_THIS(INFO, "Resizing: from:%zu to:%u.", size(), to_size); if (!empty()) throw internal_error("ChunkList::resize(...) called on an non-empty object."); base_type::resize(to_size); uint32_t index = 0; for (auto& chunk : *this) { chunk.set_index(index); ++index; } } void ChunkList::clear() { LT_LOG_THIS(INFO, "Clearing.", 0); // Don't do any sync'ing as whomever decided to shut down really // doesn't care, so just de-reference all chunks in queue. for (auto chunk : m_queue) { if (chunk->references() != 1 || chunk->writable() != 1) throw internal_error("ChunkList::clear() called but a node in the queue is still referenced."); chunk->dec_rw(); clear_chunk(chunk, release_default); } m_queue.clear(); if (std::any_of(begin(), end(), std::mem_fn(&ChunkListNode::chunk))) throw internal_error("ChunkList::clear() called but a node with a valid chunk was found."); if (std::any_of(begin(), end(), std::mem_fn(&ChunkListNode::references))) throw internal_error("ChunkList::clear() called but a node with references != 0 was found."); if (std::any_of(begin(), end(), std::mem_fn(&ChunkListNode::writable))) throw internal_error("ChunkList::clear() called but a node with writable != 0 was found."); if (std::any_of(begin(), end(), std::mem_fn(&ChunkListNode::blocking))) throw internal_error("ChunkList::clear() called but a node with blocking != 0 was found."); base_type::clear(); } ChunkHandle ChunkList::get(size_type index, get_flags flags) { LT_LOG_THIS(DEBUG, "Get: index:%" PRIu32 " flags:%#x.", index, flags); errno = 0; ChunkListNode* node = &base_type::at(index); int allocate_flags = (flags & get_dont_log) ? ChunkManager::allocate_dont_log : 0; int prot_flags = MemoryChunk::prot_read | ((flags & get_writable) ? MemoryChunk::prot_write : 0); if (!node->is_valid()) { if (!m_manager->allocate(m_chunk_size, allocate_flags)) { LT_LOG_THIS(DEBUG, "Could not allocate: memory:%" PRIu64 " block:%" PRIu32 ".", m_manager->memory_usage(), m_manager->memory_block_count()); return ChunkHandle::from_error(ENOMEM); } Chunk* chunk; if ((flags & get_hashing)) chunk = m_slot_create_hashing_chunk(index, prot_flags); else if (flags & get_not_hashing) chunk = m_slot_create_chunk(index, prot_flags); else throw internal_error("ChunkList::get(...) called with get_hashing and get_not_hashing flags set."); if (chunk == nullptr) { int err = errno; LT_LOG_THIS(DEBUG, "Could not create: memory:%" PRIu64 " block:%" PRIu32 " errno:%i errmsg:%s.", m_manager->memory_usage(), m_manager->memory_block_count(), err, std::strerror(err)); m_manager->deallocate(m_chunk_size, allocate_flags | ChunkManager::allocate_revert_log); return ChunkHandle::from_error(err); } node->set_chunk(chunk); node->set_time_modified(0us); } else if (flags & get_writable && !node->chunk()->is_writable()) { if (node->blocking() != 0) { if ((flags & get_nonblock)) return ChunkHandle::from_error(EAGAIN); throw internal_error("No support yet for getting write permission for blocked chunk."); } Chunk* chunk = m_slot_create_chunk(index, prot_flags); if (chunk == nullptr) return ChunkHandle::from_error(errno); delete node->chunk(); node->set_chunk(chunk); node->set_time_modified(0us); } node->inc_references(); if (flags & get_writable) { node->inc_writable(); // Make sure that periodic syncing uses async on any subsequent // changes even if it was triggered before this get. node->set_sync_triggered(false); } if (flags & get_blocking) { node->inc_blocking(); } return ChunkHandle(node, flags & get_writable, flags & get_blocking); } // The chunks in 'm_queue' have been modified and need to be synced // when appropriate. Hopefully keeping the chunks mmap'ed for a while // will allow us to schedule writes at more resonable intervals. void ChunkList::release(ChunkHandle* handle, release_flags flags) { if (!handle->is_valid()) throw internal_error("ChunkList::release(...) received an invalid handle."); if (handle->object() < &*begin() || handle->object() >= &*end()) throw internal_error("ChunkList::release(...) received an unknown handle."); LT_LOG_THIS(DEBUG, "Release: index:%" PRIu32 " flags:%#x.", handle->index(), flags); if (handle->object()->references() <= 0 || (handle->is_writable() && handle->object()->writable() <= 0) || (handle->is_blocking() && handle->object()->blocking() <= 0)) throw internal_error("ChunkList::release(...) received a node with bad reference count."); if (handle->is_blocking()) { handle->object()->dec_blocking(); } if (handle->is_writable()) { if (handle->object()->writable() == 1) { if (is_queued(handle->object())) throw internal_error("ChunkList::release(...) tried to queue an already queued chunk."); // Only add those that have a modification time set? // // Only chunks that are not already in the queue will execute // this branch. m_queue.push_back(handle->object()); } else { handle->object()->dec_rw(); } } else { if (handle->object()->dec_references() == 0) { if (is_queued(handle->object())) throw internal_error("ChunkList::release(...) tried to unmap a queued chunk."); clear_chunk(handle->object(), flags); } } handle->clear(); } void ChunkList::clear_chunk(ChunkListNode* node, release_flags flags) { if (!node->is_valid()) throw internal_error("ChunkList::clear_chunk(...) !node->is_valid()."); delete node->chunk(); node->set_chunk(NULL); m_manager->deallocate(m_chunk_size, (flags & release_dont_log) ? ChunkManager::allocate_dont_log : 0); } inline bool ChunkList::sync_chunk(ChunkListNode* node, std::pair options) { if (node->references() <= 0 || node->writable() <= 0) throw internal_error("ChunkList::sync_chunk(...) got a node with invalid reference count."); if (!node->chunk()->sync(options.first)) return false; node->set_sync_triggered(true); // When returning here we're not properly deallocating the piece. // // Only release the chunk after a blocking sync. if (!options.second) return true; node->dec_rw(); if (node->references() == 0) clear_chunk(node, release_default); return true; } uint32_t ChunkList::sync_chunks(sync_flags flags) { LT_LOG_THIS(DEBUG, "Sync chunks: flags:%#x.", flags); Queue::iterator split; if ((flags & sync_all)) split = m_queue.begin(); else split = std::stable_partition(m_queue.begin(), m_queue.end(), [](ChunkListNode* n) { return 1 != n->writable(); }); // Allow a flag that does more culling, so that we only get large // continous sections. // // How does this interact with timers, should be make it so that // only areas with timers are (preferably) synced? std::sort(split, m_queue.end()); // If we got enough diskspace and have not requested safe syncing, // then sync all chunks with MS_ASYNC. if (!(flags & (sync_safe | sync_sloppy))) { if (m_manager->safe_sync() || m_slot_free_diskspace() <= m_manager->safe_free_diskspace()) flags = flags | sync_safe; else flags = flags | sync_force; } // TODO: This won't trigger for default sync_force. if ((flags & sync_use_timeout) && !(flags & sync_force)) split = partition_optimize(split, m_queue.end(), 50, 5, false); uint32_t failed = 0; for (auto itr = split, last = m_queue.end(); itr != last; ++itr) { // We can easily skip pieces by swap_iter, so there should be no // problem being selective about the ranges we sync. // Use a function for checking the next few chunks and see how far // we want to sync. When we want to sync everything use end. Call // before the loop, or add a check. // if we don't want to sync, swap and break. std::pair options = sync_options(*itr, flags); if (!sync_chunk(*itr, options)) { std::iter_swap(itr, split++); failed++; continue; } if (!options.second) std::iter_swap(itr, split++); } if (lt_log_is_valid(LOG_INSTRUMENTATION_MINCORE)) { instrumentation_update(INSTRUMENTATION_MINCORE_SYNC_SUCCESS, std::distance(split, m_queue.end())); instrumentation_update(INSTRUMENTATION_MINCORE_SYNC_FAILED, failed); instrumentation_update(INSTRUMENTATION_MINCORE_SYNC_NOT_SYNCED, std::distance(m_queue.begin(), split)); instrumentation_update(INSTRUMENTATION_MINCORE_SYNC_NOT_DEALLOCATED, std::count_if(split, m_queue.end(), std::mem_fn(&ChunkListNode::is_valid))); } m_queue.erase(split, m_queue.end()); // The caller must either make sure that it is safe to close the // download or set the sync_ignore_error flag. if (failed && !(flags & sync_ignore_error)) m_slot_storage_error("Could not sync chunk: " + std::string(std::strerror(errno))); return failed; } std::pair ChunkList::sync_options(ChunkListNode* node, sync_flags flags) { if ((flags & sync_force)) { if ((flags & sync_safe)) return std::make_pair(MemoryChunk::sync_sync, true); else return std::make_pair(MemoryChunk::sync_async, true); } else if ((flags & sync_safe)) { if (node->sync_triggered()) return std::make_pair(MemoryChunk::sync_sync, true); else return std::make_pair(MemoryChunk::sync_async, false); } else { return std::make_pair(MemoryChunk::sync_async, true); } } // Using a rather simple algorithm for now. This should really be more // robust against holes withing otherwise compact ranges and take into // consideration chunk size. ChunkList::Queue::iterator ChunkList::seek_range(Queue::iterator first, Queue::iterator last) { uint32_t prevIndex = (*first)->index(); while (++first != last) { if ((*first)->index() - prevIndex > 5) break; prevIndex = (*first)->index(); } return first; } inline bool ChunkList::check_node(ChunkListNode* node) { return node->time_modified() != 0us && node->time_modified() + std::chrono::seconds(m_manager->timeout_sync()) < this_thread::cached_time(); } // Optimize the selection of chunks to sync. Continuous regions are // preferred, while if too fragmented or if too few chunks are // available it skips syncing of all chunks. ChunkList::Queue::iterator ChunkList::partition_optimize(Queue::iterator first, Queue::iterator last, int weight, int maxDistance, bool dontSkip) { for (auto itr = first; itr != last;) { auto range = seek_range(itr, last); bool required = std::any_of(itr, range, [this](auto wrapper) { return check_node(wrapper); }); dontSkip = dontSkip || required; if (!required && std::distance(itr, range) < maxDistance) { // Don't sync this range. unsigned int l = std::min(range - itr, itr - first); std::swap_ranges(first, first + l, range - l); first += l; } else { // This probably increases too fast. weight -= std::distance(itr, range) * std::distance(itr, range); } itr = range; } // These values are all arbritrary... if (!dontSkip && weight > 0) return last; return first; } ChunkList::chunk_address_result ChunkList::find_address(void* ptr) { auto first = begin(); auto last = end(); for (; first != last; first++) { if (!first->is_valid()) continue; auto partition = first->chunk()->find_address(ptr); if (partition != first->chunk()->end()) return chunk_address_result(first, partition); first++; } return chunk_address_result(end(), Chunk::iterator()); } } // namespace torrent libtorrent-0.16.11/src/data/hash_queue_node.cc0000644000000000000000000000406515175073411014647 // libTorrent - BitTorrent library // Copyright (C) 2005-2011, Jari Sundell // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // In addition, as a special exception, the copyright holders give // permission to link the code of portions of this program with the // OpenSSL library under certain conditions as described in each // individual source file, and distribute linked combinations // including the two. // // You must obey the GNU General Public License in all respects for // all of the code used other than OpenSSL. If you modify file(s) // with this exception, you may extend this exception to your version // of the file(s), but you are not obligated to do so. If you do not // wish to do so, delete this exception statement from your version. // If you delete this exception statement from all source files in the // program, then also delete it here. // // Contact: Jari Sundell // // Skomakerveien 33 // 3185 Skoppum, NORWAY #include "config.h" #include "hash_chunk.h" #include "hash_queue_node.h" namespace torrent { uint32_t HashQueueNode::get_index() const { return m_chunk->chunk()->index(); } void HashQueueNode::clear() { delete m_chunk; m_chunk = NULL; } uint32_t HashQueueNode::call_willneed() { if (!m_willneed) { m_willneed = true; m_chunk->advise_willneed(m_chunk->remaining()); } return m_chunk->remaining(); } } // namespace torrent libtorrent-0.16.11/src/data/hash_queue_node.h0000644000000000000000000000600115175073411014501 // libTorrent - BitTorrent library // Copyright (C) 2005-2011, Jari Sundell // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // In addition, as a special exception, the copyright holders give // permission to link the code of portions of this program with the // OpenSSL library under certain conditions as described in each // individual source file, and distribute linked combinations // including the two. // // You must obey the GNU General Public License in all respects for // all of the code used other than OpenSSL. If you modify file(s) // with this exception, you may extend this exception to your version // of the file(s), but you are not obligated to do so. If you do not // wish to do so, delete this exception statement from your version. // If you delete this exception statement from all source files in the // program, then also delete it here. // // Contact: Jari Sundell // // Skomakerveien 33 // 3185 Skoppum, NORWAY #ifndef LIBTORRENT_DATA_HASH_QUEUE_NODE_H #define LIBTORRENT_DATA_HASH_QUEUE_NODE_H #include #include #include #include #include "chunk_handle.h" #include "hash_chunk.h" namespace torrent { class download_data; class HashQueueNode { public: using slot_done_type = std::function; using id_type = download_data*; HashQueueNode(id_type id, HashChunk* c, slot_done_type d) : m_id(id), m_chunk(c), m_slot_done(std::move(d)) {} id_type id() const { return m_id; } ChunkHandle& handle() { return *m_chunk->chunk(); } uint32_t get_index() const; HashChunk* get_chunk() const { return m_chunk; } bool get_willneed() const { return m_willneed; } bool perform_remaining(bool force) { return m_chunk->perform(m_chunk->remaining(), force); } void clear(); // Does not call multiple times on the same chunk. Returns the // number of bytes not checked in this chunk. uint32_t call_willneed(); slot_done_type& slot_done() { return m_slot_done; } private: id_type m_id; HashChunk* m_chunk; bool m_willneed{false}; slot_done_type m_slot_done; }; } // namespace torrent #endif libtorrent-0.16.11/src/data/socket_file.h0000644000000000000000000000307515175073411013644 #ifndef LIBTORRENT_SOCKET_FILE_H #define LIBTORRENT_SOCKET_FILE_H #include #include #include #include #include "memory_chunk.h" namespace torrent { class SocketFile { public: using fd_type = int; static constexpr fd_type invalid_fd = -1; static constexpr int o_create = O_CREAT; static constexpr int o_truncate = O_TRUNC; static constexpr int o_nonblock = O_NONBLOCK; static constexpr int flag_fallocate = (1 << 0); static constexpr int flag_fallocate_blocking = (1 << 1); SocketFile() = default; ~SocketFile() = default; SocketFile(fd_type fd) : m_fd(fd) {} bool is_open() const { return m_fd != invalid_fd; } bool open(const std::string& path, int prot, int flags, mode_t mode = 0666); void close(); uint64_t size() const; bool set_size(uint64_t size) const; bool allocate(uint64_t size, int flags = 0) const; static MemoryChunk create_padding_chunk(uint32_t length, int prot, int flags); MemoryChunk create_chunk(uint64_t offset, uint32_t length, int prot, int flags) const; fd_type fd() const { return m_fd; } private: SocketFile(const SocketFile&) = delete; SocketFile& operator=(const SocketFile&) = delete; // Use custom flags if stuff like file locking etc is implemented. fd_type m_fd{invalid_fd}; }; } // namespace torrent #endif libtorrent-0.16.11/src/data/memory_chunk.cc0000644000000000000000000000615515175073411014215 #include "config.h" #include #include #include "torrent/exceptions.h" #include "memory_chunk.h" #ifdef __sun__ extern "C" int madvise(void *, size_t, int); //#include //Should be the include line instead, but Solaris //has an annoying bug wherein it doesn't declare //madvise for C++. #endif namespace torrent { uint32_t MemoryChunk::m_pagesize = getpagesize(); inline void MemoryChunk::align_pair(uint32_t* offset, uint32_t* length) const { *offset += page_align(); *length += *offset % m_pagesize; *offset -= *offset % m_pagesize; } MemoryChunk::MemoryChunk(char* ptr, char* begin, char* end, int prot, int flags) : m_ptr(ptr), m_begin(begin), m_end(end), m_prot(prot), m_flags(flags) { if (ptr == NULL) throw internal_error("MemoryChunk::MemoryChunk(...) received ptr == NULL"); if (page_align() >= m_pagesize) throw internal_error("MemoryChunk::MemoryChunk(...) received an page alignment >= page size"); if (reinterpret_cast(ptr) % m_pagesize) throw internal_error("MemoryChunk::MemoryChunk(...) is not aligned to a page"); } void MemoryChunk::unmap() { if (!is_valid()) throw internal_error("MemoryChunk::unmap() called on an invalid object"); if (munmap(m_ptr, m_end - m_ptr) != 0) throw internal_error("MemoryChunk::unmap() system call failed: " + std::string(std::strerror(errno))); } void MemoryChunk::incore(char* buf, uint32_t offset, uint32_t length) { if (!is_valid()) throw internal_error("Called MemoryChunk::incore(...) on an invalid object"); if (!is_valid_range(offset, length)) throw internal_error("MemoryChunk::incore(...) received out-of-range input"); align_pair(&offset, &length); #if USE_MINCORE #if USE_MINCORE_UNSIGNED if (mincore(m_ptr + offset, length, reinterpret_cast(buf))) #else if (mincore(m_ptr + offset, length, buf)) #endif throw storage_error("System call mincore failed: " + std::string(std::strerror(errno))); #else // !USE_MINCORE // Pretend all pages are in memory. memset(buf, 1, pages_touched(offset, length)); #endif } bool MemoryChunk::advise(uint32_t offset, uint32_t length, int advice) { if (!is_valid()) throw internal_error("Called MemoryChunk::advise() on an invalid object"); if (!is_valid_range(offset, length)) throw internal_error("MemoryChunk::advise(...) received out-of-range input"); #if USE_MADVISE align_pair(&offset, &length); if (madvise(m_ptr + offset, length, advice) == 0) return true; else if (errno == EINVAL || (errno == ENOMEM && advice != advice_willneed) || errno == EBADF) throw internal_error("MemoryChunk::advise(...) " + std::string(strerror(errno))); else return false; #else return true; #endif } bool MemoryChunk::sync(uint32_t offset, uint32_t length, int flags) { if (!is_valid()) throw internal_error("Called MemoryChunk::sync() on an invalid object"); if (!is_valid_range(offset, length)) throw internal_error("MemoryChunk::sync(...) received out-of-range input"); align_pair(&offset, &length); return msync(m_ptr + offset, length, flags) == 0; } } // namespace torrent libtorrent-0.16.11/src/data/hash_torrent.cc0000644000000000000000000001412215175073411014206 #include "config.h" #include "data/chunk_list.h" #include "torrent/exceptions.h" #include "torrent/data/download_data.h" #include "torrent/utils/log.h" #include "hash_torrent.h" #define LT_LOG_THIS(log_level, log_fmt, ...) \ lt_log_print_data(LOG_STORAGE_##log_level, m_chunk_list->data(), "hash_torrent", log_fmt, __VA_ARGS__); namespace torrent { HashTorrent::HashTorrent(ChunkList* c) : m_chunk_list(c) { } bool HashTorrent::start(bool try_quick) { LT_LOG_THIS(INFO, "start : position:%u size:%zu quick:%u.", m_position, m_chunk_list->size(), try_quick); if (m_position == m_chunk_list->size()) return true; if (m_position > 0 || m_chunk_list->empty()) throw internal_error("HashTorrent::start() call failed."); m_outstanding = 0; queue(try_quick); return m_position == m_chunk_list->size(); } void HashTorrent::clear() { LT_LOG_THIS(INFO, "clear", 0); m_outstanding = -1; m_position = 0; m_errno = 0; this_thread::scheduler()->erase(&m_delay_checked); } bool HashTorrent::is_checked() const { // When closed the chunk list is empty. Position can be equal to // chunk list for a short while as we have outstanding chunks, so // check the latter. return !m_chunk_list->empty() && m_position == m_chunk_list->size() && m_outstanding == -1; } // After all chunks are checked it won't show as is_checked until // after this function is called. This allows for the hash done signal // to be delayed. void HashTorrent::confirm_checked() { LT_LOG_THIS(INFO, "confirmed checked", 0); if (m_outstanding != 0) throw internal_error("HashTorrent::confirm_checked() m_outstanding != 0."); m_outstanding = -1; } void HashTorrent::receive_chunkdone(uint32_t index) { LT_LOG_THIS(DEBUG, "received chunk done: index:%" PRIu32 " outstanding:%i.", index, m_outstanding); if (m_outstanding <= 0) throw internal_error("HashTorrent::receive_chunkdone() m_outstanding <= 0."); // m_signalChunk will always point to // DownloadMain::receive_hash_done, so it will take care of cleanup. // // Make sure we call chunkdone before torrentDone has a chance to // trigger. m_outstanding--; queue(false); } // Mark unsuccessful checks so that if we have just stopped the // hash checker it will ensure those pieces get rechecked upon // restart. void HashTorrent::receive_chunk_cleared(uint32_t index) { LT_LOG_THIS(DEBUG, "received chunk cleared: index:%" PRIu32 " outstanding:%i.", index, m_outstanding); if (m_outstanding <= 0) throw internal_error("HashTorrent::receive_chunk_cleared() m_outstanding < 0."); if (m_ranges.has(index)) throw internal_error("HashTorrent::receive_chunk_cleared() m_ranges.has(index)."); m_outstanding--; m_ranges.insert(index, index + 1); } void HashTorrent::queue(bool quick) { LT_LOG_THIS(INFO, "queuing : position:%u outstanding:%i quick:%u", m_position, m_outstanding, quick); if (!is_checking()) throw internal_error("HashTorrent::queue() called but it's not running."); while (m_position < m_chunk_list->size()) { if (m_outstanding > 10 && m_outstanding * m_chunk_list->chunk_size() > (128 << 20)) return; // Not very efficient, but this is seldomly done. auto itr = m_ranges.find(m_position); if (itr == m_ranges.end()) { m_position = m_chunk_list->size(); break; } else if (m_position < itr->first) { m_position = itr->first; } // Need to do increment later if we're going to support resume // hashing a quick hashed torrent. ChunkHandle handle = m_chunk_list->get(m_position, ChunkList::get_dont_log | ChunkList::get_hashing); if (quick) { // We're not actually interested in doing any hashing, so just // skip what we know is not possible to hash. // // If the file does not exist then no valid error number is // returned. if (m_outstanding != 0) throw internal_error("HashTorrent::queue() quick hashing but m_outstanding != 0."); if (handle.is_valid()) { LT_LOG_THIS(DEBUG, "quick : skip valid handle : position:%u", m_position); return m_chunk_list->release(&handle, ChunkList::release_dont_log); } if (handle.error_number() != 0 && handle.error_number() != ENOENT) { LT_LOG_THIS(DEBUG, "quick : skip invalid handle with non-ENOENT error : position:%u errno:%s", m_position, system::errno_enum(handle.error_number())); return; } m_position++; continue; } // If the error number is not valid, then we've just encountered a // file that hasn't be created/resized. Which means we ignore it // when doing initial hashing. if (handle.error_number() != 0 && handle.error_number() != ENOENT) { if (handle.is_valid()) throw internal_error("HashTorrent::queue() valid handle with error number: " + system::errno_enum_str(handle.error_number())); // We wait for all the outstanding chunks to be checked before // borking completely, else low-memory devices might not be able // to finish the hash check. if (m_outstanding != 0) return; // The rest of the outstanding chunks get ignored by // DownloadWrapper::receive_hash_done. Obsolete. clear(); m_errno = handle.error_number(); LT_LOG_THIS(INFO, "completed with error: position:%u errno:%s", m_position, system::errno_enum(handle.error_number())); this_thread::scheduler()->update_wait_for(&m_delay_checked, 0s); return; } m_position++; if (!handle.is_valid() && handle.error_number() == 0) throw internal_error("HashTorrent::queue() invalid handle but no error."); // Missing file, skip the hash check. if (!handle.is_valid()) continue; if (m_slot_check_chunk) m_slot_check_chunk(handle); m_outstanding++; } if (m_outstanding == 0) { LT_LOG_THIS(INFO, "completed : position:%u", m_position); // Update the scheduled item just to make sure that if hashing is // started again during the delay it won't cause an exception. this_thread::scheduler()->update_wait_for(&m_delay_checked, 0s); } } } // namespace torrent libtorrent-0.16.11/src/data/chunk_handle.h0000644000000000000000000000266215175073411014001 #ifndef LIBTORRENT_DATA_CHUNK_HANDLE_H #define LIBTORRENT_DATA_CHUNK_HANDLE_H #include "chunk_list_node.h" #include namespace torrent { class ChunkListNode; class ChunkHandle { public: ChunkHandle(ChunkListNode* c = NULL, bool wr = false, bool blk = false) : m_node(c), m_writable(wr), m_blocking(blk) {} bool is_valid() const { return m_node != NULL; } bool is_loaded() const { return m_node != NULL && m_node->is_valid(); } bool is_writable() const { return m_writable; } bool is_blocking() const { return m_blocking; } void clear() { m_node = NULL; m_writable = false; m_blocking = false; } int error_number() const { return m_errno; } void set_error_number(int e) { m_errno = e; } ChunkListNode* object() const { return m_node; } Chunk* chunk() const { return m_node->chunk(); } uint32_t index() const { return m_node->index(); } static ChunkHandle from_error(int err); private: ChunkListNode* m_node{}; bool m_writable{}; bool m_blocking{}; int m_errno{}; }; inline ChunkHandle ChunkHandle::from_error(int err) { if (err == 0) err = ENOENT; ChunkHandle h; h.set_error_number(err); return h; } } // namespace torrent #endif libtorrent-0.16.11/src/data/socket_file.cc0000644000000000000000000001026015175073411013774 #include "config.h" #include "data/socket_file.h" #include #include #include #include #include "torrent/exceptions.h" #include "torrent/utils/file_stat.h" #include "torrent/utils/log.h" #define LT_LOG_ERROR(log_fmt, ...) \ lt_log_print(LOG_STORAGE, "socket_file->%i: " log_fmt, m_fd, __VA_ARGS__); namespace torrent { bool SocketFile::open(const std::string& path, int prot, int flags, mode_t mode) { close(); if (prot & MemoryChunk::prot_read && prot & MemoryChunk::prot_write) flags |= O_RDWR; else if (prot & MemoryChunk::prot_read) flags |= O_RDONLY; else if (prot & MemoryChunk::prot_write) flags |= O_WRONLY; else throw internal_error("torrent::SocketFile::open(...) Tried to open file with no protection flags"); #ifdef O_LARGEFILE fd_type fd = ::open(path.c_str(), flags | O_LARGEFILE, mode); #else fd_type fd = ::open(path.c_str(), flags, mode); #endif if (fd == invalid_fd) return false; m_fd = fd; return true; } void SocketFile::close() { if (!is_open()) return; ::close(m_fd); m_fd = invalid_fd; } uint64_t SocketFile::size() const { if (!is_open()) throw internal_error("SocketFile::size() called on a closed file"); utils::FileStat fs; return fs.update(m_fd) ? fs.size() : 0; } bool SocketFile::set_size(uint64_t size) const { if (!is_open()) throw internal_error("SocketFile::set_size() called on a closed file"); if (ftruncate(m_fd, size) == -1) { return false; } return true; } bool SocketFile::allocate([[maybe_unused]] uint64_t size, [[maybe_unused]] int flags) const { if (!is_open()) throw internal_error("SocketFile::allocate() called on a closed file"); #if defined(USE_FALLOCATE) if (flags & flag_fallocate) { if (fallocate(m_fd, 0, 0, size) == -1) { LT_LOG_ERROR("fallocate failed : %s", strerror(errno)); return false; } } #elif defined(USE_POSIX_FALLOCATE) if (flags & flag_fallocate && flags & flag_fallocate_blocking) { if (posix_fallocate(m_fd, 0, size) == -1) { LT_LOG_ERROR("posix_fallocate failed : %s", strerror(errno)); return false; } } #elif defined(SYS_DARWIN) if (flags & flag_fallocate) { fstore_t fstore; fstore.fst_flags = F_ALLOCATECONTIG; fstore.fst_posmode = F_PEOFPOSMODE; fstore.fst_offset = 0; fstore.fst_length = size; fstore.fst_bytesalloc = 0; // This shouldn't really be something we fail the set_size // on. // // Yet is somehow fails with ENOSPC. // if (fcntl(m_fd, F_PREALLOCATE, &fstore) == -1) // throw internal_error("hack: fcntl failed" + std::string(strerror(errno))); if (fcntl(m_fd, F_PREALLOCATE, &fstore) == -1) LT_LOG_ERROR("fcntl(,F_PREALLOCATE,) failed : %s", strerror(errno)); return true; } #endif return true; } MemoryChunk SocketFile::create_padding_chunk(uint32_t length, int prot, int flags) { flags |= MemoryChunk::map_anon; auto ptr = static_cast(mmap(NULL, length, prot, flags, -1, 0)); if (ptr == MAP_FAILED) return MemoryChunk(); return MemoryChunk(ptr, ptr, ptr + length, prot, flags); } MemoryChunk SocketFile::create_chunk(uint64_t offset, uint32_t length, int prot, int flags) const { if (!is_open()) throw internal_error("SocketFile::get_chunk() called on a closed file"); // For some reason mapping beyond the extent of the file does not // cause mmap to complain, so we need to check manually here. if (length == 0 || offset > size() || offset + length > size()) return MemoryChunk(); uint32_t page_size = MemoryChunk::page_size(); uint64_t align = offset % page_size; if (page_size < 4096 || page_size >= (1 << 18)) throw internal_error("SocketFile::get_chunk() page size is out-of-bounds: " + std::to_string(page_size)); if (align >= page_size) throw internal_error("SocketFile::get_chunk() alignment calculation error: " + std::to_string(align)); auto ptr = static_cast(::mmap(nullptr, length + align, prot, flags, m_fd, offset - align)); if (ptr == MAP_FAILED) return MemoryChunk(); return MemoryChunk(ptr, ptr + align, ptr + align + length, prot, flags); } } // namespace torrent libtorrent-0.16.11/src/data/hash_torrent.h0000644000000000000000000000324015175073411014047 #ifndef LIBTORRENT_DATA_HASH_TORRENT_H #define LIBTORRENT_DATA_HASH_TORRENT_H #include #include #include #include "data/chunk_handle.h" #include "torrent/utils/ranges.h" #include "torrent/utils/scheduler.h" namespace torrent { class ChunkList; class HashTorrent { public: using Ranges = ranges; using slot_chunk_handle = std::function; HashTorrent(ChunkList* c); ~HashTorrent() { clear(); } bool start(bool try_quick); void clear(); bool is_checking() const { return m_outstanding >= 0; } bool is_checked() const; void confirm_checked(); Ranges& hashing_ranges() { return m_ranges; } uint32_t position() const { return m_position; } uint32_t outstanding() const { return m_outstanding; } int error_number() const { return m_errno; } slot_chunk_handle& slot_check_chunk() { return m_slot_check_chunk; } auto& delay_checked() { return m_delay_checked; } void receive_chunkdone(uint32_t index); void receive_chunk_cleared(uint32_t index); private: void queue(bool quick); unsigned int m_position{0}; int m_outstanding{-1}; Ranges m_ranges; int m_errno{0}; ChunkList* m_chunk_list; slot_chunk_handle m_slot_check_chunk; utils::SchedulerEntry m_delay_checked; }; } // namespace torrent #endif libtorrent-0.16.11/src/data/thread_disk.h0000644000000000000000000000174115175073411013634 #ifndef LIBTORRENT_DATA_THREAD_DISK_H #define LIBTORRENT_DATA_THREAD_DISK_H #include "data/hash_check_queue.h" #include "torrent/common.h" #include "torrent/system/thread.h" namespace torrent { class LIBTORRENT_EXPORT ThreadDisk : public system::Thread { public: ~ThreadDisk() override; static void create_thread(); static void destroy_thread(); static ThreadDisk* thread_disk(); const char* name() const override { return "rtorrent disk"; } HashCheckQueue* hash_check_queue() { return &m_hash_check_queue; } void init_thread() override; void cleanup_thread() override; private: ThreadDisk() = default; void call_events() override; std::chrono::microseconds next_timeout() override; static ThreadDisk* m_thread_disk; HashCheckQueue m_hash_check_queue; }; inline ThreadDisk* thread_disk() { return ThreadDisk::thread_disk(); } } // namespace torrent #endif // LIBTORRENT_DATA_THREAD_DISK_H libtorrent-0.16.11/src/data/chunk_part.cc0000644000000000000000000000277115175073411013653 #include "config.h" #include #include "torrent/exceptions.h" #include "chunk_part.h" namespace torrent { void ChunkPart::clear() { switch (m_mapped) { case MAPPED_MMAP: m_chunk.unmap(); break; default: case MAPPED_STATIC: throw internal_error("ChunkPart::clear() only MAPPED_MMAP supported."); } m_chunk.clear(); } bool ChunkPart::is_incore(uint32_t pos, uint32_t length) { length = std::min(length, remaining_from(pos)); pos = pos - m_position; if (pos > size()) throw internal_error("ChunkPart::is_incore(...) got invalid position."); if (length > size() || pos + length > size()) throw internal_error("ChunkPart::is_incore(...) got invalid length."); return m_chunk.is_incore(pos, length); } // TODO: Buggy. uint32_t ChunkPart::incore_length(uint32_t pos, uint32_t length) { // Do we want to use this? length = std::min(length, remaining_from(pos)); pos = pos - m_position; if (pos >= size()) throw internal_error("ChunkPart::incore_length(...) got invalid position"); const uint32_t touched = m_chunk.pages_touched(pos, length); auto buf = std::make_unique(touched); auto begin = buf.get(); auto end = buf.get() + touched; m_chunk.incore(begin, pos, length); uint32_t dist = std::distance(begin, std::find(begin, end, 0)); // This doesn't properly account for alignment when calculating the length. return std::min(dist ? (dist * MemoryChunk::page_size() - m_chunk.page_align()) : 0, length); } } // namespace torrent libtorrent-0.16.11/src/data/hash_check_queue.cc0000644000000000000000000000525715175073411015003 #include "config.h" #include "hash_check_queue.h" #include "data/hash_chunk.h" #include "torrent/hash_string.h" #include "utils/instrumentation.h" namespace torrent { HashCheckQueue::HashCheckQueue() = default; HashCheckQueue::~HashCheckQueue() = default; // Always poke thread_disk after calling this. void HashCheckQueue::push_back(HashChunk* hash_chunk) { if (hash_chunk == NULL || !hash_chunk->chunk()->is_loaded() || !hash_chunk->chunk()->is_blocking()) throw internal_error("Invalid hash chunk passed to HashCheckQueue."); auto lock = std::scoped_lock(m_lock); // Set blocking...(? this needs to be possible to do after getting // the chunk) When doing this make sure we verify that the handle is // not previously blocked. base_type::push_back(hash_chunk); int64_t size = hash_chunk->chunk()->chunk()->chunk_size(); instrumentation_update(INSTRUMENTATION_MEMORY_HASHING_CHUNK_COUNT, 1); instrumentation_update(INSTRUMENTATION_MEMORY_HASHING_CHUNK_USAGE, size); } // erase... // // The erasing function should call slot, perhaps return a bool if we // deleted, or in the rare case it has already been hashed and will // arraive in the near future? // // We could handle this by polling the done chunks on false return // values. // Lock the chunk list and increment blocking only when starting the // checking. // No removal of entries, only clearing. bool HashCheckQueue::remove(HashChunk* hash_chunk) { auto lock = std::scoped_lock(m_lock); bool result; auto itr = std::find(begin(), end(), hash_chunk); if (itr != end()) { base_type::erase(itr); result = true; int64_t size = hash_chunk->chunk()->chunk()->chunk_size(); instrumentation_update(INSTRUMENTATION_MEMORY_HASHING_CHUNK_COUNT, -1); instrumentation_update(INSTRUMENTATION_MEMORY_HASHING_CHUNK_USAGE, -size); } else { result = false; } return result; } void HashCheckQueue::perform() { auto lock = std::unique_lock(m_lock); while (!empty()) { HashChunk* hash_chunk = base_type::front(); base_type::pop_front(); if (!hash_chunk->chunk()->is_loaded()) throw internal_error("HashCheckQueue::perform(): !entry.node->is_loaded()."); int64_t size = hash_chunk->chunk()->chunk()->chunk_size(); instrumentation_update(INSTRUMENTATION_MEMORY_HASHING_CHUNK_COUNT, -1); instrumentation_update(INSTRUMENTATION_MEMORY_HASHING_CHUNK_USAGE, -size); lock.unlock(); if (!hash_chunk->perform(~uint32_t(), true)) throw internal_error("HashCheckQueue::perform(): !hash_chunk->perform(~uint32_t(), true)."); HashString hash; hash_chunk->hash_c(hash.data()); m_slot_chunk_done(hash_chunk, hash); lock.lock(); } } } // namespace torrent libtorrent-0.16.11/src/data/chunk_part.h0000644000000000000000000000403515175073411013510 #ifndef LIBTORRENT_DATA_STORAGE_CHUNK_PART_H #define LIBTORRENT_DATA_STORAGE_CHUNK_PART_H #include #include "memory_chunk.h" namespace torrent { class File; class ChunkPart { public: enum mapped_type { MAPPED_MMAP, MAPPED_STATIC }; ChunkPart(mapped_type mapped, const MemoryChunk& c, uint32_t pos) : m_mapped(mapped), m_chunk(c), m_position(pos) {} bool is_valid() const { return m_chunk.is_valid(); } bool is_contained(uint32_t p) const { return p >= m_position && p < m_position + size(); } bool has_address(void* p) const { return static_cast(p) >= m_chunk.begin() && p < m_chunk.end(); } void clear(); mapped_type mapped() const { return m_mapped; } MemoryChunk& chunk() { return m_chunk; } const MemoryChunk& chunk() const { return m_chunk; } uint32_t size() const { return m_chunk.size(); } uint32_t position() const { return m_position; } uint32_t remaining_from(uint32_t pos) const { return size() - (pos - m_position); } File* file() const { return m_file; } uint64_t file_offset() const { return m_file_offset; } void set_file(File* f, uint64_t f_offset) { m_file = f; m_file_offset = f_offset; } bool is_incore(uint32_t pos, uint32_t length = ~uint32_t()); uint32_t incore_length(uint32_t pos, uint32_t length = ~uint32_t()); private: mapped_type m_mapped; MemoryChunk m_chunk; uint32_t m_position; // Currently used to figure out what file and where a SIGBUS // occurred. Can also be used in the future to indicate if a part is // temporary storage, etc. File* m_file{}; uint64_t m_file_offset{0}; }; } // namespace torrent #endif libtorrent-0.16.11/src/data/chunk_list_node.h0000644000000000000000000000523615175073411014526 #ifndef LIBTORRENT_DATA_CHUNK_LIST_NODE_H #define LIBTORRENT_DATA_CHUNK_LIST_NODE_H #include "torrent/utils/chrono.h" #include namespace torrent { class Chunk; // ChunkNode can contain information like how long since it was last // used, last synced, last checked with mincore and how many // references there are to it. // // ChunkList will make sure all the nodes are cleaned up properly, so // no dtor is needed. class ChunkListNode { public: static constexpr uint32_t invalid_index = ~uint32_t(); bool is_valid() const { return m_chunk != NULL; } uint32_t index() const { return m_index; } void set_index(uint32_t idx) { m_index = idx; } Chunk* chunk() const { return m_chunk; } void set_chunk(Chunk* c) { m_chunk = c; } auto time_modified() const { return m_time_modified; } void set_time_modified(std::chrono::microseconds t) { m_time_modified = t; } auto time_preloaded() const { return m_time_preloaded; } void set_time_preloaded(std::chrono::microseconds t) { m_time_preloaded = t; } bool sync_triggered() const { return m_async_triggered; } void set_sync_triggered(bool v) { m_async_triggered = v; } int references() const { return m_references; } int dec_references() { return --m_references; } int inc_references() { return ++m_references; } int writable() const { return m_writable; } int dec_writable() { return --m_writable; } int inc_writable() { return ++m_writable; } int blocking() const { return m_blocking; } int dec_blocking() { return --m_blocking; } int inc_blocking() { return ++m_blocking; } void inc_rw() { inc_writable(); inc_references(); } void dec_rw() { dec_writable(); dec_references(); } private: uint32_t m_index{invalid_index}; Chunk* m_chunk{}; int m_references{0}; int m_writable{0}; int m_blocking{0}; bool m_async_triggered{false}; std::chrono::microseconds m_time_modified{}; std::chrono::microseconds m_time_preloaded{}; }; } // namespace torrent #endif libtorrent-0.16.11/src/data/hash_queue.h0000644000000000000000000000346715175073411013511 #ifndef LIBTORRENT_DATA_HASH_QUEUE_H #define LIBTORRENT_DATA_HASH_QUEUE_H #include #include #include #include #include #include "torrent/hash_string.h" #include "hash_queue_node.h" #include "chunk_handle.h" namespace torrent { class HashChunk; class ThreadDisk; // Calculating hash of incore memory is blindingly fast, it's always // the loading from swap/disk that takes time. So with the exception // of large resumed downloads, try to check the hash immediately. This // helps us in getting as much done as possible while the pages are in // memory. class HashQueue : private std::deque { public: using base_type = std::deque; using done_chunks_type = std::map; using slot_done_type = HashQueueNode::slot_done_type; using slot_bool = std::function; using base_type::iterator; using base_type::empty; using base_type::size; using base_type::begin; using base_type::end; using base_type::front; using base_type::back; HashQueue() = default; ~HashQueue() { clear(); } void push_back(ChunkHandle handle, HashQueueNode::id_type id, slot_done_type d); bool has(HashQueueNode::id_type id); bool has(HashQueueNode::id_type id, uint32_t index); void remove(HashQueueNode::id_type id); void clear(); void work(); slot_bool& slot_has_work() { return m_slot_has_work; } void chunk_done(HashChunk* hash_chunk, const HashString& hash_value); private: done_chunks_type m_done_chunks; slot_bool m_slot_has_work; std::mutex m_done_chunks_lock; std::condition_variable m_cv; }; } // namespace torrent #endif libtorrent-0.16.11/src/data/hash_chunk.h0000644000000000000000000000336615175073411013473 #ifndef LIBTORRENT_HASH_CHUNK_H #define LIBTORRENT_HASH_CHUNK_H #include #include "chunk.h" #include "chunk_handle.h" #include "torrent/exceptions.h" #include "utils/sha1.h" namespace torrent { // This class interface assumes we're always going to check the whole // chunk. All we need is control of the (non-)blocking nature, and other // stuff related to performance and responsiveness. class ChunkListNode; class HashChunk { public: HashChunk(ChunkHandle h); ~HashChunk() = default; ChunkHandle* chunk() { return &m_chunk; } ChunkHandle& handle() { return m_chunk; } uint32_t remaining() const; void set_chunk(ChunkHandle h); void hash_c(char* buffer); // If force is true, then the return value is always true. bool perform(uint32_t length, bool force = true); void advise_willneed(uint32_t length); private: HashChunk(const HashChunk&) = delete; HashChunk& operator=(const HashChunk&) = delete; static uint32_t remaining_part(Chunk::iterator itr, uint32_t pos); uint32_t perform_part(Chunk::iterator itr, uint32_t length); uint32_t m_position; ChunkHandle m_chunk; Sha1 m_hash; }; inline HashChunk::HashChunk(ChunkHandle h) { set_chunk(h); } inline uint32_t HashChunk::remaining_part(Chunk::iterator itr, uint32_t pos) { return itr->size() - (pos - itr->position()); } inline uint32_t HashChunk::remaining() const { if (!m_chunk.is_loaded()) throw internal_error("HashChunk::remaining(...) called on an invalid chunk"); return m_chunk.chunk()->chunk_size() - m_position; } } // namespace torrent #endif libtorrent-0.16.11/src/data/hash_queue.cc0000644000000000000000000001053015175073411013634 #include "config.h" #include "data/hash_queue.h" #include #include #include "data/hash_chunk.h" #include "data/thread_disk.h" #include "torrent/data/download_data.h" #include "torrent/exceptions.h" #include "torrent/utils/log.h" #include "torrent/utils/string_manip.h" #define LT_LOG_DATA(data, log_level, log_fmt, ...) \ lt_log_print_data(LOG_STORAGE_##log_level, data, "hash_queue", log_fmt, __VA_ARGS__); namespace torrent { struct HashQueueEqual { HashQueueEqual(HashQueueNode::id_type id, uint32_t index) : m_id(id), m_index(index) {} bool operator () (const HashQueueNode& q) const { return m_id == q.id() && m_index == q.get_index(); } HashQueueNode::id_type m_id; uint32_t m_index; }; struct HashQueueWillneed { HashQueueWillneed(int bytes) : m_bytes(bytes) {} bool operator () (HashQueueNode& q) { return (m_bytes -= q.call_willneed()) <= 0; } int m_bytes; }; // If madvise is not available it will always mark the pages as being // in memory, thus we don't need to modify m_maxTries to have full // disk usage. But this may cause too much blocking as it will think // everything is in memory, thus we need to throttle. // If we're done immediately, move the chunk to the front of the list so // the next work cycle gets stuff done. void HashQueue::push_back(ChunkHandle handle, HashQueueNode::id_type id, slot_done_type d) { LT_LOG_DATA(id, DEBUG, "Adding index:%" PRIu32 " to queue.", handle.index()); if (!handle.is_loaded()) throw internal_error("HashQueue::add(...) received an invalid chunk"); auto hash_chunk = new HashChunk(handle); base_type::push_back(HashQueueNode(id, hash_chunk, std::move(d))); thread_disk()->hash_check_queue()->push_back(hash_chunk); thread_disk()->interrupt(); } bool HashQueue::has(HashQueueNode::id_type id) { return std::any_of(begin(), end(), [id](const auto& n) { return id == n.id(); }); } bool HashQueue::has(HashQueueNode::id_type id, uint32_t index) { return std::any_of(begin(), end(), HashQueueEqual(id, index)); } void HashQueue::remove(HashQueueNode::id_type id) { base_type::erase(std::remove_if(begin(), end(), [id, this](auto& itr) { if (itr.id() != id) return false; HashChunk *hash_chunk = itr.get_chunk(); LT_LOG_DATA(id, DEBUG, "Removing index:%" PRIu32 " from queue.", hash_chunk->handle().index()); bool result = thread_disk()->hash_check_queue()->remove(hash_chunk); // The hash chunk was not found, so we need to wait until the hash // check finishes. if (!result) { auto lock = std::unique_lock(m_done_chunks_lock); m_cv.wait(lock, [this, hash_chunk] { return m_done_chunks.find(hash_chunk) != m_done_chunks.end(); }); m_done_chunks.erase(hash_chunk); } itr.slot_done()(*hash_chunk->chunk(), NULL); itr.clear(); return true; }), end()); } void HashQueue::clear() { if (!empty()) throw internal_error("HashQueue::clear() called but valid nodes were found."); // Replace with a dtor check to ensure it is empty? // std::for_each(begin(), end(), std::mem_fn(&HashQueueNode::clear)); // base_type::clear(); } void HashQueue::work() { auto lock = std::scoped_lock(m_done_chunks_lock); while (!m_done_chunks.empty()) { HashChunk* hash_chunk = m_done_chunks.begin()->first; HashString hash_value = m_done_chunks.begin()->second; m_done_chunks.erase(m_done_chunks.begin()); // TODO: This is not optimal as we jump around... Check for front // of HashQueue in done_chunks instead. auto itr = std::find_if(begin(), end(), [hash_chunk](auto& node) { return node.get_chunk() == hash_chunk; }); // TODO: Fix this... if (itr == end()) throw internal_error("Could not find done chunk's node."); LT_LOG_DATA(itr->id(), DEBUG, "Passing index:%" PRIu32 " to owner: %s.", hash_chunk->handle().index(), utils::transform_to_hex_str(hash_value).c_str()); HashQueueNode::slot_done_type slotDone = itr->slot_done(); base_type::erase(itr); slotDone(hash_chunk->handle(), hash_value.c_str()); delete hash_chunk; } } void HashQueue::chunk_done(HashChunk* hash_chunk, const HashString& hash_value) { auto lock = std::scoped_lock(m_done_chunks_lock); m_done_chunks[hash_chunk] = hash_value; m_slot_has_work(m_done_chunks.empty()); m_cv.notify_all(); } } // namespace torrent libtorrent-0.16.11/src/data/hash_chunk.cc0000644000000000000000000000316315175073411013624 #include "config.h" #include "chunk.h" #include "chunk_list_node.h" #include "hash_chunk.h" namespace torrent { void HashChunk::set_chunk(ChunkHandle h) { m_position = 0; m_chunk = h; m_hash.init(); } void HashChunk::hash_c(char* buffer) { m_hash.final_c(buffer); } bool HashChunk::perform(uint32_t length, bool force) { length = std::min(length, remaining()); if (m_position + length > m_chunk.chunk()->chunk_size()) throw internal_error("HashChunk::perform(...) received length out of range"); uint32_t l = force ? length : m_chunk.chunk()->incore_length(m_position); bool complete = l == length; while (l) { auto node = m_chunk.chunk()->at_position(m_position); l -= perform_part(node, l); } return complete; } void HashChunk::advise_willneed(uint32_t length) { if (!m_chunk.is_valid()) throw internal_error("HashChunk::willneed(...) called on an invalid chunk"); if (m_position + length > m_chunk.chunk()->chunk_size()) throw internal_error("HashChunk::willneed(...) received length out of range"); uint32_t pos = m_position; while (length) { auto itr = m_chunk.chunk()->at_position(pos); auto l = std::min(length, remaining_part(itr, pos)); itr->chunk().advise(pos - itr->position(), l, MemoryChunk::advice_willneed); pos += l; length -= l; ++itr; } } uint32_t HashChunk::perform_part(Chunk::iterator itr, uint32_t length) { length = std::min(length, remaining_part(itr, m_position)); m_hash.update(itr->chunk().begin() + m_position - itr->position(), length); m_position += length; return length; } } // namespace torrent libtorrent-0.16.11/src/data/chunk_iterator.h0000644000000000000000000000713415175073411014376 // libTorrent - BitTorrent library // Copyright (C) 2005-2011, Jari Sundell // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // In addition, as a special exception, the copyright holders give // permission to link the code of portions of this program with the // OpenSSL library under certain conditions as described in each // individual source file, and distribute linked combinations // including the two. // // You must obey the GNU General Public License in all respects for // all of the code used other than OpenSSL. If you modify file(s) // with this exception, you may extend this exception to your version // of the file(s), but you are not obligated to do so. If you do not // wish to do so, delete this exception statement from your version. // If you delete this exception statement from all source files in the // program, then also delete it here. // // Contact: Jari Sundell // // Skomakerveien 33 // 3185 Skoppum, NORWAY #ifndef LIBTORRENT_DATA_CHUNK_ITERATOR_H #define LIBTORRENT_DATA_CHUNK_ITERATOR_H #include "chunk.h" namespace torrent { class ChunkIterator { public: ChunkIterator(Chunk* chunk, uint32_t first, uint32_t last); bool empty() const { return m_iterator == m_chunk->end() || m_first >= m_last; } // Only non-zero length ranges will be returned. Chunk::data_type data(); MemoryChunk* memory_chunk() { return &m_iterator->chunk(); } uint32_t memory_chunk_first() const { return m_first - m_iterator->position(); } uint32_t memory_chunk_last() const { return m_last - m_iterator->position(); } bool next(); bool forward(uint32_t length); private: Chunk* m_chunk; Chunk::iterator m_iterator; uint32_t m_first; uint32_t m_last; }; inline ChunkIterator::ChunkIterator(Chunk* chunk, uint32_t first, uint32_t last) : m_chunk(chunk), m_iterator(chunk->at_position(first)), m_first(first), m_last(last) { } inline Chunk::data_type ChunkIterator::data() { Chunk::data_type data = m_chunk->at_memory(m_first, m_iterator); data.second = std::min(data.second, m_last - m_first); return data; } inline bool ChunkIterator::next() { m_first = m_iterator->position() + m_iterator->size(); while (++m_iterator != m_chunk->end()) { if (m_iterator->size() != 0) return m_first < m_last; } return false; } // Returns true if the new position is on a file boundary while not at // the edges of the chunk. // // Do not return true if the length was zero, in order to avoid // getting stuck looping when no data is being read/written. inline bool ChunkIterator::forward(uint32_t length) { m_first += length; if (m_first >= m_last) return false; do { if (m_first < m_iterator->position() + m_iterator->size()) return true; m_iterator++; } while (m_iterator != m_chunk->end()); return false; } } // namespace torrent #endif libtorrent-0.16.11/src/data/hash_check_queue.h0000644000000000000000000000204215175073411014632 #ifndef LIBTORRENT_DATA_HASH_CHECK_QUEUE_H #define LIBTORRENT_DATA_HASH_CHECK_QUEUE_H #include #include #include // TODO: Create separate directory for thread_disk's hash checking code. namespace torrent { class HashString; class HashChunk; class HashCheckQueue : private std::deque { public: using base_type = std::deque; using slot_chunk_handle = std::function; using base_type::iterator; using base_type::empty; using base_type::size; using base_type::begin; using base_type::end; using base_type::front; using base_type::back; HashCheckQueue(); ~HashCheckQueue(); // Guarded functions for adding new... void push_back(HashChunk* node); void perform(); bool remove(HashChunk* node); slot_chunk_handle& slot_chunk_done() { return m_slot_chunk_done; } private: std::mutex m_lock; slot_chunk_handle m_slot_chunk_done; }; } // namespace torrent #endif libtorrent-0.16.11/src/data/thread_disk.cc0000644000000000000000000000324315175073411013771 #include "config.h" #include "data/thread_disk.h" #include #include "thread_main.h" #include "data/hash_queue.h" #include "torrent/exceptions.h" #include "torrent/net/resolver.h" #include "utils/instrumentation.h" namespace torrent { ThreadDisk* ThreadDisk::m_thread_disk{nullptr}; ThreadDisk::~ThreadDisk() = default; void ThreadDisk::create_thread() { assert(m_thread_disk == nullptr && "ThreadDisk already created."); m_thread_disk = new ThreadDisk; } void ThreadDisk::destroy_thread() { delete m_thread_disk; m_thread_disk = nullptr; } ThreadDisk* ThreadDisk::thread_disk() { return m_thread_disk; } void ThreadDisk::init_thread() { m_resolver = std::make_unique(); m_state = STATE_INITIALIZED; m_instrumentation_index = INSTRUMENTATION_POLLING_DO_POLL_DISK - INSTRUMENTATION_POLLING_DO_POLL; m_hash_check_queue.slot_chunk_done() = [](auto hc, const auto& hv) { ThreadMain::thread_main()->hash_queue()->chunk_done(hc, hv); }; } void ThreadDisk::cleanup_thread() { assert(m_hash_check_queue.empty() && "ThreadDisk::cleanup_thread(): m_hash_check_queue not empty."); } void ThreadDisk::call_events() { // lt_log_print_locked(torrent::LOG_THREAD_NOTICE, "Got thread_disk tick."); // TODO: Consider moving this into timer events instead. if ((m_flags & flag_do_shutdown)) { if ((m_flags & flag_did_shutdown)) throw internal_error("Already trigged shutdown."); m_flags |= flag_did_shutdown; throw shutdown_exception(); } m_hash_check_queue.perform(); process_callbacks(); } std::chrono::microseconds ThreadDisk::next_timeout() { return std::chrono::microseconds(10s); } } // namespace torrent libtorrent-0.16.11/src/data/chunk.cc0000644000000000000000000002030615175073411012617 // libTorrent - BitTorrent library // Copyright (C) 2005-2011, Jari Sundell // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // In addition, as a special exception, the copyright holders give // permission to link the code of portions of this program with the // OpenSSL library under certain conditions as described in each // individual source file, and distribute linked combinations // including the two. // // You must obey the GNU General Public License in all respects for // all of the code used other than OpenSSL. If you modify file(s) // with this exception, you may extend this exception to your version // of the file(s), but you are not obligated to do so. If you do not // wish to do so, delete this exception statement from your version. // If you delete this exception statement from all source files in the // program, then also delete it here. // // Contact: Jari Sundell // // Skomakerveien 33 // 3185 Skoppum, NORWAY #include "config.h" #include #include #include #include #include #include "torrent/exceptions.h" #include "chunk.h" #include "chunk_iterator.h" namespace { jmp_buf jmp_disk_full; void bus_handler(int, siginfo_t* si, void*) { if (si && si->si_code == BUS_ADRERR) longjmp(jmp_disk_full, 1); } } // namespace namespace torrent { bool Chunk::is_all_valid() const { return !empty() && std::all_of(begin(), end(), std::mem_fn(&ChunkPart::is_valid)); } void Chunk::clear() { std::for_each(begin(), end(), std::mem_fn(&ChunkPart::clear)); m_chunkSize = 0; m_prot = ~0; base_type::clear(); } // Each add calls vector's reserve adding 1. This should keep // the size of the vector at exactly what we need. Though it // will require a few more cycles, it won't matter as we only // rarely have more than 1 or 2 nodes. // // If the user knows how many chunk parts he is going to add, then he // may call reserve prior to this. void Chunk::push_back(value_type::mapped_type mapped, const MemoryChunk& c) { m_prot &= c.get_prot(); // Gcc starts the reserved size at 1 for the first insert, so we // won't be wasting any space in the general case. base_type::insert(end(), ChunkPart(mapped, c, m_chunkSize)); m_chunkSize += c.size(); } Chunk::iterator Chunk::at_position(uint32_t pos) { if (pos >= m_chunkSize) throw internal_error("Chunk::at_position(...) tried to get Chunk position out of range."); auto itr = std::find_if(begin(), end(), [pos](const auto& chunk) { return chunk.is_contained(pos); }); if (itr == end()) throw internal_error("Chunk::at_position(...) might be mangled, at_position failed horribly"); if (itr->size() == 0) throw internal_error("Chunk::at_position(...) tried to return a node with length 0"); return itr; } Chunk::data_type Chunk::at_memory(uint32_t offset, iterator part) { if (part == end()) throw internal_error("Chunk::at_memory(...) reached end."); if (!part->chunk().is_valid()) throw internal_error("Chunk::at_memory(...) chunk part isn't valid."); if (offset < part->position() || offset >= part->position() + part->size()) throw internal_error("Chunk::at_memory(...) out of range."); offset -= part->position(); return data_type(part->chunk().begin() + offset, part->size() - offset); } bool Chunk::is_incore(uint32_t pos, uint32_t length) { auto itr = at_position(pos); if (itr == end()) throw internal_error("Chunk::incore_length(...) at end()"); uint32_t last = pos + std::min(length, chunk_size() - pos); while (itr->is_incore(pos, last - pos)) { if (++itr == end() || itr->position() >= last) return true; pos = itr->position(); } return false; } // TODO: Buggy, hitting internal_error. Likely need to fix // ChunkPart::incore_length's length align. uint32_t Chunk::incore_length(uint32_t pos, uint32_t length) { uint32_t result = 0; auto itr = at_position(pos); if (itr == end()) throw internal_error("Chunk::incore_length(...) at end()"); length = std::min(length, chunk_size() - pos); do { uint32_t incore_len = itr->incore_length(pos, length); if (incore_len > length) throw internal_error("Chunk::incore_length(...) incore_len > length."); pos += incore_len; length -= incore_len; result += incore_len; } while (pos == itr->position() + itr->size() && ++itr != end()); return result; } bool Chunk::sync(int flags) { bool success = true; for (auto& c : *this) if (!c.chunk().sync(0, c.chunk().size(), flags)) success = false; return success; } void Chunk::preload(uint32_t position, uint32_t length, bool useAdvise) { if (position >= m_chunkSize) throw internal_error("Chunk::preload(...) position > m_chunkSize."); if (length == 0) return; Chunk::data_type data; ChunkIterator itr(this, position, position + std::min(length, m_chunkSize - position)); do { data = itr.data(); // Don't do preloading for zero-length chunks. if (useAdvise) { itr.memory_chunk()->advise(itr.memory_chunk_first(), data.second, MemoryChunk::advice_willneed); } else { for (char* first = static_cast(data.first), *last = static_cast(data.first) + data.second; first < last; first += 4096) [[maybe_unused]] volatile char touchChunk = *static_cast(data.first); // Make sure we touch the last page in the range. [[maybe_unused]] volatile char ouchChunk = *(static_cast(data.first) + data.second - 1); } } while (itr.next()); } // Consider using uint32_t returning first mismatch or length if // matching. bool Chunk::to_buffer(void* buffer, uint32_t position, uint32_t length) { if (position + length > m_chunkSize) throw internal_error("Chunk::to_buffer(...) position + length > m_chunkSize."); if (length == 0) return true; Chunk::data_type data; ChunkIterator itr(this, position, position + length); do { data = itr.data(); std::memcpy(buffer, data.first, data.second); buffer = static_cast(buffer) + data.second; } while (itr.next()); return true; } // Consider using uint32_t returning first mismatch or length if // matching. bool Chunk::from_buffer(const void* buffer, uint32_t position, uint32_t length) { struct sigaction sa{}, oldact; sa.sa_sigaction = &bus_handler; sa.sa_flags = SA_SIGINFO; sigfillset(&sa.sa_mask); sigaction(SIGBUS, &sa, &oldact); if (position + length > m_chunkSize) throw internal_error("Chunk::from_buffer(...) position + length > m_chunkSize."); if (length == 0) return true; Chunk::data_type data; ChunkIterator itr(this, position, position + length); if (setjmp(jmp_disk_full) == 0) { do { data = itr.data(); std::memcpy(data.first, buffer, data.second); buffer = static_cast(buffer) + data.second; } while (itr.next()); } else { throw storage_error("no space left on disk"); } sigaction(SIGBUS, &oldact, NULL); return true; } // Consider using uint32_t returning first mismatch or length if // matching. bool Chunk::compare_buffer(const void* buffer, uint32_t position, uint32_t length) { if (position + length > m_chunkSize) throw internal_error("Chunk::compare_buffer(...) position + length > m_chunkSize."); if (length == 0) return true; Chunk::data_type data; ChunkIterator itr(this, position, position + length); do { data = itr.data(); if (std::memcmp(data.first, buffer, data.second) != 0) return false; buffer = static_cast(buffer) + data.second; } while (itr.next()); return true; } } // namespace torrent libtorrent-0.16.11/src/data/chunk.h0000644000000000000000000000524415175073411012465 #ifndef LIBTORRENT_STORAGE_CHUNK_H #define LIBTORRENT_STORAGE_CHUNK_H #include #include #include #include #include "chunk_part.h" namespace torrent { class Chunk : private std::vector { public: using base_type = std::vector; using data_type = std::pair; using base_type::value_type; using base_type::iterator; using base_type::reverse_iterator; using base_type::const_iterator; using base_type::empty; using base_type::reserve; using base_type::begin; using base_type::end; using base_type::rbegin; using base_type::rend; using base_type::front; using base_type::back; Chunk() = default; ~Chunk() { clear(); } Chunk(const Chunk&) = delete; Chunk& operator=(const Chunk&) = delete; bool is_all_valid() const; // All permissions are set for empty chunks. bool is_readable() const { return m_prot & MemoryChunk::prot_read; } bool is_writable() const { return m_prot & MemoryChunk::prot_write; } bool has_permissions(int prot) const { return !(prot & ~m_prot); } uint32_t chunk_size() const { return m_chunkSize; } void clear(); void push_back(value_type::mapped_type mapped, const MemoryChunk& c); // The at_position functions only returns non-zero length iterators // or end. iterator at_position(uint32_t pos); iterator at_position(uint32_t pos, iterator itr); data_type at_memory(uint32_t offset, iterator part); iterator find_address(void* ptr); // Check how much of the chunk is incore from pos. bool is_incore(uint32_t pos, uint32_t length = ~uint32_t()); uint32_t incore_length(uint32_t pos, uint32_t length = ~uint32_t()); bool sync(int flags); void preload(uint32_t position, uint32_t length, bool useAdvise); bool to_buffer(void* buffer, uint32_t position, uint32_t length); bool from_buffer(const void* buffer, uint32_t position, uint32_t length); bool compare_buffer(const void* buffer, uint32_t position, uint32_t length); private: uint32_t m_chunkSize{}; int m_prot{~0}; }; inline Chunk::iterator Chunk::at_position(uint32_t pos, iterator itr) { while (itr != end() && itr->position() + itr->size() <= pos) itr++; return itr; } inline Chunk::iterator Chunk::find_address(void* ptr) { return std::find_if(begin(), end(), [&](auto& part) { return part.has_address(ptr); }); } } // namespace torrent #endif libtorrent-0.16.11/src/data/memory_chunk.h0000644000000000000000000001201115175073411014043 #ifndef LIBTORRENT_DATA_MEMORY_CHUNK_H #define LIBTORRENT_DATA_MEMORY_CHUNK_H #include #include #include #include #include namespace torrent { class MemoryChunk { public: // Consider information about whetever the memory maps to a file or // not, since mincore etc can only be called on files. static constexpr int prot_exec = PROT_EXEC; static constexpr int prot_read = PROT_READ; static constexpr int prot_write = PROT_WRITE; static constexpr int prot_none = PROT_NONE; static constexpr int map_shared = MAP_SHARED; static constexpr int map_anon = MAP_ANON; #ifdef USE_MADVISE static constexpr int advice_normal = MADV_NORMAL; static constexpr int advice_random = MADV_RANDOM; static constexpr int advice_sequential = MADV_SEQUENTIAL; static constexpr int advice_willneed = MADV_WILLNEED; static constexpr int advice_dontneed = MADV_DONTNEED; #else static constexpr int advice_normal = 0; static constexpr int advice_random = 1; static constexpr int advice_sequential = 2; static constexpr int advice_willneed = 3; static constexpr int advice_dontneed = 4; #endif static constexpr int sync_sync = MS_SYNC; static constexpr int sync_async = MS_ASYNC; static constexpr int sync_invalidate = MS_INVALIDATE; MemoryChunk() = default; ~MemoryChunk() { clear(); } MemoryChunk(const MemoryChunk&) = default; MemoryChunk& operator=(const MemoryChunk&) = default; // Doesn't allow ptr == NULL, use the default ctor instead. MemoryChunk(char* ptr, char* begin, char* end, int prot, int flags); bool is_valid() const { return m_ptr; } bool is_readable() const { return m_prot & PROT_READ; } bool is_writable() const { return m_prot & PROT_WRITE; } bool is_exec() const { return m_prot & PROT_EXEC; } inline bool is_valid_range(uint32_t offset, uint32_t length) const; bool has_permissions(int prot) const { return !(prot & ~m_prot); } char* ptr() const { return m_ptr; } char* begin() const { return m_begin; } char* end() const { return m_end; } int get_prot() const { return m_prot; } uint32_t size() const { return m_end - m_begin; } uint32_t size_aligned() const; inline void clear(); void unmap(); // Use errno and strerror if you want to know why these failed. void incore(char* buf, uint32_t offset, uint32_t length); bool advise(uint32_t offset, uint32_t length, int advice); bool sync(uint32_t offset, uint32_t length, int flags); bool is_incore(uint32_t offset, uint32_t length); // Helper functions for aligning offsets and ranges to page boundaries. uint32_t page_align() const { return m_begin - m_ptr; } uint32_t page_align(uint32_t o) const { return (o + page_align()) % m_pagesize; } // This won't return correct values if length == 0. inline uint32_t pages_touched(uint32_t offset, uint32_t length) const; static uint32_t page_size() { return m_pagesize; } private: inline void align_pair(uint32_t* offset, uint32_t* length) const; static uint32_t m_pagesize; char* m_ptr{}; char* m_begin{}; char* m_end{}; int m_prot; int m_flags{PROT_NONE}; }; inline bool MemoryChunk::is_valid_range(uint32_t offset, uint32_t length) const { return length != 0 && static_cast(offset) + length <= size(); } inline void MemoryChunk::clear() { m_ptr = m_begin = m_end = NULL; m_flags = PROT_NONE; } inline uint32_t MemoryChunk::pages_touched(uint32_t offset, uint32_t length) const { if (length == 0) return 0; return (length + page_align(offset) + m_pagesize - 1) / m_pagesize; } // The size of the mapped memory. inline uint32_t MemoryChunk::size_aligned() const { return std::distance(m_ptr, m_end) + page_size() - ((std::distance(m_ptr, m_end) - 1) % page_size() + 1); } inline bool MemoryChunk::is_incore(uint32_t offset, uint32_t length) { const uint32_t size = pages_touched(offset, length); auto buf = std::make_unique(size); auto begin = buf.get(); auto end = begin + size; incore(begin, offset, length); return std::find(begin, end, 0) == end; } } // namespace torrent #endif libtorrent-0.16.11/src/data/chunk_list.h0000644000000000000000000001203015175073411013507 #ifndef LIBTORRENT_DATA_CHUNK_LIST_H #define LIBTORRENT_DATA_CHUNK_LIST_H #include #include #include #include "chunk.h" #include "chunk_handle.h" #include "chunk_list_node.h" namespace torrent { class ChunkManager; class Content; class download_data; class DownloadWrapper; class FileList; class ChunkList : private std::vector { public: using size_type = uint32_t; using base_type = std::vector; using Queue = std::vector; using slot_chunk_index = std::function; using slot_value = std::function; using slot_string = std::function; using base_type::value_type; using base_type::reference; using base_type::difference_type; using base_type::iterator; using base_type::reverse_iterator; using base_type::const_iterator; using base_type::begin; using base_type::end; using base_type::size; using base_type::empty; using base_type::operator[]; enum sync_flags { sync_all = (1 << 0), sync_force = (1 << 1), sync_safe = (1 << 2), sync_sloppy = (1 << 3), sync_use_timeout = (1 << 4), sync_ignore_error = (1 << 5) }; enum get_flags { get_writable = (1 << 0), get_blocking = (1 << 1), get_nonblock = (1 << 2), get_hashing = (1 << 3), get_not_hashing = (1 << 4), get_dont_log = (1 << 5) }; enum release_flags { release_default = 0, release_dont_log = (1 << 0) }; static constexpr int flag_active = (1 << 0); ChunkList() = default; ~ChunkList() { clear(); } int flags() const { return m_flags; } void set_flags(int flags) { m_flags |= flags; } void unset_flags(int flags) { m_flags &= ~flags; } void change_flags(int flags, bool state) { if (state) set_flags(flags); else unset_flags(flags); } uint32_t chunk_size() const { return m_chunk_size; } size_type queue_size() const { return m_queue.size(); } download_data* data() { return m_data; } void set_data(download_data* data) { m_data = data; } void set_manager(ChunkManager* manager) { m_manager = manager; } void set_chunk_size(uint32_t cs) { m_chunk_size = cs; } bool has_chunk(size_type index, int prot) const; void resize(size_type to_size); void clear(); ChunkHandle get(size_type index, get_flags flags); void release(ChunkHandle* handle, release_flags flags); // Replace use_timeout with something like performance related // keyword. Then use that flag to decide if we should skip // non-continious regions. // Returns the number of failed syncs. uint32_t sync_chunks(sync_flags flags); slot_string& slot_storage_error() { return m_slot_storage_error; } slot_chunk_index& slot_create_chunk() { return m_slot_create_chunk; } slot_chunk_index& slot_create_hashing_chunk() { return m_slot_create_hashing_chunk; } slot_value& slot_free_diskspace() { return m_slot_free_diskspace; } using chunk_address_result = std::pair; chunk_address_result find_address(void* ptr); private: ChunkList(const ChunkList&) = delete; ChunkList& operator=(const ChunkList&) = delete; inline bool is_queued(ChunkListNode* node); inline void clear_chunk(ChunkListNode* node, release_flags flags); inline bool sync_chunk(ChunkListNode* node, std::pair options); Queue::iterator partition_optimize(Queue::iterator first, Queue::iterator last, int weight, int maxDistance, bool dontSkip); static Queue::iterator seek_range(Queue::iterator first, Queue::iterator last); inline bool check_node(ChunkListNode* node); static std::pair sync_options(ChunkListNode* node, sync_flags flags); download_data* m_data{}; ChunkManager* m_manager{}; Queue m_queue; int m_flags{0}; uint32_t m_chunk_size{0}; slot_string m_slot_storage_error; slot_chunk_index m_slot_create_chunk; slot_chunk_index m_slot_create_hashing_chunk; slot_value m_slot_free_diskspace; }; inline ChunkList::sync_flags operator|(ChunkList::sync_flags a, ChunkList::sync_flags b) { return static_cast(static_cast(a) | static_cast(b)); } inline ChunkList::get_flags operator|(ChunkList::get_flags a, ChunkList::get_flags b) { return static_cast(static_cast(a) | static_cast(b)); } inline ChunkList::release_flags operator|(ChunkList::release_flags a, ChunkList::release_flags b) { return static_cast(static_cast(a) | static_cast(b)); } } // namespace torrent #endif libtorrent-0.16.11/src/download/0000755000000000000000000000000015175073434012162 5libtorrent-0.16.11/src/download/delegator.cc0000644000000000000000000001156015175073411014355 #include "config.h" #include "torrent/bitfield.h" #include "torrent/data/block.h" #include "torrent/data/block_list.h" #include "torrent/data/block_transfer.h" #include "protocol/peer_chunks.h" #include "delegator.h" namespace torrent { std::vector Delegator::delegate(PeerChunks* peerChunks, uint32_t affinity, uint32_t maxPieces) { // TODO: Make sure we don't queue the same piece several time on the same peer when // it timeout cancels them. std::vector new_transfers; PeerInfo* peerInfo = peerChunks->peer_info(); // Find piece with same index as affinity. This affinity should ensure that we // never start another piece while the chunk this peer used to download is still // in progress. // TODO: What if the hash failed? Don't want data from that peer again. if (affinity >= 0) { for (BlockList* itr : m_transfers) { if (new_transfers.size() >= maxPieces) return new_transfers; if (affinity == itr->index()) delegate_from_blocklist(new_transfers, maxPieces, itr, peerInfo); } } // Prioritize full seeders if (peerChunks->is_seeder()) { for (BlockList* itr : m_transfers) { if (new_transfers.size() >= maxPieces) return new_transfers; if (itr->by_seeder()) delegate_from_blocklist(new_transfers, maxPieces, itr, peerInfo); } // Create new high priority pieces. delegate_new_chunks(new_transfers, maxPieces, peerChunks, true); // Create new normal priority pieces. delegate_new_chunks(new_transfers, maxPieces, peerChunks, false); } if (new_transfers.size() >= maxPieces) return new_transfers; // Find existing high priority pieces. for (BlockList* itr : m_transfers) { if (new_transfers.size() >= maxPieces) return new_transfers; if (itr->priority() == PRIORITY_HIGH && peerChunks->bitfield()->get(itr->index())) delegate_from_blocklist(new_transfers, maxPieces, itr, peerInfo); } // Create new high priority pieces. delegate_new_chunks(new_transfers, maxPieces, peerChunks, true); // Find existing normal priority pieces. for (BlockList* itr : m_transfers) { if (new_transfers.size() >= maxPieces) return new_transfers; if (itr->priority() == PRIORITY_NORMAL && peerChunks->bitfield()->get(itr->index())) delegate_from_blocklist(new_transfers, maxPieces, itr, peerInfo); } // Create new normal priority pieces. delegate_new_chunks(new_transfers, maxPieces, peerChunks, false); if (!m_aggressive) return new_transfers; // In aggressive mode, look for possible downloads that already have // one or more transfers queued. // No more than 4 per piece. uint16_t overlapped = 5; for (BlockList* itr : m_transfers) { if (new_transfers.size() >= maxPieces) return new_transfers; if (peerChunks->bitfield()->get(itr->index()) && itr->priority() != PRIORITY_OFF) { for (auto bl_itr = itr->begin(); bl_itr != itr->end() && overlapped != 0; bl_itr++) { if (new_transfers.size() >= maxPieces || bl_itr->size_not_stalled() >= overlapped) break; if (!bl_itr->is_finished()) { BlockTransfer* inserted_info = bl_itr->insert(peerInfo); if (inserted_info != NULL) { new_transfers.push_back(inserted_info); overlapped = bl_itr->size_not_stalled(); } } } } } return new_transfers; } void Delegator::delegate_new_chunks(std::vector &transfers, uint32_t maxPieces, PeerChunks* pc, bool highPriority) { // Find new chunks and if successful, add all possible pieces into `transfers` while (transfers.size() < maxPieces) { uint32_t index = m_slot_chunk_find(pc, highPriority); if (index == ~uint32_t{0}) return; auto itr = m_transfers.insert(Piece(index, 0, m_slot_chunk_size(index)), block_size); (*itr)->set_by_seeder(pc->is_seeder()); if (highPriority) (*itr)->set_priority(PRIORITY_HIGH); else (*itr)->set_priority(PRIORITY_NORMAL); delegate_from_blocklist(transfers, maxPieces, *itr, pc->peer_info()); } } void Delegator::delegate_from_blocklist(std::vector &transfers, uint32_t maxPieces, BlockList* c, PeerInfo* peerInfo) { for (auto i = c->begin(); i != c->end() && transfers.size() < maxPieces; ++i) { // If not finished and stalled, and no one is downloading this, then assign if (!i->is_finished() && i->is_stalled() && i->size_all() == 0) transfers.push_back(i->insert(peerInfo)); } if (transfers.size() >= maxPieces) return; // Fill any remaining slots with potentially stalled pieces. for (auto i = c->begin(); i != c->end() && transfers.size() < maxPieces; ++i) { if (!i->is_finished() && i->is_stalled()) { BlockTransfer* inserted_info = i->insert(peerInfo); if (inserted_info != NULL) transfers.push_back(inserted_info); } } } } // namespace torrent libtorrent-0.16.11/src/download/chunk_selector.h0000644000000000000000000000635715175073411015271 #ifndef LIBTORRENT_DOWNLOAD_CHUNK_SELECTOR_H #define LIBTORRENT_DOWNLOAD_CHUNK_SELECTOR_H #include #include "torrent/bitfield.h" #include "torrent/data/download_data.h" #include "torrent/utils/ranges.h" #include "utils/partial_queue.h" namespace torrent { // This class is responsible for deciding on which chunk index to // download next based on the peer's bitfield. It keeps its own // bitfield which starts out as a copy of Content::bitfield but sets // chunks that are being downloaded. // // When updating Content::bitfield, make sure you update this bitfield // and unmark any chunks in Delegator. class ChunkStatistics; class PeerChunks; class ChunkSelector { public: static constexpr auto invalid_chunk = ~uint32_t{0}; ChunkSelector(download_data* data) : m_data(data) {} bool empty() const { return size() == 0; } uint32_t size() const { return m_data->untouched_bitfield()->size_bits(); } // const Bitfield* bitfield() { return m_data->untouched_bitfield(); } // priority_ranges* high_priority() { return &m_highPriority; } // priority_ranges* normal_priority() { return &m_normalPriority; } // Initialize doesn't update the priority cache, so it is as if it // has empty priority ranges. void initialize(ChunkStatistics* cs); void cleanup(); // Call this once you've modified the bitfield or priorities to // update cached information. This must be called once before using // find. void update_priorities(); uint32_t find(PeerChunks* pc, bool highPriority); bool is_wanted(uint32_t index) const; // Call this to set the index as being downloaded, finished etc, // thus ignored. Propably should find a better name for this. void using_index(uint32_t index); void not_using_index(uint32_t index); // The caller must ensure that the chunk index is valid and has not // been set already. // // The user only needs to call this when it needs to know whetever // it should become interested, or if it is in the process of // downloading. // // Returns whetever we're interested in that piece. bool received_have_chunk(PeerChunks* pc, uint32_t index); private: bool search_linear(const Bitfield* bf, utils::PartialQueue* pq, const download_data::priority_ranges* ranges, uint32_t first, uint32_t last); inline bool search_linear_range(const Bitfield* bf, utils::PartialQueue* pq, uint32_t first, uint32_t last); inline bool search_linear_byte(utils::PartialQueue* pq, uint32_t index, Bitfield::value_type wanted); // inline uint32_t search_rarest(const Bitfield* bf, priority_ranges* ranges, uint32_t first, uint32_t last); // inline uint32_t search_rarest_range(const Bitfield* bf, uint32_t first, uint32_t last); // inline uint32_t search_rarest_byte(uint8_t wanted); void advance_position(); download_data* m_data; ChunkStatistics* m_statistics; utils::PartialQueue m_sharedQueue; uint32_t m_position; }; } // namespace torrent #endif // LIBTORRENT_DOWNLOAD_CHUNK_SELECTOR_H libtorrent-0.16.11/src/download/chunk_selector.cc0000644000000000000000000001664615175073411015431 #include "config.h" #include "download/chunk_selector.h" #include #include #include "download/chunk_statistics.h" #include "protocol/peer_chunks.h" #include "torrent/exceptions.h" namespace torrent { // Consider making statistics a part of selector. void ChunkSelector::initialize(ChunkStatistics* cs) { m_position = invalid_chunk; m_statistics = cs; Bitfield* completed = m_data->mutable_completed_bitfield(); Bitfield* untouched = m_data->mutable_untouched_bitfield(); untouched->set_size_bits(completed->size_bits()); untouched->allocate(); std::transform(completed->begin(), completed->end(), untouched->begin(), [](const Bitfield::value_type& v) { return ~v; }); untouched->update(); m_sharedQueue.enable(32); m_sharedQueue.clear(); } void ChunkSelector::cleanup() { m_data->mutable_untouched_bitfield()->clear(); m_statistics = NULL; } // Consider if ChunksSelector::not_using_index(...) needs to be // modified. void ChunkSelector::update_priorities() { if (empty()) return; m_sharedQueue.clear(); if (m_position == invalid_chunk) m_position = random() % size(); advance_position(); } uint32_t ChunkSelector::find(PeerChunks* pc, [[maybe_unused]] bool highPriority) { // This needs to be re-enabled. if (m_position == invalid_chunk) return invalid_chunk; // When we're a seeder, 'm_sharedQueue' is used. Since the peer's // bitfield is guaranteed to be filled we can use the same code as // for non-seeders. This generalization does incur a slight // performance hit as it compares against a bitfield we know has all // set. auto* queue = pc->is_seeder() ? &m_sharedQueue : pc->download_cache(); // Randomize position on average every 16 chunks to prevent // inefficient distribution with a slow seed and fast peers // all arriving at the same position. if ((random() & 63) == 0) { m_position = random() % size(); queue->clear(); } if (queue->is_enabled()) { // First check the cached queue. while (queue->prepare_pop()) { uint32_t pos = queue->pop(); if (!m_data->untouched_bitfield()->get(pos)) continue; return pos; } } else { // Only non-seeders can reach this branch as m_sharedQueue is // always enabled. queue->enable(8); } queue->clear(); (search_linear(pc->bitfield(), queue, m_data->high_priority(), m_position, size()) && search_linear(pc->bitfield(), queue, m_data->high_priority(), 0, m_position)); if (queue->prepare_pop()) { // Set that the peer has high priority pieces cached. } else { // Set that the peer has normal priority pieces cached. // Urgh... queue->clear(); (search_linear(pc->bitfield(), queue, m_data->normal_priority(), m_position, size()) && search_linear(pc->bitfield(), queue, m_data->normal_priority(), 0, m_position)); if (!queue->prepare_pop()) return invalid_chunk; } uint32_t pos = queue->pop(); if (!m_data->untouched_bitfield()->get(pos)) throw internal_error("ChunkSelector::find(...) bad index."); return pos; } bool ChunkSelector::is_wanted(uint32_t index) const { return m_data->untouched_bitfield()->get(index) && (m_data->normal_priority()->has(index) || m_data->high_priority()->has(index)); } void ChunkSelector::using_index(uint32_t index) { if (index >= size()) throw internal_error("ChunkSelector::select_index(...) index out of range."); if (!m_data->untouched_bitfield()->get(index)) throw internal_error("ChunkSelector::select_index(...) index already set."); m_data->mutable_untouched_bitfield()->unset(index); // We always know 'm_position' points to a wanted chunk. If it // changes, we need to move m_position to the next one. if (index == m_position) advance_position(); } void ChunkSelector::not_using_index(uint32_t index) { if (index >= size()) throw internal_error("ChunkSelector::deselect_index(...) index out of range."); if (m_data->untouched_bitfield()->get(index)) throw internal_error("ChunkSelector::deselect_index(...) index already unset."); m_data->mutable_untouched_bitfield()->set(index); // This will make sure that if we enable new chunks, it will start // downloading them event when 'index == invalid_chunk'. if (m_position == invalid_chunk) m_position = index; } // This could propably be split into two functions, one for checking // if it shoul insert into the request_list(), and the other // whetever we are interested in the new piece. // // Since this gets called whenever a new piece arrives, we can skip // the rarity-first/linear etc searches through bitfields and just // start downloading. bool ChunkSelector::received_have_chunk(PeerChunks* pc, uint32_t index) { if (!m_data->untouched_bitfield()->get(index)) return false; // Also check if the peer only has high-priority chunks. if (!m_data->high_priority()->has(index) && !m_data->normal_priority()->has(index)) return false; if (pc->download_cache()->is_enabled()) pc->download_cache()->insert(m_statistics->rarity(index), index); return true; } bool ChunkSelector::search_linear(const Bitfield* bf, utils::PartialQueue* pq, const download_data::priority_ranges* ranges, uint32_t first, uint32_t last) { auto itr = ranges->find(first); while (itr != ranges->end() && itr->first < last) { if (!search_linear_range(bf, pq, std::max(first, itr->first), std::min(last, itr->second))) return false; ++itr; } return true; } // Could propably add another argument for max seen or something, this // would be used to find better chunks to request. inline bool ChunkSelector::search_linear_range(const Bitfield* bf, utils::PartialQueue* pq, uint32_t first, uint32_t last) { if (first >= last || last > size()) throw internal_error("ChunkSelector::search_linear_range(...) received an invalid range."); auto local = m_data->untouched_bitfield()->begin() + first / 8; auto source = bf->begin() + first / 8; // Unset any bits before 'first'. Bitfield::value_type wanted = (*source & *local) & Bitfield::mask_from(first % 8); while (m_data->untouched_bitfield()->position(local + 1) < last) { if (wanted && !search_linear_byte(pq, m_data->untouched_bitfield()->position(local), wanted)) return false; wanted = (*++source & *++local); } // Unset any bits from 'last'. wanted &= Bitfield::mask_before(last - m_data->untouched_bitfield()->position(local)); if (wanted) return search_linear_byte(pq, m_data->untouched_bitfield()->position(local), wanted); else return true; } // Take pointer to partial_queue inline bool ChunkSelector::search_linear_byte(utils::PartialQueue* pq, uint32_t index, Bitfield::value_type wanted) { for (int i = 0; i < 8; ++i) { if (!(wanted & Bitfield::mask_at(i))) continue; if (!pq->insert(m_statistics->rarity(index + i), index + i) && pq->is_full()) return false; } return true; } void ChunkSelector::advance_position() { // Need to replace with a special-purpose function for finding the // next position. // int position = m_position; // ((m_position = search_linear(&m_bitfield, &m_highPriority, position, size())) == invalid_chunk && // (m_position = search_linear(&m_bitfield, &m_highPriority, 0, position)) == invalid_chunk && // (m_position = search_linear(&m_bitfield, &m_normalPriority, position, size())) == invalid_chunk && // (m_position = search_linear(&m_bitfield, &m_normalPriority, 0, position)) == invalid_chunk); } } // namespace torrent libtorrent-0.16.11/src/download/download_main.h0000644000000000000000000001510115175073411015057 #ifndef LIBTORRENT_DOWNLOAD_MAIN_H #define LIBTORRENT_DOWNLOAD_MAIN_H #include #include #include "data/chunk_handle.h" #include "download/delegator.h" #include "net/address_list.h" #include "net/data_buffer.h" #include "torrent/data/file_list.h" #include "torrent/download/group_entry.h" #include "torrent/peer/peer_list.h" #include "torrent/tracker/wrappers.h" #include "torrent/utils/scheduler.h" namespace torrent { class ChunkList; class ChunkSelector; class ChunkStatistics; class choke_group; class ConnectionList; class DownloadWrapper; class HandshakeManager; class DownloadInfo; class ThrottleList; class InitialSeeding; class DownloadMain { public: using have_queue_type = std::deque>; using pex_list = std::vector; DownloadMain(); ~DownloadMain(); DownloadMain(const DownloadMain&) = delete; DownloadMain& operator=(const DownloadMain&) = delete; void post_initialize(); void open(int flags); void close(); void start(int flags); void stop(); class choke_group* choke_group() { return m_choke_group; } const class choke_group* c_choke_group() const { return m_choke_group; } void set_choke_group(class choke_group* grp) { m_choke_group = grp; } tracker::TrackerControllerWrapper tracker_controller() { return m_tracker_controller; } TrackerList* tracker_list() { return m_tracker_list; } DownloadInfo* info() { return m_info; } // Only retrieve writable chunks when the download is active. ChunkList* chunk_list() { return m_chunkList; } ChunkSelector* chunk_selector() { return m_chunkSelector; } ChunkStatistics* chunk_statistics() { return m_chunkStatistics; } Delegator* delegator() { return &m_delegator; } have_queue_type* have_queue() { return &m_haveQueue; } InitialSeeding* initial_seeding() { return m_initial_seeding.get(); } bool start_initial_seeding(); void initial_seeding_done(PeerConnectionBase* pcb); ConnectionList* connection_list() { return m_connectionList; } FileList* file_list() { return &m_fileList; } PeerList* peer_list() { return &m_peerList; } std::pair throttles(const sockaddr* sa); ThrottleList* upload_throttle() { return m_upload_throttle; } void set_upload_throttle(ThrottleList* t) { m_upload_throttle = t; } ThrottleList* download_throttle() { return m_download_throttle; } void set_download_throttle(ThrottleList* t) { m_download_throttle = t; } group_entry* up_group_entry() { return &m_up_group_entry; } group_entry* down_group_entry() { return &m_down_group_entry; } DataBuffer get_ut_pex(bool initial) { return (initial ? m_ut_pex_initial : m_ut_pex_delta).clone(); } bool want_pex_msg(); void set_metadata_size(size_t s); // Carefull with these. void setup_delegator(); void setup_tracker(); using slot_count_handshakes_type = std::function; using slot_hash_check_add_type = std::function; using slot_start_handshake_type = std::function; using slot_stop_handshakes_type = std::function; void slot_start_handshake(slot_start_handshake_type s) { m_slot_start_handshake = std::move(s); } void slot_stop_handshakes(slot_stop_handshakes_type s) { m_slot_stop_handshakes = std::move(s); } void slot_count_handshakes(slot_count_handshakes_type s) { m_slot_count_handshakes = std::move(s); } void slot_hash_check_add(slot_hash_check_add_type s) { m_slot_hash_check_add = std::move(s); } void add_peer(const sockaddr* sa); void receive_connect_peers(); void receive_chunk_done(unsigned int index); void receive_corrupt_chunk(PeerInfo* peerInfo); void receive_tracker_success(); void receive_tracker_request(); void receive_do_peer_exchange(); void do_peer_exchange(); void update_endgame(); auto& delay_download_done() { return m_delay_download_done; } auto& delay_partially_done() { return m_delay_partially_done; } auto& delay_partially_restarted() { return m_delay_partially_restarted; } auto& delay_disconnect_peers() { return m_delay_disconnect_peers; } private: void setup_start(); void setup_stop(); DownloadInfo* m_info; tracker::TrackerControllerWrapper m_tracker_controller; TrackerList* m_tracker_list; class choke_group* m_choke_group{}; group_entry m_up_group_entry; group_entry m_down_group_entry; ChunkList* m_chunkList; ChunkSelector* m_chunkSelector; ChunkStatistics* m_chunkStatistics; Delegator m_delegator; have_queue_type m_haveQueue; std::unique_ptr m_initial_seeding; ConnectionList* m_connectionList; FileList m_fileList; PeerList m_peerList; DataBuffer m_ut_pex_delta; DataBuffer m_ut_pex_initial; pex_list m_ut_pex_list; ThrottleList* m_upload_throttle{}; ThrottleList* m_download_throttle{}; slot_start_handshake_type m_slot_start_handshake; slot_stop_handshakes_type m_slot_stop_handshakes; slot_count_handshakes_type m_slot_count_handshakes; slot_hash_check_add_type m_slot_hash_check_add; utils::SchedulerEntry m_delay_download_done; utils::SchedulerEntry m_delay_partially_done; utils::SchedulerEntry m_delay_partially_restarted; utils::SchedulerEntry m_delay_disconnect_peers; utils::SchedulerEntry m_task_tracker_request; }; } // namespace torrent #endif libtorrent-0.16.11/src/download/download_wrapper.h0000644000000000000000000000607715175073411015627 #ifndef LIBTORRENT_DOWNLOAD_WRAPPER_H #define LIBTORRENT_DOWNLOAD_WRAPPER_H #include "data/chunk_handle.h" #include "download_main.h" namespace torrent { // Remember to clean up the pointers, DownloadWrapper won't do it. class AddressList; class FileManager; class HashQueue; class HashTorrent; class HandshakeManager; class DownloadInfo; class Object; class Peer; class DownloadWrapper { public: DownloadWrapper(); ~DownloadWrapper(); DownloadWrapper(const DownloadWrapper&) = delete; DownloadWrapper& operator=(const DownloadWrapper&) = delete; DownloadInfo* info() { return m_main->info(); } download_data* data() { return m_main->file_list()->mutable_data(); } FileList* file_list() { return m_main->file_list(); } ChunkList* chunk_list() { return m_main->chunk_list(); } // Initialize hash checker and various download stuff. void initialize(const std::string& hash, const std::string& id, uint32_t tracker_key); void close(); bool is_stopped() const; DownloadMain* main() { return m_main.get(); } const DownloadMain* main() const { return m_main.get(); } HashTorrent* hash_checker() { return m_hash_checker.get(); } Object* bencode() { return m_bencode.get(); } void set_bencode(Object* o) { m_bencode.reset(o); } HashQueue* hash_queue() { return m_hash_queue; } void set_hash_queue(HashQueue* q) { m_hash_queue = q; } const std::string& complete_hash() { return m_hash; } const char* chunk_hash(unsigned int index) { return m_hash.c_str() + 20 * index; } void set_complete_hash(const std::string& hash) { m_hash = hash; } int connection_type() const { return m_connectionType; } void set_connection_type(int t) { m_connectionType = t; } // // Internal: // void receive_initial_hash(); void receive_hash_done(ChunkHandle handle, const char* hash); void check_chunk_hash(ChunkHandle handle, bool hashing); void receive_storage_error(const std::string& str); uint32_t receive_tracker_success(AddressList* l); void receive_tracker_failed(const std::string& msg); void receive_tick(uint32_t ticks); void receive_update_priorities(); private: void finished_download(); std::unique_ptr m_main; std::unique_ptr m_bencode; std::unique_ptr m_hash_checker; HashQueue* m_hash_queue; std::string m_hash; int m_connectionType{0}; }; } // namespace torrent #endif libtorrent-0.16.11/src/download/available_list.cc0000644000000000000000000000265315175073411015365 #include "config.h" #include #include #include "download/available_list.h" #include "torrent/exceptions.h" #include "torrent/net/socket_address.h" namespace torrent { AvailableList::value_type AvailableList::pop_random() { if (empty()) throw internal_error("AvailableList::pop_random() called on an empty container"); size_type idx = random() % size(); auto tmp = std::move(*(begin() + idx)); *(begin() + idx) = std::move(back()); pop_back(); return tmp; } void AvailableList::insert(AddressList* source_list) { if (!want_more()) return; source_list->sort(); std::sort(begin(), end(), [](auto& a, auto& b) { return sa_less(&a.sa, &b.sa); }); // Can we use the std::remove* semantics for this, and just copy to 'l'?. // // 'l' is guaranteed to be sorted, so we can just do std::set_difference. AddressList difference; std::set_difference(source_list->begin(), source_list->end(), begin(), end(), std::back_inserter(difference), [](auto& a, auto& b) { return sa_less(&a.sa, &b.sa); }); base_type::insert(end(), difference.begin(), difference.end()); } bool AvailableList::insert_unique(const sockaddr* sa) { if (std::find_if(begin(), end(), [sa](auto& a) { return sa_equal(&a.sa, sa); }) != end()) return false; base_type::push_back(sa_inet_union_from_sa(sa)); return true; } } // namespace torrent libtorrent-0.16.11/src/download/download_wrapper.cc0000644000000000000000000003127515175073411015763 #include "config.h" #include "download/download_wrapper.h" #include "data/chunk_list.h" #include "data/hash_queue.h" #include "data/hash_torrent.h" #include "download/chunk_selector.h" #include "protocol/handshake_manager.h" #include "protocol/peer_connection_base.h" #include "torrent/data/file.h" #include "torrent/data/file_list.h" #include "torrent/data/file_manager.h" #include "torrent/download_info.h" #include "torrent/peer/connection_list.h" #include "torrent/peer/peer.h" #include "torrent/tracker/manager.h" #include "torrent/utils/log.h" #include "tracker/thread_tracker.h" #include "tracker/tracker_list.h" #include "utils/functional.h" #include "utils/sha1.h" #define LT_LOG_THIS(log_fmt, ...) \ lt_log_print_info(LOG_TORRENT_INFO, this->info(), "download", log_fmt, __VA_ARGS__); #define LT_LOG_STORAGE_ERRORS(log_fmt, ...) \ lt_log_print_info(LOG_PROTOCOL_STORAGE_ERRORS, this->info(), "storage_errors", log_fmt, __VA_ARGS__); namespace torrent { DownloadWrapper::DownloadWrapper() : m_main(new DownloadMain) { m_main->delay_download_done().slot() = [this] { data()->call_download_done(); }; m_main->delay_partially_done().slot() = [this] { data()->call_partially_done(); }; m_main->delay_partially_restarted().slot() = [this] { data()->call_partially_restarted(); }; m_main->peer_list()->set_info(info()); m_main->tracker_list()->set_info(info()); m_main->chunk_list()->slot_storage_error() = [this](const auto& str) { receive_storage_error(str); }; } DownloadWrapper::~DownloadWrapper() { if (info()->is_active()) m_main->stop(); if (info()->is_open()) close(); // Check if needed. m_main->connection_list()->clear(); m_main->tracker_list()->clear(); if (m_main->tracker_controller().is_valid()) { // If the client wants to do a quick cleanup after calling close, it // will need to manually cancel the tracker requests. m_main->tracker_controller().close(); thread_tracker()->tracker_manager()->remove_controller(m_main->tracker_controller()); m_main->tracker_controller().get_shared().reset(); } } void DownloadWrapper::initialize(const std::string& hash, const std::string& id, uint32_t tracker_key) { char hashObfuscated[20]; sha1_salt("req2", 4, hash.c_str(), hash.length(), hashObfuscated); info()->mutable_hash().assign(hash.c_str()); info()->mutable_hash_obfuscated().assign(hashObfuscated); info()->mutable_local_id().assign(id.c_str()); info()->slot_left() = [this] { return m_main->file_list()->left_bytes(); }; info()->slot_completed() = [this] { return m_main->file_list()->completed_bytes(); }; file_list()->mutable_data()->mutable_hash().assign(hash.c_str()); m_main->tracker_list()->set_key(tracker_key); m_main->slot_hash_check_add([this](torrent::ChunkHandle handle) { return check_chunk_hash(handle, false); }); // Info hash must be calculate from here on. m_hash_checker = std::make_unique(m_main->chunk_list()); // Connect various signals and slots. m_hash_checker->slot_check_chunk() = [this](auto h) { check_chunk_hash(h, true); }; m_hash_checker->delay_checked().slot() = [this] { receive_initial_hash(); }; m_main->post_initialize(); m_main->tracker_controller().set_slots([this](auto l) { return receive_tracker_success(l); }, [this](auto& m) { return receive_tracker_failed(m); }); } void DownloadWrapper::close() { // Stop the hashing first as we need to make sure all chunks are // released when DownloadMain::close() is called. m_hash_checker->clear(); // Clear after m_hash_checker to ensure that the empty hash done signal does // not get passed to HashTorrent. hash_queue()->remove(data()); // This could/should be async as we do not care that much if it // succeeds or not, any chunks not included in that last // hash_resume_save get ignored anyway. m_main->chunk_list()->sync_chunks(ChunkList::sync_all | ChunkList::sync_force | ChunkList::sync_sloppy | ChunkList::sync_ignore_error); m_main->close(); // Should this perhaps be in stop? this_thread::scheduler()->erase(&m_main->delay_download_done()); this_thread::scheduler()->erase(&m_main->delay_partially_done()); this_thread::scheduler()->erase(&m_main->delay_partially_restarted()); } bool DownloadWrapper::is_stopped() const { return !m_main->tracker_controller().is_active() && !m_main->tracker_list()->has_active_not_dht(); } void DownloadWrapper::receive_initial_hash() { if (info()->is_active()) throw internal_error("DownloadWrapper::receive_initial_hash() but we're in a bad state."); if (!m_hash_checker->is_checking()) { receive_storage_error("Hash checker was unable to map chunk: " + std::string(std::strerror(m_hash_checker->error_number()))); } else { m_hash_checker->confirm_checked(); if (hash_queue()->has(data())) throw internal_error("DownloadWrapper::receive_initial_hash() found a chunk in the HashQueue."); // Initialize the ChunkSelector here so that no chunks will be // marked by HashTorrent that are not accounted for. m_main->chunk_selector()->initialize(m_main->chunk_statistics()); receive_update_priorities(); } if (data()->slot_initial_hash()) data()->slot_initial_hash()(); } void DownloadWrapper::receive_hash_done(ChunkHandle handle, const char* hash) { if (!handle.is_valid()) throw internal_error("DownloadWrapper::receive_hash_done(...) called on an invalid chunk."); if (!info()->is_open()) throw internal_error("DownloadWrapper::receive_hash_done(...) called but the download is not open."); if (m_hash_checker->is_checking()) { if (hash == NULL) { m_hash_checker->receive_chunk_cleared(handle.index()); } else { if (std::memcmp(hash, chunk_hash(handle.index()), 20) == 0) m_main->file_list()->mark_completed(handle.index()); m_hash_checker->receive_chunkdone(handle.index()); } m_main->chunk_list()->release(&handle, ChunkList::release_dont_log); return; } // If hash == NULL we're clearing the queue, so do nothing. if (hash != NULL) { if (!m_hash_checker->is_checked()) throw internal_error("DownloadWrapper::receive_hash_done(...) Was not expecting non-NULL hash."); // Receiving chunk hashes after stopping the torrent should be // safe. if (data()->untouched_bitfield()->get(handle.index())) throw internal_error("DownloadWrapper::receive_hash_done(...) received a chunk that isn't set in ChunkSelector."); if (std::memcmp(hash, chunk_hash(handle.index()), 20) == 0) { bool was_partial = data()->wanted_chunks() != 0; m_main->file_list()->mark_completed(handle.index()); m_main->delegator()->transfer_list()->hash_succeeded(handle.index(), handle.chunk()); m_main->update_endgame(); if (m_main->file_list()->is_done()) { finished_download(); } else if (was_partial && data()->wanted_chunks() == 0) { this_thread::scheduler()->erase(&m_main->delay_partially_restarted()); this_thread::scheduler()->update_wait_for(&m_main->delay_partially_done(), 0us); } if (!m_main->have_queue()->empty() && m_main->have_queue()->front().first >= this_thread::cached_time()) m_main->have_queue()->emplace_front(m_main->have_queue()->front().first + 1us, handle.index()); else m_main->have_queue()->emplace_front(this_thread::cached_time(), handle.index()); } else { // This needs to ensure the chunk is still valid. m_main->delegator()->transfer_list()->hash_failed(handle.index(), handle.chunk()); } } data()->call_chunk_done(handle.object()); m_main->chunk_list()->release(&handle, ChunkList::release_default); } void DownloadWrapper::check_chunk_hash(ChunkHandle handle, bool hashing) { // TODO: Hack... auto flags = ChunkList::get_blocking; if (hashing) flags = flags | ChunkList::get_hashing; else flags = flags | ChunkList::get_not_hashing; ChunkHandle new_handle = m_main->chunk_list()->get(handle.index(), flags); m_main->chunk_list()->release(&handle, ChunkList::release_default); hash_queue()->push_back(new_handle, data(), [this](auto c, auto h) { receive_hash_done(c, h); }); } void DownloadWrapper::receive_storage_error(const std::string& str) { m_main->stop(); close(); m_main->tracker_controller().disable(); m_main->tracker_controller().close(); LT_LOG_STORAGE_ERRORS("%s", str.c_str()); } uint32_t DownloadWrapper::receive_tracker_success(AddressList* l) { uint32_t inserted = m_main->peer_list()->insert_available(l); m_main->receive_connect_peers(); m_main->receive_tracker_success(); ::utils::slot_list_call(info()->signal_tracker_success()); return inserted; } void DownloadWrapper::receive_tracker_failed(const std::string& msg) { ::utils::slot_list_call(info()->signal_tracker_failed(), msg); } void DownloadWrapper::receive_tick(uint32_t ticks) { // Trigger culling of PeerInfo's every hour. This should be called // before the is_open check to ensure that stopped torrents reduce // their memory usage. if (ticks % 120 == 0) // if (ticks % 1 == 0) m_main->peer_list()->cull_peers(PeerList::cull_old | PeerList::cull_keep_interesting); if (!info()->is_open()) return; // Every 2 minutes. if (ticks % 4 == 0) { if (info()->is_active()) { if (info()->is_pex_enabled()) { m_main->do_peer_exchange(); // If PEX was disabled since the last peer exchange, deactivate it now. } else if (info()->is_pex_active()) { info()->unset_flags(DownloadInfo::flag_pex_active); for (auto& connection : *m_main->connection_list()) connection->m_ptr()->set_peer_exchange(false); } } for (auto itr = m_main->connection_list()->begin(); itr != m_main->connection_list()->end();) if (!(*itr)->m_ptr()->receive_keepalive()) itr = m_main->connection_list()->erase(itr, ConnectionList::disconnect_available); else itr++; } auto have_queue = m_main->have_queue(); have_queue->erase(std::find_if(have_queue->rbegin(), have_queue->rend(), [](auto& p) { return this_thread::cached_time() - 600s < p.first; }).base(), have_queue->end()); m_main->receive_connect_peers(); } void DownloadWrapper::receive_update_priorities() { LT_LOG_THIS("update priorities: chunks_selected:%" PRIu32 " wanted_chunks:%" PRIu32, m_main->chunk_selector()->size(), data()->wanted_chunks()); data()->mutable_high_priority()->clear(); data()->mutable_normal_priority()->clear(); for (auto& file : *m_main->file_list()) { switch (file->priority()) { case PRIORITY_NORMAL: { File::range_type range = file->range(); if (file->has_flags(File::flag_prioritize_first) && range.first != range.second) { data()->mutable_high_priority()->insert(range.first, range.first + 1); range.first++; } if (file->has_flags(File::flag_prioritize_last) && range.first != range.second) { data()->mutable_high_priority()->insert(range.second - 1, range.second); range.second--; } data()->mutable_normal_priority()->insert(range); break; } case PRIORITY_HIGH: data()->mutable_high_priority()->insert(file->range().first, file->range().second); break; default: break; } } bool was_partial = data()->wanted_chunks() != 0; data()->update_wanted_chunks(); m_main->chunk_selector()->update_priorities(); for (const auto& peer : *m_main->connection_list()) { peer->m_ptr()->update_interested(); } // The 'partially_done/restarted' signal only gets triggered when a // download is active and not completed. if (info()->is_active() && !file_list()->is_done() && was_partial != (data()->wanted_chunks() != 0)) { this_thread::scheduler()->erase(&m_main->delay_partially_done()); this_thread::scheduler()->erase(&m_main->delay_partially_restarted()); if (was_partial) this_thread::scheduler()->wait_for(&m_main->delay_partially_done(), 0us); else this_thread::scheduler()->wait_for(&m_main->delay_partially_restarted(), 0us); } } void DownloadWrapper::finished_download() { // We delay emitting the signal to allow the delegator to // clean up. If we do a straight call it would cause problems // for clients that wish to close and reopen the torrent, as // HashQueue, Delegator etc shouldn't be cleaned up at this // point. // // This needs to be seperated into a new function. this_thread::scheduler()->update_wait_for(&m_main->delay_download_done(), 0us); m_main->connection_list()->erase_seeders(); info()->mutable_down_rate()->reset_rate(); } } // namespace torrent libtorrent-0.16.11/src/download/delegator.h0000644000000000000000000000336315175073411014221 #ifndef LIBTORRENT_DELEGATOR_H #define LIBTORRENT_DELEGATOR_H #include #include #include #include "torrent/data/transfer_list.h" namespace torrent { class Block; class BlockList; class BlockTransfer; class Piece; class PeerChunks; class PeerInfo; class Delegator { public: using slot_peer_chunk = std::function; using slot_size = std::function; static constexpr unsigned int block_size = 1 << 14; TransferList* transfer_list() { return &m_transfers; } const TransferList* transfer_list() const { return &m_transfers; } std::vector delegate(PeerChunks* peerChunks, uint32_t affinity, uint32_t maxPieces); bool get_aggressive() const { return m_aggressive; } void set_aggressive(bool a) { m_aggressive = a; } slot_peer_chunk& slot_chunk_find() { return m_slot_chunk_find; } slot_size& slot_chunk_size() { return m_slot_chunk_size; } private: static void delegate_from_blocklist(std::vector &transfers, uint32_t maxPieces, BlockList* c, PeerInfo* peerInfo); void delegate_new_chunks(std::vector &transfers, uint32_t maxPieces, PeerChunks* pc, bool highPriority); Block* delegate_seeder(PeerChunks* peerChunks); TransferList m_transfers; bool m_aggressive{false}; // Propably should add a m_slotChunkStart thing, which will take // care of enabling etc, and will be possible to listen to. slot_peer_chunk m_slot_chunk_find; slot_size m_slot_chunk_size; }; } // namespace torrent #endif libtorrent-0.16.11/src/download/chunk_statistics.h0000644000000000000000000001027315175073411015633 // libTorrent - BitTorrent library // Copyright (C) 2005-2011, Jari Sundell // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // In addition, as a special exception, the copyright holders give // permission to link the code of portions of this program with the // OpenSSL library under certain conditions as described in each // individual source file, and distribute linked combinations // including the two. // // You must obey the GNU General Public License in all respects for // all of the code used other than OpenSSL. If you modify file(s) // with this exception, you may extend this exception to your version // of the file(s), but you are not obligated to do so. If you do not // wish to do so, delete this exception statement from your version. // If you delete this exception statement from all source files in the // program, then also delete it here. // // Contact: Jari Sundell // // Skomakerveien 33 // 3185 Skoppum, NORWAY #ifndef LIBTORRENT_DOWNLOAD_CHUNK_STATISTICS_H #define LIBTORRENT_DOWNLOAD_CHUNK_STATISTICS_H #include #include namespace torrent { class PeerChunks; class ChunkStatistics : public std::vector { public: using base_type = std::vector; using size_type = uint32_t; using value_type = base_type::value_type; using reference = base_type::reference; using const_reference = base_type::const_reference; using iterator = base_type::iterator; using const_iterator = base_type::const_iterator; using reverse_iterator = base_type::reverse_iterator; using base_type::empty; using base_type::size; static constexpr size_type max_accounted = 255; ChunkStatistics() = default; ~ChunkStatistics() = default; ChunkStatistics(const ChunkStatistics&) = delete; ChunkStatistics& operator=(const ChunkStatistics&) = delete; size_type complete() const { return m_complete; } //size_type incomplete() const; // Number of non-complete peers whom's bitfield is added to the // statistics. size_type accounted() const { return m_accounted; } void initialize(size_type s); void clear(); // When a peer connects and sends a non-empty bitfield and is not a // seeder, we can be fairly sure it won't just disconnect // immediately. Thus it should be resonable to possibly spend the // effort adding it to the statistics if nessesary. // Where do we decide on policy? On whetever we count the chunks, // the type of connection shouldn't matter? As f.ex PCSeed will only // make sense when seeding, it won't be counted. // Might want to prefer to add peers we are interested in, but which // arn't in us. void received_connect(PeerChunks* pc); void received_disconnect(PeerChunks* pc); // The caller must ensure that the chunk index is valid and has not // been set already. void received_have_chunk(PeerChunks* pc, uint32_t index, uint32_t length); const_iterator begin() const { return base_type::begin(); } const_iterator end() const { return base_type::end(); } const_reference rarity(size_type n) const { return base_type::operator[](n); } const_reference operator [] (size_type n) const { return base_type::operator[](n); } private: inline bool should_add(PeerChunks* pc) const; size_type m_complete{}; size_type m_accounted{}; }; } // namespace torrent #endif libtorrent-0.16.11/src/download/available_list.h0000644000000000000000000000247615175073411015232 #ifndef LIBTORRENT_DOWNLOAD_AVAILABLE_LIST_H #define LIBTORRENT_DOWNLOAD_AVAILABLE_LIST_H #include #include "net/address_list.h" #include "torrent/net/types.h" namespace torrent { // TODO: Always keep sorted? Also, do we use address list buffer? class AvailableList : private std::vector { public: using base_type = std::vector; using base_type::size; using base_type::capacity; using base_type::reserve; using base_type::empty; using base_type::begin; using base_type::end; value_type pop_random(); // Fuzzy size limit. size_type max_size() const { return m_maxSize; } void set_max_size(size_type s) { m_maxSize = s; } bool want_more() const { return size() <= m_maxSize; } void insert(AddressList* source_list); bool insert_unique(const sockaddr* sa); void erase(iterator itr) { *itr = std::move(back()); pop_back(); } // A place to temporarily put addresses before re-adding them to the // AvailableList. AddressList* buffer() { return &m_buffer; } private: size_type m_maxSize{1000}; AddressList m_buffer; }; } // namespace torrent #endif libtorrent-0.16.11/src/download/chunk_statistics.cc0000644000000000000000000001156715175073411016000 // libTorrent - BitTorrent library // Copyright (C) 2005-2011, Jari Sundell // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // In addition, as a special exception, the copyright holders give // permission to link the code of portions of this program with the // OpenSSL library under certain conditions as described in each // individual source file, and distribute linked combinations // including the two. // // You must obey the GNU General Public License in all respects for // all of the code used other than OpenSSL. If you modify file(s) // with this exception, you may extend this exception to your version // of the file(s), but you are not obligated to do so. If you do not // wish to do so, delete this exception statement from your version. // If you delete this exception statement from all source files in the // program, then also delete it here. // // Contact: Jari Sundell // // Skomakerveien 33 // 3185 Skoppum, NORWAY #include "config.h" #include "torrent/exceptions.h" #include "protocol/peer_chunks.h" #include "chunk_statistics.h" #include namespace torrent { inline bool ChunkStatistics::should_add(PeerChunks* pc) const { return m_accounted < max_accounted; } void ChunkStatistics::initialize(size_type s) { if (!empty()) throw internal_error("ChunkStatistics::initialize(...) called on an initialized object."); base_type::resize(s); } void ChunkStatistics::clear() { if (m_complete != 0) throw internal_error("ChunkStatistics::clear() m_complete != 0."); base_type::clear(); } void ChunkStatistics::received_connect(PeerChunks* pc) { if (pc->using_counter()) throw internal_error("ChunkStatistics::received_connect(...) pc->using_counter() == true."); if (pc->bitfield()->is_all_set()) { pc->set_using_counter(true); m_complete++; } else if (!pc->bitfield()->is_all_unset() && should_add(pc)) { // There should be additional checks, so that we don't do this // when there's no need. pc->set_using_counter(true); m_accounted++; auto itr = base_type::begin(); // Use a bitfield iterator instead. for (Bitfield::size_type index = 0; index < pc->bitfield()->size_bits(); ++index, ++itr) *itr += pc->bitfield()->get(index); } } void ChunkStatistics::received_disconnect(PeerChunks* pc) { // The 'using_counter' of complete peers is used, but not added to // 'm_accounted', so that we can safely disconnect peers right after // receiving the bitfield without calling 'received_connect'. if (!pc->using_counter()) return; pc->set_using_counter(false); if (pc->bitfield()->is_all_set()) { m_complete--; } else { if (m_accounted == 0) throw internal_error("ChunkStatistics::received_disconnect(...) m_accounted == 0."); m_accounted--; auto itr = base_type::begin(); // Use a bitfield iterator instead. for (Bitfield::size_type index = 0; index < pc->bitfield()->size_bits(); ++index, ++itr) *itr -= pc->bitfield()->get(index); } } void ChunkStatistics::received_have_chunk(PeerChunks* pc, uint32_t index, uint32_t length) { // When the bitfield is empty, it is very cheap to add the peer to // the statistics. It needs to be done here else we need to check if // a connection has sent any messages, else it might send a bitfield. if (pc->bitfield()->is_all_unset() && should_add(pc)) { if (pc->using_counter()) throw internal_error("ChunkStatistics::received_have_chunk(...) pc->using_counter() == true."); pc->set_using_counter(true); m_accounted++; } pc->bitfield()->set(index); pc->peer_rate()->insert(length); if (pc->using_counter()) { base_type::operator[](index)++; // The below code should not cause useless work to be done in case // of immediate disconnect. if (pc->bitfield()->is_all_set()) { if (m_accounted == 0) throw internal_error("ChunkStatistics::received_disconnect(...) m_accounted == 0."); m_complete++; m_accounted--; std::transform(base_type::begin(), base_type::end(), base_type::begin(), [] (auto c) { return c - 1; }); } } else { if (pc->bitfield()->is_all_set()) { pc->set_using_counter(true); m_complete++; } } } } // namespace torrent libtorrent-0.16.11/src/download/download_main.cc0000644000000000000000000004143715175073411015230 #include "config.h" #include "download/download_main.h" #include #include #include "data/chunk_list.h" #include "download/available_list.h" #include "download/chunk_selector.h" #include "download/chunk_statistics.h" #include "download/download_wrapper.h" #include "manager.h" #include "protocol/extensions.h" #include "protocol/handshake_manager.h" #include "protocol/initial_seed.h" #include "protocol/peer_connection_base.h" #include "protocol/peer_factory.h" #include "torrent/data/file_list.h" #include "torrent/download.h" #include "torrent/download/choke_queue.h" #include "torrent/download/download_manager.h" #include "torrent/download_info.h" #include "torrent/exceptions.h" #include "torrent/net/network_config.h" #include "torrent/peer/connection_list.h" #include "torrent/peer/peer.h" #include "torrent/peer/peer_info.h" #include "torrent/throttle.h" #include "torrent/tracker/manager.h" #include "torrent/utils/log.h" #include "tracker/thread_tracker.h" #include "tracker/tracker_controller.h" #include "tracker/tracker_list.h" #define LT_LOG_THIS(log_level, log_fmt, ...) \ lt_log_print_info(LOG_TORRENT_##log_level, m_ptr->info(), "download", log_fmt, __VA_ARGS__); namespace torrent { DownloadMain::DownloadMain() : m_info(new DownloadInfo), m_tracker_list(new TrackerList), m_chunkList(new ChunkList), m_chunkSelector(new ChunkSelector(file_list()->mutable_data())), m_chunkStatistics(new ChunkStatistics), m_connectionList(new ConnectionList(this)) { m_info->set_load_date(utils::cast_seconds(utils::time_since_epoch()).count()); // Only set trivial values here, the rest is done in DownloadWrapper. m_delegator.slot_chunk_find() = [this](auto pc, auto prio) { return m_chunkSelector->find(pc, prio); }; m_delegator.slot_chunk_size() = [this](auto i) { return file_list()->chunk_index_size(i); }; m_delegator.transfer_list()->slot_canceled() = [this](auto i) { m_chunkSelector->not_using_index(i); }; m_delegator.transfer_list()->slot_queued() = [this](auto i) { m_chunkSelector->using_index(i); }; m_delegator.transfer_list()->slot_completed() = [this](auto i) { receive_chunk_done(i); }; m_delegator.transfer_list()->slot_corrupt() = [this](auto i) { receive_corrupt_chunk(i); }; m_delay_disconnect_peers.slot() = [this] { m_connectionList->disconnect_queued(); }; m_task_tracker_request.slot() = [this] { receive_tracker_request(); }; m_chunkList->set_data(file_list()->mutable_data()); m_chunkList->slot_create_chunk() = [this](uint32_t index, int prot) { return file_list()->create_chunk_index(index, prot); }; m_chunkList->slot_create_hashing_chunk() = [this](uint32_t index, int prot) { return file_list()->create_hashing_chunk_index(index, prot); }; m_chunkList->slot_free_diskspace() = [this]() { return file_list()->free_diskspace(); }; } DownloadMain::~DownloadMain() { assert(!m_task_tracker_request.is_scheduled() && "DownloadMain::~DownloadMain(): m_task_tracker_request is scheduled."); assert(m_info->size_pex() == 0 && "DownloadMain::~DownloadMain(): m_info->size_pex() != 0."); delete m_tracker_list; delete m_connectionList; delete m_chunkStatistics; delete m_chunkList; delete m_chunkSelector; delete m_info; m_ut_pex_delta.clear(); m_ut_pex_initial.clear(); } void DownloadMain::post_initialize() { auto tc = std::make_shared(m_tracker_list); m_tracker_list->slot_success() = [tc](const auto& t, auto al) { return tc->receive_success(t, al); }; m_tracker_list->slot_failure() = [tc](const auto& t, const auto& str) { tc->receive_failure(t, str); }; m_tracker_list->slot_scrape_success() = [tc](const auto& t) { tc->receive_scrape(t); }; m_tracker_list->slot_new_peers() = [tc](auto al) { return tc->receive_new_peers(al); }; m_tracker_list->slot_tracker_enabled() = [tc](const auto& t) { tc->receive_tracker_enabled(t); }; m_tracker_list->slot_tracker_disabled() = [tc](const auto& t) { tc->receive_tracker_disabled(t); }; m_tracker_controller = thread_tracker()->tracker_manager()->add_controller(info(), std::move(tc)); } std::pair DownloadMain::throttles(const sockaddr* sa) { ThrottlePair pair = ThrottlePair(NULL, NULL); if (manager->connection_manager()->address_throttle()) pair = manager->connection_manager()->address_throttle()(sa); return std::make_pair(pair.first == NULL ? upload_throttle() : pair.first->throttle_list(), pair.second == NULL ? download_throttle() : pair.second->throttle_list()); } void DownloadMain::open(int flags) { if (info()->is_open()) throw internal_error("Tried to open a download that is already open"); // TODO: Move file_list open calls to DownloadMain. file_list()->open(true, (flags & FileList::open_no_create)); m_chunkList->resize(file_list()->size_chunks()); m_chunkStatistics->initialize(file_list()->size_chunks()); info()->set_flags(DownloadInfo::flag_open); } void DownloadMain::close() { if (info()->is_active()) throw internal_error("Tried to close an active download"); if (!info()->is_open()) return; info()->unset_flags(DownloadInfo::flag_open); // Don't close the tracker manager here else it will cause STOPPED // requests to be lost. TODO: Check that this is valid. // m_trackerManager->close(); m_delegator.transfer_list()->clear(); file_list()->close(); // Clear the chunklist last as it requires all referenced chunks to // be released. m_chunkStatistics->clear(); m_chunkList->clear(); m_chunkSelector->cleanup(); } void DownloadMain::start(int flags) { if (!info()->is_open()) throw internal_error("Tried to start a closed download"); if (info()->is_active()) throw internal_error("Tried to start an active download"); // Close and clear open files to ensure hashing file/mmap advise is cleared. // // We should not need to clear chunks after hash checking the whole torrent as those chunk handle // references go to zero. file_list()->close_all_files(); // If the FileList::open_no_create flag was not set, our new // behavior is to create all zero-length files with // flag_queued_create set. file_list()->open(false, (flags & ~FileList::open_no_create)); info()->set_flags(DownloadInfo::flag_active); chunk_list()->set_flags(ChunkList::flag_active); m_delegator.set_aggressive(false); update_endgame(); receive_connect_peers(); } void DownloadMain::stop() { if (!info()->is_active()) return; // Set this early so functions like receive_connect_peers() knows // not to eat available peers. info()->unset_flags(DownloadInfo::flag_active); chunk_list()->unset_flags(ChunkList::flag_active); m_slot_stop_handshakes(this); connection_list()->erase_remaining(connection_list()->begin(), ConnectionList::disconnect_available); m_initial_seeding.reset(); this_thread::scheduler()->erase(&m_delay_disconnect_peers); this_thread::scheduler()->erase(&m_task_tracker_request); if (info()->upload_unchoked() != 0 || info()->download_unchoked() != 0) throw internal_error("DownloadMain::stop(): info()->upload_unchoked() != 0 || info()->download_unchoked() != 0."); } bool DownloadMain::start_initial_seeding() { if (!file_list()->is_done()) return false; m_initial_seeding = std::make_unique(this); return true; } void DownloadMain::initial_seeding_done(PeerConnectionBase* pcb) { if (m_initial_seeding == nullptr) throw internal_error("DownloadMain::initial_seeding_done called when not initial seeding."); // Close all connections but the currently active one (pcb), that // one will be closed by throw close_connection() later. // // When calling initial_seed()->new_peer(...) the 'pcb' won't be in // the connection list, so don't treat it as an error. Make sure to // catch close_connection() at the caller of new_peer(...) and just // close the filedesc before proceeding as normal. auto pcb_itr = std::find(m_connectionList->begin(), m_connectionList->end(), pcb); if (pcb_itr != m_connectionList->end()) { std::iter_swap(m_connectionList->begin(), pcb_itr); m_connectionList->erase_remaining(m_connectionList->begin() + 1, ConnectionList::disconnect_available); } else { m_connectionList->erase_remaining(m_connectionList->begin(), ConnectionList::disconnect_available); } // Switch to normal seeding. auto itr = manager->download_manager()->find(m_info); (*itr)->set_connection_type(Download::CONNECTION_SEED); m_connectionList->slot_new_connection(&createPeerConnectionSeed); m_initial_seeding.reset(); // And close the current connection. throw close_connection(); } bool DownloadMain::want_pex_msg() { return m_info->is_pex_active() && m_peerList.available_list()->want_more(); } void DownloadMain::update_endgame() { if (!m_delegator.get_aggressive() && file_list()->completed_chunks() + m_delegator.transfer_list()->size() + 5 >= file_list()->size_chunks()) m_delegator.set_aggressive(true); } void DownloadMain::receive_chunk_done(unsigned int index) { // TODO: Should we unmap the chunk here if we want sequential access? ChunkHandle handle = m_chunkList->get(index, ChunkList::get_hashing); if (!handle.is_valid()) throw storage_error("DownloadState::chunk_done(...) called with an index we couldn't retrieve from storage"); m_slot_hash_check_add(handle); } void DownloadMain::receive_corrupt_chunk(PeerInfo* peerInfo) { peerInfo->set_failed_counter(peerInfo->failed_counter() + 1); // Just use some very primitive heuristics here to decide if we're // going to disconnect the peer. Also, consider adding a flag so we // don't recalculate these things whenever the peer reconnects. // That is... non at all ;) if (peerInfo->failed_counter() > HandshakeManager::max_failed) connection_list()->erase(peerInfo, ConnectionList::disconnect_unwanted); } void DownloadMain::add_peer(const sockaddr* sa) { if (config::network_config()->is_block_outgoing()) return; m_slot_start_handshake(sa, this); } void DownloadMain::receive_connect_peers() { if (!info()->is_active()) return; // TODO: Is this actually going to be used? AddressList* alist = peer_list()->available_list()->buffer(); if (!alist->empty()) { alist->sort(); peer_list()->insert_available(alist); alist->clear(); } if (config::network_config()->is_block_outgoing()) return; while (!peer_list()->available_list()->empty() && manager->connection_manager()->can_connect() && connection_list()->size() < connection_list()->min_size() && connection_list()->size() + m_slot_count_handshakes(this) < connection_list()->max_size()) { auto sa = peer_list()->available_list()->pop_random(); if (connection_list()->find(&sa.sa) == connection_list()->end()) m_slot_start_handshake(&sa.sa, this); } } void DownloadMain::receive_tracker_success() { if (!info()->is_active()) return; this_thread::scheduler()->update_wait_for_ceil_seconds(&m_task_tracker_request, 10s); } void DownloadMain::receive_tracker_request() { if ((info()->is_pex_enabled() && info()->size_pex()) > 0 || connection_list()->size() + peer_list()->available_list()->size() / 2 >= connection_list()->min_size()) { m_tracker_controller.stop_requesting(); return; } m_tracker_controller.start_requesting(); } static bool SocketAddressCompact_less(const SocketAddressCompact& a, const SocketAddressCompact& b) { return (a.addr < b.addr) || ((a.addr == b.addr) && (a.port < b.port)); } void DownloadMain::do_peer_exchange() { if (!info()->is_active()) throw internal_error("DownloadMain::do_peer_exchange called on inactive download."); // Check whether we should tell the peers to stop/start sending PEX // messages. int togglePex = 0; if (!m_info->is_pex_active() && m_connectionList->size() < m_connectionList->min_size() / 2 && m_peerList.available_list()->size() < m_peerList.available_list()->max_size() / 4) { m_info->set_flags(DownloadInfo::flag_pex_active); // Only set PEX_ENABLE if we don't have max_size_pex set to zero. if (m_info->size_pex() < m_info->max_size_pex()) togglePex = PeerConnectionBase::PEX_ENABLE; } else if (m_info->is_pex_active() && m_connectionList->size() >= m_connectionList->min_size()) { // m_peerList.available_list()->size() >= m_peerList.available_list()->max_size() / 2) { togglePex = PeerConnectionBase::PEX_DISABLE; m_info->unset_flags(DownloadInfo::flag_pex_active); } // Return if we don't really want to do anything? ProtocolExtension::PEXList current; for (auto& connection : *m_connectionList) { auto pcb = connection->m_ptr(); auto sa = pcb->peer_info()->socket_address(); if (pcb->peer_info()->listen_port() != 0 && sa->sa_family == AF_INET) { // The reinterpret_cast requires const in push_back, while not in emplace_back. // // Might be the cause of corrupt address values in rtorrent-docker tests. // current.emplace_back(reinterpret_cast(&sa)->sin_addr.s_addr, htons(pcb->peer_info()->listen_port())); current.push_back(SocketAddressCompact(reinterpret_cast(sa)->sin_addr.s_addr, htons(pcb->peer_info()->listen_port()))); } if (!pcb->extensions()->is_remote_supported(ProtocolExtension::UT_PEX)) continue; if (togglePex == PeerConnectionBase::PEX_ENABLE) { pcb->set_peer_exchange(true); if (m_info->size_pex() >= m_info->max_size_pex()) togglePex = 0; } else if (!pcb->extensions()->is_local_enabled(ProtocolExtension::UT_PEX)) { continue; } else if (togglePex == PeerConnectionBase::PEX_DISABLE) { pcb->set_peer_exchange(false); continue; } // Still using the old buffer? Make a copy in this rare case. DataBuffer* message = pcb->extension_message(); if (!message->empty() && (message->data() == m_ut_pex_initial.data() || message->data() == m_ut_pex_delta.data())) { auto buffer = new char[message->length()]; memcpy(buffer, message->data(), message->length()); message->set(buffer, buffer + message->length(), true); } pcb->do_peer_exchange(); } std::sort(current.begin(), current.end(), SocketAddressCompact_less); ProtocolExtension::PEXList added; added.reserve(current.size()); std::set_difference(current.begin(), current.end(), m_ut_pex_list.begin(), m_ut_pex_list.end(), std::back_inserter(added), SocketAddressCompact_less); ProtocolExtension::PEXList removed; removed.reserve(m_ut_pex_list.size()); std::set_difference(m_ut_pex_list.begin(), m_ut_pex_list.end(), current.begin(), current.end(), std::back_inserter(removed), SocketAddressCompact_less); if (current.size() > torrent::DownloadInfo::max_size_pex_list()) { // This test is only correct as long as we have a constant max // size. if (added.size() < current.size() - torrent::DownloadInfo::max_size_pex_list()) throw internal_error("DownloadMain::do_peer_exchange() added.size() < current.size() - m_info->max_size_pex_list()."); // Randomize this: added.erase(added.end() - (current.size() - torrent::DownloadInfo::max_size_pex_list()), added.end()); // Create the new m_ut_pex_list by removing any 'removed' // addresses from the original list and then adding the new // addresses. m_ut_pex_list.erase( std::set_difference( m_ut_pex_list.begin(), m_ut_pex_list.end(), removed.begin(), removed.end(), m_ut_pex_list.begin(), SocketAddressCompact_less), m_ut_pex_list.end()); m_ut_pex_list.insert(m_ut_pex_list.end(), added.begin(), added.end()); std::sort(m_ut_pex_list.begin(), m_ut_pex_list.end(), SocketAddressCompact_less); } else { m_ut_pex_list.swap(current); } current.clear(); m_ut_pex_delta.clear(); // If no peers were added or removed, the initial message is still correct and // the delta message stays emptied. Otherwise generate the appropriate messages. if (!added.empty() || !m_ut_pex_list.empty()) { m_ut_pex_delta = ProtocolExtension::generate_ut_pex_message(added, removed); m_ut_pex_initial.clear(); m_ut_pex_initial = ProtocolExtension::generate_ut_pex_message(m_ut_pex_list, current); } } void DownloadMain::set_metadata_size(size_t size) { if (m_info->is_meta_download()) { if(size == 0 || size > (1 << 26)) throw communication_error("Peer-supplied invalid metadata size."); if (m_fileList.size_bytes() < 2) file_list()->reset_filesize(size); else if (size != m_fileList.size_bytes()) throw communication_error("Peer-supplied metadata size mismatch."); } else if (m_info->metadata_size() && m_info->metadata_size() != size) { throw communication_error("Peer-supplied metadata size mismatch."); } m_info->set_metadata_size(size); } } // namespace torrent libtorrent-0.16.11/src/download/download_constructor.cc0000644000000000000000000003151415175073411016664 #include "config.h" #include "download/download_constructor.h" #include #include #include #include "manager.h" #include "download/download_wrapper.h" #include "torrent/download_info.h" #include "torrent/exceptions.h" #include "torrent/data/file.h" #include "torrent/data/file_list.h" #include "torrent/utils/string_manip.h" #include "tracker/tracker_list.h" namespace torrent { static bool download_constructor_is_single_path(Object::map_type::const_reference v) { return v.first.rfind("name.", 0) == 0 && v.second.is_string(); } static bool download_constructor_is_multi_path(Object::map_type::const_reference v) { return v.first.rfind("path.", 0) == 0 && v.second.is_list(); } void DownloadConstructor::initialize(Object& b) { if (!b.has_key_map("info") && b.has_key_string("magnet-uri")) parse_magnet_uri(b, b.get_key_string("magnet-uri")); if (b.has_key_string("encoding")) m_defaultEncoding = b.get_key_string("encoding"); if (b.has_key_value("creation date")) m_download->info()->set_creation_date(b.get_key_value("creation date")); if (b.get_key("info").has_key_value("private") && b.get_key("info").get_key_value("private") == 1) m_download->info()->set_private(); parse_name(b.get_key("info")); parse_info(b.get_key("info")); } // Currently using a hack of the path thingie to extract the correct // torrent name. void DownloadConstructor::parse_name(const Object& b) { if (is_invalid_path_element(b.get_key("name"))) throw input_error("Bad torrent file, \"name\" is an invalid path name."); std::list pathList; pathList.emplace_back(); pathList.back().set_encoding(m_defaultEncoding); pathList.back().push_back(b.get_key_string("name")); for (const auto& map : b.as_map()) { if (download_constructor_is_single_path(map)) { pathList.emplace_back(); pathList.back().set_encoding(map.first.substr(sizeof("name.") - 1)); pathList.back().push_back(map.second.as_string()); } } if (pathList.empty()) throw input_error("Bad torrent file, an entry has no valid name."); Path name = choose_path(&pathList); if (name.empty()) throw internal_error("DownloadConstructor::parse_name(...) Ended up with an empty Path."); m_download->info()->set_name(name.front()); } void DownloadConstructor::parse_info(const Object& b) { FileList* fileList = m_download->main()->file_list(); if (!fileList->empty()) throw internal_error("parse_info received an already initialized Content object."); if (b.flags() & Object::flag_unordered) throw input_error("Download has unordered info dictionary."); uint32_t chunkSize; if (b.has_key_value("meta_download") && b.get_key_value("meta_download")) m_download->info()->set_flags(DownloadInfo::flag_meta_download); if (m_download->info()->is_meta_download()) { if (b.get_key_string("pieces").length() != HashString::size_data) throw input_error("Meta-download has invalid piece data."); chunkSize = 1; parse_single_file(b, chunkSize); } else { chunkSize = b.get_key_value("piece length"); if (chunkSize <= (1 << 10) || chunkSize > (512 << 20)) throw input_error("Torrent has an invalid \"piece length\"."); } if (b.has_key("length")) { parse_single_file(b, chunkSize); } else if (b.has_key("files")) { parse_multi_files(b.get_key("files"), chunkSize); fileList->set_root_dir("./" + m_download->info()->name()); } else if (!m_download->info()->is_meta_download()) { throw input_error("Torrent must have either length or files entry."); } if (fileList->size_bytes() == 0 && !m_download->info()->is_meta_download()) throw input_error("Torrent has zero length."); // Set chunksize before adding files to make sure the index range is // correct. m_download->set_complete_hash(b.get_key_string("pieces")); if (m_download->complete_hash().size() / 20 < fileList->size_chunks()) throw bencode_error("Torrent size and 'info:pieces' length does not match."); } void DownloadConstructor::parse_tracker(const Object& b) { const Object::list_type* announce_list = NULL; if (b.has_key_list("announce-list") && // Some torrent makers create empty/invalid 'announce-list' // entries while still having valid 'announce'. !(announce_list = &b.get_key_list("announce-list"))->empty() && std::any_of(announce_list->begin(), announce_list->end(), std::mem_fn(&Object::is_list))) { for (const auto& group : *announce_list) { add_tracker_group(group); } } else if (b.has_key("announce")) { add_tracker_single(b.get_key("announce"), 0); } if (!m_download->info()->is_private()) m_download->main()->tracker_list()->insert_url(m_download->main()->tracker_list()->size_group(), "dht://"); // Deprecating DHT nodes key in torrent files as this is no longer needed. // if (b.has_key_list("nodes")) { // for (const auto& node : b.get_key_list("nodes")) // add_dht_node(node); // } m_download->main()->tracker_list()->randomize_group_entries(); } void DownloadConstructor::add_tracker_group(const Object& b) { if (!b.is_list()) throw bencode_error("Tracker group list not a list"); auto group = m_download->main()->tracker_list()->size_group(); for (const auto& tracker : b.as_list()) { add_tracker_single(tracker, group); } } void DownloadConstructor::add_tracker_single(const Object& b, int group) { if (!b.is_string()) throw bencode_error("Tracker entry not a string"); m_download->main()->tracker_list()->insert_url(group, utils::trim_spaces_str(b.as_string())); } bool DownloadConstructor::is_valid_path_element(const Object& b) { return b.is_string() && b.as_string() != "." && b.as_string() != ".." && std::find(b.as_string().begin(), b.as_string().end(), '/') == b.as_string().end() && std::find(b.as_string().begin(), b.as_string().end(), '\0') == b.as_string().end(); } void DownloadConstructor::parse_single_file(const Object& b, uint32_t chunkSize) { if (is_invalid_path_element(b.get_key("name"))) throw input_error("Bad torrent file, \"name\" is an invalid path name."); FileList* fileList = m_download->main()->file_list(); fileList->initialize(chunkSize == 1 ? 1 : b.get_key_value("length"), chunkSize); fileList->set_multi_file(false); std::list pathList; pathList.emplace_back(); pathList.back().set_encoding(m_defaultEncoding); pathList.back().push_back(b.get_key_string("name")); for (const auto& map : b.as_map()) { if (!download_constructor_is_single_path(map)) continue; pathList.emplace_back(); pathList.back().set_encoding(map.first.substr(sizeof("name.") - 1)); pathList.back().push_back(map.second.as_string()); } if (pathList.empty()) throw input_error("Bad torrent file, an entry has no valid filename."); *fileList->front()->mutable_path() = choose_path(&pathList); fileList->update_paths(fileList->begin(), fileList->end()); } void DownloadConstructor::parse_multi_files(const Object& b, uint32_t chunk_size) { const Object::list_type& object_list = b.as_list(); // Multi file torrent if (object_list.empty()) throw input_error("Bad torrent file, entry has no files."); int64_t torrent_size = 0; std::vector split_list; split_list.reserve(object_list.size()); for (const auto& object : object_list) { std::list path_list; if (object.has_key_list("path")) path_list.push_back(create_path(object.get_key_list("path"), m_defaultEncoding)); for (const auto& path : object.as_map()) if (download_constructor_is_multi_path(path)) path_list.push_back(create_path(path.second.as_list(), path.first.substr(sizeof("path.") - 1))); if (path_list.empty()) throw input_error("Bad torrent file, an entry has no valid filename."); int64_t length = object.get_key_value("length"); if (length < 0 || torrent_size + length < 0) throw input_error("Bad torrent file, invalid length for file."); torrent_size += length; int attr_flags = 0; if (object.has_key_string("attr")) { if (object.get_key_string("attr").find('p') != std::string::npos) attr_flags |= File::flag_attr_padding; } split_list.emplace_back(length, choose_path(&path_list), attr_flags); } FileList* file_list = m_download->main()->file_list(); file_list->set_multi_file(true); file_list->initialize(torrent_size, chunk_size); file_list->split(file_list->begin(), &*split_list.begin(), &*split_list.end()); file_list->update_paths(file_list->begin(), file_list->end()); } inline Path DownloadConstructor::create_path(const Object::list_type& plist, const std::string& enc) { // Make sure we are given a proper file path. if (plist.empty()) throw input_error("Bad torrent file, \"path\" has zero entries."); if (std::any_of(plist.begin(), plist.end(), &DownloadConstructor::is_invalid_path_element)) throw input_error("Bad torrent file, \"path\" has zero entries or a zero length entry."); Path p; p.set_encoding(enc); std::transform(plist.begin(), plist.end(), std::back_inserter(p), std::mem_fn(&Object::as_string_c)); return p; } inline Path DownloadConstructor::choose_path(std::list* pathList) { for (const auto& encoding : *m_encodingList) { auto itr = std::find_if(pathList->begin(), pathList->end(), [&encoding](const Path& p) { return strcasecmp(p.encoding().c_str(), encoding.c_str()) == 0; }); if (itr != pathList->end()) pathList->splice(pathList->begin(), *pathList, itr); } return pathList->front(); } static const char* parse_base32_sha1(const char* pos, HashString& hash) { HashString::iterator hashItr = hash.begin(); static constexpr int base_shift = 8+8-5; int shift = base_shift; uint16_t decoded = 0; while (*pos) { char c = *pos++; uint16_t value; if (c >= 'A' && c <= 'Z') value = c - 'A'; else if (c >= 'a' && c <= 'z') value = c - 'a'; else if (c >= '2' && c <= '7') value = 26 + c - '2'; else if (c == '&') break; else return NULL; decoded |= (value << shift); if (shift <= 8) { // Too many characters for a base32 SHA1. if (hashItr == hash.end()) return NULL; *hashItr++ = (decoded >> 8); decoded <<= 8; shift += 3; } else { shift -= 5; } } return hashItr != hash.end() || shift != base_shift ? NULL : pos; } void DownloadConstructor::parse_magnet_uri(Object& b, const std::string& uri) { if (std::strncmp(uri.c_str(), "magnet:?", 8)) throw input_error("Invalid magnet URI."); const char* pos = uri.c_str() + 8; Object trackers(Object::create_list()); HashString hash; bool hashValid = false; while (*pos) { const char* tagStart = pos; while (*pos != '=') { if (!*pos++) break; } raw_string tag(tagStart, pos - tagStart); pos++; // hash may be base32 encoded (optional in BEP 0009 and common practice) if (raw_bencode_equal_c_str(tag, "xt")) { if (strncmp(pos, "urn:btih:", 9)) throw input_error("Invalid magnet URI."); pos += 9; const char* nextPos = parse_base32_sha1(pos, hash); if (nextPos != NULL) { pos = nextPos; hashValid = true; continue; } } // everything else, including sometimes the hash, is url encoded. std::string decoded; while (*pos) { char c = *pos++; if (c == '%') { if (sscanf(pos, "%02hhx", &c) != 1) throw input_error("Invalid magnet URI."); pos += 2; } else if (c == '&') { break; } decoded.push_back(c); } if (raw_bencode_equal_c_str(tag, "xt")) { if (decoded.length() == torrent::HashString::size_data) { // url-encoded hash as per magnet URN specs hash = *HashString::cast_from(decoded); hashValid = true; } else if (decoded.length() == torrent::HashString::size_data * 2) { // hex-encoded hash as per BEP 0009 if (utils::transform_from_hex(decoded, hash) != hash.end()) throw input_error("Invalid magnet URI."); hashValid = true; } else { throw input_error("Invalid magnet URI."); } } else if (raw_bencode_equal_c_str(tag, "tr")) { trackers.insert_back(Object::create_list()).insert_back(decoded); } // could also handle "dn" = display name (torrent name), but we can't really use that } if (!hashValid) throw input_error("Invalid magnet URI."); Object& info = b.insert_key("info", Object::create_map()); info.insert_key("pieces", hash.str()); info.insert_key("name", utils::transform_to_hex_str(hash) + ".meta"); info.insert_key("meta_download", static_cast(1)); if (!trackers.as_list().empty()) { b.insert_preserve_copy("announce", trackers.as_list().begin()->as_list().begin()->as_string()); b.insert_preserve_type("announce-list", trackers); } } } // namespace torrent libtorrent-0.16.11/src/download/download_constructor.h0000644000000000000000000000302415175073411016521 #ifndef LIBTORRENT_PARSE_DOWNLOAD_CONSTRUCTOR_H #define LIBTORRENT_PARSE_DOWNLOAD_CONSTRUCTOR_H #include #include "torrent/object.h" namespace torrent { class Content; class DownloadWrapper; class Path; using EncodingList = std::list; class DownloadConstructor { public: void initialize(Object& b); void parse_tracker(const Object& b); void set_download(DownloadWrapper* d) { m_download = d; } void set_encoding_list(const EncodingList* e) { m_encodingList = e; } private: void parse_name(const Object& b); void parse_info(const Object& b); static void parse_magnet_uri(Object& b, const std::string& uri); void add_tracker_group(const Object& b); void add_tracker_single(const Object& b, int group); static bool is_valid_path_element(const Object& b); static bool is_invalid_path_element(const Object& b) { return !is_valid_path_element(b); } void parse_single_file(const Object& b, uint32_t chunkSize); void parse_multi_files(const Object& b, uint32_t chunkSize); static Path create_path(const Object::list_type& plist, const std::string& enc); inline Path choose_path(std::list* pathList); DownloadWrapper* m_download{}; const EncodingList* m_encodingList{}; std::string m_defaultEncoding; }; } // namespace torrent #endif // LIBTORRENT_PARSE_DOWNLOAD_CONSTRUCTOR_H libtorrent-0.16.11/missing0000755000000000000000000001706015175073426011110 #! /bin/sh # Common wrapper for a few potentially missing GNU and other programs. scriptversion=2024-06-07.14; # UTC # shellcheck disable=SC2006,SC2268 # we must support pre-POSIX shells # Copyright (C) 1996-2024 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try '$0 --help' for more information" exit 1 fi case $1 in --is-lightweight) # Used by our autoconf macros to check whether the available missing # script is modern enough. exit 0 ;; --run) # Back-compat with the calling convention used by older automake. shift ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due to PROGRAM being missing or too old. Options: -h, --help display this help and exit -v, --version output version information and exit Supported PROGRAM values: aclocal autoconf autogen autoheader autom4te automake autoreconf bison flex help2man lex makeinfo perl yacc Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and 'g' are ignored when checking the name. Report bugs to . GNU Automake home page: . General help using GNU software: ." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing (GNU Automake) $scriptversion" exit $? ;; -*) echo 1>&2 "$0: unknown '$1' option" echo 1>&2 "Try '$0 --help' for more information" exit 1 ;; esac # Run the given program, remember its exit status. "$@"; st=$? # If it succeeded, we are done. test $st -eq 0 && exit 0 # Also exit now if we it failed (or wasn't found), and '--version' was # passed; such an option is passed most likely to detect whether the # program is present and works. case $2 in --version|--help) exit $st;; esac # Exit code 63 means version mismatch. This often happens when the user # tries to use an ancient version of a tool on a file that requires a # minimum version. if test $st -eq 63; then msg="probably too old" elif test $st -eq 127; then # Program was missing. msg="missing on your system" else # Program was found and executed, but failed. Give up. exit $st fi perl_URL=https://www.perl.org/ flex_URL=https://github.com/westes/flex gnu_software_URL=https://www.gnu.org/software program_details () { case $1 in aclocal|automake|autoreconf) echo "The '$1' program is part of the GNU Automake package:" echo "<$gnu_software_URL/automake>" echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/autoconf>" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; autoconf|autom4te|autoheader) echo "The '$1' program is part of the GNU Autoconf package:" echo "<$gnu_software_URL/autoconf/>" echo "It also requires GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; *) : ;; esac } give_advice () { # Normalize program name to check for. normalized_program=`echo "$1" | sed ' s/^gnu-//; t s/^gnu//; t s/^g//; t'` printf '%s\n' "'$1' is $msg." configure_deps="'configure.ac' or m4 files included by 'configure.ac'" autoheader_deps="'acconfig.h'" automake_deps="'Makefile.am'" aclocal_deps="'acinclude.m4'" case $normalized_program in aclocal*) echo "You should only need it if you modified $aclocal_deps or" echo "$configure_deps." ;; autoconf*) echo "You should only need it if you modified $configure_deps." ;; autogen*) echo "You should only need it if you modified a '.def' or '.tpl' file." echo "You may want to install the GNU AutoGen package:" echo "<$gnu_software_URL/autogen/>" ;; autoheader*) echo "You should only need it if you modified $autoheader_deps or" echo "$configure_deps." ;; automake*) echo "You should only need it if you modified $automake_deps or" echo "$configure_deps." ;; autom4te*) echo "You might have modified some maintainer files that require" echo "the 'autom4te' program to be rebuilt." ;; autoreconf*) echo "You should only need it if you modified $aclocal_deps or" echo "$automake_deps or $autoheader_deps or $automake_deps or" echo "$configure_deps." ;; bison*|yacc*) echo "You should only need it if you modified a '.y' file." echo "You may want to install the GNU Bison package:" echo "<$gnu_software_URL/bison/>" ;; help2man*) echo "You should only need it if you modified a dependency" \ "of a man page." echo "You may want to install the GNU Help2man package:" echo "<$gnu_software_URL/help2man/>" ;; lex*|flex*) echo "You should only need it if you modified a '.l' file." echo "You may want to install the Fast Lexical Analyzer package:" echo "<$flex_URL>" ;; makeinfo*) echo "You should only need it if you modified a '.texi' file, or" echo "any other file indirectly affecting the aspect of the manual." echo "You might want to install the Texinfo package:" echo "<$gnu_software_URL/texinfo/>" echo "The spurious makeinfo call might also be the consequence of" echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" echo "want to install GNU make:" echo "<$gnu_software_URL/make/>" ;; perl*) echo "You should only need it to run GNU Autoconf, GNU Automake, " echo " assorted other tools, or if you modified a Perl source file." echo "You may want to install the Perl 5 language interpreter:" echo "<$perl_URL>" ;; *) echo "You might have modified some files without having the proper" echo "tools for further handling them. Check the 'README' file, it" echo "often tells you about the needed prerequisites for installing" echo "this package. You may also peek at any GNU archive site, in" echo "case some other package contains this missing '$1' program." ;; esac program_details "$normalized_program" } give_advice "$1" | sed -e '1s/^/WARNING: /' \ -e '2,$s/^/ /' >&2 # Propagate the correct exit status (expected to be 127 for a program # not found, 63 for a program that failed due to version mismatch). exit $st # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: libtorrent-0.16.11/INSTALL0000644000000000000000000003661415175073410010541 Installation Instructions ************************* Copyright (C) 1994-1996, 1999-2002, 2004-2016 Free Software Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without warranty of any kind. Basic Installation ================== Briefly, the shell command './configure && make && make install' should configure, build, and install this package. The following more-detailed instructions are generic; see the 'README' file for instructions specific to this package. Some packages provide this 'INSTALL' file but do not implement all of the features documented below. The lack of an optional feature in a given package is not necessarily a bug. More recommendations for GNU packages can be found in *note Makefile Conventions: (standards)Makefile Conventions. The 'configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a 'Makefile' in each directory of the package. It may also create one or more '.h' files containing system-dependent definitions. Finally, it creates a shell script 'config.status' that you can run in the future to recreate the current configuration, and a file 'config.log' containing compiler output (useful mainly for debugging 'configure'). It can also use an optional file (typically called 'config.cache' and enabled with '--cache-file=config.cache' or simply '-C') that saves the results of its tests to speed up reconfiguring. Caching is disabled by default to prevent problems with accidental use of stale cache files. If you need to do unusual things to compile the package, please try to figure out how 'configure' could check whether to do them, and mail diffs or instructions to the address given in the 'README' so they can be considered for the next release. If you are using the cache, and at some point 'config.cache' contains results you don't want to keep, you may remove or edit it. The file 'configure.ac' (or 'configure.in') is used to create 'configure' by a program called 'autoconf'. You need 'configure.ac' if you want to change it or regenerate 'configure' using a newer version of 'autoconf'. The simplest way to compile this package is: 1. 'cd' to the directory containing the package's source code and type './configure' to configure the package for your system. Running 'configure' might take a while. While running, it prints some messages telling which features it is checking for. 2. Type 'make' to compile the package. 3. Optionally, type 'make check' to run any self-tests that come with the package, generally using the just-built uninstalled binaries. 4. Type 'make install' to install the programs and any data files and documentation. When installing into a prefix owned by root, it is recommended that the package be configured and built as a regular user, and only the 'make install' phase executed with root privileges. 5. Optionally, type 'make installcheck' to repeat any self-tests, but this time using the binaries in their final installed location. This target does not install anything. Running this target as a regular user, particularly if the prior 'make install' required root privileges, verifies that the installation completed correctly. 6. You can remove the program binaries and object files from the source code directory by typing 'make clean'. To also remove the files that 'configure' created (so you can compile the package for a different kind of computer), type 'make distclean'. There is also a 'make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. 7. Often, you can also type 'make uninstall' to remove the installed files again. In practice, not all packages have tested that uninstallation works correctly, even though it is required by the GNU Coding Standards. 8. Some packages, particularly those that use Automake, provide 'make distcheck', which can by used by developers to test that all other targets like 'make install' and 'make uninstall' work correctly. This target is generally not run by end users. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the 'configure' script does not know about. Run './configure --help' for details on some of the pertinent environment variables. You can give 'configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: ./configure CC=c99 CFLAGS=-g LIBS=-lposix *Note Defining Variables::, for more details. Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you can use GNU 'make'. 'cd' to the directory where you want the object files and executables to go and run the 'configure' script. 'configure' automatically checks for the source code in the directory that 'configure' is in and in '..'. This is known as a "VPATH" build. With a non-GNU 'make', it is safer to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use 'make distclean' before reconfiguring for another architecture. On MacOS X 10.5 and later systems, you can create libraries and executables that work on multiple system types--known as "fat" or "universal" binaries--by specifying multiple '-arch' options to the compiler but only a single '-arch' option to the preprocessor. Like this: ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CPP="gcc -E" CXXCPP="g++ -E" This is not guaranteed to produce working output in all cases, you may have to build one architecture at a time and combine the results using the 'lipo' tool if you have problems. Installation Names ================== By default, 'make install' installs the package's commands under '/usr/local/bin', include files under '/usr/local/include', etc. You can specify an installation prefix other than '/usr/local' by giving 'configure' the option '--prefix=PREFIX', where PREFIX must be an absolute file name. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you pass the option '--exec-prefix=PREFIX' to 'configure', the package uses PREFIX as the prefix for installing programs and libraries. Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give options like '--bindir=DIR' to specify different values for particular kinds of files. Run 'configure --help' for a list of the directories you can set and what kinds of files go in them. In general, the default for these options is expressed in terms of '${prefix}', so that specifying just '--prefix' will affect all of the other directory specifications that were not explicitly provided. The most portable way to affect installation locations is to pass the correct locations to 'configure'; however, many packages provide one or both of the following shortcuts of passing variable assignments to the 'make install' command line to change installation locations without having to reconfigure or recompile. The first method involves providing an override variable for each affected directory. For example, 'make install prefix=/alternate/directory' will choose an alternate location for all directory configuration variables that were expressed in terms of '${prefix}'. Any directories that were specified during 'configure', but not in terms of '${prefix}', must each be overridden at install time for the entire installation to be relocated. The approach of makefile variable overrides for each directory variable is required by the GNU Coding Standards, and ideally causes no recompilation. However, some platforms have known limitations with the semantics of shared libraries that end up requiring recompilation when using this method, particularly noticeable in packages that use GNU Libtool. The second method involves providing the 'DESTDIR' variable. For example, 'make install DESTDIR=/alternate/directory' will prepend '/alternate/directory' before all installation names. The approach of 'DESTDIR' overrides is not required by the GNU Coding Standards, and does not work on platforms that have drive letters. On the other hand, it does better at avoiding recompilation issues, and works well even when some directory options were not specified in terms of '${prefix}' at 'configure' time. Optional Features ================= If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving 'configure' the option '--program-prefix=PREFIX' or '--program-suffix=SUFFIX'. Some packages pay attention to '--enable-FEATURE' options to 'configure', where FEATURE indicates an optional part of the package. They may also pay attention to '--with-PACKAGE' options, where PACKAGE is something like 'gnu-as' or 'x' (for the X Window System). The 'README' should mention any '--enable-' and '--with-' options that the package recognizes. For packages that use the X Window System, 'configure' can usually find the X include and library files automatically, but if it doesn't, you can use the 'configure' options '--x-includes=DIR' and '--x-libraries=DIR' to specify their locations. Some packages offer the ability to configure how verbose the execution of 'make' will be. For these packages, running './configure --enable-silent-rules' sets the default to minimal output, which can be overridden with 'make V=1'; while running './configure --disable-silent-rules' sets the default to verbose, which can be overridden with 'make V=0'. Particular systems ================== On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC is not installed, it is recommended to use the following options in order to use an ANSI C compiler: ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" and if that doesn't work, install pre-built binaries of GCC for HP-UX. HP-UX 'make' updates targets which have the same time stamps as their prerequisites, which makes it generally unusable when shipped generated files such as 'configure' are involved. Use GNU 'make' instead. On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot parse its '' header file. The option '-nodtk' can be used as a workaround. If GNU CC is not installed, it is therefore recommended to try ./configure CC="cc" and if that doesn't work, try ./configure CC="cc -nodtk" On Solaris, don't put '/usr/ucb' early in your 'PATH'. This directory contains several dysfunctional programs; working variants of these programs are available in '/usr/bin'. So, if you need '/usr/ucb' in your 'PATH', put it _after_ '/usr/bin'. On Haiku, software installed for all users goes in '/boot/common', not '/usr/local'. It is recommended to use the following options: ./configure --prefix=/boot/common Specifying the System Type ========================== There may be some features 'configure' cannot figure out automatically, but needs to determine by the type of machine the package will run on. Usually, assuming the package is built to be run on the _same_ architectures, 'configure' can figure that out, but if it prints a message saying it cannot guess the machine type, give it the '--build=TYPE' option. TYPE can either be a short name for the system type, such as 'sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM where SYSTEM can have one of these forms: OS KERNEL-OS See the file 'config.sub' for the possible values of each field. If 'config.sub' isn't included in this package, then this package doesn't need to know the machine type. If you are _building_ compiler tools for cross-compiling, you should use the option '--target=TYPE' to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the "host" platform (i.e., that on which the generated programs will eventually be run) with '--host=TYPE'. Sharing Defaults ================ If you want to set default values for 'configure' scripts to share, you can create a site shell script called 'config.site' that gives default values for variables like 'CC', 'cache_file', and 'prefix'. 'configure' looks for 'PREFIX/share/config.site' if it exists, then 'PREFIX/etc/config.site' if it exists. Or, you can set the 'CONFIG_SITE' environment variable to the location of the site script. A warning: not all 'configure' scripts look for a site script. Defining Variables ================== Variables not defined in a site shell script can be set in the environment passed to 'configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set them in the 'configure' command line, using 'VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc causes the specified 'gcc' to be used as the C compiler (unless it is overridden in the site shell script). Unfortunately, this technique does not work for 'CONFIG_SHELL' due to an Autoconf limitation. Until the limitation is lifted, you can use this workaround: CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash 'configure' Invocation ====================== 'configure' recognizes the following options to control how it operates. '--help' '-h' Print a summary of all of the options to 'configure', and exit. '--help=short' '--help=recursive' Print a summary of the options unique to this package's 'configure', and exit. The 'short' variant lists options used only in the top level, while the 'recursive' variant lists options also present in any nested packages. '--version' '-V' Print the version of Autoconf used to generate the 'configure' script, and exit. '--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, traditionally 'config.cache'. FILE defaults to '/dev/null' to disable caching. '--config-cache' '-C' Alias for '--cache-file=config.cache'. '--quiet' '--silent' '-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to '/dev/null' (any error messages will still be shown). '--srcdir=DIR' Look for the package's source code in directory DIR. Usually 'configure' can determine that directory automatically. '--prefix=DIR' Use DIR as the installation prefix. *note Installation Names:: for more details, including other options available for fine-tuning the installation locations. '--no-create' '-n' Run the configure checks, but stop before creating any output files. 'configure' also accepts some other, not widely useful, options. Run 'configure --help' for more details. libtorrent-0.16.11/configure0000755000000000000000000273661315175073425011435 #! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.72 for libtorrent 0.16.11. # # Report bugs to . # # # Copyright (C) 1992-1996, 1998-2017, 2020-2023 Free Software Foundation, # Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case e in #( e) case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac ;; esac fi # Reset variables that may have inherited troublesome values from # the environment. # IFS needs to be set, to space, tab, and newline, in precisely that order. # (If _AS_PATH_WALK were called with IFS unset, it would have the # side effect of setting IFS to empty, thus disabling word splitting.) # Quoting is to prevent editors from complaining about space-tab. as_nl=' ' export as_nl IFS=" "" $as_nl" PS1='$ ' PS2='> ' PS4='+ ' # Ensure predictable behavior from utilities with locale-dependent output. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # We cannot yet rely on "unset" to work, but we need these variables # to be unset--not just set to an empty or harmless value--now, to # avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct # also avoids known problems related to "unset" and subshell syntax # in other old shells (e.g. bash 2.01 and pdksh 5.2.14). for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH do eval test \${$as_var+y} \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done # Ensure that fds 0, 1, and 2 are open. if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi if (exec 3>&2) ; then :; else exec 2>/dev/null; fi # The user is always right. if ${PATH_SEPARATOR+false} :; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac test -r "$as_dir$0" && as_myself=$as_dir$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as 'sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed 'exec'. printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case e in #( e) case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ) then : else case e in #( e) exitcode=1; echo positional parameters were not saved. ;; esac fi test x\$exitcode = x0 || exit 1 blah=\$(echo \$(echo blah)) test x\"\$blah\" = xblah || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null then : as_have_required=yes else case e in #( e) as_have_required=no ;; esac fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null then : else case e in #( e) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null then : CONFIG_SHELL=$as_shell as_have_required=yes if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null then : break 2 fi fi done;; esac as_found=false done IFS=$as_save_IFS if $as_found then : else case e in #( e) if { test -f "$SHELL" || test -f "$SHELL.exe"; } && as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null then : CONFIG_SHELL=$SHELL as_have_required=yes fi ;; esac fi if test "x$CONFIG_SHELL" != x then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed 'exec'. printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno then : printf "%s\n" "$0: This script requires a shell more modern than all" printf "%s\n" "$0: the shells that I found on your system." if test ${ZSH_VERSION+y} ; then printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should" printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later." else printf "%s\n" "$0: Please tell bug-autoconf@gnu.org and $0: [sundell.software@gmail.com] about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi ;; esac fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null then : eval 'as_fn_append () { eval $1+=\$2 }' else case e in #( e) as_fn_append () { eval $1=\$$1\$2 } ;; esac fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null then : eval 'as_fn_arith () { as_val=$(( $* )) }' else case e in #( e) as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } ;; esac fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi printf "%s\n" "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' t clear :clear s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } # Determine whether it's possible to make 'echo' print without a newline. # These variables are no longer used directly by Autoconf, but are AC_SUBSTed # for compatibility with existing Makefiles. ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac # For backward compatibility with old third-party macros, we provide # the shell variables $as_echo and $as_echo_n. New code should use # AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively. as_echo='printf %s\n' as_echo_n='printf %s' rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both 'ln -s file dir' and 'ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; 'ln -s' creates a wrapper executable. # In both cases, we have to default to 'cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_sed_cpp="y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g" as_tr_cpp="eval sed '$as_sed_cpp'" # deprecated # Sed expression to map a string onto a valid variable name. as_sed_sh="y%*+%pp%;s%[^_$as_cr_alnum]%_%g" as_tr_sh="eval sed '$as_sed_sh'" # deprecated SHELL=${CONFIG_SHELL-/bin/sh} test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='libtorrent' PACKAGE_TARNAME='libtorrent' PACKAGE_VERSION='0.16.11' PACKAGE_STRING='libtorrent 0.16.11' PACKAGE_BUGREPORT='sundell.software@gmail.com' PACKAGE_URL='' # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_STDIO_H # include #endif #ifdef HAVE_STDLIB_H # include #endif #ifdef HAVE_STRING_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_header_c_list= enable_year2038=no ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBOBJS LIBTORRENT_CFLAGS LIBTORRENT_LIBS OPENSSL_LIBS OPENSSL_CFLAGS ZLIB_LIBS ZLIB_CFLAGS CPPUNIT_LIBS CPPUNIT_CFLAGS LIBCURL LIBCURL_CPPFLAGS _libcurl_config LIBCURL_LIBS LIBCURL_CFLAGS PKG_CONFIG_LIBDIR PKG_CONFIG_PATH PKG_CONFIG ATOMIC_LIBS PTHREAD_CFLAGS PTHREAD_LIBS PTHREAD_CXX PTHREAD_CC ax_pthread_config CPP HAVE_CXX17 CXXCPP am__fastdepCXX_FALSE am__fastdepCXX_TRUE CXXDEPMODE ac_ct_CXX CXXFLAGS CXX LIBTORRENT_INTERFACE_VERSION_NO LIBTORRENT_INTERFACE_VERSION_INFO LIBTORRENT_CURRENT LT_SYS_LIBRARY_PATH OTOOL64 OTOOL LIPO NMEDIT DSYMUTIL MANIFEST_TOOL RANLIB ac_ct_AR AR DLLTOOL OBJDUMP FILECMD LN_S NM ac_ct_DUMPBIN DUMPBIN LD FGREP EGREP GREP SED am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE am__nodep AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE am__include DEPDIR OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC host_os host_vendor host_cpu host build_os build_vendor build_cpu build LIBTOOL am__xargs_n am__rm_f_notfound AM_BACKSLASH AM_DEFAULT_VERBOSITY AM_DEFAULT_V AM_V CSCOPE ETAGS CTAGS am__untar am__tar AMTAR am__leading_dot SET_MAKE AWK mkdir_p MKDIR_P INSTALL_STRIP_PROGRAM STRIP install_sh MAKEINFO AUTOHEADER AUTOMAKE AUTOCONF ACLOCAL VERSION PACKAGE CYGPATH_W am__isrc INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir runstatedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL am__quote' ac_subst_files='' ac_user_opts=' enable_option_checking enable_silent_rules enable_static enable_shared with_pic enable_fast_install with_aix_soname enable_dependency_tracking with_gnu_ld with_sysroot enable_libtool_lock enable_largefile enable_debug enable_extra_debug enable_werror enable_aligned enable_interrupt_socket enable_arch with_kqueue with_epoll with_posix_fallocate with_address_space with_statvfs with_statfs enable_attribute_visibility enable_execinfo with_libcurl enable_pthread_setname_np enable_mincore enable_instrumentation enable_year2038 ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS LT_SYS_LIBRARY_PATH CXX CXXFLAGS CCC CXXCPP CPP PKG_CONFIG PKG_CONFIG_PATH PKG_CONFIG_LIBDIR LIBCURL_CFLAGS LIBCURL_LIBS CPPUNIT_CFLAGS CPPUNIT_LIBS ZLIB_CFLAGS ZLIB_LIBS OPENSSL_CFLAGS OPENSSL_LIBS' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: '$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: '$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -runstatedir | --runstatedir | --runstatedi | --runstated \ | --runstate | --runstat | --runsta | --runst | --runs \ | --run | --ru | --r) ac_prev=runstatedir ;; -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ | --run=* | --ru=* | --r=*) runstatedir=$ac_optarg ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: '$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: '$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: '$ac_option' Try '$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: '$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && printf "%s\n" "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: '$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but 'cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF 'configure' configures libtorrent 0.16.11 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print 'checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for '--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or '..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, 'make install' will install all the files in '$ac_default_prefix/bin', '$ac_default_prefix/lib' etc. You can specify an installation prefix other than '$ac_default_prefix' using '--prefix', for instance '--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/libtorrent] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of libtorrent 0.16.11:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-silent-rules less verbose build output (undo: "make V=1") --disable-silent-rules verbose build output (undo: "make V=0") --enable-static[=PKGS] build static libraries [default=no] --enable-shared[=PKGS] build shared libraries [default=yes] --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --enable-dependency-tracking do not reject slow dependency extractors --disable-dependency-tracking speeds up one-time build --disable-libtool-lock avoid locking (might break parallel builds) --disable-largefile omit support for large files --enable-debug enable debug information [[default=yes]] --enable-extra-debug enable extra debugging checks [[default=no]] --enable-werror enable the -Werror and -Wall flags [[default -Wall only]] --enable-aligned enable alignment safe code [[default=check]] --enable-interrupt-socket enable interrupt socket [[default=no]] --enable-arch=ARCH comma seprated list of architectures to compile for --disable-attribute-visibility disable symbol visibility attribute [[default=enable]] --disable-execinfo disable libexecinfo [[default=enable]] --disable-pthread-setname-np disable pthread_setname_np --disable-mincore disable mincore check [[default=enable]] --disable-instrumentation disable instrumentation [[default=enabled]] --enable-year2038 support timestamps after 2038 Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use both] --with-aix-soname=aix|svr4|both shared library versioning (aka "SONAME") variant to provide on AIX, [default=aix]. --with-gnu-ld assume the C compiler uses GNU ld [default=no] --with-sysroot[=DIR] Search for dependent libraries within DIR (or the compiler's sysroot if not specified). --with-sysroot=PATH compile and link with a specific sysroot --without-kqueue do not check for kqueue support --without-epoll do not check for epoll support --with-posix-fallocate check for and use posix_fallocate to allocate files --with-address-space=MB change the default address space size [[default=1024mb]] --without-statvfs don't try to use statvfs to find free diskspace --without-statfs don't try to use statfs to find free diskspace --with-libcurl=PREFIX look for the curl library in PREFIX/lib and headers in PREFIX/include Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory LT_SYS_LIBRARY_PATH User-defined run-time library search path. CXX C++ compiler command CXXFLAGS C++ compiler flags CXXCPP C++ preprocessor CPP C preprocessor PKG_CONFIG path to pkg-config utility PKG_CONFIG_PATH directories to add to pkg-config's search path PKG_CONFIG_LIBDIR path overriding pkg-config's built-in search path LIBCURL_CFLAGS C compiler flags for LIBCURL, overriding pkg-config LIBCURL_LIBS linker flags for LIBCURL, overriding pkg-config CPPUNIT_CFLAGS C compiler flags for CPPUNIT, overriding pkg-config CPPUNIT_LIBS linker flags for CPPUNIT, overriding pkg-config ZLIB_CFLAGS C compiler flags for ZLIB, overriding pkg-config ZLIB_LIBS linker flags for ZLIB, overriding pkg-config OPENSSL_CFLAGS C compiler flags for OPENSSL, overriding pkg-config OPENSSL_LIBS linker flags for OPENSSL, overriding pkg-config Use these variables to override the choices made by 'configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for configure.gnu first; this name is used for a wrapper for # Metaconfig's "Configure" on case-insensitive file systems. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF libtorrent configure 0.16.11 generated by GNU Autoconf 2.72 Copyright (C) 2023 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest.beam if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext then : ac_retval=0 else case e in #( e) printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 ;; esac fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext } then : ac_retval=0 else case e in #( e) printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 ;; esac fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 printf %s "checking for $2... " >&6; } if eval test \${$3+y} then : printf %s "(cached) " >&6 else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO" then : eval "$3=yes" else case e in #( e) eval "$3=no" ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi eval ac_res=\$$3 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 printf %s "checking for $2... " >&6; } if eval test \${$3+y} then : printf %s "(cached) " >&6 else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (void); below. */ #include #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (void); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main (void) { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : eval "$3=yes" else case e in #( e) eval "$3=no" ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext ;; esac fi eval ac_res=\$$3 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func # ac_fn_cxx_try_compile LINENO # ---------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest.beam if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext then : ac_retval=0 else case e in #( e) printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 ;; esac fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_compile # ac_fn_cxx_try_cpp LINENO # ------------------------ # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err } then : ac_retval=0 else case e in #( e) printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 ;; esac fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_cpp # ac_fn_cxx_try_link LINENO # ------------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext } then : ac_retval=0 else case e in #( e) printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 ;; esac fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_link # ac_fn_c_try_run LINENO # ---------------------- # Try to run conftest.$ac_ext, and return whether this succeeded. Assumes that # executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; } then : ac_retval=0 else case e in #( e) printf "%s\n" "$as_me: program exited with status $ac_status" >&5 printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status ;; esac fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_compute_int LINENO EXPR VAR INCLUDES # -------------------------------------------- # Tries to find the compile-time value of EXPR in a program that includes # INCLUDES, setting VAR accordingly. Returns whether the value could be # computed ac_fn_c_compute_int () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if test "$cross_compiling" = yes; then # Depending upon the size, compute the lo and hi bounds. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main (void) { static int test_array [1 - 2 * !(($2) >= 0)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_lo=0 ac_mid=0 while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main (void) { static int test_array [1 - 2 * !(($2) <= $ac_mid)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_hi=$ac_mid; break else case e in #( e) as_fn_arith $ac_mid + 1 && ac_lo=$as_val if test $ac_lo -le $ac_mid; then ac_lo= ac_hi= break fi as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext done else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main (void) { static int test_array [1 - 2 * !(($2) < 0)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_hi=-1 ac_mid=-1 while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main (void) { static int test_array [1 - 2 * !(($2) >= $ac_mid)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_lo=$ac_mid; break else case e in #( e) as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val if test $ac_mid -le $ac_hi; then ac_lo= ac_hi= break fi as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext done else case e in #( e) ac_lo= ac_hi= ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext # Binary search between lo and hi bounds. while test "x$ac_lo" != "x$ac_hi"; do as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main (void) { static int test_array [1 - 2 * !(($2) <= $ac_mid)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_hi=$ac_mid else case e in #( e) as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext done case $ac_lo in #(( ?*) eval "$3=\$ac_lo"; ac_retval=0 ;; '') ac_retval=1 ;; esac else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 static long int longval (void) { return $2; } static unsigned long int ulongval (void) { return $2; } #include #include int main (void) { FILE *f = fopen ("conftest.val", "w"); if (! f) return 1; if (($2) < 0) { long int i = longval (); if (i != ($2)) return 1; fprintf (f, "%ld", i); } else { unsigned long int i = ulongval (); if (i != ($2)) return 1; fprintf (f, "%lu", i); } /* Do not output a trailing newline, as this causes \r\n confusion on some platforms. */ return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO" then : echo >>conftest.val; read $3 &5 printf %s "checking for $2... " >&6; } if eval test \${$3+y} then : printf %s "(cached) " >&6 else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : eval "$3=yes" else case e in #( e) eval "$3=no" ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi eval ac_res=\$$3 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_cxx_check_header_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err } then : ac_retval=0 else case e in #( e) printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 ;; esac fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_check_decl LINENO SYMBOL VAR INCLUDES EXTRA-OPTIONS FLAG-VAR # ------------------------------------------------------------------ # Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR # accordingly. Pass EXTRA-OPTIONS to the compiler, using FLAG-VAR. ac_fn_check_decl () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack as_decl_name=`echo $2|sed 's/ *(.*//'` { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 printf %s "checking whether $as_decl_name is declared... " >&6; } if eval test \${$3+y} then : printf %s "(cached) " >&6 else case e in #( e) as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` eval ac_save_FLAGS=\$$6 as_fn_append $6 " $5" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main (void) { #ifndef $as_decl_name #ifdef __cplusplus (void) $as_decl_use; #else (void) $as_decl_name; #endif #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : eval "$3=yes" else case e in #( e) eval "$3=no" ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext eval $6=\$ac_save_FLAGS ;; esac fi eval ac_res=\$$3 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_check_decl ac_configure_args_raw= for ac_arg do case $ac_arg in *\'*) ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append ac_configure_args_raw " '$ac_arg'" done case $ac_configure_args_raw in *$as_nl*) ac_safe_unquote= ;; *) ac_unsafe_z='|&;<>()$`\\"*?[ '' ' # This string ends in space, tab. ac_unsafe_a="$ac_unsafe_z#~" ac_safe_unquote="s/ '\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\)'/ \\1/g" ac_configure_args_raw=` printf "%s\n" "$ac_configure_args_raw" | sed "$ac_safe_unquote"`;; esac cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by libtorrent $as_me 0.16.11, which was generated by GNU Autoconf 2.72. Invocation command line was $ $0$ac_configure_args_raw _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac printf "%s\n" "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Sanitize IFS. IFS=" "" $as_nl" # Save into config.log some information that might help in debugging. { echo printf "%s\n" "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo printf "%s\n" "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac printf "%s\n" "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then printf "%s\n" "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac printf "%s\n" "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then printf "%s\n" "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && printf "%s\n" "$as_me: caught signal $ac_signal" printf "%s\n" "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h printf "%s\n" "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. if test -n "$CONFIG_SITE"; then ac_site_files="$CONFIG_SITE" elif test "x$prefix" != xNONE; then ac_site_files="$prefix/share/config.site $prefix/etc/config.site" else ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" fi for ac_site_file in $ac_site_files do case $ac_site_file in #( */*) : ;; #( *) : ac_site_file=./$ac_site_file ;; esac if test -f "$ac_site_file" && test -r "$ac_site_file"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See 'config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 printf "%s\n" "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 printf "%s\n" "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Test code for whether the C compiler supports C89 (global declarations) ac_c_conftest_c89_globals=' /* Does the compiler advertise C89 conformance? Do not test the value of __STDC__, because some compilers set it to 0 while being otherwise adequately conformant. */ #if !defined __STDC__ # error "Compiler does not advertise C89 conformance" #endif #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7 src/conf.sh. */ struct buf { int x; }; struct buf * (*rcsopen) (struct buf *, struct stat *, int); static char *e (char **p, int i) { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* C89 style stringification. */ #define noexpand_stringify(a) #a const char *stringified = noexpand_stringify(arbitrary+token=sequence); /* C89 style token pasting. Exercises some of the corner cases that e.g. old MSVC gets wrong, but not very hard. */ #define noexpand_concat(a,b) a##b #define expand_concat(a,b) noexpand_concat(a,b) extern int vA; extern int vbee; #define aye A #define bee B int *pvA = &expand_concat(v,aye); int *pvbee = &noexpand_concat(v,bee); /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not \xHH hex character constants. These do not provoke an error unfortunately, instead are silently treated as an "x". The following induces an error, until -std is added to get proper ANSI mode. Curiously \x00 != x always comes out true, for an array size at least. It is necessary to write \x00 == 0 to get something that is true only with -std. */ int osf4_cc_array ['\''\x00'\'' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) '\''x'\'' int xlc6_cc_array[FOO(a) == '\''x'\'' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, int *(*)(struct buf *, struct stat *, int), int, int);' # Test code for whether the C compiler supports C89 (body of main). ac_c_conftest_c89_main=' ok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]); ' # Test code for whether the C compiler supports C99 (global declarations) ac_c_conftest_c99_globals=' /* Does the compiler advertise C99 conformance? */ #if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L # error "Compiler does not advertise C99 conformance" #endif // See if C++-style comments work. #include extern int puts (const char *); extern int printf (const char *, ...); extern int dprintf (int, const char *, ...); extern void *malloc (size_t); extern void free (void *); // Check varargs macros. These examples are taken from C99 6.10.3.5. // dprintf is used instead of fprintf to avoid needing to declare // FILE and stderr. #define debug(...) dprintf (2, __VA_ARGS__) #define showlist(...) puts (#__VA_ARGS__) #define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) static void test_varargs_macros (void) { int x = 1234; int y = 5678; debug ("Flag"); debug ("X = %d\n", x); showlist (The first, second, and third items.); report (x>y, "x is %d but y is %d", x, y); } // Check long long types. #define BIG64 18446744073709551615ull #define BIG32 4294967295ul #define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) #if !BIG_OK #error "your preprocessor is broken" #endif #if BIG_OK #else #error "your preprocessor is broken" #endif static long long int bignum = -9223372036854775807LL; static unsigned long long int ubignum = BIG64; struct incomplete_array { int datasize; double data[]; }; struct named_init { int number; const wchar_t *name; double average; }; typedef const char *ccp; static inline int test_restrict (ccp restrict text) { // Iterate through items via the restricted pointer. // Also check for declarations in for loops. for (unsigned int i = 0; *(text+i) != '\''\0'\''; ++i) continue; return 0; } // Check varargs and va_copy. static bool test_varargs (const char *format, ...) { va_list args; va_start (args, format); va_list args_copy; va_copy (args_copy, args); const char *str = ""; int number = 0; float fnumber = 0; while (*format) { switch (*format++) { case '\''s'\'': // string str = va_arg (args_copy, const char *); break; case '\''d'\'': // int number = va_arg (args_copy, int); break; case '\''f'\'': // float fnumber = va_arg (args_copy, double); break; default: break; } } va_end (args_copy); va_end (args); return *str && number && fnumber; } ' # Test code for whether the C compiler supports C99 (body of main). ac_c_conftest_c99_main=' // Check bool. _Bool success = false; success |= (argc != 0); // Check restrict. if (test_restrict ("String literal") == 0) success = true; char *restrict newvar = "Another string"; // Check varargs. success &= test_varargs ("s, d'\'' f .", "string", 65, 34.234); test_varargs_macros (); // Check flexible array members. struct incomplete_array *ia = malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); ia->datasize = 10; for (int i = 0; i < ia->datasize; ++i) ia->data[i] = i * 1.234; // Work around memory leak warnings. free (ia); // Check named initializers. struct named_init ni = { .number = 34, .name = L"Test wide string", .average = 543.34343, }; ni.number = 58; int dynamic_array[ni.number]; dynamic_array[0] = argv[0][0]; dynamic_array[ni.number - 1] = 543; // work around unused variable warnings ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\''x'\'' || dynamic_array[ni.number - 1] != 543); ' # Test code for whether the C compiler supports C11 (global declarations) ac_c_conftest_c11_globals=' /* Does the compiler advertise C11 conformance? */ #if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L # error "Compiler does not advertise C11 conformance" #endif // Check _Alignas. char _Alignas (double) aligned_as_double; char _Alignas (0) no_special_alignment; extern char aligned_as_int; char _Alignas (0) _Alignas (int) aligned_as_int; // Check _Alignof. enum { int_alignment = _Alignof (int), int_array_alignment = _Alignof (int[100]), char_alignment = _Alignof (char) }; _Static_assert (0 < -_Alignof (int), "_Alignof is signed"); // Check _Noreturn. int _Noreturn does_not_return (void) { for (;;) continue; } // Check _Static_assert. struct test_static_assert { int x; _Static_assert (sizeof (int) <= sizeof (long int), "_Static_assert does not work in struct"); long int y; }; // Check UTF-8 literals. #define u8 syntax error! char const utf8_literal[] = u8"happens to be ASCII" "another string"; // Check duplicate typedefs. typedef long *long_ptr; typedef long int *long_ptr; typedef long_ptr long_ptr; // Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1. struct anonymous { union { struct { int i; int j; }; struct { int k; long int l; } w; }; int m; } v1; ' # Test code for whether the C compiler supports C11 (body of main). ac_c_conftest_c11_main=' _Static_assert ((offsetof (struct anonymous, i) == offsetof (struct anonymous, w.k)), "Anonymous union alignment botch"); v1.i = 2; v1.w.k = 5; ok |= v1.i != 5; ' # Test code for whether the C compiler supports C11 (complete). ac_c_conftest_c11_program="${ac_c_conftest_c89_globals} ${ac_c_conftest_c99_globals} ${ac_c_conftest_c11_globals} int main (int argc, char **argv) { int ok = 0; ${ac_c_conftest_c89_main} ${ac_c_conftest_c99_main} ${ac_c_conftest_c11_main} return ok; } " # Test code for whether the C compiler supports C99 (complete). ac_c_conftest_c99_program="${ac_c_conftest_c89_globals} ${ac_c_conftest_c99_globals} int main (int argc, char **argv) { int ok = 0; ${ac_c_conftest_c89_main} ${ac_c_conftest_c99_main} return ok; } " # Test code for whether the C compiler supports C89 (complete). ac_c_conftest_c89_program="${ac_c_conftest_c89_globals} int main (int argc, char **argv) { int ok = 0; ${ac_c_conftest_c89_main} return ok; } " as_fn_append ac_header_c_list " stdio.h stdio_h HAVE_STDIO_H" as_fn_append ac_header_c_list " stdlib.h stdlib_h HAVE_STDLIB_H" as_fn_append ac_header_c_list " string.h string_h HAVE_STRING_H" as_fn_append ac_header_c_list " inttypes.h inttypes_h HAVE_INTTYPES_H" as_fn_append ac_header_c_list " stdint.h stdint_h HAVE_STDINT_H" as_fn_append ac_header_c_list " strings.h strings_h HAVE_STRINGS_H" as_fn_append ac_header_c_list " sys/stat.h sys_stat_h HAVE_SYS_STAT_H" as_fn_append ac_header_c_list " sys/types.h sys_types_h HAVE_SYS_TYPES_H" as_fn_append ac_header_c_list " unistd.h unistd_h HAVE_UNISTD_H" # Test code for whether the C++ compiler supports C++98 (global declarations) ac_cxx_conftest_cxx98_globals=' // Does the compiler advertise C++98 conformance? #if !defined __cplusplus || __cplusplus < 199711L # error "Compiler does not advertise C++98 conformance" #endif // These inclusions are to reject old compilers that // lack the unsuffixed header files. #include #include // and are *not* freestanding headers in C++98. extern void assert (int); namespace std { extern int strcmp (const char *, const char *); } // Namespaces, exceptions, and templates were all added after "C++ 2.0". using std::exception; using std::strcmp; namespace { void test_exception_syntax() { try { throw "test"; } catch (const char *s) { // Extra parentheses suppress a warning when building autoconf itself, // due to lint rules shared with more typical C programs. assert (!(strcmp) (s, "test")); } } template struct test_template { T const val; explicit test_template(T t) : val(t) {} template T add(U u) { return static_cast(u) + val; } }; } // anonymous namespace ' # Test code for whether the C++ compiler supports C++98 (body of main) ac_cxx_conftest_cxx98_main=' assert (argc); assert (! argv[0]); { test_exception_syntax (); test_template tt (2.0); assert (tt.add (4) == 6.0); assert (true && !false); } ' # Test code for whether the C++ compiler supports C++11 (global declarations) ac_cxx_conftest_cxx11_globals=' // Does the compiler advertise C++ 2011 conformance? #if !defined __cplusplus || __cplusplus < 201103L # error "Compiler does not advertise C++11 conformance" #endif namespace cxx11test { constexpr int get_val() { return 20; } struct testinit { int i; double d; }; class delegate { public: delegate(int n) : n(n) {} delegate(): delegate(2354) {} virtual int getval() { return this->n; }; protected: int n; }; class overridden : public delegate { public: overridden(int n): delegate(n) {} virtual int getval() override final { return this->n * 2; } }; class nocopy { public: nocopy(int i): i(i) {} nocopy() = default; nocopy(const nocopy&) = delete; nocopy & operator=(const nocopy&) = delete; private: int i; }; // for testing lambda expressions template Ret eval(Fn f, Ret v) { return f(v); } // for testing variadic templates and trailing return types template auto sum(V first) -> V { return first; } template auto sum(V first, Args... rest) -> V { return first + sum(rest...); } } ' # Test code for whether the C++ compiler supports C++11 (body of main) ac_cxx_conftest_cxx11_main=' { // Test auto and decltype auto a1 = 6538; auto a2 = 48573953.4; auto a3 = "String literal"; int total = 0; for (auto i = a3; *i; ++i) { total += *i; } decltype(a2) a4 = 34895.034; } { // Test constexpr short sa[cxx11test::get_val()] = { 0 }; } { // Test initializer lists cxx11test::testinit il = { 4323, 435234.23544 }; } { // Test range-based for int array[] = {9, 7, 13, 15, 4, 18, 12, 10, 5, 3, 14, 19, 17, 8, 6, 20, 16, 2, 11, 1}; for (auto &x : array) { x += 23; } } { // Test lambda expressions using cxx11test::eval; assert (eval ([](int x) { return x*2; }, 21) == 42); double d = 2.0; assert (eval ([&](double x) { return d += x; }, 3.0) == 5.0); assert (d == 5.0); assert (eval ([=](double x) mutable { return d += x; }, 4.0) == 9.0); assert (d == 5.0); } { // Test use of variadic templates using cxx11test::sum; auto a = sum(1); auto b = sum(1, 2); auto c = sum(1.0, 2.0, 3.0); } { // Test constructor delegation cxx11test::delegate d1; cxx11test::delegate d2(); cxx11test::delegate d3(45); } { // Test override and final cxx11test::overridden o1(55464); } { // Test nullptr char *c = nullptr; } { // Test template brackets test_template<::test_template> v(test_template(12)); } { // Unicode literals char const *utf8 = u8"UTF-8 string \u2500"; char16_t const *utf16 = u"UTF-8 string \u2500"; char32_t const *utf32 = U"UTF-32 string \u2500"; } ' # Test code for whether the C compiler supports C++11 (complete). ac_cxx_conftest_cxx11_program="${ac_cxx_conftest_cxx98_globals} ${ac_cxx_conftest_cxx11_globals} int main (int argc, char **argv) { int ok = 0; ${ac_cxx_conftest_cxx98_main} ${ac_cxx_conftest_cxx11_main} return ok; } " # Test code for whether the C compiler supports C++98 (complete). ac_cxx_conftest_cxx98_program="${ac_cxx_conftest_cxx98_globals} int main (int argc, char **argv) { int ok = 0; ${ac_cxx_conftest_cxx98_main} return ok; } " # Auxiliary files required by this configure script. ac_aux_files="compile config.guess config.sub ltmain.sh missing install-sh" # Locations in which to look for auxiliary files. ac_aux_dir_candidates="${srcdir}${PATH_SEPARATOR}${srcdir}/..${PATH_SEPARATOR}${srcdir}/../.." # Search for a directory containing all of the required auxiliary files, # $ac_aux_files, from the $PATH-style list $ac_aux_dir_candidates. # If we don't find one directory that contains all the files we need, # we report the set of missing files from the *first* directory in # $ac_aux_dir_candidates and give up. ac_missing_aux_files="" ac_first_candidate=: printf "%s\n" "$as_me:${as_lineno-$LINENO}: looking for aux files: $ac_aux_files" >&5 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in $ac_aux_dir_candidates do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac as_found=: printf "%s\n" "$as_me:${as_lineno-$LINENO}: trying $as_dir" >&5 ac_aux_dir_found=yes ac_install_sh= for ac_aux in $ac_aux_files do # As a special case, if "install-sh" is required, that requirement # can be satisfied by any of "install-sh", "install.sh", or "shtool", # and $ac_install_sh is set appropriately for whichever one is found. if test x"$ac_aux" = x"install-sh" then if test -f "${as_dir}install-sh"; then printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install-sh found" >&5 ac_install_sh="${as_dir}install-sh -c" elif test -f "${as_dir}install.sh"; then printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install.sh found" >&5 ac_install_sh="${as_dir}install.sh -c" elif test -f "${as_dir}shtool"; then printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}shtool found" >&5 ac_install_sh="${as_dir}shtool install -c" else ac_aux_dir_found=no if $ac_first_candidate; then ac_missing_aux_files="${ac_missing_aux_files} install-sh" else break fi fi else if test -f "${as_dir}${ac_aux}"; then printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}${ac_aux} found" >&5 else ac_aux_dir_found=no if $ac_first_candidate; then ac_missing_aux_files="${ac_missing_aux_files} ${ac_aux}" else break fi fi fi done if test "$ac_aux_dir_found" = yes; then ac_aux_dir="$as_dir" break fi ac_first_candidate=false as_found=false done IFS=$as_save_IFS if $as_found then : else case e in #( e) as_fn_error $? "cannot find required auxiliary files:$ac_missing_aux_files" "$LINENO" 5 ;; esac fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. if test -f "${ac_aux_dir}config.guess"; then ac_config_guess="$SHELL ${ac_aux_dir}config.guess" fi if test -f "${ac_aux_dir}config.sub"; then ac_config_sub="$SHELL ${ac_aux_dir}config.sub" fi if test -f "$ac_aux_dir/configure"; then ac_configure="$SHELL ${ac_aux_dir}configure" fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: '$ac_var' was set to '$ac_old_val' in the previous run" >&5 printf "%s\n" "$as_me: error: '$ac_var' was set to '$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: '$ac_var' was not set in the previous run" >&5 printf "%s\n" "$as_me: error: '$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: '$ac_var' has changed since the previous run:" >&5 printf "%s\n" "$as_me: error: '$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in '$ac_var' since the previous run:" >&5 printf "%s\n" "$as_me: warning: ignoring whitespace changes in '$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: former value: '$ac_old_val'" >&5 printf "%s\n" "$as_me: former value: '$ac_old_val'" >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: current value: '$ac_new_val'" >&5 printf "%s\n" "$as_me: current value: '$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`printf "%s\n" "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run '${MAKE-make} distclean' and/or 'rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_config_headers="$ac_config_headers config.h" am__api_version='1.17' # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 printf %s "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if test ${ac_cv_path_install+y} then : printf %s "(cached) " >&6 else case e in #( e) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac # Account for fact that we put trailing slashes in our PATH walk. case $as_dir in #(( ./ | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir/" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir ;; esac fi if test ${ac_cv_path_install+y}; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 printf "%s\n" "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether sleep supports fractional seconds" >&5 printf %s "checking whether sleep supports fractional seconds... " >&6; } if test ${am_cv_sleep_fractional_seconds+y} then : printf %s "(cached) " >&6 else case e in #( e) if sleep 0.001 2>/dev/null then : am_cv_sleep_fractional_seconds=yes else case e in #( e) am_cv_sleep_fractional_seconds=no ;; esac fi ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_sleep_fractional_seconds" >&5 printf "%s\n" "$am_cv_sleep_fractional_seconds" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking filesystem timestamp resolution" >&5 printf %s "checking filesystem timestamp resolution... " >&6; } if test ${am_cv_filesystem_timestamp_resolution+y} then : printf %s "(cached) " >&6 else case e in #( e) # Default to the worst case. am_cv_filesystem_timestamp_resolution=2 # Only try to go finer than 1 sec if sleep can do it. # Don't try 1 sec, because if 0.01 sec and 0.1 sec don't work, # - 1 sec is not much of a win compared to 2 sec, and # - it takes 2 seconds to perform the test whether 1 sec works. # # Instead, just use the default 2s on platforms that have 1s resolution, # accept the extra 1s delay when using $sleep in the Automake tests, in # exchange for not incurring the 2s delay for running the test for all # packages. # am_try_resolutions= if test "$am_cv_sleep_fractional_seconds" = yes; then # Even a millisecond often causes a bunch of false positives, # so just try a hundredth of a second. The time saved between .001 and # .01 is not terribly consequential. am_try_resolutions="0.01 0.1 $am_try_resolutions" fi # In order to catch current-generation FAT out, we must *modify* files # that already exist; the *creation* timestamp is finer. Use names # that make ls -t sort them differently when they have equal # timestamps than when they have distinct timestamps, keeping # in mind that ls -t prints the *newest* file first. rm -f conftest.ts? : > conftest.ts1 : > conftest.ts2 : > conftest.ts3 # Make sure ls -t actually works. Do 'set' in a subshell so we don't # clobber the current shell's arguments. (Outer-level square brackets # are removed by m4; they're present so that m4 does not expand # ; be careful, easy to get confused.) if ( set X `ls -t conftest.ts[12]` && { test "$*" != "X conftest.ts1 conftest.ts2" || test "$*" != "X conftest.ts2 conftest.ts1"; } ); then :; else # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". printf "%s\n" ""Bad output from ls -t: \"`ls -t conftest.ts[12]`\""" >&5 { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error $? "ls -t produces unexpected output. Make sure there is not a broken ls alias in your environment. See 'config.log' for more details" "$LINENO" 5; } fi for am_try_res in $am_try_resolutions; do # Any one fine-grained sleep might happen to cross the boundary # between two values of a coarser actual resolution, but if we do # two fine-grained sleeps in a row, at least one of them will fall # entirely within a coarse interval. echo alpha > conftest.ts1 sleep $am_try_res echo beta > conftest.ts2 sleep $am_try_res echo gamma > conftest.ts3 # We assume that 'ls -t' will make use of high-resolution # timestamps if the operating system supports them at all. if (set X `ls -t conftest.ts?` && test "$2" = conftest.ts3 && test "$3" = conftest.ts2 && test "$4" = conftest.ts1); then # # Ok, ls -t worked. If we're at a resolution of 1 second, we're done, # because we don't need to test make. make_ok=true if test $am_try_res != 1; then # But if we've succeeded so far with a subsecond resolution, we # have one more thing to check: make. It can happen that # everything else supports the subsecond mtimes, but make doesn't; # notably on macOS, which ships make 3.81 from 2006 (the last one # released under GPLv2). https://bugs.gnu.org/68808 # # We test $MAKE if it is defined in the environment, else "make". # It might get overridden later, but our hope is that in practice # it does not matter: it is the system "make" which is (by far) # the most likely to be broken, whereas if the user overrides it, # probably they did so with a better, or at least not worse, make. # https://lists.gnu.org/archive/html/automake/2024-06/msg00051.html # # Create a Makefile (real tab character here): rm -f conftest.mk echo 'conftest.ts1: conftest.ts2' >conftest.mk echo ' touch conftest.ts2' >>conftest.mk # # Now, running # touch conftest.ts1; touch conftest.ts2; make # should touch ts1 because ts2 is newer. This could happen by luck, # but most often, it will fail if make's support is insufficient. So # test for several consecutive successes. # # (We reuse conftest.ts[12] because we still want to modify existing # files, not create new ones, per above.) n=0 make=${MAKE-make} until test $n -eq 3; do echo one > conftest.ts1 sleep $am_try_res echo two > conftest.ts2 # ts2 should now be newer than ts1 if $make -f conftest.mk | grep 'up to date' >/dev/null; then make_ok=false break # out of $n loop fi n=`expr $n + 1` done fi # if $make_ok; then # Everything we know to check worked out, so call this resolution good. am_cv_filesystem_timestamp_resolution=$am_try_res break # out of $am_try_res loop fi # Otherwise, we'll go on to check the next resolution. fi done rm -f conftest.ts? # (end _am_filesystem_timestamp_resolution) ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_filesystem_timestamp_resolution" >&5 printf "%s\n" "$am_cv_filesystem_timestamp_resolution" >&6; } # This check should not be cached, as it may vary across builds of # different projects. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 printf %s "checking whether build environment is sane... " >&6; } # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[\\\"\#\$\&\'\`$am_lf]*) as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; esac case $srcdir in *[\\\"\#\$\&\'\`$am_lf\ \ ]*) as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). am_build_env_is_sane=no am_has_slept=no rm -f conftest.file for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file if ( set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi test "$2" = conftest.file ); then am_build_env_is_sane=yes break fi # Just in case. sleep "$am_cv_filesystem_timestamp_resolution" am_has_slept=yes done { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_build_env_is_sane" >&5 printf "%s\n" "$am_build_env_is_sane" >&6; } if test "$am_build_env_is_sane" = no; then as_fn_error $? "newly created file is older than distributed files! Check your system clock" "$LINENO" 5 fi # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if test -e conftest.file || grep 'slept: no' conftest.file >/dev/null 2>&1 then : else case e in #( e) ( sleep "$am_cv_filesystem_timestamp_resolution" ) & am_sleep_pid=$! ;; esac fi rm -f conftest.file test "$program_prefix" != NONE && program_transform_name="s&^&$program_prefix&;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s&\$&$program_suffix&;$program_transform_name" # Double any \ or $. # By default was 's,x,x', remove it if useless. ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`printf "%s\n" "$program_transform_name" | sed "$ac_script"` # Expand $ac_aux_dir to an absolute path. am_aux_dir=`cd "$ac_aux_dir" && pwd` if test x"${MISSING+set}" != xset; then MISSING="\${SHELL} '$am_aux_dir/missing'" fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 printf "%s\n" "$as_me: WARNING: 'missing' script is too old or missing" >&2;} fi if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_STRIP+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 printf "%s\n" "$STRIP" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_STRIP+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 printf "%s\n" "$ac_ct_STRIP" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a race-free mkdir -p" >&5 printf %s "checking for a race-free mkdir -p... " >&6; } if test -z "$MKDIR_P"; then if test ${ac_cv_path_mkdir+y} then : printf %s "(cached) " >&6 else case e in #( e) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do as_fn_executable_p "$as_dir$ac_prog$ac_exec_ext" || continue case `"$as_dir$ac_prog$ac_exec_ext" --version 2>&1` in #( 'mkdir ('*'coreutils) '* | \ *'BusyBox '* | \ 'mkdir (fileutils) '4.1*) ac_cv_path_mkdir=$as_dir$ac_prog$ac_exec_ext break 3;; esac done done done IFS=$as_save_IFS ;; esac fi test -d ./--version && rmdir ./--version if test ${ac_cv_path_mkdir+y}; then MKDIR_P="$ac_cv_path_mkdir -p" else # As a last resort, use plain mkdir -p, # in the hope it doesn't have the bugs of ancient mkdir. MKDIR_P='mkdir -p' fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 printf "%s\n" "$MKDIR_P" >&6; } for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_AWK+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 printf "%s\n" "$AWK" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$AWK" && break done { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 printf %s "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`printf "%s\n" "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval test \${ac_cv_prog_make_${ac_make}_set+y} then : printf %s "(cached) " >&6 else case e in #( e) cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make ;; esac fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } SET_MAKE= else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AM_DEFAULT_VERBOSITY=1 # Check whether --enable-silent-rules was given. if test ${enable_silent_rules+y} then : enableval=$enable_silent_rules; fi am_make=${MAKE-make} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 printf %s "checking whether $am_make supports nested variables... " >&6; } if test ${am_cv_make_support_nested_variables+y} then : printf %s "(cached) " >&6 else case e in #( e) if printf "%s\n" 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 printf "%s\n" "$am_cv_make_support_nested_variables" >&6; } AM_BACKSLASH='\' am__rm_f_notfound= if (rm -f && rm -fr && rm -rf) 2>/dev/null then : else case e in #( e) am__rm_f_notfound='""' ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking xargs -n works" >&5 printf %s "checking xargs -n works... " >&6; } if test ${am_cv_xargs_n_works+y} then : printf %s "(cached) " >&6 else case e in #( e) if test "`echo 1 2 3 | xargs -n2 echo`" = "1 2 3" then : am_cv_xargs_n_works=yes else case e in #( e) am_cv_xargs_n_works=no ;; esac fi ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_xargs_n_works" >&5 printf "%s\n" "$am_cv_xargs_n_works" >&6; } if test "$am_cv_xargs_n_works" = yes then : am__xargs_n='xargs -n' else case e in #( e) am__xargs_n='am__xargs_n () { shift; sed "s/ /\\n/g" | while read am__xargs_n_arg; do "" "$am__xargs_n_arg"; done; }' ;; esac fi if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." am__isrc=' -I$(srcdir)' # test to see if srcdir already configured if test -f $srcdir/config.status; then as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE='libtorrent' VERSION='0.16.11' printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h printf "%s\n" "#define VERSION \"$VERSION\"" >>confdefs.h # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # mkdir_p='$(MKDIR_P)' # We need awk for the "check" target (and possibly the TAP driver). The # system "awk" is bad on some platforms. # Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AMTAR='$${TAR-tar}' # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar pax cpio none' am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' # Variables for tags utilities; see am/tags.am if test -z "$CTAGS"; then CTAGS=ctags fi if test -z "$ETAGS"; then ETAGS=etags fi if test -z "$CSCOPE"; then CSCOPE=cscope fi case `pwd` in *\ * | *\ *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 printf "%s\n" "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; esac macro_version='2.4.7' macro_revision='2.4.7' ltmain=$ac_aux_dir/ltmain.sh # Make sure we can run config.sub. $SHELL "${ac_aux_dir}config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL ${ac_aux_dir}config.sub" "$LINENO" 5 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 printf %s "checking build system type... " >&6; } if test ${ac_cv_build+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "${ac_aux_dir}config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "${ac_aux_dir}config.sub" $ac_build_alias` || as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $ac_build_alias failed" "$LINENO" 5 ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 printf "%s\n" "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 printf %s "checking host system type... " >&6; } if test ${ac_cv_host+y} then : printf %s "(cached) " >&6 else case e in #( e) if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "${ac_aux_dir}config.sub" $host_alias` || as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $host_alias failed" "$LINENO" 5 fi ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 printf "%s\n" "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac # Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\(["`$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 printf %s "checking how to print strings... " >&6; } # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "" } case $ECHO in printf*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: printf" >&5 printf "%s\n" "printf" >&6; } ;; print*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 printf "%s\n" "print -r" >&6; } ;; *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: cat" >&5 printf "%s\n" "cat" >&6; } ;; esac DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} supports the include directive" >&5 printf %s "checking whether ${MAKE-make} supports the include directive... " >&6; } cat > confinc.mk << 'END' am__doit: @echo this is the am__doit target >confinc.out .PHONY: am__doit END am__include="#" am__quote= # BSD make does it like this. echo '.include "confinc.mk" # ignored' > confmf.BSD # Other make implementations (GNU, Solaris 10, AIX) do it like this. echo 'include confinc.mk # ignored' > confmf.GNU _am_result=no for s in GNU BSD; do { echo "$as_me:$LINENO: ${MAKE-make} -f confmf.$s && cat confinc.out" >&5 (${MAKE-make} -f confmf.$s && cat confinc.out) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } case $?:`cat confinc.out 2>/dev/null` in #( '0:this is the am__doit target') : case $s in #( BSD) : am__include='.include' am__quote='"' ;; #( *) : am__include='include' am__quote='' ;; esac ;; #( *) : ;; esac if test "$am__include" != "#"; then _am_result="yes ($s style)" break fi done rm -f confinc.* confmf.* { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${_am_result}" >&5 printf "%s\n" "${_am_result}" >&6; } # Check whether --enable-dependency-tracking was given. if test ${enable_dependency_tracking+y} then : enableval=$enable_dependency_tracking; fi if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@" fi fi fi ;; esac fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args. set dummy ${ac_tool_prefix}clang; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}clang" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "clang", so it can be a program name with args. set dummy clang; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="clang" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi fi test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See 'config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion -version; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 printf %s "checking whether the C compiler works... " >&6; } ac_link_default=`printf "%s\n" "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then : # Autoconf-2.13 could set the ac_cv_exeext variable to 'no'. # So ignore a value of 'no', otherwise this would lead to 'EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test ${ac_cv_exeext+y} && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an '-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else case e in #( e) ac_file='' ;; esac fi if test -z "$ac_file" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See 'config.log' for more details" "$LINENO" 5; } else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 printf %s "checking for C compiler default output file name... " >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 printf "%s\n" "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 printf %s "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then : # If both 'conftest.exe' and 'conftest' are 'present' (well, observable) # catch 'conftest.exe'. For instance with Cygwin, 'ls conftest' will # work properly (i.e., refer to 'conftest.exe'), while it won't with # 'rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else case e in #( e) { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See 'config.log' for more details" "$LINENO" 5; } ;; esac fi rm -f conftest conftest$ac_cv_exeext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 printf "%s\n" "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { FILE *f = fopen ("conftest.out", "w"); if (!f) return 1; return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 printf %s "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error 77 "cannot run C compiled programs. If you meant to cross compile, use '--host'. See 'config.log' for more details" "$LINENO" 5; } fi fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 printf "%s\n" "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext \ conftest.o conftest.obj conftest.out ac_clean_files=$ac_clean_files_save { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 printf %s "checking for suffix of object files... " >&6; } if test ${ac_cv_objext+y} then : printf %s "(cached) " >&6 else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else case e in #( e) printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See 'config.log' for more details" "$LINENO" 5; } ;; esac fi rm -f conftest.$ac_cv_objext conftest.$ac_ext ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 printf "%s\n" "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5 printf %s "checking whether the compiler supports GNU C... " >&6; } if test ${ac_cv_c_compiler_gnu+y} then : printf %s "(cached) " >&6 else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_compiler_gnu=yes else case e in #( e) ac_compiler_gnu=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; } ac_compiler_gnu=$ac_cv_c_compiler_gnu if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+y} ac_save_CFLAGS=$CFLAGS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 printf %s "checking whether $CC accepts -g... " >&6; } if test ${ac_cv_prog_cc_g+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_g=yes else case e in #( e) CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : else case e in #( e) ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 printf "%s\n" "$ac_cv_prog_cc_g" >&6; } if test $ac_test_CFLAGS; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi ac_prog_cc_stdc=no if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5 printf %s "checking for $CC option to enable C11 features... " >&6; } if test ${ac_cv_prog_cc_c11+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_cv_prog_cc_c11=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c11_program _ACEOF for ac_arg in '' -std=gnu11 do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c11=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c11" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC ;; esac fi if test "x$ac_cv_prog_cc_c11" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else case e in #( e) if test "x$ac_cv_prog_cc_c11" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5 printf "%s\n" "$ac_cv_prog_cc_c11" >&6; } CC="$CC $ac_cv_prog_cc_c11" ;; esac fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11 ac_prog_cc_stdc=c11 ;; esac fi fi if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5 printf %s "checking for $CC option to enable C99 features... " >&6; } if test ${ac_cv_prog_cc_c99+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_cv_prog_cc_c99=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c99_program _ACEOF for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99= do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c99=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c99" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC ;; esac fi if test "x$ac_cv_prog_cc_c99" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else case e in #( e) if test "x$ac_cv_prog_cc_c99" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 printf "%s\n" "$ac_cv_prog_cc_c99" >&6; } CC="$CC $ac_cv_prog_cc_c99" ;; esac fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99 ac_prog_cc_stdc=c99 ;; esac fi fi if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5 printf %s "checking for $CC option to enable C89 features... " >&6; } if test ${ac_cv_prog_cc_c89+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c89_program _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC ;; esac fi if test "x$ac_cv_prog_cc_c89" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else case e in #( e) if test "x$ac_cv_prog_cc_c89" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 printf "%s\n" "$ac_cv_prog_cc_c89" >&6; } CC="$CC $ac_cv_prog_cc_c89" ;; esac fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89 ac_prog_cc_stdc=c89 ;; esac fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 printf %s "checking whether $CC understands -c and -o together... " >&6; } if test ${am_cv_prog_cc_c_o+y} then : printf %s "(cached) " >&6 else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 printf "%s\n" "$am_cv_prog_cc_c_o" >&6; } if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CC" am_compiler_list= { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 printf %s "checking dependency style of $depcc... " >&6; } if test ${am_cv_CC_dependencies_compiler_type+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thus: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 printf "%s\n" "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 printf %s "checking for a sed that does not truncate output... " >&6; } if test ${ac_cv_path_SED+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ for ac_i in 1 2 3 4 5 6 7; do ac_script="$ac_script$as_nl$ac_script" done echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed { ac_script=; unset ac_script;} if test -z "$SED"; then ac_path_SED_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_prog in sed gsed do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_SED="$as_dir$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_SED" || continue # Check for GNU ac_path_SED and select it if it is found. # Check for GNU $ac_path_SED case `"$ac_path_SED" --version 2>&1` in #( *GNU*) ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; #( *) ac_count=0 printf %s 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" printf "%s\n" '' >> "conftest.nl" "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_SED_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_SED="$ac_path_SED" ac_path_SED_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_SED_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_SED"; then as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 fi else ac_cv_path_SED=$SED fi ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 printf "%s\n" "$ac_cv_path_SED" >&6; } SED="$ac_cv_path_SED" rm -f conftest.sed test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 printf %s "checking for grep that handles long lines and -e... " >&6; } if test ${ac_cv_path_GREP+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_prog in grep ggrep do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in #( *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; #( *) ac_count=0 printf %s 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" printf "%s\n" 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 printf "%s\n" "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 printf %s "checking for egrep... " >&6; } if test ${ac_cv_path_EGREP+y} then : printf %s "(cached) " >&6 else case e in #( e) if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_prog in egrep do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in #( *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; #( *) ac_count=0 printf %s 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" printf "%s\n" 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 printf "%s\n" "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" EGREP_TRADITIONAL=$EGREP ac_cv_path_EGREP_TRADITIONAL=$EGREP { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 printf %s "checking for fgrep... " >&6; } if test ${ac_cv_path_FGREP+y} then : printf %s "(cached) " >&6 else case e in #( e) if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 then ac_cv_path_FGREP="$GREP -F" else if test -z "$FGREP"; then ac_path_FGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_prog in fgrep do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_FGREP="$as_dir$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_FGREP" || continue # Check for GNU ac_path_FGREP and select it if it is found. # Check for GNU $ac_path_FGREP case `"$ac_path_FGREP" --version 2>&1` in #( *GNU*) ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; #( *) ac_count=0 printf %s 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" printf "%s\n" 'FGREP' >> "conftest.nl" "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_FGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_FGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_FGREP"; then as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_FGREP=$FGREP fi fi ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 printf "%s\n" "$ac_cv_path_FGREP" >&6; } FGREP="$ac_cv_path_FGREP" test -z "$GREP" && GREP=grep # Check whether --with-gnu-ld was given. if test ${with_gnu_ld+y} then : withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes else case e in #( e) with_gnu_ld=no ;; esac fi ac_prog=ld if test yes = "$GCC"; then # Check if gcc -print-prog-name=ld gives a path. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 printf %s "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return, which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD=$ac_prog ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test yes = "$with_gnu_ld"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 printf %s "checking for GNU ld... " >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 printf %s "checking for non-GNU ld... " >&6; } fi if test ${lt_cv_path_LD+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -z "$LD"; then lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD=$ac_dir/$ac_prog # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 printf "%s\n" "$LD" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 printf %s "checking if the linker ($LD) is GNU ld... " >&6; } if test ${lt_cv_prog_gnu_ld+y} then : printf %s "(cached) " >&6 else case e in #( e) # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 printf "%s\n" "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 printf %s "checking for BSD- or MS-compatible name lister (nm)... " >&6; } if test ${lt_cv_path_NM+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM=$NM else lt_nm_to_check=${ac_tool_prefix}nm if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. tmp_nm=$ac_dir/$lt_tmp_nm if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then # Check to see if the nm accepts a BSD-compat flag. # Adding the 'sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty case $build_os in mingw*) lt_bad_file=conftest.nm/nofile ;; *) lt_bad_file=/dev/null ;; esac case `"$tmp_nm" -B $lt_bad_file 2>&1 | $SED '1q'` in *$lt_bad_file* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break 2 ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | $SED '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break 2 ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS=$lt_save_ifs done : ${lt_cv_path_NM=no} fi ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 printf "%s\n" "$lt_cv_path_NM" >&6; } if test no != "$lt_cv_path_NM"; then NM=$lt_cv_path_NM else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else if test -n "$ac_tool_prefix"; then for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_DUMPBIN+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$DUMPBIN"; then ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi DUMPBIN=$ac_cv_prog_DUMPBIN if test -n "$DUMPBIN"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 printf "%s\n" "$DUMPBIN" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$DUMPBIN" && break done fi if test -z "$DUMPBIN"; then ac_ct_DUMPBIN=$DUMPBIN for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_DUMPBIN+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$ac_ct_DUMPBIN"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN if test -n "$ac_ct_DUMPBIN"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 printf "%s\n" "$ac_ct_DUMPBIN" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$ac_ct_DUMPBIN" && break done if test "x$ac_ct_DUMPBIN" = x; then DUMPBIN=":" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DUMPBIN=$ac_ct_DUMPBIN fi fi case `$DUMPBIN -symbols -headers /dev/null 2>&1 | $SED '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols -headers" ;; *) DUMPBIN=: ;; esac fi if test : != "$DUMPBIN"; then NM=$DUMPBIN fi fi test -z "$NM" && NM=nm { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 printf %s "checking the name lister ($NM) interface... " >&6; } if test ${lt_cv_nm_interface+y} then : printf %s "(cached) " >&6 else case e in #( e) lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest* ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 printf "%s\n" "$lt_cv_nm_interface" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 printf %s "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 printf "%s\n" "no, using $LN_S" >&6; } fi # find the maximum length of command line arguments { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 printf %s "checking the maximum length of command line arguments... " >&6; } if test ${lt_cv_sys_max_cmd_len+y} then : printf %s "(cached) " >&6 else case e in #( e) i=0 teststring=ABCD case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; bitrig* | darwin* | dragonfly* | freebsd* | midnightbsd* | netbsd* | openbsd*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | $SED 's/.*[ ]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len" && \ test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test X`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test 17 != "$i" # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac ;; esac fi if test -n "$lt_cv_sys_max_cmd_len"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 printf "%s\n" "$lt_cv_sys_max_cmd_len" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none" >&5 printf "%s\n" "none" >&6; } fi max_cmd_len=$lt_cv_sys_max_cmd_len : ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 printf %s "checking how to convert $build file names to $host format... " >&6; } if test ${lt_cv_to_host_file_cmd+y} then : printf %s "(cached) " >&6 else case e in #( e) case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac ;; esac fi to_host_file_cmd=$lt_cv_to_host_file_cmd { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 printf "%s\n" "$lt_cv_to_host_file_cmd" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 printf %s "checking how to convert $build file names to toolchain format... " >&6; } if test ${lt_cv_to_tool_file_cmd+y} then : printf %s "(cached) " >&6 else case e in #( e) #assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac ;; esac fi to_tool_file_cmd=$lt_cv_to_tool_file_cmd { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 printf "%s\n" "$lt_cv_to_tool_file_cmd" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 printf %s "checking for $LD option to reload object files... " >&6; } if test ${lt_cv_ld_reload_flag+y} then : printf %s "(cached) " >&6 else case e in #( e) lt_cv_ld_reload_flag='-r' ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 printf "%s\n" "$lt_cv_ld_reload_flag" >&6; } reload_flag=$lt_cv_ld_reload_flag case $reload_flag in "" | " "*) ;; *) reload_flag=" $reload_flag" ;; esac reload_cmds='$LD$reload_flag -o $output$reload_objs' case $host_os in cygwin* | mingw* | pw32* | cegcc*) if test yes != "$GCC"; then reload_cmds=false fi ;; darwin*) if test yes = "$GCC"; then reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs' else reload_cmds='$LD$reload_flag -o $output$reload_objs' fi ;; esac if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}file", so it can be a program name with args. set dummy ${ac_tool_prefix}file; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_FILECMD+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$FILECMD"; then ac_cv_prog_FILECMD="$FILECMD" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_FILECMD="${ac_tool_prefix}file" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi FILECMD=$ac_cv_prog_FILECMD if test -n "$FILECMD"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $FILECMD" >&5 printf "%s\n" "$FILECMD" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_FILECMD"; then ac_ct_FILECMD=$FILECMD # Extract the first word of "file", so it can be a program name with args. set dummy file; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_FILECMD+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$ac_ct_FILECMD"; then ac_cv_prog_ac_ct_FILECMD="$ac_ct_FILECMD" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_FILECMD="file" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi ac_ct_FILECMD=$ac_cv_prog_ac_ct_FILECMD if test -n "$ac_ct_FILECMD"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_FILECMD" >&5 printf "%s\n" "$ac_ct_FILECMD" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_FILECMD" = x; then FILECMD=":" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac FILECMD=$ac_ct_FILECMD fi else FILECMD="$ac_cv_prog_FILECMD" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. set dummy ${ac_tool_prefix}objdump; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_OBJDUMP+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$OBJDUMP"; then ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi OBJDUMP=$ac_cv_prog_OBJDUMP if test -n "$OBJDUMP"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 printf "%s\n" "$OBJDUMP" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_OBJDUMP"; then ac_ct_OBJDUMP=$OBJDUMP # Extract the first word of "objdump", so it can be a program name with args. set dummy objdump; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_OBJDUMP+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$ac_ct_OBJDUMP"; then ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OBJDUMP="objdump" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP if test -n "$ac_ct_OBJDUMP"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 printf "%s\n" "$ac_ct_OBJDUMP" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_OBJDUMP" = x; then OBJDUMP="false" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OBJDUMP=$ac_ct_OBJDUMP fi else OBJDUMP="$ac_cv_prog_OBJDUMP" fi test -z "$OBJDUMP" && OBJDUMP=objdump { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 printf %s "checking how to recognize dependent libraries... " >&6; } if test ${lt_cv_deplibs_check_method+y} then : printf %s "(cached) " >&6 else case e in #( e) lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # 'unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # that responds to the $file_magic_cmd with a given extended regex. # If you have 'file' or equivalent on your system and you're not sure # whether 'pass_all' will *always* work, you probably want this one. case $host_os in aix[4-9]*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[45]*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='$FILECMD -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. if ( file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly* | midnightbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=$FILECMD lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=$FILECMD case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[3-9]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=$FILECMD lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd* | bitrig*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; os2*) lt_cv_deplibs_check_method=pass_all ;; esac ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 printf "%s\n" "$lt_cv_deplibs_check_method" >&6; } file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. set dummy ${ac_tool_prefix}dlltool; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_DLLTOOL+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$DLLTOOL"; then ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi DLLTOOL=$ac_cv_prog_DLLTOOL if test -n "$DLLTOOL"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 printf "%s\n" "$DLLTOOL" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_DLLTOOL"; then ac_ct_DLLTOOL=$DLLTOOL # Extract the first word of "dlltool", so it can be a program name with args. set dummy dlltool; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_DLLTOOL+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$ac_ct_DLLTOOL"; then ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DLLTOOL="dlltool" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL if test -n "$ac_ct_DLLTOOL"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 printf "%s\n" "$ac_ct_DLLTOOL" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_DLLTOOL" = x; then DLLTOOL="false" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DLLTOOL=$ac_ct_DLLTOOL fi else DLLTOOL="$ac_cv_prog_DLLTOOL" fi test -z "$DLLTOOL" && DLLTOOL=dlltool { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 printf %s "checking how to associate runtime and link libraries... " >&6; } if test ${lt_cv_sharedlib_from_linklib_cmd+y} then : printf %s "(cached) " >&6 else case e in #( e) lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh; # decide which one to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd=$ECHO ;; esac ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 printf "%s\n" "$lt_cv_sharedlib_from_linklib_cmd" >&6; } sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO if test -n "$ac_tool_prefix"; then for ac_prog in ar do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_AR+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_AR="$ac_tool_prefix$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi AR=$ac_cv_prog_AR if test -n "$AR"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 printf "%s\n" "$AR" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$AR" && break done fi if test -z "$AR"; then ac_ct_AR=$AR for ac_prog in ar do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_AR+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 printf "%s\n" "$ac_ct_AR" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$ac_ct_AR" && break done if test "x$ac_ct_AR" = x; then AR="false" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi fi : ${AR=ar} # Use ARFLAGS variable as AR's operation code to sync the variable naming with # Automake. If both AR_FLAGS and ARFLAGS are specified, AR_FLAGS should have # higher priority because thats what people were doing historically (setting # ARFLAGS for automake and AR_FLAGS for libtool). FIXME: Make the AR_FLAGS # variable obsoleted/removed. test ${AR_FLAGS+y} || AR_FLAGS=${ARFLAGS-cr} lt_ar_flags=$AR_FLAGS # Make AR_FLAGS overridable by 'make ARFLAGS='. Don't try to run-time override # by AR_FLAGS because that was never working and AR_FLAGS is about to die. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 printf %s "checking for archiver @FILE support... " >&6; } if test ${lt_cv_ar_at_file+y} then : printf %s "(cached) " >&6 else case e in #( e) lt_cv_ar_at_file=no cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test 0 -eq "$ac_status"; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test 0 -ne "$ac_status"; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 printf "%s\n" "$lt_cv_ar_at_file" >&6; } if test no = "$lt_cv_ar_at_file"; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_STRIP+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 printf "%s\n" "$STRIP" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_STRIP+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 printf "%s\n" "$ac_ct_STRIP" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi test -z "$STRIP" && STRIP=: if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_RANLIB+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 printf "%s\n" "$RANLIB" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_RANLIB+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 printf "%s\n" "$ac_ct_RANLIB" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi test -z "$RANLIB" && RANLIB=: # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in bitrig* | openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Check for command to grab the raw symbol name followed by C symbol from nm. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 printf %s "checking command to parse $NM output from $compiler object... " >&6; } if test ${lt_cv_sys_global_symbol_pipe+y} then : printf %s "(cached) " >&6 else case e in #( e) # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[BCDEGRST]' # Regexp to match symbols that can be accessed directly from C. sympat='\([_A-Za-z][_A-Za-z0-9]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[BCDT]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[ABCDGISTW]' ;; hpux*) if test ia64 = "$host_cpu"; then symcode='[ABCDEGRST]' fi ;; irix* | nonstopux*) symcode='[BCDEGRST]' ;; osf*) symcode='[BCDEGQRST]' ;; solaris*) symcode='[BDRT]' ;; sco3.2v5*) symcode='[DT]' ;; sysv4.2uw2*) symcode='[DT]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[ABDT]' ;; sysv4) symcode='[DFNSTU]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[ABCDGIRSTW]' ;; esac if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Gets list of data symbols to import. lt_cv_sys_global_symbol_to_import="$SED -n -e 's/^I .* \(.*\)$/\1/p'" # Adjust the below global symbol transforms to fixup imported variables. lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" lt_c_name_lib_hook="\ -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" else # Disable hooks by default. lt_cv_sys_global_symbol_to_import= lt_cdecl_hook= lt_c_name_hook= lt_c_name_lib_hook= fi # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="$SED -n"\ $lt_cdecl_hook\ " -e 's/^T .* \(.*\)$/extern int \1();/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="$SED -n"\ $lt_c_name_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" # Transform an extracted symbol line into symbol name with lib prefix and # symbol address. lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="$SED -n"\ $lt_c_name_lib_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function, # D for any global variable and I for any imported variable. # Also find C++ and __fastcall symbols from MSVC++ or ICC, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK '"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ " /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ " /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ " {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ " s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx" else lt_cv_sys_global_symbol_pipe="$SED -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | $SED '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # Now try to grab the symbols. nlist=conftest.nm if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE /* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS=conftstm.$ac_objext CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest$ac_exeext; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&5 fi else echo "cannot find nm_test_var in $nlist" >&5 fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 fi else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test yes = "$pipe_works"; then break else lt_cv_sys_global_symbol_pipe= fi done ;; esac fi if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: failed" >&5 printf "%s\n" "failed" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ok" >&5 printf "%s\n" "ok" >&6; } fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then nm_file_list_spec='@' fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 printf %s "checking for sysroot... " >&6; } # Check whether --with-sysroot was given. if test ${with_sysroot+y} then : withval=$with_sysroot; else case e in #( e) with_sysroot=no ;; esac fi lt_sysroot= case $with_sysroot in #( yes) if test yes = "$GCC"; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | $SED -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $with_sysroot" >&5 printf "%s\n" "$with_sysroot" >&6; } as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 printf "%s\n" "${lt_sysroot:-no}" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a working dd" >&5 printf %s "checking for a working dd... " >&6; } if test ${ac_cv_path_lt_DD+y} then : printf %s "(cached) " >&6 else case e in #( e) printf 0123456789abcdef0123456789abcdef >conftest.i cat conftest.i conftest.i >conftest2.i : ${lt_DD:=$DD} if test -z "$lt_DD"; then ac_path_lt_DD_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_prog in dd do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_lt_DD="$as_dir$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_lt_DD" || continue if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: fi $ac_path_lt_DD_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_lt_DD"; then : fi else ac_cv_path_lt_DD=$lt_DD fi rm -f conftest.i conftest2.i conftest.out ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_lt_DD" >&5 printf "%s\n" "$ac_cv_path_lt_DD" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to truncate binary pipes" >&5 printf %s "checking how to truncate binary pipes... " >&6; } if test ${lt_cv_truncate_bin+y} then : printf %s "(cached) " >&6 else case e in #( e) printf 0123456789abcdef0123456789abcdef >conftest.i cat conftest.i conftest.i >conftest2.i lt_cv_truncate_bin= if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" fi rm -f conftest.i conftest2.i conftest.out test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q" ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_truncate_bin" >&5 printf "%s\n" "$lt_cv_truncate_bin" >&6; } # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. func_cc_basename () { for cc_temp in $*""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` } # Check whether --enable-libtool-lock was given. if test ${enable_libtool_lock+y} then : enableval=$enable_libtool_lock; fi test no = "$enable_libtool_lock" || enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out what ABI is being produced by ac_compile, and set mode # options accordingly. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `$FILECMD conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE=32 ;; *ELF-64*) HPUX_IA64_MODE=64 ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '#line '$LINENO' "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then if test yes = "$lt_cv_prog_gnu_ld"; then case `$FILECMD conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `$FILECMD conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; mips64*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '#line '$LINENO' "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then emul=elf case `$FILECMD conftest.$ac_objext` in *32-bit*) emul="${emul}32" ;; *64-bit*) emul="${emul}64" ;; esac case `$FILECMD conftest.$ac_objext` in *MSB*) emul="${emul}btsmip" ;; *LSB*) emul="${emul}ltsmip" ;; esac case `$FILECMD conftest.$ac_objext` in *N32*) emul="${emul}n32" ;; esac LD="${LD-ld} -m $emul" fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. Note that the listed cases only cover the # situations where additional linker options are needed (such as when # doing 32-bit compilation for a host where ld defaults to 64-bit, or # vice versa); the common cases where no linker options are needed do # not appear in the list. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `$FILECMD conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) case `$FILECMD conftest.o` in *x86-64*) LD="${LD-ld} -m elf32_x86_64" ;; *) LD="${LD-ld} -m elf_i386" ;; esac ;; powerpc64le-*linux*) LD="${LD-ld} -m elf32lppclinux" ;; powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; powerpcle-*linux*) LD="${LD-ld} -m elf64lppc" ;; powerpc-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS=$CFLAGS CFLAGS="$CFLAGS -belf" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 printf %s "checking whether the C compiler needs -belf... " >&6; } if test ${lt_cv_cc_needs_belf+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : lt_cv_cc_needs_belf=yes else case e in #( e) lt_cv_cc_needs_belf=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 printf "%s\n" "$lt_cv_cc_needs_belf" >&6; } if test yes != "$lt_cv_cc_needs_belf"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS=$SAVE_CFLAGS fi ;; *-*solaris*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `$FILECMD conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*|x86_64-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD=${LD-ld}_sol2 fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks=$enable_libtool_lock if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. set dummy ${ac_tool_prefix}mt; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_MANIFEST_TOOL+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$MANIFEST_TOOL"; then ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL if test -n "$MANIFEST_TOOL"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 printf "%s\n" "$MANIFEST_TOOL" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_MANIFEST_TOOL"; then ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL # Extract the first word of "mt", so it can be a program name with args. set dummy mt; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_MANIFEST_TOOL+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$ac_ct_MANIFEST_TOOL"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL if test -n "$ac_ct_MANIFEST_TOOL"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 printf "%s\n" "$ac_ct_MANIFEST_TOOL" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_MANIFEST_TOOL" = x; then MANIFEST_TOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL fi else MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" fi test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 printf %s "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } if test ${lt_cv_path_mainfest_tool+y} then : printf %s "(cached) " >&6 else case e in #( e) lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&5 if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest* ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 printf "%s\n" "$lt_cv_path_mainfest_tool" >&6; } if test yes != "$lt_cv_path_mainfest_tool"; then MANIFEST_TOOL=: fi case $host_os in rhapsody* | darwin*) if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_DSYMUTIL+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$DSYMUTIL"; then ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi DSYMUTIL=$ac_cv_prog_DSYMUTIL if test -n "$DSYMUTIL"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 printf "%s\n" "$DSYMUTIL" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_DSYMUTIL"; then ac_ct_DSYMUTIL=$DSYMUTIL # Extract the first word of "dsymutil", so it can be a program name with args. set dummy dsymutil; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_DSYMUTIL+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$ac_ct_DSYMUTIL"; then ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL if test -n "$ac_ct_DSYMUTIL"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 printf "%s\n" "$ac_ct_DSYMUTIL" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_DSYMUTIL" = x; then DSYMUTIL=":" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DSYMUTIL=$ac_ct_DSYMUTIL fi else DSYMUTIL="$ac_cv_prog_DSYMUTIL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. set dummy ${ac_tool_prefix}nmedit; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_NMEDIT+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$NMEDIT"; then ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi NMEDIT=$ac_cv_prog_NMEDIT if test -n "$NMEDIT"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 printf "%s\n" "$NMEDIT" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_NMEDIT"; then ac_ct_NMEDIT=$NMEDIT # Extract the first word of "nmedit", so it can be a program name with args. set dummy nmedit; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_NMEDIT+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$ac_ct_NMEDIT"; then ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_NMEDIT="nmedit" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT if test -n "$ac_ct_NMEDIT"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 printf "%s\n" "$ac_ct_NMEDIT" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_NMEDIT" = x; then NMEDIT=":" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac NMEDIT=$ac_ct_NMEDIT fi else NMEDIT="$ac_cv_prog_NMEDIT" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. set dummy ${ac_tool_prefix}lipo; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_LIPO+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$LIPO"; then ac_cv_prog_LIPO="$LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_LIPO="${ac_tool_prefix}lipo" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi LIPO=$ac_cv_prog_LIPO if test -n "$LIPO"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 printf "%s\n" "$LIPO" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_LIPO"; then ac_ct_LIPO=$LIPO # Extract the first word of "lipo", so it can be a program name with args. set dummy lipo; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_LIPO+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$ac_ct_LIPO"; then ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_LIPO="lipo" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO if test -n "$ac_ct_LIPO"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 printf "%s\n" "$ac_ct_LIPO" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_LIPO" = x; then LIPO=":" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac LIPO=$ac_ct_LIPO fi else LIPO="$ac_cv_prog_LIPO" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. set dummy ${ac_tool_prefix}otool; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_OTOOL+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$OTOOL"; then ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL="${ac_tool_prefix}otool" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi OTOOL=$ac_cv_prog_OTOOL if test -n "$OTOOL"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 printf "%s\n" "$OTOOL" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL"; then ac_ct_OTOOL=$OTOOL # Extract the first word of "otool", so it can be a program name with args. set dummy otool; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_OTOOL+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$ac_ct_OTOOL"; then ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL="otool" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL if test -n "$ac_ct_OTOOL"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 printf "%s\n" "$ac_ct_OTOOL" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_OTOOL" = x; then OTOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL=$ac_ct_OTOOL fi else OTOOL="$ac_cv_prog_OTOOL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. set dummy ${ac_tool_prefix}otool64; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_OTOOL64+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$OTOOL64"; then ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi OTOOL64=$ac_cv_prog_OTOOL64 if test -n "$OTOOL64"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 printf "%s\n" "$OTOOL64" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL64"; then ac_ct_OTOOL64=$OTOOL64 # Extract the first word of "otool64", so it can be a program name with args. set dummy otool64; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_OTOOL64+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$ac_ct_OTOOL64"; then ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL64="otool64" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 if test -n "$ac_ct_OTOOL64"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 printf "%s\n" "$ac_ct_OTOOL64" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_OTOOL64" = x; then OTOOL64=":" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL64=$ac_ct_OTOOL64 fi else OTOOL64="$ac_cv_prog_OTOOL64" fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 printf %s "checking for -single_module linker flag... " >&6; } if test ${lt_cv_apple_cc_single_mod+y} then : printf %s "(cached) " >&6 else case e in #( e) lt_cv_apple_cc_single_mod=no if test -z "$LT_MULTI_MODULE"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&5 $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&5 # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test 0 = "$_lt_result"; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&5 fi rm -rf libconftest.dylib* rm -f conftest.* fi ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 printf "%s\n" "$lt_cv_apple_cc_single_mod" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 printf %s "checking for -exported_symbols_list linker flag... " >&6; } if test ${lt_cv_ld_exported_symbols_list+y} then : printf %s "(cached) " >&6 else case e in #( e) lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : lt_cv_ld_exported_symbols_list=yes else case e in #( e) lt_cv_ld_exported_symbols_list=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 printf "%s\n" "$lt_cv_ld_exported_symbols_list" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 printf %s "checking for -force_load linker flag... " >&6; } if test ${lt_cv_ld_force_load+y} then : printf %s "(cached) " >&6 else case e in #( e) lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 echo "$AR $AR_FLAGS libconftest.a conftest.o" >&5 $AR $AR_FLAGS libconftest.a conftest.o 2>&5 echo "$RANLIB libconftest.a" >&5 $RANLIB libconftest.a 2>&5 cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&5 elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then lt_cv_ld_force_load=yes else cat conftest.err >&5 fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 printf "%s\n" "$lt_cv_ld_force_load" >&6; } case $host_os in rhapsody* | darwin1.[012]) _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; darwin*) case $MACOSX_DEPLOYMENT_TARGET,$host in 10.[012],*|,*powerpc*-darwin[5-8]*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; *) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test yes = "$lt_cv_apple_cc_single_mod"; then _lt_dar_single_mod='$single_module' fi if test yes = "$lt_cv_ld_exported_symbols_list"; then _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' fi if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac # func_munge_path_list VARIABLE PATH # ----------------------------------- # VARIABLE is name of variable containing _space_ separated list of # directories to be munged by the contents of PATH, which is string # having a format: # "DIR[:DIR]:" # string "DIR[ DIR]" will be prepended to VARIABLE # ":DIR[:DIR]" # string "DIR[ DIR]" will be appended to VARIABLE # "DIRP[:DIRP]::[DIRA:]DIRA" # string "DIRP[ DIRP]" will be prepended to VARIABLE and string # "DIRA[ DIRA]" will be appended to VARIABLE # "DIR[:DIR]" # VARIABLE will be replaced by "DIR[ DIR]" func_munge_path_list () { case x$2 in x) ;; *:) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" ;; x:*) eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" ;; *::*) eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" ;; *) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" ;; esac } ac_header= ac_cache= for ac_item in $ac_header_c_list do if test $ac_cache; then ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default" if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then printf "%s\n" "#define $ac_item 1" >> confdefs.h fi ac_header= ac_cache= elif test $ac_header; then ac_cache=$ac_item else ac_header=$ac_item fi done if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes then : printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default " if test "x$ac_cv_header_dlfcn_h" = xyes then : printf "%s\n" "#define HAVE_DLFCN_H 1" >>confdefs.h fi # Set options # Check whether --enable-static was given. if test ${enable_static+y} then : enableval=$enable_static; p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS=$lt_save_ifs ;; esac else case e in #( e) enable_static=no ;; esac fi enable_dlopen=no enable_win32_dll=no # Check whether --enable-shared was given. if test ${enable_shared+y} then : enableval=$enable_shared; p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS=$lt_save_ifs ;; esac else case e in #( e) enable_shared=yes ;; esac fi # Check whether --with-pic was given. if test ${with_pic+y} then : withval=$with_pic; lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for lt_pkg in $withval; do IFS=$lt_save_ifs if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS=$lt_save_ifs ;; esac else case e in #( e) pic_mode=default ;; esac fi # Check whether --enable-fast-install was given. if test ${enable_fast_install+y} then : enableval=$enable_fast_install; p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS=$lt_save_ifs ;; esac else case e in #( e) enable_fast_install=yes ;; esac fi shared_archive_member_spec= case $host,$enable_shared in power*-*-aix[5-9]*,yes) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5 printf %s "checking which variant of shared library versioning to provide... " >&6; } # Check whether --with-aix-soname was given. if test ${with_aix_soname+y} then : withval=$with_aix_soname; case $withval in aix|svr4|both) ;; *) as_fn_error $? "Unknown argument to --with-aix-soname" "$LINENO" 5 ;; esac lt_cv_with_aix_soname=$with_aix_soname else case e in #( e) if test ${lt_cv_with_aix_soname+y} then : printf %s "(cached) " >&6 else case e in #( e) lt_cv_with_aix_soname=aix ;; esac fi with_aix_soname=$lt_cv_with_aix_soname ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $with_aix_soname" >&5 printf "%s\n" "$with_aix_soname" >&6; } if test aix != "$with_aix_soname"; then # For the AIX way of multilib, we name the shared archive member # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, # the AIX toolchain works better with OBJECT_MODE set (default 32). if test 64 = "${OBJECT_MODE-32}"; then shared_archive_member_spec=shr_64 else shared_archive_member_spec=shr fi fi ;; *) with_aix_soname=aix ;; esac # This can be used to rebuild libtool when needed LIBTOOL_DEPS=$ltmain # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' test -z "$LN_S" && LN_S="ln -s" if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 printf %s "checking for objdir... " >&6; } if test ${lt_cv_objdir+y} then : printf %s "(cached) " >&6 else case e in #( e) rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 printf "%s\n" "$lt_cv_objdir" >&6; } objdir=$lt_cv_objdir printf "%s\n" "#define LT_OBJDIR \"$lt_cv_objdir/\"" >>confdefs.h case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a '.a' archive for static linking (except MSVC and # ICC, which need '.lib'). libext=a with_gnu_ld=$lt_cv_prog_gnu_ld old_CC=$CC old_CFLAGS=$CFLAGS # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o func_cc_basename $compiler cc_basename=$func_cc_basename_result # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 printf %s "checking for ${ac_tool_prefix}file... " >&6; } if test ${lt_cv_path_MAGIC_CMD+y} then : printf %s "(cached) " >&6 else case e in #( e) case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD=$MAGIC_CMD lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/${ac_tool_prefix}file"; then lt_cv_path_MAGIC_CMD=$ac_dir/"${ac_tool_prefix}file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS=$lt_save_ifs MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac ;; esac fi MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 printf "%s\n" "$MAGIC_CMD" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for file" >&5 printf %s "checking for file... " >&6; } if test ${lt_cv_path_MAGIC_CMD+y} then : printf %s "(cached) " >&6 else case e in #( e) case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD=$MAGIC_CMD lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/file"; then lt_cv_path_MAGIC_CMD=$ac_dir/"file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS=$lt_save_ifs MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac ;; esac fi MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 printf "%s\n" "$MAGIC_CMD" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi else MAGIC_CMD=: fi fi fi ;; esac # Use C for the default configuration in the libtool script lt_save_CC=$CC ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o objext=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then lt_prog_compiler_no_builtin_flag= if test yes = "$GCC"; then case $cc_basename in nvcc*) lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; *) lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 printf %s "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } if test ${lt_cv_prog_compiler_rtti_exceptions+y} then : printf %s "(cached) " >&6 else case e in #( e) lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-fno-rtti -fno-exceptions" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_rtti_exceptions=yes fi fi $RM conftest* ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 printf "%s\n" "$lt_cv_prog_compiler_rtti_exceptions" >&6; } if test yes = "$lt_cv_prog_compiler_rtti_exceptions"; then lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" else : fi fi lt_prog_compiler_wl= lt_prog_compiler_pic= lt_prog_compiler_static= if test yes = "$GCC"; then lt_prog_compiler_wl='-Wl,' lt_prog_compiler_static='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' fi lt_prog_compiler_pic='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support lt_prog_compiler_pic='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic='-DDLL_EXPORT' case $host_os in os2*) lt_prog_compiler_static='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. lt_prog_compiler_static= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) lt_prog_compiler_pic='-fPIC' ;; esac ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic=-Kconform_pic fi ;; *) lt_prog_compiler_pic='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 lt_prog_compiler_wl='-Xlinker ' if test -n "$lt_prog_compiler_pic"; then lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl='-Wl,' if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' else lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' fi ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' case $cc_basename in nagfor*) # NAG Fortran compiler lt_prog_compiler_wl='-Wl,-Wl,,' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; esac ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' case $host_os in os2*) lt_prog_compiler_static='$wl-static' ;; esac ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static='$wl-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in # old Intel for x86_64, which still supported -KPIC. ecc*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; # Lahey Fortran 8.1. lf95*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='--shared' lt_prog_compiler_static='--static' ;; nagfor*) # NAG Fortran compiler lt_prog_compiler_wl='-Wl,-Wl,,' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; tcc*) # Fabrice Bellard et al's Tiny C Compiler lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; ccc*) lt_prog_compiler_wl='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-qpic' lt_prog_compiler_static='-qstaticlink' ;; *) case `$CC -V 2>&1 | $SED 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='' ;; *Sun\ F* | *Sun*Fortran*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Wl,' ;; *Intel*\ [CF]*Compiler*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; *Portland\ Group*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; esac ;; esac ;; newsos6) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static='-non_shared' ;; rdos*) lt_prog_compiler_static='-non_shared' ;; solaris*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) lt_prog_compiler_wl='-Qoption ld ';; *) lt_prog_compiler_wl='-Wl,';; esac ;; sunos4*) lt_prog_compiler_wl='-Qoption ld ' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic='-Kconform_pic' lt_prog_compiler_static='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; unicos*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_can_build_shared=no ;; uts4*) lt_prog_compiler_pic='-pic' lt_prog_compiler_static='-Bstatic' ;; *) lt_prog_compiler_can_build_shared=no ;; esac fi case $host_os in # For platforms that do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic= ;; *) lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 printf %s "checking for $compiler option to produce PIC... " >&6; } if test ${lt_cv_prog_compiler_pic+y} then : printf %s "(cached) " >&6 else case e in #( e) lt_cv_prog_compiler_pic=$lt_prog_compiler_pic ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 printf "%s\n" "$lt_cv_prog_compiler_pic" >&6; } lt_prog_compiler_pic=$lt_cv_prog_compiler_pic # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 printf %s "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } if test ${lt_cv_prog_compiler_pic_works+y} then : printf %s "(cached) " >&6 else case e in #( e) lt_cv_prog_compiler_pic_works=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic -DPIC" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works=yes fi fi $RM conftest* ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 printf "%s\n" "$lt_cv_prog_compiler_pic_works" >&6; } if test yes = "$lt_cv_prog_compiler_pic_works"; then case $lt_prog_compiler_pic in "" | " "*) ;; *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; esac else lt_prog_compiler_pic= lt_prog_compiler_can_build_shared=no fi fi # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 printf %s "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if test ${lt_cv_prog_compiler_static_works+y} then : printf %s "(cached) " >&6 else case e in #( e) lt_cv_prog_compiler_static_works=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works=yes fi else lt_cv_prog_compiler_static_works=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 printf "%s\n" "$lt_cv_prog_compiler_static_works" >&6; } if test yes = "$lt_cv_prog_compiler_static_works"; then : else lt_prog_compiler_static= fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 printf %s "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if test ${lt_cv_prog_compiler_c_o+y} then : printf %s "(cached) " >&6 else case e in #( e) lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 printf "%s\n" "$lt_cv_prog_compiler_c_o" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 printf %s "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if test ${lt_cv_prog_compiler_c_o+y} then : printf %s "(cached) " >&6 else case e in #( e) lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 printf "%s\n" "$lt_cv_prog_compiler_c_o" >&6; } hard_links=nottested if test no = "$lt_cv_prog_compiler_c_o" && test no != "$need_locks"; then # do not overwrite the value of need_locks provided by the user { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 printf %s "checking if we can lock with hard links... " >&6; } hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 printf "%s\n" "$hard_links" >&6; } if test no = "$hard_links"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 printf "%s\n" "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 printf %s "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } runpath_var= allow_undefined_flag= always_export_symbols=no archive_cmds= archive_expsym_cmds= compiler_needs_object=no enable_shared_with_static_runtimes=no export_dynamic_flag_spec= export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' hardcode_automatic=no hardcode_direct=no hardcode_direct_absolute=no hardcode_libdir_flag_spec= hardcode_libdir_separator= hardcode_minus_L=no hardcode_shlibpath_var=unsupported inherit_rpath=no link_all_deplibs=unknown module_cmds= module_expsym_cmds= old_archive_from_new_cmds= old_archive_from_expsyms_cmds= thread_safe_flag_spec= whole_archive_flag_spec= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ' (' and ')$', so one must not match beginning or # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', # as well as any symbol that contains 'd'. exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ and ICC port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++ or Intel C++ Compiler. if test yes != "$GCC"; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++ or ICC) with_gnu_ld=yes ;; openbsd* | bitrig*) with_gnu_ld=no ;; esac ld_shlibs=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test yes = "$with_gnu_ld"; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; *\ \(GNU\ Binutils\)\ [3-9]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test yes = "$lt_use_gnu_ld_interface"; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='$wl' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' export_dynamic_flag_spec='$wl--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then whole_archive_flag_spec=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else whole_archive_flag_spec= fi supports_anon_versioning=no case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken if test ia64 != "$host_cpu"; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then allow_undefined_flag=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else ld_shlibs=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' export_dynamic_flag_spec='$wl--export-all-symbols' allow_undefined_flag=unsupported always_export_symbols=no enable_shared_with_static_runtimes=yes export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs=no fi ;; haiku*) archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' link_all_deplibs=yes ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported shrext_cmds=.dll archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' enable_shared_with_static_runtimes=yes file_list_spec='@' ;; interix[3-9]*) hardcode_direct=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='$wl-rpath,$libdir' export_dynamic_flag_spec='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test linux-dietlibc = "$host_os"; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test no = "$tmp_diet" then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 whole_archive_flag_spec= tmp_sharedflag='--shared' ;; nagfor*) # NAGFOR 5.3 tmp_sharedflag='-Wl,-shared' ;; xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' compiler_needs_object=yes ;; esac case `$CC -V 2>&1 | $SED 5q` in *Sun\ C*) # Sun C 5.9 whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' compiler_needs_object=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi case $cc_basename in tcc*) export_dynamic_flag_spec='-rdynamic' ;; xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test yes = "$supports_anon_versioning"; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else ld_shlibs=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac ;; sunos4*) archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct=yes hardcode_shlibpath_var=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac if test no = "$ld_shlibs"; then runpath_var= hardcode_libdir_flag_spec= export_dynamic_flag_spec= whole_archive_flag_spec= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag=unsupported always_export_symbols=yes archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix[4-9]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then aix_use_runtimelinking=yes break fi done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds='' hardcode_direct=yes hardcode_direct_absolute=yes hardcode_libdir_separator=':' link_all_deplibs=yes file_list_spec='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # traditional, no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. hardcode_direct=no hardcode_direct_absolute=no ;; esac if test yes = "$GCC"; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi ;; esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag="$shared_flag "'$wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi export_dynamic_flag_spec='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag='-berok' # Determine the default libpath from the value encoded in an # empty executable. if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if test ${lt_cv_aix_libpath_+y} then : printf %s "(cached) " >&6 else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=/usr/lib:/lib fi ;; esac fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then hardcode_libdir_flag_spec='$wl-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if test ${lt_cv_aix_libpath_+y} then : printf %s "(cached) " >&6 else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=/usr/lib:/lib fi ;; esac fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag=' $wl-bernotok' allow_undefined_flag=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. whole_archive_flag_spec='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec='$convenience' fi archive_cmds_need_lc=yes archive_expsym_cmds='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols archive_expsym_cmds="$archive_expsym_cmds"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi archive_expsym_cmds="$archive_expsym_cmds"'~$RM -r $output_objdir/$realname.d' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; bsdi[45]*) export_dynamic_flag_spec=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++ or Intel C++ Compiler. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl* | icl*) # Native MSVC or ICC hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported always_export_symbols=yes file_list_spec='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, )='true' enable_shared_with_static_runtimes=yes exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib old_postinstall_cmds='chmod 644 $oldlib' postlink_cmds='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC and ICC wrapper hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_from_new_cmds='true' # FIXME: Should let the user specify the lib program. old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' enable_shared_with_static_runtimes=yes ;; esac ;; darwin* | rhapsody*) archive_cmds_need_lc=no hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported if test yes = "$lt_cv_ld_force_load"; then whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' else whole_archive_flag_spec='' fi link_all_deplibs=yes allow_undefined_flag=$_lt_dar_allow_undefined case $cc_basename in ifort*|nagfor*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test yes = "$_lt_dar_can_shared"; then output_verbose_link_cmd=func_echo_all archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" archive_expsym_cmds="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" module_expsym_cmds="$SED -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" else ld_shlibs=no fi ;; dgux*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly* | midnightbsd*) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; hpux9*) if test yes = "$GCC"; then archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes export_dynamic_flag_spec='$wl-E' ;; hpux10*) if test yes,no = "$GCC,$with_gnu_ld"; then archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test no = "$with_gnu_ld"; then hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes fi ;; hpux11*) if test yes,no = "$GCC,$with_gnu_ld"; then case $host_cpu in hppa*64*) archive_cmds='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) archive_cmds='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 printf %s "checking if $CC understands -b... " >&6; } if test ${lt_cv_prog_compiler__b+y} then : printf %s "(cached) " >&6 else case e in #( e) lt_cv_prog_compiler__b=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -b" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler__b=yes fi else lt_cv_prog_compiler__b=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 printf "%s\n" "$lt_cv_prog_compiler__b" >&6; } if test yes = "$lt_cv_prog_compiler__b"; then archive_cmds='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi ;; esac fi if test no = "$with_gnu_ld"; then hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: case $host_cpu in hppa*64*|ia64*) hardcode_direct=no hardcode_shlibpath_var=no ;; *) hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test yes = "$GCC"; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 printf %s "checking whether the $host_os linker accepts -exported_symbol... " >&6; } if test ${lt_cv_irix_exported_symbol+y} then : printf %s "(cached) " >&6 else case e in #( e) save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int foo (void) { return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : lt_cv_irix_exported_symbol=yes else case e in #( e) lt_cv_irix_exported_symbol=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 printf "%s\n" "$lt_cv_irix_exported_symbol" >&6; } if test yes = "$lt_cv_irix_exported_symbol"; then archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' fi else archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: inherit_rpath=yes link_all_deplibs=yes ;; linux*) case $cc_basename in tcc*) # Fabrice Bellard et al's Tiny C Compiler ld_shlibs=yes archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; *nto* | *qnx*) ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then hardcode_direct=yes hardcode_shlibpath_var=no hardcode_direct_absolute=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' hardcode_libdir_flag_spec='$wl-rpath,$libdir' export_dynamic_flag_spec='$wl-E' else archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='$wl-rpath,$libdir' fi else ld_shlibs=no fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported shrext_cmds=.dll archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' enable_shared_with_static_runtimes=yes file_list_spec='@' ;; osf3*) if test yes = "$GCC"; then allow_undefined_flag=' $wl-expect_unresolved $wl\*' archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test yes = "$GCC"; then allow_undefined_flag=' $wl-expect_unresolved $wl\*' archive_cmds='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi archive_cmds_need_lc='no' hardcode_libdir_separator=: ;; solaris*) no_undefined_flag=' -z defs' if test yes = "$GCC"; then wlarc='$wl' archive_cmds='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' archive_cmds='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='$wl' archive_cmds='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi hardcode_libdir_flag_spec='-R$libdir' hardcode_shlibpath_var=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. GCC discards it without '$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test yes = "$GCC"; then whole_archive_flag_spec='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' else whole_archive_flag_spec='-z allextract$convenience -z defaultextract' fi ;; esac link_all_deplibs=yes ;; sunos4*) if test sequent = "$host_vendor"; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; sysv4) case $host_vendor in sni) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds='$CC -r -o $output$reload_objs' hardcode_direct=no ;; motorola) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; sysv4.3*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no export_dynamic_flag_spec='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag='$wl-z,text' archive_cmds_need_lc=no hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag='$wl-z,text' allow_undefined_flag='$wl-z,nodefs' archive_cmds_need_lc=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='$wl-R,$libdir' hardcode_libdir_separator=':' link_all_deplibs=yes export_dynamic_flag_spec='$wl-Bexport' runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; *) ld_shlibs=no ;; esac if test sni = "$host_vendor"; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) export_dynamic_flag_spec='$wl-Blargedynsym' ;; esac fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 printf "%s\n" "$ld_shlibs" >&6; } test no = "$ld_shlibs" && can_build_shared=no with_gnu_ld=$with_gnu_ld # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc" in x|xyes) # Assume -lc should be added archive_cmds_need_lc=yes if test yes,yes = "$GCC,$enable_shared"; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 printf %s "checking whether -lc should be explicitly linked in... " >&6; } if test ${lt_cv_archive_cmds_need_lc+y} then : printf %s "(cached) " >&6 else case e in #( e) $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl pic_flag=$lt_prog_compiler_pic compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag allow_undefined_flag= if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then lt_cv_archive_cmds_need_lc=no else lt_cv_archive_cmds_need_lc=yes fi allow_undefined_flag=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 printf "%s\n" "$lt_cv_archive_cmds_need_lc" >&6; } archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc ;; esac fi ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 printf %s "checking dynamic linker characteristics... " >&6; } if test yes = "$GCC"; then case $host_os in darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; *) lt_awk_arg='/^libraries:/' ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq='s|=\([A-Za-z]:\)|\1|g' ;; *) lt_sed_strip_eq='s|=/|/|g' ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary... lt_tmp_lt_search_path_spec= lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` # ...but if some path component already ends with the multilib dir we assume # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). case "$lt_multi_os_dir; $lt_search_path_spec " in "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) lt_multi_os_dir= ;; esac for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" elif test -n "$lt_multi_os_dir"; then test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS = " "; FS = "/|\n";} { lt_foo = ""; lt_count = 0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo = "/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[lt_foo]++; } if (lt_freq[lt_foo] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's|/\([A-Za-z]:\)|\1|g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=.so postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='$libname$release$shared_ext$major' ;; aix[4-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test ia64 = "$host_cpu"; then # AIX 5 supports IA64 library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line '#! .'. This would cause the generated library to # depend on '.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # Using Import Files as archive members, it is possible to support # filename-based versioning of shared library archives on AIX. While # this would work for both with and without runtime linking, it will # prevent static linking of such archives. So we do filename-based # shared library versioning with .so extension only, which is used # when both runtime linking and shared linking is enabled. # Unfortunately, runtime linking may impact performance, so we do # not want this to be the default eventually. Also, we use the # versioned .so libs for executables only if there is the -brtl # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. # To allow for filename-based versioning support, we need to create # libNAME.so.V as an archive file, containing: # *) an Import File, referring to the versioned filename of the # archive as well as the shared archive member, telling the # bitwidth (32 or 64) of that shared object, and providing the # list of exported symbols of that shared object, eventually # decorated with the 'weak' keyword # *) the shared object with the F_LOADONLY flag set, to really avoid # it being seen by the linker. # At run time we better use the real file rather than another symlink, # but for link time we create the symlink libNAME.so -> libNAME.so.V case $with_aix_soname,$aix_use_runtimelinking in # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. aix,yes) # traditional libtool dynamic_linker='AIX unversionable lib.so' # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; aix,no) # traditional AIX only dynamic_linker='AIX lib.a(lib.so.V)' # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' ;; svr4,*) # full svr4 only dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,yes) # both, prefer svr4 dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # unpreferred sharedlib libNAME.a needs extra handling postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,no) # both, prefer aix dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' ;; esac shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='$libname$shared_ext' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo $libname | $SED -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo $libname | $SED -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl* | *,icl*) # Native MSVC or ICC libname_spec='$name' soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' library_names_spec='$libname.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec=$LIB if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC and ICC wrapper library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' soname_spec='$libname$release$major$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly* | midnightbsd*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[23].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=no sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' if test 32 = "$HPUX_IA64_MODE"; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[3-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test yes = "$lt_cv_prog_gnu_ld"; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; linux*android*) version_type=none # Android doesn't support versioned libraries. need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext' soname_spec='$libname$release$shared_ext' finish_cmds= shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes dynamic_linker='Android linker' # Don't embed -rpath directories since the linker doesn't support them. hardcode_libdir_flag_spec='-L$libdir' ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH if test ${lt_cv_shlibpath_overrides_runpath+y} then : printf %s "(cached) " >&6 else case e in #( e) lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null then : lt_cv_shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS libdir=$save_libdir ;; esac fi shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Ideally, we could use ldconfig to report *all* directores which are # searched for libraries, however this is still not possible. Aside from not # being certain /sbin/ldconfig is available, command # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, # even though it is searched at run-time. Try to do the best guess by # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd* | bitrig*) version_type=sunos sys_lib_dlsearch_path_spec=/usr/lib need_lib_prefix=no if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then need_version=no else need_version=yes fi library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; os2*) libname_spec='$name' version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no # OS/2 can only load a DLL with a base name of 8 characters or less. soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; v=$($ECHO $release$versuffix | tr -d .-); n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); $ECHO $n$v`$shared_ext' library_names_spec='${libname}_dll.$libext' dynamic_linker='OS/2 ld.exe' shlibpath_var=BEGINLIBPATH sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test yes = "$with_gnu_ld"; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec; then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' soname_spec='$libname$shared_ext.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=sco need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test yes = "$with_gnu_ld"; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 printf "%s\n" "$dynamic_linker" >&6; } test no = "$dynamic_linker" && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test yes = "$GCC"; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec fi if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec fi # remember unaugmented sys_lib_dlsearch_path content for libtool script decls... configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec # ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" # to be used as default LT_SYS_LIBRARY_PATH value in generated libtool configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 printf %s "checking how to hardcode library paths into programs... " >&6; } hardcode_action= if test -n "$hardcode_libdir_flag_spec" || test -n "$runpath_var" || test yes = "$hardcode_automatic"; then # We can hardcode non-existent directories. if test no != "$hardcode_direct" && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, )" && test no != "$hardcode_minus_L"; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action=unsupported fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 printf "%s\n" "$hardcode_action" >&6; } if test relink = "$hardcode_action" || test yes = "$inherit_rpath"; then # Fast installation is not supported enable_fast_install=no elif test yes = "$shlibpath_overrides_runpath" || test no = "$enable_shared"; then # Fast installation is not necessary enable_fast_install=needless fi if test yes != "$enable_dlopen"; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen=load_add_on lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen=LoadLibrary lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen=dlopen lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 printf %s "checking for dlopen in -ldl... " >&6; } if test ${ac_cv_lib_dl_dlopen+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. The 'extern "C"' is for builds by C++ compilers; although this is not generally supported in C code supporting it here has little cost and some practical benefit (sr 110532). */ #ifdef __cplusplus extern "C" #endif char dlopen (void); int main (void) { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_dl_dlopen=yes else case e in #( e) ac_cv_lib_dl_dlopen=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 printf "%s\n" "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes then : lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl else case e in #( e) lt_cv_dlopen=dyld lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; esac fi ;; tpf*) # Don't try to run any link tests for TPF. We know it's impossible # because TPF is a cross-compiler, and we know how we open DSOs. lt_cv_dlopen=dlopen lt_cv_dlopen_libs= lt_cv_dlopen_self=no ;; *) ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" if test "x$ac_cv_func_shl_load" = xyes then : lt_cv_dlopen=shl_load else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 printf %s "checking for shl_load in -ldld... " >&6; } if test ${ac_cv_lib_dld_shl_load+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. The 'extern "C"' is for builds by C++ compilers; although this is not generally supported in C code supporting it here has little cost and some practical benefit (sr 110532). */ #ifdef __cplusplus extern "C" #endif char shl_load (void); int main (void) { return shl_load (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_dld_shl_load=yes else case e in #( e) ac_cv_lib_dld_shl_load=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 printf "%s\n" "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes then : lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld else case e in #( e) ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" if test "x$ac_cv_func_dlopen" = xyes then : lt_cv_dlopen=dlopen else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 printf %s "checking for dlopen in -ldl... " >&6; } if test ${ac_cv_lib_dl_dlopen+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. The 'extern "C"' is for builds by C++ compilers; although this is not generally supported in C code supporting it here has little cost and some practical benefit (sr 110532). */ #ifdef __cplusplus extern "C" #endif char dlopen (void); int main (void) { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_dl_dlopen=yes else case e in #( e) ac_cv_lib_dl_dlopen=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 printf "%s\n" "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes then : lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 printf %s "checking for dlopen in -lsvld... " >&6; } if test ${ac_cv_lib_svld_dlopen+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_check_lib_save_LIBS=$LIBS LIBS="-lsvld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. The 'extern "C"' is for builds by C++ compilers; although this is not generally supported in C code supporting it here has little cost and some practical benefit (sr 110532). */ #ifdef __cplusplus extern "C" #endif char dlopen (void); int main (void) { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_svld_dlopen=yes else case e in #( e) ac_cv_lib_svld_dlopen=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 printf "%s\n" "$ac_cv_lib_svld_dlopen" >&6; } if test "x$ac_cv_lib_svld_dlopen" = xyes then : lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 printf %s "checking for dld_link in -ldld... " >&6; } if test ${ac_cv_lib_dld_dld_link+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. The 'extern "C"' is for builds by C++ compilers; although this is not generally supported in C code supporting it here has little cost and some practical benefit (sr 110532). */ #ifdef __cplusplus extern "C" #endif char dld_link (void); int main (void) { return dld_link (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_dld_dld_link=yes else case e in #( e) ac_cv_lib_dld_dld_link=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 printf "%s\n" "$ac_cv_lib_dld_dld_link" >&6; } if test "x$ac_cv_lib_dld_dld_link" = xyes then : lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld fi ;; esac fi ;; esac fi ;; esac fi ;; esac fi ;; esac fi ;; esac if test no = "$lt_cv_dlopen"; then enable_dlopen=no else enable_dlopen=yes fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS=$CPPFLAGS test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS=$LDFLAGS wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS=$LIBS LIBS="$lt_cv_dlopen_libs $LIBS" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 printf %s "checking whether a program can dlopen itself... " >&6; } if test ${lt_cv_dlopen_self+y} then : printf %s "(cached) " >&6 else case e in #( e) if test yes = "$cross_compiling"; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; esac else : # compilation failed lt_cv_dlopen_self=no fi fi rm -fr conftest* ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 printf "%s\n" "$lt_cv_dlopen_self" >&6; } if test yes = "$lt_cv_dlopen_self"; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 printf %s "checking whether a statically linked program can dlopen itself... " >&6; } if test ${lt_cv_dlopen_self_static+y} then : printf %s "(cached) " >&6 else case e in #( e) if test yes = "$cross_compiling"; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; esac else : # compilation failed lt_cv_dlopen_self_static=no fi fi rm -fr conftest* ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 printf "%s\n" "$lt_cv_dlopen_self_static" >&6; } fi CPPFLAGS=$save_CPPFLAGS LDFLAGS=$save_LDFLAGS LIBS=$save_LIBS ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi striplib= old_striplib= { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 printf %s "checking whether stripping libraries is possible... " >&6; } if test -z "$STRIP"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } else if $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then old_striplib="$STRIP --strip-debug" striplib="$STRIP --strip-unneeded" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else case $host_os in darwin*) # FIXME - insert some real tests, host_os isn't really good enough striplib="$STRIP -x" old_striplib="$STRIP -S" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } ;; freebsd*) if $STRIP -V 2>&1 | $GREP "elftoolchain" >/dev/null; then old_striplib="$STRIP --strip-debug" striplib="$STRIP --strip-unneeded" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi ;; *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } ;; esac fi fi # Report what library types will actually be built { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 printf %s "checking if libtool supports shared libraries... " >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 printf "%s\n" "$can_build_shared" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 printf %s "checking whether to build shared libraries... " >&6; } test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[4-9]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 printf "%s\n" "$enable_shared" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 printf %s "checking whether to build static libraries... " >&6; } # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 printf "%s\n" "$enable_static" >&6; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC=$lt_save_CC ac_config_commands="$ac_config_commands libtool" # Only expand once: # When releasing the first 1.x.y version, we need to start with 1.1.0 (or higher) as we've already # used 0.16.x. printf "%s\n" "#define PEER_NAME \"-lt100B-\"" >>confdefs.h printf "%s\n" "#define PEER_VERSION \"lt\\x10\\x0B\"" >>confdefs.h LIBTORRENT_CURRENT=41 LIBTORRENT_REVISION=0 LIBTORRENT_AGE=0 LIBTORRENT_INTERFACE_VERSION_INFO=$LIBTORRENT_CURRENT:$LIBTORRENT_REVISION:$LIBTORRENT_AGE LIBTORRENT_INTERFACE_VERSION_NO=$LIBTORRENT_CURRENT.$LIBTORRENT_AGE.$LIBTORRENT_REVISION ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test -z "$CXX"; then if test -n "$CCC"; then CXX=$CCC else if test -n "$ac_tool_prefix"; then for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC clang++ do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CXX+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi CXX=$ac_cv_prog_CXX if test -n "$CXX"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 printf "%s\n" "$CXX" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$CXX" && break done fi if test -z "$CXX"; then ac_ct_CXX=$CXX for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC clang++ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CXX+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$ac_ct_CXX"; then ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CXX="$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi ac_ct_CXX=$ac_cv_prog_ac_ct_CXX if test -n "$ac_ct_CXX"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 printf "%s\n" "$ac_ct_CXX" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$ac_ct_CXX" && break done if test "x$ac_ct_CXX" = x; then CXX="g++" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CXX=$ac_ct_CXX fi fi fi fi # Provide some information about the compiler. printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C++" >&5 printf %s "checking whether the compiler supports GNU C++... " >&6; } if test ${ac_cv_cxx_compiler_gnu+y} then : printf %s "(cached) " >&6 else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : ac_compiler_gnu=yes else case e in #( e) ac_compiler_gnu=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_cv_cxx_compiler_gnu=$ac_compiler_gnu ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 printf "%s\n" "$ac_cv_cxx_compiler_gnu" >&6; } ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test $ac_compiler_gnu = yes; then GXX=yes else GXX= fi ac_test_CXXFLAGS=${CXXFLAGS+y} ac_save_CXXFLAGS=$CXXFLAGS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 printf %s "checking whether $CXX accepts -g... " >&6; } if test ${ac_cv_prog_cxx_g+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_save_cxx_werror_flag=$ac_cxx_werror_flag ac_cxx_werror_flag=yes ac_cv_prog_cxx_g=no CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : ac_cv_prog_cxx_g=yes else case e in #( e) CXXFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : else case e in #( e) ac_cxx_werror_flag=$ac_save_cxx_werror_flag CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : ac_cv_prog_cxx_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_cxx_werror_flag=$ac_save_cxx_werror_flag ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 printf "%s\n" "$ac_cv_prog_cxx_g" >&6; } if test $ac_test_CXXFLAGS; then CXXFLAGS=$ac_save_CXXFLAGS elif test $ac_cv_prog_cxx_g = yes; then if test "$GXX" = yes; then CXXFLAGS="-g -O2" else CXXFLAGS="-g" fi else if test "$GXX" = yes; then CXXFLAGS="-O2" else CXXFLAGS= fi fi ac_prog_cxx_stdcxx=no if test x$ac_prog_cxx_stdcxx = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++11 features" >&5 printf %s "checking for $CXX option to enable C++11 features... " >&6; } if test ${ac_cv_prog_cxx_cxx11+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_cv_prog_cxx_cxx11=no ac_save_CXX=$CXX cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_cxx_conftest_cxx11_program _ACEOF for ac_arg in '' -std=gnu++11 -std=gnu++0x -std=c++11 -std=c++0x -qlanglvl=extended0x -AA do CXX="$ac_save_CXX $ac_arg" if ac_fn_cxx_try_compile "$LINENO" then : ac_cv_prog_cxx_cxx11=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cxx_cxx11" != "xno" && break done rm -f conftest.$ac_ext CXX=$ac_save_CXX ;; esac fi if test "x$ac_cv_prog_cxx_cxx11" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else case e in #( e) if test "x$ac_cv_prog_cxx_cxx11" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_cxx11" >&5 printf "%s\n" "$ac_cv_prog_cxx_cxx11" >&6; } CXX="$CXX $ac_cv_prog_cxx_cxx11" ;; esac fi ac_cv_prog_cxx_stdcxx=$ac_cv_prog_cxx_cxx11 ac_prog_cxx_stdcxx=cxx11 ;; esac fi fi if test x$ac_prog_cxx_stdcxx = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++98 features" >&5 printf %s "checking for $CXX option to enable C++98 features... " >&6; } if test ${ac_cv_prog_cxx_cxx98+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_cv_prog_cxx_cxx98=no ac_save_CXX=$CXX cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_cxx_conftest_cxx98_program _ACEOF for ac_arg in '' -std=gnu++98 -std=c++98 -qlanglvl=extended -AA do CXX="$ac_save_CXX $ac_arg" if ac_fn_cxx_try_compile "$LINENO" then : ac_cv_prog_cxx_cxx98=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cxx_cxx98" != "xno" && break done rm -f conftest.$ac_ext CXX=$ac_save_CXX ;; esac fi if test "x$ac_cv_prog_cxx_cxx98" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else case e in #( e) if test "x$ac_cv_prog_cxx_cxx98" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_cxx98" >&5 printf "%s\n" "$ac_cv_prog_cxx_cxx98" >&6; } CXX="$CXX $ac_cv_prog_cxx_cxx98" ;; esac fi ac_cv_prog_cxx_stdcxx=$ac_cv_prog_cxx_cxx98 ac_prog_cxx_stdcxx=cxx98 ;; esac fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CXX" am_compiler_list= { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 printf %s "checking dependency style of $depcc... " >&6; } if test ${am_cv_CXX_dependencies_compiler_type+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CXX_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thus: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CXX_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CXX_dependencies_compiler_type=none fi ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5 printf "%s\n" "$am_cv_CXX_dependencies_compiler_type" >&6; } CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then am__fastdepCXX_TRUE= am__fastdepCXX_FALSE='#' else am__fastdepCXX_TRUE='#' am__fastdepCXX_FALSE= fi func_stripname_cnf () { case $2 in .*) func_stripname_result=`$ECHO "$3" | $SED "s%^$1%%; s%\\\\$2\$%%"`;; *) func_stripname_result=`$ECHO "$3" | $SED "s%^$1%%; s%$2\$%%"`;; esac } # func_stripname_cnf if test -n "$CXX" && ( test no != "$CXX" && ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || (test g++ != "$CXX"))); then ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5 printf %s "checking how to run the C++ preprocessor... " >&6; } if test -z "$CXXCPP"; then if test ${ac_cv_prog_CXXCPP+y} then : printf %s "(cached) " >&6 else case e in #( e) # Double quotes because $CXX needs to be expanded for CXXCPP in "$CXX -E" cpp /lib/cpp do ac_preproc_ok=false for ac_cxx_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include Syntax error _ACEOF if ac_fn_cxx_try_cpp "$LINENO" then : else case e in #( e) # Broken: fails on valid input. continue ;; esac fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_cxx_try_cpp "$LINENO" then : # Broken: success on invalid input. continue else case e in #( e) # Passes both tests. ac_preproc_ok=: break ;; esac fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of 'break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok then : break fi done ac_cv_prog_CXXCPP=$CXXCPP ;; esac fi CXXCPP=$ac_cv_prog_CXXCPP else ac_cv_prog_CXXCPP=$CXXCPP fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5 printf "%s\n" "$CXXCPP" >&6; } ac_preproc_ok=false for ac_cxx_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include Syntax error _ACEOF if ac_fn_cxx_try_cpp "$LINENO" then : else case e in #( e) # Broken: fails on valid input. continue ;; esac fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_cxx_try_cpp "$LINENO" then : # Broken: success on invalid input. continue else case e in #( e) # Passes both tests. ac_preproc_ok=: break ;; esac fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of 'break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok then : else case e in #( e) { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check See 'config.log' for more details" "$LINENO" 5; } ;; esac fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu else _lt_caught_CXX_error=yes fi ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu archive_cmds_need_lc_CXX=no allow_undefined_flag_CXX= always_export_symbols_CXX=no archive_expsym_cmds_CXX= compiler_needs_object_CXX=no export_dynamic_flag_spec_CXX= hardcode_direct_CXX=no hardcode_direct_absolute_CXX=no hardcode_libdir_flag_spec_CXX= hardcode_libdir_separator_CXX= hardcode_minus_L_CXX=no hardcode_shlibpath_var_CXX=unsupported hardcode_automatic_CXX=no inherit_rpath_CXX=no module_cmds_CXX= module_expsym_cmds_CXX= link_all_deplibs_CXX=unknown old_archive_cmds_CXX=$old_archive_cmds reload_flag_CXX=$reload_flag reload_cmds_CXX=$reload_cmds no_undefined_flag_CXX= whole_archive_flag_spec_CXX= enable_shared_with_static_runtimes_CXX=no # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o objext_CXX=$objext # No sense in running all these tests if we already determined that # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_caught_CXX_error"; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} CFLAGS=$CXXFLAGS compiler=$CC compiler_CXX=$CC func_cc_basename $compiler cc_basename=$func_cc_basename_result if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately if test yes = "$GXX"; then lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin' else lt_prog_compiler_no_builtin_flag_CXX= fi if test yes = "$GXX"; then # Set up default GNU C++ configuration # Check whether --with-gnu-ld was given. if test ${with_gnu_ld+y} then : withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes else case e in #( e) with_gnu_ld=no ;; esac fi ac_prog=ld if test yes = "$GCC"; then # Check if gcc -print-prog-name=ld gives a path. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 printf %s "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return, which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD=$ac_prog ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test yes = "$with_gnu_ld"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 printf %s "checking for GNU ld... " >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 printf %s "checking for non-GNU ld... " >&6; } fi if test ${lt_cv_path_LD+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -z "$LD"; then lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD=$ac_dir/$ac_prog # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 printf "%s\n" "$LD" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 printf %s "checking if the linker ($LD) is GNU ld... " >&6; } if test ${lt_cv_prog_gnu_ld+y} then : printf %s "(cached) " >&6 else case e in #( e) # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 printf "%s\n" "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test yes = "$with_gnu_ld"; then archive_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' export_dynamic_flag_spec_CXX='$wl--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='$wl' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then whole_archive_flag_spec_CXX=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else whole_archive_flag_spec_CXX= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 printf %s "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } ld_shlibs_CXX=yes case $host_os in aix3*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aix[4-9]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds_CXX='' hardcode_direct_CXX=yes hardcode_direct_absolute_CXX=yes hardcode_libdir_separator_CXX=':' link_all_deplibs_CXX=yes file_list_spec_CXX='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. hardcode_direct_CXX=no hardcode_direct_absolute_CXX=no ;; esac if test yes = "$GXX"; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct_CXX=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L_CXX=yes hardcode_libdir_flag_spec_CXX='-L$libdir' hardcode_libdir_separator_CXX= fi esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag=$shared_flag' $wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi export_dynamic_flag_spec_CXX='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. always_export_symbols_CXX=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. # The "-G" linker flag allows undefined symbols. no_undefined_flag_CXX='-bernotok' # Determine the default libpath from the value encoded in an empty # executable. if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if test ${lt_cv_aix_libpath__CXX+y} then : printf %s "(cached) " >&6 else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO" then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX=/usr/lib:/lib fi ;; esac fi aix_libpath=$lt_cv_aix_libpath__CXX fi hardcode_libdir_flag_spec_CXX='$wl-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then hardcode_libdir_flag_spec_CXX='$wl-R $libdir:/usr/lib:/lib' allow_undefined_flag_CXX="-z nodefs" archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if test ${lt_cv_aix_libpath__CXX+y} then : printf %s "(cached) " >&6 else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO" then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX=/usr/lib:/lib fi ;; esac fi aix_libpath=$lt_cv_aix_libpath__CXX fi hardcode_libdir_flag_spec_CXX='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag_CXX=' $wl-bernotok' allow_undefined_flag_CXX=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. whole_archive_flag_spec_CXX='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec_CXX='$convenience' fi archive_cmds_need_lc_CXX=yes archive_expsym_cmds_CXX='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$RM -r $output_objdir/$realname.d' fi fi ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then allow_undefined_flag_CXX=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else ld_shlibs_CXX=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; cygwin* | mingw* | pw32* | cegcc*) case $GXX,$cc_basename in ,cl* | no,cl* | ,icl* | no,icl*) # Native MSVC or ICC # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec_CXX=' ' allow_undefined_flag_CXX=unsupported always_export_symbols_CXX=yes file_list_spec_CXX='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. archive_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' archive_expsym_cmds_CXX='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, CXX)='true' enable_shared_with_static_runtimes_CXX=yes # Don't use ranlib old_postinstall_cmds_CXX='chmod 644 $oldlib' postlink_cmds_CXX='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ func_to_tool_file "$lt_outputfile"~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # g++ # _LT_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec_CXX='-L$libdir' export_dynamic_flag_spec_CXX='$wl--export-all-symbols' allow_undefined_flag_CXX=unsupported always_export_symbols_CXX=no enable_shared_with_static_runtimes_CXX=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... archive_expsym_cmds_CXX='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs_CXX=no fi ;; esac ;; darwin* | rhapsody*) archive_cmds_need_lc_CXX=no hardcode_direct_CXX=no hardcode_automatic_CXX=yes hardcode_shlibpath_var_CXX=unsupported if test yes = "$lt_cv_ld_force_load"; then whole_archive_flag_spec_CXX='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' else whole_archive_flag_spec_CXX='' fi link_all_deplibs_CXX=yes allow_undefined_flag_CXX=$_lt_dar_allow_undefined case $cc_basename in ifort*|nagfor*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test yes = "$_lt_dar_can_shared"; then output_verbose_link_cmd=func_echo_all archive_cmds_CXX="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" module_cmds_CXX="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" archive_expsym_cmds_CXX="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" module_expsym_cmds_CXX="$SED -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" if test yes != "$lt_cv_apple_cc_single_mod"; then archive_cmds_CXX="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" archive_expsym_cmds_CXX="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" fi else ld_shlibs_CXX=no fi ;; os2*) hardcode_libdir_flag_spec_CXX='-L$libdir' hardcode_minus_L_CXX=yes allow_undefined_flag_CXX=unsupported shrext_cmds=.dll archive_cmds_CXX='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' archive_expsym_cmds_CXX='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' old_archive_From_new_cmds_CXX='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' enable_shared_with_static_runtimes_CXX=yes file_list_spec_CXX='@' ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; freebsd2.*) # C++ shared libraries reported to be fairly broken before # switch to ELF ld_shlibs_CXX=no ;; freebsd-elf*) archive_cmds_need_lc_CXX=no ;; freebsd* | dragonfly* | midnightbsd*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions ld_shlibs_CXX=yes ;; haiku*) archive_cmds_CXX='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' link_all_deplibs_CXX=yes ;; hpux9*) hardcode_libdir_flag_spec_CXX='$wl+b $wl$libdir' hardcode_libdir_separator_CXX=: export_dynamic_flag_spec_CXX='$wl-E' hardcode_direct_CXX=yes hardcode_minus_L_CXX=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aCC*) archive_cmds_CXX='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then archive_cmds_CXX='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; hpux10*|hpux11*) if test no = "$with_gnu_ld"; then hardcode_libdir_flag_spec_CXX='$wl+b $wl$libdir' hardcode_libdir_separator_CXX=: case $host_cpu in hppa*64*|ia64*) ;; *) export_dynamic_flag_spec_CXX='$wl-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) hardcode_direct_CXX=no hardcode_shlibpath_var_CXX=no ;; *) hardcode_direct_CXX=yes hardcode_direct_absolute_CXX=yes hardcode_minus_L_CXX=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aCC*) case $host_cpu in hppa*64*) archive_cmds_CXX='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) archive_cmds_CXX='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) archive_cmds_CXX='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then case $host_cpu in hppa*64*) archive_cmds_CXX='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) archive_cmds_CXX='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) archive_cmds_CXX='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; interix[3-9]*) hardcode_direct_CXX=no hardcode_shlibpath_var_CXX=no hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' export_dynamic_flag_spec_CXX='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds_CXX='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' fi fi link_all_deplibs_CXX=yes ;; esac hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' hardcode_libdir_separator_CXX=: inherit_rpath_CXX=yes ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' export_dynamic_flag_spec_CXX='$wl--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc* | ecpc* ) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac archive_cmds_need_lc_CXX=no hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' export_dynamic_flag_spec_CXX='$wl--export-dynamic' whole_archive_flag_spec_CXX='$wl--whole-archive$convenience $wl--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [1-5].* | *pgcpp\ [1-5].*) prelink_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' old_archive_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ $RANLIB $oldlib' archive_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 6 and above use weak symbols archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac hardcode_libdir_flag_spec_CXX='$wl--rpath $wl$libdir' export_dynamic_flag_spec_CXX='$wl--export-dynamic' whole_archive_flag_spec_CXX='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' ;; cxx*) # Compaq C++ archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec_CXX='-rpath $libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' export_dynamic_flag_spec_CXX='$wl--export-dynamic' archive_cmds_CXX='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then archive_expsym_cmds_CXX='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi ;; *) case `$CC -V 2>&1 | $SED 5q` in *Sun\ C*) # Sun C++ 5.9 no_undefined_flag_CXX=' -zdefs' archive_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' archive_expsym_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' hardcode_libdir_flag_spec_CXX='-R$libdir' whole_archive_flag_spec_CXX='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' compiler_needs_object_CXX=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; m88k*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= hardcode_libdir_flag_spec_CXX='-R$libdir' hardcode_direct_CXX=yes hardcode_shlibpath_var_CXX=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; *nto* | *qnx*) ld_shlibs_CXX=yes ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then hardcode_direct_CXX=yes hardcode_shlibpath_var_CXX=no hardcode_direct_absolute_CXX=yes archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' export_dynamic_flag_spec_CXX='$wl-E' whole_archive_flag_spec_CXX=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else ld_shlibs_CXX=no fi ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' hardcode_libdir_separator_CXX=: # Archives containing C++ object files must be created using # the KAI C++ compiler. case $host in osf3*) old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; *) old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' ;; esac ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; cxx*) case $host in osf3*) allow_undefined_flag_CXX=' $wl-expect_unresolved $wl\*' archive_cmds_CXX='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' ;; *) allow_undefined_flag_CXX=' -expect_unresolved \*' archive_cmds_CXX='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ $RM $lib.exp' hardcode_libdir_flag_spec_CXX='-rpath $libdir' ;; esac hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes,no = "$GXX,$with_gnu_ld"; then allow_undefined_flag_CXX=' $wl-expect_unresolved $wl\*' case $host in osf3*) archive_cmds_CXX='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; *) archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; esac hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ archive_cmds_need_lc_CXX=yes no_undefined_flag_CXX=' -zdefs' archive_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' hardcode_libdir_flag_spec_CXX='-R$libdir' hardcode_shlibpath_var_CXX=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) whole_archive_flag_spec_CXX='-z allextract$convenience -z defaultextract' ;; esac link_all_deplibs_CXX=yes output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test yes,no = "$GXX,$with_gnu_ld"; then no_undefined_flag_CXX=' $wl-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # g++ 2.7 appears to require '-G' NOT '-shared' on this # platform. archive_cmds_CXX='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' fi hardcode_libdir_flag_spec_CXX='$wl-R $wl$libdir' case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) whole_archive_flag_spec_CXX='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag_CXX='$wl-z,text' archive_cmds_need_lc_CXX=no hardcode_shlibpath_var_CXX=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) archive_cmds_CXX='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds_CXX='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag_CXX='$wl-z,text' allow_undefined_flag_CXX='$wl-z,nodefs' archive_cmds_need_lc_CXX=no hardcode_shlibpath_var_CXX=no hardcode_libdir_flag_spec_CXX='$wl-R,$libdir' hardcode_libdir_separator_CXX=':' link_all_deplibs_CXX=yes export_dynamic_flag_spec_CXX='$wl-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) archive_cmds_CXX='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' old_archive_cmds_CXX='$CC -Tprelink_objects $oldobjs~ '"$old_archive_cmds_CXX" reload_cmds_CXX='$CC -Tprelink_objects $reload_objs~ '"$reload_cmds_CXX" ;; *) archive_cmds_CXX='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 printf "%s\n" "$ld_shlibs_CXX" >&6; } test no = "$ld_shlibs_CXX" && can_build_shared=no GCC_CXX=$GXX LD_CXX=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... # Dependencies to place before and after the object being linked: predep_objects_CXX= postdep_objects_CXX= predeps_CXX= postdeps_CXX= compiler_lib_search_path_CXX= cat > conftest.$ac_ext <<_LT_EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; _LT_EOF _lt_libdeps_save_CFLAGS=$CFLAGS case "$CC $CFLAGS " in #( *\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; *\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; *\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; esac if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do case $prev$p in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test x-L = "$p" || test x-R = "$p"; then prev=$p continue fi # Expand the sysroot to ease extracting the directories later. if test -z "$prev"; then case $p in -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; esac fi case $p in =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; esac if test no = "$pre_test_object_deps_done"; then case $prev in -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$compiler_lib_search_path_CXX"; then compiler_lib_search_path_CXX=$prev$p else compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} $prev$p" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$postdeps_CXX"; then postdeps_CXX=$prev$p else postdeps_CXX="${postdeps_CXX} $prev$p" fi fi prev= ;; *.lto.$objext) ;; # Ignore GCC LTO objects *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test no = "$pre_test_object_deps_done"; then if test -z "$predep_objects_CXX"; then predep_objects_CXX=$p else predep_objects_CXX="$predep_objects_CXX $p" fi else if test -z "$postdep_objects_CXX"; then postdep_objects_CXX=$p else postdep_objects_CXX="$postdep_objects_CXX $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling CXX test program" fi $RM -f confest.$objext CFLAGS=$_lt_libdeps_save_CFLAGS # PORTME: override above test on systems where it is broken case $host_os in interix[3-9]*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. predep_objects_CXX= postdep_objects_CXX= postdeps_CXX= ;; esac case " $postdeps_CXX " in *" -lc "*) archive_cmds_need_lc_CXX=no ;; esac compiler_lib_search_dirs_CXX= if test -n "${compiler_lib_search_path_CXX}"; then compiler_lib_search_dirs_CXX=`echo " ${compiler_lib_search_path_CXX}" | $SED -e 's! -L! !g' -e 's!^ !!'` fi lt_prog_compiler_wl_CXX= lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX= # C++ specific cases for pic, static, wl, etc. if test yes = "$GXX"; then lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_CXX='-Bstatic' fi lt_prog_compiler_pic_CXX='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support lt_prog_compiler_pic_CXX='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic_CXX='-DDLL_EXPORT' case $host_os in os2*) lt_prog_compiler_static_CXX='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic_CXX='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all lt_prog_compiler_pic_CXX= ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. lt_prog_compiler_static_CXX= ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic_CXX=-Kconform_pic fi ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) ;; *) lt_prog_compiler_pic_CXX='-fPIC' ;; esac ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic_CXX='-fPIC -shared' ;; *) lt_prog_compiler_pic_CXX='-fPIC' ;; esac else case $host_os in aix[4-9]*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_CXX='-Bstatic' else lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic_CXX='-DDLL_EXPORT' ;; dgux*) case $cc_basename in ec++*) lt_prog_compiler_pic_CXX='-KPIC' ;; ghcx*) # Green Hills C++ Compiler lt_prog_compiler_pic_CXX='-pic' ;; *) ;; esac ;; freebsd* | dragonfly* | midnightbsd*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='$wl-a ${wl}archive' if test ia64 != "$host_cpu"; then lt_prog_compiler_pic_CXX='+Z' fi ;; aCC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='$wl-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic_CXX='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # KAI C++ Compiler lt_prog_compiler_wl_CXX='--backend -Wl,' lt_prog_compiler_pic_CXX='-fPIC' ;; ecpc* ) # old Intel C++ for x86_64, which still supported -KPIC. lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-static' ;; icpc* ) # Intel C++, used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-fPIC' lt_prog_compiler_static_CXX='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-fpic' lt_prog_compiler_static_CXX='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX='-non_shared' ;; xlc* | xlC* | bgxl[cC]* | mpixl[cC]*) # IBM XL 8.0, 9.0 on PPC and BlueGene lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-qpic' lt_prog_compiler_static_CXX='-qstaticlink' ;; *) case `$CC -V 2>&1 | $SED 5q` in *Sun\ C*) # Sun C++ 5.9 lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' lt_prog_compiler_wl_CXX='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) lt_prog_compiler_pic_CXX='-W c,exportall' ;; *) ;; esac ;; netbsd*) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic_CXX='-fPIC -shared' ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) lt_prog_compiler_wl_CXX='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 lt_prog_compiler_pic_CXX='-pic' ;; cxx*) # Digital/Compaq C++ lt_prog_compiler_wl_CXX='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' lt_prog_compiler_wl_CXX='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler lt_prog_compiler_pic_CXX='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x lt_prog_compiler_pic_CXX='-pic' lt_prog_compiler_static_CXX='-Bstatic' ;; lcc*) # Lucid lt_prog_compiler_pic_CXX='-pic' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 lt_prog_compiler_pic_CXX='-KPIC' ;; *) ;; esac ;; vxworks*) ;; *) lt_prog_compiler_can_build_shared_CXX=no ;; esac fi case $host_os in # For platforms that do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic_CXX= ;; *) lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC" ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 printf %s "checking for $compiler option to produce PIC... " >&6; } if test ${lt_cv_prog_compiler_pic_CXX+y} then : printf %s "(cached) " >&6 else case e in #( e) lt_cv_prog_compiler_pic_CXX=$lt_prog_compiler_pic_CXX ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_CXX" >&5 printf "%s\n" "$lt_cv_prog_compiler_pic_CXX" >&6; } lt_prog_compiler_pic_CXX=$lt_cv_prog_compiler_pic_CXX # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic_CXX"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5 printf %s "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... " >&6; } if test ${lt_cv_prog_compiler_pic_works_CXX+y} then : printf %s "(cached) " >&6 else case e in #( e) lt_cv_prog_compiler_pic_works_CXX=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works_CXX=yes fi fi $RM conftest* ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works_CXX" >&5 printf "%s\n" "$lt_cv_prog_compiler_pic_works_CXX" >&6; } if test yes = "$lt_cv_prog_compiler_pic_works_CXX"; then case $lt_prog_compiler_pic_CXX in "" | " "*) ;; *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;; esac else lt_prog_compiler_pic_CXX= lt_prog_compiler_can_build_shared_CXX=no fi fi # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 printf %s "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if test ${lt_cv_prog_compiler_static_works_CXX+y} then : printf %s "(cached) " >&6 else case e in #( e) lt_cv_prog_compiler_static_works_CXX=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works_CXX=yes fi else lt_cv_prog_compiler_static_works_CXX=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works_CXX" >&5 printf "%s\n" "$lt_cv_prog_compiler_static_works_CXX" >&6; } if test yes = "$lt_cv_prog_compiler_static_works_CXX"; then : else lt_prog_compiler_static_CXX= fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 printf %s "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if test ${lt_cv_prog_compiler_c_o_CXX+y} then : printf %s "(cached) " >&6 else case e in #( e) lt_cv_prog_compiler_c_o_CXX=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o_CXX=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 printf "%s\n" "$lt_cv_prog_compiler_c_o_CXX" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 printf %s "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if test ${lt_cv_prog_compiler_c_o_CXX+y} then : printf %s "(cached) " >&6 else case e in #( e) lt_cv_prog_compiler_c_o_CXX=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o_CXX=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 printf "%s\n" "$lt_cv_prog_compiler_c_o_CXX" >&6; } hard_links=nottested if test no = "$lt_cv_prog_compiler_c_o_CXX" && test no != "$need_locks"; then # do not overwrite the value of need_locks provided by the user { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 printf %s "checking if we can lock with hard links... " >&6; } hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 printf "%s\n" "$hard_links" >&6; } if test no = "$hard_links"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 printf "%s\n" "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 printf %s "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms_CXX='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' case $host_os in aix[4-9]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else export_symbols_cmds_CXX='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi ;; pw32*) export_symbols_cmds_CXX=$ltdll_cmds ;; cygwin* | mingw* | cegcc*) case $cc_basename in cl* | icl*) exclude_expsyms_CXX='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' ;; *) export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms_CXX='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' ;; esac ;; *) export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 printf "%s\n" "$ld_shlibs_CXX" >&6; } test no = "$ld_shlibs_CXX" && can_build_shared=no with_gnu_ld_CXX=$with_gnu_ld # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc_CXX" in x|xyes) # Assume -lc should be added archive_cmds_need_lc_CXX=yes if test yes,yes = "$GCC,$enable_shared"; then case $archive_cmds_CXX in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 printf %s "checking whether -lc should be explicitly linked in... " >&6; } if test ${lt_cv_archive_cmds_need_lc_CXX+y} then : printf %s "(cached) " >&6 else case e in #( e) $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl_CXX pic_flag=$lt_prog_compiler_pic_CXX compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag_CXX allow_undefined_flag_CXX= if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then lt_cv_archive_cmds_need_lc_CXX=no else lt_cv_archive_cmds_need_lc_CXX=yes fi allow_undefined_flag_CXX=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc_CXX" >&5 printf "%s\n" "$lt_cv_archive_cmds_need_lc_CXX" >&6; } archive_cmds_need_lc_CXX=$lt_cv_archive_cmds_need_lc_CXX ;; esac fi ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 printf %s "checking dynamic linker characteristics... " >&6; } library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=.so postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='$libname$release$shared_ext$major' ;; aix[4-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test ia64 = "$host_cpu"; then # AIX 5 supports IA64 library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line '#! .'. This would cause the generated library to # depend on '.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # Using Import Files as archive members, it is possible to support # filename-based versioning of shared library archives on AIX. While # this would work for both with and without runtime linking, it will # prevent static linking of such archives. So we do filename-based # shared library versioning with .so extension only, which is used # when both runtime linking and shared linking is enabled. # Unfortunately, runtime linking may impact performance, so we do # not want this to be the default eventually. Also, we use the # versioned .so libs for executables only if there is the -brtl # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. # To allow for filename-based versioning support, we need to create # libNAME.so.V as an archive file, containing: # *) an Import File, referring to the versioned filename of the # archive as well as the shared archive member, telling the # bitwidth (32 or 64) of that shared object, and providing the # list of exported symbols of that shared object, eventually # decorated with the 'weak' keyword # *) the shared object with the F_LOADONLY flag set, to really avoid # it being seen by the linker. # At run time we better use the real file rather than another symlink, # but for link time we create the symlink libNAME.so -> libNAME.so.V case $with_aix_soname,$aix_use_runtimelinking in # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. aix,yes) # traditional libtool dynamic_linker='AIX unversionable lib.so' # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; aix,no) # traditional AIX only dynamic_linker='AIX lib.a(lib.so.V)' # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' ;; svr4,*) # full svr4 only dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,yes) # both, prefer svr4 dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # unpreferred sharedlib libNAME.a needs extra handling postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,no) # both, prefer aix dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' ;; esac shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='$libname$shared_ext' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo $libname | $SED -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo $libname | $SED -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl* | *,icl*) # Native MSVC or ICC libname_spec='$name' soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' library_names_spec='$libname.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec=$LIB if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC and ICC wrapper library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' soname_spec='$libname$release$major$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly* | midnightbsd*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[23].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=no sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' if test 32 = "$HPUX_IA64_MODE"; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[3-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test yes = "$lt_cv_prog_gnu_ld"; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; linux*android*) version_type=none # Android doesn't support versioned libraries. need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext' soname_spec='$libname$release$shared_ext' finish_cmds= shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes dynamic_linker='Android linker' # Don't embed -rpath directories since the linker doesn't support them. hardcode_libdir_flag_spec_CXX='-L$libdir' ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH if test ${lt_cv_shlibpath_overrides_runpath+y} then : printf %s "(cached) " >&6 else case e in #( e) lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$lt_prog_compiler_wl_CXX\"; \ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec_CXX\"" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO" then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null then : lt_cv_shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS libdir=$save_libdir ;; esac fi shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Ideally, we could use ldconfig to report *all* directores which are # searched for libraries, however this is still not possible. Aside from not # being certain /sbin/ldconfig is available, command # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, # even though it is searched at run-time. Try to do the best guess by # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd* | bitrig*) version_type=sunos sys_lib_dlsearch_path_spec=/usr/lib need_lib_prefix=no if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then need_version=no else need_version=yes fi library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; os2*) libname_spec='$name' version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no # OS/2 can only load a DLL with a base name of 8 characters or less. soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; v=$($ECHO $release$versuffix | tr -d .-); n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); $ECHO $n$v`$shared_ext' library_names_spec='${libname}_dll.$libext' dynamic_linker='OS/2 ld.exe' shlibpath_var=BEGINLIBPATH sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test yes = "$with_gnu_ld"; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec; then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' soname_spec='$libname$shared_ext.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=sco need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test yes = "$with_gnu_ld"; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 printf "%s\n" "$dynamic_linker" >&6; } test no = "$dynamic_linker" && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test yes = "$GCC"; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec fi if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec fi # remember unaugmented sys_lib_dlsearch_path content for libtool script decls... configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec # ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" # to be used as default LT_SYS_LIBRARY_PATH value in generated libtool configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 printf %s "checking how to hardcode library paths into programs... " >&6; } hardcode_action_CXX= if test -n "$hardcode_libdir_flag_spec_CXX" || test -n "$runpath_var_CXX" || test yes = "$hardcode_automatic_CXX"; then # We can hardcode non-existent directories. if test no != "$hardcode_direct_CXX" && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, CXX)" && test no != "$hardcode_minus_L_CXX"; then # Linking always hardcodes the temporary library directory. hardcode_action_CXX=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action_CXX=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action_CXX=unsupported fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $hardcode_action_CXX" >&5 printf "%s\n" "$hardcode_action_CXX" >&6; } if test relink = "$hardcode_action_CXX" || test yes = "$inherit_rpath_CXX"; then # Fast installation is not supported enable_fast_install=no elif test yes = "$shlibpath_overrides_runpath" || test no = "$enable_shared"; then # Fast installation is not necessary enable_fast_install=needless fi fi # test -n "$compiler" CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld fi # test yes != "$_lt_caught_CXX_error" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Filter out unwanted flags added by autoconf on some systems, e.g. MacOS. values_to_check=`for i in $CXX; do echo $i; done` unwanted_values=`for i in -std=c++11 -std=gnu++11; do echo $i; done` if test -z "${unwanted_values}"; then CXX="$CXX" else result=`echo "${values_to_check}" | $GREP -Fvx -- "${unwanted_values}" | $GREP -v '^$'` # join with spaces, squeeze repeats, and trim trailing space CXX=$(printf '%s\n' "$result" | tr '\n' ' ' | sed 's/ */ /g; s/ *$//') fi ax_cxx_compile_alternatives="17 1z" ax_cxx_compile_cxx17_required=true ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu ac_success=no if test x$ac_success = xno; then for alternative in ${ax_cxx_compile_alternatives}; do for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do cachevar=`printf "%s\n" "ax_cv_cxx_compile_cxx17_$switch" | sed "$as_sed_sh"` { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++17 features with $switch" >&5 printf %s "checking whether $CXX supports C++17 features with $switch... " >&6; } if eval test \${$cachevar+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_save_CXX="$CXX" CXX="$CXX $switch" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ // If the compiler admits that it is not ready for C++11, why torture it? // Hopefully, this will speed up the test. #ifndef __cplusplus #error "This is not a C++ compiler" #elif __cplusplus < 201103L #error "This is not a C++11 compiler" #else namespace cxx11 { namespace test_static_assert { template struct check { static_assert(sizeof(int) <= sizeof(T), "not big enough"); }; } namespace test_final_override { struct Base { virtual ~Base() {} virtual void f() {} }; struct Derived : public Base { virtual ~Derived() override {} virtual void f() override {} }; } namespace test_double_right_angle_brackets { template < typename T > struct check {}; typedef check single_type; typedef check> double_type; typedef check>> triple_type; typedef check>>> quadruple_type; } namespace test_decltype { int f() { int a = 1; decltype(a) b = 2; return a + b; } } namespace test_type_deduction { template < typename T1, typename T2 > struct is_same { static const bool value = false; }; template < typename T > struct is_same { static const bool value = true; }; template < typename T1, typename T2 > auto add(T1 a1, T2 a2) -> decltype(a1 + a2) { return a1 + a2; } int test(const int c, volatile int v) { static_assert(is_same::value == true, ""); static_assert(is_same::value == false, ""); static_assert(is_same::value == false, ""); auto ac = c; auto av = v; auto sumi = ac + av + 'x'; auto sumf = ac + av + 1.0; static_assert(is_same::value == true, ""); static_assert(is_same::value == true, ""); static_assert(is_same::value == true, ""); static_assert(is_same::value == false, ""); static_assert(is_same::value == true, ""); return (sumf > 0.0) ? sumi : add(c, v); } } namespace test_noexcept { int f() { return 0; } int g() noexcept { return 0; } static_assert(noexcept(f()) == false, ""); static_assert(noexcept(g()) == true, ""); } namespace test_constexpr { template < typename CharT > unsigned long constexpr strlen_c_r(const CharT *const s, const unsigned long acc) noexcept { return *s ? strlen_c_r(s + 1, acc + 1) : acc; } template < typename CharT > unsigned long constexpr strlen_c(const CharT *const s) noexcept { return strlen_c_r(s, 0UL); } static_assert(strlen_c("") == 0UL, ""); static_assert(strlen_c("1") == 1UL, ""); static_assert(strlen_c("example") == 7UL, ""); static_assert(strlen_c("another\0example") == 7UL, ""); } namespace test_rvalue_references { template < int N > struct answer { static constexpr int value = N; }; answer<1> f(int&) { return answer<1>(); } answer<2> f(const int&) { return answer<2>(); } answer<3> f(int&&) { return answer<3>(); } void test() { int i = 0; const int c = 0; static_assert(decltype(f(i))::value == 1, ""); static_assert(decltype(f(c))::value == 2, ""); static_assert(decltype(f(0))::value == 3, ""); } } namespace test_uniform_initialization { struct test { static const int zero {}; static const int one {1}; }; static_assert(test::zero == 0, ""); static_assert(test::one == 1, ""); } namespace test_lambdas { void test1() { auto lambda1 = [](){}; auto lambda2 = lambda1; lambda1(); lambda2(); } int test2() { auto a = [](int i, int j){ return i + j; }(1, 2); auto b = []() -> int { return '0'; }(); auto c = [=](){ return a + b; }(); auto d = [&](){ return c; }(); auto e = [a, &b](int x) mutable { const auto identity = [](int y){ return y; }; for (auto i = 0; i < a; ++i) a += b--; return x + identity(a + b); }(0); return a + b + c + d + e; } int test3() { const auto nullary = [](){ return 0; }; const auto unary = [](int x){ return x; }; using nullary_t = decltype(nullary); using unary_t = decltype(unary); const auto higher1st = [](nullary_t f){ return f(); }; const auto higher2nd = [unary](nullary_t f1){ return [unary, f1](unary_t f2){ return f2(unary(f1())); }; }; return higher1st(nullary) + higher2nd(nullary)(unary); } } namespace test_variadic_templates { template struct sum; template struct sum { static constexpr auto value = N0 + sum::value; }; template <> struct sum<> { static constexpr auto value = 0; }; static_assert(sum<>::value == 0, ""); static_assert(sum<1>::value == 1, ""); static_assert(sum<23>::value == 23, ""); static_assert(sum<1, 2>::value == 3, ""); static_assert(sum<5, 5, 11>::value == 21, ""); static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); } // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function // because of this. namespace test_template_alias_sfinae { struct foo {}; template using member = typename T::member_type; template void func(...) {} template void func(member*) {} void test(); void test() { func(0); } } } // namespace cxx11 #endif // __cplusplus >= 201103L // If the compiler admits that it is not ready for C++14, why torture it? // Hopefully, this will speed up the test. #ifndef __cplusplus #error "This is not a C++ compiler" #elif __cplusplus < 201402L #error "This is not a C++14 compiler" #else namespace cxx14 { namespace test_polymorphic_lambdas { int test() { const auto lambda = [](auto&&... args){ const auto istiny = [](auto x){ return (sizeof(x) == 1UL) ? 1 : 0; }; const int aretiny[] = { istiny(args)... }; return aretiny[0]; }; return lambda(1, 1L, 1.0f, '1'); } } namespace test_binary_literals { constexpr auto ivii = 0b0000000000101010; static_assert(ivii == 42, "wrong value"); } namespace test_generalized_constexpr { template < typename CharT > constexpr unsigned long strlen_c(const CharT *const s) noexcept { auto length = 0UL; for (auto p = s; *p; ++p) ++length; return length; } static_assert(strlen_c("") == 0UL, ""); static_assert(strlen_c("x") == 1UL, ""); static_assert(strlen_c("test") == 4UL, ""); static_assert(strlen_c("another\0test") == 7UL, ""); } namespace test_lambda_init_capture { int test() { auto x = 0; const auto lambda1 = [a = x](int b){ return a + b; }; const auto lambda2 = [a = lambda1(x)](){ return a; }; return lambda2(); } } namespace test_digit_separators { constexpr auto ten_million = 100'000'000; static_assert(ten_million == 100000000, ""); } namespace test_return_type_deduction { auto f(int& x) { return x; } decltype(auto) g(int& x) { return x; } template < typename T1, typename T2 > struct is_same { static constexpr auto value = false; }; template < typename T > struct is_same { static constexpr auto value = true; }; int test() { auto x = 0; static_assert(is_same::value, ""); static_assert(is_same::value, ""); return x; } } } // namespace cxx14 #endif // __cplusplus >= 201402L // If the compiler admits that it is not ready for C++17, why torture it? // Hopefully, this will speed up the test. #ifndef __cplusplus #error "This is not a C++ compiler" #elif __cplusplus < 201703L #error "This is not a C++17 compiler" #else #include #include #include namespace cxx17 { namespace test_constexpr_lambdas { constexpr int foo = [](){return 42;}(); } namespace test::nested_namespace::definitions { } namespace test_fold_expression { template int multiply(Args... args) { return (args * ... * 1); } template bool all(Args... args) { return (args && ...); } } namespace test_extended_static_assert { static_assert (true); } namespace test_auto_brace_init_list { auto foo = {5}; auto bar {5}; static_assert(std::is_same, decltype(foo)>::value); static_assert(std::is_same::value); } namespace test_typename_in_template_template_parameter { template typename X> struct D; } namespace test_fallthrough_nodiscard_maybe_unused_attributes { int f1() { return 42; } [[nodiscard]] int f2() { [[maybe_unused]] auto unused = f1(); switch (f1()) { case 17: f1(); [[fallthrough]]; case 42: f1(); } return f1(); } } namespace test_extended_aggregate_initialization { struct base1 { int b1, b2 = 42; }; struct base2 { base2() { b3 = 42; } int b3; }; struct derived : base1, base2 { int d; }; derived d1 {{1, 2}, {}, 4}; // full initialization derived d2 {{}, {}, 4}; // value-initialized bases } namespace test_general_range_based_for_loop { struct iter { int i; int& operator* () { return i; } const int& operator* () const { return i; } iter& operator++() { ++i; return *this; } }; struct sentinel { int i; }; bool operator== (const iter& i, const sentinel& s) { return i.i == s.i; } bool operator!= (const iter& i, const sentinel& s) { return !(i == s); } struct range { iter begin() const { return {0}; } sentinel end() const { return {5}; } }; void f() { range r {}; for (auto i : r) { [[maybe_unused]] auto v = i; } } } namespace test_lambda_capture_asterisk_this_by_value { struct t { int i; int foo() { return [*this]() { return i; }(); } }; } namespace test_enum_class_construction { enum class byte : unsigned char {}; byte foo {42}; } namespace test_constexpr_if { template int f () { if constexpr(cond) { return 13; } else { return 42; } } } namespace test_selection_statement_with_initializer { int f() { return 13; } int f2() { if (auto i = f(); i > 0) { return 3; } switch (auto i = f(); i + 4) { case 17: return 2; default: return 1; } } } namespace test_template_argument_deduction_for_class_templates { template struct pair { pair (T1 p1, T2 p2) : m1 {p1}, m2 {p2} {} T1 m1; T2 m2; }; void f() { [[maybe_unused]] auto p = pair{13, 42u}; } } namespace test_non_type_auto_template_parameters { template struct B {}; B<5> b1; B<'a'> b2; } namespace test_structured_bindings { int arr[2] = { 1, 2 }; std::pair pr = { 1, 2 }; auto f1() -> int(&)[2] { return arr; } auto f2() -> std::pair& { return pr; } struct S { int x1 : 2; volatile double y1; }; S f3() { return {}; } auto [ x1, y1 ] = f1(); auto& [ xr1, yr1 ] = f1(); auto [ x2, y2 ] = f2(); auto& [ xr2, yr2 ] = f2(); const auto [ x3, y3 ] = f3(); } namespace test_exception_spec_type_system { struct Good {}; struct Bad {}; void g1() noexcept; void g2(); template Bad f(T*, T*); template Good f(T1*, T2*); static_assert (std::is_same_v); } namespace test_inline_variables { template void f(T) {} template inline T g(T) { return T{}; } template<> inline void f<>(int) {} template<> int g<>(int) { return 5; } } } // namespace cxx17 #endif // __cplusplus < 201703L _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : eval $cachevar=yes else case e in #( e) eval $cachevar=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext CXX="$ac_save_CXX" ;; esac fi eval ac_res=\$$cachevar { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } if eval test x\$$cachevar = xyes; then CXX="$CXX $switch" if test -n "$CXXCPP" ; then CXXCPP="$CXXCPP $switch" fi ac_success=yes break fi done if test x$ac_success = xyes; then break fi done fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test x$ax_cxx_compile_cxx17_required = xtrue; then if test x$ac_success = xno; then as_fn_error $? "*** A compiler with support for C++17 language features is required." "$LINENO" 5 fi fi if test x$ac_success = xno; then HAVE_CXX17=0 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: No compiler with C++17 support was found" >&5 printf "%s\n" "$as_me: No compiler with C++17 support was found" >&6;} else HAVE_CXX17=1 printf "%s\n" "#define HAVE_CXX17 1" >>confdefs.h fi # Check whether --enable-largefile was given. if test ${enable_largefile+y} then : enableval=$enable_largefile; fi if test "$enable_largefile,$enable_year2038" != no,no then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable large file support" >&5 printf %s "checking for $CC option to enable large file support... " >&6; } if test ${ac_cv_sys_largefile_opts+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_save_CC="$CC" ac_opt_found=no for ac_opt in "none needed" "-D_FILE_OFFSET_BITS=64" "-D_LARGE_FILES=1" "-n32"; do if test x"$ac_opt" != x"none needed" then : CC="$ac_save_CC $ac_opt" fi cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #ifndef FTYPE # define FTYPE off_t #endif /* Check that FTYPE can represent 2**63 - 1 correctly. We can't simply define LARGE_FTYPE to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_FTYPE (((FTYPE) 1 << 31 << 31) - 1 + ((FTYPE) 1 << 31 << 31)) int FTYPE_is_large[(LARGE_FTYPE % 2147483629 == 721 && LARGE_FTYPE % 2147483647 == 1) ? 1 : -1]; int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : if test x"$ac_opt" = x"none needed" then : # GNU/Linux s390x and alpha need _FILE_OFFSET_BITS=64 for wide ino_t. CC="$CC -DFTYPE=ino_t" if ac_fn_c_try_compile "$LINENO" then : else case e in #( e) CC="$CC -D_FILE_OFFSET_BITS=64" if ac_fn_c_try_compile "$LINENO" then : ac_opt='-D_FILE_OFFSET_BITS=64' fi rm -f core conftest.err conftest.$ac_objext conftest.beam ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam fi ac_cv_sys_largefile_opts=$ac_opt ac_opt_found=yes fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext test $ac_opt_found = no || break done CC="$ac_save_CC" test $ac_opt_found = yes || ac_cv_sys_largefile_opts="support not detected" ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_opts" >&5 printf "%s\n" "$ac_cv_sys_largefile_opts" >&6; } ac_have_largefile=yes case $ac_cv_sys_largefile_opts in #( "none needed") : ;; #( "supported through gnulib") : ;; #( "support not detected") : ac_have_largefile=no ;; #( "-D_FILE_OFFSET_BITS=64") : printf "%s\n" "#define _FILE_OFFSET_BITS 64" >>confdefs.h ;; #( "-D_LARGE_FILES=1") : printf "%s\n" "#define _LARGE_FILES 1" >>confdefs.h ;; #( "-n32") : CC="$CC -n32" ;; #( *) : as_fn_error $? "internal error: bad value for \$ac_cv_sys_largefile_opts" "$LINENO" 5 ;; esac if test "$enable_year2038" != no then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option for timestamps after 2038" >&5 printf %s "checking for $CC option for timestamps after 2038... " >&6; } if test ${ac_cv_sys_year2038_opts+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_save_CPPFLAGS="$CPPFLAGS" ac_opt_found=no for ac_opt in "none needed" "-D_TIME_BITS=64" "-D__MINGW_USE_VC2005_COMPAT" "-U_USE_32_BIT_TIME_T -D__MINGW_USE_VC2005_COMPAT"; do if test x"$ac_opt" != x"none needed" then : CPPFLAGS="$ac_save_CPPFLAGS $ac_opt" fi cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include /* Check that time_t can represent 2**32 - 1 correctly. */ #define LARGE_TIME_T \\ ((time_t) (((time_t) 1 << 30) - 1 + 3 * ((time_t) 1 << 30))) int verify_time_t_range[(LARGE_TIME_T / 65537 == 65535 && LARGE_TIME_T % 65537 == 0) ? 1 : -1]; int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_sys_year2038_opts="$ac_opt" ac_opt_found=yes fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext test $ac_opt_found = no || break done CPPFLAGS="$ac_save_CPPFLAGS" test $ac_opt_found = yes || ac_cv_sys_year2038_opts="support not detected" ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_year2038_opts" >&5 printf "%s\n" "$ac_cv_sys_year2038_opts" >&6; } ac_have_year2038=yes case $ac_cv_sys_year2038_opts in #( "none needed") : ;; #( "support not detected") : ac_have_year2038=no ;; #( "-D_TIME_BITS=64") : printf "%s\n" "#define _TIME_BITS 64" >>confdefs.h ;; #( "-D__MINGW_USE_VC2005_COMPAT") : printf "%s\n" "#define __MINGW_USE_VC2005_COMPAT 1" >>confdefs.h ;; #( "-U_USE_32_BIT_TIME_T"*) : { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error $? "the 'time_t' type is currently forced to be 32-bit. It will stop working after mid-January 2038. Remove _USE_32BIT_TIME_T from the compiler flags. See 'config.log' for more details" "$LINENO" 5; } ;; #( *) : as_fn_error $? "internal error: bad value for \$ac_cv_sys_year2038_opts" "$LINENO" 5 ;; esac fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 printf %s "checking whether byte ordering is bigendian... " >&6; } if test ${ac_cv_c_bigendian+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_cv_c_bigendian=unknown # See if we're dealing with a universal compiler. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __APPLE_CC__ not a universal capable compiler #endif typedef int dummy; _ACEOF if ac_fn_c_try_compile "$LINENO" then : # Check for potential -arch flags. It is not universal unless # there are at least two -arch flags with different values. ac_arch= ac_prev= for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do if test -n "$ac_prev"; then case $ac_word in i?86 | x86_64 | ppc | ppc64) if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then ac_arch=$ac_word else ac_cv_c_bigendian=universal break fi ;; esac ac_prev= elif test "x$ac_word" = "x-arch"; then ac_prev=arch fi done fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext if test $ac_cv_c_bigendian = unknown; then # See if sys/param.h defines the BYTE_ORDER macro. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main (void) { #if ! (defined BYTE_ORDER && defined BIG_ENDIAN \\ && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \\ && LITTLE_ENDIAN) bogus endian macros #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : # It does; now see whether it defined to BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main (void) { #if BYTE_ORDER != BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_c_bigendian=yes else case e in #( e) ac_cv_c_bigendian=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi if test $ac_cv_c_bigendian = unknown; then # See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { #if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) bogus endian macros #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : # It does; now see whether it defined to _BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { #ifndef _BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_c_bigendian=yes else case e in #( e) ac_cv_c_bigendian=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi if test $ac_cv_c_bigendian = unknown; then # Compile a test program. if test "$cross_compiling" = yes then : # Try to guess by grepping values from an object file. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ unsigned short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; unsigned short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; int use_ascii (int i) { return ascii_mm[i] + ascii_ii[i]; } unsigned short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; unsigned short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; int use_ebcdic (int i) { return ebcdic_mm[i] + ebcdic_ii[i]; } int main (int argc, char **argv) { /* Intimidate the compiler so that it does not optimize the arrays away. */ char *p = argv[0]; ascii_mm[1] = *p++; ebcdic_mm[1] = *p++; ascii_ii[1] = *p++; ebcdic_ii[1] = *p++; return use_ascii (argc) == use_ebcdic (*p); } _ACEOF if ac_fn_c_try_link "$LINENO" then : if grep BIGenDianSyS conftest$ac_exeext >/dev/null; then ac_cv_c_bigendian=yes fi if grep LiTTleEnDian conftest$ac_exeext >/dev/null ; then if test "$ac_cv_c_bigendian" = unknown; then ac_cv_c_bigendian=no else # finding both strings is unlikely to happen, but who knows? ac_cv_c_bigendian=unknown fi fi fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main (void) { /* Are we little or big endian? From Harbison&Steele. */ union { long int l; char c[sizeof (long int)]; } u; u.l = 1; return u.c[sizeof (long int) - 1] == 1; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO" then : ac_cv_c_bigendian=no else case e in #( e) ac_cv_c_bigendian=yes ;; esac fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi fi ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 printf "%s\n" "$ac_cv_c_bigendian" >&6; } case $ac_cv_c_bigendian in #( yes) printf "%s\n" "#define IS_BIG_ENDIAN 1" >>confdefs.h ;; #( no) printf "%s\n" "#define IS_LITTLE_ENDIAN 1" >>confdefs.h ;; #( universal) printf "%s\n" "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h ;; #( *) as_fn_error $? "Could not determine endianness" "$LINENO" 5 ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for user-defined CFLAGS" >&5 printf %s "checking for user-defined CFLAGS... " >&6; } if test "$CFLAGS" = ""; then unset CFLAGS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: undefined" >&5 printf "%s\n" "undefined" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: user-defined \"$CFLAGS\"" >&5 printf "%s\n" "user-defined \"$CFLAGS\"" >&6; } fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for user-defined CXXFLAGS" >&5 printf %s "checking for user-defined CXXFLAGS... " >&6; } if test "$CXXFLAGS" = ""; then unset CXXFLAGS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: undefined" >&5 printf "%s\n" "undefined" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: user-defined \"$CXXFLAGS\"" >&5 printf "%s\n" "user-defined \"$CXXFLAGS\"" >&6; } fi # Check whether --enable-debug was given. if test ${enable_debug+y} then : enableval=$enable_debug; if test "$enableval" = "yes"; then CXXFLAGS="$CXXFLAGS -g -DDEBUG" else CXXFLAGS="$CXXFLAGS -DNDEBUG" fi else case e in #( e) CXXFLAGS="$CXXFLAGS -g -DDEBUG" ;; esac fi # Check whether --enable-extra-debug was given. if test ${enable_extra_debug+y} then : enableval=$enable_extra_debug; if test "$enableval" = "yes"; then printf "%s\n" "#define USE_EXTRA_DEBUG 1" >>confdefs.h fi fi # Check whether --enable-werror was given. if test ${enable_werror+y} then : enableval=$enable_werror; if test "$enableval" = "yes"; then CXXFLAGS="$CXXFLAGS -Werror -Wall" fi else case e in #( e) CXXFLAGS="$CXXFLAGS -Wall" ;; esac fi # Check whether --enable-aligned was given. if test ${enable_aligned+y} then : enableval=$enable_aligned; if test "$enableval" = "yes"; then printf "%s\n" "#define USE_ALIGNED 1" >>confdefs.h fi else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking the byte alignment" >&5 printf %s "checking the byte alignment... " >&6; } if test "$cross_compiling" = yes then : { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error $? "cannot run test program while cross compiling See 'config.log' for more details" "$LINENO" 5; } else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main() { char buf[8] = { 0, 0, 0, 0, 1, 0, 0, 0 }; int i; for (i = 1; i < 4; ++i) if (*(uint32_t*)(buf + i) == 0) return -1; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else case e in #( e) printf "%s\n" "#define USE_ALIGNED 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: required" >&5 printf "%s\n" "required" >&6; } ;; esac fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi ;; esac fi # Check whether --enable-interrupt-socket was given. if test ${enable_interrupt_socket+y} then : enableval=$enable_interrupt_socket; if test "$enableval" = "yes"; then printf "%s\n" "#define USE_INTERRUPT_SOCKET 1" >>confdefs.h fi fi # Check whether --enable-arch was given. if test ${enable_arch+y} then : enableval=$enable_arch; { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for target architectures" >&5 printf %s "checking for target architectures... " >&6; } if test "$enableval" = "yes"; then as_fn_error $? "no arch supplied" "$LINENO" 5 elif test "$enableval" = "no"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: using default" >&5 printf "%s\n" "using default" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $enableval" >&5 printf "%s\n" "$enableval" >&6; } for i in `IFS=,; echo $enableval`; do CFLAGS="$CFLAGS -march=$i" CXXFLAGS="$CXXFLAGS -march=$i" LDFLAGS="$LDFLAGS -march=$i" done fi fi # Check whether --with-sysroot was given. if test ${with_sysroot+y} then : withval=$with_sysroot; { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 printf %s "checking for sysroot... " >&6; } if test "$withval" = "no"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } elif test "$withval" = "yes"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: not a path" >&5 printf "%s\n" "not a path" >&6; } as_fn_error like f.ex "/Developer/SDKs/MacOSX10.4u.sdk". "The sysroot option must point to a directory" "$LINENO" 5 else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $withval" >&5 printf "%s\n" "$withval" >&6; } CXXFLAGS="$CXXFLAGS -isysroot $withval" LDFLAGS="$LDFLAGS -Wl,-syslibroot,$withval" fi fi # Check whether --with-kqueue was given. if test ${with_kqueue+y} then : withval=$with_kqueue; if test "$withval" = "yes"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for kqueue support" >&5 printf %s "checking for kqueue support... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include /* Because OpenBSD's sys/event.h fails to compile otherwise. Yeah... */ #include int main() { int fd = kqueue(); return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : printf "%s\n" "#define USE_KQUEUE 1" >>confdefs.h use_kqueue=yes { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext fi else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for kqueue support" >&5 printf %s "checking for kqueue support... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include /* Because OpenBSD's sys/event.h fails to compile otherwise. Yeah... */ #include int main() { int fd = kqueue(); return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : printf "%s\n" "#define USE_KQUEUE 1" >>confdefs.h use_kqueue=yes { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext ;; esac fi # Check whether --with-epoll was given. if test ${with_epoll+y} then : withval=$with_epoll; if test "$withval" = "yes"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for epoll support" >&5 printf %s "checking for epoll support... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main() { int fd = epoll_create(100); return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : printf "%s\n" "#define USE_EPOLL 1" >>confdefs.h use_epoll=yes { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for epoll support" >&5 printf %s "checking for epoll support... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main() { int fd = epoll_create(100); return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : printf "%s\n" "#define USE_EPOLL 1" >>confdefs.h use_epoll=yes { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for fallocate" >&5 printf %s "checking for fallocate... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _GNU_SOURCE #include int main (void) { fallocate(0, FALLOC_FL_KEEP_SIZE, 0, 0); return 0; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : printf "%s\n" "#define USE_FALLOCATE 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext # Check whether --with-posix-fallocate was given. if test ${with_posix_fallocate+y} then : withval=$with_posix_fallocate; if test "$withval" = "yes"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for posix_fallocate" >&5 printf %s "checking for posix_fallocate... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { posix_fallocate(0, 0, 0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : printf "%s\n" "#define USE_POSIX_FALLOCATE 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext fi fi # Check whether --with-address-space was given. if test ${with_address_space+y} then : withval=$with_address_space; if test ! -z $withval -a "$withval" != "yes" -a "$withval" != "no"; then printf "%s\n" "#define DEFAULT_ADDRESS_SPACE_SIZE $withval" >>confdefs.h else as_fn_error $? "--with-address-space requires a parameter." "$LINENO" 5 fi else case e in #( e) # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like 'int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of long" >&5 printf %s "checking size of long... " >&6; } if test ${ac_cv_sizeof_long+y} then : printf %s "(cached) " >&6 else case e in #( e) if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long))" "ac_cv_sizeof_long" "$ac_includes_default" then : else case e in #( e) if test "$ac_cv_type_long" = yes; then { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (long) See 'config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_long=0 fi ;; esac fi ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long" >&5 printf "%s\n" "$ac_cv_sizeof_long" >&6; } printf "%s\n" "#define SIZEOF_LONG $ac_cv_sizeof_long" >>confdefs.h if test $ac_cv_sizeof_long = 8; then printf "%s\n" "#define DEFAULT_ADDRESS_SPACE_SIZE 4096" >>confdefs.h else printf "%s\n" "#define DEFAULT_ADDRESS_SPACE_SIZE 1024" >>confdefs.h fi ;; esac fi # Check whether --with-statvfs was given. if test ${with_statvfs+y} then : withval=$with_statvfs; if test "$withval" = "yes"; then ac_fn_c_check_header_compile "$LINENO" "sys/vfs.h" "ac_cv_header_sys_vfs_h" "$ac_includes_default" if test "x$ac_cv_header_sys_vfs_h" = xyes then : printf "%s\n" "#define HAVE_SYS_VFS_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "sys/statvfs.h" "ac_cv_header_sys_statvfs_h" "$ac_includes_default" if test "x$ac_cv_header_sys_statvfs_h" = xyes then : printf "%s\n" "#define HAVE_SYS_STATVFS_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "sys/statfs.h" "ac_cv_header_sys_statfs_h" "$ac_includes_default" if test "x$ac_cv_header_sys_statfs_h" = xyes then : printf "%s\n" "#define HAVE_SYS_STATFS_H 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for statvfs" >&5 printf %s "checking for statvfs... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if HAVE_SYS_VFS_H #include #endif #if HAVE_SYS_STATVFS_H #include #endif #if HAVE_SYS_STATFS_H #include #endif int main (void) { struct statvfs s; fsblkcnt_t c; statvfs("", &s); fstatvfs(0, &s); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : printf "%s\n" "#define FS_STAT_FD fstatvfs(fd, &m_stat) == 0" >>confdefs.h printf "%s\n" "#define FS_STAT_FN statvfs(fn, &m_stat) == 0" >>confdefs.h printf "%s\n" "#define FS_STAT_STRUCT struct statvfs" >>confdefs.h printf "%s\n" "#define FS_STAT_SIZE_TYPE unsigned long" >>confdefs.h printf "%s\n" "#define FS_STAT_COUNT_TYPE fsblkcnt_t" >>confdefs.h printf "%s\n" "#define FS_STAT_BLOCK_SIZE (m_stat.f_frsize)" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ok" >&5 printf "%s\n" "ok" >&6; } have_stat_vfs=yes else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } have_stat_vfs=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext else have_stat_vfs=no fi else case e in #( e) ac_fn_c_check_header_compile "$LINENO" "sys/vfs.h" "ac_cv_header_sys_vfs_h" "$ac_includes_default" if test "x$ac_cv_header_sys_vfs_h" = xyes then : printf "%s\n" "#define HAVE_SYS_VFS_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "sys/statvfs.h" "ac_cv_header_sys_statvfs_h" "$ac_includes_default" if test "x$ac_cv_header_sys_statvfs_h" = xyes then : printf "%s\n" "#define HAVE_SYS_STATVFS_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "sys/statfs.h" "ac_cv_header_sys_statfs_h" "$ac_includes_default" if test "x$ac_cv_header_sys_statfs_h" = xyes then : printf "%s\n" "#define HAVE_SYS_STATFS_H 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for statvfs" >&5 printf %s "checking for statvfs... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if HAVE_SYS_VFS_H #include #endif #if HAVE_SYS_STATVFS_H #include #endif #if HAVE_SYS_STATFS_H #include #endif int main (void) { struct statvfs s; fsblkcnt_t c; statvfs("", &s); fstatvfs(0, &s); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : printf "%s\n" "#define FS_STAT_FD fstatvfs(fd, &m_stat) == 0" >>confdefs.h printf "%s\n" "#define FS_STAT_FN statvfs(fn, &m_stat) == 0" >>confdefs.h printf "%s\n" "#define FS_STAT_STRUCT struct statvfs" >>confdefs.h printf "%s\n" "#define FS_STAT_SIZE_TYPE unsigned long" >>confdefs.h printf "%s\n" "#define FS_STAT_COUNT_TYPE fsblkcnt_t" >>confdefs.h printf "%s\n" "#define FS_STAT_BLOCK_SIZE (m_stat.f_frsize)" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ok" >&5 printf "%s\n" "ok" >&6; } have_stat_vfs=yes else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } have_stat_vfs=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext ;; esac fi # Check whether --with-statfs was given. if test ${with_statfs+y} then : withval=$with_statfs; if test "$have_stat_vfs" = "no"; then if test "$withval" = "yes"; then ac_fn_c_check_header_compile "$LINENO" "sys/statfs.h" "ac_cv_header_sys_statfs_h" "$ac_includes_default" if test "x$ac_cv_header_sys_statfs_h" = xyes then : printf "%s\n" "#define HAVE_SYS_STATFS_H 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for statfs" >&5 printf %s "checking for statfs... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if HAVE_SYS_STATFS_H #include #endif int main (void) { struct statfs s; statfs("", &s); fstatfs(0, &s); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : printf "%s\n" "#define FS_STAT_FD fstatfs(fd, &m_stat) == 0" >>confdefs.h printf "%s\n" "#define FS_STAT_FN statfs(fn, &m_stat) == 0" >>confdefs.h printf "%s\n" "#define FS_STAT_STRUCT struct statfs" >>confdefs.h printf "%s\n" "#define FS_STAT_SIZE_TYPE long" >>confdefs.h printf "%s\n" "#define FS_STAT_COUNT_TYPE long" >>confdefs.h printf "%s\n" "#define FS_STAT_BLOCK_SIZE (m_stat.f_bsize)" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ok" >&5 printf "%s\n" "ok" >&6; } have_stat_vfs=yes else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } have_stat_vfs=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext else printf "%s\n" "#define FS_STAT_FD (errno = ENOSYS) == 0" >>confdefs.h printf "%s\n" "#define FS_STAT_FN (errno = ENOSYS) == 0" >>confdefs.h printf "%s\n" "#define FS_STAT_STRUCT struct {blocksize_type f_bsize; blockcount_type f_bavail;}" >>confdefs.h printf "%s\n" "#define FS_STAT_SIZE_TYPE int" >>confdefs.h printf "%s\n" "#define FS_STAT_COUNT_TYPE int" >>confdefs.h printf "%s\n" "#define FS_STAT_BLOCK_SIZE (4096)" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: No filesystem stats available" >&5 printf "%s\n" "No filesystem stats available" >&6; } fi fi else case e in #( e) if test "$have_stat_vfs" = "no"; then ac_fn_c_check_header_compile "$LINENO" "sys/statfs.h" "ac_cv_header_sys_statfs_h" "$ac_includes_default" if test "x$ac_cv_header_sys_statfs_h" = xyes then : printf "%s\n" "#define HAVE_SYS_STATFS_H 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for statfs" >&5 printf %s "checking for statfs... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if HAVE_SYS_STATFS_H #include #endif int main (void) { struct statfs s; statfs("", &s); fstatfs(0, &s); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : printf "%s\n" "#define FS_STAT_FD fstatfs(fd, &m_stat) == 0" >>confdefs.h printf "%s\n" "#define FS_STAT_FN statfs(fn, &m_stat) == 0" >>confdefs.h printf "%s\n" "#define FS_STAT_STRUCT struct statfs" >>confdefs.h printf "%s\n" "#define FS_STAT_SIZE_TYPE long" >>confdefs.h printf "%s\n" "#define FS_STAT_COUNT_TYPE long" >>confdefs.h printf "%s\n" "#define FS_STAT_BLOCK_SIZE (m_stat.f_bsize)" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ok" >&5 printf "%s\n" "ok" >&6; } have_stat_vfs=yes else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } have_stat_vfs=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext if test "$have_stat_vfs" = "no"; then printf "%s\n" "#define FS_STAT_FD (errno = ENOSYS) == 0" >>confdefs.h printf "%s\n" "#define FS_STAT_FN (errno = ENOSYS) == 0" >>confdefs.h printf "%s\n" "#define FS_STAT_STRUCT struct {blocksize_type f_bsize; blockcount_type f_bavail;}" >>confdefs.h printf "%s\n" "#define FS_STAT_SIZE_TYPE int" >>confdefs.h printf "%s\n" "#define FS_STAT_COUNT_TYPE int" >>confdefs.h printf "%s\n" "#define FS_STAT_BLOCK_SIZE (4096)" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: No filesystem stats available" >&5 printf "%s\n" "No filesystem stats available" >&6; } fi fi ;; esac fi ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu ac_fn_cxx_check_header_compile "$LINENO" "sys/inotify.h" "ac_cv_header_sys_inotify_h" "$ac_includes_default" if test "x$ac_cv_header_sys_inotify_h" = xyes then : printf "%s\n" "#define HAVE_SYS_INOTIFY_H 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether sys/inotify.h actually works" >&5 printf %s "checking whether sys/inotify.h actually works... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main(int,const char**) { return (-1 == inotify_init()); } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : printf "%s\n" "#define USE_INOTIFY 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: failed" >&5 printf "%s\n" "failed" >&6; } ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Check whether --enable-attribute-visibility was given. if test ${enable_attribute_visibility+y} then : enableval=$enable_attribute_visibility; if test "$enableval" = "yes"; then ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu tmp_CXXFLAGS=$CXXFLAGS CXXFLAGS="$CXXFLAGS -fvisibility=hidden" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler supports __attribute__((visibility(\"default\")))" >&5 printf %s "checking if compiler supports __attribute__((visibility(\"default\")))... " >&6; } if test ${cc_cv_attribute_visibility+y} then : printf %s "(cached) " >&6 else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ void __attribute__((visibility("default"))) visibility_function() { } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : cc_cv_attribute_visibility=yes else case e in #( e) cc_cv_attribute_visibility=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cc_cv_attribute_visibility" >&5 printf "%s\n" "$cc_cv_attribute_visibility" >&6; } CXXFLAGS=$tmp_CXXFLAGS ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test "x$cc_cv_attribute_visibility" = "xyes"; then printf "%s\n" "#define SUPPORT_ATTRIBUTE_VISIBILITY 1" >>confdefs.h CXXFLAGS="$CXXFLAGS -fvisibility=hidden" else true fi fi else case e in #( e) ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu tmp_CXXFLAGS=$CXXFLAGS CXXFLAGS="$CXXFLAGS -fvisibility=hidden" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler supports __attribute__((visibility(\"default\")))" >&5 printf %s "checking if compiler supports __attribute__((visibility(\"default\")))... " >&6; } if test ${cc_cv_attribute_visibility+y} then : printf %s "(cached) " >&6 else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ void __attribute__((visibility("default"))) visibility_function() { } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : cc_cv_attribute_visibility=yes else case e in #( e) cc_cv_attribute_visibility=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cc_cv_attribute_visibility" >&5 printf "%s\n" "$cc_cv_attribute_visibility" >&6; } CXXFLAGS=$tmp_CXXFLAGS ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test "x$cc_cv_attribute_visibility" = "xyes"; then printf "%s\n" "#define SUPPORT_ATTRIBUTE_VISIBILITY 1" >>confdefs.h CXXFLAGS="$CXXFLAGS -fvisibility=hidden" else true fi ;; esac fi # Check whether --enable-execinfo was given. if test ${enable_execinfo+y} then : enableval=$enable_execinfo; if test "$enableval" = "yes"; then ac_fn_c_check_header_compile "$LINENO" "execinfo.h" "ac_cv_header_execinfo_h" "$ac_includes_default" if test "x$ac_cv_header_execinfo_h" = xyes then : printf "%s\n" "#define HAVE_EXECINFO_H 1" >>confdefs.h fi if test x"$ac_cv_header_execinfo_h" = xyes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size parameter type for backtrace()" >&5 printf %s "checking size parameter type for backtrace()... " >&6; } if test ${ax_cv_proto_backtrace_type+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu for ax_cv_proto_backtrace_type in size_t int none; do if test "${ax_cv_proto_backtrace_type}" = none then : ax_cv_proto_backtrace_type= ; break fi cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include extern ${ax_cv_proto_backtrace_type} backtrace(void **addrlist, ${ax_cv_proto_backtrace_type} len); char **backtrace_symbols(void *const *buffer, ${ax_cv_proto_backtrace_type} size); int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : break fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext done ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_proto_backtrace_type" >&5 printf "%s\n" "$ax_cv_proto_backtrace_type" >&6; } fi if test x${ax_cv_proto_backtrace_type} != x then : printf "%s\n" "#define backtrace_size_t $ax_cv_proto_backtrace_type" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing backtrace" >&5 printf %s "checking for library containing backtrace... " >&6; } if test ${ac_cv_search_backtrace+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. The 'extern "C"' is for builds by C++ compilers; although this is not generally supported in C code supporting it here has little cost and some practical benefit (sr 110532). */ #ifdef __cplusplus extern "C" #endif char backtrace (void); int main (void) { return backtrace (); ; return 0; } _ACEOF for ac_lib in '' execinfo do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO" then : ac_cv_search_backtrace=$ac_res fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext if test ${ac_cv_search_backtrace+y} then : break fi done if test ${ac_cv_search_backtrace+y} then : else case e in #( e) ac_cv_search_backtrace=no ;; esac fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_backtrace" >&5 printf "%s\n" "$ac_cv_search_backtrace" >&6; } ac_res=$ac_cv_search_backtrace if test "$ac_res" != no then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi if test x"${ax_cv_proto_backtrace_type}" != x -a x"$ac_cv_header_execinfo_h" = xyes -a x"$ac_cv_search_backtrace" != xno then : printf "%s\n" "#define HAVE_BACKTRACE 1" >>confdefs.h fi fi else case e in #( e) ac_fn_c_check_header_compile "$LINENO" "execinfo.h" "ac_cv_header_execinfo_h" "$ac_includes_default" if test "x$ac_cv_header_execinfo_h" = xyes then : printf "%s\n" "#define HAVE_EXECINFO_H 1" >>confdefs.h fi if test x"$ac_cv_header_execinfo_h" = xyes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size parameter type for backtrace()" >&5 printf %s "checking size parameter type for backtrace()... " >&6; } if test ${ax_cv_proto_backtrace_type+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu for ax_cv_proto_backtrace_type in size_t int none; do if test "${ax_cv_proto_backtrace_type}" = none then : ax_cv_proto_backtrace_type= ; break fi cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include extern ${ax_cv_proto_backtrace_type} backtrace(void **addrlist, ${ax_cv_proto_backtrace_type} len); char **backtrace_symbols(void *const *buffer, ${ax_cv_proto_backtrace_type} size); int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : break fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext done ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_proto_backtrace_type" >&5 printf "%s\n" "$ax_cv_proto_backtrace_type" >&6; } fi if test x${ax_cv_proto_backtrace_type} != x then : printf "%s\n" "#define backtrace_size_t $ax_cv_proto_backtrace_type" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing backtrace" >&5 printf %s "checking for library containing backtrace... " >&6; } if test ${ac_cv_search_backtrace+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. The 'extern "C"' is for builds by C++ compilers; although this is not generally supported in C code supporting it here has little cost and some practical benefit (sr 110532). */ #ifdef __cplusplus extern "C" #endif char backtrace (void); int main (void) { return backtrace (); ; return 0; } _ACEOF for ac_lib in '' execinfo do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO" then : ac_cv_search_backtrace=$ac_res fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext if test ${ac_cv_search_backtrace+y} then : break fi done if test ${ac_cv_search_backtrace+y} then : else case e in #( e) ac_cv_search_backtrace=no ;; esac fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_backtrace" >&5 printf "%s\n" "$ac_cv_search_backtrace" >&6; } ac_res=$ac_cv_search_backtrace if test "$ac_res" != no then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi if test x"${ax_cv_proto_backtrace_type}" != x -a x"$ac_cv_header_execinfo_h" = xyes -a x"$ac_cv_search_backtrace" != xno then : printf "%s\n" "#define HAVE_BACKTRACE 1" >>confdefs.h fi ;; esac fi if test "x$use_kqueue" != "xyes" && test "x$use_epoll" != "xyes"; then as_fn_error $? "Must enable at least one of either kqueue or epoll" "$LINENO" 5 fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 printf %s "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if test ${ac_cv_prog_CPP+y} then : printf %s "(cached) " >&6 else case e in #( e) # Double quotes because $CC needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" cpp /lib/cpp do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO" then : else case e in #( e) # Broken: fails on valid input. continue ;; esac fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO" then : # Broken: success on invalid input. continue else case e in #( e) # Passes both tests. ac_preproc_ok=: break ;; esac fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of 'break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok then : break fi done ac_cv_prog_CPP=$CPP ;; esac fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 printf "%s\n" "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO" then : else case e in #( e) # Broken: fails on valid input. continue ;; esac fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO" then : # Broken: success on invalid input. continue else case e in #( e) # Passes both tests. ac_preproc_ok=: break ;; esac fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of 'break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok then : else case e in #( e) { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See 'config.log' for more details" "$LINENO" 5; } ;; esac fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for egrep -e" >&5 printf %s "checking for egrep -e... " >&6; } if test ${ac_cv_path_EGREP_TRADITIONAL+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -z "$EGREP_TRADITIONAL"; then ac_path_EGREP_TRADITIONAL_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_prog in grep ggrep do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP_TRADITIONAL="$as_dir$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP_TRADITIONAL" || continue # Check for GNU ac_path_EGREP_TRADITIONAL and select it if it is found. # Check for GNU $ac_path_EGREP_TRADITIONAL case `"$ac_path_EGREP_TRADITIONAL" --version 2>&1` in #( *GNU*) ac_cv_path_EGREP_TRADITIONAL="$ac_path_EGREP_TRADITIONAL" ac_path_EGREP_TRADITIONAL_found=:;; #( *) ac_count=0 printf %s 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" printf "%s\n" 'EGREP_TRADITIONAL' >> "conftest.nl" "$ac_path_EGREP_TRADITIONAL" -E 'EGR(EP|AC)_TRADITIONAL$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_TRADITIONAL_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP_TRADITIONAL="$ac_path_EGREP_TRADITIONAL" ac_path_EGREP_TRADITIONAL_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_TRADITIONAL_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP_TRADITIONAL"; then : fi else ac_cv_path_EGREP_TRADITIONAL=$EGREP_TRADITIONAL fi if test "$ac_cv_path_EGREP_TRADITIONAL" then : ac_cv_path_EGREP_TRADITIONAL="$ac_cv_path_EGREP_TRADITIONAL -E" else case e in #( e) if test -z "$EGREP_TRADITIONAL"; then ac_path_EGREP_TRADITIONAL_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_prog in egrep do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP_TRADITIONAL="$as_dir$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP_TRADITIONAL" || continue # Check for GNU ac_path_EGREP_TRADITIONAL and select it if it is found. # Check for GNU $ac_path_EGREP_TRADITIONAL case `"$ac_path_EGREP_TRADITIONAL" --version 2>&1` in #( *GNU*) ac_cv_path_EGREP_TRADITIONAL="$ac_path_EGREP_TRADITIONAL" ac_path_EGREP_TRADITIONAL_found=:;; #( *) ac_count=0 printf %s 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" printf "%s\n" 'EGREP_TRADITIONAL' >> "conftest.nl" "$ac_path_EGREP_TRADITIONAL" 'EGR(EP|AC)_TRADITIONAL$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_TRADITIONAL_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP_TRADITIONAL="$ac_path_EGREP_TRADITIONAL" ac_path_EGREP_TRADITIONAL_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_TRADITIONAL_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP_TRADITIONAL"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP_TRADITIONAL=$EGREP_TRADITIONAL fi ;; esac fi ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP_TRADITIONAL" >&5 printf "%s\n" "$ac_cv_path_EGREP_TRADITIONAL" >&6; } EGREP_TRADITIONAL=$ac_cv_path_EGREP_TRADITIONAL ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ax_pthread_ok=no # We used to check for pthread.h first, but this fails if pthread.h # requires special compiler flags (e.g. on Tru64 or Sequent). # It gets checked for in the link test anyway. # First of all, check if the user has set any of the PTHREAD_LIBS, # etcetera environment variables, and if threads linking works using # them: if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then ax_pthread_save_CC="$CC" ax_pthread_save_CFLAGS="$CFLAGS" ax_pthread_save_LIBS="$LIBS" if test "x$PTHREAD_CC" != "x" then : CC="$PTHREAD_CC" fi if test "x$PTHREAD_CXX" != "x" then : CXX="$PTHREAD_CXX" fi CFLAGS="$CFLAGS $PTHREAD_CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS" >&5 printf %s "checking for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. The 'extern "C"' is for builds by C++ compilers; although this is not generally supported in C code supporting it here has little cost and some practical benefit (sr 110532). */ #ifdef __cplusplus extern "C" #endif char pthread_join (void); int main (void) { return pthread_join (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ax_pthread_ok=yes fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_ok" >&5 printf "%s\n" "$ax_pthread_ok" >&6; } if test "x$ax_pthread_ok" = "xno"; then PTHREAD_LIBS="" PTHREAD_CFLAGS="" fi CC="$ax_pthread_save_CC" CFLAGS="$ax_pthread_save_CFLAGS" LIBS="$ax_pthread_save_LIBS" fi # We must check for the threads library under a number of different # names; the ordering is very important because some systems # (e.g. DEC) have both -lpthread and -lpthreads, where one of the # libraries is broken (non-POSIX). # Create a list of thread flags to try. Items with a "," contain both # C compiler flags (before ",") and linker flags (after ","). Other items # starting with a "-" are C compiler flags, and remaining items are # library names, except for "none" which indicates that we try without # any flags at all, and "pthread-config" which is a program returning # the flags for the Pth emulation library. ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" # The ordering *is* (sometimes) important. Some notes on the # individual items follow: # pthreads: AIX (must check this before -lpthread) # none: in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) # -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64 # (Note: HP C rejects this with "bad form for `-t' option") # -pthreads: Solaris/gcc (Note: HP C also rejects) # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it # doesn't hurt to check since this sometimes defines pthreads and # -D_REENTRANT too), HP C (must be checked before -lpthread, which # is present but should not be used directly; and before -mthreads, # because the compiler interprets this as "-mt" + "-hreads") # -mthreads: Mingw32/gcc, Lynx/gcc # pthread: Linux, etcetera # --thread-safe: KAI C++ # pthread-config: use pthread-config program (for GNU Pth library) case $host_os in freebsd*) # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) ax_pthread_flags="-kthread lthread $ax_pthread_flags" ;; hpux*) # From the cc(1) man page: "[-mt] Sets various -D flags to enable # multi-threading and also sets -lpthread." ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags" ;; openedition*) # IBM z/OS requires a feature-test macro to be defined in order to # enable POSIX threads at all, so give the user a hint if this is # not set. (We don't define these ourselves, as they can affect # other portions of the system API in unpredictable ways.) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ # if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS) AX_PTHREAD_ZOS_MISSING # endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP_TRADITIONAL "AX_PTHREAD_ZOS_MISSING" >/dev/null 2>&1 then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support." >&5 printf "%s\n" "$as_me: WARNING: IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support." >&2;} fi rm -rf conftest* ;; solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based # tests will erroneously succeed. (N.B.: The stubs are missing # pthread_cleanup_push, or rather a function called by this macro, # so we could check for that, but who knows whether they'll stub # that too in a future libc.) So we'll check first for the # standard Solaris way of linking pthreads (-mt -lpthread). ax_pthread_flags="-mt,-lpthread pthread $ax_pthread_flags" ;; esac # Are we compiling with Clang? { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC is Clang" >&5 printf %s "checking whether $CC is Clang... " >&6; } if test ${ax_cv_PTHREAD_CLANG+y} then : printf %s "(cached) " >&6 else case e in #( e) ax_cv_PTHREAD_CLANG=no # Note that Autoconf sets GCC=yes for Clang as well as GCC if test "x$GCC" = "xyes"; then cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Note: Clang 2.7 lacks __clang_[a-z]+__ */ # if defined(__clang__) && defined(__llvm__) AX_PTHREAD_CC_IS_CLANG # endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP_TRADITIONAL "AX_PTHREAD_CC_IS_CLANG" >/dev/null 2>&1 then : ax_cv_PTHREAD_CLANG=yes fi rm -rf conftest* fi ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_CLANG" >&5 printf "%s\n" "$ax_cv_PTHREAD_CLANG" >&6; } ax_pthread_clang="$ax_cv_PTHREAD_CLANG" # GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC) # Note that for GCC and Clang -pthread generally implies -lpthread, # except when -nostdlib is passed. # This is problematic using libtool to build C++ shared libraries with pthread: # [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25460 # [2] https://bugzilla.redhat.com/show_bug.cgi?id=661333 # [3] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=468555 # To solve this, first try -pthread together with -lpthread for GCC if test "x$GCC" = "xyes" then : ax_pthread_flags="-pthread,-lpthread -pthread -pthreads $ax_pthread_flags" fi # Clang takes -pthread (never supported any other flag), but we'll try with -lpthread first if test "x$ax_pthread_clang" = "xyes" then : ax_pthread_flags="-pthread,-lpthread -pthread" fi # The presence of a feature test macro requesting re-entrant function # definitions is, on some systems, a strong hint that pthreads support is # correctly enabled case $host_os in darwin* | hpux* | linux* | osf* | solaris*) ax_pthread_check_macro="_REENTRANT" ;; aix*) ax_pthread_check_macro="_THREAD_SAFE" ;; *) ax_pthread_check_macro="--" ;; esac if test "x$ax_pthread_check_macro" = "x--" then : ax_pthread_check_cond=0 else case e in #( e) ax_pthread_check_cond="!defined($ax_pthread_check_macro)" ;; esac fi if test "x$ax_pthread_ok" = "xno"; then for ax_pthread_try_flag in $ax_pthread_flags; do case $ax_pthread_try_flag in none) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether pthreads work without any flags" >&5 printf %s "checking whether pthreads work without any flags... " >&6; } ;; *,*) PTHREAD_CFLAGS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\1/"` PTHREAD_LIBS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\2/"` { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with \"$PTHREAD_CFLAGS\" and \"$PTHREAD_LIBS\"" >&5 printf %s "checking whether pthreads work with \"$PTHREAD_CFLAGS\" and \"$PTHREAD_LIBS\"... " >&6; } ;; -*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with $ax_pthread_try_flag" >&5 printf %s "checking whether pthreads work with $ax_pthread_try_flag... " >&6; } PTHREAD_CFLAGS="$ax_pthread_try_flag" ;; pthread-config) # Extract the first word of "pthread-config", so it can be a program name with args. set dummy pthread-config; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ax_pthread_config+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$ax_pthread_config"; then ac_cv_prog_ax_pthread_config="$ax_pthread_config" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ax_pthread_config="yes" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_ax_pthread_config" && ac_cv_prog_ax_pthread_config="no" fi ;; esac fi ax_pthread_config=$ac_cv_prog_ax_pthread_config if test -n "$ax_pthread_config"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_config" >&5 printf "%s\n" "$ax_pthread_config" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ax_pthread_config" = "xno" then : continue fi PTHREAD_CFLAGS="`pthread-config --cflags`" PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" ;; *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for the pthreads library -l$ax_pthread_try_flag" >&5 printf %s "checking for the pthreads library -l$ax_pthread_try_flag... " >&6; } PTHREAD_LIBS="-l$ax_pthread_try_flag" ;; esac ax_pthread_save_CFLAGS="$CFLAGS" ax_pthread_save_LIBS="$LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" # Check for various functions. We must include pthread.h, # since some functions may be macros. (On the Sequent, we # need a special flag -Kthread to make this header compile.) # We check for pthread_join because it is in -lpthread on IRIX # while pthread_create is in libc. We check for pthread_attr_init # due to DEC craziness with -lpthreads. We check for # pthread_cleanup_push because it is one of the few pthread # functions on Solaris that doesn't have a non-functional libc stub. # We try pthread_create on general principles. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include # if $ax_pthread_check_cond # error "$ax_pthread_check_macro must be defined" # endif static void *some_global = NULL; static void routine(void *a) { /* To avoid any unused-parameter or unused-but-set-parameter warning. */ some_global = a; } static void *start_routine(void *a) { return a; } int main (void) { pthread_t th; pthread_attr_t attr; pthread_create(&th, 0, start_routine, 0); pthread_join(th, 0); pthread_attr_init(&attr); pthread_cleanup_push(routine, 0); pthread_cleanup_pop(0) /* ; */ ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ax_pthread_ok=yes fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext CFLAGS="$ax_pthread_save_CFLAGS" LIBS="$ax_pthread_save_LIBS" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_ok" >&5 printf "%s\n" "$ax_pthread_ok" >&6; } if test "x$ax_pthread_ok" = "xyes" then : break fi PTHREAD_LIBS="" PTHREAD_CFLAGS="" done fi # Clang needs special handling, because older versions handle the -pthread # option in a rather... idiosyncratic way if test "x$ax_pthread_clang" = "xyes"; then # Clang takes -pthread; it has never supported any other flag # (Note 1: This will need to be revisited if a system that Clang # supports has POSIX threads in a separate library. This tends not # to be the way of modern systems, but it's conceivable.) # (Note 2: On some systems, notably Darwin, -pthread is not needed # to get POSIX threads support; the API is always present and # active. We could reasonably leave PTHREAD_CFLAGS empty. But # -pthread does define _REENTRANT, and while the Darwin headers # ignore this macro, third-party headers might not.) # However, older versions of Clang make a point of warning the user # that, in an invocation where only linking and no compilation is # taking place, the -pthread option has no effect ("argument unused # during compilation"). They expect -pthread to be passed in only # when source code is being compiled. # # Problem is, this is at odds with the way Automake and most other # C build frameworks function, which is that the same flags used in # compilation (CFLAGS) are also used in linking. Many systems # supported by AX_PTHREAD require exactly this for POSIX threads # support, and in fact it is often not straightforward to specify a # flag that is used only in the compilation phase and not in # linking. Such a scenario is extremely rare in practice. # # Even though use of the -pthread flag in linking would only print # a warning, this can be a nuisance for well-run software projects # that build with -Werror. So if the active version of Clang has # this misfeature, we search for an option to squash it. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether Clang needs flag to prevent \"argument unused\" warning when linking with -pthread" >&5 printf %s "checking whether Clang needs flag to prevent \"argument unused\" warning when linking with -pthread... " >&6; } if test ${ax_cv_PTHREAD_CLANG_NO_WARN_FLAG+y} then : printf %s "(cached) " >&6 else case e in #( e) ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown # Create an alternate version of $ac_link that compiles and # links in two steps (.c -> .o, .o -> exe) instead of one # (.c -> exe), because the warning occurs only in the second # step ax_pthread_save_ac_link="$ac_link" ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g' ax_pthread_link_step=`printf "%s\n" "$ac_link" | sed "$ax_pthread_sed"` ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)" ax_pthread_save_CFLAGS="$CFLAGS" for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do if test "x$ax_pthread_try" = "xunknown" then : break fi CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS" ac_link="$ax_pthread_save_ac_link" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main(void){return 0;} _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_link="$ax_pthread_2step_ac_link" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main(void){return 0;} _ACEOF if ac_fn_c_try_link "$LINENO" then : break fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext done ac_link="$ax_pthread_save_ac_link" CFLAGS="$ax_pthread_save_CFLAGS" if test "x$ax_pthread_try" = "x" then : ax_pthread_try=no fi ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try" ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" >&5 printf "%s\n" "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" >&6; } case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in no | unknown) ;; *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;; esac fi # $ax_pthread_clang = yes # Various other checks: if test "x$ax_pthread_ok" = "xyes"; then ax_pthread_save_CFLAGS="$CFLAGS" ax_pthread_save_LIBS="$LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for joinable pthread attribute" >&5 printf %s "checking for joinable pthread attribute... " >&6; } if test ${ax_cv_PTHREAD_JOINABLE_ATTR+y} then : printf %s "(cached) " >&6 else case e in #( e) ax_cv_PTHREAD_JOINABLE_ATTR=unknown for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { int attr = $ax_pthread_attr; return attr /* ; */ ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext done ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_JOINABLE_ATTR" >&5 printf "%s\n" "$ax_cv_PTHREAD_JOINABLE_ATTR" >&6; } if test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \ test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \ test "x$ax_pthread_joinable_attr_defined" != "xyes" then : printf "%s\n" "#define PTHREAD_CREATE_JOINABLE $ax_cv_PTHREAD_JOINABLE_ATTR" >>confdefs.h ax_pthread_joinable_attr_defined=yes fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether more special flags are required for pthreads" >&5 printf %s "checking whether more special flags are required for pthreads... " >&6; } if test ${ax_cv_PTHREAD_SPECIAL_FLAGS+y} then : printf %s "(cached) " >&6 else case e in #( e) ax_cv_PTHREAD_SPECIAL_FLAGS=no case $host_os in solaris*) ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS" ;; esac ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_SPECIAL_FLAGS" >&5 printf "%s\n" "$ax_cv_PTHREAD_SPECIAL_FLAGS" >&6; } if test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \ test "x$ax_pthread_special_flags_added" != "xyes" then : PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS" ax_pthread_special_flags_added=yes fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for PTHREAD_PRIO_INHERIT" >&5 printf %s "checking for PTHREAD_PRIO_INHERIT... " >&6; } if test ${ax_cv_PTHREAD_PRIO_INHERIT+y} then : printf %s "(cached) " >&6 else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { int i = PTHREAD_PRIO_INHERIT; return i; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ax_cv_PTHREAD_PRIO_INHERIT=yes else case e in #( e) ax_cv_PTHREAD_PRIO_INHERIT=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_PRIO_INHERIT" >&5 printf "%s\n" "$ax_cv_PTHREAD_PRIO_INHERIT" >&6; } if test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \ test "x$ax_pthread_prio_inherit_defined" != "xyes" then : printf "%s\n" "#define HAVE_PTHREAD_PRIO_INHERIT 1" >>confdefs.h ax_pthread_prio_inherit_defined=yes fi CFLAGS="$ax_pthread_save_CFLAGS" LIBS="$ax_pthread_save_LIBS" # More AIX lossage: compile with *_r variant if test "x$GCC" != "xyes"; then case $host_os in aix*) case "x/$CC" in #( x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6) : #handle absolute path differently from PATH based program lookup case "x$CC" in #( x/*) : if as_fn_executable_p ${CC}_r then : PTHREAD_CC="${CC}_r" fi if test "x${CXX}" != "x" then : if as_fn_executable_p ${CXX}_r then : PTHREAD_CXX="${CXX}_r" fi fi ;; #( *) : for ac_prog in ${CC}_r do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_PTHREAD_CC+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$PTHREAD_CC"; then ac_cv_prog_PTHREAD_CC="$PTHREAD_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_PTHREAD_CC="$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi PTHREAD_CC=$ac_cv_prog_PTHREAD_CC if test -n "$PTHREAD_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PTHREAD_CC" >&5 printf "%s\n" "$PTHREAD_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$PTHREAD_CC" && break done test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" if test "x${CXX}" != "x" then : for ac_prog in ${CXX}_r do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_PTHREAD_CXX+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$PTHREAD_CXX"; then ac_cv_prog_PTHREAD_CXX="$PTHREAD_CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_PTHREAD_CXX="$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi PTHREAD_CXX=$ac_cv_prog_PTHREAD_CXX if test -n "$PTHREAD_CXX"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PTHREAD_CXX" >&5 printf "%s\n" "$PTHREAD_CXX" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$PTHREAD_CXX" && break done test -n "$PTHREAD_CXX" || PTHREAD_CXX="$CXX" fi ;; esac ;; #( *) : ;; esac ;; esac fi fi test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" test -n "$PTHREAD_CXX" || PTHREAD_CXX="$CXX" # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: if test "x$ax_pthread_ok" = "xyes"; then printf "%s\n" "#define HAVE_PTHREAD 1" >>confdefs.h : else ax_pthread_ok=no fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether std::atomic can be used without link library" >&5 printf %s "checking whether std::atomic can be used without link library... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main() { std::atomic a{}; int64_t v = 5; int64_t r = a.fetch_add(v); return static_cast(r); } _ACEOF if ac_fn_cxx_try_link "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether std::atomic needs -latomic" >&5 printf %s "checking whether std::atomic needs -latomic... " >&6; } OLD_LIBS="$LIBS" LIBS="$LIBS -latomic" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main() { std::atomic a{}; int64_t v = 5; int64_t r = a.fetch_add(v); return static_cast(r); } _ACEOF if ac_fn_cxx_try_link "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error $? "cannot figure out how to use std::atomic See 'config.log' for more details" "$LINENO" 5; } ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS="$OLD_LIBS" ATOMIC_LIBS="-latomic" ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_PKG_CONFIG+y} then : printf %s "(cached) " >&6 else case e in #( e) case $PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_PKG_CONFIG="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac ;; esac fi PKG_CONFIG=$ac_cv_path_PKG_CONFIG if test -n "$PKG_CONFIG"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 printf "%s\n" "$PKG_CONFIG" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_path_PKG_CONFIG"; then ac_pt_PKG_CONFIG=$PKG_CONFIG # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_ac_pt_PKG_CONFIG+y} then : printf %s "(cached) " >&6 else case e in #( e) case $ac_pt_PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_ac_pt_PKG_CONFIG="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac ;; esac fi ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG if test -n "$ac_pt_PKG_CONFIG"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 printf "%s\n" "$ac_pt_PKG_CONFIG" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_pt_PKG_CONFIG" = x; then PKG_CONFIG="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac PKG_CONFIG=$ac_pt_PKG_CONFIG fi else PKG_CONFIG="$ac_cv_path_PKG_CONFIG" fi fi if test -n "$PKG_CONFIG"; then _pkg_min_version=0.9.0 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 printf %s "checking pkg-config is at least version $_pkg_min_version... " >&6; } if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } PKG_CONFIG="" fi fi if test -z "$PKG_CONFIG"; then as_fn_error $? "pkg-config not found" "$LINENO" 5 fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC options needed to detect all undeclared functions" >&5 printf %s "checking for $CC options needed to detect all undeclared functions... " >&6; } if test ${ac_cv_c_undeclared_builtin_options+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_save_CFLAGS=$CFLAGS ac_cv_c_undeclared_builtin_options='cannot detect' for ac_arg in '' -fno-builtin; do CFLAGS="$ac_save_CFLAGS $ac_arg" # This test program should *not* compile successfully. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { (void) strchr; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : else case e in #( e) # This test program should compile successfully. # No library function is consistently available on # freestanding implementations, so test against a dummy # declaration. Include always-available headers on the # off chance that they somehow elicit warnings. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include extern void ac_decl (int, char *); int main (void) { (void) ac_decl (0, (char *) 0); (void) ac_decl; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : if test x"$ac_arg" = x then : ac_cv_c_undeclared_builtin_options='none needed' else case e in #( e) ac_cv_c_undeclared_builtin_options=$ac_arg ;; esac fi break fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext done CFLAGS=$ac_save_CFLAGS ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_undeclared_builtin_options" >&5 printf "%s\n" "$ac_cv_c_undeclared_builtin_options" >&6; } case $ac_cv_c_undeclared_builtin_options in #( 'cannot detect') : { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error $? "cannot make $CC report undeclared builtins See 'config.log' for more details" "$LINENO" 5; } ;; #( 'none needed') : ac_c_undeclared_builtin_options='' ;; #( *) : ac_c_undeclared_builtin_options=$ac_cv_c_undeclared_builtin_options ;; esac pkg_failed=no { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libcurl" >&5 printf %s "checking for libcurl... " >&6; } if test -n "$LIBCURL_CFLAGS"; then pkg_cv_LIBCURL_CFLAGS="$LIBCURL_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libcurl\""; } >&5 ($PKG_CONFIG --exists --print-errors "libcurl") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_LIBCURL_CFLAGS=`$PKG_CONFIG --cflags "libcurl" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$LIBCURL_LIBS"; then pkg_cv_LIBCURL_LIBS="$LIBCURL_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libcurl\""; } >&5 ($PKG_CONFIG --exists --print-errors "libcurl") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_LIBCURL_LIBS=`$PKG_CONFIG --libs "libcurl" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then LIBCURL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libcurl" 2>&1` else LIBCURL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libcurl" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$LIBCURL_PKG_ERRORS" >&5 # Check whether --with-libcurl was given. if test ${with_libcurl+y} then : withval=$with_libcurl; _libcurl_with=$withval else case e in #( e) _libcurl_with=yes ;; esac fi if test "$_libcurl_with" != "no" ; then for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_AWK+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 printf "%s\n" "$AWK" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$AWK" && break done _libcurl_version_parse="eval $AWK '{split(\$NF,A,\".\"); X=256*256*A[1]+256*A[2]+A[3]; print X;}'" _libcurl_try_link=yes if test -d "$_libcurl_with" ; then LIBCURL_CPPFLAGS="-I$withval/include" _libcurl_ldflags="-L$withval/lib" # Extract the first word of "curl-config", so it can be a program name with args. set dummy curl-config; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path__libcurl_config+y} then : printf %s "(cached) " >&6 else case e in #( e) case $_libcurl_config in [\\/]* | ?:[\\/]*) ac_cv_path__libcurl_config="$_libcurl_config" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in "$withval/bin" do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path__libcurl_config="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac ;; esac fi _libcurl_config=$ac_cv_path__libcurl_config if test -n "$_libcurl_config"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $_libcurl_config" >&5 printf "%s\n" "$_libcurl_config" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi else # Extract the first word of "curl-config", so it can be a program name with args. set dummy curl-config; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path__libcurl_config+y} then : printf %s "(cached) " >&6 else case e in #( e) case $_libcurl_config in [\\/]* | ?:[\\/]*) ac_cv_path__libcurl_config="$_libcurl_config" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path__libcurl_config="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac ;; esac fi _libcurl_config=$ac_cv_path__libcurl_config if test -n "$_libcurl_config"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $_libcurl_config" >&5 printf "%s\n" "$_libcurl_config" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test x$_libcurl_config != "x" ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for the version of libcurl" >&5 printf %s "checking for the version of libcurl... " >&6; } if test ${libcurl_cv_lib_curl_version+y} then : printf %s "(cached) " >&6 else case e in #( e) libcurl_cv_lib_curl_version=`$_libcurl_config --version | $AWK '{print $2}'` ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libcurl_cv_lib_curl_version" >&5 printf "%s\n" "$libcurl_cv_lib_curl_version" >&6; } _libcurl_version=`echo $libcurl_cv_lib_curl_version | $_libcurl_version_parse` _libcurl_wanted=`echo 0 | $_libcurl_version_parse` if test $_libcurl_wanted -gt 0 ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libcurl >= version " >&5 printf %s "checking for libcurl >= version ... " >&6; } if test ${libcurl_cv_lib_version_ok+y} then : printf %s "(cached) " >&6 else case e in #( e) if test $_libcurl_version -ge $_libcurl_wanted ; then libcurl_cv_lib_version_ok=yes else libcurl_cv_lib_version_ok=no fi ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libcurl_cv_lib_version_ok" >&5 printf "%s\n" "$libcurl_cv_lib_version_ok" >&6; } fi if test $_libcurl_wanted -eq 0 || test x$libcurl_cv_lib_version_ok = xyes ; then if test x"$LIBCURL_CPPFLAGS" = "x" ; then LIBCURL_CPPFLAGS=`$_libcurl_config --cflags` fi if test x"$LIBCURL" = "x" ; then LIBCURL=`$_libcurl_config --libs` # This is so silly, but Apple actually has a bug in their # curl-config script. Fixed in Tiger, but there are still # lots of Panther installs around. case "${host}" in powerpc-apple-darwin7*) LIBCURL=`echo $LIBCURL | sed -e 's|-arch i386||g'` ;; esac fi # All curl-config scripts support --feature _libcurl_features=`$_libcurl_config --feature` # Is it modern enough to have --protocols? (7.12.4) if test $_libcurl_version -ge 461828 ; then _libcurl_protocols=`$_libcurl_config --protocols` fi else _libcurl_try_link=no fi unset _libcurl_wanted fi if test $_libcurl_try_link = yes ; then # we did not find curl-config, so let's see if the user-supplied # link line (or failing that, "-lcurl") is enough. LIBCURL=${LIBCURL-"$_libcurl_ldflags -lcurl"} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether libcurl is usable" >&5 printf %s "checking whether libcurl is usable... " >&6; } if test ${libcurl_cv_lib_curl_usable+y} then : printf %s "(cached) " >&6 else case e in #( e) _libcurl_save_cppflags=$CPPFLAGS CPPFLAGS="$LIBCURL_CPPFLAGS $CPPFLAGS" _libcurl_save_libs=$LIBS LIBS="$LIBCURL $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { /* Try to use a few common options to force a failure if we are missing symbols or cannot link. */ int x; curl_easy_setopt(NULL,CURLOPT_URL,NULL); x=CURL_ERROR_SIZE; x=CURLOPT_WRITEFUNCTION; x=CURLOPT_WRITEDATA; x=CURLOPT_ERRORBUFFER; x=CURLOPT_STDERR; x=CURLOPT_VERBOSE; if (x) {;} ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : libcurl_cv_lib_curl_usable=yes else case e in #( e) libcurl_cv_lib_curl_usable=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext CPPFLAGS=$_libcurl_save_cppflags LIBS=$_libcurl_save_libs unset _libcurl_save_cppflags unset _libcurl_save_libs ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libcurl_cv_lib_curl_usable" >&5 printf "%s\n" "$libcurl_cv_lib_curl_usable" >&6; } if test $libcurl_cv_lib_curl_usable = yes ; then # Does curl_free() exist in this version of libcurl? # If not, fake it with free() _libcurl_save_cppflags=$CPPFLAGS CPPFLAGS="$CPPFLAGS $LIBCURL_CPPFLAGS" _libcurl_save_libs=$LIBS LIBS="$LIBS $LIBCURL" ac_fn_check_decl "$LINENO" "curl_free" "ac_cv_have_decl_curl_free" "#include " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_curl_free" = xyes then : else case e in #( e) printf "%s\n" "#define curl_free free" >>confdefs.h ;; esac fi CPPFLAGS=$_libcurl_save_cppflags LIBS=$_libcurl_save_libs unset _libcurl_save_cppflags unset _libcurl_save_libs printf "%s\n" "#define HAVE_LIBCURL 1" >>confdefs.h for _libcurl_feature in $_libcurl_features ; do cat >>confdefs.h <<_ACEOF #define `printf "%s\n" "libcurl_feature_$_libcurl_feature" | sed "$as_sed_cpp"` 1 _ACEOF eval `printf "%s\n" "libcurl_feature_$_libcurl_feature" | sed "$as_sed_sh"`=yes done if test "x$_libcurl_protocols" = "x" ; then # We do not have --protocols, so just assume that all # protocols are available _libcurl_protocols="HTTP FTP FILE TELNET LDAP DICT TFTP" if test x$libcurl_feature_SSL = xyes ; then _libcurl_protocols="$_libcurl_protocols HTTPS" # FTPS was not standards-compliant until version # 7.11.0 (0x070b00 == 461568) if test $_libcurl_version -ge 461568; then _libcurl_protocols="$_libcurl_protocols FTPS" fi fi # RTSP, IMAP, POP3 and SMTP were added in # 7.20.0 (0x071400 == 463872) if test $_libcurl_version -ge 463872; then _libcurl_protocols="$_libcurl_protocols RTSP IMAP POP3 SMTP" fi fi for _libcurl_protocol in $_libcurl_protocols ; do cat >>confdefs.h <<_ACEOF #define `printf "%s\n" "libcurl_protocol_$_libcurl_protocol" | sed "$as_sed_cpp"` 1 _ACEOF eval `printf "%s\n" "libcurl_protocol_$_libcurl_protocol" | sed "$as_sed_sh"`=yes done else unset LIBCURL unset LIBCURL_CPPFLAGS fi fi unset _libcurl_try_link unset _libcurl_version_parse unset _libcurl_config unset _libcurl_feature unset _libcurl_features unset _libcurl_protocol unset _libcurl_protocols unset _libcurl_version unset _libcurl_ldflags fi if test x$_libcurl_with = xno || test x$libcurl_cv_lib_curl_usable != xyes ; then # This is the IF-NO path : else # This is the IF-YES path : fi unset _libcurl_with elif test $pkg_failed = untried; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } # Check whether --with-libcurl was given. if test ${with_libcurl+y} then : withval=$with_libcurl; _libcurl_with=$withval else case e in #( e) _libcurl_with=yes ;; esac fi if test "$_libcurl_with" != "no" ; then for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_AWK+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 printf "%s\n" "$AWK" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$AWK" && break done _libcurl_version_parse="eval $AWK '{split(\$NF,A,\".\"); X=256*256*A[1]+256*A[2]+A[3]; print X;}'" _libcurl_try_link=yes if test -d "$_libcurl_with" ; then LIBCURL_CPPFLAGS="-I$withval/include" _libcurl_ldflags="-L$withval/lib" # Extract the first word of "curl-config", so it can be a program name with args. set dummy curl-config; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path__libcurl_config+y} then : printf %s "(cached) " >&6 else case e in #( e) case $_libcurl_config in [\\/]* | ?:[\\/]*) ac_cv_path__libcurl_config="$_libcurl_config" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in "$withval/bin" do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path__libcurl_config="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac ;; esac fi _libcurl_config=$ac_cv_path__libcurl_config if test -n "$_libcurl_config"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $_libcurl_config" >&5 printf "%s\n" "$_libcurl_config" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi else # Extract the first word of "curl-config", so it can be a program name with args. set dummy curl-config; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path__libcurl_config+y} then : printf %s "(cached) " >&6 else case e in #( e) case $_libcurl_config in [\\/]* | ?:[\\/]*) ac_cv_path__libcurl_config="$_libcurl_config" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path__libcurl_config="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac ;; esac fi _libcurl_config=$ac_cv_path__libcurl_config if test -n "$_libcurl_config"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $_libcurl_config" >&5 printf "%s\n" "$_libcurl_config" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test x$_libcurl_config != "x" ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for the version of libcurl" >&5 printf %s "checking for the version of libcurl... " >&6; } if test ${libcurl_cv_lib_curl_version+y} then : printf %s "(cached) " >&6 else case e in #( e) libcurl_cv_lib_curl_version=`$_libcurl_config --version | $AWK '{print $2}'` ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libcurl_cv_lib_curl_version" >&5 printf "%s\n" "$libcurl_cv_lib_curl_version" >&6; } _libcurl_version=`echo $libcurl_cv_lib_curl_version | $_libcurl_version_parse` _libcurl_wanted=`echo 0 | $_libcurl_version_parse` if test $_libcurl_wanted -gt 0 ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libcurl >= version " >&5 printf %s "checking for libcurl >= version ... " >&6; } if test ${libcurl_cv_lib_version_ok+y} then : printf %s "(cached) " >&6 else case e in #( e) if test $_libcurl_version -ge $_libcurl_wanted ; then libcurl_cv_lib_version_ok=yes else libcurl_cv_lib_version_ok=no fi ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libcurl_cv_lib_version_ok" >&5 printf "%s\n" "$libcurl_cv_lib_version_ok" >&6; } fi if test $_libcurl_wanted -eq 0 || test x$libcurl_cv_lib_version_ok = xyes ; then if test x"$LIBCURL_CPPFLAGS" = "x" ; then LIBCURL_CPPFLAGS=`$_libcurl_config --cflags` fi if test x"$LIBCURL" = "x" ; then LIBCURL=`$_libcurl_config --libs` # This is so silly, but Apple actually has a bug in their # curl-config script. Fixed in Tiger, but there are still # lots of Panther installs around. case "${host}" in powerpc-apple-darwin7*) LIBCURL=`echo $LIBCURL | sed -e 's|-arch i386||g'` ;; esac fi # All curl-config scripts support --feature _libcurl_features=`$_libcurl_config --feature` # Is it modern enough to have --protocols? (7.12.4) if test $_libcurl_version -ge 461828 ; then _libcurl_protocols=`$_libcurl_config --protocols` fi else _libcurl_try_link=no fi unset _libcurl_wanted fi if test $_libcurl_try_link = yes ; then # we did not find curl-config, so let's see if the user-supplied # link line (or failing that, "-lcurl") is enough. LIBCURL=${LIBCURL-"$_libcurl_ldflags -lcurl"} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether libcurl is usable" >&5 printf %s "checking whether libcurl is usable... " >&6; } if test ${libcurl_cv_lib_curl_usable+y} then : printf %s "(cached) " >&6 else case e in #( e) _libcurl_save_cppflags=$CPPFLAGS CPPFLAGS="$LIBCURL_CPPFLAGS $CPPFLAGS" _libcurl_save_libs=$LIBS LIBS="$LIBCURL $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { /* Try to use a few common options to force a failure if we are missing symbols or cannot link. */ int x; curl_easy_setopt(NULL,CURLOPT_URL,NULL); x=CURL_ERROR_SIZE; x=CURLOPT_WRITEFUNCTION; x=CURLOPT_WRITEDATA; x=CURLOPT_ERRORBUFFER; x=CURLOPT_STDERR; x=CURLOPT_VERBOSE; if (x) {;} ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : libcurl_cv_lib_curl_usable=yes else case e in #( e) libcurl_cv_lib_curl_usable=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext CPPFLAGS=$_libcurl_save_cppflags LIBS=$_libcurl_save_libs unset _libcurl_save_cppflags unset _libcurl_save_libs ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libcurl_cv_lib_curl_usable" >&5 printf "%s\n" "$libcurl_cv_lib_curl_usable" >&6; } if test $libcurl_cv_lib_curl_usable = yes ; then # Does curl_free() exist in this version of libcurl? # If not, fake it with free() _libcurl_save_cppflags=$CPPFLAGS CPPFLAGS="$CPPFLAGS $LIBCURL_CPPFLAGS" _libcurl_save_libs=$LIBS LIBS="$LIBS $LIBCURL" ac_fn_check_decl "$LINENO" "curl_free" "ac_cv_have_decl_curl_free" "#include " "$ac_c_undeclared_builtin_options" "CFLAGS" if test "x$ac_cv_have_decl_curl_free" = xyes then : else case e in #( e) printf "%s\n" "#define curl_free free" >>confdefs.h ;; esac fi CPPFLAGS=$_libcurl_save_cppflags LIBS=$_libcurl_save_libs unset _libcurl_save_cppflags unset _libcurl_save_libs printf "%s\n" "#define HAVE_LIBCURL 1" >>confdefs.h for _libcurl_feature in $_libcurl_features ; do cat >>confdefs.h <<_ACEOF #define `printf "%s\n" "libcurl_feature_$_libcurl_feature" | sed "$as_sed_cpp"` 1 _ACEOF eval `printf "%s\n" "libcurl_feature_$_libcurl_feature" | sed "$as_sed_sh"`=yes done if test "x$_libcurl_protocols" = "x" ; then # We do not have --protocols, so just assume that all # protocols are available _libcurl_protocols="HTTP FTP FILE TELNET LDAP DICT TFTP" if test x$libcurl_feature_SSL = xyes ; then _libcurl_protocols="$_libcurl_protocols HTTPS" # FTPS was not standards-compliant until version # 7.11.0 (0x070b00 == 461568) if test $_libcurl_version -ge 461568; then _libcurl_protocols="$_libcurl_protocols FTPS" fi fi # RTSP, IMAP, POP3 and SMTP were added in # 7.20.0 (0x071400 == 463872) if test $_libcurl_version -ge 463872; then _libcurl_protocols="$_libcurl_protocols RTSP IMAP POP3 SMTP" fi fi for _libcurl_protocol in $_libcurl_protocols ; do cat >>confdefs.h <<_ACEOF #define `printf "%s\n" "libcurl_protocol_$_libcurl_protocol" | sed "$as_sed_cpp"` 1 _ACEOF eval `printf "%s\n" "libcurl_protocol_$_libcurl_protocol" | sed "$as_sed_sh"`=yes done else unset LIBCURL unset LIBCURL_CPPFLAGS fi fi unset _libcurl_try_link unset _libcurl_version_parse unset _libcurl_config unset _libcurl_feature unset _libcurl_features unset _libcurl_protocol unset _libcurl_protocols unset _libcurl_version unset _libcurl_ldflags fi if test x$_libcurl_with = xno || test x$libcurl_cv_lib_curl_usable != xyes ; then # This is the IF-NO path : else # This is the IF-YES path : fi unset _libcurl_with else LIBCURL_CFLAGS=$pkg_cv_LIBCURL_CFLAGS LIBCURL_LIBS=$pkg_cv_LIBCURL_LIBS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } fi pkg_failed=no { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for cppunit" >&5 printf %s "checking for cppunit... " >&6; } if test -n "$CPPUNIT_CFLAGS"; then pkg_cv_CPPUNIT_CFLAGS="$CPPUNIT_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"cppunit\""; } >&5 ($PKG_CONFIG --exists --print-errors "cppunit") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_CPPUNIT_CFLAGS=`$PKG_CONFIG --cflags "cppunit" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$CPPUNIT_LIBS"; then pkg_cv_CPPUNIT_LIBS="$CPPUNIT_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"cppunit\""; } >&5 ($PKG_CONFIG --exists --print-errors "cppunit") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_CPPUNIT_LIBS=`$PKG_CONFIG --libs "cppunit" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then CPPUNIT_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "cppunit" 2>&1` else CPPUNIT_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "cppunit" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$CPPUNIT_PKG_ERRORS" >&5 no_cppunit="yes" elif test $pkg_failed = untried; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } no_cppunit="yes" else CPPUNIT_CFLAGS=$pkg_cv_CPPUNIT_CFLAGS CPPUNIT_LIBS=$pkg_cv_CPPUNIT_LIBS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } fi pkg_failed=no { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for zlib" >&5 printf %s "checking for zlib... " >&6; } if test -n "$ZLIB_CFLAGS"; then pkg_cv_ZLIB_CFLAGS="$ZLIB_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"zlib\""; } >&5 ($PKG_CONFIG --exists --print-errors "zlib") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_ZLIB_CFLAGS=`$PKG_CONFIG --cflags "zlib" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$ZLIB_LIBS"; then pkg_cv_ZLIB_LIBS="$ZLIB_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"zlib\""; } >&5 ($PKG_CONFIG --exists --print-errors "zlib") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_ZLIB_LIBS=`$PKG_CONFIG --libs "zlib" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then ZLIB_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "zlib" 2>&1` else ZLIB_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "zlib" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$ZLIB_PKG_ERRORS" >&5 as_fn_error $? "Package requirements (zlib) were not met: $ZLIB_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. Alternatively, you may set the environment variables ZLIB_CFLAGS and ZLIB_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. Alternatively, you may set the environment variables ZLIB_CFLAGS and ZLIB_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details. To get pkg-config, see . See 'config.log' for more details" "$LINENO" 5; } else ZLIB_CFLAGS=$pkg_cv_ZLIB_CFLAGS ZLIB_LIBS=$pkg_cv_ZLIB_LIBS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } fi CFLAGS="$LIBCURL_CFLAGS $PTHREAD_CFLAGS $ZLIB_CFLAGS $CFLAGS" CXXFLAGS="$LIBCURL_CFLAGS $LIBCURL_CPPFLAGS $PTHREAD_CFLAGS $ZLIB_CFLAGS $CXXFLAGS" LIBS="$LIBCURL_LIBS $ATOMIC_LIBS $PTHREAD_LIBS $ZLIB_LIBS $LIBS" pkg_failed=no { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libcrypto" >&5 printf %s "checking for libcrypto... " >&6; } if test -n "$OPENSSL_CFLAGS"; then pkg_cv_OPENSSL_CFLAGS="$OPENSSL_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libcrypto\""; } >&5 ($PKG_CONFIG --exists --print-errors "libcrypto") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_OPENSSL_CFLAGS=`$PKG_CONFIG --cflags "libcrypto" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$OPENSSL_LIBS"; then pkg_cv_OPENSSL_LIBS="$OPENSSL_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libcrypto\""; } >&5 ($PKG_CONFIG --exists --print-errors "libcrypto") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_OPENSSL_LIBS=`$PKG_CONFIG --libs "libcrypto" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then OPENSSL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libcrypto" 2>&1` else OPENSSL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libcrypto" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$OPENSSL_PKG_ERRORS" >&5 as_fn_error $? "Package requirements (libcrypto) were not met: $OPENSSL_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. Alternatively, you may set the environment variables OPENSSL_CFLAGS and OPENSSL_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. Alternatively, you may set the environment variables OPENSSL_CFLAGS and OPENSSL_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details. To get pkg-config, see . See 'config.log' for more details" "$LINENO" 5; } else OPENSSL_CFLAGS=$pkg_cv_OPENSSL_CFLAGS OPENSSL_LIBS=$pkg_cv_OPENSSL_LIBS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CXXFLAGS="$CXXFLAGS $OPENSSL_CFLAGS"; LIBS="$LIBS $OPENSSL_LIBS" fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for cacheline" >&5 printf %s "checking for cacheline... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include void* vptr __cacheline_aligned; void f() { posix_memalign(&vptr, SMP_CACHE_BYTES, 42); } _ACEOF if ac_fn_c_try_compile "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: found builtin" >&5 printf "%s\n" "found builtin" >&6; } printf "%s\n" "#define LT_SMP_CACHE_BYTES 128" >>confdefs.h else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: using default 128 bytes" >&5 printf "%s\n" "using default 128 bytes" >&6; } printf "%s\n" "#define LT_SMP_CACHE_BYTES 128" >>confdefs.h ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for __builtin_popcount" >&5 printf %s "checking for __builtin_popcount... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int f() { return __builtin_popcount(0); } _ACEOF if ac_fn_c_try_compile "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } printf "%s\n" "#define USE_BUILTIN_POPCOUNT 1" >>confdefs.h else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for madvise" >&5 printf %s "checking for madvise... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include void f() { static char test[1024]; madvise((void *)test, sizeof(test), MADV_NORMAL); } _ACEOF if ac_fn_c_try_compile "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } printf "%s\n" "#define USE_MADVISE 1" >>confdefs.h else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for posix_fadvise" >&5 printf %s "checking for posix_fadvise... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include void f() { posix_fadvise(0, 0, 0, POSIX_FADV_RANDOM); } _ACEOF if ac_fn_c_try_compile "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } printf "%s\n" "#define USE_POSIX_FADVISE 1" >>confdefs.h else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pthread_setname_no" >&5 printf %s "checking for pthread_setname_no... " >&6; } # Check whether --enable-pthread-setname-np was given. if test ${enable_pthread_setname_np+y} then : enableval=$enable_pthread_setname_np; if test "$enableval" = "no"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: disabled" >&5 printf "%s\n" "disabled" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: checking" >&5 printf "%s\n" "checking" >&6; } ac_fn_c_check_header_compile "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default" if test "x$ac_cv_header_pthread_h" = xyes then : printf "%s\n" "#define HAVE_PTHREAD_H 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pthread_setname_np type" >&5 printf %s "checking for pthread_setname_np type... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _GNU_SOURCE #include #include int main (void) { pthread_t t; pthread_setname_np(t, "foo"); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : printf "%s\n" "#define HAS_PTHREAD_SETNAME_NP_GENERIC 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: generic" >&5 printf "%s\n" "generic" >&6; } else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main (void) { pthread_t t; pthread_setname_np("foo"); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : printf "%s\n" "#define HAS_PTHREAD_SETNAME_NP_DARWIN 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: darwin" >&5 printf "%s\n" "darwin" >&6; } else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext fi else case e in #( e) ac_fn_c_check_header_compile "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default" if test "x$ac_cv_header_pthread_h" = xyes then : printf "%s\n" "#define HAVE_PTHREAD_H 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pthread_setname_np type" >&5 printf %s "checking for pthread_setname_np type... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _GNU_SOURCE #include #include int main (void) { pthread_t t; pthread_setname_np(t, "foo"); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : printf "%s\n" "#define HAS_PTHREAD_SETNAME_NP_GENERIC 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: generic" >&5 printf "%s\n" "generic" >&6; } else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main (void) { pthread_t t; pthread_setname_np("foo"); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : printf "%s\n" "#define HAS_PTHREAD_SETNAME_NP_DARWIN 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: darwin" >&5 printf "%s\n" "darwin" >&6; } else case e in #( e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext ;; esac fi # Check whether --enable-mincore was given. if test ${enable_mincore+y} then : enableval=$enable_mincore; if test "$enableval" = "yes"; then ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking signedness of mincore parameter" >&5 printf %s "checking signedness of mincore parameter... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include void f() { mincore((char*)0, 0, (unsigned char*)0); } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : printf "%s\n" "#define USE_MINCORE 1" >>confdefs.h printf "%s\n" "#define USE_MINCORE_UNSIGNED 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsigned" >&5 printf "%s\n" "unsigned" >&6; } else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include void f() { mincore((char*)0, 0, (char*)0); } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : printf "%s\n" "#define USE_MINCORE 1" >>confdefs.h printf "%s\n" "#define USE_MINCORE_UNSIGNED 0" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: signed" >&5 printf "%s\n" "signed" >&6; } else case e in #( e) as_fn_error $? "failed, do *not* attempt fix this with --disable-mincore unless you are running Win32 or OpenBSD." "$LINENO" 5 ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mincore" >&5 printf %s "checking for mincore... " >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: disabled" >&5 printf "%s\n" "disabled" >&6; } fi else case e in #( e) ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking signedness of mincore parameter" >&5 printf %s "checking signedness of mincore parameter... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include void f() { mincore((char*)0, 0, (unsigned char*)0); } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : printf "%s\n" "#define USE_MINCORE 1" >>confdefs.h printf "%s\n" "#define USE_MINCORE_UNSIGNED 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsigned" >&5 printf "%s\n" "unsigned" >&6; } else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include void f() { mincore((char*)0, 0, (char*)0); } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : printf "%s\n" "#define USE_MINCORE 1" >>confdefs.h printf "%s\n" "#define USE_MINCORE_UNSIGNED 0" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: signed" >&5 printf "%s\n" "signed" >&6; } else case e in #( e) as_fn_error $? "failed, do *not* attempt fix this with --disable-mincore unless you are running Win32 or OpenBSD." "$LINENO" 5 ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if instrumentation should be included" >&5 printf %s "checking if instrumentation should be included... " >&6; } # Check whether --enable-instrumentation was given. if test ${enable_instrumentation+y} then : enableval=$enable_instrumentation; if test "$enableval" = "yes"; then printf "%s\n" "#define LT_INSTRUMENTATION 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi else case e in #( e) printf "%s\n" "#define LT_INSTRUMENTATION 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } ;; esac fi LIBTORRENT_LIBS="-ltorrent" LIBTORRENT_CFLAGS="" printf "%s\n" "#define HAVE_CONFIG_H 1" >>confdefs.h ac_config_files="$ac_config_files libtorrent.pc Makefile src/Makefile src/torrent/Makefile test/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # 'ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* 'ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # 'set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # 'set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 printf "%s\n" "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 printf %s "checking that generated files are newer than configure... " >&6; } if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: done" >&5 printf "%s\n" "done" >&6; } case $enable_silent_rules in # ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; esac if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi if test -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' else am__EXEEXT_TRUE='#' am__EXEEXT_FALSE= fi if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then as_fn_error $? "conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCXX\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi # Check whether --enable-year2038 was given. if test ${enable_year2038+y} then : enableval=$enable_year2038; fi : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case e in #( e) case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac ;; esac fi # Reset variables that may have inherited troublesome values from # the environment. # IFS needs to be set, to space, tab, and newline, in precisely that order. # (If _AS_PATH_WALK were called with IFS unset, it would have the # side effect of setting IFS to empty, thus disabling word splitting.) # Quoting is to prevent editors from complaining about space-tab. as_nl=' ' export as_nl IFS=" "" $as_nl" PS1='$ ' PS2='> ' PS4='+ ' # Ensure predictable behavior from utilities with locale-dependent output. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # We cannot yet rely on "unset" to work, but we need these variables # to be unset--not just set to an empty or harmless value--now, to # avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct # also avoids known problems related to "unset" and subshell syntax # in other old shells (e.g. bash 2.01 and pdksh 5.2.14). for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH do eval test \${$as_var+y} \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done # Ensure that fds 0, 1, and 2 are open. if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi if (exec 3>&2) ; then :; else exec 2>/dev/null; fi # The user is always right. if ${PATH_SEPARATOR+false} :; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac test -r "$as_dir$0" && as_myself=$as_dir$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as 'sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi printf "%s\n" "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null then : eval 'as_fn_append () { eval $1+=\$2 }' else case e in #( e) as_fn_append () { eval $1=\$$1\$2 } ;; esac fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null then : eval 'as_fn_arith () { as_val=$(( $* )) }' else case e in #( e) as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } ;; esac fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # Determine whether it's possible to make 'echo' print without a newline. # These variables are no longer used directly by Autoconf, but are AC_SUBSTed # for compatibility with existing Makefiles. ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac # For backward compatibility with old third-party macros, we provide # the shell variables $as_echo and $as_echo_n. New code should use # AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively. as_echo='printf %s\n' as_echo_n='printf %s' rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both 'ln -s file dir' and 'ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; 'ln -s' creates a wrapper executable. # In both cases, we have to default to 'cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_sed_cpp="y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g" as_tr_cpp="eval sed '$as_sed_cpp'" # deprecated # Sed expression to map a string onto a valid variable name. as_sed_sh="y%*+%pp%;s%[^_$as_cr_alnum]%_%g" as_tr_sh="eval sed '$as_sed_sh'" # deprecated exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by libtorrent $as_me 0.16.11, which was generated by GNU Autoconf 2.72. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ '$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to ." _ACEOF ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"` ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"` cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ libtorrent config.status 0.16.11 configured by $0, generated by GNU Autoconf 2.72, with options \\"\$ac_cs_config\\" Copyright (C) 2023 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' MKDIR_P='$MKDIR_P' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) printf "%s\n" "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) printf "%s\n" "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: '$1' Try '$0 --help' for more information.";; --help | --hel | -h ) printf "%s\n" "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: '$1' Try '$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX printf "%s\n" "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}" # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`' SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' FILECMD='`$ECHO "$FILECMD" | $SED "$delay_single_quote_subst"`' OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' lt_ar_flags='`$ECHO "$lt_ar_flags" | $SED "$delay_single_quote_subst"`' AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`' nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`' objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`' configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`' hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' compiler_lib_search_dirs='`$ECHO "$compiler_lib_search_dirs" | $SED "$delay_single_quote_subst"`' predep_objects='`$ECHO "$predep_objects" | $SED "$delay_single_quote_subst"`' postdep_objects='`$ECHO "$postdep_objects" | $SED "$delay_single_quote_subst"`' predeps='`$ECHO "$predeps" | $SED "$delay_single_quote_subst"`' postdeps='`$ECHO "$postdeps" | $SED "$delay_single_quote_subst"`' compiler_lib_search_path='`$ECHO "$compiler_lib_search_path" | $SED "$delay_single_quote_subst"`' LD_CXX='`$ECHO "$LD_CXX" | $SED "$delay_single_quote_subst"`' reload_flag_CXX='`$ECHO "$reload_flag_CXX" | $SED "$delay_single_quote_subst"`' reload_cmds_CXX='`$ECHO "$reload_cmds_CXX" | $SED "$delay_single_quote_subst"`' old_archive_cmds_CXX='`$ECHO "$old_archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' compiler_CXX='`$ECHO "$compiler_CXX" | $SED "$delay_single_quote_subst"`' GCC_CXX='`$ECHO "$GCC_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag_CXX='`$ECHO "$lt_prog_compiler_no_builtin_flag_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_pic_CXX='`$ECHO "$lt_prog_compiler_pic_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_wl_CXX='`$ECHO "$lt_prog_compiler_wl_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_static_CXX='`$ECHO "$lt_prog_compiler_static_CXX" | $SED "$delay_single_quote_subst"`' lt_cv_prog_compiler_c_o_CXX='`$ECHO "$lt_cv_prog_compiler_c_o_CXX" | $SED "$delay_single_quote_subst"`' archive_cmds_need_lc_CXX='`$ECHO "$archive_cmds_need_lc_CXX" | $SED "$delay_single_quote_subst"`' enable_shared_with_static_runtimes_CXX='`$ECHO "$enable_shared_with_static_runtimes_CXX" | $SED "$delay_single_quote_subst"`' export_dynamic_flag_spec_CXX='`$ECHO "$export_dynamic_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' whole_archive_flag_spec_CXX='`$ECHO "$whole_archive_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' compiler_needs_object_CXX='`$ECHO "$compiler_needs_object_CXX" | $SED "$delay_single_quote_subst"`' old_archive_from_new_cmds_CXX='`$ECHO "$old_archive_from_new_cmds_CXX" | $SED "$delay_single_quote_subst"`' old_archive_from_expsyms_cmds_CXX='`$ECHO "$old_archive_from_expsyms_cmds_CXX" | $SED "$delay_single_quote_subst"`' archive_cmds_CXX='`$ECHO "$archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' archive_expsym_cmds_CXX='`$ECHO "$archive_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' module_cmds_CXX='`$ECHO "$module_cmds_CXX" | $SED "$delay_single_quote_subst"`' module_expsym_cmds_CXX='`$ECHO "$module_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' with_gnu_ld_CXX='`$ECHO "$with_gnu_ld_CXX" | $SED "$delay_single_quote_subst"`' allow_undefined_flag_CXX='`$ECHO "$allow_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' no_undefined_flag_CXX='`$ECHO "$no_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' hardcode_libdir_flag_spec_CXX='`$ECHO "$hardcode_libdir_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' hardcode_libdir_separator_CXX='`$ECHO "$hardcode_libdir_separator_CXX" | $SED "$delay_single_quote_subst"`' hardcode_direct_CXX='`$ECHO "$hardcode_direct_CXX" | $SED "$delay_single_quote_subst"`' hardcode_direct_absolute_CXX='`$ECHO "$hardcode_direct_absolute_CXX" | $SED "$delay_single_quote_subst"`' hardcode_minus_L_CXX='`$ECHO "$hardcode_minus_L_CXX" | $SED "$delay_single_quote_subst"`' hardcode_shlibpath_var_CXX='`$ECHO "$hardcode_shlibpath_var_CXX" | $SED "$delay_single_quote_subst"`' hardcode_automatic_CXX='`$ECHO "$hardcode_automatic_CXX" | $SED "$delay_single_quote_subst"`' inherit_rpath_CXX='`$ECHO "$inherit_rpath_CXX" | $SED "$delay_single_quote_subst"`' link_all_deplibs_CXX='`$ECHO "$link_all_deplibs_CXX" | $SED "$delay_single_quote_subst"`' always_export_symbols_CXX='`$ECHO "$always_export_symbols_CXX" | $SED "$delay_single_quote_subst"`' export_symbols_cmds_CXX='`$ECHO "$export_symbols_cmds_CXX" | $SED "$delay_single_quote_subst"`' exclude_expsyms_CXX='`$ECHO "$exclude_expsyms_CXX" | $SED "$delay_single_quote_subst"`' include_expsyms_CXX='`$ECHO "$include_expsyms_CXX" | $SED "$delay_single_quote_subst"`' prelink_cmds_CXX='`$ECHO "$prelink_cmds_CXX" | $SED "$delay_single_quote_subst"`' postlink_cmds_CXX='`$ECHO "$postlink_cmds_CXX" | $SED "$delay_single_quote_subst"`' file_list_spec_CXX='`$ECHO "$file_list_spec_CXX" | $SED "$delay_single_quote_subst"`' hardcode_action_CXX='`$ECHO "$hardcode_action_CXX" | $SED "$delay_single_quote_subst"`' compiler_lib_search_dirs_CXX='`$ECHO "$compiler_lib_search_dirs_CXX" | $SED "$delay_single_quote_subst"`' predep_objects_CXX='`$ECHO "$predep_objects_CXX" | $SED "$delay_single_quote_subst"`' postdep_objects_CXX='`$ECHO "$postdep_objects_CXX" | $SED "$delay_single_quote_subst"`' predeps_CXX='`$ECHO "$predeps_CXX" | $SED "$delay_single_quote_subst"`' postdeps_CXX='`$ECHO "$postdeps_CXX" | $SED "$delay_single_quote_subst"`' compiler_lib_search_path_CXX='`$ECHO "$compiler_lib_search_path_CXX" | $SED "$delay_single_quote_subst"`' LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } # Quote evaled strings. for var in SHELL \ ECHO \ PATH_SEPARATOR \ SED \ GREP \ EGREP \ FGREP \ LD \ NM \ LN_S \ lt_SP2NL \ lt_NL2SP \ reload_flag \ FILECMD \ OBJDUMP \ deplibs_check_method \ file_magic_cmd \ file_magic_glob \ want_nocaseglob \ DLLTOOL \ sharedlib_from_linklib_cmd \ AR \ archiver_list_spec \ STRIP \ RANLIB \ CC \ CFLAGS \ compiler \ lt_cv_sys_global_symbol_pipe \ lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_import \ lt_cv_sys_global_symbol_to_c_name_address \ lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ lt_cv_nm_interface \ nm_file_list_spec \ lt_cv_truncate_bin \ lt_prog_compiler_no_builtin_flag \ lt_prog_compiler_pic \ lt_prog_compiler_wl \ lt_prog_compiler_static \ lt_cv_prog_compiler_c_o \ need_locks \ MANIFEST_TOOL \ DSYMUTIL \ NMEDIT \ LIPO \ OTOOL \ OTOOL64 \ shrext_cmds \ export_dynamic_flag_spec \ whole_archive_flag_spec \ compiler_needs_object \ with_gnu_ld \ allow_undefined_flag \ no_undefined_flag \ hardcode_libdir_flag_spec \ hardcode_libdir_separator \ exclude_expsyms \ include_expsyms \ file_list_spec \ variables_saved_for_relink \ libname_spec \ library_names_spec \ soname_spec \ install_override_mode \ finish_eval \ old_striplib \ striplib \ compiler_lib_search_dirs \ predep_objects \ postdep_objects \ predeps \ postdeps \ compiler_lib_search_path \ LD_CXX \ reload_flag_CXX \ compiler_CXX \ lt_prog_compiler_no_builtin_flag_CXX \ lt_prog_compiler_pic_CXX \ lt_prog_compiler_wl_CXX \ lt_prog_compiler_static_CXX \ lt_cv_prog_compiler_c_o_CXX \ export_dynamic_flag_spec_CXX \ whole_archive_flag_spec_CXX \ compiler_needs_object_CXX \ with_gnu_ld_CXX \ allow_undefined_flag_CXX \ no_undefined_flag_CXX \ hardcode_libdir_flag_spec_CXX \ hardcode_libdir_separator_CXX \ exclude_expsyms_CXX \ include_expsyms_CXX \ file_list_spec_CXX \ compiler_lib_search_dirs_CXX \ predep_objects_CXX \ postdep_objects_CXX \ predeps_CXX \ postdeps_CXX \ compiler_lib_search_path_CXX; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in reload_cmds \ old_postinstall_cmds \ old_postuninstall_cmds \ old_archive_cmds \ extract_expsyms_cmds \ old_archive_from_new_cmds \ old_archive_from_expsyms_cmds \ archive_cmds \ archive_expsym_cmds \ module_cmds \ module_expsym_cmds \ export_symbols_cmds \ prelink_cmds \ postlink_cmds \ postinstall_cmds \ postuninstall_cmds \ finish_cmds \ sys_lib_search_path_spec \ configure_time_dlsearch_path \ configure_time_lt_sys_library_path \ reload_cmds_CXX \ old_archive_cmds_CXX \ old_archive_from_new_cmds_CXX \ old_archive_from_expsyms_cmds_CXX \ archive_cmds_CXX \ archive_expsym_cmds_CXX \ module_cmds_CXX \ module_expsym_cmds_CXX \ export_symbols_cmds_CXX \ prelink_cmds_CXX \ postlink_cmds_CXX; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done ac_aux_dir='$ac_aux_dir' # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi PACKAGE='$PACKAGE' VERSION='$VERSION' RM='$RM' ofile='$ofile' _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "libtorrent.pc") CONFIG_FILES="$CONFIG_FILES libtorrent.pc" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; "src/torrent/Makefile") CONFIG_FILES="$CONFIG_FILES src/torrent/Makefile" ;; "test/Makefile") CONFIG_FILES="$CONFIG_FILES test/Makefile" ;; *) as_fn_error $? "invalid argument: '$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files test ${CONFIG_HEADERS+y} || CONFIG_HEADERS=$config_headers test ${CONFIG_COMMANDS+y} || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to '$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with './config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with './config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script 'defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag '$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain ':'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: '$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is 'configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 printf "%s\n" "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`printf "%s\n" "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac ac_MKDIR_P=$MKDIR_P case $MKDIR_P in [\\/$]* | ?:[\\/]* ) ;; */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when '$srcdir' = '.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable 'datarootdir' which seems to be undefined. Please make sure it is defined" >&5 printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable 'datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { printf "%s\n" "/* $configure_input */" >&1 \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 printf "%s\n" "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else printf "%s\n" "/* $configure_input */" >&1 \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi # Compute "$ac_file"'s index in $config_headers. _am_arg="$ac_file" _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || $as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$_am_arg" : 'X\(//\)[^/]' \| \ X"$_am_arg" : 'X\(//\)$' \| \ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$_am_arg" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'`/stamp-h$_am_stamp_count ;; :C) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 printf "%s\n" "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || { # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. # TODO: see whether this extra hack can be removed once we start # requiring Autoconf 2.70 or later. case $CONFIG_FILES in #( *\'*) : eval set x "$CONFIG_FILES" ;; #( *) : set x $CONFIG_FILES ;; #( *) : ;; esac shift # Used to flag and report bootstrapping failures. am_rc=0 for am_mf do # Strip MF so we end up with the name of the file. am_mf=`printf "%s\n" "$am_mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile which includes # dependency-tracking related rules and includes. # Grep'ing the whole file directly is not great: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ || continue am_dirpart=`$as_dirname -- "$am_mf" || $as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$am_mf" : 'X\(//\)[^/]' \| \ X"$am_mf" : 'X\(//\)$' \| \ X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$am_mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` am_filepart=`$as_basename -- "$am_mf" || $as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \ X"$am_mf" : 'X\(//\)$' \| \ X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X/"$am_mf" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` { echo "$as_me:$LINENO: cd "$am_dirpart" \ && sed -e '/# am--include-marker/d' "$am_filepart" \ | $MAKE -f - am--depfiles" >&5 (cd "$am_dirpart" \ && sed -e '/# am--include-marker/d' "$am_filepart" \ | $MAKE -f - am--depfiles) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } || am_rc=$? done if test $am_rc -ne 0; then { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error $? "Something went wrong bootstrapping makefile fragments for automatic dependency tracking. If GNU make was not used, consider re-running the configure script with MAKE=\"gmake\" (or whatever is necessary). You can also try re-running configure with the '--disable-dependency-tracking' option to at least be able to build the package (albeit without support for automatic dependency tracking). See 'config.log' for more details" "$LINENO" 5; } fi { am_dirpart=; unset am_dirpart;} { am_filepart=; unset am_filepart;} { am_mf=; unset am_mf;} { am_rc=; unset am_rc;} rm -f conftest-deps.mk } ;; "libtool":C) # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi cfgfile=${ofile}T trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # Generated automatically by $as_me ($PACKAGE) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # Provide generalized library-building support services. # Written by Gordon Matzigkeit, 1996 # Copyright (C) 2014 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of of the License, or # (at your option) any later version. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program or library that is built # using GNU Libtool, you may include this file under the same # distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # The names of the tagged configurations supported by this script. available_tags='CXX ' # Configured defaults for sys_lib_dlsearch_path munging. : \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} # ### BEGIN LIBTOOL CONFIG # Which release of libtool.m4 was used? macro_version=$macro_version macro_revision=$macro_revision # Whether or not to build static libraries. build_old_libs=$enable_static # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # What type of objects to build. pic_mode=$pic_mode # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # Shared archive member basename,for filename based shared library versioning on AIX. shared_archive_member_spec=$shared_archive_member_spec # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # An echo program that protects backslashes. ECHO=$lt_ECHO # The PATH separator for the build system. PATH_SEPARATOR=$lt_PATH_SEPARATOR # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # A sed program that does not truncate output. SED=$lt_SED # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="\$SED -e 1s/^X//" # A grep program that handles long lines. GREP=$lt_GREP # An ERE matcher. EGREP=$lt_EGREP # A literal string matcher. FGREP=$lt_FGREP # A BSD- or MS-compatible name lister. NM=$lt_NM # Whether we need soft or hard links. LN_S=$lt_LN_S # What is the maximum length of a command? max_cmd_len=$max_cmd_len # Object file suffix (normally "o"). objext=$ac_objext # Executable file suffix (normally ""). exeext=$exeext # whether the shell understands "unset". lt_unset=$lt_unset # turn spaces into newlines. SP2NL=$lt_lt_SP2NL # turn newlines into spaces. NL2SP=$lt_lt_NL2SP # convert \$build file names to \$host format. to_host_file_cmd=$lt_cv_to_host_file_cmd # convert \$build files to toolchain format. to_tool_file_cmd=$lt_cv_to_tool_file_cmd # A file(cmd) program that detects file types. FILECMD=$lt_FILECMD # An object symbol dumper. OBJDUMP=$lt_OBJDUMP # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method = "file_magic". file_magic_cmd=$lt_file_magic_cmd # How to find potential files when deplibs_check_method = "file_magic". file_magic_glob=$lt_file_magic_glob # Find potential files using nocaseglob when deplibs_check_method = "file_magic". want_nocaseglob=$lt_want_nocaseglob # DLL creation program. DLLTOOL=$lt_DLLTOOL # Command to associate shared and link libraries. sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd # The archiver. AR=$lt_AR # Flags to create an archive (by configure). lt_ar_flags=$lt_ar_flags # Flags to create an archive. AR_FLAGS=\${ARFLAGS-"\$lt_ar_flags"} # How to feed a file listing to the archiver. archiver_list_spec=$lt_archiver_list_spec # A symbol stripping program. STRIP=$lt_STRIP # Commands used to install an old-style archive. RANLIB=$lt_RANLIB old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Whether to use a lock for old archive extraction. lock_old_archive_extraction=$lock_old_archive_extraction # A C compiler. LTCC=$lt_CC # LTCC compiler flags. LTCFLAGS=$lt_CFLAGS # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration. global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm into a list of symbols to manually relocate. global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import # Transform the output of nm in a C name address pair. global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # Transform the output of nm in a C name address pair when lib prefix is needed. global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix # The name lister interface. nm_interface=$lt_lt_cv_nm_interface # Specify filename containing input files for \$NM. nm_file_list_spec=$lt_nm_file_list_spec # The root where to search for dependent libraries,and where our libraries should be installed. lt_sysroot=$lt_sysroot # Command to truncate a binary pipe. lt_truncate_bin=$lt_lt_cv_truncate_bin # The name of the directory that contains temporary libtool files. objdir=$objdir # Used to examine libraries when file_magic_cmd begins with "file". MAGIC_CMD=$MAGIC_CMD # Must we lock files when doing compilation? need_locks=$lt_need_locks # Manifest tool. MANIFEST_TOOL=$lt_MANIFEST_TOOL # Tool to manipulate archived DWARF debug symbol files on Mac OS X. DSYMUTIL=$lt_DSYMUTIL # Tool to change global to local symbols on Mac OS X. NMEDIT=$lt_NMEDIT # Tool to manipulate fat objects and archives on Mac OS X. LIPO=$lt_LIPO # ldd/readelf like tool for Mach-O binaries on Mac OS X. OTOOL=$lt_OTOOL # ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. OTOOL64=$lt_OTOOL64 # Old archive suffix (normally "a"). libext=$libext # Shared library suffix (normally ".so"). shrext_cmds=$lt_shrext_cmds # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Variables whose values should be saved in libtool wrapper scripts and # restored at link time. variables_saved_for_relink=$lt_variables_saved_for_relink # Do we need the "lib" prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Library versioning type. version_type=$version_type # Shared library runtime path variable. runpath_var=$runpath_var # Shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Permission mode override for installation of shared libraries. install_override_mode=$lt_install_override_mode # Command to use after installation of a shared archive. postinstall_cmds=$lt_postinstall_cmds # Command to use after uninstallation of a shared archive. postuninstall_cmds=$lt_postuninstall_cmds # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # As "finish_cmds", except a single script fragment to be evaled but # not shown. finish_eval=$lt_finish_eval # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Compile-time system search path for libraries. sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Detected run-time system search path for libraries. sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path # Explicit LT_SYS_LIBRARY_PATH set during ./configure time. configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # The linker used to build libraries. LD=$lt_LD # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds # A language specific compiler. CC=$lt_compiler # Is the compiler the GNU compiler? with_gcc=$GCC # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc # Whether or not to disallow shared libs when runtime libs are static. allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec # Whether the compiler copes with passing no objects directly. compiler_needs_object=$lt_compiler_needs_object # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds # Commands used to build a shared archive. archive_cmds=$lt_archive_cmds archive_expsym_cmds=$lt_archive_expsym_cmds # Commands used to build a loadable module if different from building # a shared archive. module_cmds=$lt_module_cmds module_expsym_cmds=$lt_module_expsym_cmds # Whether we are building with GNU ld or not. with_gnu_ld=$lt_with_gnu_ld # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag # Flag that enforces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary and the resulting library dependency is # "absolute",i.e impossible to change by setting \$shlibpath_var if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute # Set to "yes" if using the -LDIR flag during linking hardcodes DIR # into the resulting binary. hardcode_minus_L=$hardcode_minus_L # Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR # into the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var # Set to "yes" if building a shared library automatically hardcodes DIR # into the library and all subsequent libraries and executables linked # against it. hardcode_automatic=$hardcode_automatic # Set to yes if linker adds runtime paths of dependent libraries # to runtime path list. inherit_rpath=$inherit_rpath # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms # Symbols that must always be exported. include_expsyms=$lt_include_expsyms # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds # Commands necessary for finishing linking programs. postlink_cmds=$lt_postlink_cmds # Specify filename containing input files. file_list_spec=$lt_file_list_spec # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action # The directories searched by this compiler when creating a shared library. compiler_lib_search_dirs=$lt_compiler_lib_search_dirs # Dependencies to place before and after the objects being linked to # create a shared library. predep_objects=$lt_predep_objects postdep_objects=$lt_postdep_objects predeps=$lt_predeps postdeps=$lt_postdeps # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_compiler_lib_search_path # ### END LIBTOOL CONFIG _LT_EOF cat <<'_LT_EOF' >> "$cfgfile" # ### BEGIN FUNCTIONS SHARED WITH CONFIGURE # func_munge_path_list VARIABLE PATH # ----------------------------------- # VARIABLE is name of variable containing _space_ separated list of # directories to be munged by the contents of PATH, which is string # having a format: # "DIR[:DIR]:" # string "DIR[ DIR]" will be prepended to VARIABLE # ":DIR[:DIR]" # string "DIR[ DIR]" will be appended to VARIABLE # "DIRP[:DIRP]::[DIRA:]DIRA" # string "DIRP[ DIRP]" will be prepended to VARIABLE and string # "DIRA[ DIRA]" will be appended to VARIABLE # "DIR[:DIR]" # VARIABLE will be replaced by "DIR[ DIR]" func_munge_path_list () { case x$2 in x) ;; *:) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" ;; x:*) eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" ;; *::*) eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" ;; *) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" ;; esac } # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. func_cc_basename () { for cc_temp in $*""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` } # ### END FUNCTIONS SHARED WITH CONFIGURE _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac ltmain=$ac_aux_dir/ltmain.sh # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? $SED '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" cat <<_LT_EOF >> "$ofile" # ### BEGIN LIBTOOL TAG CONFIG: CXX # The linker used to build libraries. LD=$lt_LD_CXX # How to create reloadable object files. reload_flag=$lt_reload_flag_CXX reload_cmds=$lt_reload_cmds_CXX # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds_CXX # A language specific compiler. CC=$lt_compiler_CXX # Is the compiler the GNU compiler? with_gcc=$GCC_CXX # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic_CXX # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl_CXX # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static_CXX # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc_CXX # Whether or not to disallow shared libs when runtime libs are static. allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX # Whether the compiler copes with passing no objects directly. compiler_needs_object=$lt_compiler_needs_object_CXX # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX # Commands used to build a shared archive. archive_cmds=$lt_archive_cmds_CXX archive_expsym_cmds=$lt_archive_expsym_cmds_CXX # Commands used to build a loadable module if different from building # a shared archive. module_cmds=$lt_module_cmds_CXX module_expsym_cmds=$lt_module_expsym_cmds_CXX # Whether we are building with GNU ld or not. with_gnu_ld=$lt_with_gnu_ld_CXX # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag_CXX # Flag that enforces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag_CXX # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct_CXX # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary and the resulting library dependency is # "absolute",i.e impossible to change by setting \$shlibpath_var if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute_CXX # Set to "yes" if using the -LDIR flag during linking hardcodes DIR # into the resulting binary. hardcode_minus_L=$hardcode_minus_L_CXX # Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR # into the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX # Set to "yes" if building a shared library automatically hardcodes DIR # into the library and all subsequent libraries and executables linked # against it. hardcode_automatic=$hardcode_automatic_CXX # Set to yes if linker adds runtime paths of dependent libraries # to runtime path list. inherit_rpath=$inherit_rpath_CXX # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs_CXX # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols_CXX # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds_CXX # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms_CXX # Symbols that must always be exported. include_expsyms=$lt_include_expsyms_CXX # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds_CXX # Commands necessary for finishing linking programs. postlink_cmds=$lt_postlink_cmds_CXX # Specify filename containing input files. file_list_spec=$lt_file_list_spec_CXX # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action_CXX # The directories searched by this compiler when creating a shared library. compiler_lib_search_dirs=$lt_compiler_lib_search_dirs_CXX # Dependencies to place before and after the objects being linked to # create a shared library. predep_objects=$lt_predep_objects_CXX postdep_objects=$lt_postdep_objects_CXX predeps=$lt_predeps_CXX postdeps=$lt_postdeps_CXX # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_compiler_lib_search_path_CXX # ### END LIBTOOL TAG CONFIG: CXX _LT_EOF ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi libtorrent-0.16.11/AUTHORS0000644000000000000000000000005215175073410010543 Jari Sundell