libisofs-1.4.2/0000755000175700017510000000000012626306721010346 500000000000000libisofs-1.4.2/README0000644000175700017510000002227312557151266011161 00000000000000------------------------------------------------------------------------------ libisofs ------------------------------------------------------------------------------ Released under GPL (see COPYING file for details). Copyright (C) 2008 - 2015 Vreixo Formoso, Mario Danic, Vladimir Serbinenko, Thomas Schmitt libisofs is part of the libburnia project (libburnia-project.org) ------------------------------------------------------------------------------ Download, Build and Installation libisofs code is mantained in a Bazaar repository at Launchpad (https://launchpad.net/libisofs/). You can download it with: $ bzr branch lp:libisofs/for-libisoburn Our build system is based on autotools. For preparing the build you will need autotools of at least version 1.7. If you have download the code from the repository, first of all you need to execute ./autogen.sh on toplevel dir to execute autotools. Alternatively you may unpack a release tarball for which you do not need autotools installed. For the most recent release of libisofs see: http://libburnia-project.org/wiki/Releases To build libisofs it should be sufficient to go into its toplevel directory and execute ./configure --prefix=/usr make To make the libraries accessible for running and developing applications make install On GNU/Linux it will try to run program ldconfig with the library installation directory as only argument. Failure to do so will not abort installation. One may disable ldconfig by ./configure option --disable-ldconfig-at-install . By use of a version script, the libisofs.so library exposes no other function names but those of the API definitions in . If -Wl,--version-script=... makes problems with the local compiler, then disable this encapsulation feature by ./configure --disable-versioned-libs make clean ; make The ./configure script checks for the availability of supporting libraries. If found, they will become mandatory for the emerging libisofs.so and all applications which use it. This dependency can be avoided by configure options --disable-libacl avoid use of ACL functions like acl_to_text() --disable-xattr avoid use of xattr functions like listxattr() --disable-zlib avoid use of zlib functions like compress2() --disable-libjte avoid use of libjte functions See INSTALL file for general options of ./configure. ------------------------------------------------------------------------------ libisofs is a library to create an ISO-9660 filesystem, supports extensions like RockRidge or Joliet, and introduces an own extension AAIP. It is a full featured ISO-9660 editor which composes and changes the directory tree of an ISO image. This tree and its newly imported data file contents get then written as independent single-session image or as add-on session for the image from where the tree was originally loaded. Features: --------- - Image creation - Creates ISO-9660 images from local files. - Support for RockRidge and Joliet extensions. - Support for ISO-9660:1999 (version 2). - Support for El-Torito bootable images. Tested are: PC-BIOS and EFI. - Support for multi-extent data files up to 400 GB (level 3). - Full-featured edition of the image files, including: addition of new files, removing of existent files, moving files, renaming files, change file attributes (permissions, timestamps...) - Optional recording per file of non-ISO 9660 features: ACL, xattr, content MD5, hard link relations. They do not hamper image readability by operating systems but can be retrieved only via libisofs. - Optional zisofs compression, gzip compression, external filter processes. - Several options to relax ISO-9660 constraints. - Special options for images intended for distribution (suitable default modes for files, hiding of real timestamps...). - Image reading - Image tree and data heap can be verified by stream reading and eventually recorded MD5 tags. - Directory tree and file attributes of ISO 9660 session get loaded into memory for editing or for extraction into local filesystem. - File content can be read by applications. - Automatic zisofs decompression. - Optional application of gzip decompression or external filter processes. - Eventually recorded MD5 of data file can be obtained, MD5 of data stream can be computed and compared. - Helper functions for restoring ACL and/or xattr to the local filesystem. - Multisession - Support for growing an existing image on multi-session media. - Support for "emulated multisession" on overwriteable media such as DVD+RW, USB sticks, regular files. - Support for blindly prepared add-on sessions (mkisofs style -M -C) suitable for pipes which lead to an external burn program. - Image modification - Creates a completely new image from files out of another image and eventual editing operations. Suitable for any target medium. - Others - Handling of different input and output charset. - Good integration with libburn for image burning. - Reliable, good handling of different kind of errors. Requirements: ------------- - iconv() functions for character set conversion must be available. Either implicitely as in Linux or by a separate library like libiconv on FreeBSD. Know bugs: ---------- Multisession and image growing can lead to undesired results in several cases: a) Images with unsupported features, such as: - UDF. - HSF/HFS+ or other Mac extensions. - ECMA-119 Extended attributes. - ... In all these cases, the resulting new image (or new session) could lack some features of the original image. Nevertheless, the ECMA-119 System Area with an eventual Master Boot Record gets preserved by default. In some cases libisofs will issue warning messages, or even refuse to grow or modify the image. Others remain undetected. Images created with libisofs do not have this problems. b) Bootable El-Torito images may have problems, that result in a new image that is not bootable, or that boots from an outdated session. In some cases it might be necessary to add boot info again in a new first session. - There is no safe way to modify hidden boot images, as the size of the boot image can't be figured out. c) Generated images could have different ECMA-119 low level names, due to different way to mangle names, to new files added that force old files to be renamed, to different relaxed contraints... This only affect the ISO-9660 info, not the RR names, so it shouldn't be a problem in most cases. If your app. relies on low level ISO-9660 names, you will need to ensure all node names are valid ISO names (maybe together with some relaxed contraints), otherwise libisofs might arbitrarily change the names. ------------------------------------------------------------------------------ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 or later as published by the Free Software Foundation. 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 ------------------------------------------------------------------------------ Clarification in my name and in the name of Mario Danic, upcoming copyright holders on toplevel of libburnia. To be fully in effect after the remaining other copyrighted code has been replaced by ours and by copyright-free contributions of our friends. Note: In the particular case of libisofs there is no foreign copyright involved. As of 2010 foreign copyright is only in component libburn. ------------------------------------------------------------------------------ We will not raise any legal protest to dynamic linking of our libraries with applications that are not under GPL, as long as they fulfill the condition of offering the library source code used, whether altered or unaltered, under the GPLv2+, along with the application. Nevertheless, the safest legal position is not to link libburn with non-GPL compatible programs. We ask you politely to use our work in open source spirit and with the due reference to the entire open source community. If there should really arise the case where above clarification does not suffice to fulfill a clear and neat request in open source spirit that would otherwise be declined for mere formal reasons, only in that case we will duely consider to issue a special license covering only that special case. It is the open source idea of responsible freedom which will be decisive and you will have to prove that you exhausted all own means to qualify for GPL. We are firmly committed to allow GPLv2+ now and with future releases. Signed: Mario Danic, Thomas Schmitt Agreement joined later by: Vreixo Formoso Public contact: libisofs-1.4.2/lt~obsolete.m40000644000175700017510000001375612626305073013115 00000000000000# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # # Copyright (C) 2004, 2005, 2007, 2009 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])]) libisofs-1.4.2/COPYING0000644000175700017510000003542711112746253011331 00000000000000 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 libisofs-1.4.2/TODO0000644000175700017510000000300111112746253010745 00000000000000FEATURES ======== TODO ==== #00001 (node.h) -> consider adding new timestamps to IsoTreeNode #00004 (libisofs.h) -> Add a get_mime_type() function. #00005 (node.c) -> optimize iso_dir_iter_take. #00006 (libisofs.h) -> define more replace values when adding a node to a dir #00008 (data_dource.c) -> guard against partial reads #00009 (ecma119_tree.c/h) -> add true support for harlinks and inode numbers #00010 (buffer.c) -> optimize ring buffer #00011 (ecma119.c) -> guard against bad path table usage with more than 65535 dirs #00012 (fs_image.c) -> support follow symlinks on imafe filesystem #00013 (fs_image.c) -> check for unsupported flags when reading a dir record #00014 (fs_image.c) -> more sanity checks to ensure dir record info is valid #00015 (fs_image.c) -> take care of CD-ROM XA discs when reading SP entry #00016 (fs_image.c) -> handle non RR ER entries #00017 (fs_image.c) -> take advantage of other atts of PVD #00018 (fs_image.c) -> check if there are more entries in the boot catalog #00019 (fs_image.c) -> set IsoImage attribs from Joliet SVD? #00020 (fs_image.c) -> handle RR info in Joliet tree #00021 (fs_image.c) -> handle RR info in ISO 9660:1999 tree #00022 (joliet.c) -> support relaxed constraints in joliet filenames #00024 (libisofs.h) -> option to convert names to lower case for iso reading #00025 (libisofs.h) -> support for merging old image files #00026 (libisofs.h) -> add support for "hidden" bootable images. #00027 (iso1999.h) -> Follow ISO 9660:1999 specs when sorting files FIXME ===== libisofs-1.4.2/Makefile.in0000644000175700017510000027453212626305074012350 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 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 = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' 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)) 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@ target_triplet = @target@ noinst_PROGRAMS = demo/demo$(EXEEXT) subdir = . DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/configure $(am__configure_deps) \ $(top_srcdir)/doc/doxygen.conf.in $(srcdir)/version.h.in \ $(srcdir)/libisofs-1.pc.in depcomp $(libinclude_HEADERS) \ AUTHORS COPYING ChangeLog INSTALL NEWS README TODO compile \ config.guess config.sub install-sh missing ltmain.sh ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/libtool.m4 \ $(top_srcdir)/ltoptions.m4 $(top_srcdir)/ltsugar.m4 \ $(top_srcdir)/ltversion.m4 $(top_srcdir)/lt~obsolete.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_CLEAN_FILES = doc/doxygen.conf version.h libisofs-1.pc 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 -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" \ "$(DESTDIR)$(libincludedir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = libisofs_libisofs_la_DEPENDENCIES = $(am__DEPENDENCIES_1) am__dirstamp = $(am__leading_dot)dirstamp am_libisofs_libisofs_la_OBJECTS = \ libisofs/libisofs_libisofs_la-builder.lo \ libisofs/libisofs_libisofs_la-node.lo \ libisofs/libisofs_libisofs_la-tree.lo \ libisofs/libisofs_libisofs_la-find.lo \ libisofs/libisofs_libisofs_la-image.lo \ libisofs/libisofs_libisofs_la-fsource.lo \ libisofs/libisofs_libisofs_la-fs_local.lo \ libisofs/libisofs_libisofs_la-fs_image.lo \ libisofs/libisofs_libisofs_la-messages.lo \ libisofs/libisofs_libisofs_la-libiso_msgs.lo \ libisofs/libisofs_libisofs_la-stream.lo \ libisofs/libisofs_libisofs_la-filter.lo \ libisofs/filters/libisofs_libisofs_la-external.lo \ libisofs/filters/libisofs_libisofs_la-zisofs.lo \ libisofs/filters/libisofs_libisofs_la-gzip.lo \ libisofs/libisofs_libisofs_la-util.lo \ libisofs/libisofs_libisofs_la-util_rbtree.lo \ libisofs/libisofs_libisofs_la-util_htable.lo \ libisofs/libisofs_libisofs_la-filesrc.lo \ libisofs/libisofs_libisofs_la-ecma119.lo \ libisofs/libisofs_libisofs_la-ecma119_tree.lo \ libisofs/libisofs_libisofs_la-buffer.lo \ libisofs/libisofs_libisofs_la-rockridge.lo \ libisofs/libisofs_libisofs_la-rockridge_read.lo \ libisofs/libisofs_libisofs_la-joliet.lo \ libisofs/libisofs_libisofs_la-hfsplus.lo \ libisofs/libisofs_libisofs_la-hfsplus_decompose.lo \ libisofs/libisofs_libisofs_la-hfsplus_classes.lo \ libisofs/libisofs_libisofs_la-hfsplus_case.lo \ libisofs/libisofs_libisofs_la-eltorito.lo \ libisofs/libisofs_libisofs_la-system_area.lo \ libisofs/libisofs_libisofs_la-make_isohybrid_mbr.lo \ libisofs/libisofs_libisofs_la-iso1999.lo \ libisofs/libisofs_libisofs_la-data_source.lo \ libisofs/libisofs_libisofs_la-aaip_0_2.lo \ libisofs/libisofs_libisofs_la-md5.lo libisofs_libisofs_la_OBJECTS = $(am_libisofs_libisofs_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 = libisofs_libisofs_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) \ $(libisofs_libisofs_la_LDFLAGS) $(LDFLAGS) -o $@ PROGRAMS = $(noinst_PROGRAMS) am_demo_demo_OBJECTS = demo/demo_demo-demo.$(OBJEXT) demo_demo_OBJECTS = $(am_demo_demo_OBJECTS) am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) demo_demo_DEPENDENCIES = $(libisofs_libisofs_la_OBJECTS) \ $(am__DEPENDENCIES_2) 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@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f 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 = $(libisofs_libisofs_la_SOURCES) $(demo_demo_SOURCES) DIST_SOURCES = $(libisofs_libisofs_la_SOURCES) $(demo_demo_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(nodist_pkgconfig_DATA) HEADERS = $(libinclude_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)` ETAGS = etags CTAGS = ctags CSCOPE = cscope AM_RECURSIVE_TARGETS = cscope 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 -200 -exec chmod u+w {} ';' \ && rm -rf "$(distdir)" \ || { sleep 5 && rm -rf "$(distdir)"; }; \ else :; fi am__post_remove_distdir = $(am__remove_distdir) DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best DIST_TARGETS = dist-gzip distuninstallcheck_listfiles = find . -type f -print am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ ARCH = @ARCH@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ 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@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBACL_DEF = @LIBACL_DEF@ LIBBURNIA_LDCONFIG_CMD = @LIBBURNIA_LDCONFIG_CMD@ LIBBURNIA_PKGCONFDIR = @LIBBURNIA_PKGCONFDIR@ LIBBURN_ARCH_LIBS = @LIBBURN_ARCH_LIBS@ LIBISOFS_MAJOR_VERSION = @LIBISOFS_MAJOR_VERSION@ LIBISOFS_MICRO_VERSION = @LIBISOFS_MICRO_VERSION@ LIBISOFS_MINOR_VERSION = @LIBISOFS_MINOR_VERSION@ LIBISOFS_VERSION = @LIBISOFS_VERSION@ LIBJTE_DEF = @LIBJTE_DEF@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBTOOL_DEPS = @LIBTOOL_DEPS@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_AGE = @LT_AGE@ LT_CURRENT = @LT_CURRENT@ LT_CURRENT_MINUS_AGE = @LT_CURRENT_MINUS_AGE@ LT_RELEASE = @LT_RELEASE@ LT_REVISION = @LT_REVISION@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ THREAD_LIBS = @THREAD_LIBS@ VERSION = @VERSION@ XATTR_DEF = @XATTR_DEF@ ZLIB_DEF = @ZLIB_DEF@ 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_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ 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 = $(DESTDIR)$(prefix)/share/doc/$(PACKAGE)-$(VERSION) 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@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ # ts A90315 : LIBBURNIA_PKGCONFDIR is defined OS specific in acinclude.m4 # was: pkgconfigdir=$(libdir)/pkgconfig pkgconfigdir = $(LIBBURNIA_PKGCONFDIR) libincludedir = $(includedir)/libisofs lib_LTLIBRARIES = libisofs/libisofs.la ACLOCAL_AMFLAGS = -I ./ # Build libraries libisofs_libisofs_la_LDFLAGS = \ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) # Eventually enabling system adapters for ACL and EA. # ts A90409: Eventually enabling use of zlib. # ts B00927: Eventually enabling use of libjte (Jigdo Template Extraction) libisofs_libisofs_la_CFLAGS = $(LIBACL_DEF) $(XATTR_DEF) $(ZLIB_DEF) \ $(LIBJTE_DEF) # ts A90114 : added aaip_0_2.* libisofs_libisofs_la_SOURCES = \ libisofs/builder.h \ libisofs/builder.c \ libisofs/node.h \ libisofs/node.c \ libisofs/tree.h \ libisofs/tree.c \ libisofs/find.c \ libisofs/image.h \ libisofs/image.c \ libisofs/fsource.h \ libisofs/fsource.c \ libisofs/fs_local.c \ libisofs/fs_image.c \ libisofs/messages.h \ libisofs/messages.c \ libisofs/libiso_msgs.h \ libisofs/libiso_msgs.c \ libisofs/stream.h \ libisofs/stream.c \ libisofs/filter.h \ libisofs/filter.c \ libisofs/filters/external.c \ libisofs/filters/zisofs.c \ libisofs/filters/gzip.c \ libisofs/util.h \ libisofs/util.c \ libisofs/util_rbtree.c \ libisofs/util_htable.c \ libisofs/filesrc.h \ libisofs/filesrc.c \ libisofs/ecma119.h \ libisofs/ecma119.c \ libisofs/ecma119_tree.h \ libisofs/ecma119_tree.c \ libisofs/writer.h \ libisofs/buffer.h \ libisofs/buffer.c \ libisofs/rockridge.h \ libisofs/rockridge.c \ libisofs/rockridge_read.c \ libisofs/joliet.h \ libisofs/joliet.c \ libisofs/hfsplus.h \ libisofs/hfsplus.c \ libisofs/hfsplus_decompose.c \ libisofs/hfsplus_classes.c \ libisofs/hfsplus_case.c \ libisofs/eltorito.h \ libisofs/eltorito.c \ libisofs/system_area.h \ libisofs/system_area.c \ libisofs/make_isohybrid_mbr.c \ libisofs/iso1999.h \ libisofs/iso1999.c \ libisofs/data_source.c \ libisofs/aaip_0_2.h \ libisofs/aaip_0_2.c \ libisofs/md5.h \ libisofs/md5.c libisofs_libisofs_la_LIBADD = \ $(THREAD_LIBS) libinclude_HEADERS = \ libisofs/libisofs.h # demo/tree \ # demo/find \ # demo/iso \ # demo/isoread \ # demo/isocat \ # demo/isomodify \ # demo/isoms # demo/ecma119tree \ # demo/lsl \ # demo/cat \ # demo/catbuffer \ # demo/isogrow # ts A90807 # Consolidated demo code for having less linker mesages with a make run. demo_demo_CPPFLAGS = -Ilibisofs demo_demo_LDADD = $(libisofs_libisofs_la_OBJECTS) $(libisofs_libisofs_la_LIBADD) demo_demo_SOURCES = demo/demo.c # Extra things nodist_pkgconfig_DATA = \ libisofs-1.pc # ts A80114 : added aaip-os* EXTRA_DIST = \ bootstrap \ libisofs-1.pc.in \ version.h.in \ doc/doxygen.conf.in \ doc/Tutorial \ README \ AUTHORS \ COPYRIGHT \ COPYING \ NEWS \ INSTALL \ TODO \ ChangeLog \ Roadmap \ doc/susp_aaip_2_0.txt \ doc/susp_aaip_isofs_names.txt \ doc/zisofs_format.txt \ doc/checksums.txt \ libisofs/libisofs.ver \ libisofs/aaip-os-dummy.c \ libisofs/aaip-os-linux.c \ libisofs/aaip-os-freebsd.c all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj am--refresh: Makefile @: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(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 .PRECIOUS: 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__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): doc/doxygen.conf: $(top_builddir)/config.status $(top_srcdir)/doc/doxygen.conf.in cd $(top_builddir) && $(SHELL) ./config.status $@ version.h: $(top_builddir)/config.status $(srcdir)/version.h.in cd $(top_builddir) && $(SHELL) ./config.status $@ libisofs-1.pc: $(top_builddir)/config.status $(srcdir)/libisofs-1.pc.in cd $(top_builddir) && $(SHELL) ./config.status $@ 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: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libisofs/$(am__dirstamp): @$(MKDIR_P) libisofs @: > libisofs/$(am__dirstamp) libisofs/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) libisofs/$(DEPDIR) @: > libisofs/$(DEPDIR)/$(am__dirstamp) libisofs/libisofs_libisofs_la-builder.lo: libisofs/$(am__dirstamp) \ libisofs/$(DEPDIR)/$(am__dirstamp) libisofs/libisofs_libisofs_la-node.lo: libisofs/$(am__dirstamp) \ libisofs/$(DEPDIR)/$(am__dirstamp) libisofs/libisofs_libisofs_la-tree.lo: libisofs/$(am__dirstamp) \ libisofs/$(DEPDIR)/$(am__dirstamp) libisofs/libisofs_libisofs_la-find.lo: libisofs/$(am__dirstamp) \ libisofs/$(DEPDIR)/$(am__dirstamp) libisofs/libisofs_libisofs_la-image.lo: libisofs/$(am__dirstamp) \ libisofs/$(DEPDIR)/$(am__dirstamp) libisofs/libisofs_libisofs_la-fsource.lo: libisofs/$(am__dirstamp) \ libisofs/$(DEPDIR)/$(am__dirstamp) libisofs/libisofs_libisofs_la-fs_local.lo: libisofs/$(am__dirstamp) \ libisofs/$(DEPDIR)/$(am__dirstamp) libisofs/libisofs_libisofs_la-fs_image.lo: libisofs/$(am__dirstamp) \ libisofs/$(DEPDIR)/$(am__dirstamp) libisofs/libisofs_libisofs_la-messages.lo: libisofs/$(am__dirstamp) \ libisofs/$(DEPDIR)/$(am__dirstamp) libisofs/libisofs_libisofs_la-libiso_msgs.lo: \ libisofs/$(am__dirstamp) libisofs/$(DEPDIR)/$(am__dirstamp) libisofs/libisofs_libisofs_la-stream.lo: libisofs/$(am__dirstamp) \ libisofs/$(DEPDIR)/$(am__dirstamp) libisofs/libisofs_libisofs_la-filter.lo: libisofs/$(am__dirstamp) \ libisofs/$(DEPDIR)/$(am__dirstamp) libisofs/filters/$(am__dirstamp): @$(MKDIR_P) libisofs/filters @: > libisofs/filters/$(am__dirstamp) libisofs/filters/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) libisofs/filters/$(DEPDIR) @: > libisofs/filters/$(DEPDIR)/$(am__dirstamp) libisofs/filters/libisofs_libisofs_la-external.lo: \ libisofs/filters/$(am__dirstamp) \ libisofs/filters/$(DEPDIR)/$(am__dirstamp) libisofs/filters/libisofs_libisofs_la-zisofs.lo: \ libisofs/filters/$(am__dirstamp) \ libisofs/filters/$(DEPDIR)/$(am__dirstamp) libisofs/filters/libisofs_libisofs_la-gzip.lo: \ libisofs/filters/$(am__dirstamp) \ libisofs/filters/$(DEPDIR)/$(am__dirstamp) libisofs/libisofs_libisofs_la-util.lo: libisofs/$(am__dirstamp) \ libisofs/$(DEPDIR)/$(am__dirstamp) libisofs/libisofs_libisofs_la-util_rbtree.lo: \ libisofs/$(am__dirstamp) libisofs/$(DEPDIR)/$(am__dirstamp) libisofs/libisofs_libisofs_la-util_htable.lo: \ libisofs/$(am__dirstamp) libisofs/$(DEPDIR)/$(am__dirstamp) libisofs/libisofs_libisofs_la-filesrc.lo: libisofs/$(am__dirstamp) \ libisofs/$(DEPDIR)/$(am__dirstamp) libisofs/libisofs_libisofs_la-ecma119.lo: libisofs/$(am__dirstamp) \ libisofs/$(DEPDIR)/$(am__dirstamp) libisofs/libisofs_libisofs_la-ecma119_tree.lo: \ libisofs/$(am__dirstamp) libisofs/$(DEPDIR)/$(am__dirstamp) libisofs/libisofs_libisofs_la-buffer.lo: libisofs/$(am__dirstamp) \ libisofs/$(DEPDIR)/$(am__dirstamp) libisofs/libisofs_libisofs_la-rockridge.lo: libisofs/$(am__dirstamp) \ libisofs/$(DEPDIR)/$(am__dirstamp) libisofs/libisofs_libisofs_la-rockridge_read.lo: \ libisofs/$(am__dirstamp) libisofs/$(DEPDIR)/$(am__dirstamp) libisofs/libisofs_libisofs_la-joliet.lo: libisofs/$(am__dirstamp) \ libisofs/$(DEPDIR)/$(am__dirstamp) libisofs/libisofs_libisofs_la-hfsplus.lo: libisofs/$(am__dirstamp) \ libisofs/$(DEPDIR)/$(am__dirstamp) libisofs/libisofs_libisofs_la-hfsplus_decompose.lo: \ libisofs/$(am__dirstamp) libisofs/$(DEPDIR)/$(am__dirstamp) libisofs/libisofs_libisofs_la-hfsplus_classes.lo: \ libisofs/$(am__dirstamp) libisofs/$(DEPDIR)/$(am__dirstamp) libisofs/libisofs_libisofs_la-hfsplus_case.lo: \ libisofs/$(am__dirstamp) libisofs/$(DEPDIR)/$(am__dirstamp) libisofs/libisofs_libisofs_la-eltorito.lo: libisofs/$(am__dirstamp) \ libisofs/$(DEPDIR)/$(am__dirstamp) libisofs/libisofs_libisofs_la-system_area.lo: \ libisofs/$(am__dirstamp) libisofs/$(DEPDIR)/$(am__dirstamp) libisofs/libisofs_libisofs_la-make_isohybrid_mbr.lo: \ libisofs/$(am__dirstamp) libisofs/$(DEPDIR)/$(am__dirstamp) libisofs/libisofs_libisofs_la-iso1999.lo: libisofs/$(am__dirstamp) \ libisofs/$(DEPDIR)/$(am__dirstamp) libisofs/libisofs_libisofs_la-data_source.lo: \ libisofs/$(am__dirstamp) libisofs/$(DEPDIR)/$(am__dirstamp) libisofs/libisofs_libisofs_la-aaip_0_2.lo: libisofs/$(am__dirstamp) \ libisofs/$(DEPDIR)/$(am__dirstamp) libisofs/libisofs_libisofs_la-md5.lo: libisofs/$(am__dirstamp) \ libisofs/$(DEPDIR)/$(am__dirstamp) libisofs/libisofs.la: $(libisofs_libisofs_la_OBJECTS) $(libisofs_libisofs_la_DEPENDENCIES) $(EXTRA_libisofs_libisofs_la_DEPENDENCIES) libisofs/$(am__dirstamp) $(AM_V_CCLD)$(libisofs_libisofs_la_LINK) -rpath $(libdir) $(libisofs_libisofs_la_OBJECTS) $(libisofs_libisofs_la_LIBADD) $(LIBS) clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list demo/$(am__dirstamp): @$(MKDIR_P) demo @: > demo/$(am__dirstamp) demo/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) demo/$(DEPDIR) @: > demo/$(DEPDIR)/$(am__dirstamp) demo/demo_demo-demo.$(OBJEXT): demo/$(am__dirstamp) \ demo/$(DEPDIR)/$(am__dirstamp) demo/demo$(EXEEXT): $(demo_demo_OBJECTS) $(demo_demo_DEPENDENCIES) $(EXTRA_demo_demo_DEPENDENCIES) demo/$(am__dirstamp) @rm -f demo/demo$(EXEEXT) $(AM_V_CCLD)$(LINK) $(demo_demo_OBJECTS) $(demo_demo_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) -rm -f demo/*.$(OBJEXT) -rm -f libisofs/*.$(OBJEXT) -rm -f libisofs/*.lo -rm -f libisofs/filters/*.$(OBJEXT) -rm -f libisofs/filters/*.lo distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@demo/$(DEPDIR)/demo_demo-demo.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libisofs/$(DEPDIR)/libisofs_libisofs_la-aaip_0_2.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libisofs/$(DEPDIR)/libisofs_libisofs_la-buffer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libisofs/$(DEPDIR)/libisofs_libisofs_la-builder.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libisofs/$(DEPDIR)/libisofs_libisofs_la-data_source.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libisofs/$(DEPDIR)/libisofs_libisofs_la-ecma119.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libisofs/$(DEPDIR)/libisofs_libisofs_la-ecma119_tree.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libisofs/$(DEPDIR)/libisofs_libisofs_la-eltorito.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libisofs/$(DEPDIR)/libisofs_libisofs_la-filesrc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libisofs/$(DEPDIR)/libisofs_libisofs_la-filter.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libisofs/$(DEPDIR)/libisofs_libisofs_la-find.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libisofs/$(DEPDIR)/libisofs_libisofs_la-fs_image.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libisofs/$(DEPDIR)/libisofs_libisofs_la-fs_local.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libisofs/$(DEPDIR)/libisofs_libisofs_la-fsource.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libisofs/$(DEPDIR)/libisofs_libisofs_la-hfsplus.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libisofs/$(DEPDIR)/libisofs_libisofs_la-hfsplus_case.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libisofs/$(DEPDIR)/libisofs_libisofs_la-hfsplus_classes.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libisofs/$(DEPDIR)/libisofs_libisofs_la-hfsplus_decompose.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libisofs/$(DEPDIR)/libisofs_libisofs_la-image.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libisofs/$(DEPDIR)/libisofs_libisofs_la-iso1999.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libisofs/$(DEPDIR)/libisofs_libisofs_la-joliet.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libisofs/$(DEPDIR)/libisofs_libisofs_la-libiso_msgs.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libisofs/$(DEPDIR)/libisofs_libisofs_la-make_isohybrid_mbr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libisofs/$(DEPDIR)/libisofs_libisofs_la-md5.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libisofs/$(DEPDIR)/libisofs_libisofs_la-messages.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libisofs/$(DEPDIR)/libisofs_libisofs_la-node.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libisofs/$(DEPDIR)/libisofs_libisofs_la-rockridge.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libisofs/$(DEPDIR)/libisofs_libisofs_la-rockridge_read.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libisofs/$(DEPDIR)/libisofs_libisofs_la-stream.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libisofs/$(DEPDIR)/libisofs_libisofs_la-system_area.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libisofs/$(DEPDIR)/libisofs_libisofs_la-tree.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libisofs/$(DEPDIR)/libisofs_libisofs_la-util.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libisofs/$(DEPDIR)/libisofs_libisofs_la-util_htable.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libisofs/$(DEPDIR)/libisofs_libisofs_la-util_rbtree.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libisofs/filters/$(DEPDIR)/libisofs_libisofs_la-external.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libisofs/filters/$(DEPDIR)/libisofs_libisofs_la-gzip.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libisofs/filters/$(DEPDIR)/libisofs_libisofs_la-zisofs.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< libisofs/libisofs_libisofs_la-builder.lo: libisofs/builder.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -MT libisofs/libisofs_libisofs_la-builder.lo -MD -MP -MF libisofs/$(DEPDIR)/libisofs_libisofs_la-builder.Tpo -c -o libisofs/libisofs_libisofs_la-builder.lo `test -f 'libisofs/builder.c' || echo '$(srcdir)/'`libisofs/builder.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libisofs/$(DEPDIR)/libisofs_libisofs_la-builder.Tpo libisofs/$(DEPDIR)/libisofs_libisofs_la-builder.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libisofs/builder.c' object='libisofs/libisofs_libisofs_la-builder.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -c -o libisofs/libisofs_libisofs_la-builder.lo `test -f 'libisofs/builder.c' || echo '$(srcdir)/'`libisofs/builder.c libisofs/libisofs_libisofs_la-node.lo: libisofs/node.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -MT libisofs/libisofs_libisofs_la-node.lo -MD -MP -MF libisofs/$(DEPDIR)/libisofs_libisofs_la-node.Tpo -c -o libisofs/libisofs_libisofs_la-node.lo `test -f 'libisofs/node.c' || echo '$(srcdir)/'`libisofs/node.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libisofs/$(DEPDIR)/libisofs_libisofs_la-node.Tpo libisofs/$(DEPDIR)/libisofs_libisofs_la-node.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libisofs/node.c' object='libisofs/libisofs_libisofs_la-node.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -c -o libisofs/libisofs_libisofs_la-node.lo `test -f 'libisofs/node.c' || echo '$(srcdir)/'`libisofs/node.c libisofs/libisofs_libisofs_la-tree.lo: libisofs/tree.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -MT libisofs/libisofs_libisofs_la-tree.lo -MD -MP -MF libisofs/$(DEPDIR)/libisofs_libisofs_la-tree.Tpo -c -o libisofs/libisofs_libisofs_la-tree.lo `test -f 'libisofs/tree.c' || echo '$(srcdir)/'`libisofs/tree.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libisofs/$(DEPDIR)/libisofs_libisofs_la-tree.Tpo libisofs/$(DEPDIR)/libisofs_libisofs_la-tree.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libisofs/tree.c' object='libisofs/libisofs_libisofs_la-tree.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -c -o libisofs/libisofs_libisofs_la-tree.lo `test -f 'libisofs/tree.c' || echo '$(srcdir)/'`libisofs/tree.c libisofs/libisofs_libisofs_la-find.lo: libisofs/find.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -MT libisofs/libisofs_libisofs_la-find.lo -MD -MP -MF libisofs/$(DEPDIR)/libisofs_libisofs_la-find.Tpo -c -o libisofs/libisofs_libisofs_la-find.lo `test -f 'libisofs/find.c' || echo '$(srcdir)/'`libisofs/find.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libisofs/$(DEPDIR)/libisofs_libisofs_la-find.Tpo libisofs/$(DEPDIR)/libisofs_libisofs_la-find.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libisofs/find.c' object='libisofs/libisofs_libisofs_la-find.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -c -o libisofs/libisofs_libisofs_la-find.lo `test -f 'libisofs/find.c' || echo '$(srcdir)/'`libisofs/find.c libisofs/libisofs_libisofs_la-image.lo: libisofs/image.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -MT libisofs/libisofs_libisofs_la-image.lo -MD -MP -MF libisofs/$(DEPDIR)/libisofs_libisofs_la-image.Tpo -c -o libisofs/libisofs_libisofs_la-image.lo `test -f 'libisofs/image.c' || echo '$(srcdir)/'`libisofs/image.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libisofs/$(DEPDIR)/libisofs_libisofs_la-image.Tpo libisofs/$(DEPDIR)/libisofs_libisofs_la-image.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libisofs/image.c' object='libisofs/libisofs_libisofs_la-image.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -c -o libisofs/libisofs_libisofs_la-image.lo `test -f 'libisofs/image.c' || echo '$(srcdir)/'`libisofs/image.c libisofs/libisofs_libisofs_la-fsource.lo: libisofs/fsource.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -MT libisofs/libisofs_libisofs_la-fsource.lo -MD -MP -MF libisofs/$(DEPDIR)/libisofs_libisofs_la-fsource.Tpo -c -o libisofs/libisofs_libisofs_la-fsource.lo `test -f 'libisofs/fsource.c' || echo '$(srcdir)/'`libisofs/fsource.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libisofs/$(DEPDIR)/libisofs_libisofs_la-fsource.Tpo libisofs/$(DEPDIR)/libisofs_libisofs_la-fsource.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libisofs/fsource.c' object='libisofs/libisofs_libisofs_la-fsource.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -c -o libisofs/libisofs_libisofs_la-fsource.lo `test -f 'libisofs/fsource.c' || echo '$(srcdir)/'`libisofs/fsource.c libisofs/libisofs_libisofs_la-fs_local.lo: libisofs/fs_local.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -MT libisofs/libisofs_libisofs_la-fs_local.lo -MD -MP -MF libisofs/$(DEPDIR)/libisofs_libisofs_la-fs_local.Tpo -c -o libisofs/libisofs_libisofs_la-fs_local.lo `test -f 'libisofs/fs_local.c' || echo '$(srcdir)/'`libisofs/fs_local.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libisofs/$(DEPDIR)/libisofs_libisofs_la-fs_local.Tpo libisofs/$(DEPDIR)/libisofs_libisofs_la-fs_local.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libisofs/fs_local.c' object='libisofs/libisofs_libisofs_la-fs_local.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -c -o libisofs/libisofs_libisofs_la-fs_local.lo `test -f 'libisofs/fs_local.c' || echo '$(srcdir)/'`libisofs/fs_local.c libisofs/libisofs_libisofs_la-fs_image.lo: libisofs/fs_image.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -MT libisofs/libisofs_libisofs_la-fs_image.lo -MD -MP -MF libisofs/$(DEPDIR)/libisofs_libisofs_la-fs_image.Tpo -c -o libisofs/libisofs_libisofs_la-fs_image.lo `test -f 'libisofs/fs_image.c' || echo '$(srcdir)/'`libisofs/fs_image.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libisofs/$(DEPDIR)/libisofs_libisofs_la-fs_image.Tpo libisofs/$(DEPDIR)/libisofs_libisofs_la-fs_image.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libisofs/fs_image.c' object='libisofs/libisofs_libisofs_la-fs_image.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -c -o libisofs/libisofs_libisofs_la-fs_image.lo `test -f 'libisofs/fs_image.c' || echo '$(srcdir)/'`libisofs/fs_image.c libisofs/libisofs_libisofs_la-messages.lo: libisofs/messages.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -MT libisofs/libisofs_libisofs_la-messages.lo -MD -MP -MF libisofs/$(DEPDIR)/libisofs_libisofs_la-messages.Tpo -c -o libisofs/libisofs_libisofs_la-messages.lo `test -f 'libisofs/messages.c' || echo '$(srcdir)/'`libisofs/messages.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libisofs/$(DEPDIR)/libisofs_libisofs_la-messages.Tpo libisofs/$(DEPDIR)/libisofs_libisofs_la-messages.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libisofs/messages.c' object='libisofs/libisofs_libisofs_la-messages.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -c -o libisofs/libisofs_libisofs_la-messages.lo `test -f 'libisofs/messages.c' || echo '$(srcdir)/'`libisofs/messages.c libisofs/libisofs_libisofs_la-libiso_msgs.lo: libisofs/libiso_msgs.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -MT libisofs/libisofs_libisofs_la-libiso_msgs.lo -MD -MP -MF libisofs/$(DEPDIR)/libisofs_libisofs_la-libiso_msgs.Tpo -c -o libisofs/libisofs_libisofs_la-libiso_msgs.lo `test -f 'libisofs/libiso_msgs.c' || echo '$(srcdir)/'`libisofs/libiso_msgs.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libisofs/$(DEPDIR)/libisofs_libisofs_la-libiso_msgs.Tpo libisofs/$(DEPDIR)/libisofs_libisofs_la-libiso_msgs.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libisofs/libiso_msgs.c' object='libisofs/libisofs_libisofs_la-libiso_msgs.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -c -o libisofs/libisofs_libisofs_la-libiso_msgs.lo `test -f 'libisofs/libiso_msgs.c' || echo '$(srcdir)/'`libisofs/libiso_msgs.c libisofs/libisofs_libisofs_la-stream.lo: libisofs/stream.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -MT libisofs/libisofs_libisofs_la-stream.lo -MD -MP -MF libisofs/$(DEPDIR)/libisofs_libisofs_la-stream.Tpo -c -o libisofs/libisofs_libisofs_la-stream.lo `test -f 'libisofs/stream.c' || echo '$(srcdir)/'`libisofs/stream.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libisofs/$(DEPDIR)/libisofs_libisofs_la-stream.Tpo libisofs/$(DEPDIR)/libisofs_libisofs_la-stream.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libisofs/stream.c' object='libisofs/libisofs_libisofs_la-stream.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -c -o libisofs/libisofs_libisofs_la-stream.lo `test -f 'libisofs/stream.c' || echo '$(srcdir)/'`libisofs/stream.c libisofs/libisofs_libisofs_la-filter.lo: libisofs/filter.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -MT libisofs/libisofs_libisofs_la-filter.lo -MD -MP -MF libisofs/$(DEPDIR)/libisofs_libisofs_la-filter.Tpo -c -o libisofs/libisofs_libisofs_la-filter.lo `test -f 'libisofs/filter.c' || echo '$(srcdir)/'`libisofs/filter.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libisofs/$(DEPDIR)/libisofs_libisofs_la-filter.Tpo libisofs/$(DEPDIR)/libisofs_libisofs_la-filter.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libisofs/filter.c' object='libisofs/libisofs_libisofs_la-filter.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -c -o libisofs/libisofs_libisofs_la-filter.lo `test -f 'libisofs/filter.c' || echo '$(srcdir)/'`libisofs/filter.c libisofs/filters/libisofs_libisofs_la-external.lo: libisofs/filters/external.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -MT libisofs/filters/libisofs_libisofs_la-external.lo -MD -MP -MF libisofs/filters/$(DEPDIR)/libisofs_libisofs_la-external.Tpo -c -o libisofs/filters/libisofs_libisofs_la-external.lo `test -f 'libisofs/filters/external.c' || echo '$(srcdir)/'`libisofs/filters/external.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libisofs/filters/$(DEPDIR)/libisofs_libisofs_la-external.Tpo libisofs/filters/$(DEPDIR)/libisofs_libisofs_la-external.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libisofs/filters/external.c' object='libisofs/filters/libisofs_libisofs_la-external.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -c -o libisofs/filters/libisofs_libisofs_la-external.lo `test -f 'libisofs/filters/external.c' || echo '$(srcdir)/'`libisofs/filters/external.c libisofs/filters/libisofs_libisofs_la-zisofs.lo: libisofs/filters/zisofs.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -MT libisofs/filters/libisofs_libisofs_la-zisofs.lo -MD -MP -MF libisofs/filters/$(DEPDIR)/libisofs_libisofs_la-zisofs.Tpo -c -o libisofs/filters/libisofs_libisofs_la-zisofs.lo `test -f 'libisofs/filters/zisofs.c' || echo '$(srcdir)/'`libisofs/filters/zisofs.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libisofs/filters/$(DEPDIR)/libisofs_libisofs_la-zisofs.Tpo libisofs/filters/$(DEPDIR)/libisofs_libisofs_la-zisofs.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libisofs/filters/zisofs.c' object='libisofs/filters/libisofs_libisofs_la-zisofs.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -c -o libisofs/filters/libisofs_libisofs_la-zisofs.lo `test -f 'libisofs/filters/zisofs.c' || echo '$(srcdir)/'`libisofs/filters/zisofs.c libisofs/filters/libisofs_libisofs_la-gzip.lo: libisofs/filters/gzip.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -MT libisofs/filters/libisofs_libisofs_la-gzip.lo -MD -MP -MF libisofs/filters/$(DEPDIR)/libisofs_libisofs_la-gzip.Tpo -c -o libisofs/filters/libisofs_libisofs_la-gzip.lo `test -f 'libisofs/filters/gzip.c' || echo '$(srcdir)/'`libisofs/filters/gzip.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libisofs/filters/$(DEPDIR)/libisofs_libisofs_la-gzip.Tpo libisofs/filters/$(DEPDIR)/libisofs_libisofs_la-gzip.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libisofs/filters/gzip.c' object='libisofs/filters/libisofs_libisofs_la-gzip.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -c -o libisofs/filters/libisofs_libisofs_la-gzip.lo `test -f 'libisofs/filters/gzip.c' || echo '$(srcdir)/'`libisofs/filters/gzip.c libisofs/libisofs_libisofs_la-util.lo: libisofs/util.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -MT libisofs/libisofs_libisofs_la-util.lo -MD -MP -MF libisofs/$(DEPDIR)/libisofs_libisofs_la-util.Tpo -c -o libisofs/libisofs_libisofs_la-util.lo `test -f 'libisofs/util.c' || echo '$(srcdir)/'`libisofs/util.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libisofs/$(DEPDIR)/libisofs_libisofs_la-util.Tpo libisofs/$(DEPDIR)/libisofs_libisofs_la-util.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libisofs/util.c' object='libisofs/libisofs_libisofs_la-util.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -c -o libisofs/libisofs_libisofs_la-util.lo `test -f 'libisofs/util.c' || echo '$(srcdir)/'`libisofs/util.c libisofs/libisofs_libisofs_la-util_rbtree.lo: libisofs/util_rbtree.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -MT libisofs/libisofs_libisofs_la-util_rbtree.lo -MD -MP -MF libisofs/$(DEPDIR)/libisofs_libisofs_la-util_rbtree.Tpo -c -o libisofs/libisofs_libisofs_la-util_rbtree.lo `test -f 'libisofs/util_rbtree.c' || echo '$(srcdir)/'`libisofs/util_rbtree.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libisofs/$(DEPDIR)/libisofs_libisofs_la-util_rbtree.Tpo libisofs/$(DEPDIR)/libisofs_libisofs_la-util_rbtree.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libisofs/util_rbtree.c' object='libisofs/libisofs_libisofs_la-util_rbtree.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -c -o libisofs/libisofs_libisofs_la-util_rbtree.lo `test -f 'libisofs/util_rbtree.c' || echo '$(srcdir)/'`libisofs/util_rbtree.c libisofs/libisofs_libisofs_la-util_htable.lo: libisofs/util_htable.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -MT libisofs/libisofs_libisofs_la-util_htable.lo -MD -MP -MF libisofs/$(DEPDIR)/libisofs_libisofs_la-util_htable.Tpo -c -o libisofs/libisofs_libisofs_la-util_htable.lo `test -f 'libisofs/util_htable.c' || echo '$(srcdir)/'`libisofs/util_htable.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libisofs/$(DEPDIR)/libisofs_libisofs_la-util_htable.Tpo libisofs/$(DEPDIR)/libisofs_libisofs_la-util_htable.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libisofs/util_htable.c' object='libisofs/libisofs_libisofs_la-util_htable.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -c -o libisofs/libisofs_libisofs_la-util_htable.lo `test -f 'libisofs/util_htable.c' || echo '$(srcdir)/'`libisofs/util_htable.c libisofs/libisofs_libisofs_la-filesrc.lo: libisofs/filesrc.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -MT libisofs/libisofs_libisofs_la-filesrc.lo -MD -MP -MF libisofs/$(DEPDIR)/libisofs_libisofs_la-filesrc.Tpo -c -o libisofs/libisofs_libisofs_la-filesrc.lo `test -f 'libisofs/filesrc.c' || echo '$(srcdir)/'`libisofs/filesrc.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libisofs/$(DEPDIR)/libisofs_libisofs_la-filesrc.Tpo libisofs/$(DEPDIR)/libisofs_libisofs_la-filesrc.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libisofs/filesrc.c' object='libisofs/libisofs_libisofs_la-filesrc.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -c -o libisofs/libisofs_libisofs_la-filesrc.lo `test -f 'libisofs/filesrc.c' || echo '$(srcdir)/'`libisofs/filesrc.c libisofs/libisofs_libisofs_la-ecma119.lo: libisofs/ecma119.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -MT libisofs/libisofs_libisofs_la-ecma119.lo -MD -MP -MF libisofs/$(DEPDIR)/libisofs_libisofs_la-ecma119.Tpo -c -o libisofs/libisofs_libisofs_la-ecma119.lo `test -f 'libisofs/ecma119.c' || echo '$(srcdir)/'`libisofs/ecma119.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libisofs/$(DEPDIR)/libisofs_libisofs_la-ecma119.Tpo libisofs/$(DEPDIR)/libisofs_libisofs_la-ecma119.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libisofs/ecma119.c' object='libisofs/libisofs_libisofs_la-ecma119.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -c -o libisofs/libisofs_libisofs_la-ecma119.lo `test -f 'libisofs/ecma119.c' || echo '$(srcdir)/'`libisofs/ecma119.c libisofs/libisofs_libisofs_la-ecma119_tree.lo: libisofs/ecma119_tree.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -MT libisofs/libisofs_libisofs_la-ecma119_tree.lo -MD -MP -MF libisofs/$(DEPDIR)/libisofs_libisofs_la-ecma119_tree.Tpo -c -o libisofs/libisofs_libisofs_la-ecma119_tree.lo `test -f 'libisofs/ecma119_tree.c' || echo '$(srcdir)/'`libisofs/ecma119_tree.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libisofs/$(DEPDIR)/libisofs_libisofs_la-ecma119_tree.Tpo libisofs/$(DEPDIR)/libisofs_libisofs_la-ecma119_tree.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libisofs/ecma119_tree.c' object='libisofs/libisofs_libisofs_la-ecma119_tree.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -c -o libisofs/libisofs_libisofs_la-ecma119_tree.lo `test -f 'libisofs/ecma119_tree.c' || echo '$(srcdir)/'`libisofs/ecma119_tree.c libisofs/libisofs_libisofs_la-buffer.lo: libisofs/buffer.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -MT libisofs/libisofs_libisofs_la-buffer.lo -MD -MP -MF libisofs/$(DEPDIR)/libisofs_libisofs_la-buffer.Tpo -c -o libisofs/libisofs_libisofs_la-buffer.lo `test -f 'libisofs/buffer.c' || echo '$(srcdir)/'`libisofs/buffer.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libisofs/$(DEPDIR)/libisofs_libisofs_la-buffer.Tpo libisofs/$(DEPDIR)/libisofs_libisofs_la-buffer.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libisofs/buffer.c' object='libisofs/libisofs_libisofs_la-buffer.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -c -o libisofs/libisofs_libisofs_la-buffer.lo `test -f 'libisofs/buffer.c' || echo '$(srcdir)/'`libisofs/buffer.c libisofs/libisofs_libisofs_la-rockridge.lo: libisofs/rockridge.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -MT libisofs/libisofs_libisofs_la-rockridge.lo -MD -MP -MF libisofs/$(DEPDIR)/libisofs_libisofs_la-rockridge.Tpo -c -o libisofs/libisofs_libisofs_la-rockridge.lo `test -f 'libisofs/rockridge.c' || echo '$(srcdir)/'`libisofs/rockridge.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libisofs/$(DEPDIR)/libisofs_libisofs_la-rockridge.Tpo libisofs/$(DEPDIR)/libisofs_libisofs_la-rockridge.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libisofs/rockridge.c' object='libisofs/libisofs_libisofs_la-rockridge.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -c -o libisofs/libisofs_libisofs_la-rockridge.lo `test -f 'libisofs/rockridge.c' || echo '$(srcdir)/'`libisofs/rockridge.c libisofs/libisofs_libisofs_la-rockridge_read.lo: libisofs/rockridge_read.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -MT libisofs/libisofs_libisofs_la-rockridge_read.lo -MD -MP -MF libisofs/$(DEPDIR)/libisofs_libisofs_la-rockridge_read.Tpo -c -o libisofs/libisofs_libisofs_la-rockridge_read.lo `test -f 'libisofs/rockridge_read.c' || echo '$(srcdir)/'`libisofs/rockridge_read.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libisofs/$(DEPDIR)/libisofs_libisofs_la-rockridge_read.Tpo libisofs/$(DEPDIR)/libisofs_libisofs_la-rockridge_read.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libisofs/rockridge_read.c' object='libisofs/libisofs_libisofs_la-rockridge_read.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -c -o libisofs/libisofs_libisofs_la-rockridge_read.lo `test -f 'libisofs/rockridge_read.c' || echo '$(srcdir)/'`libisofs/rockridge_read.c libisofs/libisofs_libisofs_la-joliet.lo: libisofs/joliet.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -MT libisofs/libisofs_libisofs_la-joliet.lo -MD -MP -MF libisofs/$(DEPDIR)/libisofs_libisofs_la-joliet.Tpo -c -o libisofs/libisofs_libisofs_la-joliet.lo `test -f 'libisofs/joliet.c' || echo '$(srcdir)/'`libisofs/joliet.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libisofs/$(DEPDIR)/libisofs_libisofs_la-joliet.Tpo libisofs/$(DEPDIR)/libisofs_libisofs_la-joliet.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libisofs/joliet.c' object='libisofs/libisofs_libisofs_la-joliet.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -c -o libisofs/libisofs_libisofs_la-joliet.lo `test -f 'libisofs/joliet.c' || echo '$(srcdir)/'`libisofs/joliet.c libisofs/libisofs_libisofs_la-hfsplus.lo: libisofs/hfsplus.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -MT libisofs/libisofs_libisofs_la-hfsplus.lo -MD -MP -MF libisofs/$(DEPDIR)/libisofs_libisofs_la-hfsplus.Tpo -c -o libisofs/libisofs_libisofs_la-hfsplus.lo `test -f 'libisofs/hfsplus.c' || echo '$(srcdir)/'`libisofs/hfsplus.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libisofs/$(DEPDIR)/libisofs_libisofs_la-hfsplus.Tpo libisofs/$(DEPDIR)/libisofs_libisofs_la-hfsplus.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libisofs/hfsplus.c' object='libisofs/libisofs_libisofs_la-hfsplus.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -c -o libisofs/libisofs_libisofs_la-hfsplus.lo `test -f 'libisofs/hfsplus.c' || echo '$(srcdir)/'`libisofs/hfsplus.c libisofs/libisofs_libisofs_la-hfsplus_decompose.lo: libisofs/hfsplus_decompose.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -MT libisofs/libisofs_libisofs_la-hfsplus_decompose.lo -MD -MP -MF libisofs/$(DEPDIR)/libisofs_libisofs_la-hfsplus_decompose.Tpo -c -o libisofs/libisofs_libisofs_la-hfsplus_decompose.lo `test -f 'libisofs/hfsplus_decompose.c' || echo '$(srcdir)/'`libisofs/hfsplus_decompose.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libisofs/$(DEPDIR)/libisofs_libisofs_la-hfsplus_decompose.Tpo libisofs/$(DEPDIR)/libisofs_libisofs_la-hfsplus_decompose.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libisofs/hfsplus_decompose.c' object='libisofs/libisofs_libisofs_la-hfsplus_decompose.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -c -o libisofs/libisofs_libisofs_la-hfsplus_decompose.lo `test -f 'libisofs/hfsplus_decompose.c' || echo '$(srcdir)/'`libisofs/hfsplus_decompose.c libisofs/libisofs_libisofs_la-hfsplus_classes.lo: libisofs/hfsplus_classes.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -MT libisofs/libisofs_libisofs_la-hfsplus_classes.lo -MD -MP -MF libisofs/$(DEPDIR)/libisofs_libisofs_la-hfsplus_classes.Tpo -c -o libisofs/libisofs_libisofs_la-hfsplus_classes.lo `test -f 'libisofs/hfsplus_classes.c' || echo '$(srcdir)/'`libisofs/hfsplus_classes.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libisofs/$(DEPDIR)/libisofs_libisofs_la-hfsplus_classes.Tpo libisofs/$(DEPDIR)/libisofs_libisofs_la-hfsplus_classes.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libisofs/hfsplus_classes.c' object='libisofs/libisofs_libisofs_la-hfsplus_classes.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -c -o libisofs/libisofs_libisofs_la-hfsplus_classes.lo `test -f 'libisofs/hfsplus_classes.c' || echo '$(srcdir)/'`libisofs/hfsplus_classes.c libisofs/libisofs_libisofs_la-hfsplus_case.lo: libisofs/hfsplus_case.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -MT libisofs/libisofs_libisofs_la-hfsplus_case.lo -MD -MP -MF libisofs/$(DEPDIR)/libisofs_libisofs_la-hfsplus_case.Tpo -c -o libisofs/libisofs_libisofs_la-hfsplus_case.lo `test -f 'libisofs/hfsplus_case.c' || echo '$(srcdir)/'`libisofs/hfsplus_case.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libisofs/$(DEPDIR)/libisofs_libisofs_la-hfsplus_case.Tpo libisofs/$(DEPDIR)/libisofs_libisofs_la-hfsplus_case.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libisofs/hfsplus_case.c' object='libisofs/libisofs_libisofs_la-hfsplus_case.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -c -o libisofs/libisofs_libisofs_la-hfsplus_case.lo `test -f 'libisofs/hfsplus_case.c' || echo '$(srcdir)/'`libisofs/hfsplus_case.c libisofs/libisofs_libisofs_la-eltorito.lo: libisofs/eltorito.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -MT libisofs/libisofs_libisofs_la-eltorito.lo -MD -MP -MF libisofs/$(DEPDIR)/libisofs_libisofs_la-eltorito.Tpo -c -o libisofs/libisofs_libisofs_la-eltorito.lo `test -f 'libisofs/eltorito.c' || echo '$(srcdir)/'`libisofs/eltorito.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libisofs/$(DEPDIR)/libisofs_libisofs_la-eltorito.Tpo libisofs/$(DEPDIR)/libisofs_libisofs_la-eltorito.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libisofs/eltorito.c' object='libisofs/libisofs_libisofs_la-eltorito.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -c -o libisofs/libisofs_libisofs_la-eltorito.lo `test -f 'libisofs/eltorito.c' || echo '$(srcdir)/'`libisofs/eltorito.c libisofs/libisofs_libisofs_la-system_area.lo: libisofs/system_area.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -MT libisofs/libisofs_libisofs_la-system_area.lo -MD -MP -MF libisofs/$(DEPDIR)/libisofs_libisofs_la-system_area.Tpo -c -o libisofs/libisofs_libisofs_la-system_area.lo `test -f 'libisofs/system_area.c' || echo '$(srcdir)/'`libisofs/system_area.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libisofs/$(DEPDIR)/libisofs_libisofs_la-system_area.Tpo libisofs/$(DEPDIR)/libisofs_libisofs_la-system_area.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libisofs/system_area.c' object='libisofs/libisofs_libisofs_la-system_area.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -c -o libisofs/libisofs_libisofs_la-system_area.lo `test -f 'libisofs/system_area.c' || echo '$(srcdir)/'`libisofs/system_area.c libisofs/libisofs_libisofs_la-make_isohybrid_mbr.lo: libisofs/make_isohybrid_mbr.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -MT libisofs/libisofs_libisofs_la-make_isohybrid_mbr.lo -MD -MP -MF libisofs/$(DEPDIR)/libisofs_libisofs_la-make_isohybrid_mbr.Tpo -c -o libisofs/libisofs_libisofs_la-make_isohybrid_mbr.lo `test -f 'libisofs/make_isohybrid_mbr.c' || echo '$(srcdir)/'`libisofs/make_isohybrid_mbr.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libisofs/$(DEPDIR)/libisofs_libisofs_la-make_isohybrid_mbr.Tpo libisofs/$(DEPDIR)/libisofs_libisofs_la-make_isohybrid_mbr.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libisofs/make_isohybrid_mbr.c' object='libisofs/libisofs_libisofs_la-make_isohybrid_mbr.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -c -o libisofs/libisofs_libisofs_la-make_isohybrid_mbr.lo `test -f 'libisofs/make_isohybrid_mbr.c' || echo '$(srcdir)/'`libisofs/make_isohybrid_mbr.c libisofs/libisofs_libisofs_la-iso1999.lo: libisofs/iso1999.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -MT libisofs/libisofs_libisofs_la-iso1999.lo -MD -MP -MF libisofs/$(DEPDIR)/libisofs_libisofs_la-iso1999.Tpo -c -o libisofs/libisofs_libisofs_la-iso1999.lo `test -f 'libisofs/iso1999.c' || echo '$(srcdir)/'`libisofs/iso1999.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libisofs/$(DEPDIR)/libisofs_libisofs_la-iso1999.Tpo libisofs/$(DEPDIR)/libisofs_libisofs_la-iso1999.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libisofs/iso1999.c' object='libisofs/libisofs_libisofs_la-iso1999.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -c -o libisofs/libisofs_libisofs_la-iso1999.lo `test -f 'libisofs/iso1999.c' || echo '$(srcdir)/'`libisofs/iso1999.c libisofs/libisofs_libisofs_la-data_source.lo: libisofs/data_source.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -MT libisofs/libisofs_libisofs_la-data_source.lo -MD -MP -MF libisofs/$(DEPDIR)/libisofs_libisofs_la-data_source.Tpo -c -o libisofs/libisofs_libisofs_la-data_source.lo `test -f 'libisofs/data_source.c' || echo '$(srcdir)/'`libisofs/data_source.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libisofs/$(DEPDIR)/libisofs_libisofs_la-data_source.Tpo libisofs/$(DEPDIR)/libisofs_libisofs_la-data_source.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libisofs/data_source.c' object='libisofs/libisofs_libisofs_la-data_source.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -c -o libisofs/libisofs_libisofs_la-data_source.lo `test -f 'libisofs/data_source.c' || echo '$(srcdir)/'`libisofs/data_source.c libisofs/libisofs_libisofs_la-aaip_0_2.lo: libisofs/aaip_0_2.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -MT libisofs/libisofs_libisofs_la-aaip_0_2.lo -MD -MP -MF libisofs/$(DEPDIR)/libisofs_libisofs_la-aaip_0_2.Tpo -c -o libisofs/libisofs_libisofs_la-aaip_0_2.lo `test -f 'libisofs/aaip_0_2.c' || echo '$(srcdir)/'`libisofs/aaip_0_2.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libisofs/$(DEPDIR)/libisofs_libisofs_la-aaip_0_2.Tpo libisofs/$(DEPDIR)/libisofs_libisofs_la-aaip_0_2.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libisofs/aaip_0_2.c' object='libisofs/libisofs_libisofs_la-aaip_0_2.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -c -o libisofs/libisofs_libisofs_la-aaip_0_2.lo `test -f 'libisofs/aaip_0_2.c' || echo '$(srcdir)/'`libisofs/aaip_0_2.c libisofs/libisofs_libisofs_la-md5.lo: libisofs/md5.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -MT libisofs/libisofs_libisofs_la-md5.lo -MD -MP -MF libisofs/$(DEPDIR)/libisofs_libisofs_la-md5.Tpo -c -o libisofs/libisofs_libisofs_la-md5.lo `test -f 'libisofs/md5.c' || echo '$(srcdir)/'`libisofs/md5.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libisofs/$(DEPDIR)/libisofs_libisofs_la-md5.Tpo libisofs/$(DEPDIR)/libisofs_libisofs_la-md5.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libisofs/md5.c' object='libisofs/libisofs_libisofs_la-md5.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -c -o libisofs/libisofs_libisofs_la-md5.lo `test -f 'libisofs/md5.c' || echo '$(srcdir)/'`libisofs/md5.c demo/demo_demo-demo.o: demo/demo.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_demo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT demo/demo_demo-demo.o -MD -MP -MF demo/$(DEPDIR)/demo_demo-demo.Tpo -c -o demo/demo_demo-demo.o `test -f 'demo/demo.c' || echo '$(srcdir)/'`demo/demo.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) demo/$(DEPDIR)/demo_demo-demo.Tpo demo/$(DEPDIR)/demo_demo-demo.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='demo/demo.c' object='demo/demo_demo-demo.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_demo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o demo/demo_demo-demo.o `test -f 'demo/demo.c' || echo '$(srcdir)/'`demo/demo.c demo/demo_demo-demo.obj: demo/demo.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_demo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT demo/demo_demo-demo.obj -MD -MP -MF demo/$(DEPDIR)/demo_demo-demo.Tpo -c -o demo/demo_demo-demo.obj `if test -f 'demo/demo.c'; then $(CYGPATH_W) 'demo/demo.c'; else $(CYGPATH_W) '$(srcdir)/demo/demo.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) demo/$(DEPDIR)/demo_demo-demo.Tpo demo/$(DEPDIR)/demo_demo-demo.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='demo/demo.c' object='demo/demo_demo-demo.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_demo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o demo/demo_demo-demo.obj `if test -f 'demo/demo.c'; then $(CYGPATH_W) 'demo/demo.c'; else $(CYGPATH_W) '$(srcdir)/demo/demo.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs -rm -rf demo/.libs demo/_libs -rm -rf libisofs/.libs libisofs/_libs -rm -rf libisofs/filters/.libs libisofs/filters/_libs distclean-libtool: -rm -f libtool config.lt install-nodist_pkgconfigDATA: $(nodist_pkgconfig_DATA) @$(NORMAL_INSTALL) @list='$(nodist_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-nodist_pkgconfigDATA: @$(NORMAL_UNINSTALL) @list='$(nodist_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) install-libincludeHEADERS: $(libinclude_HEADERS) @$(NORMAL_INSTALL) @list='$(libinclude_HEADERS)'; test -n "$(libincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libincludedir)" || 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)$(libincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(libincludedir)" || exit $$?; \ done uninstall-libincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(libinclude_HEADERS)'; test -n "$(libincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(libincludedir)'; $(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" 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-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 -rm -f cscope.out cscope.in.out cscope.po.out cscope.files distdir: $(DISTFILES) $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(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 -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) | GZIP=$(GZIP_ENV) gzip -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-tarZ: distdir @echo WARNING: "Support for shar distribution archives 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 distribution archives compressed with" \ "legacy program 'compress' is deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 shar $(distdir) | GZIP=$(GZIP_ENV) gzip -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*) \ GZIP=$(GZIP_ENV) 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*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac chmod -R a-w $(distdir) chmod u+w $(distdir) mkdir $(distdir)/_build $(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 \ && ../configure \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ --srcdir=.. --prefix="$$dc_install_base" \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(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-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(libincludedir)"; 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: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) -rm -f demo/$(DEPDIR)/$(am__dirstamp) -rm -f demo/$(am__dirstamp) -rm -f libisofs/$(DEPDIR)/$(am__dirstamp) -rm -f libisofs/$(am__dirstamp) -rm -f libisofs/filters/$(DEPDIR)/$(am__dirstamp) -rm -f libisofs/filters/$(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-libLTLIBRARIES clean-libtool clean-local \ clean-noinstPROGRAMS mostlyclean-am distclean: distclean-am -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf demo/$(DEPDIR) libisofs/$(DEPDIR) libisofs/filters/$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-libtool distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-data-local install-libincludeHEADERS \ install-nodist_pkgconfigDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-exec-hook 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 $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -rf demo/$(DEPDIR) libisofs/$(DEPDIR) libisofs/filters/$(DEPDIR) -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-libLTLIBRARIES uninstall-libincludeHEADERS \ uninstall-local uninstall-nodist_pkgconfigDATA .MAKE: install-am install-exec-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--refresh check check-am clean \ clean-cscope clean-generic clean-libLTLIBRARIES clean-libtool \ clean-local clean-noinstPROGRAMS cscope cscopelist-am ctags \ ctags-am dist dist-all dist-bzip2 dist-gzip dist-lzip \ dist-shar dist-tarZ dist-xz dist-zip distcheck distclean \ distclean-compile distclean-generic 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-data-local install-dvi \ install-dvi-am install-exec install-exec-am install-exec-hook \ install-html install-html-am install-info install-info-am \ install-libLTLIBRARIES install-libincludeHEADERS install-man \ install-nodist_pkgconfigDATA 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-libLTLIBRARIES \ uninstall-libincludeHEADERS uninstall-local \ uninstall-nodist_pkgconfigDATA install-exec-hook: $(LIBBURNIA_LDCONFIG_CMD) "$(DESTDIR)$(libdir)" || echo 'NOTE: Explicit dynamic library configuration failed. If needed, configure manually for:' "$(DESTDIR)$(libdir)" # ts A90806 # This includes fsource.h and thus is no API demo # demo_lsl_CPPFLAGS = -Ilibisofs # demo_lsl_LDADD = $(libisofs_libisofs_la_OBJECTS) $(libisofs_libisofs_la_LIBADD) # demo_lsl_SOURCES = demo/lsl.c # ts A90806 # This includes fsource.h and thus is no API demo # demo_cat_CPPFLAGS = -Ilibisofs # demo_cat_LDADD = $(libisofs_libisofs_la_OBJECTS) $(libisofs_libisofs_la_LIBADD) # demo_cat_SOURCES = demo/cat.c # ts A90806 # This inlcudes buffer.h and thus is no API demo # demo_catbuffer_CPPFLAGS = -Ilibisofs # demo_catbuffer_LDADD = $(libisofs_libisofs_la_OBJECTS) \ # $(libisofs_libisofs_la_LIBADD) # demo_catbuffer_SOURCES = demo/cat_buffer.c # ts A90807 # Consolidated in demo/demo # demo_tree_CPPFLAGS = -Ilibisofs # demo_tree_LDADD = $(libisofs_libisofs_la_OBJECTS) \ # $(libisofs_libisofs_la_LIBADD) # demo_tree_SOURCES = demo/tree.c # ts A90807 # Consolidated in demo/demo # demo_find_CPPFLAGS = -Ilibisofs # demo_find_LDADD = $(libisofs_libisofs_la_OBJECTS) \ # $(libisofs_libisofs_la_LIBADD) # demo_find_SOURCES = demo/find.c # ts A90806 # This inlcudes lots of internal .h files and thus is no API demo # demo_ecma119tree_CPPFLAGS = -Ilibisofs # demo_ecma119tree_LDADD = $(libisofs_libisofs_la_OBJECTS) \ # $(libisofs_libisofs_la_LIBADD) # demo_ecma119tree_SOURCES = demo/ecma119_tree.c # ts A90807 # Consolidated in demo/demo # demo_iso_CPPFLAGS = -Ilibisofs # demo_iso_LDADD = $(libisofs_libisofs_la_OBJECTS) $(libisofs_libisofs_la_LIBADD) # demo_iso_SOURCES = demo/iso.c # ts A90807 # Consolidated in demo/demo # demo_isoread_CPPFLAGS = -Ilibisofs # demo_isoread_LDADD = $(libisofs_libisofs_la_OBJECTS) \ # $(libisofs_libisofs_la_LIBADD) # demo_isoread_SOURCES = demo/iso_read.c # ts A90807 # Consolidated in demo/demo # demo_isocat_CPPFLAGS = -Ilibisofs # demo_isocat_LDADD = $(libisofs_libisofs_la_OBJECTS) \ # $(libisofs_libisofs_la_LIBADD) # demo_isocat_SOURCES = demo/iso_cat.c # ts A90807 # Consolidated in demo/demo # demo_isomodify_CPPFLAGS = -Ilibisofs # demo_isomodify_LDADD = $(libisofs_libisofs_la_OBJECTS) \ # $(libisofs_libisofs_la_LIBADD) # demo_isomodify_SOURCES = demo/iso_modify.c # ts A90807 # Consolidated in demo/demo # demo_isoms_CPPFLAGS = -Ilibisofs # demo_isoms_LDADD = $(libisofs_libisofs_la_OBJECTS) \ # $(libisofs_libisofs_la_LIBADD) # demo_isoms_SOURCES = demo/iso_ms.c # demo_isogrow_CPPFLAGS = -Ilibisofs -Ilibburn # demo_isogrow_LDADD = $(libisofs_libisofs_la_OBJECTS) \ # $(libisofs_libisofs_la_LIBADD) \ # -lburn # demo_isogrow_SOURCES = demo/iso_grow.c # ## Build unit test # check_PROGRAMS = \ # test/test # # test_test_CPPFLAGS = -Ilibisofs # test_test_LDADD = $(libisofs_libisofs_la_OBJECTS) \ # $(libisofs_libisofs_la_LIBADD) -lcunit # test_test_LDFLAGS = -L.. -lm # # test_test_SOURCES = \ # test/test.h \ # test/test.c \ # test/test_node.c \ # test/test_image.c \ # test/test_tree.c \ # test/test_util.c \ # test/test_rockridge.c \ # test/test_stream.c \ # test/mocked_fsrc.h \ # test/mocked_fsrc.c # "make clean" shall remove a few stubborn .libs directories # which George Danchev reported Dec 03 2011. # Learned from: http://www.gnu.org/software/automake/manual/automake.html#Clean clean-local: -rm -rf demo/.libs doc: doc/html doc/html: doc/doxygen.conf $(RM) -r doc/html; \ doxygen doc/doxygen.conf; install-data-local: if [ -d doc/html ]; then \ $(mkinstalldirs) $(docdir)/html; \ $(INSTALL_DATA) doc/html/* $(docdir)/html; \ fi uninstall-local: rm -rf $(docdir) # 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: libisofs-1.4.2/config.guess0000755000175700017510000012760712132767012012617 00000000000000#! /bin/sh # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # 2011, 2012 Free Software Foundation, Inc. timestamp='2012-09-25' # 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 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, 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 Per Bothner. Please send patches (context # diff format) to and include a ChangeLog # entry. # # This script attempts to guess a canonical system name similar to # config.sub. If it succeeds, it prints the system name on stdout, and # exits with 0. Otherwise, it exits with 1. # # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -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 (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 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 trap 'exit 1' 1 2 15 # 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. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { 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) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; 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 ; set_cc_for_build= ;' # 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) >/dev/null 2>&1 ; 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 # 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". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-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. case "${UNAME_MACHINE_ARCH}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $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 # 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/[-_].*/\./'` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; *:SolidBSD:*:*) echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} exit ;; macppc:MirBSD:*:*) echo powerpc-unknown-mirbsd${UNAME_RELEASE} exit ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit ;; alpha:OSF1:*:*) 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. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition exit ;; *:z/VM:*:*) echo s390-ibm-zvmoe exit ;; *:OS400:*:*) echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit ;; arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) echo i386-pc-auroraux${UNAME_RELEASE} exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) eval $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 [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH="x86_64" fi fi echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; 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. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; 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'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit ;; 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) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit ;; # 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:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} exit ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $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; } echo mips-mips-riscos${UNAME_RELEASE} exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $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 echo "$SYSTEM_NAME" else echo rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit ;; *: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 [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit ;; 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 [ -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 [ "${HP_ARCH}" = "" ]; then eval $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 [ ${HP_ARCH} = "hppa2.0w" ] then eval $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 echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit ;; 3050*:HI-UX:*:*) eval $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; } echo unknown-hitachi-hiuxwe2 exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit ;; 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*:*) echo c34-convex-bsd exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; 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:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; 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/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 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/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` case ${UNAME_PROCESSOR} in amd64) echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; *) echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; esac exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; *:MINGW64*:*) echo ${UNAME_MACHINE}-pc-mingw64 exit ;; *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; i*:MSYS*:*) echo ${UNAME_MACHINE}-pc-msys exit ;; i*:windows32*:*) # uname -m includes "-pc" on this system. echo ${UNAME_MACHINE}-mingw32 exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; *:Interix*:*) case ${UNAME_MACHINE} in x86) echo i586-pc-interix${UNAME_RELEASE} exit ;; authenticamd | genuineintel | EM64T) echo x86_64-unknown-interix${UNAME_RELEASE} exit ;; IA64) echo ia64-unknown-interix${UNAME_RELEASE} exit ;; esac ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; 8664:Windows_NT:*) echo x86_64-pc-mks exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i586-pc-interix exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; *:GNU:*:*) # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; aarch64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` 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="libc1" ; else LIBC="" ; fi echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} exit ;; arm*:Linux:*:*) eval $set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then echo ${UNAME_MACHINE}-unknown-linux-gnu else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then echo ${UNAME_MACHINE}-unknown-linux-gnueabi else echo ${UNAME_MACHINE}-unknown-linux-gnueabihf fi fi exit ;; avr32*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; cris:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-gnu exit ;; crisv32:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-gnu exit ;; frv:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; hexagon:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; i*86:Linux:*:*) LIBC=gnu eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __dietlibc__ LIBC=dietlibc #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` echo "${UNAME_MACHINE}-pc-linux-${LIBC}" exit ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; m32r*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; mips:Linux:*:* | mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef ${UNAME_MACHINE} #undef ${UNAME_MACHINE}el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=${UNAME_MACHINE}el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=${UNAME_MACHINE} #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } ;; or32:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; padre:Linux:*:*) echo sparc-unknown-linux-gnu exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-gnu exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-gnu ;; PA8*) echo hppa2.0-unknown-linux-gnu ;; *) echo hppa-unknown-linux-gnu ;; esac exit ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-gnu exit ;; ppc:Linux:*:*) echo powerpc-unknown-linux-gnu exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux exit ;; sh64*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; tile*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; vax:Linux:*:*) echo ${UNAME_MACHINE}-dec-linux-gnu exit ;; x86_64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; xtensa*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; 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. echo i386-sequent-sysv4 exit ;; 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. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit ;; i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit ;; 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 echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit ;; 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 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit ;; 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 configury will decide that # this is a cross-build. echo i586-pc-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; paragon:*:*:*) echo i860-intel-osf1 exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit ;; 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*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. echo ${UNAME_MACHINE}-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. echo i586-pc-haiku exit ;; x86_64:Haiku:*:*) echo x86_64-unknown-haiku exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit ;; SX-7:SUPER-UX:*:*) echo sx7-nec-superux${UNAME_RELEASE} exit ;; SX-8:SUPER-UX:*:*) echo sx8-nec-superux${UNAME_RELEASE} exit ;; SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux${UNAME_RELEASE} exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown case $UNAME_PROCESSOR in i386) eval $set_cc_for_build if [ "$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 UNAME_PROCESSOR="x86_64" fi fi ;; unknown) UNAME_PROCESSOR=powerpc ;; esac echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; NEO-?:NONSTOP_KERNEL:*:*) echo neo-tandem-nsk${UNAME_RELEASE} exit ;; NSE-*:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit ;; *: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 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit ;; *:ITS:*:*) echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} exit ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case "${UNAME_MACHINE}" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; esac ;; *:XENIX:*:SysV) echo i386-pc-xenix exit ;; i*86:skyos:*:*) echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' exit ;; i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos exit ;; i*86:AROS:*:*) echo ${UNAME_MACHINE}-pc-aros exit ;; x86_64:VMkernel:*:*) echo ${UNAME_MACHINE}-unknown-esx exit ;; esac eval $set_cc_for_build cat >$dummy.c < # include #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 (__arm) && defined (__acorn) && defined (__unix) printf ("arm-acorn-riscix\n"); exit (0); #endif #if defined (hp300) && !defined (hpux) printf ("m68k-hp-bsd\n"); exit (0); #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 printf ("vax-dec-ultrix\n"); exit (0); # 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; } # Convex versions that predate uname can use getsysinfo(1) if [ -x /usr/convex/getsysinfo ] then case `getsysinfo -f cpu_type` in c1*) echo c1-convex-bsd exit ;; c2*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; c34*) echo c34-convex-bsd exit ;; c38*) echo c38-convex-bsd exit ;; c4*) echo c4-convex-bsd exit ;; esac fi cat >&2 < in order to provide the needed information to handle your system. config.guess timestamp = $timestamp 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` /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 exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: libisofs-1.4.2/version.h.in0000644000175700017510000000025011112746253012523 00000000000000#define LIBISOFS_MAJOR_VERSION @LIBISOFS_MAJOR_VERSION@ #define LIBISOFS_MINOR_VERSION @LIBISOFS_MINOR_VERSION@ #define LIBISOFS_MICRO_VERSION @LIBISOFS_MICRO_VERSION@ libisofs-1.4.2/AUTHORS0000644000175700017510000000007711757220507011343 00000000000000Vreixo Formoso Mario Danic Vladimir Serbinenko Thomas Schmitt libisofs-1.4.2/acinclude.m40000644000175700017510000001433612433642044012463 00000000000000AC_DEFUN([LIBBURNIA_SET_FLAGS], [ case $target_os in freebsd* | netbsd*) LDFLAGS="$LDFLAGS -L/usr/local/lib" CPPFLAGS="$CPPFLAGS -I/usr/local/include" ;; esac ]) AC_DEFUN([TARGET_SHIZZLE], [ ARCH="" LIBBURNIA_PKGCONFDIR="$libdir"/pkgconfig AC_MSG_CHECKING([target operating system]) LIBBURNIA_LDCONFIG_CMD="echo 'No ldconfig run performed. If needed, configure manually for:'" case $target in *-*-linux*) ARCH=linux LIBBURN_ARCH_LIBS= LIBBURNIA_LDCONFIG_CMD=ldconfig ;; *-*-freebsd*) ARCH=freebsd LIBBURN_ARCH_LIBS=-lcam # This may later be overridden by configure --enable-libdir-pkgconfig LIBBURNIA_PKGCONFDIR=$(echo "$libdir" | sed 's/\/lib$/\/libdata/')/pkgconfig ;; *) ARCH= LIBBURN_ARCH_LIBS= # AC_ERROR([You are attempting to compile for an unsupported platform]) ;; esac AC_MSG_RESULT([$ARCH]) ]) dnl LIBBURNIA_CHECK_ICONV is by Thomas Schmitt, libburnia project dnl It is based on gestures from: dnl iconv.m4 serial AM7 (gettext-0.18) dnl Copyright (C) 2000-2002, 2007-2009 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. dnl AC_DEFUN([LIBBURNIA_CHECK_ICONV], [ dnl Check whether it is allowed to link with -liconv AC_MSG_CHECKING([for iconv() in separate -liconv ]) libburnia_liconv="no" libburnia_save_LIBS="$LIBS" LIBS="$LIBS -liconv" AC_TRY_LINK([#include #include ], [iconv_t cd = iconv_open("",""); iconv(cd,NULL,NULL,NULL,NULL); iconv_close(cd);], [libburnia_liconv="yes"], [LIBS="$libburnia_save_LIBS"] ) AC_MSG_RESULT([$libburnia_liconv]) if test x"$libburnia_save_LIBS" = x"$LIBS" then dnl GNU iconv has no function iconv() but libiconv() and a macro iconv() dnl It is not tested whether this is detected by above macro. AC_CHECK_LIB(iconv, libiconv, , ) fi dnl Check for iconv(..., const char **inbuf, ...) AC_MSG_CHECKING([for const qualifier with iconv() ]) AC_TRY_COMPILE([ #include #include size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft); ], [], [libburnia_iconv_const=""], [libburnia_iconv_const="const"] ) AC_DEFINE_UNQUOTED([ICONV_CONST], [$libburnia_iconv_const]) test -z "$libburnia_iconv_const" && libburnia_iconv_const="no" AC_MSG_RESULT([$libburnia_iconv_const]) ]) dnl LIBBURNIA_ASSERT_ICONV is by Thomas Schmitt, libburnia project dnl AC_DEFUN([LIBBURNIA_ASSERT_ICONV], [ if test x$LIBISOFS_ASSUME_ICONV = x then dnl Check for the essential gestures of libisofs/util.c AC_MSG_CHECKING([for iconv() to be accessible now ]) AC_TRY_LINK([ #include #include #include #include #include #include #include #include #include #include #include ], [iconv_t cd = iconv_open("",""); iconv(cd,NULL,NULL,NULL,NULL); iconv_close(cd); ], [iconv_test="yes"], [iconv_test="no"] ) AC_MSG_RESULT([$iconv_test]) if test x$iconv_test = xno then echo >&2 echo "Cannot get function iconv() to work. Configuration aborted." >&2 echo "Check whether your system needs a separate libiconv installed." >&2 echo "If it is installed but not found, try something like" >&2 echo ' export LDFLAGS="$LDFLAGS -L/usr/local/lib"' >&2 echo ' export CPPFLAGS="$CPPFLAGS -I/usr/local/include"' >&2 echo ' export LIBS="$LIBS -liconv"' >&2 echo "You may override this test by exporting variable" >&2 echo " LIBISOFS_ASSUME_ICONV=yes" >&2 echo >&2 (exit 1); exit 1; fi fi ]) dnl LIBISOFS_ASSERT_VERS_LIBS is by Thomas Schmitt, libburnia project dnl It tests whether -Wl,--version-script=... works with the compiler AC_DEFUN([LIBISOFS_ASSERT_VERS_LIBS], [ libburnia_save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -Wl,--version-script=libisofs/libisofs.ver" AC_TRY_LINK([#include ], [printf("Hello\n");], [vers_libs_test="yes"], [vers_libs_test="no"]) if test x$vers_libs_test = xno then LDFLAGS="$libburnia_save_LDFLAGS" fi ]) dnl LIBBURNIA_SET_PKGCONFIG determines the install directory for the *.pc file. dnl Important: Must be performed _after_ TARGET_SHIZZLE dnl AC_DEFUN([LIBBURNIA_SET_PKGCONFIG], [ ### for testing --enable-libdir-pkgconfig on Linux ### LIBBURNIA_PKGCONFDIR="$libdir"data/pkgconfig if test "x$LIBBURNIA_PKGCONFDIR" = "x$libdir"/pkgconfig then dummy=dummy else AC_ARG_ENABLE(libdir-pkgconfig, [ --enable-libdir-pkgconfig Install to $libdir/pkgconfig on any OS, default=no], , enable_libdir_pkgconfig="no") AC_MSG_CHECKING([for --enable-libdir-pkgconfig]) if test "x$enable_libdir_pkgconfig" = xyes then LIBBURNIA_PKGCONFDIR="$libdir"/pkgconfig fi AC_MSG_RESULT([$enable_libdir_pkgconfig]) fi libburnia_pkgconfig_override="no" AC_ARG_ENABLE(pkgconfig-path, [ --enable-pkgconfig-path=DIR Absolute path of directory for libisofs-*.pc], libburnia_pkgconfig_override="yes" , enable_pkgconfig_path="none") AC_MSG_CHECKING([for overridden pkgconfig directory path]) if test "x$enable_pkgconfig_path" = xno then libburnia_pkgconfig_override="no" fi if test "x$enable_pkgconfig_path" = x -o "x$enable_pkgconfig_path" = xyes then libburnia_pkgconfig_override="invalid argument" fi if test "x$libburnia_pkgconfig_override" = xyes then LIBBURNIA_PKGCONFDIR="$enable_pkgconfig_path" AC_MSG_RESULT([$LIBBURNIA_PKGCONFDIR]) else AC_MSG_RESULT([$libburnia_pkgconfig_override]) fi AC_SUBST(LIBBURNIA_PKGCONFDIR) dnl For debugging only ### AC_MSG_RESULT([LIBBURNIA_PKGCONFDIR = $LIBBURNIA_PKGCONFDIR]) ]) dnl LIBBURNIA_TRY_TIMEZONE is by Thomas Schmitt, libburnia project dnl It tests whether the global variable exists and is suitable for dnl integer arithmetics. AC_DEFUN([LIBBURNIA_TRY_TIMEZONE], [ echo -n "checking for timezone variable ... " AC_TRY_LINK([ #include ], [long int i; i = 1 - timezone; ], [LIBBURNIA_TIMEZONE="timezone"], [LIBBURNIA_TIMEZONE="0"] ) echo "$LIBBURNIA_TIMEZONE" ]) libisofs-1.4.2/compile0000755000175700017510000000717311112746612011650 00000000000000#! /bin/sh # Wrapper for compilers which do not understand `-c -o'. scriptversion=2005-05-14.22 # Copyright (C) 1999, 2000, 2003, 2004, 2005 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, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # 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 # . 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 . EOF exit $? ;; -v | --v*) echo "compile $scriptversion" exit $? ;; esac ofile= cfile= eat= 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 -e 's|^.*/||' -e '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 mv "$cofile" "$ofile" elif test -f "${cofile}bj"; then mv "${cofile}bj" "$ofile" fi rmdir "$lockdir" exit $ret # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-end: "$" # End: libisofs-1.4.2/doc/0000755000175700017510000000000012626306721011113 500000000000000libisofs-1.4.2/doc/checksums.txt0000644000175700017510000003365611335520406013570 00000000000000 Description of libisofs MD5 checksumming by Thomas Schmitt - mailto:scdbackup@gmx.net Libburnia project - mailto:libburn-hackers@pykix.org 26 Aug 2009 MD5 is a 128 bit message digest with a very low probability to be the same for any pair of differing data files. It is described in RFC 1321. and can be computed e.g. by program md5sum. libisofs can equip its images with MD5 checksums for superblock, directory tree, the whole session, and for each single data file. See libisofs.h, iso_write_opts_set_record_md5(). The data file checksums get loaded together with the directory tree if this is enabled by iso_read_opts_set_no_md5(). Loaded checksums can be inquired by iso_image_get_session_md5() and iso_file_get_md5(). Stream recognizable checksum tags occupy exactly one block each. They can be detected by submitting a block to iso_util_decode_md5_tag(). libisofs has own MD5 computation functions: iso_md5_start(), iso_md5_compute(), iso_md5_clone(), iso_md5_end(), iso_md5_match() Representation in the Image There may be several stream recognizable checksum tags and a compact array of MD5 items at the end of the session. The latter allows to quickly load many file checksums from media with slow random access. The Checksum Array Location and layout of the checksum array is recorded as AAIP attribute "isofs.ca" of the root node. See doc/susp_aaip_2_0.txt for a general description of AAIP and doc/susp_aaip_isofs_names.txt for the layout of "isofs.ca". The single data files hold an index to their MD5 checksum in individual AAIP attributes "isofs.cx". Index I means: array base address + 16 * I. If there are N checksummed data files then the array consists of N + 2 entries with 16 bytes each. Entry number 0 holds a session checksum which covers the range from the session start block up to (but not including) the start block of the checksum area. This range is described by attribute "isofs.ca" of the root node. Entries 1 to N hold the checksums of individual data files. Entry number N + 1 holds the MD5 checksum of entries 0 to N. The Checksum Tags Because the inquiry of AAIP attributes demands loading of the image tree, there are also checksum tags which can be detected on the fly when reading and checksumming the session from its start point as learned from a media table-of-content. The superblock checksum tag is written after the ECMA-119 volume descriptors. The tree checksum tag is written after the ECMA-119 directory entries. The session checksum tag is written after all payload including the checksum array. (Then follows eventual padding.) The tags are single lines of printable text at the very beginning of a block of 2048 bytes. They have the following format: Tag_id pos=# range_start=# range_size=# [session_start|next=#] md5=# self=#\n Tag_id distinguishes the following tag types "libisofs_rlsb32_checksum_tag_v1" Relocated 64 kB superblock tag "libisofs_sb_checksum_tag_v1" Superblock tag "libisofs_tree_checksum_tag_v1" Directory tree tag "libisofs_checksum_tag_v1" Session tag A relocated superblock may appear at LBA 0 of an image which was produced for being stored in a disk file or on overwriteable media (e.g. DVD+RW, BD-RE). Typically there is a first session recorded with a superblock at LBA 32 and the next session may follow shortly after its session tag. (Typically at the next block address which is divisible by 32.) Normally no session starts after the address given by parameter session_start=. Session oriented media like CD-R[W], DVD+R, BD-R will have no relocated superblock but rather bear a table-of-content on media level (to be inquired by MMC commands). Example: A relocated superblock which points to the last session. Then the first session which starts at Logical Block Address 32. The following sessions have the same structure as the first one. LBA 0: <... ECMA-119 System Area and Volume Descriptors ...> LBA 18: libisofs_rlsb32_checksum_tag_v1 pos=18 range_start=0 range_size=18 session_start=311936 md5=6fd252d5b1db52b3c5193447081820e4 self=526f7a3c7fefce09754275c6b924b6d9 <... padding up to LBA 32 ...> LBA 32: <... First Session: ECMA-119 System Area and Volume Descriptors ...> libisofs_sb_checksum_tag_v1 pos=50 range_start=32 range_size=18 md5=17471035f1360a69eedbd1d0c67a6aa2 self=52d602210883eeababfc9cd287e28682 <... ECMA-119 Directory Entries (the tree of file names) ...> LBA 334: libisofs_tree_checksum_tag_v1 pos=334 range_start=32 range_size=302 md5=41acd50285339be5318decce39834a45 self=fe100c338c8f9a494a5432b5bfe6bf3c <... Data file payload and checksum array ...> LBA 81554: libisofs_checksum_tag_v1 pos=81554 range_start=32 range_size=81522 md5=8adb404bdf7f5c0a078873bb129ee5b9 self=57c2c2192822b658240d62cbc88270cb <... more sessions ...> LBA 311936: <... Last Session: ECMA-119 System Area and Volume Descriptors ...> LBA 311954: libisofs_sb_checksum_tag_v1 pos=311954 range_start=311936 range_size=18 next=312286 md5=7f1586e02ac962432dc859a4ae166027 self=2c5fce263cd0ca6984699060f6253e62 <... Last Session: tree, tree checksum tag, data payload, session tag ...> There are several tag parameters. Addresses are given as decimal numbers, MD5 checksums as strings of 32 hex digits. pos= gives the block address where the tag supposes itself to be stored. If this does not match the block address where the tag is found then this either indicates that the tag is payload of the image or that the image has been relocated. (The latter makes the image unusable.) range_start= The block address where the session is supposed to start. If this does not match the session start on media then the volume descriptors of the image have been relocated. (This can happen with overwriteable media. If checksumming started at LBA 0 and finds range_start=32, then one has to restart checksumming at LBA 32. See libburn/doc/cookbook.txt "ISO 9660 multi-session emulation on overwriteable media" for background information.) range_size= The number of blocks beginning at range_start which are covered by the checksum of the tag. Only with superblock tag and tree tag: next= The block address where the next tag is supposed to be found. This is to avoid the small possibility that a checksum tag with matching position is part of a directory entry or data file. The superblock tag is quite uniquely placed directly after the ECMA-119 Volume Descriptor Set Terminator where no such cleartext is supposed to reside by accident. Only with relocated 64 kB superblock tag: session_start= The start block address (System Area) of the session to which the relocated superblock points. md5= The checksum payload of the tag as lower case hex digits. self= The MD5 checksum of the tag itself up to and including the last hex digit of parameter "md5=". The newline character at the end is mandatory. After that newline there may follow more lines. Their meaning is not necessarily described in this document. One such line type is the scdbackup checksum tag, an ancestor of libisofs tags which is suitable only for single session images which begin at LBA 0. It bears a checksum record which by its MD5 covers all bytes from LBA 0 up to the newline character preceding the scdbackup tag. See scdbackup/README appendix VERIFY for details. ------------------------------------------------------------------------------- Usage at Read Time Checking Before Image Tree Loading In order to check for a trustworthy loadable image tree, read the first 32 blocks from to the session start and look in block 16 to 32 for a superblock checksum tag by iso_util_decode_md5_tag(block, &tag_type, &pos, &range_start, &range_size, &next_tag, md5, 0); If a tag of type 2 or 4 appears and has plausible parameters, then check whether its MD5 matches the MD5 of the data blocks which were read before. With tag type 2: Keep the original MD5 context of the data blocks and clone one for obtaining the MD5 bytes. If the MD5s match, then compute the checksum block and all folowing ones into the kept MD5 context and go on with reading and computing for the tree checksum tag. This will be found at block address next_tag, verified and parsed by: iso_util_decode_md5_tag(block, &tag_type, &pos, &range_start, &range_size, &next_tag, md5, 3); Again, if the parameters match the reading state, the MD5 must match the MD5 computed from the data blocks which were before. If so, then the tree is ok and safe to be loaded by iso_image_import(). With tag type 4: End the MD5 context and start a new context for the session which you will read next. Then look for the actual session by starting to read at the address given by parameter session_start= which is returned by iso_util_decode_md5_tag() as next_tag. Go on by looking for tag type 2 and follow above prescription. Checking the Data Part of the Session In order to check the trustworthyness of a whole session, continue reading and checksumming after the tree was verified. Read and checksum the blocks. When reaching block address next_tag (from the tree tag) submit this block to iso_util_decode_md5_tag(block, &tag_type, &pos, &range_start, &range_size, &next_tag, md5, 1); If this returns 1, then check whether the returned parameters pos, range_start, and range_size match the state of block reading, and whether the returned bytes in parameter md5 match the MD5 computed from the data blocks which were read before the tag block. Checking All Sessions If the media is sequentially recordable, obtain a table of content and check the first track of each session as prescribed above in Checking Before Image Tree Loading and in Checking the Data Part of the Session. With disk files or overwriteable media, look for a relocated superblock tag but do not hop to address next_tag (given by session_start=). Instead look at LBA 32 for the first session and check it as prescribed above. After reaching its end, round up the read address to the next multiple of 32 and check whether it is smaller than session_start= from the super block. If so, expect another session to start there. Checking Single Files in a Loaded Image An image may consist of many sessions wherein many data blocks may not belong to files in the directory tree of the most recent session. Checking this tree and all its data files can ensure that all actually valid data in the image are trustworthy. This will leave out the trees of the older sessions and the obsolete data blocks of overwritten or deleted files. Once the image has been loaded, you can obtain MD5 sums from IsoNode objects which fulfill iso_node_get_type(node) == LIBISO_FILE The recorded checksum can be obtained by iso_file_get_md5(image, (IsoFile *) node, md5, 0); For accessing the file data in the loaded image use iso_file_get_stream((IsoFile *) node); to get the data stream of the object. The checksums cover the data content as it was actually written into the ISO image stream, not necessarily as it was on hard disk before or afterwards. This implies that content filtered files bear the MD5 of the filtered data and not of the original files on disk. When checkreading, one has to avoid any reverse filtering. Dig out the stream which directly reads image data by calling iso_stream_get_input_stream() until it returns NULL and use iso_stream_get_size() rather than iso_file_get_size(). Now you may call iso_stream_open(), iso_stream_read(), iso_stream_close() for reading file content from the loaded image. Session Check in a Loaded Image iso_image_get_session_md5() gives start LBA and session payload size as of "isofs.ca" and the session checksum as of the checksum array. For reading you may use the IsoDataSource object which you submitted to iso_image_import() when reading the image. If this source is associated to a libburn drive, then libburn function burn_read_data() can read directly from it. ------------------------------------------------------------------------------- scdbackup Checksum Tags The session checksum tag does not occupy its whole block. So there is room to store a scdbackup stream checksum tag, which is an ancestor format of the tags described here. This feature allows scdbackup to omit its own checksum filter if using xorriso as ISO 9660 formatter program. Such a tag makes only sense if the session begins at LBA 0. See scdbackup-*/README, appendix VERIFY for a specification. Example of a scdbackup checksum tag: scdbackup_checksum_tag_v0.1 2456606865 61 2_2 B00109.143415 2456606865 485bbef110870c45754d7adcc844a72c c2355d5ea3c94d792ff5893dfe0d6d7b The tag is located at byte position 2456606865, contains 61 bytes of scdbackup checksum record (the next four words): Name of the backup volume is "2_2". Written in year B0 = 2010 (A9 = 2009, B1 = 2011), January (01), 9th (09), 14:34:15 local time. The size of the volume is 2456606865 bytes, which have a MD5 sum of 485bbef110870c45754d7adcc844a72c. The checksum of "2_2 B00109.143415 2456606865 485bbef110870c45754d7adcc844a72c" is c2355d5ea3c94d792ff5893dfe0d6d7b. ------------------------------------------------------------------------------- This text is under Copyright (c) 2009 - 2010 Thomas Schmitt It shall only be modified in sync with libisofs and other software which makes use of libisofs checksums. Please mail change requests to mailing list or to the copyright holder in private. Only if you cannot reach the copyright holder for at least one month it is permissible to modify this text under the same license as the affected copy of libisofs. If you do so, you commit yourself to taking reasonable effort to stay in sync with the other interested users of this text. libisofs-1.4.2/doc/doxygen.conf.in0000644000175700017510000015135711552037502013773 00000000000000# Doxyfile 1.5.3 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file that # follow. The default is UTF-8 which is also the encoding used for all text before # the first occurrence of this tag. Doxygen uses libiconv (or the iconv built into # libc) for the transcoding. See http://www.gnu.org/software/libiconv for the list # of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = @PACKAGE_NAME@ # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = @PACKAGE_VERSION@ # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian, # Italian, Japanese, Japanese-en (Japanese with English messages), Korean, # Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian, # Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = YES # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = @top_srcdir@ # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = YES # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = YES # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 4 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for Java. # For instance, namespaces will be presented as packages, qualified scopes # will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to # include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = YES # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be extracted # and appear in the documentation as a namespace called 'anonymous_namespace{file}', # where file will be replaced with the base name of the file that contains the anonymous # namespace. By default anonymous namespace are hidden. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = NO # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. SHOW_DIRECTORIES = NO # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from the # version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = YES # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be abled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text " # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = libisofs \ doc # This tag can be used to specify the character encoding of the source files that # doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default # input encoding. Doxygen uses libiconv (or the iconv built into libc) for the transcoding. # See http://www.gnu.org/software/libiconv for the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx # *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py FILE_PATTERNS = libisofs.h \ comments # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix filesystem feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the output. # The symbol name can be a fully qualified name, a word, or if the wildcard * is used, # a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = test # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. If you have enabled CALL_GRAPH or CALLER_GRAPH # then you must also enable this option. If you don't then doxygen will produce # a warning and turn it on anyway SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = YES # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = NO # If the REFERENCED_BY_RELATION tag is set to YES (the default) # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES (the default) # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. Otherwise they will link to the documentstion. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = OB \ OTK \ _ #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = doc/html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compressed HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. For this to work a browser that supports # JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox # Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). HTML_DYNAMIC_SECTIONS = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # If the GENERATE_TREEVIEW tag is set to YES, a side panel will be # generated containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, # Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are # probably better off using the HTML help feature. GENERATE_TREEVIEW = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 200 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = letter # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = YES # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = NO # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. This is useful # if you want to understand what is going on. On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = DOXYGEN # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse # the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option is superseded by the HAVE_DOT option below. This is only a # fallback. It is recommended to install and use dot, since it yields more # powerful graphs. CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see http://www.mcternan.me.uk/mscgen/) to # produce the chart and insert it in the documentation. The MSCGEN_PATH tag allows you to # specify the directory where the mscgen tool resides. If left empty the tool is assumed to # be found in the default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) # ts B10415: dot causes sigsegv on Debian buildd HAVE_DOT = NO # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will # generate a call dependency graph for every global function or class method. # Note that enabling this option will significantly increase the time of a run. # So in most cases it will be better to enable call graphs for selected # functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will # generate a caller dependency graph for every global function or class method. # Note that enabling this option will significantly increase the time of a run. # So in most cases it will be better to enable caller graphs for selected # functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = NO # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the number # of direct children of the root node in a graph is already larger than # MAX_DOT_GRAPH_NOTES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, which results in a white background. # Warning: Depending on the platform used, enabling this option may lead to # badly anti-aliased labels on the edges of a graph (i.e. they become hard to # read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- # The SEARCHENGINE tag specifies whether or not a search engine should be # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO libisofs-1.4.2/doc/susp_aaip_isofs_names.txt0000644000175700017510000001773212600774663016166 00000000000000 Arbitrary Attribute Interchange Protocol Interchange of Persistent File Attributes Directory of Namespace "isofs." by Thomas Schmitt - mailto:scdbackup@gmx.net Libburnia project - mailto:libburn-hackers@pykix.org The following names are defined for AAIP namespace "isofs." as mentioned in specification of AAIP. Unless explicitly stated otherwise, numbers with names like *_LEN are 8 bit unsigned integers, those with *_BYTES are 32 bit unsigned integers. ------------------------------------------------------------------------------- Name: isofs.ca Purpose: Records the range of checksummed image data (START, END), the number of checksum items (COUNT), the number of bytes in a single checksum item (SIZE), and the name of the checksum algorithm (CHECKSUM_TYPE). END is also the block address of the start of the checksum recording area in the image. See also isofs.cx . This attribute shall be attached to the root directory entry and be global for the whole image. Format of Value: START_LEN | START_BYTES | END_LEN | END_BYTES | COUNT_LEN | COUNT_BYTES | SIZE_LEN | SIZE_BYTES | CHECKSUM_TYPE Each number is encoded as _LEN byte and _BYTES value string. The _LEN fields comply to ISO 9660 Format section 7.1.1. The byte strings START_BYTES, END_BYTES, COUNT_BYTES, SIZE_BYTES begin with the most significant byte. Leading zero bytes are allowed. CHECKSUM_TYPE consists of the bytes after START_LEN + END_LEN + COUNT_LEN + SIZE_LEN + 4. It shall be a string of printable characters without terminating 0-byte. Type names shall be registered here. For now there is: "MD5" 128 bit message digest, see RFC 1321, see man md5sum Example: LBA range 32 to 1000000 , 520 checksums recorded, MD5 { 1, 32, 3, 15, 66, 64, 2, 2, 8, 1, 16, 'M', 'D', '5' } or { 4, 0, 0, 0, 32, 4, 0, 15, 66, 64, 4, 0, 0, 2, 8, 1, 16, 'M', 'D', '5' } Registered: 16 Jul 2009 by Thomas Schmitt for libisofs. ------------------------------------------------------------------------------- Name: isofs.cs Purpose: Records the name of the character set that was used as output character set when writing the RRIP name tree of the ISO 9660 image. It shall be suitable as parameter for function iconv_open(3). This attribute shall be attached to the root directory entry and be global for the whole image. Format of Value: Shall hold the character set name without terminating 0-byte. Example: { 'I', 'S', 'O', '-', '8', '8', '5', '9' , '-', '1' } Registered: 18 Mar 2009 by Thomas Schmitt for libisofs. ------------------------------------------------------------------------------- Name: isofs.cx Purpose: Records the index of the file's checksum in the checksum area at the end of the image. The byte address of the checksum is checksum_area_lba * 2048 + isofs.cx * checksum_size Default checksum algorithm is MD5 with a size of 16 byte. See also isofs.ca . Format of Value: A byte string which begins with the most significant byte. Example: Index 123456 { 1, 226, 64 } Registered: 16 Jul 2009 by Thomas Schmitt for libisofs. ------------------------------------------------------------------------------- Name: isofs.di Purpose: Records .st_dev and .st_ino of struct stat of the file source in the local filesystem. See man 2 stat. Both values may be unsigned integers up to 255 bytes. Format of Value: DEV_LEN | DEV_BYTES | INO_LEN | INO_BYTES The _LEN fields comply to ISO 9660 Format section 7.1.1. The byte strings begin with the most significant byte. Example: Device number 2001, inode number 176343 { 2, 7, 209, 3, 2, 176, 215 } Registered: 17 Feb 2009 by Thomas Schmitt for xorriso. ------------------------------------------------------------------------------- Name: isofs.hb Purpose: Records the IsoHfsplusBlessings blessing of a IsoNode as defined in libisofs.h. At image load time, this info may be converted back into a relation between IsoImage and IsoNode so that it is available for the HFS+ writer when a new ISO 9660 / HFS+ image gets produced. Format of Value: BLESSING This is a single byte out of {'p', 'i', 's', '9', 'x'} for ISO_HFSPLUS_BLESS_PPC_BOOTDIR, ISO_HFSPLUS_BLESS_INTEL_BOOTFILE, ISO_HFSPLUS_BLESS_SHOWFOLDER, ISO_HFSPLUS_BLESS_OS9_FOLDER, ISO_HFSPLUS_BLESS_OSX_FOLDER. Example: { 'p' } Registered: 07 Jun 2012 by Thomas Schmitt for xorriso. ------------------------------------------------------------------------------- Name: isofs.hx Purpose: Records the iso_hfsplus_xinfo_data information as defined in libisofs.h. At image load time, this info may be converted back into an xinfo attachment for iso_hfsplus_xinfo_func so that it is available for the HFS+ writer when a new ISO 9660 / HFS+ image gets produced. Format of Value: VERSION_LEN | VERSION | CREATOR | TYPE VERSION_LEN complies to ISO 9660 Format section 7.1.1. The byte string VERSION begins with the most significant byte. VERSION == 0 is the only one that is currently defined. It assures the existence of 4 bytes CREATOR and 4 bytes TYPE. Higher versions will keep these 8 bytes and possibly add new ones. Example: { 1, 0, 'Y', 'Y', 'D', 'N', 'T', 'E', 'X', 'T' } Registered: 07 Jun 2012 by Thomas Schmitt for xorriso. ------------------------------------------------------------------------------- Name: isofs.nt Purpose: Records the name truncation mode and the truncation length for Rock Ridge names. See iso_image_set_truncate_mode() in libisofs.h. This attribute shall be attached to the root directory entry and be global for the whole image. Format of Value: MODE_LEN | MODE_BYTES | LENGTH_LEN | LENGTH_BYTES Example: { 1, 1, 1, 255 } Registered: 24 Sep 2015 by Thomas Schmitt for libisofs. ------------------------------------------------------------------------------- Name: isofs.st Purpose: Records a time point at least 1 second before any nodes were added to a freshly loaded or created ISO image. Nodes in the image which have younger timestamps are suspect to have changed their content during image production and might bear inconsistent content. The RRIP timestamps have a blind second during which a change after node registration would not be recognizable for incremental backups which are based in "isofs.di" rather than on content comparison. This attribute shall be attached to the root directory entry and be global for the whole image. Format of Value: Shall hold UTC seconds since 1970 as decimal number string without terminating 0-byte. Example: { '1', '2', '3', '8', '7', '4', '2', '2', '9', '6' } Registered: 03 Apr 2009 by Thomas Schmitt for xorriso. ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- This text is under Copyright (c) 2009 - 2011 Thomas Schmitt It shall only be modified in sync with libisofs and other software which makes use of AAIP. Please mail change requests to mailing list or to the copyright holder in private. Only if you cannot reach the copyright holder for at least one month it is permissible to modify this text under the same license as the affected copy of libisofs. If you do so, you commit yourself to taking reasonable effort to stay in sync with the other interested users of this text. libisofs-1.4.2/doc/Tutorial0000755000175700017510000004561611112746253012575 00000000000000=============================================================================== LIBISOFS DEVELOPMENT TUTORIAL =============================================================================== Creation date: 2008-Jan-27 Author: Vreixo Formoso _______________________________________________________________________________ This is a little tutorial of how to use libisofs library for application development. Contents: --------- 1. Introduction 1.1 Library initialization 1.2 Image context 1.3 Error reporting 2. Creating an image 2.1 Image tree manipulation 2.2 Set the write options 2.3 Obtaining a burn_source 3. Image growing and modification 3.1 Growing vs Modification 3.2 Image import 3.3 Generating a new image 4. Bootable images 5. Advanced features ------------------------------------------------------------------------------- 1. Introduction ------------------------------------------------------------------------------- [TODO some lines about refcounts] ------------------------------------------------------------------------------- 1.1. Library initialization Before any usage of the library, you have to call iso_init() in the same way, when you have finished using the library, you should call iso_finish() to free all resources reserved by the library. ------------------------------------------------------------------------------- 1.2. Image context Libisofs is image-oriented, the core of libisofs usage is the IsoImage object. Thus, the first you need to do is to get your own IsoImage object: IsoImage *my_image; iso_image_new("NEW DISC", &my_image); An IsoImage is a context for image creation. It holds the files that will be added to image, other related information and several options to customize the behavior of libisofs when working with such Image. i.e., an IsoImage is a context for libisofs operations. As such, you can work with several image contexts at a time. ------------------------------------------------------------------------------- 1.3. Error reporting In libisofs error reporting is done in two ways: with the return value of the functions and with the message queue. Error codes are negative numbers, defined in "libisofs.h" header. An error code is associated with a given severity, either "DEBUG", "UPDATE", "NOTE", "HINT", "WARNING", "SORRY", "FAILURE" and "FATAL". For the meaning of each severity take a look at private header "libiso_msgs.h". Errors reported by function return value are always "FAILURE" or "FATAL". Other kind of errors are only reported with the message queue. You can get the severity of any error message with iso_error_get_severity() function. First of all, most libisofs functions return an integer. If such integer is a negative number, it means the function has returned an error. The error code and its severity is encoded in the return value (take a look at error codes in libisofs.h header). Additionally, libisofs reports most of its errors in a message queue. Error messages on that queue can be printed directly to stderr or programmatically retrieved. First of all, you should set the severity threshold over which an error is printed or enqueued, with function: iso_set_msgs_severities() Errors enqueued can be retrieved with function: iso_obtain_msgs() Together with the code error, a text message and its severity, this function also returns the image id. This is an identifier that uniquely identifies a given image context. You can get the identifier of each IsoImage with the iso_image_get_msg_id() and that way distinguish what image has issued the message. ------------------------------------------------------------------------------- 2. Creating an Image ------------------------------------------------------------------------------- An image is built from a set of files that you want to store together in an ISO-9660 volume. We call the "iso tree" to the file hierarchy that will be written to image. The image context, IsoImage, holds that tree, together with configuration options and other properties of the image, that provide info about the volume (such as the identifier, author, etc...). All configuration options and volume properties are set by its corresponding setters (iso_image_set_volset_id(), iso_image_set_publisher_id()...) To create an image, you have to follow the following steps: * Obtain the image context. See "1.2 Image context" for details of how to obtain the IsoImage. * Set the desired properties * Prepare the iso tree with the files you want to add to image. See "2.1 Image tree manipulation" for details * Select the options for image generation. See "2.2 Set the write options" * Get the burn_source used to actually write the image. ------------------------------------------------------------------------------- 2.1 Image tree manipulation libisofs maintains in memory a file tree (usually called the iso tree), that represents the files and directories that will be written later to image. You are allowed to make whatever changes you want to that tree, just like you do to any "real" filesystem, before actually write it to image. Unlike other ISO-9660 mastering tools, you have full control over the file hierarchy that will be written to image, via the libisofs API. You can add new files, create any file in image, change its name, attributes, etc The iso tree behaves just like any other POSIX filesystem. The root of the iso tree is created automatically when the IsoImage is allocated, and you can't replace it. To get a reference to it you can use the function: iso_image_get_root() * Iso tree objects Each file in the image or iso tree is represented by an IsoNode instance. In the same way a POSIX filesystem has several file types (regular files, directories, symlinks...), the IsoNode has several subtypes: IsoNode | --------------------------------- | | | | IsoDir IsoFile IsoSymlink IsoSpecial where - IsoDir represents a directory - IsoFile represents a regular file - IsoSymlink represents a symbolic linke - IsoSpecial represents any other POSIX file, i.e. block and character devices, FIFOs, sockets. You can obtain the concrete type of an IsoNode with the iso_node_get_type() function. Many libisofs functions take or return an IsoNode. Many others, however, require an specific type. You can safety cast any subtype to an IsoNode object. In the same way, after ensuring you are dealing with the correct subtype, you can downcast a given IsoNode to the specific subtype. IsoDir *dir; IsoNode *node; node = (IsoNode*) dir; if (iso_node_get_type(node) == LIBISO_DIR) { dir = (IsoDir*) node; ... } or with the provided macros: IsoDir *dir; IsoNode *node; node = ISO_NODE(dir); if (ISO_NODE_IS_DIR(node)) { dir = ISO_DIR(node); ... } * Adding files to the image Files can be added to the image or iso tree either as new files or as files from the filesystem. In the first case, files are created directly on the image. They do not correspond to any file in the filesystem. Provided functions are: - iso_tree_add_new_dir() - iso_tree_add_new_symlink() - iso_tree_add_new_special() On the other side, you can add local files to the image, either with the iso_tree_add_node() or with iso_tree_add_dir_rec(). The first is intended to add a single file, while the last can be used to add, recursively, a full directory (see below for details). It is important to note that libisofs doesn't store any kind of link between the IsoNode and the filesystem file it was created from. The above functions just initialize a newly created IsoNode with the attributes of a given file in the filesystem. After that, you can move the original file, change its attributes or even delete it. The IsoNode in the image tree remains with the original attributes. One exception to this rule are the contents of a regular file. Libisofs does not make any copy of those contents until they're actually written to image. Thus, you shouldn't modify, move or delete regular files after adding them to the IsoImage. * Recursive directory addition. One common use case is to add a local directory to the image. While this can be done with iso_tree_add_node(), handling the addition of directory children in the application, libisofs provides a function suitable for this case: iso_tree_add_dir_rec() that takes care of adding all files inside a directory, recursing on directory children. By default, this function adds all children. However, it is usual that you don't want really this. For example, you may want to exclude some kind of files (backup files, application sockets,...). Libisofs provides several functions to customize the behavior of that function: - iso_tree_set_follow_symlinks() - iso_tree_set_ignore_hidden() - iso_tree_set_ignore_special() - iso_tree_add_exclude() * Operations on iso tree [TODO briefly explain how to add node, change attributes, ...] * Replace mode [TODO] ------------------------------------------------------------------------------- 2.2 Set the write options Once you have prepared the iso tree, it is time to select the options for the image writing. These options affect the characteristics of the filesystem to create in the image, but also can control how libisofs generates the image. First of all you have to get an instance of IsoWriteOpts, with the function iso_write_opts_new() The several options available can be classified in: - Extensions to add to the ISO-9660 image: iso_write_opts_set_rockridge() iso_write_opts_set_joliet() iso_write_opts_set_iso1999() RockRidge is highly recommended, in fact you should use it in all image. Joliet is needed if you want to use your images in Windows system. Nowadays, ISO-9660:1999 is no much useful, so in most cases you don't want such extension. - ISO-9660 options: iso_write_opts_set_iso_level() iso_write_opts_set_omit_version_numbers() iso_write_opts_set_allow_deep_paths() iso_write_opts_set_allow_longer_paths() iso_write_opts_set_max_37_char_filenames() iso_write_opts_set_no_force_dots() iso_write_opts_set_allow_lowercase() iso_write_opts_set_allow_full_ascii() These control the options for the ISO-9660 filesystem. In most cases you won't care about them, as it is the RockRidge or Joliet extensions what determine the properties of the files once the image is mounted. - File attributes options iso_write_opts_set_replace_mode() iso_write_opts_set_default_dir_mode() iso_write_opts_set_default_file_mode() iso_write_opts_set_default_uid() iso_write_opts_set_default_gid() iso_write_opts_set_replace_timestamps() iso_write_opts_set_default_timestamp() iso_write_opts_set_always_gmt() They allow to set default attributes for files in image, despite of the real attributes of the file on the local filesystem. ------------------------------------------------------------------------------- 2.3 Obtaining a burn_source Finally, you get the burn_source used to write the image with the function: iso_image_create_burn_source() The returned burn_source is suitable for using with libburn, to directly burn the image to a disc. Alternatively, you can use burn_source read() to get the image contents (for example, to write them to a file, pipe...). Before creating the burn_source, libisofs computes the size of the image, so the get_size() function of the burn_source always returns the final image size. It also starts a writing thread. All the operations needed to generate the image are done by this thread, including read the original files contents. The image is writing to a FIFO buffer, from which the burn_source will read. The size of the buffer can be set in advanced with a property of the IsoWriteOpts struct: iso_write_opts_set_fifo_size() You can get the state of the buffer in any moment, with the function: iso_ring_buffer_get_status() You can also cancel the writer thread at any time, with the cancel() function of the burn_source. ------------------------------------------------------------------------------- 3. Image growing and modification ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- 3.1 Growing vs Modification Libisofs is not restricted only to create new images. It can also be used to modify existing images. It supports two kind of image modifications, that we have called image growing and image modification: Image modification consists in generating a new image, based on the contents of an existing image. In this mode, libisofs takes an image, the users modifies its contents (adding new files, removing files, changing their names...), and finally libisofs generates a completely new image. On the other side, image growing is similar, with the difference that the new image is dependent on the other, i.e., it refers to files of the other image. Thus, it can't be mounted without the old image. The purpose of this kind of images is to increment or add files to a multisession disc. The new image only contains the new files. Old files are just references to the old image blocks. The advantage of the growing approach is that the generated image is smaller, as only the new files are written. This mode is suitable when you just want to add some files to a very big image, or when dealing with write-once media, such as CD-R. Both the time and space needed for the modification is much less than with normal image modify. The main problem of growing is that the new image needs to be recorded together with the old image, in order to be mountable. The total size of the image (old + new) is bigger (even much bigger) than a completely new image. So, if you plan to distribute an image on Internet, or burn it to a disc, generate a completely new image is usually a better alternative. To be able to mount a grown image, the OS needs to now you have appended new data to the original image. In multisession media (such as CD-R), the new data is appended as a new session, so the OS can identify this and mount the image propertly. However, when dealing with non-multisession media (such as DVD+RW) or plain .iso files, the new data is just appended at the end of the old image, and the OS has no way to know that the appended data is in fact a "new session". The method introduced by Andy Polyakov in growisofs can be used in those cases. It consists in overwrite the volume descriptors of the old image with a new ones that refer to the newly appended contents. ------------------------------------------------------------------------------- 3.2 Image import The first thing you need to do in order to modify or grow an image is to import it, with the function: iso_image_import() It takes several arguments. First, the image context, an IsoImage previously obtained with iso_image_new(). In most cases you will want to use an empty image. However, if you have already added files to the image, they will be removed and replaced with the contents of the image being imported. The second parameter is an IsoDataSource instance. It abstracts the original image, and it is used by libisofs to access its contents. You are free to implement your own data source to access image contents. However, libisofs has a simple implementation suitable for reading images on the local filesystem, that can be used for import both .iso files and inserted media, via the block device and POSIX functions. You can get it with iso_data_source_new_from_file() The third parameter of iso_image_import() is a pointer to an IsoReadOpts struct. It holds the options for image reading. You get it with: iso_read_opts_new() and after calling iso_image_import() you should free it with iso_read_opts_free() Some options are related to select what extensions to read. Default options are suitable for most users. iso_read_opts_set_no_rockridge() iso_read_opts_set_no_joliet() iso_read_opts_set_no_iso1999() iso_read_opts_set_preferjoliet() If RockRidge extensions are not present, many files attributes can't be obtained. In those cases libisofs uses default values. You have options to configure what default values to use. iso_read_opts_set_default_uid() iso_read_opts_set_default_gid() iso_read_opts_set_default_permissions() If the original image has been created in another system with a different charset, you may want to use: iso_read_opts_set_input_charset() to specify the encoding of the file names on image. Finally, to import multisession images, you should tell libisofs that it must read the last session. For that, you must set the block where the last session starts: iso_read_opts_set_start_block() The last parameter for iso_image_import(), optional, is a pointer that will be filled with a library-allocated IsoReadImageFeatures, that lets you access some information about the image: size, extensions used,... [TODO: explain that iso_image_import uses dir rec options] ------------------------------------------------------------------------------- 3.3 Generating a new image After importing the image, the old image tree gets loaded. You are free to make any changes to it: add new files, remove files, change names or attributes... Refer to "2.1 Image tree manipulation" for details. When it is ready, you can now create the new image. The process is the same as explained in "2.2 Set the write options" and "2.3 Obtaining a burn_source". However, there are some write options that should be taken into account. First of all, you must select whether you want to grow or modify the image (read "3.1 Growing vs Modification" for details). You must call iso_write_opts_set_appendable() An appendable image leads to image growing, and a non-appendable image leads to a completelly new image (modification). An appendable image will be appended after the old image (in a new session, for example). Thus, in those cases, the first block of the image is not 0. You should set the correct lba of the first block with: iso_write_opts_set_ms_block() That is usually the "Next Writable Address" on a multisession media, and a value slightly greater than the old image size on .iso files or DVD+RW media. You can obtain the old image size with the iso_read_image_features_get_size() function. In this last case (i.e., on a non multisession media), you will need to overwrite the volume descriptors of the old image with the new ones. To do this you need: - Allocate a buffer of at least 64 KiBs. - Initialize it with the first 64 KiBs of the original image. - Pass the buffer to libisofs with the iso_write_opts_set_overwrite_buf() option. - After appending the new image, you have to overwrite the first 64 KiBs of the original image with the new content of the buffer. ------------------------------------------------------------------------------- 4. Bootable images ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- 5. Advanced features ------------------------------------------------------------------------------- libisofs-1.4.2/doc/zisofs_format.txt0000644000175700017510000001366012557152272014472 00000000000000 Description of the zisofs Format as of zisofs-tools-1.0.8 by H. Peter Anvin and cdrtools-2.01.01a39 by Joerg Schilling For libburnia-project.org by Thomas Schmitt - distribute freely , please report any errors or ambiguities - Apr 11 2009 The zisofs format was invented by H. Peter Anvin. It compresses data file content, marks it by a header and provides a pointer array for coarse random access. Within a RRIP enhanced ISO 9660 image the format is additionally marked by a System Use entry with signature "ZF". The uncompressed size of a single zisofs compressed file is restricted to 4 GiB - 1. Larger files shall not be compressed. File Header The file header has this layout (quoted from zisofs-tools-1.0.8/mkzftree.c): Byte offset iso9660 type Contents 0 (8 bytes) Magic number (37 E4 53 96 C9 DB D6 07) 8 7.3.1 Uncompressed file size 12 7.1.1 header_size >> 2 (currently 4) 13 7.1.1 log2(block_size) 14 (2 bytes) Reserved, must be zero So its size is 16. 7.3.1 means little endian 4-byte words. 7.1.1. means unsigned single bytes. Readers shall be able to handle log2(block_size) values 15, 16 and 17 i.e. block sizes 32 kB, 64 kB, and 128 kB. Writers must not use other sizes. Block Pointers There are ceil(input_size / block_size) input and output blocks. Each input block is of fixed size whereas the output blocks have varying size (down to 0). For each output block there is an offset pointer giving its byte address in the overall file content. The next block pointer in the array tells the start of the next block which begins immediately after the end of its predecessor. A final pointer gives the first invalid byte address and thus marks the end of the last block. So there are ceil(input_size / block_size) + 1 block pointers. They are stored as an array of 4-byte values which are in ISO 9660:7.3.1 format directly after the file header, i.e. beginning at byte 16. Data Part The data part begins immediately after the pointer array. In principle it consists of the variable length output blocks as delivered by zlib function compress2() when fed with the fixed size input blocks. A special case of input and output block is defined: Zero-length blocks represent a block full of 0-bytes. Such input blocks do not get processed by compress2() but shall be mapped to 0-sized output directly. Vice versa 0-sized blocks have to bypass uncompress() when being read. ZF System Use Entry Format ZF may only be applied to files with a single extent and less than 4 GiB of uncompressed size. The ZF entry follows the general layout of SUSP and RRIP. Its fields are: [1] "BP 1 to BP 2 - Signature Word" shall be (5A)(46) ("ZF"). [2] "BP 3 - Length" shall specify as an 8-bit number the length in bytes of the ZF entry recorded according to ISO 9660:7.1.1. This length is 16 decimal. [3] "BP 4 - System Use Entry Version" shall be 1 as in ISO 9660:7.1.1. [4] "BP 5 to BP 6 - Algorithm" shall be (70)(7A) ("pz") to indicate "paged zlib". [5] "BP 7 - Header Size Div 4" shall specify as an 8-bit number the number of 4-byte words in the header part of the file data recorded according to ISO 9660:7.1.1. (This is a copy of header byte 12 / BP 13). [6] "BP 8 - Log2 of Block Size" shall specify as an 8-bit number the binary logarithm of the compression block size recorded according to ISO 9660:7.1.1. (This is a copy of header byte 13 / BP 14. The value has to be 15, 16 or 17 i.e. 32 kiB, 64 kiB, or 128 kiB.) [7] "BP 9 to BP 16 - Uncompressed Size" shall tell the number of uncompressed bytes represented by the given extent. This field shall be recorded according to ISO 9660:7.3.3. (This number is the same as in header bytes 8 to 11 / BP 9 to BP 12.) | 'Z' | 'F' | LENGTH | 1 | 'p' | 'z' | HEADER SIZE DIV 4 | LOG2 BLOCK SIZE | UNCOMPRESSED SIZE | ISO 9660:7.3.3 means 4-byte word in both byte orders, first little endian, then big endian. Example (block size 32 kiB, uncompressed file size = 1,234,567 bytes): { 'Z', "F', 16, 1, 'p', 'z', 4, 15, 0x87, 0xD6, 0x12, 0x00, 0x00, 0x12, 0xD6, 0x87 } ------------------------------------------------------------------------------- Revoked specification aspects: A comment in zisofs-tools-1.0.8 indicates a special case of output block: "a block the length of which is equal to the block size is unencoded." This is not implemented in zisofs-tools and in the Linux kernel. Existing zisofs enhanced ISO images might contain encoded blocks which could be mistaken for unencoded blocks. Therefore this rule is not part of this description and must not be implemented. ------------------------------------------------------------------------------- References: zisofs-tools http://freshmeat.net/projects/zisofs-tools/ zlib: /usr/include/zlib.h cdrtools with mkisofs ftp://ftp.berlios.de/pub/cdrecord/alpha ECMA-119 aka ISO 9660 http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-119.pdf SUSP 1.12 ftp://ftp.ymi.com/pub/rockridge/susp112.ps RRIP 1.12 ftp://ftp.ymi.com/pub/rockridge/rrip112.ps ------------------------------------------------------------------------------- This text is under Copyright (c) 2009 - 2010 Thomas Schmitt It shall reflect the effective technical specifications as implemented in zisofs-tools and the Linux kernel. So please contact mailing list or to the copyright holder in private, if you want to make changes. Only if you cannot reach the copyright holder for at least one month it is permissible to modify and distribute this text under the license "BSD revised". libisofs-1.4.2/doc/susp_aaip_2_0.txt0000644000175700017510000004727412557152354014242 00000000000000 Arbitrary Attribute Interchange Protocol Version 2.0 Mar 18 2009 Interchange of Persistent File Attributes by Thomas Schmitt - mailto:scdbackup@gmx.net Libburnia project - mailto:libburn-hackers@pykix.org AAIP is intended as companion of the Rock Ridge Interchange Protocol RRIP which under the general design of System Use Sharing Protocol SUSP extends ISO 9660 aka ECMA-119 filesystem semantics to match POSIX needs. Goal is to have for each file an arbitrary number of attributes which consist of two components (Name and Value) of arbitrary length and to have a compact representation of ACLs. This document describes a SUSP entry with Signature Word "AL" which collides neither with SUSP 1.12 nor with RRIP 1.12. The AL entry has been designed to be as similar to the RRIP entry SL as possible. The presence of AAIP shall be announced by a particular ER entry. Since the size of a SUSP entry is limited to 255, multiple entries may be needed to describe one component. The CE mechanism of SUSP shall be used to address enough storage if needed. AL entries and the ER entry of AAIP shall only be present if the ER entry of RRIP is present. ------------------------------------------------------------------------------- System Entries Provided by this Specification * AL Description of the "AL" System Use Entry The entry has exactly the same layout as RRIP entry SL. One has to expect more data bytes than with SL, though, and any of the 256 possible byte values. The reader shall be prepared to detect and handle oversized data. One or more AL entries form the Attribute List of a file object with an even number of components. Each two consequtive components form a pair of Name and Value. The empty name indicates that the value is a compact representation of ACLs. Names must not contain byte value 0x00. Names which begin by bytes 0x01 to 0x1f represent names in particular namespaces. See below: Namespaces. The meaning of any other names or name parts is not specified by this document. All AL entries except the last one shall have the CONTINUE flag set. An AL entry with CONTINUE set to 0 indicates the end of the Attribute List. The format of the AL System Use Field is as follows: [1] "BP 1 to BP 2 - Signature Word" shall be (41)(4C) ("AL"). [2] "BP 3 - Length" shall specify as an 8-bit number the length in bytes of the AL entry recorded according to ISO 9660:7.1.1. [3] "BP 4 - System Use Entry Version" shall be 1 as in ISO 9660:7.1.1. [4] "BP 5 - Flags" shall contain bit field flags numbered 0 to 7 starting with the least significant bit as follows: 0 CONTINUE This AL entry continues in the next AL entry. All other bits shall be set to 0. [5] "BP 6 to Length - Component Area" shall contain Component Records as described below. | 'A' | 'L' | LENGTH | 1 | FLAGS | COMPONENT AREA | Within AL entries each component (Name or Value) shall be recorded as one or more component records. If a component does not fit into the remaining space of an AL entry then it shall be continued in following AL entries. All Component Records of a component except the last one shall have the CONTINUE flag set. A Component Record with CONTINUE set to 0 indicates the end of the component. An eventually following Component Record starts the next component. ------------------------------------------------------------------------------- The Component Record format is identical to the one of the SL entry. The complete form of the following summary can be found in RRIP 1.12 "4.1.3.1". In case of discrepancies, RRIP 1.12 is the decisive specification. Please inform the author of this document if you find such a discrepancy. Component Records shall be recorded contiguously within each Component Area, starting in the first byte of the Component Area. The last Component Record in the Component Area of an AL System Use Entry may be continued in the Component Area of the next recorded AL System Use Entry in the same System Use Area. Each Component Record shall have the following format: [A] "BP 1 - Component Flags" shall contain bit field flags numbered 0 to 7, starting with the least significant bit, as follows: 0 CONTINUE This Component Record continues in the next AL Component Record. all others are RESERVED and shall be 0. [B] "BP 2 - Component Length (LEN_CP)" shall specify as an 8-bit number the number of component bytes in the Component Record. This length shall not include the first two bytes of the Component Record. This field shall be recorded according to ISO 9660 Format section 7.1.1. [C] "BP 3 to 2 + LEN_CP - Component Content" shall contain the component bytes in the Component Record. | COMPONENT FLAGS | LEN_CP | COMPONENT BYTES | Example: Two pairs of "name"="long...content" and "one"="more" encoded as two AL entries Field 1 contains the Component Record of Name and one Component Record of Value : { 'A', 'L', 255, 1, 1, 0, 4, 'n', 'a', 'm', 'e', 1, 255, 'l', 'o', 'n', 'g', ... 238 more bytes, 13 go to next AL ... } Field 2 contains the rest of "long...content" and the complete second pair. It marks the end of the Attribute List : { 'A', 'L', 38, 1, 0, ... 13 remaining bytes of the Component Record in first entry ... 0, 7, 'c', 'o', 'n', 't', 'e', 'n', 't', 0, 3, 'o', 'n', 'e', 0, 4, 'm', 'o', 'r', 'e' } ------------------------------------------------------------------------------- Namespaces AAIP provides a short notation for namespaces which uses a single non-printable byte at the start of the name. Reserved start bytes of names are 0x01 to 0x1F The names of extended file attributes are traditionally organized in namespaces, which get expressed as first part of an attribute name up to a period "." character. It is also tradition that names are printable text, single words and especially contain no 0-bytes. AAIP does not enforce the use of any namespace but it urges that names in the following registered namespaces are used according to traditions. The namespaces "system." and "user." are available with many file system types. "system." is file system dependent and often restricted in the choice of names. "user." is portable and allows to choose about any name. Namespace "isofs." is defined for internal use of AAIP enhanced ISO 9660 file systems. Names in this namespace should be registered at libburnia-project.org. Further namespaces may be registered at libburnia-project.org. The reserved start bytes of names have the following meaning 0x01 escape reserved character at start of name 0x02 namespace "system." 0x03 namespace "user." 0x04 namespace "isofs." 0x05 namespace "trusted." 0x06 namespace "security." 0x07 to 0x1F shall not be used yet. Examples: Name "user.abc" with and without short notation. Both is allowed. 0, 4, 0x03, 'a', 'b', 'c' 0 8, 'u', 's', 'e', 'r', '.', 'a', 'b', 'c' Name "\003abc" (if really desired) 0, 5, 0x01, 0x03, 'a', 'b', 'c' ------------------------------------------------------------------------------- Specification of binary ACL representation as special Arbitrary Attribute The Name component of a binary ACL shall be of length 0. The Value shall be an arbitrary number of ACL Entries: [a] "BP 1 - Entry Flags" shall contain bit field flags numbered 0 to 7, starting with the least significant bit, as follows: 0 EXEC indicates that this entry grants execute permission 1 WRITE write permission 2 READ read permission 3 QUALIFIER indicates that one or more Qualifier Records follow 4 - 7 TYPE shall contain the tag type of the ACL entry as four bit code: 0 TRANSLATE Entry for a global map of name to numeric id Qualifier is a record of number and text 1 ACL_USER_OBJ Permissions of owning user (as of PX entry) 3 ACL_GROUP_OBJ Permissions of owning group (as of PX entry) 5 ACL_MASK Restricts 10, 3, and 12 via logical AND 6 ACL_OTHER Permissions of non-listed, non-owning users 8 SWITCH_MARK Switch from "access" ACL to "default" ACL 10 ACL_USER_N Permissions of arbitrary user. Qualifier is the numeric user id (max. 4 bytes). 12 ACL_GROUP_N Permissions of arbitrary group. Qualifier is the numeric group id (max. 4 bytes). 15 FUTURE_VERSION Will indicate that this document does not apply to the entry. The other values are reserved. Readers shall ignore them if they are not aware of updates of this document which would assign a meaning to them. The entries must match the permission bits of the PX entry. This shall obey the rule that ACL_USER_OBJ must match S_IRWXU, ACL_OTHER must match S_IRWXO, ACL_MASK - if present - must match S_IRWXG, else ACL_GROUP_OBJ must match S_IRWXG. If there is ACL_USER_N or ACL_GROUP_N there must also be ACL_MASK. A numeric qualifier is a binary number of variable length up to 4 bytes. The Most Significant Byte comes first. The number shall be the "POSIX File User ID" or "POSIX File Group ID" as also used in RRIP PX entries. The ids of owning user and owning group shall be taken from the PX entry of the file object. Optional TRANSLATE entries may associate user or group names with numeric ids to allow the reading system to remap the numeric ids. See below. The writer is not obliged to write them and the reader is not obliged to interpret them. The ACL entries belong to the "access" ACL of a file object. An optional SWITCH_MARK entry may direct further entries to the "default" ACL which is defined for directory objects. The EXEC bit of SWITCH_MARK shall be 1. The bits for WRITE, READ, QUALIFIER shall be 0. An eventually needed qualifier is stored in one or more Qualifier Records. [b] "BP 2 - Qualifier Record Head" shall be present only if QUALIFIER is set to 1. It shall give the number of Qualifier Bytes and eventually indicate that the qualifier continues in a Qualifier Record which comes imediately after this record. 0 to 127 Q_LENGTH, the qualifier is complete by this record 128 to 255 Q_LENGTH+128, the qualifier is continued by next record So a Qualifier Record can contain at most 127 Qualifier Bytes. This field shall be recorded according to ISO 9660 Format section 7.1.1. [c] "BP 3 to BP 2 + Q_LENGTH - Qualifier Bytes" shall be present only if QUALIFIER is set to 1 and hold the announced number of bytes of the user or group name. | ENTRY FLAGS [ | QUALIFIER HEAD | QUALIFIER BYTES | ] Example: From man 5 acl: u::rw-,u:lisa:rw-,g::r--,g:toolies:rw-,m::r--,o::r-- "lisa" has user number 123, "toolies" has group number 65534 { 'A', 'L', 20, 1, 0, 0, 0, 0, 11, 0x16, 0xAE, 1, 123, 0x34, 0xCE, 2, 255, 254, 0x54, 0x64 } Example: "Access" ACL and "default" ACL (0x81 is the switch mark) u::rwx,g::r-x,o::r-x, du::rwx,dg::r-x,dm::rwx,do::r-x,du:lisa:rwx { 'A', 'L', 20, 1, 0, 0, 0, 0, 11, 0x17, 0x35, 0x65, 0x81, 0x17, 0x35, 0x57, 0x65, 0xA7, 1, 123 } ------------------------------------------------------------------------------- Association of Names and Numeric Identifiers The entry flag value 0x08 TRANSLATE is not a ACL entry of the hosting object but rather a global hint about the relation of roles, names and numeric ids. If it is recorded at all, then it shall be recorded with the first Directory Entry of the volume's root directory. According to the description of SUSP entry ER, this has to be "dot" or (00). Other than with ER, a TRANSLATE entry may not appear in the root of directory sub trees. An interested reader shall examine the Arbitrary Attributes of this Directory Entry in order to collect a translation table. The advised translation is: PX or AL Id number -> name -> local id number. The Qualifier Bytes of a TRANSLATE entry shall have the following format: [i] "BP 0 - Role" shall tell whether it is about a user name (role 0) or a group name (role 1). Other values are not allowed. [ii] "BP 1 to BP 8 - Numeric Id" shall hold the 32 bit POSIX Id number of the entry. This field shall be recorded according to ISO 9660:7.3.3. [iii] "BP 9 to End Of Qualifier - Name" shall hold the name bytes of this entry. | ROLE | NUMERIC ID | NAME | Example: User id number 123 gets associated with user name "lisa" 0x08, 13, 0, 123,0,0,0, 0,0,0,123, 'l', 'i', 's', 'a', Example: A very long qualifier naming "His_Excellency_..._the_Boss" as user #1. This needs two qualifier records. 0x08, 255, 0, 1,0,0,0, 0,0,0,1, 'H', 'i', 's', '_', 'E', 'x', 'c', 'e', 'l', 'e', ... 108 more bytes ... 8, 't', 'h', 'e', '_', 'B', 'o', 's', 's', ------------------------------------------------------------------------------- Specification of the ER System Use Entry Values for AAIP: This ER system entry shall only be present if the ER entry of RRIP is present. To be compliant with SUSP-1.12, this ER entry must be present if AL entries are present, and ES entries have to mark RRIP and AAIP entries. If for some reason compliance with SUSP-1.10 is intended, then this ER entry and the ES entries must not be present, although SUSP-1.10 would allow ER. (See below: Compatibility considerations.) The Extension Version number for this version of AAIP shall be 1. The Extension Identifier field shall be "AAIP_0200" with Identifier Length 9. The mandatory content form of the Extension Descriptor is "AL PROVIDES VIA AAIP 2.0 SUPPORT FOR ARBITRARY FILE ATTRIBUTES IN ISO 9660 IMAGES" The Description Length is 81. The recommended content of the Extension Source is "PLEASE CONTACT THE LIBBURNIA PROJECT VIA LIBBURNIA-PROJECT.ORG". The corresponding Source Length is 62. ------------------------------------------------------------------------------- Compatibility Considerations This extension is supposed not to disturb any reader system which complies to SUSP-1.10: "6.2 Requirements for a Receiving System [...] Any System Use Field which the receiving system does not recognize is to be ignored and skipped." SUSP-1.12 extends this prescription by: "Any System Use Entry, with the exception of the set of System Use Entries defined in this document, following an "ES" System Use Entry that indicates an extension specification which the receiving system does not recognize shall be ignored and skipped." According to SUSP-1.12 the ER entry is mandatory for a conformant extension. It also prescribes that in the case that ER entries of RRIP and AAIP are present, then ES entries shall be used to separate RRIP entries from AAIP entries. SUSP-1.12 frowns on extensions which are not announced by ER. Nevertheless is does not totally outrule them. SUSP-1.10 does not specify ES entries at all and allows to have extension entries without announcing them by an ER entry. So if a second ER entry is not bearable, then the SUSP-1.10 downgrade of AAIP allows to omit the AAIP ER and the ES entries. But if there is the AAIP ER then there must be ES at the appropriate places. Else the format would explicitely violate SUSP-1.12. ------------------------------------------------------------------------------- Model Relations: Attribute List ------------- [1:0..1] ------------- ACL [1:0..n] [1:0..n] Arbitrary Attribute ( [1:0..1] ACL ) Entry [1:2..2n] [1:0..1] Component ( [1..m:1..n] AL Field ) Qualifier [1:1..n] << one of >> Component Record / \ [1..m:1..n] Translation Entry , Numeric Id AL Field | | [1:1..n] [1:1] \ / Qualifier Record ------------------------------------------------------------------------------- Revoked drafts: The following outdated versions may be interpreted at read time but they shall not be written any more. AAIP-1.0 Previous versions up to AAIP 1.0 used field signature "AA" rather than "AL". This nearly collides with "Apple ISO 9660 Extensions". The Apple "AA" field of version 1 has a length of 7, whereas the shortest first AAIP field "AA" had length 9. Beginning with AAIP 2.0, the field name has been changed to "AL". If a reader interprets old AAIP "AA" fields, then it must take precautions to distinguish them from Apple "AA" fields. But it is well compliant with AAIP 2.0 to just ignore any kind of "AA" fields. AAIP 1.0 had ER signature "AAIP_0100". AAIP-0.2 AAIP 0.2 with ER signature "AAIP_0002" allowed to announce and use a different signature than "AA". This was revoked because ES entries serve the purpose to distinguish AAIP entries from eventual "AA" entries of any other extension. Regrettably no reader (kernel) was found which neatly interprets ES. Many do not even recognize the RRIP-1.12 ER signatures "IEEE_P1282", "IEEE_1282". AAIP 0.2 defined two ACL types which did not make it into AAIP 1.0 2 ACL_USER of arbitrary user, with name as qualifier 4 ACL_GROUP of arbitrary group, with name as qualifier Their job was transferred to ACL_USER_N and ACL_GROUP_N which have numeric qualifiers. AAIP-0.0 There was a draft AAIP 0.0 with ER signature "AAIP_2008A". It did not resemble the existing entry SL and was never implemented. ------------------------------------------------------------------------------- References: ECMA-119 aka ISO 9660 http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-119.pdf SUSP 1.12 (entries CE , PD , SP , ST , ER , ES) ftp://ftp.ymi.com/pub/rockridge/susp112.ps RRIP 1.12 (entries PX , PN , SL , NM , CL , PL , RE , TF , SF , obsolete: RR) ftp://ftp.ymi.com/pub/rockridge/rrip112.ps Apple ISO 9660 Extensions (entries AA and BA) http://developer.apple.com/technotes/fl/fl_36.html Amiga AS entry http://www.estamos.de/makecd/Rock_Ridge_Amiga_Specific zisofs entry ZF (prepared by zisofs-tools, written by mkisofs) http://freshmeat.net/projects/zisofs-tools/ Program mkisofs emits entry XA ftp://ftp.berlios.de/pub/cdrecord/alpha ------------------------------------------------------------------------------- This text is under Copyright (c) 2009 - 2013 Thomas Schmitt It shall only be modified in sync with libisofs and other software which makes use of AAIP. Please mail change requests to mailing list or to the copyright holder in private. Only if you cannot reach the copyright holder for at least one month it is permissible to modify this text under the same license as the affected copy of libisofs. If you do so, you commit yourself to taking reasonable effort to stay in sync with the other interested users of this text. libisofs-1.4.2/install-sh0000755000175700017510000002202111112746612012263 00000000000000#!/bin/sh # install - install a program, script, or datafile scriptversion=2005-05-14.22 # 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. It can only install one file at a time, a restriction # shared with many OS's install programs. # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit="${DOITPROG-}" # put in absolute paths if you don't have them in your path; or use env. vars. mvprog="${MVPROG-mv}" cpprog="${CPPROG-cp}" chmodprog="${CHMODPROG-chmod}" chownprog="${CHOWNPROG-chown}" chgrpprog="${CHGRPPROG-chgrp}" stripprog="${STRIPPROG-strip}" rmprog="${RMPROG-rm}" mkdirprog="${MKDIRPROG-mkdir}" chmodcmd="$chmodprog 0755" chowncmd= chgrpcmd= stripcmd= rmcmd="$rmprog -f" mvcmd="$mvprog" src= dst= dir_arg= dstarg= no_target_directory= 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: -c (ignored) -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. -s $stripprog installed files. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. --help display this help and exit. --version display version info and exit. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG " while test -n "$1"; do case $1 in -c) shift continue;; -d) dir_arg=true shift continue;; -g) chgrpcmd="$chgrpprog $2" shift shift continue;; --help) echo "$usage"; exit $?;; -m) chmodcmd="$chmodprog $2" shift shift continue;; -o) chowncmd="$chownprog $2" shift shift continue;; -s) stripcmd=$stripprog shift continue;; -t) dstarg=$2 shift shift continue;; -T) no_target_directory=true shift continue;; --version) echo "$0 $scriptversion"; exit $?;; *) # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. test -n "$dir_arg$dstarg" && break # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dstarg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dstarg" shift # fnord fi shift # arg dstarg=$arg done break;; esac done if test -z "$1"; 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 for src do # Protect names starting with `-'. case $src in -*) src=./$src ;; esac if test -n "$dir_arg"; then dst=$src src= if test -d "$dst"; then mkdircmd=: chmodcmd= else mkdircmd=$mkdirprog 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 "$dstarg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dstarg # Protect names starting with `-'. case $dst in -*) dst=./$dst ;; esac # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then if test -n "$no_target_directory"; then echo "$0: $dstarg: Is a directory" >&2 exit 1 fi dst=$dst/`basename "$src"` fi fi # This sed command emulates the dirname command. dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` # Make sure that the destination directory exists. # Skip lots of stat calls in the usual case. if test ! -d "$dstdir"; then defaultIFS=' ' IFS="${IFS-$defaultIFS}" oIFS=$IFS # Some sh's can't handle IFS=/ for some reason. IFS='%' set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` shift IFS=$oIFS pathcomp= while test $# -ne 0 ; do pathcomp=$pathcomp$1 shift if test ! -d "$pathcomp"; then $mkdirprog "$pathcomp" # mkdir can fail with a `File exist' error in case several # install-sh are creating the directory concurrently. This # is OK. test -d "$pathcomp" || exit fi pathcomp=$pathcomp/ done fi if test -n "$dir_arg"; then $doit $mkdircmd "$dst" \ && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } else dstfile=`basename "$dst"` # Make a couple of temp file names in the proper directory. dsttmp=$dstdir/_inst.$$_ rmtmp=$dstdir/_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 trap '(exit $?); exit' 1 2 13 15 # Copy the file name to the temp name. $doit $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 "$dsttmp"; } && # Now rename the file to the real destination. { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 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. { if test -f "$dstdir/$dstfile"; then $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ || { echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 (exit 1); exit 1 } else : fi } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" } } fi || { (exit 1); exit 1; } done # The final little trick to "correctly" pass the exit status to the exit trap. { (exit 0); exit 0 } # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-end: "$" # End: libisofs-1.4.2/ltversion.m40000644000175700017510000000126212626305073012555 00000000000000# ltversion.m4 -- version numbers -*- Autoconf -*- # # Copyright (C) 2004 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 3337 ltversion.m4 # This file is part of GNU Libtool m4_define([LT_PACKAGE_VERSION], [2.4.2]) m4_define([LT_PACKAGE_REVISION], [1.3337]) AC_DEFUN([LTVERSION_VERSION], [macro_version='2.4.2' macro_revision='1.3337' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) ]) libisofs-1.4.2/depcomp0000755000175700017510000003710011112746612011640 00000000000000#! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2005-07-09.11 # Copyright (C) 1999, 2000, 2003, 2004, 2005 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, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. # 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 outputing dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit $? ;; -v | --v*) echo "depcomp $scriptversion" exit $? ;; esac 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" # 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 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. "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## 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). ## - 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 -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ## 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. tr ' ' ' ' < "$tmpdepfile" | ## 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. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -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 -eq 0; then : else 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 ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ tr ' ' ' ' >> $depfile echo >> $depfile # The second pass generates a dummy entry for each header file. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> $depfile else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; 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. stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'` tmpdepfile="$stripped.u" if test "$libtool" = yes; then "$@" -Wc,-M else "$@" -M fi stat=$? if test -f "$tmpdepfile"; then : else stripped=`echo "$stripped" | sed 's,^.*/,,'` tmpdepfile="$stripped.u" fi if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi if test -f "$tmpdepfile"; then outname="$stripped.o" # Each line is of the form `foo.o: dependent.h'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; icc) # Intel's C compiler understands `-MD -MF file'. However on # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c # ICC 7.0 will fill foo.d with something like # foo.o: sub/foo.c # foo.o: sub/foo.h # which is wrong. We want: # sub/foo.o: sub/foo.c # sub/foo.o: sub/foo.h # sub/foo.c: # sub/foo.h: # ICC 7.1 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using \ : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -eq 0; then : else 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" ;; 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. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then # With Tru64 cc, shared objects can also be used to make a # static library. This mecanism is used in libtool 1.4 series to # handle both shared and static libraries in a single compilation. # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. # # With libtool 1.5 this exception was removed, and libtool now # generates 2 separate objects for the 2 libraries. These two # compilations output dependencies in 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.libs/$base.lo.d # libtool 1.4 tmpdepfile2=$dir$base.o.d # libtool 1.5 tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.o.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d tmpdepfile4=$dir$base.d "$@" -MD fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" # That's a tab and a space in the []. sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; #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 $1 != '--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:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" tr ' ' ' ' < "$tmpdepfile" | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. 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 $1 != '--mode=compile'; do shift done shift fi # X makedepend shift cleared=no for arg in "$@"; do case $cleared in no) set ""; shift cleared=yes ;; esac 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. -*|$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" cat < "$tmpdepfile" > "$depfile" sed '1,2d' "$tmpdepfile" | tr ' ' ' ' | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. 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 $1 != '--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, regardless of -o, # because we must use -o when running libtool. "$@" || exit $? IFS=" " for arg do case "$arg" in "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" echo " " >> "$depfile" . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-end: "$" # End: libisofs-1.4.2/bootstrap0000755000175700017510000000016611574062527012240 00000000000000#!/bin/sh -x aclocal -I . libtoolize --copy --force autoconf automake --foreign --add-missing --copy --include-deps libisofs-1.4.2/ltmain.sh0000644000175700017510000105235612626305073012121 00000000000000 # libtool (GNU libtool) 2.4.2 # Written by Gordon Matzigkeit , 1996 # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, # 2007, 2008, 2009, 2010, 2011 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 GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, # or obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Usage: $progname [OPTION]... [MODE-ARG]... # # Provide generalized library-building support services. # # --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 # --preserve-dup-deps don't remove duplicate dependency libraries # --quiet, --silent don't print informational messages # --no-quiet, --no-silent # print informational messages (default) # --no-warn don't display warning messages # --tag=TAG use configuration variables from tag TAG # -v, --verbose print more informational messages than default # --no-verbose don't print the extra informational messages # --version print version information # -h, --help, --help-all print short, long, or detailed 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) # $progname: (GNU libtool) 2.4.2 Debian-2.4.2-1.11 # automake: $automake_version # autoconf: $autoconf_version # # Report bugs to . # GNU libtool home page: . # General help using GNU software: . PROGRAM=libtool PACKAGE=libtool VERSION="2.4.2 Debian-2.4.2-1.11" TIMESTAMP="" package_revision=1.3337 # 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 # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } # NLS nuisances: We save the old values to restore during execute mode. lt_user_locale= lt_safe_locale= for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${$lt_var+set}\" = set; then save_$lt_var=\$$lt_var $lt_var=C export $lt_var lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\" lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" fi" done LC_ALL=C LANGUAGE=C export LANGUAGE LC_ALL $lt_unset CDPATH # 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" : ${CP="cp -f"} test "${ECHO+set}" = set || ECHO=${as_echo-'printf %s\n'} : ${MAKE="make"} : ${MKDIR="mkdir"} : ${MV="mv -f"} : ${RM="rm -f"} : ${SHELL="${CONFIG_SHELL-/bin/sh}"} : ${Xsed="$SED -e 1s/^X//"} # Global variables: 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. exit_status=$EXIT_SUCCESS # Make sure IFS has a sensible default lt_nl=' ' IFS=" $lt_nl" dirname="s,/[^/]*$,," basename="s,^.*/,," # func_dirname file append nondir_replacement # Compute the dirname of FILE. If nonempty, add APPEND to the result, # otherwise set result to NONDIR_REPLACEMENT. func_dirname () { func_dirname_result=`$ECHO "${1}" | $SED "$dirname"` if test "X$func_dirname_result" = "X${1}"; then func_dirname_result="${3}" else func_dirname_result="$func_dirname_result${2}" fi } # func_dirname may be replaced by extended shell implementation # func_basename file func_basename () { func_basename_result=`$ECHO "${1}" | $SED "$basename"` } # func_basename may be replaced by extended shell implementation # 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" # Implementation must be kept synchronized with func_dirname # and func_basename. For efficiency, we do not delegate to # those functions but instead duplicate the functionality here. func_dirname_and_basename () { # Extract subdirectory from the argument. func_dirname_result=`$ECHO "${1}" | $SED -e "$dirname"` if test "X$func_dirname_result" = "X${1}"; then func_dirname_result="${3}" else func_dirname_result="$func_dirname_result${2}" fi func_basename_result=`$ECHO "${1}" | $SED -e "$basename"` } # func_dirname_and_basename may be replaced by extended shell implementation # func_stripname 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). # func_strip_suffix prefix name func_stripname () { 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 may be replaced by extended shell implementation # These SED scripts presuppose an absolute path with a trailing slash. pathcar='s,^/\([^/]*\).*$,\1,' pathcdr='s,^/[^/]*,,' removedotparts=':dotsl s@/\./@/@g t dotsl s,/\.$,/,' collapseslashes='s@/\{1,\}@/@g' finalslash='s,/*$,/,' # 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. # value returned in "$func_normal_abspath_result" func_normal_abspath () { # 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 "$removedotparts" -e "$collapseslashes" -e "$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 "$pathcar"` func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$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_normal_abspath_result=$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_relative_path SRCDIR DSTDIR # generates a relative path from SRCDIR to DSTDIR, with a trailing # slash if non-empty, suitable for immediately appending a filename # without needing to append a separator. # value returned in "$func_relative_path_result" func_relative_path () { 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 "x$func_relative_path_tlibdir" = x ; 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 "x$func_stripname_result" != x ; then func_relative_path_result=${func_relative_path_result}/${func_stripname_result} fi # Normalisation. If bindir is libdir, return empty string, # else relative path ending with a slash; either way, target # file name can be directly appended. if test ! -z "$func_relative_path_result"; then func_stripname './' '' "$func_relative_path_result/" func_relative_path_result=$func_stripname_result fi } # The name of this program: func_dirname_and_basename "$progpath" progname=$func_basename_result # Make sure we have an absolute path for reexecution: case $progpath in [\\/]*|[A-Za-z]:\\*) ;; *[\\/]*) progdir=$func_dirname_result progdir=`cd "$progdir" && pwd` progpath="$progdir/$progname" ;; *) save_IFS="$IFS" IFS=${PATH_SEPARATOR-:} for progdir in $PATH; do IFS="$save_IFS" test -x "$progdir/$progname" && break done IFS="$save_IFS" test -n "$progdir" || progdir=`pwd` progpath="$progdir/$progname" ;; esac # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed="${SED}"' -e 1s/^X//' sed_quote_subst='s/\([`"$\\]\)/\\\1/g' # Same as above, but do not quote variable references. 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 # which contains forward slashes, into one that contains # (escaped) backslashes. A very naive implementation. lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' # Re-`\' parameter expansions in output of double_quote_subst that were # `\'-ed in input to the same. If an odd number of `\' preceded a '$' # in input to 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 '$'. bs='\\' bs2='\\\\' bs4='\\\\\\\\' dollar='\$' sed_double_backslash="\ s/$bs4/&\\ /g s/^$bs2$dollar/$bs&/ s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g s/\n//g" # Standard options: opt_dry_run=false opt_help=false opt_quiet=false opt_verbose=false opt_warning=: # func_echo arg... # Echo program name prefixed message, along with the current mode # name if it has been set yet. func_echo () { $ECHO "$progname: ${opt_mode+$opt_mode: }$*" } # func_verbose arg... # Echo program name prefixed message in verbose mode only. func_verbose () { $opt_verbose && 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_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } # func_error arg... # Echo program name prefixed message to standard error. func_error () { $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2 } # func_warning arg... # Echo program name prefixed warning message to standard error. func_warning () { $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2 # bash bug again: : } # func_fatal_error arg... # Echo program name prefixed message to standard error, and exit. func_fatal_error () { func_error ${1+"$@"} exit $EXIT_FAILURE } # func_fatal_help arg... # Echo program name prefixed message to standard error, followed by # a help hint, and exit. func_fatal_help () { func_error ${1+"$@"} func_fatal_error "$help" } help="Try \`$progname --help' for more information." ## default # func_grep expression filename # Check whether EXPRESSION matches any line of FILENAME, without output. func_grep () { $GREP "$1" "$2" >/dev/null 2>&1 } # func_mkdir_p directory-path # Make sure the entire path to DIRECTORY-PATH is available. func_mkdir_p () { my_directory_path="$1" my_dir_list= if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then # Protect directory names starting with `-' case $my_directory_path in -*) my_directory_path="./$my_directory_path" ;; esac # While some portion of DIR does not yet exist... while test ! -d "$my_directory_path"; do # ...make a list in topmost first order. Use a colon delimited # list incase some portion of path contains whitespace. my_dir_list="$my_directory_path:$my_dir_list" # If the last portion added has no slash in it, the list is done case $my_directory_path in */*) ;; *) break ;; esac # ...otherwise throw away the child directory and loop my_directory_path=`$ECHO "$my_directory_path" | $SED -e "$dirname"` done my_dir_list=`$ECHO "$my_dir_list" | $SED 's,:*$,,'` save_mkdir_p_IFS="$IFS"; IFS=':' for my_dir in $my_dir_list; do IFS="$save_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 "$my_dir" 2>/dev/null || : done IFS="$save_mkdir_p_IFS" # Bail out if we (or some other process) failed to create a directory. test -d "$my_directory_path" || \ func_fatal_error "Failed to create \`$1'" fi } # func_mktempdir [string] # Make a temporary directory that won't clash with other running # libtool processes, and avoids race conditions if possible. If # given, STRING is the basename for that directory. func_mktempdir () { my_template="${TMPDIR-/tmp}/${1-$progname}" if test "$opt_dry_run" = ":"; then # Return a directory name, but don't create it in dry-run mode my_tmpdir="${my_template}-$$" else # If mktemp works, use that first and foremost my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` if test ! -d "$my_tmpdir"; then # Failing that, at least try and use $RANDOM to avoid a race my_tmpdir="${my_template}-${RANDOM-0}$$" save_mktempdir_umask=`umask` umask 0077 $MKDIR "$my_tmpdir" umask $save_mktempdir_umask fi # If we're not in dry-run mode, bomb out on failure test -d "$my_tmpdir" || \ func_fatal_error "cannot create temporary directory \`$my_tmpdir'" fi $ECHO "$my_tmpdir" } # func_quote_for_eval arg # Aesthetically quote ARG to be evaled later. # This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT # is double-quoted, suitable for a subsequent eval, whereas # FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters # which are still active within double quotes backslashified. func_quote_for_eval () { case $1 in *[\\\`\"\$]*) func_quote_for_eval_unquoted_result=`$ECHO "$1" | $SED "$sed_quote_subst"` ;; *) func_quote_for_eval_unquoted_result="$1" ;; esac case $func_quote_for_eval_unquoted_result in # Double-quote args containing shell metacharacters to delay # word splitting, command substitution and 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_for_eval_result="\"$func_quote_for_eval_unquoted_result\"" ;; *) func_quote_for_eval_result="$func_quote_for_eval_unquoted_result" esac } # func_quote_for_expand arg # Aesthetically quote ARG to be evaled later; same as above, # but do not quote variable references. func_quote_for_expand () { case $1 in *[\\\`\"]*) my_arg=`$ECHO "$1" | $SED \ -e "$double_quote_subst" -e "$sed_double_backslash"` ;; *) my_arg="$1" ;; esac case $my_arg in # Double-quote args containing shell metacharacters to delay # word splitting and command substitution for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") my_arg="\"$my_arg\"" ;; esac func_quote_for_expand_result="$my_arg" } # func_show_eval cmd [fail_exp] # Unless opt_silent 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 () { my_cmd="$1" my_fail_exp="${2-:}" ${opt_silent-false} || { func_quote_for_expand "$my_cmd" eval "func_echo $func_quote_for_expand_result" } if ${opt_dry_run-false}; then :; else eval "$my_cmd" my_status=$? if test "$my_status" -eq 0; then :; else eval "(exit $my_status); $my_fail_exp" fi fi } # func_show_eval_locale cmd [fail_exp] # Unless opt_silent 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 () { my_cmd="$1" my_fail_exp="${2-:}" ${opt_silent-false} || { func_quote_for_expand "$my_cmd" eval "func_echo $func_quote_for_expand_result" } if ${opt_dry_run-false}; then :; else eval "$lt_user_locale $my_cmd" my_status=$? eval "$lt_safe_locale" if test "$my_status" -eq 0; then :; else eval "(exit $my_status); $my_fail_exp" fi 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 () { case $1 in [0-9]* | *[!a-zA-Z0-9_]*) func_tr_sh_result=`$ECHO "$1" | $SED 's/^\([0-9]\)/_\1/; s/[^a-zA-Z0-9_]/_/g'` ;; * ) func_tr_sh_result=$1 ;; esac } # func_version # Echo version message to standard output and exit. func_version () { $opt_debug $SED -n '/(C)/!b go :more /\./!{ N s/\n# / / b more } :go /^# '$PROGRAM' (GNU /,/# warranty; / { s/^# // s/^# *$// s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ p }' < "$progpath" exit $? } # func_usage # Echo short help message to standard output and exit. func_usage () { $opt_debug $SED -n '/^# Usage:/,/^# *.*--help/ { s/^# // s/^# *$// s/\$progname/'$progname'/ p }' < "$progpath" echo $ECHO "run \`$progname --help | more' for full usage" exit $? } # func_help [NOEXIT] # Echo long help message to standard output and exit, # unless 'noexit' is passed as argument. func_help () { $opt_debug $SED -n '/^# Usage:/,/# Report bugs to/ { :print s/^# // s/^# *$// s*\$progname*'$progname'* s*\$host*'"$host"'* s*\$SHELL*'"$SHELL"'* s*\$LTCC*'"$LTCC"'* s*\$LTCFLAGS*'"$LTCFLAGS"'* s*\$LD*'"$LD"'* s/\$with_gnu_ld/'"$with_gnu_ld"'/ s/\$automake_version/'"`(${AUTOMAKE-automake} --version) 2>/dev/null |$SED 1q`"'/ s/\$autoconf_version/'"`(${AUTOCONF-autoconf} --version) 2>/dev/null |$SED 1q`"'/ p d } /^# .* home page:/b print /^# General help using/b print ' < "$progpath" ret=$? if test -z "$1"; then exit $ret fi } # func_missing_arg argname # Echo program name prefixed message to standard error and set global # exit_cmd. func_missing_arg () { $opt_debug func_error "missing argument for $1." exit_cmd=exit } # 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. func_split_short_opt () { my_sed_short_opt='1s/^\(..\).*$/\1/;q' my_sed_short_rest='1s/^..\(.*\)$/\1/;q' func_split_short_opt_name=`$ECHO "$1" | $SED "$my_sed_short_opt"` func_split_short_opt_arg=`$ECHO "$1" | $SED "$my_sed_short_rest"` } # func_split_short_opt may be replaced by extended shell implementation # func_split_long_opt longopt # Set func_split_long_opt_name and func_split_long_opt_arg shell # variables after splitting LONGOPT at the `=' sign. func_split_long_opt () { my_sed_long_opt='1s/^\(--[^=]*\)=.*/\1/;q' my_sed_long_arg='1s/^--[^=]*=//' func_split_long_opt_name=`$ECHO "$1" | $SED "$my_sed_long_opt"` func_split_long_opt_arg=`$ECHO "$1" | $SED "$my_sed_long_arg"` } # func_split_long_opt may be replaced by extended shell implementation exit_cmd=: magic="%%%MAGIC variable%%%" magic_exe="%%%MAGIC EXE variable%%%" # Global variables. nonopt= preserve_args= lo2o="s/\\.lo\$/.${objext}/" o2lo="s/\\.${objext}\$/.lo/" 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= # func_append var value # Append VALUE to the end of shell variable VAR. func_append () { eval "${1}=\$${1}\${2}" } # func_append may be replaced by extended shell implementation # func_append_quoted var value # Quote VALUE and append to the end of shell variable VAR, separated # by a space. func_append_quoted () { func_quote_for_eval "${2}" eval "${1}=\$${1}\\ \$func_quote_for_eval_result" } # func_append_quoted may be replaced by extended shell implementation # func_arith arithmetic-term... func_arith () { func_arith_result=`expr "${@}"` } # func_arith may be replaced by extended shell implementation # func_len string # STRING may not start with a hyphen. func_len () { func_len_result=`expr "${1}" : ".*" 2>/dev/null || echo $max_cmd_len` } # func_len may be replaced by extended shell implementation # func_lo2o object func_lo2o () { func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"` } # func_lo2o may be replaced by extended shell implementation # func_xform libobj-or-source func_xform () { func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'` } # func_xform may be replaced by extended shell implementation # func_fatal_configuration arg... # Echo program name prefixed message to standard error, followed by # a configuration failure hint, and exit. func_fatal_configuration () { func_error ${1+"$@"} func_error "See the $PACKAGE documentation for more information." func_fatal_error "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 "$build_libtool_libs" = yes; then echo "enable shared libraries" else echo "disable shared libraries" fi if test "$build_old_libs" = yes; 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 } # 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 ;; esac # Option defaults: opt_debug=: opt_dry_run=false opt_config=false opt_preserve_dup_deps=false opt_features=false opt_finish=false opt_help=false opt_help_all=false opt_silent=: opt_warning=: opt_verbose=: opt_silent=false opt_verbose=false # Parse options once, thoroughly. This comes as soon as possible in the # script to make things like `--version' happen as quickly as we can. { # this just eases exit handling while test $# -gt 0; do opt="$1" shift case $opt in --debug|-x) opt_debug='set -x' func_echo "enabling shell trace mode" $opt_debug ;; --dry-run|--dryrun|-n) opt_dry_run=: ;; --config) opt_config=: func_config ;; --dlopen|-dlopen) optarg="$1" opt_dlopen="${opt_dlopen+$opt_dlopen }$optarg" shift ;; --preserve-dup-deps) opt_preserve_dup_deps=: ;; --features) opt_features=: func_features ;; --finish) opt_finish=: set dummy --mode finish ${1+"$@"}; shift ;; --help) opt_help=: ;; --help-all) opt_help_all=: opt_help=': help-all' ;; --mode) test $# = 0 && func_missing_arg $opt && break optarg="$1" opt_mode="$optarg" case $optarg in # Valid mode arguments: clean|compile|execute|finish|install|link|relink|uninstall) ;; # Catch anything else as an error *) func_error "invalid argument for $opt" exit_cmd=exit break ;; esac shift ;; --no-silent|--no-quiet) opt_silent=false func_append preserve_args " $opt" ;; --no-warning|--no-warn) opt_warning=false func_append preserve_args " $opt" ;; --no-verbose) opt_verbose=false func_append preserve_args " $opt" ;; --silent|--quiet) opt_silent=: func_append preserve_args " $opt" opt_verbose=false ;; --verbose|-v) opt_verbose=: func_append preserve_args " $opt" opt_silent=false ;; --tag) test $# = 0 && func_missing_arg $opt && break optarg="$1" opt_tag="$optarg" func_append preserve_args " $opt $optarg" func_enable_tag "$optarg" shift ;; -\?|-h) func_usage ;; --help) func_help ;; --version) func_version ;; # Separate optargs to long options: --*=*) func_split_long_opt "$opt" set dummy "$func_split_long_opt_name" "$func_split_long_opt_arg" ${1+"$@"} shift ;; # Separate non-argument short options: -\?*|-h*|-n*|-v*) func_split_short_opt "$opt" set dummy "$func_split_short_opt_name" "-$func_split_short_opt_arg" ${1+"$@"} shift ;; --) break ;; -*) func_fatal_help "unrecognized option \`$opt'" ;; *) set dummy "$opt" ${1+"$@"}; shift; break ;; esac done # Validate options: # save first non-option argument if test "$#" -gt 0; then nonopt="$opt" shift fi # preserve --debug test "$opt_debug" = : || func_append preserve_args " --debug" case $host in *cygwin* | *mingw* | *pw32* | *cegcc*) # 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 if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then func_fatal_configuration "not configured to build any kind of library" fi # Darwin sucks eval std_shrext=\"$shrext_cmds\" # Only execute mode is allowed to have -dlopen flags. if test -n "$opt_dlopen" && test "$opt_mode" != execute; 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." } # Bail if the options were screwed $exit_cmd $EXIT_FAILURE } ## ----------- ## ## Main. ## ## ----------- ## # 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 \ | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 } # 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 "$lalib_p" = yes } # 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 () { func_lalib_p "$1" } # 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 () { $opt_debug save_ifs=$IFS; IFS='~' for cmd in $1; do IFS=$save_ifs eval cmd=\"$cmd\" 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 () { $opt_debug 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 () { $opt_debug 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 "$build_libtool_libs" = yes; then write_lobj=\'${2}\' else write_lobj=none fi if test "$build_old_libs" = yes; 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 "$lt_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 () { $opt_debug # 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 () { $opt_debug 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 () { $opt_debug # awkward: cmd appends spaces to result func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | $SED -e 's/[ ]*$//' -e "$lt_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 () { $opt_debug 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 () { $opt_debug 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 () { $opt_debug 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 () { $opt_debug $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 () { $opt_debug 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 () { $opt_debug 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 () { $opt_debug 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 () { $opt_debug 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 () { $opt_debug 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 () { $opt_debug 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 () { $opt_debug 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 () { $opt_debug 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 () { $opt_debug 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 () { $opt_debug 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 () { $opt_debug 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 () { $opt_debug 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 () { $opt_debug 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_mode_compile arg... func_mode_compile () { $opt_debug # 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 "$build_libtool_libs" != yes && \ func_fatal_configuration "can not 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_for_eval "$libobj" test "X$libobj" != "X$func_quote_for_eval_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 "$build_old_libs" = yes; 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 "$pic_mode" = no && test "$deplibs_check_method" != pass_all; 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 "$compiler_c_o" = no; 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 "$need_locks" = yes; 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 "$need_locks" = warn; 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_for_eval "$srcfile" qsrcfile=$func_quote_for_eval_result # Only build a PIC object if we are building libtool libraries. if test "$build_libtool_libs" = yes; then # Without this assignment, base_compile gets emptied. fbsd_hideous_sh_bug=$base_compile if test "$pic_mode" != no; 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 "$need_locks" = warn && 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 "$suppress_opt" = yes; then suppress_output=' >/dev/null 2>&1' fi fi # Only build a position-dependent object if we build old libraries. if test "$build_old_libs" = yes; then if test "$pic_mode" != yes; then # Don't build PIC code command="$base_compile $qsrcfile$pie_flag" else command="$base_compile $qsrcfile $pic_flag" fi if test "$compiler_c_o" = yes; 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 "$need_locks" = warn && 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 "$need_locks" != no; then removelist=$lockfile $RM "$lockfile" fi } exit $EXIT_SUCCESS } $opt_help || { test "$opt_mode" = compile && 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 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 -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 -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 () { $opt_debug # 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 test "X$opt_dry_run" = Xfalse; then 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" else # 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 fi } test "$opt_mode" = execute && func_mode_execute ${1+"$@"} # func_mode_finish arg... func_mode_finish () { $opt_debug 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_silent && 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 "$opt_mode" = finish && func_mode_finish ${1+"$@"} # func_mode_install arg... func_mode_install () { $opt_debug # There may be an optional sh(1) argument at the beginning of # install_prog (especially on Windows NT). if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || # Allow the use of GNU shtool's install command. case $nonopt in *shtool*) :;; *) false;; esac; then # Aesthetically quote it. func_quote_for_eval "$nonopt" install_prog="$func_quote_for_eval_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_for_eval "$arg" func_append install_prog "$func_quote_for_eval_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=no 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=yes ;; -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$prev" = x-m && 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_for_eval "$arg" func_append install_prog " $func_quote_for_eval_result" if test -n "$arg2"; then func_quote_for_eval "$arg2" fi func_append install_shared_prog " $func_quote_for_eval_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_for_eval "$install_override_mode" func_append install_shared_prog " -m $func_quote_for_eval_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=yes if test "$isdir" = yes; 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 ;; 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 "$build_old_libs" = yes; 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=yes 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'` ### testsuite: skip nested quoting test if test -n "$libdir" && test ! -f "$libfile"; then func_warning "\`$lib' has not been installed in \`$libdir'" finalize=no fi done relink_command= func_source "$wrapper" outputname= if test "$fast_install" = no && test -n "$relink_command"; then $opt_dry_run || { if test "$finalize" = yes; 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_silent || { func_quote_for_expand "$relink_command" eval "func_echo $func_quote_for_expand_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 "$opt_mode" = install && 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 () { $opt_debug my_outputname="$1" my_originator="$2" my_pic_p="${3-no}" my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'` my_dlsyms= if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; 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$TIMESTAMP) $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 con'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 /* External symbol declarations for the compiler. */\ " if test "$dlself" = yes; 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 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[]; LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[] = {\ { \"$my_originator\", (void *) 0 }," 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" ;; *) if test "X$my_pic_p" != Xno; then pic_flag_for_symtable=" $pic_flag" fi ;; 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"' # 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_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 () { $opt_debug 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 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 } }'` 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 () { $opt_debug 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 () { $opt_debug 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 which possess that section. Heuristic: eliminate # all those which 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_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 () { $opt_debug 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 () { $opt_debug 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_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 () { $opt_debug 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 () { $opt_debug f_ex_an_ar_dir="$1"; shift f_ex_an_ar_oldlib="$1" if test "$lock_old_archive_extraction" = yes; 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 "$lock_old_archive_extraction" = yes; 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 () { $opt_debug 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` darwin_base_archive=`basename "$darwin_archive"` 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 "$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 in which 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$TIMESTAMP) $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\"" qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` $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/ which is used only on # windows platforms, and (c) all begin with the string "--lt-" # (application programs are unlikely to have options which 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$TIMESTAMP) $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 "$fast_install" = yes; 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 "$shlibpath_overrides_runpath" = yes && 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 /* 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 platforms) ... */ #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 # ifndef _INTPTR_T_DEFINED # define _INTPTR_T_DEFINED # define intptr_t int # endif #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 ((void *) 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]; int 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 = 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 (strcmp (str, pat) == 0) *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 int 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) { int orig_value_len = strlen (orig_value); int 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 #' */ int len = strlen (new_value); while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1])) { new_value[len-1] = '\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 () { $opt_debug case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in *import*) : ;; *) false ;; esac } # func_mode_link arg... func_mode_link () { $opt_debug 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 # which 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 which 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= non_pic_objects= precious_files_regex= prefer_static_libs=no preload=no 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 "$build_libtool_libs" != yes && \ func_fatal_configuration "can not build a shared library" build_old_libs=no break ;; -all-static | -static | -static-libtool-libs) case $arg in -all-static) if test "$build_libtool_libs" = yes && 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_for_eval "$arg" qarg=$func_quote_for_eval_unquoted_result func_append libtool_args " $func_quote_for_eval_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) if test "$preload" = no; then # Add the symbol object into the linking commands. func_append compile_command " @SYMFILE@" func_append finalize_command " @SYMFILE@" preload=yes fi case $arg in *.la | *.lo) ;; # We handle these cases below. force) if test "$dlself" = no; then dlself=needless export_dynamic=yes fi prev= continue ;; self) if test "$prev" = dlprefiles; then dlself=yes elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then dlself=yes else dlself=needless export_dynamic=yes fi prev= continue ;; *) if test "$prev" = dlfiles; 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 ;; 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 "$pic_object" = none && test "$non_pic_object" = none; 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 "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; 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 "$prev" = dlprefiles; 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 "$non_pic_object" != none; 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 "$pic_object" = none ; 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 ;; 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 "$prev" = rpath; 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 ;; 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$arg" = "X-export-symbols"; 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$arg" = "X-lc" || test "X$arg" = "X-lm"; 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$arg" = "X-lc" && continue ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. test "X$arg" = "X-lc" && 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$arg" = "X-lc" && continue ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work test "X$arg" = "X-lc" && continue ;; esac elif test "X$arg" = "X-lc_r"; then case $host in *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc_r directly, use -pthread flag. continue ;; esac fi func_append deplibs " $arg" 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 ;; -mt|-mthreads|-kthread|-Kthread|-pthread|-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 ;; -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_for_eval "$flag" func_append arg " $func_quote_for_eval_result" func_append compiler_flags " $func_quote_for_eval_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_for_eval "$flag" func_append arg " $wl$func_quote_for_eval_result" func_append compiler_flags " $wl$func_quote_for_eval_result" func_append linker_flags " $func_quote_for_eval_result" done IFS="$save_ifs" func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Xcompiler) prev=xcompiler continue ;; -Xlinker) prev=xlinker continue ;; -XCClinker) prev=xcclinker continue ;; # -msg_* for osf cc -msg_*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_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 # @file GCC response files # -tp=* Portland pgcc target processor selection # --sysroot=* for sysroot support # -O*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization -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*|-flto*|-fwhopr*|-fuse-linker-plugin) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" func_append compile_command " $arg" func_append finalize_command " $arg" func_append compiler_flags " $arg" continue ;; # Some other compiler flag. -* | +*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_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 "$pic_object" = none && test "$non_pic_object" = none; 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 "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; 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 "$prev" = dlprefiles; 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 "$non_pic_object" != none; 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 "$pic_object" = none ; 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 "$prev" = dlfiles; then # This library was specified with -dlopen. func_append dlfiles " $func_resolve_sysroot_result" prev= elif test "$prev" = dlprefiles; 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_for_eval "$arg" arg="$func_quote_for_eval_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 "$export_dynamic" = yes && 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\" 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 "$linkmode" = lib; 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=no 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 "$linkmode,$pass" = "lib,link"; 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 "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan"; then libs="$deplibs" deplibs= fi if test "$linkmode" = prog; then case $pass in dlopen) libs="$dlfiles" ;; dlpreopen) libs="$dlprefiles" ;; link) libs="$deplibs %DEPLIBS%" test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs" ;; esac fi if test "$linkmode,$pass" = "lib,dlpreopen"; 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 "$pass" = dlopen; then # Collect dlpreopened libraries save_deplibs="$deplibs" deplibs= fi for deplib in $libs; do lib= found=no case $deplib in -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append compiler_flags " $deplib" if test "$linkmode" = lib ; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -l*) if test "$linkmode" != lib && test "$linkmode" != prog; then func_warning "\`-l' is ignored for archives/objects" continue fi func_stripname '-l' '' "$deplib" name=$func_stripname_result if test "$linkmode" = lib; 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 "$search_ext" = ".la"; then found=yes else found=no fi break 2 fi done done if test "$found" != yes; then # deplib doesn't seem to be a libtool library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue else # 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 "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; 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=no func_dirname "$lib" "" "." ladir="$func_dirname_result" lib=$ladir/$old_library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue fi fi ;; *) ;; esac fi fi ;; # -l *.ltframework) if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" if test "$linkmode" = lib ; 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 "$pass" = conv && 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 "$pass" = conv; then deplibs="$deplib $deplibs" continue fi if test "$pass" = scan; 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 "$pass" = link; 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 "$pass" = conv; 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=no 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=yes fi ;; pass_all) valid_a_lib=yes ;; esac if test "$valid_a_lib" != yes; then 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." else echo $ECHO "*** Warning: Linking the shared library $output against the" $ECHO "*** static library $deplib is not portable!" deplibs="$deplib $deplibs" fi ;; esac continue ;; prog) if test "$pass" != link; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi continue ;; esac # linkmode ;; # *.$libext *.lo | *.$objext) if test "$pass" = conv; then deplibs="$deplib $deplibs" elif test "$linkmode" = prog; then if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; 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=yes continue ;; esac # case $deplib if test "$found" = yes || test -f "$lib"; then : else func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'" fi # 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 "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan" || { test "$linkmode" != prog && test "$linkmode" != lib; }; then test -n "$dlopen" && func_append dlfiles " $dlopen" test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" fi if test "$pass" = conv; 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" 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 elif test "$linkmode" != prog && test "$linkmode" != lib; then func_fatal_error "\`$lib' is not a convenience library" fi continue fi # $pass = conv # Get the name of the library we link against. linklib= if test -n "$old_library" && { test "$prefer_static_libs" = yes || test "$prefer_static_libs,$installed" = "built,no"; }; 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 "$pass" = dlopen; then if test -z "$libdir"; then func_fatal_error "cannot -dlopen a convenience library: \`$lib'" fi if test -z "$dlname" || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; 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 "X$installed" = Xyes; 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 "X$hardcode_automatic" = Xyes && 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 "$pass" = dlpreopen; then if test -z "$libdir" && test "$linkmode" = prog; 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 "$linkmode" = lib; then deplibs="$dir/$old_library $deplibs" elif test "$linkmode,$pass" = "prog,link"; 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 "$linkmode" = prog && test "$pass" != link; then func_append newlib_search_path " $ladir" deplibs="$lib $deplibs" linkalldeplibs=no if test "$link_all_deplibs" != no || test -z "$library_names" || test "$build_libtool_libs" = no; then linkalldeplibs=yes 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 test "$linkalldeplibs" = yes; 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 "$linkmode,$pass" = "prog,link"; then if test -n "$library_names" && { { test "$prefer_static_libs" = no || test "$prefer_static_libs,$installed" = "built,yes"; } || 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 test "$alldeplibs" = yes && { test "$deplibs_check_method" = pass_all || { test "$build_libtool_libs" = yes && 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 "$use_static_libs" = built && test "$installed" = yes; then use_static_libs=no fi if test -n "$library_names" && { test "$use_static_libs" = no || test -z "$old_library"; }; then case $host in *cygwin* | *mingw* | *cegcc*) # No point in relinking DLLs because paths are not encoded func_append notinst_deplibs " $lib" need_relink=no ;; *) if test "$installed" = no; 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 "$shouldnotlink" = yes && test "$pass" = link; then echo if test "$linkmode" = prog; 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 "$linkmode" = lib && test "$hardcode_into_libs" = yes; 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*) 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 "$linkmode" = prog || test "$opt_mode" != relink; then add_shlibpath= add_dir= add= lib_linked=yes case $hardcode_action in immediate | unsupported) if test "$hardcode_direct" = no; 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 can not # 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 "$hardcode_minus_L" = no; then case $host in *-*-sunos*) add_shlibpath="$dir" ;; esac add_dir="-L$dir" add="-l$name" elif test "$hardcode_shlibpath_var" = no; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; relink) if test "$hardcode_direct" = yes && test "$hardcode_direct_absolute" = no; then add="$dir/$linklib" elif test "$hardcode_minus_L" = yes; 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 "$hardcode_shlibpath_var" = yes; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; *) lib_linked=no ;; esac if test "$lib_linked" != yes; 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 "$linkmode" = prog; 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 "$hardcode_direct" != yes && test "$hardcode_minus_L" != yes && test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac fi fi fi if test "$linkmode" = prog || test "$opt_mode" = relink; then add_shlibpath= add_dir= add= # Finalize command for both is simple: just hardcode it. if test "$hardcode_direct" = yes && test "$hardcode_direct_absolute" = no; then add="$libdir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$libdir" add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac add="-l$name" elif test "$hardcode_automatic" = yes; 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$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 "$linkmode" = prog; 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 "$linkmode" = prog; 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 "$hardcode_direct" != unsupported; 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 "$build_libtool_libs" = yes; then # Not a shared library if test "$deplibs_check_method" != pass_all; 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 can not 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 "$module" = yes; 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 "$build_old_libs" = no; 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 "$linkmode" = lib; then if test -n "$dependency_libs" && { test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes || test "$link_static" = yes; }; 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 "$link_static" = no && 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 "$link_all_deplibs" != no; 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 "$pass" = link; then if test "$linkmode" = "prog"; 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 "$pass" = dlpreopen; then # Link the dlpreopened libraries before other libraries for deplib in $save_deplibs; do deplibs="$deplib $deplibs" done fi if test "$pass" != dlopen; then if test "$pass" != conv; then # 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= fi if test "$linkmode,$pass" != "prog,link"; then vars="deplibs" else vars="compile_deplibs finalize_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 # 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 "$linkmode" = prog; then dlfiles="$newdlfiles" fi if test "$linkmode" = prog || test "$linkmode" = lib; then dlprefiles="$newdlprefiles" fi case $linkmode in oldlib) if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; 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 "$module" = no && \ func_fatal_help "libtool library \`$output' must begin with \`lib'" if test "$need_lib_prefix" != no; 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 "$deplibs_check_method" != pass_all; 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 "$dlself" != no && \ func_warning "\`-dlopen self' is ignored for libtool libraries" set dummy $rpath shift test "$#" -gt 1 && \ func_warning "ignoring multiple \`-rpath's for a libtool library" install_libdir="$1" oldlibs= if test -z "$rpath"; then if test "$build_libtool_libs" = yes; 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 # which has an extra 1 added just for fun # case $version_type in # correct linux to gnu/linux during the next big refactor darwin|linux|osf|windows|none) func_arith $number_major + $number_minor current=$func_arith_result age="$number_minor" revision="$number_revision" ;; freebsd-aout|freebsd-elf|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 ;; *) func_fatal_configuration "$modename: unknown library version type \`$version_type'" ;; 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" ;; freebsd-aout) major=".$current" versuffix=".$current.$revision"; ;; freebsd-elf) major=.`expr $current - $age` versuffix="$major" ;; defunct_by_ts_B51007_freebsd-elf) major=".$current" versuffix=".$current"; ;; netbsd) # ts B51007 : to get library.so.N.nn major=.`expr $current - $age` versuffix="$major.$age" ;; irix | nonstopux) if test "X$lt_irix_increment" = "Xno"; 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 "$loop" -ne 0; 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 "$loop" -ne 0; 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" ;; sunos) major=".$current" versuffix=".$current.$revision" ;; windows) # Use '-' rather than '.', since we only want one # extension on DOS 8.3 filesystems. 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 "$need_version" = no; then versuffix= else versuffix=".0.0" fi fi # Remove version info from name if versioning should be avoided if test "$avoid_version" = yes && test "$need_version" = no; then major= versuffix= verstring="" fi # Check to see if the archive will have undefined symbols. if test "$allow_undefined" = yes; then if test "$allow_undefined_flag" = unsupported; then func_warning "undefined symbols not allowed in $host shared libraries" build_libtool_libs=no build_old_libs=yes fi else # Don't allow undefined symbols. allow_undefined_flag="$no_undefined_flag" fi fi func_generate_dlsyms "$libname" "$libname" "yes" func_append libobjs " $symfileobj" test "X$libobjs" = "X " && libobjs= if test "$opt_mode" != relink; 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 "X$precious_files_regex" != "X"; 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 "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; 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 "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; 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 "$build_libtool_libs" = yes; 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*) # 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 "$build_libtool_need_lc" = "yes"; 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 "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; 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 "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; 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 "X$deplibs_check_method" = "Xnone"; 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 "$droppeddeps" = yes; then if test "$module" = yes; 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 "$build_old_libs" = no; 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 "$allow_undefined" = no; 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 "$build_old_libs" = no; 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 "$build_libtool_libs" = yes; then # Remove ${wl} instances when linking with ld. # FIXME: should test the right _cmds variable. case $archive_cmds in *\$LD\ *) wl= ;; esac if test "$hardcode_into_libs" = yes; then # Hardcode the library paths hardcode_libdirs= dep_rpath= rpath="$finalize_rpath" test "$opt_mode" != relink && rpath="$compile_rpath$rpath" for libdir in $rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then func_replace_sysroot "$libdir" libdir=$func_replace_sysroot_result 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 "$opt_mode" != relink && 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 if test "x`$SED 1q $export_symbols`" != xEXPORTS; then # 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 fi ;; esac # Prepare the list of exported symbols if test -z "$export_symbols"; then if test "$always_export_symbols" = yes || 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 "$try_normal_branch" = yes \ && { 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 "X$skipped_export" != "X:"; 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 "X$skipped_export" != "X:" && 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 "$compiler_needs_object" = yes && 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 "$thread_safe" = yes && 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 "$opt_mode" = relink; 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 "$module" = yes && 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 "X$skipped_export" != "X:" && 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 "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; 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 "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then output=${output_objdir}/${output_la}.lnk func_verbose "creating linker input file list: $output" : > $output set x $save_libobjs shift firstobj= if test "$compiler_needs_object" = yes; 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 "X$objlist" = X || 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 "$k" -eq 1 ; 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 if ${skipped_export-false}; then 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 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_silent || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test "$opt_mode" = relink; 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 if ${skipped_export-false}; then 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 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 "$module" = yes && 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="$save_ifs" eval cmd=\"$cmd\" $opt_silent || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test "$opt_mode" = relink; 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 "$opt_mode" = relink; 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 "$module" = yes || test "$export_dynamic" = yes; then # On all known operating systems, these are identical. dlname="$soname" fi fi ;; obj) if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; 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= # reload_cmds runs $LD directly, so let us get rid of # -Wl from whole_archive_flag_spec and hope we can get by with # turning comma into space.. wl= if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" reload_conv_objs=$reload_objs\ `$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` 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 "$build_libtool_libs" != yes && 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" ### testsuite: skip nested quoting test 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 if test "$build_libtool_libs" != yes; then 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 fi if test -n "$pic_flag" || test "$pic_mode" != default; 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" test "$preload" = yes \ && test "$dlopen_support" = unknown \ && test "$dlopen_self" = unknown \ && test "$dlopen_self_static" = unknown && \ 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 "$tagname" = CXX ; 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 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 "$build_old_libs" = yes; 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@" "no" # template prelinking step if test -n "$prelink_cmds"; then func_execute_cmds "$prelink_cmds" 'exit $?' fi wrappers_required=yes case $host in *cegcc* | *mingw32ce*) # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. wrappers_required=no ;; *cygwin* | *mingw* ) if test "$build_libtool_libs" != yes; then wrappers_required=no fi ;; *) if test "$need_relink" = no || test "$build_libtool_libs" != yes; then wrappers_required=no fi ;; esac if test "$wrappers_required" = no; then # 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 fi 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 "$no_install" = yes; 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 if test "$hardcode_action" = relink; then # 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" else if test "$fast_install" != no; then link_command="$finalize_var$compile_command$finalize_rpath" if test "$fast_install" = yes; then relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` else # fast_install is set to needless relink_command= fi else link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" fi fi # 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_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done relink_command="(cd `pwd`; $relink_command)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` 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 if test "$build_libtool_libs" = convenience; then oldobjs="$libobjs_save $symfileobj" addlibs="$convenience" build_libtool_libs=no else if test "$build_libtool_libs" = module; then oldobjs="$libobjs_save" build_libtool_libs=no else oldobjs="$old_deplibs $non_pic_objects" if test "$preload" = yes && test -f "$symfileobj"; then func_append oldobjs " $symfileobj" fi fi addlibs="$old_convenience" fi 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 "$build_libtool_libs" = yes; 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 "X$oldobjs" = "X" ; 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 "$build_old_libs" = yes && 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_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done # Quote the link command for shipping. relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` if test "$hardcode_automatic" = yes ; then relink_command= fi # Only create the output if not a dry run. $opt_dry_run || { for installed in no yes; do if test "$installed" = yes; 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 "x$bindir" != x ; 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$TIMESTAMP) $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 can not 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 "$installed" = no && test "$need_relink" = yes; 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 } { test "$opt_mode" = link || test "$opt_mode" = relink; } && func_mode_link ${1+"$@"} # func_mode_uninstall arg... func_mode_uninstall () { $opt_debug RM="$nonopt" files= rmforce= 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=yes ;; -*) 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 "X$dir" = X.; then odir="$objdir" else odir="$dir/$objdir" fi func_basename "$file" name="$func_basename_result" test "$opt_mode" = uninstall && odir="$dir" # Remember odir for removal later, being careful to avoid duplicates if test "$opt_mode" = clean; 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 test "$rmforce" = yes; 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" 'test "$rmforce" = yes || exit_status=1' fi if test -n "$old_library"; then # Do each command in the old_postuninstall commands. func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || 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 "$pic_object" != none; 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 "$non_pic_object" != none; then func_append rmfiles " $dir/$non_pic_object" fi fi ;; *) if test "$opt_mode" = clean ; 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 "$fast_install" = yes && 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 } { test "$opt_mode" = uninstall || test "$opt_mode" = clean; } && func_mode_uninstall ${1+"$@"} 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 # in which 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: # vi:sw=2 libisofs-1.4.2/ltsugar.m40000644000175700017510000001042412626305073012211 00000000000000# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- # # Copyright (C) 2004, 2005, 2007, 2008 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 ]) libisofs-1.4.2/Roadmap0000644000175700017510000000164111112746253011573 00000000000000 >>>>>>>>>> RELEASE 0.6.1 (development) >>>>>>>>>>>>>>>>>>>>> - Review error severities OK - Prepare API for stability and compatibility check - Documentation >>>>>>>>>> RELEASE 0.6.2 (stable) >>>>>>>>>>>>>>>>>>>>>>>>>> - Intensive testing and bug fixing >>>>>>>>>> RELEASE 0.6.3 (development) >>>>>>>>>>>>>>>>>>>>> - Improves to public tree -> Expose node extended info. Always compile it. (little memory cost) -> Review builder / tree / node relation -> Optimize storage of children in node? -> Inode object? - Expose Builder and Streams - Implement filters: compression, encryption... - Consider some kind of plugin system for Builders, Filesystems and Filters. - ECMA-119, Joliet, and ISO-9660:1999 writers can share most of the code. Create a new writer as a generalization of these. - Update Java bindings >>>>>>>>>>> ...... >>>>>>>>>>> RELEASE 1.0.0 (stable) >>>>>>>>>>>>>>>>>>>>>>>>>> - UDF - HFS libisofs-1.4.2/ltoptions.m40000644000175700017510000003007312626305073012565 00000000000000# Helper functions for option handling. -*- Autoconf -*- # # Copyright (C) 2004, 2005, 2007, 2008, 2009 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 7 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_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_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=default]) test -z "$pic_mode" && 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])]) libisofs-1.4.2/aclocal.m40000644000175700017510000012531212626305073012131 00000000000000# generated automatically by aclocal 1.14.1 -*- Autoconf -*- # Copyright (C) 1996-2013 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.69],, [m4_warning([this file was generated for autoconf 2.69. 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'.])]) # Copyright (C) 2002-2013 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.14' 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.14.1], [], [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.14.1])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-2013 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-2013 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-2013 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 thusly: # 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-2013 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. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "$am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`AS_DIRNAME(["$file"])` AS_MKDIR_P([$dirpart/$fdir]) # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ])# _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. FIXME. This creates each '.P' file that we will # 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" ac_aux_dir="$ac_aux_dir"]) ]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996-2013 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 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_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([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. 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 ]) 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 # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) fi fi ]) 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-2013 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}" != 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-2013 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])]) # Add --enable-maintainer-mode option to configure. -*- Autoconf -*- # From Jim Meyering # Copyright (C) 1996-2013 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_MAINTAINER_MODE([DEFAULT-MODE]) # ---------------------------------- # Control maintainer-specific portions of Makefiles. # Default is to disable them, unless 'enable' is passed literally. # For symmetry, 'disable' may be passed as well. Anyway, the user # can override the default with the --enable/--disable switch. AC_DEFUN([AM_MAINTAINER_MODE], [m4_case(m4_default([$1], [disable]), [enable], [m4_define([am_maintainer_other], [disable])], [disable], [m4_define([am_maintainer_other], [enable])], [m4_define([am_maintainer_other], [enable]) m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])]) AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) dnl maintainer-mode's default is 'disable' unless 'enable' is passed AC_ARG_ENABLE([maintainer-mode], [AS_HELP_STRING([--]am_maintainer_other[-maintainer-mode], am_maintainer_other[ make rules and dependencies not useful (and sometimes confusing) to the casual installer])], [USE_MAINTAINER_MODE=$enableval], [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes])) AC_MSG_RESULT([$USE_MAINTAINER_MODE]) AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes]) MAINT=$MAINTAINER_MODE_TRUE AC_SUBST([MAINT])dnl ] ) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001-2013 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 to see how make treats includes. AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi AC_SUBST([am__include]) AC_SUBST([am__quote]) AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997-2013 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 case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac 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-2013 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-2013 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) 2001-2013 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-2013 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_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [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). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file 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 if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # 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". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi if test "$[2]" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT([yes]) # 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 grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi 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-2013 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([DEFAULT]) # -------------------------- # Enable less verbose build rules; with the default set to DEFAULT # ("yes" being less verbose, "no" or empty being verbose). AC_DEFUN([AM_SILENT_RULES], [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 ]) case $enable_silent_rules in @%:@ ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; esac 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]) 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 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 ]) # Copyright (C) 2001-2013 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-2013 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-2013 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 $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 $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 m4_include([libtool.m4]) m4_include([ltoptions.m4]) m4_include([ltsugar.m4]) m4_include([ltversion.m4]) m4_include([lt~obsolete.m4]) m4_include([acinclude.m4]) libisofs-1.4.2/NEWS0000644000175700017510000000106511112746253010764 00000000000000== Sun Apr 27 2008 == Libisofs v0.6.4 =============== - Extended information: iso_node_add_xinfo() - New node iteration: iso_dir_find_children() - Custom image file content via iso_tree_add_new_file() - Missing feature added to map a disk file to an arbitrary image file path via iso_tree_add_new_node() - Obtain image path of a node object via iso_tree_get_node_path() - Various bugfixes == Fri Feb 22 2008 == Libisofs v0.6.2.1 ================= - FIX: missing buffer.h in tarball == Thu Feb 14 2008 == Libisofs v0.6.2 ================ - Initial release libisofs-1.4.2/INSTALL0000644000175700017510000002231011112746253011312 00000000000000Installation Instructions ************************* Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, 2006 Free Software Foundation, Inc. This file is free documentation; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. Basic Installation ================== Briefly, the shell commands `./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. 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. 4. Type `make install' to install the programs and any data files and documentation. 5. 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. 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 `..'. 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. 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'. 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. 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'. Optional Features ================= 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. 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 bug. Until the bug is fixed you can use this workaround: CONFIG_SHELL=/bin/bash /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 the options to `configure', and exit. `--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. `configure' also accepts some other, not widely useful, options. Run `configure --help' for more details. libisofs-1.4.2/configure0000755000175700017510000156275312626305073012217 00000000000000#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for libisofs 1.4.2. # # Report bugs to . # # # Copyright (C) 1992-1996, 1998-2012 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 -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 as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. 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 # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # 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 test -z "$as_dir" && as_dir=. 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 $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # 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'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_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 -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 " 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 exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || 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 \$(( 1 + 1 )) = 2 || 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" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else 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 test -z "$as_dir" && as_dir=. 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_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS 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'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org and $0: http://libburnia-project.org 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 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=`$as_echo "$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 || $as_echo 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 as_fn_append () { eval $1=\$$1\$2 } 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 as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } 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 $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$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 || $as_echo 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 ' 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" || { $as_echo "$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 } 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 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_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" 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='libisofs' PACKAGE_TARNAME='libisofs' PACKAGE_VERSION='1.4.2' PACKAGE_STRING='libisofs 1.4.2' PACKAGE_BUGREPORT='http://libburnia-project.org' PACKAGE_URL='' ac_default_prefix=/usr/local # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBOBJS LIBBURNIA_LDCONFIG_CMD LIBJTE_DEF ZLIB_DEF XATTR_DEF LIBACL_DEF LIBBURNIA_PKGCONFDIR LIBBURN_ARCH_LIBS ARCH THREAD_LIBS LIBTOOL_DEPS OTOOL64 OTOOL LIPO NMEDIT DSYMUTIL MANIFEST_TOOL RANLIB ac_ct_AR AR DLLTOOL OBJDUMP LN_S NM ac_ct_DUMPBIN DUMPBIN LD FGREP SED LIBTOOL EGREP GREP CPP am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE am__nodep AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE am__quote am__include DEPDIR OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC MAINT MAINTAINER_MODE_FALSE MAINTAINER_MODE_TRUE LT_CURRENT_MINUS_AGE LT_AGE LT_REVISION LT_CURRENT LT_RELEASE LIBISOFS_VERSION LIBISOFS_MICRO_VERSION LIBISOFS_MINOR_VERSION LIBISOFS_MAJOR_VERSION AM_BACKSLASH AM_DEFAULT_VERBOSITY AM_DEFAULT_V AM_V 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_os target_vendor target_cpu target host_os host_vendor host_cpu host build_os build_vendor build_cpu build 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 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' ac_subst_files='' ac_user_opts=' enable_option_checking enable_silent_rules enable_maintainer_mode enable_dependency_tracking enable_largefile enable_shared enable_static with_pic enable_fast_install with_gnu_ld with_sysroot enable_libtool_lock enable_debug enable_verbose_debug enable_libdir_pkgconfig enable_pkgconfig_path enable_libacl enable_xattr enable_zlib enable_libjte enable_versioned_libs enable_ldconfig_at_install ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP' # 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' 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 # Accept the important Cygnus configure options, so we can diagnose typos. 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=`$as_echo "$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=`$as_echo "$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 ;; -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=`$as_echo "$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=`$as_echo "$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. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$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" ;; *) $as_echo "$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 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 || $as_echo 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 libisofs 1.4.2 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] --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/libisofs] --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] --target=TARGET configure for building compilers for TARGET [HOST] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of libisofs 1.4.2:";; 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-maintainer-mode enable make rules and dependencies not useful (and sometimes confusing) to the casual installer --enable-dependency-tracking do not reject slow dependency extractors --disable-dependency-tracking speeds up one-time build --disable-largefile omit support for large files --enable-shared[=PKGS] build shared libraries [default=yes] --enable-static[=PKGS] build static libraries [default=yes] --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) --enable-debug Disable aggressive optimizations, default=yes --enable-verbose-debug Enable verbose debug messages, default=no --enable-libdir-pkgconfig Install to $libdir/pkgconfig on any OS, default=no --enable-pkgconfig-path=DIR Absolute path of directory for libisofs-*.pc --enable-libacl Enable use of ACL functions by libisofs, default=yes --enable-xattr Enable use of xattr by libisofs, default=yes --enable-zlib Enable use of zlib by libisofs, default=yes --enable-libjte Enable use of libjte by libisofs, default=yes --enable-versioned-libs Enable strict symbol encapsulation , default=yes --enable-ldconfig-at-install On GNU/Linux run ldconfig, default=yes 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-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). 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 CPP C preprocessor 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=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$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 guested configure. 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 $as_echo "$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 libisofs configure 1.4.2 generated by GNU Autoconf 2.69 Copyright (C) 2012 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 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\"" $as_echo "$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 $as_echo "$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 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 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_run LINENO # ---------------------- # Try to link 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\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$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\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status 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_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\"" $as_echo "$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 $as_echo "$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 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # 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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else 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 eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_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$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\"" $as_echo "$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 $as_echo "$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 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 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_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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else 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 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #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 (); /* 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 () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ( $as_echo "## ------------------------------------------- ## ## Report this to http://libburnia-project.org ## ## ------------------------------------------- ##" ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel # ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES # ---------------------------------------------------- # Tries to find if the field MEMBER exists in type AGGR, after including # INCLUDES, setting cache variable VAR accordingly. ac_fn_c_check_member () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5 $as_echo_n "checking for $2.$3... " >&6; } if eval \${$4+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $5 int main () { static $2 ac_aggr; if (ac_aggr.$3) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$4=yes" else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $5 int main () { static $2 ac_aggr; if (sizeof ac_aggr.$3) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$4=yes" else eval "$4=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$4 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_member # ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES # --------------------------------------------- # Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR # accordingly. ac_fn_c_check_decl () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack as_decl_name=`echo $2|sed 's/ *(.*//'` as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 $as_echo_n "checking whether $as_decl_name is declared... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { #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 eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_decl 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 libisofs $as_me 1.4.2, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _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 test -z "$as_dir" && as_dir=. $as_echo "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=`$as_echo "$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=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## 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_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$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 $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$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 $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$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 { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file 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,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$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 { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$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=`$as_echo "$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 { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`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_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 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. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # 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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } if ${ac_cv_build+:} false; then : $as_echo_n "(cached) " >&6 else 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 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 $as_echo "$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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 $as_echo_n "checking host system type... " >&6; } if ${ac_cv_host+:} false; then : $as_echo_n "(cached) " >&6 else 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 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 $as_echo "$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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5 $as_echo_n "checking target system type... " >&6; } if ${ac_cv_target+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$target_alias" = x; then ac_cv_target=$ac_cv_host else ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5 $as_echo "$ac_cv_target" >&6; } case $ac_cv_target in *-*-*) ;; *) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;; esac target=$ac_cv_target ac_save_IFS=$IFS; IFS='-' set x $ac_cv_target shift target_cpu=$1 target_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: target_os=$* IFS=$ac_save_IFS case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac # The aliases save the names the user supplied, while $host etc. # will get canonicalized. test -n "$target_alias" && test "$program_prefix$program_suffix$program_transform_name" = \ NONENONEs,x,x, && program_prefix=${target_alias}- case $target_os in freebsd* | netbsd*) LDFLAGS="$LDFLAGS -L/usr/local/lib" CPPFLAGS="$CPPFLAGS -I/usr/local/include" ;; esac am__api_version='1.14' # 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. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. 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 fi if test "${ac_cv_path_install+set}" = set; 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 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 $as_echo "$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' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 $as_echo_n "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). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file 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 if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # 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_fn_error $? "ls -t appears to fail. Make sure there is not a broken alias in your environment" "$LINENO" 5 fi if test "$2" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$2" = conftest.file ) then # Ok. : else as_fn_error $? "newly created file is older than distributed files! Check your system clock" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # 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 grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! 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=`$as_echo "$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 case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 $as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} fi if test x"${install_sh}" != 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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else 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 test -z "$as_dir" && as_dir=. 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" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else 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 test -z "$as_dir" && as_dir=. 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" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$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" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 $as_echo_n "checking for a thread-safe mkdir -p... " >&6; } if test -z "$MKDIR_P"; then if ${ac_cv_path_mkdir+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. 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 (GNU coreutils) '* | \ 'mkdir (coreutils) '* | \ '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 fi test -d ./--version && rmdir ./--version if test "${ac_cv_path_mkdir+set}" = set; then MKDIR_P="$ac_cv_path_mkdir -p" else # As a last resort, use the slow shell script. Don't cache a # value for MKDIR_P 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. MKDIR_P="$ac_install_sh -d" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 $as_echo "$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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else 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 test -z "$as_dir" && as_dir=. 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" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else 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 fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "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 # Check whether --enable-silent-rules was given. if test "${enable_silent_rules+set}" = set; then : enableval=$enable_silent_rules; fi case $enable_silent_rules in # ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=1;; esac am_make=${MAKE-make} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 $as_echo_n "checking whether $am_make supports nested variables... " >&6; } if ${am_cv_make_support_nested_variables+:} false; then : $as_echo_n "(cached) " >&6 else 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 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 $as_echo "$am_cv_make_support_nested_variables" >&6; } 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 AM_BACKSLASH='\' 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='libisofs' VERSION='1.4.2' cat >>confdefs.h <<_ACEOF #define PACKAGE "$PACKAGE" _ACEOF cat >>confdefs.h <<_ACEOF #define VERSION "$VERSION" _ACEOF # 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. 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 -' # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 fi fi LIBISOFS_MAJOR_VERSION=1 LIBISOFS_MINOR_VERSION=4 LIBISOFS_MICRO_VERSION=2 LIBISOFS_VERSION=$LIBISOFS_MAJOR_VERSION.$LIBISOFS_MINOR_VERSION.$LIBISOFS_MICRO_VERSION LT_RELEASE=$LIBISOFS_MAJOR_VERSION.$LIBISOFS_MINOR_VERSION # 2015.11.28 development jump has not yet happened # SONAME = 84 - 78 = 6 . Library name = libisofs.6.78.0 LT_CURRENT=84 LT_AGE=78 LT_REVISION=0 LT_CURRENT_MINUS_AGE=`expr $LT_CURRENT - $LT_AGE` test "$prefix" = "NONE" && prefix=$ac_default_prefix { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5 $as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } # Check whether --enable-maintainer-mode was given. if test "${enable_maintainer_mode+set}" = set; then : enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval else USE_MAINTAINER_MODE=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5 $as_echo "$USE_MAINTAINER_MODE" >&6; } if test $USE_MAINTAINER_MODE = yes; then MAINTAINER_MODE_TRUE= MAINTAINER_MODE_FALSE='#' else MAINTAINER_MODE_TRUE='#' MAINTAINER_MODE_FALSE= fi MAINT=$MAINTAINER_MODE_TRUE DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 $as_echo_n "checking for style of include used by $am_make... " >&6; } am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 $as_echo "$_am_result" >&6; } rm -f confinc confmf # Check whether --enable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; 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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else 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 test -z "$as_dir" && as_dir=. 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" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else 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 test -z "$as_dir" && as_dir=. 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" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else 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 test -z "$as_dir" && as_dir=. 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" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else 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 test -z "$as_dir" && as_dir=. 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" $as_echo "$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 fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else 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 test -z "$as_dir" && as_dir=. 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" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else 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 test -z "$as_dir" && as_dir=. 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" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "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:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$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. $as_echo "$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\"" $as_echo "$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 $as_echo "$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 () { ; 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. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$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\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$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+set}" = set && 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 ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$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 { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "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\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$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 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$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; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$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 () { FILE *f = fopen ("conftest.out", "w"); 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. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "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\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$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\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$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 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; 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\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$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 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$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; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else 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 () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; 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.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; 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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) 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; } /* 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 don't provoke an error unfortunately, instead are silently treated as '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's necessary to write '\x00'==0 to get something that's 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 **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _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 test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : 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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 $as_echo_n "checking whether $CC understands -c and -o together... " >&6; } if ${am_cv_prog_cc_c_o+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; 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 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 $as_echo "$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= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CC_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else 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 thusly: # 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 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 $as_echo_n "checking for an ANSI C-conforming const... " >&6; } if ${ac_cv_c_const+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __cplusplus /* Ultrix mips cc rejects this sort of thing. */ typedef int charset[2]; const charset cs = { 0, 0 }; /* SunOS 4.1.1 cc rejects this. */ char const *const *pcpcc; char **ppc; /* NEC SVR4.0.2 mips cc rejects this. */ struct point {int x, y;}; static struct point const zero = {0,0}; /* AIX XL C 1.02.0.0 rejects this. It does not let you subtract one const X* pointer from another in an arm of an if-expression whose if-part is not a constant expression */ const char *g = "string"; pcpcc = &g + (g ? g-g : 0); /* HPUX 7.0 cc rejects these. */ ++pcpcc; ppc = (char**) pcpcc; pcpcc = (char const *const *) ppc; { /* SCO 3.2v4 cc rejects this sort of thing. */ char tx; char *t = &tx; char const *s = 0 ? (char *) 0 : (char const *) 0; *t++ = 0; if (s) return 0; } { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ int x[] = {25, 17}; const int *foo = &x[0]; ++foo; } { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ typedef const int *iptr; iptr p = 0; ++p; } { /* AIX XL C 1.02.0.0 rejects this sort of thing, saying "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ struct s { int j; const int *ap[3]; } bx; struct s *b = &bx; b->j = 5; } { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ const int foo = 10; if (!foo) return 0; } return !cs[0] && !zero.x; #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_const=yes else ac_cv_c_const=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 $as_echo "$ac_cv_c_const" >&6; } if test $ac_cv_c_const = no; then $as_echo "#define const /**/" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 $as_echo_n "checking for inline... " >&6; } if ${ac_cv_c_inline+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __cplusplus typedef int foo_t; static $ac_kw foo_t static_foo () {return 0; } $ac_kw foo_t foo () {return 0; } #endif _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_inline=$ac_kw fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext test "$ac_cv_c_inline" != no && break done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 $as_echo "$ac_cv_c_inline" >&6; } case $ac_cv_c_inline in inline | yes) ;; *) case $ac_cv_c_inline in no) ac_val=;; *) ac_val=$ac_cv_c_inline;; esac cat >>confdefs.h <<_ACEOF #ifndef __cplusplus #define inline $ac_val #endif _ACEOF ;; esac 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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "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 ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-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. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # 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. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue 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 # Passes both tests. ac_preproc_ok=: break 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 fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$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. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # 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. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue 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 # Passes both tests. ac_preproc_ok=: break 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 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else 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 test -z "$as_dir" && as_dir=. 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 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo '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 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else 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 test -z "$as_dir" && as_dir=. 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 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo '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 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 $as_echo_n "checking whether byte ordering is bigendian... " >&6; } if ${ac_cv_c_bigendian+:} false; then : $as_echo_n "(cached) " >&6 else 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.$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 () { #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 () { #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 ac_cv_c_bigendian=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext 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 () { #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 () { #ifndef _BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_bigendian=yes else ac_cv_c_bigendian=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext 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. */ short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; int use_ascii (int i) { return ascii_mm[i] + ascii_ii[i]; } short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; int use_ebcdic (int i) { return ebcdic_mm[i] + ebcdic_ii[i]; } extern int foo; int main () { return use_ascii (foo) == use_ebcdic (foo); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then ac_cv_c_bigendian=yes fi if grep LiTTleEnDian conftest.$ac_objext >/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.$ac_ext else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { /* 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 ac_cv_c_bigendian=yes fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 $as_echo "$ac_cv_c_bigendian" >&6; } case $ac_cv_c_bigendian in #( yes) $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h ;; #( no) ;; #( universal) $as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h ;; #( *) as_fn_error $? "unknown endianness presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; esac # Check whether --enable-largefile was given. if test "${enable_largefile+set}" = set; then : enableval=$enable_largefile; fi if test "$enable_largefile" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5 $as_echo_n "checking for special C compiler options needed for large files... " >&6; } if ${ac_cv_sys_largefile_CC+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_sys_largefile_CC=no if test "$GCC" != yes; then ac_save_CC=$CC while :; do # IRIX 6.2 and later do not support large files by default, # so use the C compiler's -n32 option if that helps. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : break fi rm -f core conftest.err conftest.$ac_objext CC="$CC -n32" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_largefile_CC=' -n32'; break fi rm -f core conftest.err conftest.$ac_objext break done CC=$ac_save_CC rm -f conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5 $as_echo "$ac_cv_sys_largefile_CC" >&6; } if test "$ac_cv_sys_largefile_CC" != no; then CC=$CC$ac_cv_sys_largefile_CC fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5 $as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; } if ${ac_cv_sys_file_offset_bits+:} false; then : $as_echo_n "(cached) " >&6 else while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_file_offset_bits=no; break fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _FILE_OFFSET_BITS 64 #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_file_offset_bits=64; break fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_sys_file_offset_bits=unknown break done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5 $as_echo "$ac_cv_sys_file_offset_bits" >&6; } case $ac_cv_sys_file_offset_bits in #( no | unknown) ;; *) cat >>confdefs.h <<_ACEOF #define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits _ACEOF ;; esac rm -rf conftest* if test $ac_cv_sys_file_offset_bits = unknown; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5 $as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; } if ${ac_cv_sys_large_files+:} false; then : $as_echo_n "(cached) " >&6 else while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_large_files=no; break fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _LARGE_FILES 1 #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_large_files=1; break fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_sys_large_files=unknown break done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5 $as_echo "$ac_cv_sys_large_files" >&6; } case $ac_cv_sys_large_files in #( no | unknown) ;; *) cat >>confdefs.h <<_ACEOF #define _LARGE_FILES $ac_cv_sys_large_files _ACEOF ;; esac rm -rf conftest* fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGEFILE_SOURCE value needed for large files" >&5 $as_echo_n "checking for _LARGEFILE_SOURCE value needed for large files... " >&6; } if ${ac_cv_sys_largefile_source+:} false; then : $as_echo_n "(cached) " >&6 else while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include /* for off_t */ #include int main () { int (*fp) (FILE *, off_t, int) = fseeko; return fseeko (stdin, 0, 0) && fp (stdin, 0, 0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_sys_largefile_source=no; break fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _LARGEFILE_SOURCE 1 #include /* for off_t */ #include int main () { int (*fp) (FILE *, off_t, int) = fseeko; return fseeko (stdin, 0, 0) && fp (stdin, 0, 0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_sys_largefile_source=1; break fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ac_cv_sys_largefile_source=unknown break done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_source" >&5 $as_echo "$ac_cv_sys_largefile_source" >&6; } case $ac_cv_sys_largefile_source in #( no | unknown) ;; *) cat >>confdefs.h <<_ACEOF #define _LARGEFILE_SOURCE $ac_cv_sys_largefile_source _ACEOF ;; esac rm -rf conftest* # We used to try defining _XOPEN_SOURCE=500 too, to work around a bug # in glibc 2.1.3, but that breaks too many other things. # If you want fseeko and ftello with glibc, upgrade to a fixed glibc. if test $ac_cv_sys_largefile_source != unknown; then $as_echo "#define HAVE_FSEEKO 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "fseeko" "ac_cv_func_fseeko" if test "x$ac_cv_func_fseeko" = xyes; then : fi if test ! $ac_cv_func_fseeko; then as_fn_error $? "Libisofs requires largefile support." "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for iconv() in separate -liconv " >&5 $as_echo_n "checking for iconv() in separate -liconv ... " >&6; } libburnia_liconv="no" libburnia_save_LIBS="$LIBS" LIBS="$LIBS -liconv" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { iconv_t cd = iconv_open("",""); iconv(cd,NULL,NULL,NULL,NULL); iconv_close(cd); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : libburnia_liconv="yes" else LIBS="$libburnia_save_LIBS" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libburnia_liconv" >&5 $as_echo "$libburnia_liconv" >&6; } if test x"$libburnia_save_LIBS" = x"$LIBS" then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libiconv in -liconv" >&5 $as_echo_n "checking for libiconv in -liconv... " >&6; } if ${ac_cv_lib_iconv_libiconv+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-liconv $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. */ #ifdef __cplusplus extern "C" #endif char libiconv (); int main () { return libiconv (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_iconv_libiconv=yes else ac_cv_lib_iconv_libiconv=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_iconv_libiconv" >&5 $as_echo "$ac_cv_lib_iconv_libiconv" >&6; } if test "x$ac_cv_lib_iconv_libiconv" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBICONV 1 _ACEOF LIBS="-liconv $LIBS" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for const qualifier with iconv() " >&5 $as_echo_n "checking for const qualifier with iconv() ... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft); int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : libburnia_iconv_const="" else libburnia_iconv_const="const" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext cat >>confdefs.h <<_ACEOF #define ICONV_CONST $libburnia_iconv_const _ACEOF test -z "$libburnia_iconv_const" && libburnia_iconv_const="no" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libburnia_iconv_const" >&5 $as_echo "$libburnia_iconv_const" >&6; } if test x$LIBISOFS_ASSUME_ICONV = x then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for iconv() to be accessible now " >&5 $as_echo_n "checking for iconv() to be accessible now ... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include #include #include #include #include #include #include int main () { iconv_t cd = iconv_open("",""); iconv(cd,NULL,NULL,NULL,NULL); iconv_close(cd); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : iconv_test="yes" else iconv_test="no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $iconv_test" >&5 $as_echo "$iconv_test" >&6; } if test x$iconv_test = xno then echo >&2 echo "Cannot get function iconv() to work. Configuration aborted." >&2 echo "Check whether your system needs a separate libiconv installed." >&2 echo "If it is installed but not found, try something like" >&2 echo ' export LDFLAGS="$LDFLAGS -L/usr/local/lib"' >&2 echo ' export CPPFLAGS="$CPPFLAGS -I/usr/local/include"' >&2 echo ' export LIBS="$LIBS -liconv"' >&2 echo "You may override this test by exporting variable" >&2 echo " LIBISOFS_ASSUME_ICONV=yes" >&2 echo >&2 (exit 1); exit 1; fi fi case `pwd` in *\ * | *\ *) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 $as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; esac macro_version='2.4.2' macro_revision='1.3337' ltmain="$ac_aux_dir/ltmain.sh" # 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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 $as_echo_n "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*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 $as_echo "printf" >&6; } ;; print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 $as_echo "print -r" >&6; } ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 $as_echo "cat" >&6; } ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 $as_echo_n "checking for a sed that does not truncate output... " >&6; } if ${ac_cv_path_SED+:} false; then : $as_echo_n "(cached) " >&6 else 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 test -z "$as_dir" && as_dir=. 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 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo '' >> "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 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 $as_echo "$ac_cv_path_SED" >&6; } SED="$ac_cv_path_SED" rm -f conftest.sed test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 $as_echo_n "checking for fgrep... " >&6; } if ${ac_cv_path_FGREP+:} false; then : $as_echo_n "(cached) " >&6 else 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 test -z "$as_dir" && as_dir=. 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 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo '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 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 $as_echo "$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+set}" = set; then : withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 $as_echo_n "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 "$with_gnu_ld" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 $as_echo_n "checking for non-GNU ld... " >&6; } fi if ${lt_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else 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 $as_echo "$LD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if ${lt_cv_prog_gnu_ld+:} false; then : $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 $as_echo "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 $as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } if ${lt_cv_path_NM+:} false; then : $as_echo_n "(cached) " >&6 else 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 case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) 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 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 $as_echo "$lt_cv_path_NM" >&6; } if test "$lt_cv_path_NM" != "no"; 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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else 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 test -z "$as_dir" && as_dir=. 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" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DUMPBIN=$ac_cv_prog_DUMPBIN if test -n "$DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 $as_echo "$DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else 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 test -z "$as_dir" && as_dir=. 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" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN if test -n "$ac_ct_DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 $as_echo "$ac_ct_DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "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:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$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 /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols" ;; *) DUMPBIN=: ;; esac fi if test "$DUMPBIN" != ":"; then NM="$DUMPBIN" fi fi test -z "$NM" && NM=nm { $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 $as_echo_n "checking the name lister ($NM) interface... " >&6; } if ${lt_cv_nm_interface+:} false; then : $as_echo_n "(cached) " >&6 else 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* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 $as_echo "$lt_cv_nm_interface" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 $as_echo_n "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 $as_echo "no, using $LN_S" >&6; } fi # find the maximum length of command line arguments { $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 $as_echo_n "checking the maximum length of command line arguments... " >&6; } if ${lt_cv_sys_max_cmd_len+:} false; then : $as_echo_n "(cached) " >&6 else 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; ;; netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) # 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 $i != 17 # 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 fi if test -n $lt_cv_sys_max_cmd_len ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 $as_echo "$lt_cv_sys_max_cmd_len" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 $as_echo "none" >&6; } fi max_cmd_len=$lt_cv_sys_max_cmd_len : ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5 $as_echo_n "checking whether the shell understands some XSI constructs... " >&6; } # Try some XSI features xsi_shell=no ( _lt_dummy="a/b/c" test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ = c,a/b,b/c, \ && eval 'test $(( 1 + 1 )) -eq 2 \ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ && xsi_shell=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5 $as_echo "$xsi_shell" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5 $as_echo_n "checking whether the shell understands \"+=\"... " >&6; } lt_shell_append=no ( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \ >/dev/null 2>&1 \ && lt_shell_append=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5 $as_echo "$lt_shell_append" >&6; } 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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 $as_echo_n "checking how to convert $build file names to $host format... " >&6; } if ${lt_cv_to_host_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else 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 fi to_host_file_cmd=$lt_cv_to_host_file_cmd { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 $as_echo "$lt_cv_to_host_file_cmd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 $as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } if ${lt_cv_to_tool_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else #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 fi to_tool_file_cmd=$lt_cv_to_tool_file_cmd { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 $as_echo "$lt_cv_to_tool_file_cmd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 $as_echo_n "checking for $LD option to reload object files... " >&6; } if ${lt_cv_ld_reload_flag+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_reload_flag='-r' fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 $as_echo "$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 "$GCC" != yes; then reload_cmds=false fi ;; darwin*) if test "$GCC" = yes; 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}objdump", so it can be a program name with args. set dummy ${ac_tool_prefix}objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else 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 test -z "$as_dir" && as_dir=. 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" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OBJDUMP=$ac_cv_prog_OBJDUMP if test -n "$OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 $as_echo "$OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else 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 test -z "$as_dir" && as_dir=. 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" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP if test -n "$ac_ct_OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 $as_echo "$ac_ct_OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OBJDUMP" = x; then OBJDUMP="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 $as_echo_n "checking how to recognize dependent libraries... " >&6; } if ${lt_cv_deplibs_check_method+:} false; then : $as_echo_n "(cached) " >&6 else 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 # which 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='/usr/bin/file -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. # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin. if ( test "$lt_cv_nm_interface" = "BSD nm" && 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*) 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=/usr/bin/file 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=/usr/bin/file 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* | netbsdelf*-gnu) 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=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; 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 ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 $as_echo "$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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else 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 test -z "$as_dir" && as_dir=. 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" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DLLTOOL=$ac_cv_prog_DLLTOOL if test -n "$DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 $as_echo "$DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else 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 test -z "$as_dir" && as_dir=. 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" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL if test -n "$ac_ct_DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 $as_echo "$ac_ct_DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DLLTOOL" = x; then DLLTOOL="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 $as_echo_n "checking how to associate runtime and link libraries... " >&6; } if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : $as_echo_n "(cached) " >&6 else 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 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 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 $as_echo "$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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AR+:} false; then : $as_echo_n "(cached) " >&6 else 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 test -z "$as_dir" && as_dir=. 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" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_AR+:} false; then : $as_echo_n "(cached) " >&6 else 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 test -z "$as_dir" && as_dir=. 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" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 $as_echo "$ac_ct_AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "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:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$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} : ${AR_FLAGS=cru} { $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 $as_echo_n "checking for archiver @FILE support... " >&6; } if ${lt_cv_ar_at_file+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ar_at_file=no cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; 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=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test "$ac_status" -eq 0; 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=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test "$ac_status" -ne 0; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 $as_echo "$lt_cv_ar_at_file" >&6; } if test "x$lt_cv_ar_at_file" = xno; 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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else 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 test -z "$as_dir" && as_dir=. 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" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else 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 test -z "$as_dir" && as_dir=. 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" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else 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 test -z "$as_dir" && as_dir=. 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" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else 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 test -z "$as_dir" && as_dir=. 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" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$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 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. { $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 $as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } if ${lt_cv_sys_global_symbol_pipe+:} false; then : $as_echo_n "(cached) " >&6 else # 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 "$host_cpu" = ia64; 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 # 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 -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$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 -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'" lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/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 # and D for any global variable. # Also find C++ and __fastcall symbols from MSVC++, # 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};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ " {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ " s[1]~/^[@?]/{print s[1], s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print 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=$? $as_echo "$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=$? $as_echo "$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 con'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* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$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=$? $as_echo "$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 "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done 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 { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 $as_echo "failed" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 $as_echo_n "checking for sysroot... " >&6; } # Check whether --with-sysroot was given. if test "${with_sysroot+set}" = set; then : withval=$with_sysroot; else with_sysroot=no fi lt_sysroot= case ${with_sysroot} in #( yes) if test "$GCC" = yes; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${with_sysroot}" >&5 $as_echo "${with_sysroot}" >&6; } as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 $as_echo "${lt_sysroot:-no}" >&6; } # Check whether --enable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then : enableval=$enable_libtool_lock; fi test "x$enable_libtool_lock" != xno && 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 which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE="32" ;; *ELF-64*) HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. 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=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file 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* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) case `/usr/bin/file conftest.o` in *x86-64*) LD="${LD-ld} -m elf32_x86_64" ;; *) LD="${LD-ld} -m elf_i386" ;; esac ;; powerpc64le-*) LD="${LD-ld} -m elf32lppclinux" ;; powerpc64-*) 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-*) LD="${LD-ld} -m elf64lppc" ;; powerpc-*) 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" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 $as_echo_n "checking whether the C compiler needs -belf... " >&6; } if ${lt_cv_cc_needs_belf+:} false; then : $as_echo_n "(cached) " >&6 else 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 () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_cc_needs_belf=yes else lt_cv_cc_needs_belf=no fi rm -f core conftest.err conftest.$ac_objext \ 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 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 $as_echo "$lt_cv_cc_needs_belf" >&6; } if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; *-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else 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 test -z "$as_dir" && as_dir=. 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" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL if test -n "$MANIFEST_TOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 $as_echo "$MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else 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 test -z "$as_dir" && as_dir=. 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" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL if test -n "$ac_ct_MANIFEST_TOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 $as_echo "$ac_ct_MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_MANIFEST_TOOL" = x; then MANIFEST_TOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 $as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } if ${lt_cv_path_mainfest_tool+:} false; then : $as_echo_n "(cached) " >&6 else 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* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 $as_echo "$lt_cv_path_mainfest_tool" >&6; } if test "x$lt_cv_path_mainfest_tool" != xyes; 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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else 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 test -z "$as_dir" && as_dir=. 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" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DSYMUTIL=$ac_cv_prog_DSYMUTIL if test -n "$DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 $as_echo "$DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else 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 test -z "$as_dir" && as_dir=. 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" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL if test -n "$ac_ct_DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 $as_echo "$ac_ct_DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DSYMUTIL" = x; then DSYMUTIL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else 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 test -z "$as_dir" && as_dir=. 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" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi NMEDIT=$ac_cv_prog_NMEDIT if test -n "$NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 $as_echo "$NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else 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 test -z "$as_dir" && as_dir=. 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" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT if test -n "$ac_ct_NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 $as_echo "$ac_ct_NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_NMEDIT" = x; then NMEDIT=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else 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 test -z "$as_dir" && as_dir=. 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" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi LIPO=$ac_cv_prog_LIPO if test -n "$LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 $as_echo "$LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else 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 test -z "$as_dir" && as_dir=. 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" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO if test -n "$ac_ct_LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 $as_echo "$ac_ct_LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_LIPO" = x; then LIPO=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else 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 test -z "$as_dir" && as_dir=. 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" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL=$ac_cv_prog_OTOOL if test -n "$OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 $as_echo "$OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else 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 test -z "$as_dir" && as_dir=. 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" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL if test -n "$ac_ct_OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 $as_echo "$ac_ct_OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL" = x; then OTOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else 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 test -z "$as_dir" && as_dir=. 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" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL64=$ac_cv_prog_OTOOL64 if test -n "$OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 $as_echo "$OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else 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 test -z "$as_dir" && as_dir=. 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" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 if test -n "$ac_ct_OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 $as_echo "$ac_ct_OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL64" = x; then OTOOL64=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 $as_echo_n "checking for -single_module linker flag... " >&6; } if ${lt_cv_apple_cc_single_mod+:} false; then : $as_echo_n "(cached) " >&6 else 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 $_lt_result -eq 0; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&5 fi rm -rf libconftest.dylib* rm -f conftest.* fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 $as_echo "$lt_cv_apple_cc_single_mod" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 $as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } if ${lt_cv_ld_exported_symbols_list+:} false; then : $as_echo_n "(cached) " >&6 else 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 () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_ld_exported_symbols_list=yes else lt_cv_ld_exported_symbols_list=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 $as_echo "$lt_cv_ld_exported_symbols_list" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 $as_echo_n "checking for -force_load linker flag... " >&6; } if ${lt_cv_ld_force_load+:} false; then : $as_echo_n "(cached) " >&6 else 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 cru libconftest.a conftest.o" >&5 $AR cru 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 $_lt_result -eq 0 && $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 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 $as_echo "$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*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[91]*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; 10.[012]*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test "$lt_cv_apple_cc_single_mod" = "yes"; then _lt_dar_single_mod='$single_module' fi if test "$lt_cv_ld_exported_symbols_list" = "yes"; 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 "$lt_cv_ld_force_load" = "no"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac for ac_header in dlfcn.h do : 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 : cat >>confdefs.h <<_ACEOF #define HAVE_DLFCN_H 1 _ACEOF fi done # Set options enable_dlopen=no enable_win32_dll=no # Check whether --enable-shared was given. if test "${enable_shared+set}" = set; 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 enable_shared=yes fi # Check whether --enable-static was given. if test "${enable_static+set}" = set; 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 enable_static=yes fi # Check whether --with-pic was given. if test "${with_pic+set}" = set; 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 pic_mode=default fi test -z "$pic_mode" && pic_mode=default # Check whether --enable-fast-install was given. if test "${enable_fast_install+set}" = set; 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 enable_fast_install=yes fi # 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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 $as_echo_n "checking for objdir... " >&6; } if ${lt_cv_objdir+:} false; then : $as_echo_n "(cached) " >&6 else 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 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 $as_echo "$lt_cv_objdir" >&6; } objdir=$lt_cv_objdir cat >>confdefs.h <<_ACEOF #define LT_OBJDIR "$lt_cv_objdir/" _ACEOF 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 "X${COLLECT_NAMES+set}" != Xset; 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, # which needs '.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 for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` # 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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 $as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else 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 fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 $as_echo_n "checking for file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else 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 fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "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 "$GCC" = yes; then case $cc_basename in nvcc*) lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; *) lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 $as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : $as_echo_n "(cached) " >&6 else 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" # 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* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 $as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; 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 "$GCC" = yes; then lt_prog_compiler_wl='-Wl,' lt_prog_compiler_static='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' fi ;; 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' ;; 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 "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' else lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' fi ;; 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' ;; 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' ;; 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 which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic= ;; *) lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } if ${lt_cv_prog_compiler_pic+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic=$lt_prog_compiler_pic fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 $as_echo "$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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } if ${lt_cv_prog_compiler_pic_works+:} false; then : $as_echo_n "(cached) " >&6 else 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" # 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* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 $as_echo "$lt_cv_prog_compiler_pic_works" >&6; } if test x"$lt_cv_prog_compiler_pic_works" = xyes; 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\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if ${lt_cv_prog_compiler_static_works+:} false; then : $as_echo_n "(cached) " >&6 else 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" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 $as_echo "$lt_cv_prog_compiler_static_works" >&6; } if test x"$lt_cv_prog_compiler_static_works" = xyes; then : else lt_prog_compiler_static= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else 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* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else 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* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } hard_links="nottested" if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "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 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test "$hard_links" = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 $as_echo "$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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "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++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; linux* | k*bsd*-gnu | gnu*) link_all_deplibs=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 "$with_gnu_ld" = yes; 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 "$lt_use_gnu_ld_interface" = yes; 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 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 "$host_cpu" != ia64; 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 (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; 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 ;; 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 "$host_os" = linux-dietlibc; 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 "$tmp_diet" = no 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' ;; 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 "x$supports_anon_versioning" = xyes; 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 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 "x$supports_anon_versioning" = xyes; 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* | netbsdelf*-gnu) 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 can not *** 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 "$ld_shlibs" = no; 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 "$GCC" = yes && 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 "$host_cpu" = ia64; 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 AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global # defined symbols, whereas GNU nm marks them as "W". 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) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | 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 # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; 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,' if test "$GCC" = yes; 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 "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi link_all_deplibs=no else # not using gcc if test "$host_cpu" = ia64; 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 "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi 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_use_runtimelinking" = yes; 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 "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; 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$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_="/usr/lib:/lib" fi 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 "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; 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 "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; 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$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_="/usr/lib:/lib" fi 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 "$with_gnu_ld" = yes; 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 # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' 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++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC 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~linknames=' archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $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 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 "$lt_cv_ld_force_load" = "yes"; 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*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test "$_lt_dar_can_shared" = "yes"; 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*) 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 "$GCC" = yes; 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 $output_objdir/$soname = $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 $output_objdir/$soname = $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 "$GCC" = yes && test "$with_gnu_ld" = no; 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 "$with_gnu_ld" = no; 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 "$GCC" = yes && test "$with_gnu_ld" = no; 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) { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 $as_echo_n "checking if $CC understands -b... " >&6; } if ${lt_cv_prog_compiler__b+:} false; then : $as_echo_n "(cached) " >&6 else 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" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 $as_echo "$lt_cv_prog_compiler__b" >&6; } if test x"$lt_cv_prog_compiler__b" = xyes; 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 "$with_gnu_ld" = no; 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 "$GCC" = yes; 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. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 $as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } if ${lt_cv_irix_exported_symbol+:} false; then : $as_echo_n "(cached) " >&6 else 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 lt_cv_irix_exported_symbol=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 $as_echo "$lt_cv_irix_exported_symbol" >&6; } if test "$lt_cv_irix_exported_symbol" = yes; 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 ;; netbsd* | netbsdelf*-gnu) 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*) 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__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; 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 case $host_os in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-R$libdir' ;; *) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; esac fi else ld_shlibs=no fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; 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 "$GCC" = yes; 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 "$GCC" = yes; 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 "$GCC" = yes; 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 "x$host_vendor" = xsequent; 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 "$GCC" = yes; 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 can NOT 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 "$GCC" = yes; 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 x$host_vendor = xsni; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) export_dynamic_flag_spec='${wl}-Blargedynsym' ;; esac fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 $as_echo "$ld_shlibs" >&6; } test "$ld_shlibs" = no && 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 "$enable_shared" = yes && test "$GCC" = yes; 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. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } if ${lt_cv_archive_cmds_need_lc+:} false; then : $as_echo_n "(cached) " >&6 else $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=$? $as_echo "$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=$? $as_echo "$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* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 $as_echo "$lt_cv_archive_cmds_need_lc" >&6; } archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc ;; esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } if test "$GCC" = yes; 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` 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" else 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 "$host_cpu" = ia64; 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 # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # 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}' else # 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' fi 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%'\''`; test $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*) # Native MSVC 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 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*) # 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} $libname${shared_ext}' 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=yes 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 "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; 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 "$lt_cv_prog_gnu_ld" = yes; 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 ;; # 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 ${lt_cv_shlibpath_overrides_runpath+:} false; then : $as_echo_n "(cached) " >&6 else 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 () { ; 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$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS libdir=$save_libdir 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 # Append ld.so.conf contents 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' ;; netbsdelf*-gnu) version_type=linux 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='NetBSD ld.elf_so' ;; netbsd*) # ts B51007 : changed version_type for lt_main.sh from "sunos" to "netbsd" version_type=netbsd 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*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac 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 if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; 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 "$with_gnu_ld" = yes; 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=freebsd-elf 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 "$with_gnu_ld" = yes; 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 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action= if test -n "$hardcode_libdir_flag_spec" || test -n "$runpath_var" || test "X$hardcode_automatic" = "Xyes" ; then # We can hardcode non-existent directories. if test "$hardcode_direct" != no && # 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 "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no && test "$hardcode_minus_L" != no; 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 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 $as_echo "$hardcode_action" >&6; } if test "$hardcode_action" = relink || test "$inherit_rpath" = yes; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi if test "x$enable_dlopen" != xyes; 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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else 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. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$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 lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes fi ;; *) 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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } if ${ac_cv_lib_dld_shl_load+:} false; then : $as_echo_n "(cached) " >&6 else 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. */ #ifdef __cplusplus extern "C" #endif char shl_load (); int main () { return shl_load (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_shl_load=yes else ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$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 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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else 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. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 $as_echo_n "checking for dlopen in -lsvld... " >&6; } if ${ac_cv_lib_svld_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else 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. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_svld_dlopen=yes else ac_cv_lib_svld_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 $as_echo "$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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 $as_echo_n "checking for dld_link in -ldld... " >&6; } if ${ac_cv_lib_dld_dld_link+:} false; then : $as_echo_n "(cached) " >&6 else 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. */ #ifdef __cplusplus extern "C" #endif char dld_link (); int main () { return dld_link (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_dld_link=yes else ac_cv_lib_dld_dld_link=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 $as_echo "$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 fi fi fi fi fi ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && 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" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 $as_echo_n "checking whether a program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; 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 -fvisbility=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=$? $as_echo "$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* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 $as_echo "$lt_cv_dlopen_self" >&6; } if test "x$lt_cv_dlopen_self" = xyes; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 $as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self_static+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; 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 -fvisbility=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=$? $as_echo "$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* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 $as_echo "$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= { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 $as_echo_n "checking whether stripping libraries is possible... " >&6; } if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" old_striplib="$STRIP -S" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac fi # Report which library types will actually be built { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 $as_echo_n "checking if libtool supports shared libraries... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 $as_echo "$can_build_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 $as_echo_n "checking whether to build shared libraries... " >&6; } test "$can_build_shared" = "no" && 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 "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[4-9]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 $as_echo "$enable_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 $as_echo_n "checking whether to build static libraries... " >&6; } # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 $as_echo "$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: LIBTOOL="$LIBTOOL --silent" for ac_header do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done $as_echo "#define _GNU_SOURCE 1" >>confdefs.h ac_fn_c_check_member "$LINENO" "struct tm" "tm_gmtoff" "ac_cv_member_struct_tm_tm_gmtoff" "#include " if test "x$ac_cv_member_struct_tm_tm_gmtoff" = xyes; then : $as_echo "#define HAVE_TM_GMTOFF 1" >>confdefs.h fi ac_fn_c_check_decl "$LINENO" "timegm" "ac_cv_have_decl_timegm" "#include " if test "x$ac_cv_have_decl_timegm" = xyes; then : $as_echo "#define HAVE_TIMEGM 1" >>confdefs.h fi echo -n "checking for timezone variable ... " cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { long int i; i = 1 - timezone; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : LIBBURNIA_TIMEZONE="timezone" else LIBBURNIA_TIMEZONE="0" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext echo "$LIBBURNIA_TIMEZONE" if test x$LIBBURNIA_TIMEZONE = xtimezone then $as_echo "#define Libburnia_timezonE timezone" >>confdefs.h else $as_echo "#define Libburnia_timezonE 0" >>confdefs.h fi ac_fn_c_check_decl "$LINENO" "eaccess" "ac_cv_have_decl_eaccess" "#include " if test "x$ac_cv_have_decl_eaccess" = xyes; then : $as_echo "#define HAVE_EACCESS 1" >>confdefs.h fi THREAD_LIBS=-lpthread ARCH="" LIBBURNIA_PKGCONFDIR="$libdir"/pkgconfig { $as_echo "$as_me:${as_lineno-$LINENO}: checking target operating system" >&5 $as_echo_n "checking target operating system... " >&6; } LIBBURNIA_LDCONFIG_CMD="echo 'No ldconfig run performed. If needed, configure manually for:'" case $target in *-*-linux*) ARCH=linux LIBBURN_ARCH_LIBS= LIBBURNIA_LDCONFIG_CMD=ldconfig ;; *-*-freebsd*) ARCH=freebsd LIBBURN_ARCH_LIBS=-lcam # This may later be overridden by configure --enable-libdir-pkgconfig LIBBURNIA_PKGCONFDIR=$(echo "$libdir" | sed 's/\/lib$/\/libdata/')/pkgconfig ;; *) ARCH= LIBBURN_ARCH_LIBS= # AC_ERROR([You are attempting to compile for an unsupported platform]) ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ARCH" >&5 $as_echo "$ARCH" >&6; } # Check whether --enable-debug was given. if test "${enable_debug+set}" = set; then : enableval=$enable_debug; else enable_debug=yes fi if test x$enable_debug != xyes; then if test x$GCC = xyes; then CFLAGS="-O3 $CFLAGS" CFLAGS="-fexpensive-optimizations $CFLAGS" fi CFLAGS="-DNDEBUG $CFLAGS" else if test x$GCC = xyes; then CFLAGS="-g -pedantic -Wall -Wextra -Wno-unused-parameter -Wno-char-subscripts $CFLAGS" fi CFLAGS="-DDEBUG $CFLAGS" fi # Check whether --enable-verbose-debug was given. if test "${enable_verbose_debug+set}" = set; then : enableval=$enable_verbose_debug; $as_echo "#define LIBISOFS_VERBOSE_DEBUG 1" >>confdefs.h fi ### for testing --enable-libdir-pkgconfig on Linux ### LIBBURNIA_PKGCONFDIR="$libdir"data/pkgconfig if test "x$LIBBURNIA_PKGCONFDIR" = "x$libdir"/pkgconfig then dummy=dummy else # Check whether --enable-libdir-pkgconfig was given. if test "${enable_libdir_pkgconfig+set}" = set; then : enableval=$enable_libdir_pkgconfig; else enable_libdir_pkgconfig="no" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for --enable-libdir-pkgconfig" >&5 $as_echo_n "checking for --enable-libdir-pkgconfig... " >&6; } if test "x$enable_libdir_pkgconfig" = xyes then LIBBURNIA_PKGCONFDIR="$libdir"/pkgconfig fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_libdir_pkgconfig" >&5 $as_echo "$enable_libdir_pkgconfig" >&6; } fi libburnia_pkgconfig_override="no" # Check whether --enable-pkgconfig-path was given. if test "${enable_pkgconfig_path+set}" = set; then : enableval=$enable_pkgconfig_path; libburnia_pkgconfig_override="yes" else enable_pkgconfig_path="none" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for overridden pkgconfig directory path" >&5 $as_echo_n "checking for overridden pkgconfig directory path... " >&6; } if test "x$enable_pkgconfig_path" = xno then libburnia_pkgconfig_override="no" fi if test "x$enable_pkgconfig_path" = x -o "x$enable_pkgconfig_path" = xyes then libburnia_pkgconfig_override="invalid argument" fi if test "x$libburnia_pkgconfig_override" = xyes then LIBBURNIA_PKGCONFDIR="$enable_pkgconfig_path" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBBURNIA_PKGCONFDIR" >&5 $as_echo "$LIBBURNIA_PKGCONFDIR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libburnia_pkgconfig_override" >&5 $as_echo "$libburnia_pkgconfig_override" >&6; } fi ### AC_MSG_RESULT([LIBBURNIA_PKGCONFDIR = $LIBBURNIA_PKGCONFDIR]) # Check whether --enable-libacl was given. if test "${enable_libacl+set}" = set; then : enableval=$enable_libacl; else enable_libacl=yes fi if test "x$enable_libacl" = xyes; then LIBACL_DEF="-DLibisofs_with_aaip_acL" has_acl_h_but_no_func=0 ac_fn_c_check_header_mongrel "$LINENO" "sys/acl.h" "ac_cv_header_sys_acl_h" "$ac_includes_default" if test "x$ac_cv_header_sys_acl_h" = xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for acl_to_text in -lacl" >&5 $as_echo_n "checking for acl_to_text in -lacl... " >&6; } if ${ac_cv_lib_acl_acl_to_text+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lacl $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. */ #ifdef __cplusplus extern "C" #endif char acl_to_text (); int main () { return acl_to_text (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_acl_acl_to_text=yes else ac_cv_lib_acl_acl_to_text=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_acl_acl_to_text" >&5 $as_echo "$ac_cv_lib_acl_acl_to_text" >&6; } if test "x$ac_cv_lib_acl_acl_to_text" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBACL 1 _ACEOF LIBS="-lacl $LIBS" else has_acl_h_but_no_libacl=1 fi else LIBACL_DEF= fi if test "$has_acl_h_but_no_libacl" = 1 then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for acl_to_text in -lc" >&5 $as_echo_n "checking for acl_to_text in -lc... " >&6; } if ${ac_cv_lib_c_acl_to_text+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lc $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. */ #ifdef __cplusplus extern "C" #endif char acl_to_text (); int main () { return acl_to_text (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_c_acl_to_text=yes else ac_cv_lib_c_acl_to_text=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_acl_to_text" >&5 $as_echo "$ac_cv_lib_c_acl_to_text" >&6; } if test "x$ac_cv_lib_c_acl_to_text" = xyes; then : X= else LIBACL_DEF= fi fi else LIBACL_DEF= fi # Check whether --enable-xattr was given. if test "${enable_xattr+set}" = set; then : enableval=$enable_xattr; else enable_xattr=yes fi if test "x$enable_xattr" = xyes; then XATTR_DEF="-DLibisofs_with_aaip_xattR" ac_fn_c_check_header_mongrel "$LINENO" "attr/xattr.h" "ac_cv_header_attr_xattr_h" "$ac_includes_default" if test "x$ac_cv_header_attr_xattr_h" = xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for listxattr in -lc" >&5 $as_echo_n "checking for listxattr in -lc... " >&6; } if ${ac_cv_lib_c_listxattr+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lc $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. */ #ifdef __cplusplus extern "C" #endif char listxattr (); int main () { return listxattr (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_c_listxattr=yes else ac_cv_lib_c_listxattr=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_listxattr" >&5 $as_echo "$ac_cv_lib_c_listxattr" >&6; } if test "x$ac_cv_lib_c_listxattr" = xyes; then : X= else XATTR_DEF= fi else XATTR_DEF= fi if test "x$XATTR_DEF" = x then XATTR_DEF="-DLibisofs_with_freebsd_extattR" ac_fn_c_check_header_mongrel "$LINENO" "sys/extattr.h" "ac_cv_header_sys_extattr_h" "$ac_includes_default" if test "x$ac_cv_header_sys_extattr_h" = xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for extattr_list_file in -lc" >&5 $as_echo_n "checking for extattr_list_file in -lc... " >&6; } if ${ac_cv_lib_c_extattr_list_file+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lc $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. */ #ifdef __cplusplus extern "C" #endif char extattr_list_file (); int main () { return extattr_list_file (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_c_extattr_list_file=yes else ac_cv_lib_c_extattr_list_file=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_extattr_list_file" >&5 $as_echo "$ac_cv_lib_c_extattr_list_file" >&6; } if test "x$ac_cv_lib_c_extattr_list_file" = xyes; then : X= else XATTR_DEF= fi else XATTR_DEF= fi fi else XATTR_DEF= fi # Check whether --enable-zlib was given. if test "${enable_zlib+set}" = set; then : enableval=$enable_zlib; else enable_zlib=yes fi if test "x$enable_zlib" = xyes; then ZLIB_DEF="-DLibisofs_with_zliB" ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default" if test "x$ac_cv_header_zlib_h" = xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for compressBound in -lz" >&5 $as_echo_n "checking for compressBound in -lz... " >&6; } if ${ac_cv_lib_z_compressBound+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lz $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. */ #ifdef __cplusplus extern "C" #endif char compressBound (); int main () { return compressBound (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_z_compressBound=yes else ac_cv_lib_z_compressBound=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_compressBound" >&5 $as_echo "$ac_cv_lib_z_compressBound" >&6; } if test "x$ac_cv_lib_z_compressBound" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBZ 1 _ACEOF LIBS="-lz $LIBS" else ZLIB_DEF= fi else ZLIB_DEF= fi else ZLIB_DEF= fi # Check whether --enable-libjte was given. if test "${enable_libjte+set}" = set; then : enableval=$enable_libjte; else enable_libjte=yes fi if test "x$enable_libjte" = xyes; then LIBJTE_DEF="-DLibisofs_with_libjtE" ac_fn_c_check_header_mongrel "$LINENO" "libjte/libjte.h" "ac_cv_header_libjte_libjte_h" "$ac_includes_default" if test "x$ac_cv_header_libjte_libjte_h" = xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libjte_new in -ljte" >&5 $as_echo_n "checking for libjte_new in -ljte... " >&6; } if ${ac_cv_lib_jte_libjte_new+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ljte $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. */ #ifdef __cplusplus extern "C" #endif char libjte_new (); int main () { return libjte_new (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_jte_libjte_new=yes else ac_cv_lib_jte_libjte_new=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_jte_libjte_new" >&5 $as_echo "$ac_cv_lib_jte_libjte_new" >&6; } if test "x$ac_cv_lib_jte_libjte_new" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBJTE 1 _ACEOF LIBS="-ljte $LIBS" else LIBJTE_DEF= fi else LIBJTE_DEF= fi else LIBJTE_DEF= fi # Library versioning normally serves a complex purpose. # Since libisofs obeys strict ABI backward compatibility, it needs only the # simple feature to declare function names "global:" or "local:". Only the # global ones are visible to applications at library load time. # Check whether --enable-versioned-libs was given. if test "${enable_versioned_libs+set}" = set; then : enableval=$enable_versioned_libs; else enable_versioned_libs=yes fi if test x$enable_versioned_libs = xyes; then vers_libs_test=no libburnia_save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -Wl,--version-script=libisofs/libisofs.ver" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { printf("Hello\n"); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : vers_libs_test="yes" else vers_libs_test="no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test x$vers_libs_test = xno then LDFLAGS="$libburnia_save_LDFLAGS" fi if test x$vers_libs_test = xno then echo "disabled strict symbol encapsulation (test failed)" else echo "enabled strict symbol encapsulation" fi else echo "disabled strict symbol encapsulation" fi # Check whether --enable-ldconfig-at-install was given. if test "${enable_ldconfig_at_install+set}" = set; then : enableval=$enable_ldconfig_at_install; else ldconfig_at_install=yes fi if test x$ldconfig_at_install = xyes; then dummy=dummy else LIBBURNIA_LDCONFIG_CMD="echo 'NOTE: ldconfig is disabled. If needed, configure manually for:'" echo "disabled run of ldconfig during installation on GNU/Linux" fi ac_config_files="$ac_config_files Makefile doc/doxygen.conf version.h libisofs-1.pc" 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_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$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+set}" = set || &/ 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 { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$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 { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$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}' # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. ac_script=' :mline /\\$/{ N s,\\\n,, b mline } t clear :clear s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g t quote s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g t quote b any :quote s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g s/\[/\\&/g s/\]/\\&/g s/\$/$$/g H :any ${ g s/^\n// s/\n/ /g p } ' DEFS=`sed -n "$ac_script" confdefs.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=`$as_echo "$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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 $as_echo_n "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 { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 $as_echo "done" >&6; } if test -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' else am__EXEEXT_TRUE='#' am__EXEEXT_FALSE= fi if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 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 : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$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 -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 as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. 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 # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # 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 test -z "$as_dir" && as_dir=. 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 $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # 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 $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$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 as_fn_append () { eval $1=\$$1\$2 } 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 as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } 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 || $as_echo 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 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 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=`$as_echo "$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 || $as_echo 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_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" 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 libisofs $as_me 1.4.2, which was generated by GNU Autoconf 2.69. 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 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" 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 Configuration files: $config_files Configuration commands: $config_commands Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ libisofs config.status 1.4.2 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 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 ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) $as_echo "$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 \$as_echo "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 $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" # 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_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' enable_static='`$ECHO "$enable_static" | $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"`' 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"`' 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"`' 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_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"`' nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' lt_sysroot='`$ECHO "$lt_sysroot" | $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"`' sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $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"`' 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 \ OBJDUMP \ deplibs_check_method \ file_magic_cmd \ file_magic_glob \ want_nocaseglob \ DLLTOOL \ sharedlib_from_linklib_cmd \ AR \ AR_FLAGS \ 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_c_name_address \ lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ nm_file_list_spec \ 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; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ;; *) 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 \ sys_lib_dlsearch_path_spec; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done ac_aux_dir='$ac_aux_dir' xsi_shell='$xsi_shell' lt_shell_append='$lt_shell_append' # See if we are running on zsh, and set the options which 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' TIMESTAMP='$TIMESTAMP' 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 "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "doc/doxygen.conf") CONFIG_FILES="$CONFIG_FILES doc/doxygen.conf" ;; "version.h") CONFIG_FILES="$CONFIG_FILES version.h" ;; "libisofs-1.pc") CONFIG_FILES="$CONFIG_FILES libisofs-1.pc" ;; *) 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+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_COMMANDS+set}" = set || 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" eval set X " :F $CONFIG_FILES :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=`$as_echo "$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 '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$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 || $as_echo 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=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$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@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$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"; } && { $as_echo "$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 $as_echo "$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 ;; :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 $as_echo "$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. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`$as_dirname -- "$mf" || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ X"$mf" : 'X\(//\)$' \| \ X"$mf" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "$am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`$as_dirname -- "$file" || $as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$file" : 'X\(//\)[^/]' \| \ X"$file" : 'X\(//\)$' \| \ X"$file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir=$dirpart/$fdir; as_fn_mkdir_p # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ;; "libtool":C) # See if we are running on zsh, and set the options which 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 # `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $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. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010, 2011 Free Software # Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is part of GNU Libtool. # # 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 GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, or # obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # The names of the tagged configurations supported by this script. available_tags="" # ### BEGIN LIBTOOL CONFIG # Which release of libtool.m4 was used? macro_version=$macro_version macro_revision=$macro_revision # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # What type of objects to build. pic_mode=$pic_mode # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # 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 # 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. AR_FLAGS=$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 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 # 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 in which our libraries should be installed. lt_sysroot=$lt_sysroot # 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 # Run-time system search path for libraries. sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # 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 # ### END LIBTOOL CONFIG _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 "X${COLLECT_NAMES+set}" != Xset; 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) if test x"$xsi_shell" = xyes; then sed -e '/^func_dirname ()$/,/^} # func_dirname /c\ func_dirname ()\ {\ \ case ${1} in\ \ */*) func_dirname_result="${1%/*}${2}" ;;\ \ * ) func_dirname_result="${3}" ;;\ \ esac\ } # Extended-shell func_dirname implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_basename ()$/,/^} # func_basename /c\ func_basename ()\ {\ \ func_basename_result="${1##*/}"\ } # Extended-shell func_basename implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_dirname_and_basename ()$/,/^} # func_dirname_and_basename /c\ func_dirname_and_basename ()\ {\ \ case ${1} in\ \ */*) func_dirname_result="${1%/*}${2}" ;;\ \ * ) func_dirname_result="${3}" ;;\ \ esac\ \ func_basename_result="${1##*/}"\ } # Extended-shell func_dirname_and_basename implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_stripname ()$/,/^} # func_stripname /c\ func_stripname ()\ {\ \ # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are\ \ # positional parameters, so assign one to ordinary parameter first.\ \ func_stripname_result=${3}\ \ func_stripname_result=${func_stripname_result#"${1}"}\ \ func_stripname_result=${func_stripname_result%"${2}"}\ } # Extended-shell func_stripname implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_split_long_opt ()$/,/^} # func_split_long_opt /c\ func_split_long_opt ()\ {\ \ func_split_long_opt_name=${1%%=*}\ \ func_split_long_opt_arg=${1#*=}\ } # Extended-shell func_split_long_opt implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_split_short_opt ()$/,/^} # func_split_short_opt /c\ func_split_short_opt ()\ {\ \ func_split_short_opt_arg=${1#??}\ \ func_split_short_opt_name=${1%"$func_split_short_opt_arg"}\ } # Extended-shell func_split_short_opt implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_lo2o ()$/,/^} # func_lo2o /c\ func_lo2o ()\ {\ \ case ${1} in\ \ *.lo) func_lo2o_result=${1%.lo}.${objext} ;;\ \ *) func_lo2o_result=${1} ;;\ \ esac\ } # Extended-shell func_lo2o implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_xform ()$/,/^} # func_xform /c\ func_xform ()\ {\ func_xform_result=${1%.*}.lo\ } # Extended-shell func_xform implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_arith ()$/,/^} # func_arith /c\ func_arith ()\ {\ func_arith_result=$(( $* ))\ } # Extended-shell func_arith implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_len ()$/,/^} # func_len /c\ func_len ()\ {\ func_len_result=${#1}\ } # Extended-shell func_len implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: fi if test x"$lt_shell_append" = xyes; then sed -e '/^func_append ()$/,/^} # func_append /c\ func_append ()\ {\ eval "${1}+=\\${2}"\ } # Extended-shell func_append implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_append_quoted ()$/,/^} # func_append_quoted /c\ func_append_quoted ()\ {\ \ func_quote_for_eval "${2}"\ \ eval "${1}+=\\\\ \\$func_quote_for_eval_result"\ } # Extended-shell func_append_quoted implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: # Save a `func_append' function call where possible by direct use of '+=' sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: else # Save a `func_append' function call even when '+=' is not available sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: fi if test x"$_lt_function_replace_fail" = x":"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to substitute extended shell functions in $ofile" >&5 $as_echo "$as_me: WARNING: Unable to substitute extended shell functions in $ofile" >&2;} fi mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ;; 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 { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi libisofs-1.4.2/libisofs-1.pc.in0000644000175700017510000000035411112746253013166 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: libisofs Description: ISO9660 filesystem creation library Version: @VERSION@ Requires: Libs: -L${libdir} -lisofs Cflags: -I${includedir}/libisofs libisofs-1.4.2/demo/0000755000175700017510000000000012626306721011272 500000000000000libisofs-1.4.2/demo/demo.c0000644000175700017510000006415612606772750012325 00000000000000 /* * Copyright (c) 2007 - 2015 Vreixo Formoso, Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ static char helptext[][80] = { "", "This is a collection of libisofs gestures which formerly were distinct", "programs. The first argument chooses the gesture:", " -tree absolute_directory_path", " Import a directory and print the resulting iso tree.", " -find absolute_directory_path", " Import a directory, find matching nodes and print the", " resulting iso tree.", " -iso [options] directory output_file", " Create an iso image from a local directory. For options see", " output of -iso -h", " -iso_read image_file", " Output the contents of an iso image.", " -iso_cat image_file path_in_image", " Extract a file from a given ISO image and put out its content", " to stdout. The file is addressed by path_in_image. The ISO", " image does not get loaded but rather the lookups are done", " directly in the image file.", " -iso_modify image_file absolute_directory_path output_file", " Load an iso image, add a directory, and write complete image.", " -iso_ms image_lba nwa image_file directory_path output_file", " Load an iso image, add a directory, and write as add-on", " session which shall be appended to the old image.", " image_lba gives the block address of the start of the most", " recent session in the image_file. nwa gives the block address", " where the add-on session will be appended to the image.", "@" }; #define LIBISOFS_WITHOUT_LIBBURN yes #include "libisofs.h" #include #include #include #include #include #include #include #include #include #include #include #ifndef PATH_MAX #define PATH_MAX Libisofs_default_path_maX #endif /* ----------------------------- utilities -------------------------- */ void demo_report_iso_err(int err, char *occasion) { char *severity; fprintf(stderr, "%s : err = 0x%X", occasion, (unsigned int) err); if (err < 0) { iso_sev_to_text(iso_error_get_severity(err), &severity); fprintf(stderr, " -> %s '%s'", severity, iso_error_to_msg(err)); } fprintf(stderr, "\n"); } /* ------------------------- from demo/tree.c ----------------------- */ static void print_permissions(mode_t mode) { char perm[10]; /* TODO suid, sticky... */ perm[9] = '\0'; perm[8] = mode & S_IXOTH ? 'x' : '-'; perm[7] = mode & S_IWOTH ? 'w' : '-'; perm[6] = mode & S_IROTH ? 'r' : '-'; perm[5] = mode & S_IXGRP ? 'x' : '-'; perm[4] = mode & S_IWGRP ? 'w' : '-'; perm[3] = mode & S_IRGRP ? 'r' : '-'; perm[2] = mode & S_IXUSR ? 'x' : '-'; perm[1] = mode & S_IWUSR ? 'w' : '-'; perm[0] = mode & S_IRUSR ? 'r' : '-'; printf("[%s]",perm); } static void tree_print_dir(IsoDir *dir, int level) { int i; IsoDirIter *iter; IsoNode *node; char *sp; sp = calloc(1, level * 2 + 1); for (i = 0; i < level * 2; i += 2) { sp[i] = '|'; sp[i+1] = ' '; } if (level > 0) sp[level * 2 - 1] = '-'; sp[level * 2] = '\0'; iso_dir_get_children(dir, &iter); while (iso_dir_iter_next(iter, &node) == 1) { if (ISO_NODE_IS_DIR(node)) { printf("%s+[D] ", sp); print_permissions(iso_node_get_permissions(node)); printf(" %s\n", iso_node_get_name(node)); tree_print_dir(ISO_DIR(node), level+1); } else if (ISO_NODE_IS_FILE(node)) { printf("%s-[F] ", sp); print_permissions(iso_node_get_permissions(node)); printf(" %s\n", iso_node_get_name(node) ); } else if (ISO_NODE_IS_SYMLINK(node)) { printf("%s-[L] ", sp); print_permissions(iso_node_get_permissions(node)); printf(" %s -> %s \n", iso_node_get_name(node), iso_symlink_get_dest(ISO_SYMLINK(node)) ); } else { printf("%s-[C] ", sp); print_permissions(iso_node_get_permissions(node)); printf(" %s\n", iso_node_get_name(node) ); } } iso_dir_iter_free(iter); free(sp); } int gesture_tree(int argc, char **argv) { int result; IsoImage *image; if (argc != 2) { need_abs_path:; fprintf (stderr, "You need to specify a valid absolute path\n"); return 1; } if (argv[1][0] != '/') goto need_abs_path; iso_init(); iso_set_msgs_severities("NEVER", "ALL", ""); result = iso_image_new("volume_id", &image); if (result < 0) { printf ("Error creating image\n"); return 1; } result = iso_tree_add_dir_rec(image, iso_image_get_root(image), argv[1]); if (result < 0) { printf ("Error adding directory %d\n", result); return 1; } printf("================= IMAGE =================\n"); tree_print_dir(iso_image_get_root(image), 0); printf("\n\n"); iso_image_unref(image); iso_finish(); return 0; } /* ------------------------- from demo/find.c ----------------------- */ static void find_print_dir(IsoDir *dir) { IsoDirIter *iter; IsoNode *node; IsoFindCondition *cond, *c1, *c2; c1 = iso_new_find_conditions_name("*a*"); c2 = iso_new_find_conditions_mode(S_IFREG); cond = iso_new_find_conditions_and(c1, c2); iso_dir_find_children(dir, cond, &iter); while (iso_dir_iter_next(iter, &node) == 1) { char *path = iso_tree_get_node_path(node); printf(" %s\n", path); free(path); } iso_dir_iter_free(iter); } int gesture_find(int argc, char **argv) { int result; IsoImage *image; if (argc != 2) { need_abs_path:; fprintf (stderr, "You need to specify a valid absolute path\n"); return 1; } if (argv[1][0] != '/') goto need_abs_path; iso_init(); iso_set_msgs_severities("NEVER", "ALL", ""); result = iso_image_new("volume_id", &image); if (result < 0) { printf ("Error creating image\n"); return 1; } result = iso_tree_add_dir_rec(image, iso_image_get_root(image), argv[1]); if (result < 0) { printf ("Error adding directory %d\n", result); return 1; } find_print_dir(iso_image_get_root(image)); iso_image_unref(image); iso_finish(); return 0; } /* ------------------------- from demo/iso.c ----------------------- */ static const char * const optstring = "JRIL:b:hV:"; extern char *optarg; extern int optind; void iso_usage(char **argv) { printf("%s [OPTIONS] DIRECTORY OUTPUT\n", argv[0]); } void iso_help() { printf( "Options:\n" " -J Add Joliet support\n" " -R Add Rock Ridge support\n" " -I Add ISO 9660:1999 support\n" " -V label Volume Label\n" " -L Set the ISO level (1 or 2)\n" " -b file Specifies a boot image to add to image\n" " -h Print this message\n" ); } int iso_callback(IsoFileSource *src) { char *path = iso_file_source_get_path(src); printf("CALLBACK: %s\n", path); free(path); return 1; } int gesture_iso(int argc, char **argv) { int result; int c; IsoImage *image; struct burn_source *burn_src; unsigned char buf[2048]; FILE *fp = NULL; IsoWriteOpts *opts; char *volid = "VOLID"; char *boot_img = NULL; int rr = 0, j = 0, iso1999 = 0, level = 1; while ((c = getopt(argc, argv, optstring)) != -1) { switch(c) { case 'h': iso_usage(argv); iso_help(); goto ex; break; case 'J': j = 1; break; case 'R': rr = 1; break; case 'I': iso1999 = 1; break; case 'L': level = atoi(optarg); break; case 'b': boot_img = optarg; break; case 'V': volid = optarg; break; case '?': iso_usage(argv); goto ex; break; } } if (argc < 2) { printf ("Please pass directory from which to build ISO\n"); iso_usage(argv); goto ex; } if (argc < 3) { printf ("Please supply output file\n"); iso_usage(argv); goto ex; } fp = fopen(argv[optind+1], "w"); if (fp == NULL) { err(1, "error opening output file"); goto ex; } result = iso_init(); if (result < 0) { printf ("Can't initialize libisofs\n"); goto ex; } iso_set_msgs_severities("NEVER", "ALL", ""); result = iso_image_new(volid, &image); if (result < 0) { printf ("Error creating image\n"); goto ex; } iso_tree_set_follow_symlinks(image, 0); iso_tree_set_ignore_hidden(image, 0); iso_tree_set_ignore_special(image, 0); iso_set_abort_severity("SORRY"); /*iso_tree_set_report_callback(image, callback);*/ result = iso_tree_add_dir_rec(image, iso_image_get_root(image), argv[optind]); if (result < 0) { printf ("Error adding directory %d\n", result); goto ex; } if (boot_img) { /* adds El-Torito boot info. Tunned for isolinux */ ElToritoBootImage *bootimg; result = iso_image_set_boot_image(image, boot_img, ELTORITO_NO_EMUL, "/isolinux/boot.cat", &bootimg); if (result < 0) { printf ("Error adding boot image %d\n", result); goto ex; } el_torito_set_load_size(bootimg, 4); el_torito_patch_isolinux_image(bootimg); } result = iso_write_opts_new(&opts, 0); if (result < 0) { printf ("Cant create write opts, error %d\n", result); goto ex; } iso_write_opts_set_iso_level(opts, level); iso_write_opts_set_rockridge(opts, rr); iso_write_opts_set_joliet(opts, j); iso_write_opts_set_iso1999(opts, iso1999); result = iso_image_create_burn_source(image, opts, &burn_src); if (result < 0) { printf ("Cant create image, error %d\n", result); goto ex; } iso_write_opts_free(opts); while (burn_src->read_xt(burn_src, buf, 2048) == 2048) { result = fwrite(buf, 1, 2048, fp); if (result < 2048) { printf ("Cannot write block. errno= %d\n", errno); goto ex; } } fclose(fp); burn_src->free_data(burn_src); free(burn_src); iso_image_unref(image); iso_finish(); return 0; ex:; if (fp != NULL) fclose(fp); return 1; } /* ------------------------- from demo/iso_read.c ----------------------- */ static void iso_read_print_type(mode_t mode) { switch(mode & S_IFMT) { case S_IFSOCK: printf("[S] "); break; case S_IFLNK: printf("[L] "); break; case S_IFREG: printf("[R] "); break; case S_IFBLK: printf("[B] "); break; case S_IFDIR: printf("[D] "); break; case S_IFIFO: printf("[F] "); break; } } static void iso_read_print_file_src(IsoFileSource *file) { struct stat info; char *name; iso_file_source_lstat(file, &info); iso_read_print_type(info.st_mode); print_permissions(info.st_mode); printf(" %10.f ", (double) info.st_size); /* printf(" {%ld,%ld} ", (long)info.st_dev, (long)info.st_ino); */ name = iso_file_source_get_name(file); printf(" %s", name); free(name); if (S_ISLNK(info.st_mode)) { char buf[PATH_MAX]; iso_file_source_readlink(file, buf, PATH_MAX); printf(" -> %s\n", buf); } printf("\n"); } static void iso_read_print_dir(IsoFileSource *dir, int level) { int ret, i; IsoFileSource *file; struct stat info; char *sp; sp = calloc(1, level * 2 + 1); for (i = 0; i < level * 2; i += 2) { sp[i] = '|'; sp[i+1] = ' '; } if (level > 0) sp[level * 2 - 1] = '-'; sp[level * 2] = '\0'; ret = iso_file_source_open(dir); if (ret < 0) { printf ("Can't open dir %d\n", ret); } while ((ret = iso_file_source_readdir(dir, &file)) == 1) { printf("%s", sp); iso_read_print_file_src(file); ret = iso_file_source_lstat(file, &info); if (ret < 0) { break; } if (S_ISDIR(info.st_mode)) { iso_read_print_dir(file, level + 1); } iso_file_source_unref(file); } iso_file_source_close(dir); if (ret < 0) { printf ("Can't print dir\n"); } free(sp); } int gesture_iso_read(int argc, char **argv) { int result, initialized = 0, return_val = 1; IsoImageFilesystem *fs = NULL; IsoDataSource *src = NULL; IsoFileSource *root = NULL; IsoReadOpts *ropts = NULL; if (argc != 2) { printf ("You need to specify a valid path\n"); goto ex; } result = iso_init(); if (result < 0) { demo_report_iso_err(result, "Cannot init libisofs"); goto ex; } initialized = 1; iso_set_msgs_severities("NEVER", "ALL", ""); result = iso_data_source_new_from_file(argv[1], &src); if (result < 0) { demo_report_iso_err(result, "Error creating data source"); goto ex; } result = iso_read_opts_new(&ropts, 0); if (result < 0) { demo_report_iso_err(result, "Error creating read options"); goto ex; } result = iso_image_filesystem_new(src, ropts, 1, &fs); if (result < 0) { demo_report_iso_err(result, "Error creating filesystem"); goto ex; } iso_read_opts_free(ropts); ropts = NULL; printf("\nVOLUME INFORMATION\n"); printf("==================\n\n"); printf("Vol. id: %s\n", iso_image_fs_get_volume_id(fs)); printf("Publisher: %s\n", iso_image_fs_get_publisher_id(fs)); printf("Data preparer: %s\n", iso_image_fs_get_data_preparer_id(fs)); printf("System: %s\n", iso_image_fs_get_system_id(fs)); printf("Application: %s\n", iso_image_fs_get_application_id(fs)); printf("Copyright: %s\n", iso_image_fs_get_copyright_file_id(fs)); printf("Abstract: %s\n", iso_image_fs_get_abstract_file_id(fs)); printf("Biblio: %s\n", iso_image_fs_get_biblio_file_id(fs)); printf("\nDIRECTORY TREE\n"); printf("==============\n"); result = fs->get_root(fs, &root); if (result < 0) { demo_report_iso_err(result, "Cannot get root object"); goto ex; } /* iso_read_print_file_src(root); */ iso_read_print_dir(root, 0); return_val = 0; ex:; if (root != NULL) iso_file_source_unref(root); if (ropts != NULL) iso_read_opts_free(ropts); if (fs != NULL) { fs->close(fs); iso_filesystem_unref((IsoFilesystem*)fs); } if (src != NULL) iso_data_source_unref(src); if (initialized) iso_finish(); return return_val; } /* ------------------------- from demo/iso_cat.c ----------------------- */ int gesture_iso_cat(int argc, char **argv) { int res, write_ret, ret; IsoFilesystem *fs = NULL; IsoFileSource *file = NULL; struct stat info; IsoDataSource *src = NULL; IsoReadOpts *opts = NULL; if (argc != 3) { fprintf(stderr, "Usage: -iso_cat /path/to/image /path/to/file\n"); return 1; } res = iso_init(); if (res < 0) { demo_report_iso_err(res, "Cannot init libisofs"); return 1; } /* Important Note: From here on memory objects get created which need to be freed in the end. Therefore in case of problems no direct return, but rather a hop to label "ex:", where cleanup happens. */ res = iso_data_source_new_from_file(argv[1], &src); if (res < 0) { demo_report_iso_err(res, "Error creating data source object"); ret = 1; goto ex; } res = iso_read_opts_new(&opts, 0); if (res < 0) { demo_report_iso_err(res, "Error creating read options object"); ret = 1; goto ex; } res = iso_image_filesystem_new(src, opts, 1, &fs); if (res < 0) { demo_report_iso_err(res, "Error creating filesystem object"); ret = 1; goto ex; } iso_read_opts_free(opts); opts = NULL; res = fs->get_by_path(fs, argv[2], &file); if (res < 0) { demo_report_iso_err(res, "Cannot get file object with given path"); ret = 1; goto ex; } res = iso_file_source_lstat(file, &info); if (res < 0) { demo_report_iso_err(res, "Cannot inquire type of file object with given path"); ret = 1; goto ex; } if (S_ISDIR(info.st_mode)) { fprintf(stderr, "Path refers to a directory!!\n"); ret = 1; goto ex; } else { char buf[1024]; res = iso_file_source_open(file); if (res < 0) { demo_report_iso_err(res, "Cannot open file object with given path"); ret = 1; goto ex; } while ((res = iso_file_source_read(file, buf, 1024)) > 0) { write_ret = fwrite(buf, 1, res, stdout); if (write_ret < res) { printf ("Cannot write block to stdout. errno= %d\n", errno); iso_file_source_close(file); ret = 1; goto ex; } } iso_file_source_close(file); if (res < 0) { demo_report_iso_err(res, "Error while reading data content"); fprintf(stderr, "Error reading, err = 0x%X\n", (unsigned int) res); ret = 1; goto ex; } } ret = 0; ex:; if (file != NULL) iso_file_source_unref(file); if (fs != NULL) iso_filesystem_unref(fs); if (opts != NULL) iso_read_opts_free(opts); if (src != NULL) iso_data_source_unref(src); iso_finish(); return ret; } /* ------------------------- from demo/iso_modify.c ----------------------- */ void iso_modify_usage(char **argv) { printf("%s IMAGE DIRECTORY OUTPUT\n", argv[0]); } int gesture_iso_modify(int argc, char **argv) { int result, return_val = 1, initialized = 0; IsoImage *image = NULL; IsoDataSource *src = NULL; struct burn_source *burn_src = NULL; unsigned char buf[2048]; FILE *fp = NULL; IsoWriteOpts *opts = NULL; IsoReadOpts *ropts = NULL; if (argc < 4) { iso_modify_usage(argv); goto ex; } fp = fopen(argv[3], "w"); if (fp == NULL) { err(1, "error opening output file"); goto ex; } result = iso_init(); if (result < 0) { demo_report_iso_err(result, "Cannot init libisofs"); goto ex; } initialized = 1; iso_set_msgs_severities("NEVER", "ALL", ""); /* create the data source to accesss previous image */ result = iso_data_source_new_from_file(argv[1], &src); if (result < 0) { demo_report_iso_err(result, "Error creating data source"); goto ex; } /* create the image context */ result = iso_image_new("volume_id", &image); if (result < 0) { demo_report_iso_err(result, "Error creating image"); goto ex; } iso_tree_set_follow_symlinks(image, 0); iso_tree_set_ignore_hidden(image, 0); /* import previous image */ result = iso_read_opts_new(&ropts, 0); if (result < 0) { demo_report_iso_err(result, "Error creating read options"); goto ex; } result = iso_image_import(image, src, ropts, NULL); if (result < 0) { demo_report_iso_err(result, "Error importing previous session"); goto ex; } /* (One could of course keep them alive until cleanup) */ iso_read_opts_free(ropts); ropts = NULL; iso_data_source_unref(src); src = NULL; /* add new dir */ result = iso_tree_add_dir_rec(image, iso_image_get_root(image), argv[2]); if (result < 0) { demo_report_iso_err(result, "Error adding directory"); goto ex; } /* Generate a new image with both previous and added contents. Profile 1 means Rock Ridge and ISO level 3. */ result = iso_write_opts_new(&opts, 1); if (result < 0) { demo_report_iso_err(result, "Cannot create write opts"); goto ex; } /* Prefer specs violation over relocation deep directories */ iso_write_opts_set_allow_deep_paths(opts, 1); /* For MS-Windows readers : iso_write_opts_set_joliet(opts, 1); */ result = iso_image_create_burn_source(image, opts, &burn_src); if (result < 0) { demo_report_iso_err(result, "Cannot create image object"); goto ex; } iso_write_opts_free(opts); opts = NULL; while (burn_src->read_xt(burn_src, buf, 2048) == 2048) { result = fwrite(buf, 1, 2048, fp); if (result < 2048) { fprintf (stderr, "Cannot write block. errno= %d\n", errno); goto ex; } } return_val = 0; ex: if (fp != NULL) fclose(fp); if (opts != NULL) iso_write_opts_free(opts); if (burn_src != NULL) { burn_src->free_data(burn_src); free(burn_src); } if (image != NULL) iso_image_unref(image); if (ropts != NULL) iso_read_opts_free(ropts); if (src != NULL) iso_data_source_unref(src); if (initialized) iso_finish(); return return_val; } /* ------------------------- from demo/iso_ms.c ----------------------- */ void iso_ms_usage(char **argv) { printf("%s LSS NWA DISC DIRECTORY OUTPUT\n", argv[0]); } int gesture_iso_ms(int argc, char **argv) { int result, return_val = 1, initialized = 0; IsoImage *image = NULL; IsoDataSource *src = NULL; struct burn_source *burn_src = NULL; unsigned char buf[2048]; FILE *fp = NULL; IsoWriteOpts *opts = NULL; IsoReadOpts *ropts = NULL; uint32_t ms_block; if (argc < 6) { iso_ms_usage(argv); goto ex; } if (strcmp(argv[3], argv[5]) == 0) { fprintf(stderr, "image_file and output_file must not be the same file.\n"); goto ex; } fp = fopen(argv[5], "w"); if (!fp) { err(1, "error opening output file"); goto ex; } result = iso_init(); if (result < 0) { demo_report_iso_err(result, "Cannot init libisofs"); goto ex; } initialized = 1; iso_set_msgs_severities("NEVER", "ALL", ""); /* create the data source to accesss previous image */ result = iso_data_source_new_from_file(argv[3], &src); if (result < 0) { demo_report_iso_err(result, "Error creating data source"); goto ex; } /* create the image context */ result = iso_image_new("volume_id", &image); if (result < 0) { demo_report_iso_err(result, "Error creating image"); goto ex; } iso_tree_set_follow_symlinks(image, 0); iso_tree_set_ignore_hidden(image, 0); /* import previous image */ result = iso_read_opts_new(&ropts, 0); if (result < 0) { fprintf(stderr, "Error creating read options\n"); goto ex; } iso_read_opts_set_start_block(ropts, atoi(argv[1])); result = iso_image_import(image, src, ropts, NULL); iso_read_opts_free(ropts); ropts = NULL; iso_data_source_unref(src); src = NULL; if (result < 0) { demo_report_iso_err(result, "Error importing previous session"); goto ex; } /* add new dir */ result = iso_tree_add_dir_rec(image, iso_image_get_root(image), argv[4]); if (result < 0) { demo_report_iso_err(result, "Error adding directory"); goto ex; } /* generate a multisession image with new contents */ result = iso_write_opts_new(&opts, 1); if (result < 0) { demo_report_iso_err(result, "Cannot create write opts"); goto ex; } /* round up to 32kb aligment = 16 block */ ms_block = atoi(argv[2]); iso_write_opts_set_ms_block(opts, ms_block); iso_write_opts_set_appendable(opts, 1); result = iso_image_create_burn_source(image, opts, &burn_src); if (result < 0) { printf ("Cant create image, error %d\n", result); goto ex; } iso_write_opts_free(opts); opts = NULL; while (burn_src->read_xt(burn_src, buf, 2048) == 2048) { result = fwrite(buf, 1, 2048, fp); if (result < 2048) { printf ("Cannot write block. errno= %d\n", errno); goto ex; } } return_val = 0; ex:; if (burn_src != NULL) { burn_src->free_data(burn_src); free(burn_src); } if (opts != NULL) iso_write_opts_free(opts); if (image) iso_image_unref(image); if (ropts != NULL) iso_read_opts_free(ropts); if (src != NULL) iso_data_source_unref(src); if (initialized) iso_finish(); if (fp != NULL) fclose(fp); return return_val; } /* ------------------------- switcher ----------------------- */ int main(int argc, char **argv) { char *gesture; int i; if (argc < 2) { usage:; fprintf(stderr, "usage: %s gesture [gesture_options]\n", argv[0]); for (i = 0; helptext[i][0] != '@'; i++) fprintf(stderr, "%s\n", helptext[i]); exit(1); } for (gesture = argv[1]; *gesture == '-'; gesture++); if (strcmp(gesture, "tree") == 0) { gesture_tree(argc - 1, &(argv[1])); } else if(strcmp(gesture, "find") == 0) { gesture_find(argc - 1, &(argv[1])); } else if(strcmp(gesture, "iso") == 0) { gesture_iso(argc - 1, &(argv[1])); } else if(strcmp(gesture, "iso_read") == 0) { gesture_iso_read(argc - 1, &(argv[1])); } else if(strcmp(gesture, "iso_cat") == 0) { gesture_iso_cat(argc - 1, &(argv[1])); } else if(strcmp(gesture, "iso_modify") == 0) { gesture_iso_modify(argc - 1, &(argv[1])); } else if(strcmp(gesture, "iso_ms") == 0) { gesture_iso_ms(argc - 1, &(argv[1])); } else { goto usage; } exit(0); } libisofs-1.4.2/missing0000755000175700017510000002540611112746612011670 00000000000000#! /bin/sh # Common stub for a few missing GNU programs while installing. scriptversion=2005-06-08.21 # Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005 # Free Software Foundation, Inc. # Originally 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, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. # 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 run=: # In the cases where this matters, `missing' is being run in the # srcdir already. if test -f configure.ac; then configure_ac=configure.ac else configure_ac=configure.in fi msg="missing on your system" case "$1" in --run) # Try to run requested program, and just exit if it succeeds. run= shift "$@" && exit 0 # Exit code 63 means version mismatch. This often happens # when the user try to use an ancient version of a tool on # a file that requires a minimum version. In this case we # we should proceed has if the program had been absent, or # if --run hadn't been passed. if test $? = 63; then run=: msg="probably too old" fi ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an error status if there is no known handling for PROGRAM. Options: -h, --help display this help and exit -v, --version output version information and exit --run try to run the given command, and emulate it if it fails Supported PROGRAM values: aclocal touch file \`aclocal.m4' autoconf touch file \`configure' autoheader touch file \`config.h.in' automake touch all \`Makefile.in' files bison create \`y.tab.[ch]', if possible, from existing .[ch] flex create \`lex.yy.c', if possible, from existing .c help2man touch the output file lex create \`lex.yy.c', if possible, from existing .c makeinfo touch the output file tar try tar, gnutar, gtar, then tar without non-portable flags yacc create \`y.tab.[ch]', if possible, from existing .[ch] Send bug reports to ." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: Unknown \`$1' option" echo 1>&2 "Try \`$0 --help' for more information" exit 1 ;; esac # Now exit if we have it, but it failed. Also exit now if we # don't have it and --version was passed (most likely to detect # the program). case "$1" in lex|yacc) # Not GNU programs, they don't have --version. ;; tar) if test -n "$run"; then echo 1>&2 "ERROR: \`tar' requires --run" exit 1 elif test "x$2" = "x--version" || test "x$2" = "x--help"; then exit 1 fi ;; *) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 elif test "x$2" = "x--version" || test "x$2" = "x--help"; then # Could not run --version or --help. This is probably someone # running `$TOOL --version' or `$TOOL --help' to check whether # $TOOL exists and not knowing $TOOL uses missing. exit 1 fi ;; esac # If it does not exist, or fails to run (possibly an outdated version), # try to emulate it. case "$1" in aclocal*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." touch aclocal.m4 ;; autoconf) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." touch configure ;; autoheader) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`acconfig.h' or \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` test -z "$files" && files="config.h" touch_files= for f in $files; do case "$f" in *:*) touch_files="$touch_files "`echo "$f" | sed -e 's/^[^:]*://' -e 's/:.*//'`;; *) touch_files="$touch_files $f.in";; esac done touch $touch_files ;; automake*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." find . -type f -name Makefile.am -print | sed 's/\.am$/.in/' | while read f; do touch "$f"; done ;; autom4te) echo 1>&2 "\ WARNING: \`$1' is needed, but is $msg. You might have modified some files without having the proper tools for further handling them. You can get \`$1' as part of \`Autoconf' from any GNU archive site." file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'` test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'` if test -f "$file"; then touch $file else test -z "$file" || exec >$file echo "#! /bin/sh" echo "# Created by GNU Automake missing as a replacement of" echo "# $ $@" echo "exit 0" chmod +x $file exit 1 fi ;; bison|yacc) echo 1>&2 "\ WARNING: \`$1' $msg. You should only need it if you modified a \`.y' file. You may need the \`Bison' package in order for those modifications to take effect. You can get \`Bison' from any GNU archive site." rm -f y.tab.c y.tab.h if [ $# -ne 1 ]; then eval LASTARG="\${$#}" case "$LASTARG" in *.y) SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" y.tab.c fi SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" y.tab.h fi ;; esac fi if [ ! -f y.tab.h ]; then echo >y.tab.h fi if [ ! -f y.tab.c ]; then echo 'main() { return 0; }' >y.tab.c fi ;; lex|flex) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a \`.l' file. You may need the \`Flex' package in order for those modifications to take effect. You can get \`Flex' from any GNU archive site." rm -f lex.yy.c if [ $# -ne 1 ]; then eval LASTARG="\${$#}" case "$LASTARG" in *.l) SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" lex.yy.c fi ;; esac fi if [ ! -f lex.yy.c ]; then echo 'main() { return 0; }' >lex.yy.c fi ;; help2man) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a dependency of a manual page. You may need the \`Help2man' package in order for those modifications to take effect. You can get \`Help2man' from any GNU archive site." file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` if test -z "$file"; then file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` fi if [ -f "$file" ]; then touch $file else test -z "$file" || exec >$file echo ".ab help2man is required to generate this page" exit 1 fi ;; makeinfo) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a \`.texi' or \`.texinfo' file, or any other file indirectly affecting the aspect of the manual. The spurious call might also be the consequence of using a buggy \`make' (AIX, DU, IRIX). You might want to install the \`Texinfo' package or the \`GNU make' package. Grab either from any GNU archive site." # The file to touch is that specified with -o ... file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` if test -z "$file"; then # ... or it is the one specified with @setfilename ... infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $infile` # ... or it is derived from the source name (dir/f.texi becomes f.info) test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info fi # If the file does not exist, the user really needs makeinfo; # let's fail without touching anything. test -f $file || exit 1 touch $file ;; tar) shift # We have already tried tar in the generic part. # Look for gnutar/gtar before invocation to avoid ugly error # messages. if (gnutar --version > /dev/null 2>&1); then gnutar "$@" && exit 0 fi if (gtar --version > /dev/null 2>&1); then gtar "$@" && exit 0 fi firstarg="$1" if shift; then case "$firstarg" in *o*) firstarg=`echo "$firstarg" | sed s/o//` tar "$firstarg" "$@" && exit 0 ;; esac case "$firstarg" in *h*) firstarg=`echo "$firstarg" | sed s/h//` tar "$firstarg" "$@" && exit 0 ;; esac fi echo 1>&2 "\ WARNING: I can't seem to be able to run \`tar' with the given arguments. You may want to install GNU tar or Free paxutils, or check the command line arguments." exit 1 ;; *) echo 1>&2 "\ WARNING: \`$1' is needed, and is $msg. You might have modified some files without having the proper tools for further handling them. Check the \`README' file, it often tells you about the needed prerequisites for installing this package. You may also peek at any GNU archive site, in case some other package would contain this missing \`$1' program." exit 1 ;; esac exit 0 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-end: "$" # End: libisofs-1.4.2/Makefile.am0000644000175700017510000001652712450230606012326 00000000000000 # ts A90315 : LIBBURNIA_PKGCONFDIR is defined OS specific in acinclude.m4 # was: pkgconfigdir=$(libdir)/pkgconfig pkgconfigdir=$(LIBBURNIA_PKGCONFDIR) libincludedir=$(includedir)/libisofs lib_LTLIBRARIES = libisofs/libisofs.la ACLOCAL_AMFLAGS = -I ./ ## ========================================================================= ## # Build libraries libisofs_libisofs_la_LDFLAGS = \ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) # Eventually enabling system adapters for ACL and EA. # ts A90409: Eventually enabling use of zlib. # ts B00927: Eventually enabling use of libjte (Jigdo Template Extraction) libisofs_libisofs_la_CFLAGS = $(LIBACL_DEF) $(XATTR_DEF) $(ZLIB_DEF) \ $(LIBJTE_DEF) # ts A90114 : added aaip_0_2.* libisofs_libisofs_la_SOURCES = \ libisofs/builder.h \ libisofs/builder.c \ libisofs/node.h \ libisofs/node.c \ libisofs/tree.h \ libisofs/tree.c \ libisofs/find.c \ libisofs/image.h \ libisofs/image.c \ libisofs/fsource.h \ libisofs/fsource.c \ libisofs/fs_local.c \ libisofs/fs_image.c \ libisofs/messages.h \ libisofs/messages.c \ libisofs/libiso_msgs.h \ libisofs/libiso_msgs.c \ libisofs/stream.h \ libisofs/stream.c \ libisofs/filter.h \ libisofs/filter.c \ libisofs/filters/external.c \ libisofs/filters/zisofs.c \ libisofs/filters/gzip.c \ libisofs/util.h \ libisofs/util.c \ libisofs/util_rbtree.c \ libisofs/util_htable.c \ libisofs/filesrc.h \ libisofs/filesrc.c \ libisofs/ecma119.h \ libisofs/ecma119.c \ libisofs/ecma119_tree.h \ libisofs/ecma119_tree.c \ libisofs/writer.h \ libisofs/buffer.h \ libisofs/buffer.c \ libisofs/rockridge.h \ libisofs/rockridge.c \ libisofs/rockridge_read.c \ libisofs/joliet.h \ libisofs/joliet.c \ libisofs/hfsplus.h \ libisofs/hfsplus.c \ libisofs/hfsplus_decompose.c \ libisofs/hfsplus_classes.c \ libisofs/hfsplus_case.c \ libisofs/eltorito.h \ libisofs/eltorito.c \ libisofs/system_area.h \ libisofs/system_area.c \ libisofs/make_isohybrid_mbr.c \ libisofs/iso1999.h \ libisofs/iso1999.c \ libisofs/data_source.c \ libisofs/aaip_0_2.h \ libisofs/aaip_0_2.c \ libisofs/md5.h \ libisofs/md5.c libisofs_libisofs_la_LIBADD= \ $(THREAD_LIBS) libinclude_HEADERS = \ libisofs/libisofs.h install-exec-hook: $(LIBBURNIA_LDCONFIG_CMD) "$(DESTDIR)$(libdir)" || echo 'NOTE: Explicit dynamic library configuration failed. If needed, configure manually for:' "$(DESTDIR)$(libdir)" ## ========================================================================= ## ## Build demo applications noinst_PROGRAMS = \ demo/demo # demo/tree \ # demo/find \ # demo/iso \ # demo/isoread \ # demo/isocat \ # demo/isomodify \ # demo/isoms # demo/ecma119tree \ # demo/lsl \ # demo/cat \ # demo/catbuffer \ # demo/isogrow # ts A90807 # Consolidated demo code for having less linker mesages with a make run. demo_demo_CPPFLAGS = -Ilibisofs demo_demo_LDADD = $(libisofs_libisofs_la_OBJECTS) $(libisofs_libisofs_la_LIBADD) demo_demo_SOURCES = demo/demo.c # ts A90806 # This includes fsource.h and thus is no API demo # demo_lsl_CPPFLAGS = -Ilibisofs # demo_lsl_LDADD = $(libisofs_libisofs_la_OBJECTS) $(libisofs_libisofs_la_LIBADD) # demo_lsl_SOURCES = demo/lsl.c # ts A90806 # This includes fsource.h and thus is no API demo # demo_cat_CPPFLAGS = -Ilibisofs # demo_cat_LDADD = $(libisofs_libisofs_la_OBJECTS) $(libisofs_libisofs_la_LIBADD) # demo_cat_SOURCES = demo/cat.c # ts A90806 # This inlcudes buffer.h and thus is no API demo # demo_catbuffer_CPPFLAGS = -Ilibisofs # demo_catbuffer_LDADD = $(libisofs_libisofs_la_OBJECTS) \ # $(libisofs_libisofs_la_LIBADD) # demo_catbuffer_SOURCES = demo/cat_buffer.c # ts A90807 # Consolidated in demo/demo # demo_tree_CPPFLAGS = -Ilibisofs # demo_tree_LDADD = $(libisofs_libisofs_la_OBJECTS) \ # $(libisofs_libisofs_la_LIBADD) # demo_tree_SOURCES = demo/tree.c # ts A90807 # Consolidated in demo/demo # demo_find_CPPFLAGS = -Ilibisofs # demo_find_LDADD = $(libisofs_libisofs_la_OBJECTS) \ # $(libisofs_libisofs_la_LIBADD) # demo_find_SOURCES = demo/find.c # ts A90806 # This inlcudes lots of internal .h files and thus is no API demo # demo_ecma119tree_CPPFLAGS = -Ilibisofs # demo_ecma119tree_LDADD = $(libisofs_libisofs_la_OBJECTS) \ # $(libisofs_libisofs_la_LIBADD) # demo_ecma119tree_SOURCES = demo/ecma119_tree.c # ts A90807 # Consolidated in demo/demo # demo_iso_CPPFLAGS = -Ilibisofs # demo_iso_LDADD = $(libisofs_libisofs_la_OBJECTS) $(libisofs_libisofs_la_LIBADD) # demo_iso_SOURCES = demo/iso.c # ts A90807 # Consolidated in demo/demo # demo_isoread_CPPFLAGS = -Ilibisofs # demo_isoread_LDADD = $(libisofs_libisofs_la_OBJECTS) \ # $(libisofs_libisofs_la_LIBADD) # demo_isoread_SOURCES = demo/iso_read.c # ts A90807 # Consolidated in demo/demo # demo_isocat_CPPFLAGS = -Ilibisofs # demo_isocat_LDADD = $(libisofs_libisofs_la_OBJECTS) \ # $(libisofs_libisofs_la_LIBADD) # demo_isocat_SOURCES = demo/iso_cat.c # ts A90807 # Consolidated in demo/demo # demo_isomodify_CPPFLAGS = -Ilibisofs # demo_isomodify_LDADD = $(libisofs_libisofs_la_OBJECTS) \ # $(libisofs_libisofs_la_LIBADD) # demo_isomodify_SOURCES = demo/iso_modify.c # ts A90807 # Consolidated in demo/demo # demo_isoms_CPPFLAGS = -Ilibisofs # demo_isoms_LDADD = $(libisofs_libisofs_la_OBJECTS) \ # $(libisofs_libisofs_la_LIBADD) # demo_isoms_SOURCES = demo/iso_ms.c # demo_isogrow_CPPFLAGS = -Ilibisofs -Ilibburn # demo_isogrow_LDADD = $(libisofs_libisofs_la_OBJECTS) \ # $(libisofs_libisofs_la_LIBADD) \ # -lburn # demo_isogrow_SOURCES = demo/iso_grow.c ## ts A90428 , ticket 147, The test code does not use the API and is totally ## outdated in its creation of mocked objects. ## A volunteer is needed to rewrite it using the API. # ## Build unit test # check_PROGRAMS = \ # test/test # # test_test_CPPFLAGS = -Ilibisofs # test_test_LDADD = $(libisofs_libisofs_la_OBJECTS) \ # $(libisofs_libisofs_la_LIBADD) -lcunit # test_test_LDFLAGS = -L.. -lm # # test_test_SOURCES = \ # test/test.h \ # test/test.c \ # test/test_node.c \ # test/test_image.c \ # test/test_tree.c \ # test/test_util.c \ # test/test_rockridge.c \ # test/test_stream.c \ # test/mocked_fsrc.h \ # test/mocked_fsrc.c # "make clean" shall remove a few stubborn .libs directories # which George Danchev reported Dec 03 2011. # Learned from: http://www.gnu.org/software/automake/manual/automake.html#Clean clean-local: -rm -rf demo/.libs ## ========================================================================= ## ## Build documentation (You need Doxygen for this to work) docdir = $(DESTDIR)$(prefix)/share/doc/$(PACKAGE)-$(VERSION) doc: doc/html doc/html: doc/doxygen.conf $(RM) -r doc/html; \ doxygen doc/doxygen.conf; install-data-local: if [ -d doc/html ]; then \ $(mkinstalldirs) $(docdir)/html; \ $(INSTALL_DATA) doc/html/* $(docdir)/html; \ fi uninstall-local: rm -rf $(docdir) ## ========================================================================= ## # Extra things nodist_pkgconfig_DATA = \ libisofs-1.pc # ts A80114 : added aaip-os* EXTRA_DIST = \ bootstrap \ libisofs-1.pc.in \ version.h.in \ doc/doxygen.conf.in \ doc/Tutorial \ README \ AUTHORS \ COPYRIGHT \ COPYING \ NEWS \ INSTALL \ TODO \ ChangeLog \ Roadmap \ doc/susp_aaip_2_0.txt \ doc/susp_aaip_isofs_names.txt \ doc/zisofs_format.txt \ doc/checksums.txt \ libisofs/libisofs.ver \ libisofs/aaip-os-dummy.c \ libisofs/aaip-os-linux.c \ libisofs/aaip-os-freebsd.c libisofs-1.4.2/config.sub0000755000175700017510000010554712132767025012265 00000000000000#! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # 2011, 2012 Free Software Foundation, Inc. timestamp='2012-10-10' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software # can handle that machine. It does not imply ALL GNU software can. # # 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 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, 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. # Please send patches to . Submit a context # diff and a properly formatted GNU ChangeLog entry. # # 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: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD # 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. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -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 (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 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" 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 # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ knetbsd*-gnu* | netbsd*-gnu* | \ kopensolaris*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; android-linux) os=-linux-android basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -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*) os= basic_machine=$1 ;; -bluegene*) os=-cnk ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco6) os=-sco5v6 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*178) os=-lynxos178 ;; -lynx*5) os=-lynxos5 ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | aarch64 | aarch64_be \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ | be32 | be64 \ | bfin \ | c4x | clipper \ | d10v | d30v | dlx | dsp16xx \ | epiphany \ | fido | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | le32 | le64 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64octeon | mips64octeonel \ | mips64orion | mips64orionel \ | mips64r5900 | mips64r5900el \ | mips64vr | mips64vrel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | moxie \ | mt \ | msp430 \ | nds32 | nds32le | nds32be \ | nios | nios2 \ | ns16k | ns32k \ | open8 \ | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ | pyramid \ | rl78 | rx \ | score \ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | spu \ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | we32k \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown ;; c54x) basic_machine=tic54x-unknown ;; c55x) basic_machine=tic55x-unknown ;; c6x) basic_machine=tic6x-unknown ;; m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; ms1) basic_machine=mt-unknown ;; strongarm | thumb | xscale) basic_machine=arm-unknown ;; xgate) basic_machine=$basic_machine-unknown os=-none ;; xscaleeb) basic_machine=armeb-unknown ;; xscaleel) basic_machine=armel-unknown ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ | le32-* | le64-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ | microblaze-* | microblazeel-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64octeon-* | mips64octeonel-* \ | mips64orion-* | mips64orionel-* \ | mips64r5900-* | mips64r5900el-* \ | mips64vr-* | mips64vrel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nds32-* | nds32le-* | nds32be-* \ | nios-* | nios2-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | open8-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pyramid-* \ | rl78-* | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile*-* \ | tron-* \ | ubicom32-* \ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ | ymp-* \ | z8k-* | z80-*) ;; # Recognize the basic CPU types without company name, with glob match. xtensa*) basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aros) basic_machine=i386-pc os=-aros ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; blackfin) basic_machine=bfin-unknown os=-linux ;; blackfin-*) basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) basic_machine=powerpc-ibm os=-cnk ;; c54x-*) basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c55x-*) basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c6x-*) basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c90) basic_machine=c90-cray os=-unicos ;; cegcc) basic_machine=arm-unknown os=-cegcc ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16 | cr16-*) basic_machine=cr16-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; crisv32 | crisv32-* | etraxfs*) basic_machine=crisv32-axis ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dicos) basic_machine=i686-pc os=-dicos ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; microblaze*) basic_machine=microblaze-xilinx ;; mingw64) basic_machine=x86_64-pc os=-mingw64 ;; mingw32) basic_machine=i386-pc os=-mingw32 ;; mingw32ce) basic_machine=arm-unknown os=-mingw32ce ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; msys) basic_machine=i386-pc os=-msys ;; mvs) basic_machine=i370-ibm os=-mvs ;; nacl) basic_machine=le32-unknown os=-nacl ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; neo-tandem) basic_machine=neo-tandem ;; nse-tandem) basic_machine=nse-tandem ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; openrisc | openrisc-*) basic_machine=or32-unknown ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; parisc) basic_machine=hppa-unknown os=-linux ;; parisc-*) basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pc98) basic_machine=i386-pc ;; pc98-*) basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc | ppcbe) basic_machine=powerpc-unknown ;; ppc-* | ppcbe-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rdos) basic_machine=i386-pc os=-rdos ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sde) basic_machine=mipsisa32-sde os=-elf ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh5el) basic_machine=sh5le-unknown ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; strongarm-* | thumb-*) basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tile*) basic_machine=$basic_machine-unknown os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xbox) basic_machine=i686-pc os=-mingw32 ;; xps | xps100) basic_machine=xps100-honeywell ;; xscale-* | xscalee[bl]-*) basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; z80-*-coff) basic_machine=z80-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # 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) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; mmix) basic_machine=mmix-knuth ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -auroraux) os=-auroraux ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* | -aros* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ | -bitrig* | -openbsd* | -solidbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* | -cegcc* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -kaos*) os=-kaos ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; -nacl*) ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in score-*) os=-elf ;; spu-*) os=-elf ;; *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; hexagon-*) os=-elf ;; tic54x-*) os=-coff ;; tic55x-*) os=-coff ;; tic6x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 ;; m68*-cisco) os=-aout ;; mep-*) os=-elf ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-haiku) os=-haiku ;; *-ibm) os=-aix ;; *-knuth) os=-mmixware ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $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 ;; -mvs* | -opened*) vendor=ibm ;; -os400*) 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 basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: libisofs-1.4.2/libisofs/0000755000175700017510000000000012626306721012160 500000000000000libisofs-1.4.2/libisofs/builder.h0000644000175700017510000000443412321161425013674 00000000000000/* * Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2014 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ #ifndef LIBISO_BUILDER_H_ #define LIBISO_BUILDER_H_ /* * Definitions for IsoNode builders. */ /* * Some functions here will be moved to libisofs.h when we expose * Builder. */ #include "libisofs.h" #include "fsource.h" typedef struct Iso_Node_Builder IsoNodeBuilder; struct Iso_Node_Builder { /** * Create a new IsoFile from an IsoFileSource. Name, permissions * and other attributes are taken from src, but a regular file will * always be created, even if src is another kind of file. * * In that case, if the implementation can't do the conversion, it * should fail propertly. * * Note that the src is never unref, so you need to free it. * * @return * 1 on success, < 0 on error */ int (*create_file)(IsoNodeBuilder *builder, IsoImage *image, IsoFileSource *src, IsoFile **file); /** * Create a new IsoNode from a IsoFileSource. The type of the node to be * created is determined from the type of the file source. Name, * permissions and other attributes are taken from source file. * But name may be overridden by parameter name if it is not NULL. * * Note that the src is never unref, so you need to free it. * * @return * 1 on success, < 0 on error */ int (*create_node)(IsoNodeBuilder *builder, IsoImage *image, IsoFileSource *src, char *name, IsoNode **node); /** * Free implementation specific data. Should never be called by user. * Use iso_node_builder_unref() instead. */ void (*free)(IsoNodeBuilder *builder); int refcount; void *create_file_data; void *create_node_data; }; void iso_node_builder_ref(IsoNodeBuilder *builder); void iso_node_builder_unref(IsoNodeBuilder *builder); /** * Create a new basic builder ... * * @return * 1 success, < 0 error */ int iso_node_basic_builder_new(IsoNodeBuilder **builder); #endif /*LIBISO_BUILDER_H_*/ libisofs-1.4.2/libisofs/find.c0000644000175700017510000004401612321161425013161 00000000000000/* * Copyright (c) 2008 Vreixo Formoso * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif #include "libisofs.h" #include "node.h" #include #include struct iso_find_condition { /* * Check whether the given node matches this condition. * * @param cond * The condition to check * @param node * The node that should be checked * @return * 1 if the node matches the condition, 0 if not */ int (*matches)(IsoFindCondition *cond, IsoNode *node); /** * Free condition specific data */ void (*free)(IsoFindCondition*); /** condition specific data */ void *data; }; struct find_iter_data { IsoDir *dir; /**< original dir of the iterator */ IsoDirIter *iter; IsoDirIter *itersec; /**< iterator to deal with child dirs */ IsoFindCondition *cond; int err; /**< error? */ IsoNode *current; /**< node to be returned next */ IsoNode *prev; /**< last returned node, needed for removal */ int free_cond; /**< whether to free cond on iter_free */ }; static int get_next(struct find_iter_data *iter, IsoNode **n) { int ret; if (iter->itersec != NULL) { ret = iso_dir_iter_next(iter->itersec, n); if (ret <= 0) { /* secondary item no more needed */ iso_dir_iter_free(iter->itersec); iter->itersec = NULL; } if (ret != 0) { /* succes or error */ return ret; } } /* * we reach here if: * - no secondary item is present * - secondary item has no more items */ while ((ret = iso_dir_iter_next(iter->iter, n)) == 1) { if (iter->cond->matches(iter->cond, *n)) { return ISO_SUCCESS; } else if (ISO_NODE_IS_DIR(*n)) { /* recurse on child dir */ struct find_iter_data *data; ret = iso_dir_find_children((IsoDir*)*n, iter->cond, &iter->itersec); if (ret < 0) { return ret; } data = iter->itersec->data; data->free_cond = 0; /* we don't need sec iter to free cond */ return get_next(iter, n); } } return ret; } static void update_next(IsoDirIter *iter) { int ret; IsoNode *n; struct find_iter_data *data = iter->data; if (data->prev) { iso_node_unref(data->prev); } data->prev = data->current; if (data->itersec == NULL && data->current != NULL && ISO_NODE_IS_DIR(data->current)) { /* we need to recurse on child dir */ struct find_iter_data *data2; ret = iso_dir_find_children((IsoDir*)data->current, data->cond, &data->itersec); if (ret < 0) { data->current = NULL; data->err = ret; return; } data2 = data->itersec->data; data2->free_cond = 0; /* we don't need sec iter to free cond */ } ret = get_next(data, &n); iso_node_unref((IsoNode*)iter->dir); if (ret == 1) { data->current = n; iso_node_ref(n); data->err = 0; iter->dir = n->parent; } else { data->current = NULL; data->err = ret; iter->dir = data->dir; } iso_node_ref((IsoNode*)iter->dir); } static int find_iter_next(IsoDirIter *iter, IsoNode **node) { struct find_iter_data *data; if (iter == NULL || node == NULL) { return ISO_NULL_POINTER; } data = iter->data; if (data->err < 0) { return data->err; } *node = data->current; update_next(iter); return (*node == NULL) ? 0 : ISO_SUCCESS; } static int find_iter_has_next(IsoDirIter *iter) { struct find_iter_data *data = iter->data; return (data->current != NULL); } static void find_iter_free(IsoDirIter *iter) { struct find_iter_data *data = iter->data; if (data->free_cond) { data->cond->free(data->cond); free(data->cond); } iso_node_unref((IsoNode*)data->dir); /* free refs to nodes */ if (data->prev) { iso_node_unref(data->prev); } if (data->current) { iso_node_unref(data->current); } /* free underlying iter */ iso_dir_iter_free(data->iter); free(iter->data); } static int find_iter_take(IsoDirIter *iter) { struct find_iter_data *data = iter->data; if (data->prev == NULL) { return ISO_ERROR; /* next not called or end of dir */ } return iso_node_take(data->prev); } static int find_iter_remove(IsoDirIter *iter) { struct find_iter_data *data = iter->data; if (data->prev == NULL) { return ISO_ERROR; /* next not called or end of dir */ } return iso_node_remove(data->prev); } void find_notify_child_taken(IsoDirIter *iter, IsoNode *node) { struct find_iter_data *data = iter->data; if (data->prev == node) { /* free our ref */ iso_node_unref(node); data->prev = NULL; } else if (data->current == node) { iso_node_unref(node); data->current = NULL; update_next(iter); } } static struct iso_dir_iter_iface find_iter_class = { find_iter_next, find_iter_has_next, find_iter_free, find_iter_take, find_iter_remove, find_notify_child_taken }; int iso_dir_find_children(IsoDir* dir, IsoFindCondition *cond, IsoDirIter **iter) { int ret; IsoDirIter *children; IsoDirIter *it; struct find_iter_data *data; if (dir == NULL || cond == NULL || iter == NULL) { return ISO_NULL_POINTER; } it = malloc(sizeof(IsoDirIter)); if (it == NULL) { return ISO_OUT_OF_MEM; } data = malloc(sizeof(struct find_iter_data)); if (data == NULL) { free(it); return ISO_OUT_OF_MEM; } ret = iso_dir_get_children(dir, &children); if (ret < 0) { free(it); free(data); return ret; } it->class = &find_iter_class; it->dir = (IsoDir*)dir; data->iter = children; data->itersec = NULL; data->cond = cond; data->free_cond = 1; data->err = 0; data->prev = data->current = NULL; it->data = data; if (iso_dir_iter_register(it) < 0) { free(it); return ISO_OUT_OF_MEM; } iso_node_ref((IsoNode*)dir); /* take another ref to the original dir */ data->dir = (IsoDir*)dir; iso_node_ref((IsoNode*)dir); update_next(it); *iter = it; return ISO_SUCCESS; } /*************** find by name wildcard condition *****************/ static int cond_name_matches(IsoFindCondition *cond, IsoNode *node) { char *pattern = (char*) cond->data; int ret = fnmatch(pattern, node->name, 0); return ret == 0 ? 1 : 0; } static void cond_name_free(IsoFindCondition *cond) { free(cond->data); } /** * Create a new condition that checks if the node name matches the given * wildcard. * * @param wildcard * @result * The created IsoFindCondition, NULL on error. * * @since 0.6.4 */ IsoFindCondition *iso_new_find_conditions_name(const char *wildcard) { IsoFindCondition *cond; if (wildcard == NULL) { return NULL; } cond = malloc(sizeof(IsoFindCondition)); if (cond == NULL) { return NULL; } cond->data = strdup(wildcard); cond->free = cond_name_free; cond->matches = cond_name_matches; return cond; } /*************** find by mode condition *****************/ static int cond_mode_matches(IsoFindCondition *cond, IsoNode *node) { mode_t *mask = (mode_t*) cond->data; return node->mode & *mask ? 1 : 0; } static void cond_mode_free(IsoFindCondition *cond) { free(cond->data); } /** * Create a new condition that checks the node mode against a mode mask. It * can be used to check both file type and permissions. * * For example: * * iso_new_find_conditions_mode(S_IFREG) : search for regular files * iso_new_find_conditions_mode(S_IFCHR | S_IWUSR) : search for character * devices where owner has write permissions. * * @param mask * Mode mask to AND against node mode. * @result * The created IsoFindCondition, NULL on error. * * @since 0.6.4 */ IsoFindCondition *iso_new_find_conditions_mode(mode_t mask) { IsoFindCondition *cond; mode_t *data; cond = malloc(sizeof(IsoFindCondition)); if (cond == NULL) { return NULL; } data = malloc(sizeof(mode_t)); if (data == NULL) { free(cond); return NULL; } *data = mask; cond->data = data; cond->free = cond_mode_free; cond->matches = cond_mode_matches; return cond; } /*************** find by gid condition *****************/ static int cond_gid_matches(IsoFindCondition *cond, IsoNode *node) { gid_t *gid = (gid_t*) cond->data; return node->gid == *gid ? 1 : 0; } static void cond_gid_free(IsoFindCondition *cond) { free(cond->data); } /** * Create a new condition that checks the node gid. * * @param gid * Desired Group Id. * @result * The created IsoFindCondition, NULL on error. * * @since 0.6.4 */ IsoFindCondition *iso_new_find_conditions_gid(gid_t gid) { IsoFindCondition *cond; gid_t *data; cond = malloc(sizeof(IsoFindCondition)); if (cond == NULL) { return NULL; } data = malloc(sizeof(gid_t)); if (data == NULL) { free(cond); return NULL; } *data = gid; cond->data = data; cond->free = cond_gid_free; cond->matches = cond_gid_matches; return cond; } /*************** find by uid condition *****************/ static int cond_uid_matches(IsoFindCondition *cond, IsoNode *node) { uid_t *uid = (uid_t*) cond->data; return node->uid == *uid ? 1 : 0; } static void cond_uid_free(IsoFindCondition *cond) { free(cond->data); } /** * Create a new condition that checks the node uid. * * @param uid * Desired User Id. * @result * The created IsoFindCondition, NULL on error. * * @since 0.6.4 */ IsoFindCondition *iso_new_find_conditions_uid(uid_t uid) { IsoFindCondition *cond; uid_t *data; cond = malloc(sizeof(IsoFindCondition)); if (cond == NULL) { return NULL; } data = malloc(sizeof(uid_t)); if (data == NULL) { free(cond); return NULL; } *data = uid; cond->data = data; cond->free = cond_uid_free; cond->matches = cond_uid_matches; return cond; } /*************** find by timestamps condition *****************/ struct cond_times { time_t time; int what_time; /* 0 atime, 1 mtime, 2 ctime */ enum iso_find_comparisons comparison; }; static int cond_time_matches(IsoFindCondition *cond, IsoNode *node) { time_t node_time; struct cond_times *data = cond->data; switch (data->what_time) { case 0: node_time = node->atime; break; case 1: node_time = node->mtime; break; default: node_time = node->ctime; break; } switch (data->comparison) { case ISO_FIND_COND_GREATER: return node_time > data->time ? 1 : 0; case ISO_FIND_COND_GREATER_OR_EQUAL: return node_time >= data->time ? 1 : 0; case ISO_FIND_COND_EQUAL: return node_time == data->time ? 1 : 0; case ISO_FIND_COND_LESS: return node_time < data->time ? 1 : 0; case ISO_FIND_COND_LESS_OR_EQUAL: return node_time <= data->time ? 1 : 0; } /* should never happen */ return 0; } static void cond_time_free(IsoFindCondition *cond) { free(cond->data); } /** * Create a new condition that checks the time of last access. * * @param time * Time to compare against IsoNode atime. * @param comparison * Comparison to be done between IsoNode atime and submitted time. * Note that ISO_FIND_COND_GREATER, for example, is true if the node * time is greater than the submitted time. * @result * The created IsoFindCondition, NULL on error. * * @since 0.6.4 */ IsoFindCondition *iso_new_find_conditions_atime(time_t time, enum iso_find_comparisons comparison) { IsoFindCondition *cond; struct cond_times *data; cond = malloc(sizeof(IsoFindCondition)); if (cond == NULL) { return NULL; } data = malloc(sizeof(struct cond_times)); if (data == NULL) { free(cond); return NULL; } data->time = time; data->comparison = comparison; data->what_time = 0; /* atime */ cond->data = data; cond->free = cond_time_free; cond->matches = cond_time_matches; return cond; } /** * Create a new condition that checks the time of last modification. * * @param time * Time to compare against IsoNode mtime. * @param comparison * Comparison to be done between IsoNode mtime and submitted time. * Note that ISO_FIND_COND_GREATER, for example, is true if the node * time is greater than the submitted time. * @result * The created IsoFindCondition, NULL on error. * * @since 0.6.4 */ IsoFindCondition *iso_new_find_conditions_mtime(time_t time, enum iso_find_comparisons comparison) { IsoFindCondition *cond; struct cond_times *data; cond = malloc(sizeof(IsoFindCondition)); if (cond == NULL) { return NULL; } data = malloc(sizeof(struct cond_times)); if (data == NULL) { free(cond); return NULL; } data->time = time; data->comparison = comparison; data->what_time = 1; /* mtime */ cond->data = data; cond->free = cond_time_free; cond->matches = cond_time_matches; return cond; } /** * Create a new condition that checks the time of last status change. * * @param time * Time to compare against IsoNode ctime. * @param comparison * Comparison to be done between IsoNode ctime and submitted time. * Note that ISO_FIND_COND_GREATER, for example, is true if the node * time is greater than the submitted time. * @result * The created IsoFindCondition, NULL on error. * * @since 0.6.4 */ IsoFindCondition *iso_new_find_conditions_ctime(time_t time, enum iso_find_comparisons comparison) { IsoFindCondition *cond; struct cond_times *data; cond = malloc(sizeof(IsoFindCondition)); if (cond == NULL) { return NULL; } data = malloc(sizeof(struct cond_times)); if (data == NULL) { free(cond); return NULL; } data->time = time; data->comparison = comparison; data->what_time = 2; /* ctime */ cond->data = data; cond->free = cond_time_free; cond->matches = cond_time_matches; return cond; } /*************** logical operations on conditions *****************/ struct logical_binary_conditions { IsoFindCondition *a; IsoFindCondition *b; }; static void cond_logical_binary_free(IsoFindCondition *cond) { struct logical_binary_conditions *data; data = cond->data; data->a->free(data->a); free(data->a); data->b->free(data->b); free(data->b); free(cond->data); } static int cond_logical_and_matches(IsoFindCondition *cond, IsoNode *node) { struct logical_binary_conditions *data = cond->data; return data->a->matches(data->a, node) && data->b->matches(data->b, node); } /** * Create a new condition that check if the two given conditions are * valid. * * @param a * @param b * IsoFindCondition to compare * @result * The created IsoFindCondition, NULL on error. * * @since 0.6.4 */ IsoFindCondition *iso_new_find_conditions_and(IsoFindCondition *a, IsoFindCondition *b) { IsoFindCondition *cond; struct logical_binary_conditions *data; cond = malloc(sizeof(IsoFindCondition)); if (cond == NULL) { return NULL; } data = malloc(sizeof(struct logical_binary_conditions)); if (data == NULL) { free(cond); return NULL; } data->a = a; data->b = b; cond->data = data; cond->free = cond_logical_binary_free; cond->matches = cond_logical_and_matches; return cond; } static int cond_logical_or_matches(IsoFindCondition *cond, IsoNode *node) { struct logical_binary_conditions *data = cond->data; return data->a->matches(data->a, node) || data->b->matches(data->b, node); } /** * Create a new condition that check if at least one the two given conditions * is valid. * * @param a * @param b * IsoFindCondition to compare * @result * The created IsoFindCondition, NULL on error. * * @since 0.6.4 */ IsoFindCondition *iso_new_find_conditions_or(IsoFindCondition *a, IsoFindCondition *b) { IsoFindCondition *cond; struct logical_binary_conditions *data; cond = malloc(sizeof(IsoFindCondition)); if (cond == NULL) { return NULL; } data = malloc(sizeof(struct logical_binary_conditions)); if (data == NULL) { free(cond); return NULL; } data->a = a; data->b = b; cond->data = data; cond->free = cond_logical_binary_free; cond->matches = cond_logical_or_matches; return cond; } static void cond_not_free(IsoFindCondition *cond) { IsoFindCondition *negate = cond->data; negate->free(negate); free(negate); } static int cond_not_matches(IsoFindCondition *cond, IsoNode *node) { IsoFindCondition *negate = cond->data; return !(negate->matches(negate, node)); } /** * Create a new condition that check if the given conditions is false. * * @param negate * @result * The created IsoFindCondition, NULL on error. * * @since 0.6.4 */ IsoFindCondition *iso_new_find_conditions_not(IsoFindCondition *negate) { IsoFindCondition *cond; cond = malloc(sizeof(IsoFindCondition)); if (cond == NULL) { return NULL; } cond->data = negate; cond->free = cond_not_free; cond->matches = cond_not_matches; return cond; } libisofs-1.4.2/libisofs/messages.c0000644000175700017510000006524512606500554014065 00000000000000/* * Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2009 - 2015 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif #include #include #include #include #include #ifdef Xorriso_standalonE #ifdef Xorriso_with_libjtE #include "../libjte/libjte.h" #endif #else #ifdef Libisofs_with_libjtE #include #endif #endif /* ! Xorriso_standalonE */ #include "libiso_msgs.h" #include "libisofs.h" #include "messages.h" #include "util.h" #include "node.h" #include "stream.h" /* * error codes are 32 bit numbers, that follow the following conventions: * * bit 31 (MSB) -> 1 (to make the value always negative) * bits 30-24 -> Encoded severity (Use ISO_ERR_SEV to translate an error code * to a LIBISO_MSGS_SEV_* constant) * = 0x10 -> DEBUG * = 0x20 -> UPDATE * = 0x30 -> NOTE * = 0x40 -> HINT * = 0x50 -> WARNING * = 0x60 -> SORRY * = 0x64 -> MISHAP * = 0x68 -> FAILURE * = 0x70 -> FATAL * = 0x71 -> ABORT * bits 23-20 -> Encoded priority (Use ISO_ERR_PRIO to translate an error code * to a LIBISO_MSGS_PRIO_* constant) * = 0x0 -> ZERO * = 0x1 -> LOW * = 0x2 -> MEDIUM * = 0x3 -> HIGH * bits 19-16 -> Reserved for future usage (maybe message ranges) * bits 15-0 -> Error code */ #define ISO_ERR_SEV(e) (e & 0x7F000000) #define ISO_ERR_PRIO(e) ((e & 0x00700000) << 8) #define ISO_ERR_CODE(e) ((e & 0x0000FFFF) | 0x00030000) int iso_message_id = LIBISO_MSGS_ORIGIN_IMAGE_BASE; /** * Threshold for aborting. */ int abort_threshold = LIBISO_MSGS_SEV_FAILURE; #define MAX_MSG_LEN 4096 struct libiso_msgs *libiso_msgr = NULL; /* ------------- List of xinfo clone functions ----------- */ struct iso_xinfo_cloner_assoc { iso_node_xinfo_func proc; iso_node_xinfo_cloner cloner; struct iso_xinfo_cloner_assoc *next; }; struct iso_xinfo_cloner_assoc *iso_xinfo_cloner_list = NULL; /* API */ int iso_node_xinfo_make_clonable(iso_node_xinfo_func proc, iso_node_xinfo_cloner cloner, int flag) { struct iso_xinfo_cloner_assoc *assoc; /* Look for existing assoc of proc */ for (assoc = iso_xinfo_cloner_list; assoc != NULL; assoc = assoc->next) if (assoc->proc == proc) break; if (assoc == NULL) { assoc = calloc(1, sizeof(struct iso_xinfo_cloner_assoc)); if (assoc == NULL) return ISO_OUT_OF_MEM; assoc->proc = proc; assoc->next = iso_xinfo_cloner_list; iso_xinfo_cloner_list = assoc; } assoc->cloner = cloner; return ISO_SUCCESS; } /* API */ int iso_node_xinfo_get_cloner(iso_node_xinfo_func proc, iso_node_xinfo_cloner *cloner, int flag) { struct iso_xinfo_cloner_assoc *assoc; *cloner = NULL; for (assoc = iso_xinfo_cloner_list; assoc != NULL; assoc = assoc->next) { if (assoc->proc != proc) continue; *cloner = assoc->cloner; return 1; } return 0; } static int iso_node_xinfo_dispose_cloners(int flag) { struct iso_xinfo_cloner_assoc *assoc, *next; for (assoc = iso_xinfo_cloner_list; assoc != NULL; assoc = next) { next = assoc->next; free((char *) assoc); } iso_xinfo_cloner_list= NULL; return(1); } /* ------------- End of xinfo clone functions list ----------- */ /* @param flag bit0= do not set up locale by LC_* environment variables */ int iso_init_with_flag(int flag) { int ret; #ifdef Libisofs_with_libjtE /* Ugly compile time check for header version compatibility. If everthing matches, then it produces no C code. In case of mismatch, intentionally faulty C code will be inserted. */ /* The indendation is an advise of man gcc to help old compilers ignoring */ #if iso_libjte_req_major > LIBJTE_VERSION_MAJOR #define Libisofs_libjte_dot_h_too_olD 1 #endif #if iso_libjte_req_major == LIBJTE_VERSION_MAJOR && iso_libjte_req_minor > LIBJTE_VERSION_MINOR #define Libisofs_libjte_dot_h_too_olD 1 #endif #if iso_libjte_req_minor == LIBJTE_VERSION_MINOR && iso_libjte_req_micro > LIBJTE_VERSION_MICRO #define Libisofs_libjte_dot_h_too_olD 1 #endif #ifdef Libisofs_libjte_dot_h_too_olD LIBJTE_MISCONFIGURATION = 0; INTENTIONAL_ABORT_OF_COMPILATION__HEADERFILE_libjte_dot_h_TOO_OLD__SEE_libisofs_dot_h_AND_messages_c = 0; LIBJTE_MISCONFIGURATION_ = 0; #endif if (! libjte__is_compatible(LIBJTE_VERSION_MAJOR, LIBJTE_VERSION_MINOR, LIBJTE_VERSION_MICRO, 0)) { fprintf(stderr, "\nlibisofs: libjte TOO OLD ! Need at least libjte-%d.%d.%d\n\n", LIBJTE_VERSION_MAJOR, LIBJTE_VERSION_MINOR, LIBJTE_VERSION_MICRO); return ISO_FATAL_ERROR; } #endif /* Libisofs_with_libjtE */ if (! (flag & 1)) { iso_init_locale(0); } if (libiso_msgr == NULL) { if (libiso_msgs_new(&libiso_msgr, 0) <= 0) return ISO_FATAL_ERROR; } libiso_msgs_set_severities(libiso_msgr, LIBISO_MSGS_SEV_NEVER, LIBISO_MSGS_SEV_FATAL, "libisofs: ", 0); ret = iso_node_xinfo_make_clonable(aaip_xinfo_func, aaip_xinfo_cloner, 0); if (ret < 0) return ret; ret = iso_node_xinfo_make_clonable(checksum_cx_xinfo_func, checksum_cx_xinfo_cloner, 0); if (ret < 0) return ret; ret = iso_node_xinfo_make_clonable(checksum_md5_xinfo_func, checksum_md5_xinfo_cloner, 0); if (ret < 0) return ret; ret = iso_node_xinfo_make_clonable(zisofs_zf_xinfo_func, zisofs_zf_xinfo_cloner, 0); if (ret < 0) return ret; ret = iso_node_xinfo_make_clonable(iso_px_ino_xinfo_func, iso_px_ino_xinfo_cloner, 0); if (ret < 0) return ret; ret = iso_node_xinfo_make_clonable(iso_hfsplus_xinfo_func, iso_hfsplus_xinfo_cloner, 0); if (ret < 0) return ret; return 1; } int iso_init() { return iso_init_with_flag(0); } void iso_finish() { libiso_msgs_destroy(&libiso_msgr, 0); iso_node_xinfo_dispose_cloners(0); iso_stream_destroy_cmpranks(0); } int iso_set_abort_severity(char *severity) { int ret, sevno; ret = libiso_msgs__text_to_sev(severity, &sevno, 0); if (ret <= 0) return ISO_WRONG_ARG_VALUE; if (sevno > LIBISO_MSGS_SEV_FAILURE || sevno < LIBISO_MSGS_SEV_NOTE) return ISO_WRONG_ARG_VALUE; ret = abort_threshold; abort_threshold = sevno; return ret; } void iso_msg_debug(int imgid, const char *fmt, ...) { char *msg = NULL; va_list ap; LIBISO_ALLOC_MEM_VOID(msg, char, MAX_MSG_LEN); va_start(ap, fmt); vsnprintf(msg, MAX_MSG_LEN, fmt, ap); va_end(ap); libiso_msgs_submit(libiso_msgr, imgid, 0x00000002, LIBISO_MSGS_SEV_DEBUG, LIBISO_MSGS_PRIO_ZERO, msg, 0, 0); ex:; LIBISO_FREE_MEM(msg); } const char *iso_error_to_msg(int errcode) { switch(errcode) { case ISO_CANCELED: return "Operation canceled"; case ISO_FATAL_ERROR: return "Unknown or unexpected fatal error"; case ISO_ERROR: return "Unknown or unexpected error"; case ISO_ASSERT_FAILURE: return "Internal programming error. Please report this bug"; case ISO_NULL_POINTER: return "NULL pointer as value for an arg. that does not allow NULL"; case ISO_OUT_OF_MEM: return "Memory allocation error"; case ISO_INTERRUPTED: return "Interrupted by a signal"; case ISO_WRONG_ARG_VALUE: return "Invalid parameter value"; case ISO_THREAD_ERROR: return "Cannot create a needed thread"; case ISO_WRITE_ERROR: return "Write error"; case ISO_BUF_READ_ERROR: return "Buffer read error"; case ISO_NODE_ALREADY_ADDED: return "Trying to add to a dir a node already added to a dir"; case ISO_NODE_NAME_NOT_UNIQUE: return "Node with same name already exists"; case ISO_NODE_NOT_ADDED_TO_DIR: return "Trying to remove a node that was not added to dir"; case ISO_NODE_DOESNT_EXIST: return "A requested node does not exist"; case ISO_IMAGE_ALREADY_BOOTABLE: return "Try to set the boot image of an already bootable image"; case ISO_BOOT_IMAGE_NOT_VALID: return "Trying to use an invalid file as boot image"; case ISO_BOOT_IMAGE_OVERFLOW: return "Too many boot images added"; case ISO_FILE_ERROR: return "Error on file operation"; case ISO_FILE_ALREADY_OPENED: return "Trying to open an already opened file"; case ISO_FILE_ACCESS_DENIED: return "Access to file is not allowed"; case ISO_FILE_BAD_PATH: return "Incorrect path to file"; case ISO_FILE_DOESNT_EXIST: return "The file does not exist in the filesystem"; case ISO_FILE_NOT_OPENED: return "Trying to read or close a file not opened"; case ISO_FILE_IS_DIR: return "Directory used where no dir is expected"; case ISO_FILE_READ_ERROR: return "Read error"; case ISO_FILE_IS_NOT_DIR: return "Not dir used where a dir is expected"; case ISO_FILE_IS_NOT_SYMLINK: return "Not symlink used where a symlink is expected"; case ISO_FILE_SEEK_ERROR: return "Cannot seek to specified location"; case ISO_FILE_IGNORED: return "File not supported in ECMA-119 tree and thus ignored"; case ISO_FILE_TOO_BIG: return "A file is bigger than supported by used standard"; case ISO_FILE_CANT_WRITE: return "File read error during image creation"; case ISO_FILENAME_WRONG_CHARSET: case ISO_FILENAME_WRONG_CHARSET_OLD: return "Cannot convert filename to requested charset"; case ISO_FILE_CANT_ADD: return "File cannot be added to the tree"; case ISO_FILE_IMGPATH_WRONG: return "File path break specification constraints and will be ignored"; case ISO_CHARSET_CONV_ERROR: return "Charset conversion error"; case ISO_MANGLE_TOO_MUCH_FILES: return "Too much files to mangle, cannot guarantee unique file names"; case ISO_WRONG_PVD: return "Wrong or damaged Primary Volume Descriptor"; case ISO_WRONG_RR: return "Wrong or damaged Rock Ridge entry"; case ISO_UNSUPPORTED_RR: return "Unsupported Rock Ridge feature"; case ISO_WRONG_ECMA119: return "Wrong or damaged ECMA-119"; case ISO_UNSUPPORTED_ECMA119: return "Unsupported ECMA-119 feature"; case ISO_WRONG_EL_TORITO: return "Wrong or damaged El-Torito catalog"; case ISO_UNSUPPORTED_EL_TORITO: return "Unsupported El-Torito feature"; case ISO_ISOLINUX_CANT_PATCH: return "Cannot patch isolinux boot image"; case ISO_UNSUPPORTED_SUSP: return "Unsupported SUSP feature"; case ISO_WRONG_RR_WARN: return "Error on a Rock Ridge entry that can be ignored"; case ISO_SUSP_UNHANDLED: return "Unhandled SUSP entry"; case ISO_SUSP_MULTIPLE_ER: return "Multiple ER SUSP entries found"; case ISO_UNSUPPORTED_VD: return "Unsupported volume descriptor found"; case ISO_EL_TORITO_WARN: return "El-Torito related warning"; case ISO_IMAGE_WRITE_CANCELED: return "Image write cancelled"; case ISO_EL_TORITO_HIDDEN: return "El-Torito image is hidden"; case ISO_DATA_SOURCE_SORRY: case ISO_DATA_SOURCE_MISHAP: case ISO_DATA_SOURCE_FAILURE: case ISO_DATA_SOURCE_FATAL: return "Read error occured with IsoDataSource"; case ISO_AAIP_IGNORED: return "AAIP info with ACL or xattr in ISO image will be ignored"; case ISO_AAIP_BAD_ACL: return "Error with decoding ACL from AAIP info"; case ISO_AAIP_BAD_ACL_TEXT: return "Error with encoding ACL for AAIP"; case ISO_AAIP_NOT_ENABLED: return "AAIP processing for ACL or xattr not enabled at compile time"; case ISO_AAIP_BAD_AASTRING: return "Error with decoding AAIP info for ACL or xattr"; case ISO_AAIP_NO_GET_LOCAL: return "Error with reading ACL or xattr from local file"; case ISO_AAIP_NO_SET_LOCAL: return "Error with attaching ACL or xattr to local file"; case ISO_AAIP_NON_USER_NAME: return "Unallowed attempt to set an xattr with non-userspace name"; case ISO_EXTF_TOO_OFTEN: return "Too many references on a single external filter command"; case ISO_ZLIB_NOT_ENABLED: return "Use of zlib was not enabled at compile time"; case ISO_ZISOFS_TOO_LARGE: return "Cannot apply zisofs filter to file >= 4 GiB"; case ISO_FILTER_WRONG_INPUT: return "Filter input differs from previous run"; case ISO_ZLIB_COMPR_ERR: return "zlib compression/decompression error"; case ISO_ZISOFS_WRONG_INPUT: return "Input stream is not in zisofs format"; case ISO_ZISOFS_PARAM_LOCK: return "Cannot set global zisofs parameters while filters exist"; case ISO_ZLIB_EARLY_EOF: return "Premature EOF of zlib input stream"; case ISO_MD5_AREA_CORRUPTED: return "Checksum area or checksum tag appear corrupted"; case ISO_MD5_TAG_MISMATCH: return "Checksum mismatch between checksum tag and data blocks"; case ISO_SB_TREE_CORRUPTED: return "Checksum mismatch in System Area, Volume Descriptors, or directory tree"; case ISO_MD5_TAG_UNEXPECTED: return "Unexpected checksum tag type encountered"; case ISO_MD5_TAG_MISPLACED: return "Misplaced checksum tag type encountered"; case ISO_MD5_TAG_OTHER_RANGE: return "Checksum tag with unexpected address range encountered"; case ISO_MD5_STREAM_CHANGE: return "Detected file content changes while it was written into the image"; case ISO_SCDBACKUP_TAG_NOT_0: return "Session does not start at LBA 0. scdbackup checksum tag not written."; case ISO_BOOT_NO_CATALOG: return "No boot catalog created yet"; case ISO_OVWRT_MS_TOO_SMALL: return "Multi-session offset too small for overwrite buffer"; case ISO_PART_OFFST_TOO_SMALL: return "Partition offset too small for first tree root."; case ISO_OVWRT_FIFO_TOO_SMALL: return "The ring buffer is too small for overwrite buffer"; case ISO_LIBJTE_NOT_ENABLED: return "Use of libjte was not enabled at compile time"; case ISO_LIBJTE_START_FAILED: return "Failed to start up Jigdo Template Extraction"; case ISO_LIBJTE_END_FAILED: return "Failed to finish Jigdo Template Extraction"; case ISO_LIBJTE_FILE_FAILED: return "Failed to process file for Jigdo Template Extraction"; case ISO_BOOT_TOO_MANY_MIPS: return "Too many MIPS Big Endian boot files given (max. 15)"; case ISO_BOOT_FILE_MISSING: return "Boot file missing in image"; case ISO_BAD_PARTITION_NO: return "Partition number out of range"; case ISO_BAD_PARTITION_FILE: return "Cannot open data file for appended partition"; case ISO_NON_MBR_SYS_AREA: return "May not combine MBR partition with non-MBR system area"; case ISO_DISPLACE_ROLLOVER: return "Displacement offset leads outside 32 bit range"; case ISO_NAME_NEEDS_TRANSL: return "File name cannot be written into ECMA-119 untranslated"; case ISO_STREAM_NO_CLONE: return "Data file input stream object offers no cloning method"; case ISO_XINFO_NO_CLONE: return "Extended information class offers no cloning method"; case ISO_MD5_TAG_COPIED: return "Found copied superblock checksum tag"; case ISO_RR_NAME_TOO_LONG: return "Rock Ridge leaf name too long"; case ISO_RR_NAME_RESERVED: return "Reserved Rock Ridge leaf name"; case ISO_RR_PATH_TOO_LONG: return "Rock Ridge path too long"; case ISO_AAIP_BAD_ATTR_NAME: return "Attribute name cannot be represented"; case ISO_AAIP_ACL_MULT_OBJ: return "ACL text contains multiple entries of user::, group::, other::"; case ISO_SECT_SCATTERED: return "File sections do not form consecutive array of blocks"; case ISO_BOOT_TOO_MANY_APM: return "Too many Apple Partition Map entries requested"; case ISO_BOOT_APM_OVERLAP: return "Overlapping Apple Partition Map entries requested"; case ISO_BOOT_TOO_MANY_GPT: return "Too many GPT entries requested"; case ISO_BOOT_GPT_OVERLAP: return "Overlapping GPT entries requested"; case ISO_BOOT_TOO_MANY_MBR: return "Too many MBR partition entries requested"; case ISO_BOOT_MBR_OVERLAP: return "Overlapping MBR partition entries requested"; case ISO_BOOT_MBR_COLLISION: return "Attempt to use an MBR partition entry twice"; case ISO_BOOT_NO_EFI_ELTO: return "No suitable El Torito EFI boot image for exposure as GPT partition"; case ISO_BOOT_HFSP_BAD_BSIZE: return "Not a supported HFS+ or APM block size"; case ISO_BOOT_APM_GPT_BSIZE: return "APM block size prevents coexistence with GPT"; case ISO_HFSP_NO_MANGLE: return "Name collision in HFS+, mangling not possible"; case ISO_DEAD_SYMLINK: return "Symbolic link cannot be resolved"; case ISO_DEEP_SYMLINK: return "Too many chained symbolic links"; case ISO_BAD_ISO_FILETYPE: return "Unrecognized file type in ISO image"; case ISO_NAME_NOT_UCS2: return "Filename not suitable for character set UCS-2"; case ISO_IMPORT_COLLISION: return "File name collision during ISO image import"; case ISO_HPPA_PALO_INCOMPL: return "Incomplete HP-PA PALO boot parameters"; case ISO_HPPA_PALO_OFLOW: return "HP-PA PALO boot address exceeds 2 GB"; case ISO_HPPA_PALO_NOTREG: return "HP-PA PALO file is not a data file"; case ISO_HPPA_PALO_CMDLEN: return "HP-PA PALO command line too long"; case ISO_SYSAREA_PROBLEMS: return "Problems encountered during inspection of System Area"; case ISO_INQ_SYSAREA_PROP: return "Unrecognized inquiry for system area property"; case ISO_ALPHA_BOOT_NOTREG: return "DEC Alpha Boot Loader file is not a data file"; case ISO_NO_KEPT_DATA_SRC: return "No data source of imported ISO image available"; case ISO_MALFORMED_READ_INTVL: return "Malformed description string for interval reader"; case ISO_INTVL_READ_PROBLEM: return "Unreadable file, premature EOF, or failure to seek for interval reader"; case ISO_NOT_REPRODUCIBLE: return "Cannot arrange content of data files in surely reproducible way"; case ISO_PATCH_FILTERED_BOOT: return "May not write boot info into filtered stream of boot image"; case ISO_PATCH_OVERSIZED_BOOT: return "Boot image to large to buffer for writing boot info"; case ISO_RR_NAME_TRUNCATED: return "File name had to be truncated and MD5 marked"; case ISO_TRUNCATE_ISOFSNT: return "File name truncation length changed by loaded image info"; case ISO_GENERAL_NOTE: return "A general note message was issued"; case ISO_BAD_FSRC_FILETYPE: return "Unrecognized file type of IsoFileSrc object"; default: return "Unknown error"; } } int iso_msg_is_abort(int errcode) { if (ISO_ERR_SEV(errcode) >= abort_threshold) return 1; return 0; } int iso_msg_submit(int imgid, int errcode, int causedby, const char *fmt, ...) { char msg[MAX_MSG_LEN]; va_list ap; /* when called with ISO_CANCELED, we don't need to submit any message */ if (errcode == (int) ISO_CANCELED && fmt == NULL) { return ISO_CANCELED; } if (fmt) { va_start(ap, fmt); vsnprintf(msg, MAX_MSG_LEN, fmt, ap); va_end(ap); } else { strncpy(msg, iso_error_to_msg(errcode), MAX_MSG_LEN - 1); msg[MAX_MSG_LEN - 1] = 0; } libiso_msgs_submit(libiso_msgr, imgid, ISO_ERR_CODE(errcode), ISO_ERR_SEV(errcode), ISO_ERR_PRIO(errcode), msg, 0, 0); if (causedby != 0) { snprintf(msg, MAX_MSG_LEN, " > Caused by: %s", iso_error_to_msg(causedby)); libiso_msgs_submit(libiso_msgr, imgid, ISO_ERR_CODE(causedby), LIBISO_MSGS_SEV_NOTE, LIBISO_MSGS_PRIO_LOW, msg, 0, 0); if (ISO_ERR_SEV(causedby) == LIBISO_MSGS_SEV_FATAL) { return ISO_CANCELED; } } if (iso_msg_is_abort(errcode)) { return ISO_CANCELED; } else { return 0; } } /** * Control queueing and stderr printing of messages from libisofs. * Severity may be one of "NEVER", "FATAL", "SORRY", "WARNING", "HINT", * "NOTE", "UPDATE", "DEBUG", "ALL". * * @param queue_severity Gives the minimum limit for messages to be queued. * Default: "NEVER". If you queue messages then you * must consume them by iso_msgs_obtain(). * @param print_severity Does the same for messages to be printed directly * to stderr. * @param print_id A text prefix to be printed before the message. * @return >0 for success, <=0 for error */ int iso_set_msgs_severities(char *queue_severity, char *print_severity, char *print_id) { int ret, queue_sevno, print_sevno; ret = libiso_msgs__text_to_sev(queue_severity, &queue_sevno, 0); if (ret <= 0) return 0; ret = libiso_msgs__text_to_sev(print_severity, &print_sevno, 0); if (ret <= 0) return 0; ret = libiso_msgs_set_severities(libiso_msgr, queue_sevno, print_sevno, print_id, 0); if (ret <= 0) return 0; return 1; } /** * Obtain the oldest pending libisofs message from the queue which has at * least the given minimum_severity. This message and any older message of * lower severity will get discarded from the queue and is then lost forever. * * Severity may be one of "NEVER", "FATAL", "SORRY", "WARNING", "HINT", * "NOTE", "UPDATE", "DEBUG", "ALL". To call with minimum_severity "NEVER" * will discard the whole queue. * * @param error_code Will become a unique error code as listed in messages.h * @param imgid Id of the image that was issued the message. * @param msg_text Must provide at least ISO_MSGS_MESSAGE_LEN bytes. * @param severity Will become the severity related to the message and * should provide at least 80 bytes. * @return 1 if a matching item was found, 0 if not, <0 for severe errors */ int iso_obtain_msgs(char *minimum_severity, int *error_code, int *imgid, char msg_text[], char severity[]) { int ret, minimum_sevno, sevno, priority, os_errno; double timestamp; pid_t pid; char *textpt, *sev_name; struct libiso_msgs_item *item= NULL; ret = libiso_msgs__text_to_sev(minimum_severity, &minimum_sevno, 0); if (ret <= 0) return 0; ret = libiso_msgs_obtain(libiso_msgr, &item, minimum_sevno, LIBISO_MSGS_PRIO_ZERO, 0); if (ret <= 0) goto ex; ret = libiso_msgs_item_get_msg(item, error_code, &textpt, &os_errno, 0); if (ret <= 0) goto ex; strncpy(msg_text, textpt, ISO_MSGS_MESSAGE_LEN-1); if (strlen(textpt) >= ISO_MSGS_MESSAGE_LEN) msg_text[ISO_MSGS_MESSAGE_LEN-1] = 0; ret = libiso_msgs_item_get_origin(item, ×tamp, &pid, imgid, 0); if (ret <= 0) goto ex; severity[0]= 0; ret = libiso_msgs_item_get_rank(item, &sevno, &priority, 0); if (ret <= 0) goto ex; ret = libiso_msgs__sev_to_text(sevno, &sev_name, 0); if (ret <= 0) goto ex; strcpy(severity, sev_name); ret = 1; ex: ; libiso_msgs_destroy_item(libiso_msgr, &item, 0); return ret; } int iso_msgs_submit(int error_code, char msg_text[], int os_errno, char severity[], int origin) { int ret, sevno; ret = libiso_msgs__text_to_sev(severity, &sevno, 0); if (ret <= 0) sevno = LIBISO_MSGS_SEV_ALL; if (error_code <= 0) { switch(sevno) { case LIBISO_MSGS_SEV_ABORT: error_code = 0x00040000; break; case LIBISO_MSGS_SEV_FATAL: error_code = 0x00040001; break; case LIBISO_MSGS_SEV_SORRY: error_code = 0x00040002; break; case LIBISO_MSGS_SEV_WARNING: error_code = 0x00040003; break; case LIBISO_MSGS_SEV_HINT: error_code = 0x00040004; break; case LIBISO_MSGS_SEV_NOTE: error_code = 0x00040005; break; case LIBISO_MSGS_SEV_UPDATE: error_code = 0x00040006; break; case LIBISO_MSGS_SEV_DEBUG: error_code = 0x00040007; break; default: error_code = 0x00040008; } } ret = libiso_msgs_submit(libiso_msgr, origin, error_code, sevno, LIBISO_MSGS_PRIO_HIGH, msg_text, os_errno, 0); return ret; } int iso_text_to_sev(char *severity_name, int *sevno) { int ret; ret = libiso_msgs__text_to_sev(severity_name, sevno, 0); if (ret <= 0) *sevno = LIBISO_MSGS_SEV_FATAL; return ret; } int iso_sev_to_text(int severity_number, char **severity_name) { int ret; ret = libiso_msgs__sev_to_text(severity_number, severity_name, 0); return ret; } /** * Return the messenger object handle used by libisofs. This handle * may be used by related libraries to their own compatible * messenger objects and thus to direct their messages to the libisofs * message queue. See also: libburn, API function burn_set_messenger(). * * @return the handle. Do only use with compatible */ void *iso_get_messenger() { return libiso_msgr; } int iso_error_get_severity(int e) { return ISO_ERR_SEV(e); } int iso_error_get_priority(int e) { return ISO_ERR_PRIO(e); } int iso_error_get_code(int e) { return ISO_ERR_CODE(e); } int iso_report_errfile(char *path, int error_code, int os_errno, int flag) { libiso_msgs_submit(libiso_msgr, 0, error_code, LIBISO_MSGS_SEV_ERRFILE, LIBISO_MSGS_PRIO_HIGH, path, os_errno, 0); return(1); } int iso_libjte_forward_msgs(void *libjte_handle, int imgid, int errcode, int flag) { #ifdef Libisofs_with_libjtE char *msg = NULL; int res; struct libjte_env *handle = (struct libjte_env *) libjte_handle; res = ISO_SUCCESS; while(1) { msg= libjte_get_next_message(handle); if(msg == NULL) break; res = iso_msg_submit(imgid, errcode, 0, msg); free(msg); } return res; #else /* Libisofs_with_libjtE */ return ISO_SUCCESS; #endif /* ! Libisofs_with_libjtE */ } libisofs-1.4.2/libisofs/fsource.c0000644000175700017510000000505312321161425013705 00000000000000/* * Copyright (c) 2007 Vreixo Formoso * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif #include "fsource.h" #include /** * Values belong 1000 are reserved for libisofs usage */ unsigned int iso_fs_global_id = 1000; void iso_file_source_ref(IsoFileSource *src) { ++src->refcount; } void iso_file_source_unref(IsoFileSource *src) { if (--src->refcount == 0) { src->class->free(src); free(src); } } void iso_filesystem_ref(IsoFilesystem *fs) { ++fs->refcount; } void iso_filesystem_unref(IsoFilesystem *fs) { if (--fs->refcount == 0) { fs->free(fs); free(fs); } } /* * this are just helpers to invoque methods in class */ inline char* iso_file_source_get_path(IsoFileSource *src) { return src->class->get_path(src); } inline char* iso_file_source_get_name(IsoFileSource *src) { return src->class->get_name(src); } inline int iso_file_source_lstat(IsoFileSource *src, struct stat *info) { return src->class->lstat(src, info); } inline int iso_file_source_access(IsoFileSource *src) { return src->class->access(src); } inline int iso_file_source_stat(IsoFileSource *src, struct stat *info) { return src->class->stat(src, info); } inline int iso_file_source_open(IsoFileSource *src) { return src->class->open(src); } inline int iso_file_source_close(IsoFileSource *src) { return src->class->close(src); } inline int iso_file_source_read(IsoFileSource *src, void *buf, size_t count) { return src->class->read(src, buf, count); } inline off_t iso_file_source_lseek(IsoFileSource *src, off_t offset, int flag) { return src->class->lseek(src, offset, flag); } inline int iso_file_source_readdir(IsoFileSource *src, IsoFileSource **child) { return src->class->readdir(src, child); } inline int iso_file_source_readlink(IsoFileSource *src, char *buf, size_t bufsiz) { return src->class->readlink(src, buf, bufsiz); } inline IsoFilesystem* iso_file_source_get_filesystem(IsoFileSource *src) { return src->class->get_filesystem(src); } inline int iso_file_source_get_aa_string(IsoFileSource *src, unsigned char **aa_string, int flag) { if (src->class->version < 1) { *aa_string = NULL; return 1; } return src->class->get_aa_string(src, aa_string, flag); } libisofs-1.4.2/libisofs/aaip-os-dummy.c0000644000175700017510000000630612557152622014735 00000000000000 /* aaip-os-dummy.c Idle placeholder for: Arbitrary Attribute Interchange Protocol , system adapter for getting and setting of ACLs and xattr. See aaip-os-linux.c for a real implementation of this interface. To be included by aaip_0_2.c Copyright (c) 2009 - 2011 Thomas Schmitt, libburnia project, GPLv2+ */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif #include #include #include #include #include #include #include /* ------------------------------ Inquiry --------------------------------- */ /* See also API iso_local_attr_support(). @param flag Bitfield for control purposes bit0= inquire availability of ACL bit1= inquire availability of xattr bit2 - bit7= Reserved for future types. It is permissibile to set them to 1 already now. bit8 and higher: reserved, submit 0 @return Bitfield corresponding to flag. bit0= ACL adapter is enabled bit1= xattr adapter is enabled bit2 - bit7= Reserved for future types. bit8 and higher: reserved, do not interpret these */ int aaip_local_attr_support(int flag) { return(0); } /* ------------------------------ Getters --------------------------------- */ /* Obtain the ACL of the given file in long text form. @return 0 ACL support not enabled at compile time */ int aaip_get_acl_text(char *path, char **text, int flag) { return(0); } /* Obtain the Extended Attributes and/or the ACLs of the given file in a form that is ready for aaip_encode(). @return 1 ok */ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names, size_t **value_lengths, char ***values, int flag) { *num_attrs= 0; *names= NULL; *value_lengths= NULL; *values= NULL; return(1); } /* ------------------------------ Setters --------------------------------- */ /* Set the ACL of the given file to a given list in long text form. @return 0 ACL support not enabled at compile time */ int aaip_set_acl_text(char *path, char *text, int flag) { return(0); } /* Bring the given attributes and/or ACLs into effect with the given file. @param flag Bitfield for control purposes bit0= decode and set ACLs bit1= first clear all existing attributes of the file bit2= do not set attributes other than ACLs @return 1 success (there was nothing to do) -6 support of xattr not enabled at compile time -7 support of ACL not enabled at compile time */ int aaip_set_attr_list(char *path, size_t num_attrs, char **names, size_t *value_lengths, char **values, int flag) { size_t i; for(i= 0; i < num_attrs; i++) { if(names[i] == NULL || values[i] == NULL) continue; if(names[i][0] == 0) { /* ACLs */ if(flag & 1) return(-7); continue; } /* Extended Attribute */ if(flag & 4) continue; if(!(flag & 8)) if(strncmp(names[i], "user.", 5)) continue; return(-6); } if(flag & 2) return(-6); return(1); } libisofs-1.4.2/libisofs/filter.h0000644000175700017510000000414412321161425013531 00000000000000/* * Copyright (c) 2008 Vreixo Formoso * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ #ifndef LIBISO_FILTER_H_ #define LIBISO_FILTER_H_ /* * Definitions of filters. */ /* dev_id for stream identification */ /* libisofs/filters/xor_encrypt.c */ #define XOR_ENCRYPT_DEV_ID 1 /* libisofs/filters/external.c */ #define ISO_FILTER_EXTERNAL_DEV_ID 2 /* libisofs/filters/zisofs.c */ #define ISO_FILTER_ZISOFS_DEV_ID 3 /* libisofs/filters/gzip.c */ #define ISO_FILTER_GZIP_DEV_ID 4 typedef struct filter_context FilterContext; struct filter_context { int version; /* reserved for future usage, set to 0 */ int refcount; /** filter specific shared data */ void *data; /** * Factory method to create a filtered stream from another stream. * * @param original * The original stream to be filtered. If the filter needs a ref to * it (most cases), it should take a ref to it with iso_stream_ref(). * @param filtered * Will be filled with the filtered IsoStream (reference belongs to * caller). * @return * 1 on success, < 0 on error */ int (*get_filter)(FilterContext *filter, IsoStream *original, IsoStream **filtered); /** * Free implementation specific data. Should never be called by user. * Use iso_filter_unref() instead. */ void (*free)(FilterContext *filter); }; /** * * @param flag * Reserved for future usage, pass always 0 for now. * TODO in a future a different value can mean filter caching, where * the filter is applied once and the filtered file is stored in a temp * dir. This prevent filter to be applied several times. */ int iso_file_add_filter(IsoFile *file, FilterContext *filter, int flag); void iso_filter_ref(FilterContext *filter); void iso_filter_unref(FilterContext *filter); #endif /*LIBISO_FILTER_H_*/ libisofs-1.4.2/libisofs/data_source.c0000644000175700017510000001034012435354343014534 00000000000000/* * Copyright (c) 2007 Vreixo Formoso * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif #include "libisofs.h" #include "util.h" #include #include #include #include #include #include /* O_BINARY is needed for Cygwin but undefined elsewhere */ #ifndef O_BINARY #define O_BINARY 0 #endif /** * Private data for File IsoDataSource */ struct file_data_src { char *path; int fd; }; /** * Increments the reference counting of the given IsoDataSource. */ void iso_data_source_ref(IsoDataSource *src) { src->refcount++; } /** * Decrements the reference counting of the given IsoDataSource, freeing it * if refcount reach 0. */ void iso_data_source_unref(IsoDataSource *src) { if (--src->refcount == 0) { src->free_data(src); free(src); } } static int ds_open(IsoDataSource *src) { int fd; struct file_data_src *data; if (src == NULL || src->data == NULL) { return ISO_NULL_POINTER; } data = (struct file_data_src*) src->data; if (data->fd != -1) { return ISO_FILE_ALREADY_OPENED; } fd = open(data->path, O_RDONLY | O_BINARY); if (fd == -1) { return ISO_FILE_ERROR; } data->fd = fd; return ISO_SUCCESS; } static int ds_close(IsoDataSource *src) { int ret; struct file_data_src *data; if (src == NULL || src->data == NULL) { return ISO_NULL_POINTER; } data = (struct file_data_src*) src->data; if (data->fd == -1) { return ISO_FILE_NOT_OPENED; } /* close can fail if fd is not valid, but that should never happen */ ret = close(data->fd); /* in any case we mark file as closed */ data->fd = -1; return ret == 0 ? ISO_SUCCESS : ISO_FILE_ERROR; } static int ds_read_block(IsoDataSource *src, uint32_t lba, uint8_t *buffer) { struct file_data_src *data; if (src == NULL || src->data == NULL || buffer == NULL) { return ISO_NULL_POINTER; } data = (struct file_data_src*) src->data; if (data->fd == -1) { return ISO_FILE_NOT_OPENED; } /* goes to requested block */ if (lseek(data->fd, (off_t)lba * (off_t)2048, SEEK_SET) == (off_t) -1) { return ISO_FILE_SEEK_ERROR; } /* TODO #00008 : guard against partial reads. */ if (read(data->fd, buffer, 2048) != 2048) { return ISO_FILE_READ_ERROR; } return ISO_SUCCESS; } static void ds_free_data(IsoDataSource *src) { struct file_data_src *data; data = (struct file_data_src*)src->data; /* close the file if needed */ if (data->fd != -1) { close(data->fd); } free(data->path); free(data); } /** * Create a new IsoDataSource from a local file. This is suitable for * accessing regular .iso images, or to acces drives via its block device * and standard POSIX I/O calls. * * @param path * The path of the file * @param src * Will be filled with the pointer to the newly created data source. * @return * 1 on success, < 0 on error. */ int iso_data_source_new_from_file(const char *path, IsoDataSource **src) { int ret; struct file_data_src *data; IsoDataSource *ds; if (path == NULL || src == NULL) { return ISO_NULL_POINTER; } /* ensure we have read access to the file */ ret = iso_eaccess(path); if (ret < 0) { return ret; } data = malloc(sizeof(struct file_data_src)); if (data == NULL) { return ISO_OUT_OF_MEM; } ds = malloc(sizeof(IsoDataSource)); if (ds == NULL) { free(data); return ISO_OUT_OF_MEM; } /* fill data fields */ data->path = strdup(path); if (data->path == NULL) { free(data); free(ds); return ISO_OUT_OF_MEM; } data->fd = -1; ds->version = 0; ds->refcount = 1; ds->data = data; ds->open = ds_open; ds->close = ds_close; ds->read_block = ds_read_block; ds->free_data = ds_free_data; *src = ds; return ISO_SUCCESS; } libisofs-1.4.2/libisofs/buffer.h0000644000175700017510000000702512321161425013516 00000000000000/* * Copyright (c) 2007 Vreixo Formoso * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ #ifndef LIBISO_BUFFER_H_ #define LIBISO_BUFFER_H_ #include #ifdef HAVE_STDINT_H #include #else #ifdef HAVE_INTTYPES_H #include #endif #endif #define BLOCK_SIZE 2048 typedef struct iso_ring_buffer IsoRingBuffer; /** * Create a new buffer. * * The created buffer should be freed with iso_ring_buffer_free() * * @param size * Number of blocks in buffer. You should supply a number >= 32, otherwise * size will be ignored and 32 will be used by default, which leads to a * 64 KiB buffer. * @return * 1 success, < 0 error */ int iso_ring_buffer_new(size_t size, IsoRingBuffer **rbuf); /** * Free a given buffer */ void iso_ring_buffer_free(IsoRingBuffer *buf); /** * Write count bytes into buffer. It blocks until all bytes where written or * reader close the buffer. * * @param buf * the buffer * @param data * pointer to a memory region of at least coun bytes, from which data * will be read. * @param * Number of bytes to write * @return * 1 succes, 0 read finished, < 0 error */ int iso_ring_buffer_write(IsoRingBuffer *buf, uint8_t *data, size_t count); /** * Read count bytes from the buffer into dest. It blocks until the desired * bytes has been read. If the writer finishes before outputting enought * bytes, 0 (EOF) is returned, the number of bytes already read remains * unknown. * * @return * 1 success, 0 EOF, < 0 error */ int iso_ring_buffer_read(IsoRingBuffer *buf, uint8_t *dest, size_t count); /** Backend of API call iso_ring_buffer_get_status() * * Get the status of a ring buffer. * * @param buf * The ring buffer object to inquire * @param size * Will be filled with the total size of the buffer, in bytes * @param free_bytes * Will be filled with the bytes currently available in buffer * @return * < 0 error, > 0 state: * 1="active" : input and consumption are active * 2="ending" : input has ended without error * 3="failing" : input had error and ended, * 5="abandoned" : consumption has ended prematurely * 6="ended" : consumption has ended without input error * 7="aborted" : consumption has ended after input error */ int iso_ring_buffer_get_buf_status(IsoRingBuffer *buf, size_t *size, size_t *free_bytes); /** * Close the buffer (to be called by the writer). * You have to explicity close the buffer when you don't have more data to * write, otherwise reader will be waiting forever. * * @param error * Writer has finished prematurely due to an error */ void iso_ring_buffer_writer_close(IsoRingBuffer *buf, int error); /** * Close the buffer (to be called by the reader). * If for any reason you don't want to read more data, you need to call this * to let the writer thread finish. * * @param error * Reader has finished prematurely due to an error */ void iso_ring_buffer_reader_close(IsoRingBuffer *buf, int error); /** * Get the times the buffer was full. */ unsigned int iso_ring_buffer_get_times_full(IsoRingBuffer *buf); /** * Get the times the buffer was empty. */ unsigned int iso_ring_buffer_get_times_empty(IsoRingBuffer *buf); #endif /*LIBISO_BUFFER_H_*/ libisofs-1.4.2/libisofs/node.c0000644000175700017510000024230612607731141013175 00000000000000/* * Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2009 - 2015 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif #include "libisofs.h" #include "image.h" #include "node.h" #include "stream.h" #include "aaip_0_2.h" #include "messages.h" #include "util.h" #include "eltorito.h" #include #include #include #include #include struct dir_iter_data { /* points to the last visited child, to NULL before start */ IsoNode *pos; /* Some control flags. * bit 0 -> 1 if next called, 0 reseted at start or on deletion */ int flag; }; /** * Increments the reference counting of the given node. */ void iso_node_ref(IsoNode *node) { ++node->refcount; } /** * Decrements the reference couting of the given node. * If it reach 0, the node is free, and, if the node is a directory, * its children will be unref() too. */ void iso_node_unref(IsoNode *node) { if (node == NULL) return; if (--node->refcount == 0) { switch (node->type) { case LIBISO_DIR: { IsoNode *child = ((IsoDir*)node)->children; while (child != NULL) { IsoNode *tmp = child->next; child->parent = NULL; iso_node_unref(child); child = tmp; } } break; case LIBISO_FILE: { IsoFile *file = (IsoFile*) node; iso_stream_unref(file->stream); } break; case LIBISO_SYMLINK: { IsoSymlink *link = (IsoSymlink*) node; free(link->dest); } break; case LIBISO_BOOT: { IsoBoot *bootcat = (IsoBoot *) node; if (bootcat->content != NULL) free(bootcat->content); } break; default: /* other kind of nodes does not need to delete anything here */ break; } if (node->xinfo) { IsoExtendedInfo *info = node->xinfo; while (info != NULL) { IsoExtendedInfo *tmp = info->next; /* free extended info */ info->process(info->data, 1); free(info); info = tmp; } } free(node->name); free(node); } } /** * Add extended information to the given node. Extended info allows * applications (and libisofs itself) to add more information to an IsoNode. * You can use this facilities to associate new information with a given * node. * * Each node keeps a list of added extended info, meaning you can add several * extended info data to each node. Each extended info you add is identified * by the proc parameter, a pointer to a function that knows how to manage * the external info data. Thus, in order to add several types of extended * info, you need to define a "proc" function for each type. * * @param node * The node where to add the extended info * @param proc * A function pointer used to identify the type of the data, and that * knows how to manage it * @param data * Extended info to add. * @return * 1 if success, 0 if the given node already has extended info of the * type defined by the "proc" function, < 0 on error */ int iso_node_add_xinfo(IsoNode *node, iso_node_xinfo_func proc, void *data) { IsoExtendedInfo *info; IsoExtendedInfo *pos; if (node == NULL || proc == NULL) { return ISO_NULL_POINTER; } pos = node->xinfo; while (pos != NULL) { if (pos->process == proc) { return 0; /* extended info already added */ } pos = pos->next; } info = malloc(sizeof(IsoExtendedInfo)); if (info == NULL) { return ISO_OUT_OF_MEM; } info->next = node->xinfo; info->data = data; info->process = proc; node->xinfo = info; return ISO_SUCCESS; } /** * Remove the given extended info (defined by the proc function) from the * given node. * * @return * 1 on success, 0 if node does not have extended info of the requested * type, < 0 on error */ int iso_node_remove_xinfo(IsoNode *node, iso_node_xinfo_func proc) { IsoExtendedInfo *pos, *prev; if (node == NULL || proc == NULL) { return ISO_NULL_POINTER; } prev = NULL; pos = node->xinfo; while (pos != NULL) { if (pos->process == proc) { /* this is the extended info we want to remove */ pos->process(pos->data, 1); if (prev != NULL) { prev->next = pos->next; } else { node->xinfo = pos->next; } free(pos); return ISO_SUCCESS; } prev = pos; pos = pos->next; } /* requested xinfo not found */ return 0; } /** * Get the given extended info (defined by the proc function) from the * given node. * * @param data * Will be filled with the extended info corresponding to the given proc * function * @return * 1 on success, 0 if node does not have extended info of the requested * type, < 0 on error */ int iso_node_get_xinfo(IsoNode *node, iso_node_xinfo_func proc, void **data) { IsoExtendedInfo *pos; if (node == NULL || proc == NULL || data == NULL) { return ISO_NULL_POINTER; } *data = NULL; pos = node->xinfo; while (pos != NULL) { if (pos->process == proc) { /* this is the extended info we want */ *data = pos->data; return ISO_SUCCESS; } pos = pos->next; } /* requested xinfo not found */ return 0; } /* API */ int iso_node_get_next_xinfo(IsoNode *node, void **handle, iso_node_xinfo_func *proc, void **data) { IsoExtendedInfo *xinfo; if (node == NULL || handle == NULL || proc == NULL || data == NULL) return ISO_NULL_POINTER; *proc = NULL; *data = NULL; xinfo = (IsoExtendedInfo *) *handle; if (xinfo == NULL) xinfo = node->xinfo; else xinfo = xinfo->next; *handle = xinfo; if (xinfo == NULL) return 0; *proc = xinfo->process; *data = xinfo->data; return ISO_SUCCESS; } int iso_node_remove_all_xinfo(IsoNode *node, int flag) { IsoExtendedInfo *pos, *next; for (pos = node->xinfo; pos != NULL; pos = next) { next = pos->next; pos->process(pos->data, 1); free((char *) pos); } node->xinfo = NULL; return ISO_SUCCESS; } static int iso_node_revert_xinfo_list(IsoNode *node, int flag) { IsoExtendedInfo *pos, *next, *prev = NULL; for (pos = node->xinfo; pos != NULL; pos = next) { next = pos->next; pos->next = prev; prev = pos; } node->xinfo = prev; return ISO_SUCCESS; } int iso_node_clone_xinfo(IsoNode *from_node, IsoNode *to_node, int flag) { void *handle = NULL, *data, *new_data; iso_node_xinfo_func proc; iso_node_xinfo_cloner cloner; int ret; iso_node_remove_all_xinfo(to_node, 0); while (1) { ret = iso_node_get_next_xinfo(from_node, &handle, &proc, &data); if (ret <= 0) break; ret = iso_node_xinfo_get_cloner(proc, &cloner, 0); if (ret == 0) return ISO_XINFO_NO_CLONE; if (ret < 0) return ret; ret = (*cloner)(data, &new_data, 0); if (ret < 0) break; ret = iso_node_add_xinfo(to_node, proc, new_data); if (ret < 0) break; } if (ret < 0) { iso_node_remove_all_xinfo(to_node, 0); } else { ret = iso_node_revert_xinfo_list(to_node, 0); } return ret; } /** * Get the type of an IsoNode. */ enum IsoNodeType iso_node_get_type(IsoNode *node) { return node->type; } /** * Set the name of a node. * * @param name The name in UTF-8 encoding * @param truncate_length (<64 = return on oversized name ) * @param flag bit0= issue warning in case of truncation */ int iso_node_set_name_trunc(IsoNode *node, const char *in_name, int truncate_length, int flag) { char *new, *name, *trunc = NULL; int ret; if ((IsoNode*)node->parent == node) { /* you can't change name of the root node */ ret = ISO_WRONG_ARG_VALUE; goto ex; } name = (char *) in_name; if (truncate_length >= 64) { trunc = strdup(name); if (trunc == 0) { ret = ISO_OUT_OF_MEM; goto ex; } ret = iso_truncate_rr_name(1, truncate_length, trunc, !(flag & 1)); if (ret < 0) goto ex; name = trunc; } /* check if the name is valid */ ret = iso_node_is_valid_name(name); if (ret < 0) goto ex; if (node->parent != NULL) { /* check if parent already has a node with same name */ if (iso_dir_get_node(node->parent, name, NULL) == 1) { ret = ISO_NODE_NAME_NOT_UNIQUE; goto ex; } } new = strdup(name); if (new == NULL) { ret = ISO_OUT_OF_MEM; goto ex; } free(node->name); node->name = new; if (node->parent != NULL) { IsoDir *parent; int res; /* take and add again to ensure correct children order */ parent = node->parent; iso_node_take(node); res = iso_dir_add_node(parent, node, 0); if (res < 0) { ret = res; goto ex; } } ret = ISO_SUCCESS; ex: if (trunc != NULL) free(trunc); return ret; } int iso_node_set_name(IsoNode *node, const char *name) { return iso_node_set_name_trunc(node, name, 0, 0); } int iso_image_set_node_name(IsoImage *image, IsoNode *node, const char *name, int flag) { if (image->truncate_mode == 0) if ((int) strlen(name) > image->truncate_length) return ISO_RR_NAME_TOO_LONG; return iso_node_set_name_trunc(node, name, image->truncate_length, flag); } /** * Get the name of a node (in UTF-8). * The returned string belongs to the node and should not be modified nor * freed. Use strdup if you really need your own copy. */ const char *iso_node_get_name(const IsoNode *node) { static char *root = {""}; if (node->name == NULL) return root; return node->name; } /** * See API function iso_node_set_permissions() * * @param flag bit0= do not adjust ACL * @return >0 success , <0 error */ int iso_node_set_perms_internal(IsoNode *node, mode_t mode, int flag) { int ret; node->mode = (node->mode & S_IFMT) | (mode & ~S_IFMT); /* If the node has ACL info : update ACL */ ret = 1; if (!(flag & 1)) ret = iso_node_set_acl_text(node, "", "", 2); return ret; } /** * Set the permissions for the node. This attribute is only useful when * Rock Ridge extensions are enabled. * * @param mode * bitmask with the permissions of the node, as specified in 'man 2 stat'. * The file type bitfields will be ignored, only file permissions will be * modified. */ void iso_node_set_permissions(IsoNode *node, mode_t mode) { iso_node_set_perms_internal(node, mode, 0); } /** * Get the permissions for the node */ mode_t iso_node_get_permissions(const IsoNode *node) { return node->mode & ~S_IFMT; } /** * Get the mode of the node, both permissions and file type, as specified in * 'man 2 stat'. */ mode_t iso_node_get_mode(const IsoNode *node) { return node->mode; } /** * Set the user id for the node. This attribute is only useful when * Rock Ridge extensions are enabled. */ void iso_node_set_uid(IsoNode *node, uid_t uid) { node->uid = uid; } /** * Get the user id of the node. */ uid_t iso_node_get_uid(const IsoNode *node) { return node->uid; } /** * Set the group id for the node. This attribute is only useful when * Rock Ridge extensions are enabled. */ void iso_node_set_gid(IsoNode *node, gid_t gid) { node->gid = gid; } /** * Get the group id of the node. */ gid_t iso_node_get_gid(const IsoNode *node) { return node->gid; } /** * Set the time of last modification of the file */ void iso_node_set_mtime(IsoNode *node, time_t time) { node->mtime = time; } /** * Get the time of last modification of the file */ time_t iso_node_get_mtime(const IsoNode *node) { return node->mtime; } /** * Set the time of last access to the file */ void iso_node_set_atime(IsoNode *node, time_t time) { node->atime = time; } /** * Get the time of last access to the file */ time_t iso_node_get_atime(const IsoNode *node) { return node->atime; } /** * Set the time of last status change of the file */ void iso_node_set_ctime(IsoNode *node, time_t time) { node->ctime = time; } /** * Get the time of last status change of the file */ time_t iso_node_get_ctime(const IsoNode *node) { return node->ctime; } void iso_node_set_hidden(IsoNode *node, int hide_attrs) { /* you can't hide root node */ if ((IsoNode*)node->parent != node) { node->hidden = hide_attrs; } } int iso_node_get_hidden(IsoNode *node) { return node->hidden; } /** * Add a new node to a dir. Note that this function don't add a new ref to * the node, so you don't need to free it, it will be automatically freed * when the dir is deleted. Of course, if you want to keep using the node * after the dir life, you need to iso_node_ref() it. * * @param dir * the dir where to add the node * @param child * the node to add. You must ensure that the node hasn't previously added * to other dir, and that the node name is unique inside the child. * Otherwise this function will return a failure, and the child won't be * inserted. * @param replace * if the dir already contains a node with the same name, whether to * replace or not the old node with this. * @return * number of nodes in dir if succes, < 0 otherwise */ int iso_dir_add_node(IsoDir *dir, IsoNode *child, enum iso_replace_mode replace) { IsoNode **pos; if (dir == NULL || child == NULL) { return ISO_NULL_POINTER; } if ((IsoNode*)dir == child) { return ISO_WRONG_ARG_VALUE; } /* * check if child is already added to another dir, or if child * is the root node, where parent == itself */ if (child->parent != NULL || child->parent == (IsoDir*)child) { return ISO_NODE_ALREADY_ADDED; } iso_dir_find(dir, child->name, &pos); return iso_dir_insert(dir, child, pos, replace); } /** * Locate a node inside a given dir. * * @param name * The name of the node * @param node * Location for a pointer to the node, it will filled with NULL if the dir * doesn't have a child with the given name. * The node will be owned by the dir and shouldn't be unref(). Just call * iso_node_ref() to get your own reference to the node. * Note that you can pass NULL is the only thing you want to do is check * if a node with such name already exists on dir. * @return * 1 node found, 0 child has no such node, < 0 error * Possible errors: * ISO_NULL_POINTER, if dir or name are NULL */ int iso_dir_get_node(IsoDir *dir, const char *name, IsoNode **node) { int ret; IsoNode **pos; if (dir == NULL || name == NULL) { return ISO_NULL_POINTER; } ret = iso_dir_exists(dir, name, &pos); if (ret == 0) { if (node) { *node = NULL; } return 0; /* node not found */ } if (node) { *node = *pos; } return 1; } int iso_dir_get_node_trunc(IsoDir *dir, int truncate_length, const char *name, IsoNode **node) { int ret; char *trunc = NULL; if ((int) strlen(name) <= truncate_length) { ret = iso_dir_get_node(dir, name, node); return ret; } trunc = strdup(name); if (trunc == NULL) return ISO_OUT_OF_MEM; ret = iso_truncate_rr_name(1, truncate_length, trunc, 1); if (ret < 0) goto ex; ret = iso_dir_get_node(dir, trunc, node); if (ret == 0) ret = 2; ex:; LIBISO_FREE_MEM(trunc); return ret; } /* API */ int iso_image_dir_get_node(IsoImage *image, IsoDir *dir, const char *name, IsoNode **node, int flag) { int ret; if (image->truncate_mode == 0 || (flag & 1)) ret = iso_dir_get_node(dir, name, node); else ret = iso_dir_get_node_trunc(dir, image->truncate_length, name, node); return ret; } /** * Get the number of children of a directory. * * @return * >= 0 number of items, < 0 error * Possible errors: * ISO_NULL_POINTER, if dir is NULL */ int iso_dir_get_children_count(IsoDir *dir) { if (dir == NULL) { return ISO_NULL_POINTER; } return dir->nchildren; } static int iter_next(IsoDirIter *iter, IsoNode **node) { struct dir_iter_data *data; if (iter == NULL || node == NULL) { return ISO_NULL_POINTER; } data = iter->data; /* clear next flag */ data->flag &= ~0x01; if (data->pos == NULL) { /* we are at the beginning */ data->pos = iter->dir->children; if (data->pos == NULL) { /* empty dir */ *node = NULL; return 0; } } else { if (data->pos->parent != iter->dir) { /* this can happen if the node has been moved to another dir */ /* TODO specific error */ return ISO_ERROR; } if (data->pos->next == NULL) { /* no more children */ *node = NULL; return 0; } else { /* free reference to current position */ iso_node_unref(data->pos); /* it is never last ref!! */ /* advance a position */ data->pos = data->pos->next; } } /* ok, take a ref to the current position, to prevent internal errors * if deleted somewhere */ iso_node_ref(data->pos); data->flag |= 0x01; /* set next flag */ /* return pointed node */ *node = data->pos; return ISO_SUCCESS; } /** * Check if there're more children. * * @return * 1 dir has more elements, 0 no, < 0 error * Possible errors: * ISO_NULL_POINTER, if iter is NULL */ static int iter_has_next(IsoDirIter *iter) { struct dir_iter_data *data; if (iter == NULL) { return ISO_NULL_POINTER; } data = iter->data; if (data->pos == NULL) { return iter->dir->children == NULL ? 0 : 1; } else { return data->pos->next == NULL ? 0 : 1; } } static void iter_free(IsoDirIter *iter) { struct dir_iter_data *data; data = iter->data; if (data->pos != NULL) { iso_node_unref(data->pos); } free(data); } static IsoNode** iso_dir_find_node(IsoDir *dir, IsoNode *node) { IsoNode **pos; pos = &(dir->children); while (*pos != NULL && *pos != node) { pos = &((*pos)->next); } return pos; } /** * Removes a child from a directory. * The child is not freed, so you will become the owner of the node. Later * you can add the node to another dir (calling iso_dir_add_node), or free * it if you don't need it (with iso_node_unref). * * @return * 1 on success, < 0 error */ int iso_node_take(IsoNode *node) { IsoNode **pos; IsoDir* dir; if (node == NULL) { return ISO_NULL_POINTER; } dir = node->parent; if (dir == NULL) { return ISO_NODE_NOT_ADDED_TO_DIR; } /* >>> Do not take root directory ! (dir == node) ? */; pos = iso_dir_find_node(dir, node); if (pos == NULL) { /* should never occur */ return ISO_ASSERT_FAILURE; } /* notify iterators just before remove */ iso_notify_dir_iters(node, 0); *pos = node->next; node->parent = NULL; node->next = NULL; dir->nchildren--; return ISO_SUCCESS; } /** * Removes a child from a directory and free (unref) it. * If you want to keep the child alive, you need to iso_node_ref() it * before this call, but in that case iso_node_take() is a better * alternative. * * @return * 1 on success, < 0 error */ int iso_node_remove(IsoNode *node) { int ret; ret = iso_node_take(node); if (ret == ISO_SUCCESS) { iso_node_unref(node); } return ret; } /* API */ int iso_node_remove_tree(IsoNode *node, IsoDirIter *boss_iter) { IsoDirIter *iter = NULL; IsoNode *sub_node; int ret; if (node->type != LIBISO_DIR) { /* >>> Do not remove root directory ! (node->parent == node) ? */; ret = iso_dir_get_children((IsoDir *) node, &iter); if (ret < 0) goto ex; while(1) { ret = iso_dir_iter_next(iter, &sub_node); if (ret == 0) break; ret = iso_node_remove_tree(sub_node, iter); if (ret < 0) goto ex; } if (node->parent == NULL) { /* node is not grafted into a boss directory */ iso_node_unref(node); goto ex; } } if (boss_iter != NULL) ret = iso_dir_iter_remove(boss_iter); else ret = iso_node_remove(node); ex:; if (iter != NULL) iso_dir_iter_free(iter); return ret; } /* * Get the parent of the given iso tree node. No extra ref is added to the * returned directory, you must take your ref. with iso_node_ref() if you * need it. * * If node is the root node, the same node will be returned as its parent. * * This returns NULL if the node doesn't pertain to any tree * (it was removed/take). */ IsoDir *iso_node_get_parent(IsoNode *node) { return node->parent; } /* TODO #00005 optimize iso_dir_iter_take */ static int iter_take(IsoDirIter *iter) { struct dir_iter_data *data; if (iter == NULL) { return ISO_NULL_POINTER; } data = iter->data; if (!(data->flag & 0x01)) { return ISO_ERROR; /* next not called or end of dir */ } if (data->pos == NULL) { return ISO_ASSERT_FAILURE; } /* clear next flag */ data->flag &= ~0x01; return iso_node_take(data->pos); } static int iter_remove(IsoDirIter *iter) { int ret; IsoNode *pos; struct dir_iter_data *data; if (iter == NULL) { return ISO_NULL_POINTER; } data = iter->data; pos = data->pos; ret = iter_take(iter); if (ret == ISO_SUCCESS) { /* remove node */ iso_node_unref(pos); } return ret; } void iter_notify_child_taken(IsoDirIter *iter, IsoNode *node) { IsoNode *pos, *pre; struct dir_iter_data *data; data = iter->data; if (data->pos == node) { pos = iter->dir->children; pre = NULL; while (pos != NULL && pos != data->pos) { pre = pos; pos = pos->next; } if (pos == NULL || pos != data->pos) { return; } /* dispose iterator reference */ iso_node_unref(data->pos); if (pre == NULL) { /* node is a first position */ iter->dir->children = pos->next; data->pos = NULL; } else { pre->next = pos->next; data->pos = pre; iso_node_ref(pre); /* take iter ref */ } } } static struct iso_dir_iter_iface iter_class = { iter_next, iter_has_next, iter_free, iter_take, iter_remove, iter_notify_child_taken }; int iso_dir_get_children(const IsoDir *dir, IsoDirIter **iter) { IsoDirIter *it; struct dir_iter_data *data; if (dir == NULL || iter == NULL) { return ISO_NULL_POINTER; } it = malloc(sizeof(IsoDirIter)); if (it == NULL) { return ISO_OUT_OF_MEM; } data = malloc(sizeof(struct dir_iter_data)); if (data == NULL) { free(it); return ISO_OUT_OF_MEM; } it->class = &iter_class; it->dir = (IsoDir*)dir; data->pos = NULL; data->flag = 0x00; it->data = data; if (iso_dir_iter_register(it) < 0) { free(it); return ISO_OUT_OF_MEM; } iso_node_ref((IsoNode*)dir); /* tak a ref to the dir */ *iter = it; return ISO_SUCCESS; } int iso_dir_iter_next(IsoDirIter *iter, IsoNode **node) { if (iter == NULL || node == NULL) { return ISO_NULL_POINTER; } return iter->class->next(iter, node); } int iso_dir_iter_has_next(IsoDirIter *iter) { if (iter == NULL) { return ISO_NULL_POINTER; } return iter->class->has_next(iter); } void iso_dir_iter_free(IsoDirIter *iter) { if (iter != NULL) { iso_dir_iter_unregister(iter); iter->class->free(iter); iso_node_unref((IsoNode*)iter->dir); free(iter); } } int iso_dir_iter_take(IsoDirIter *iter) { if (iter == NULL) { return ISO_NULL_POINTER; } return iter->class->take(iter); } int iso_dir_iter_remove(IsoDirIter *iter) { if (iter == NULL) { return ISO_NULL_POINTER; } return iter->class->remove(iter); } /** * Get the destination of a node. * The returned string belongs to the node and should not be modified nor * freed. Use strdup if you really need your own copy. */ const char *iso_symlink_get_dest(const IsoSymlink *link) { return link->dest; } /** * Set the destination of a link. */ int iso_symlink_set_dest(IsoSymlink *link, const char *dest) { char *d; int ret; ret = iso_node_is_valid_link_dest(dest); if (ret < 0) return ret; d = strdup(dest); if (d == NULL) { return ISO_OUT_OF_MEM; } free(link->dest); link->dest = d; return ISO_SUCCESS; } /** * Sets the order in which a node will be written on image. High weihted files * will be written first, so in a disc them will be written near the center. * * @param node * The node which weight will be changed. If it's a dir, this function * will change the weight of all its children. For nodes other that dirs * or regular files, this function has no effect. * @param w * The weight as a integer number, the greater this value is, the * closer from the begining of image the file will be written. */ void iso_node_set_sort_weight(IsoNode *node, int w) { if (node->type == LIBISO_DIR) { IsoNode *child = ((IsoDir*)node)->children; while (child) { iso_node_set_sort_weight(child, w); child = child->next; } } else if (node->type == LIBISO_FILE) { ((IsoFile*)node)->sort_weight = w; ((IsoFile*)node)->explicit_weight = 1; } } /** * Get the sort weight of a file. */ int iso_file_get_sort_weight(IsoFile *file) { return file->sort_weight; } /** * Get the size of the file, in bytes */ off_t iso_file_get_size(IsoFile *file) { return iso_stream_get_size(file->stream); } /** * Get the IsoStream that represents the contents of the given IsoFile. * * If you open() the stream, it should be close() before image generation. * * @return * The IsoStream. No extra ref is added, so the IsoStream belong to the * IsoFile, and it may be freed together with it. Add your own ref with * iso_stream_ref() if you need it. * * @since 0.6.4 */ IsoStream *iso_file_get_stream(IsoFile *file) { return file->stream; } /** * Get the device id (major/minor numbers) of the given block or * character device file. The result is undefined for other kind * of special files, of first be sure iso_node_get_mode() returns either * S_IFBLK or S_IFCHR. * * @since 0.6.6 */ dev_t iso_special_get_dev(IsoSpecial *special) { return special->dev; } /** * Get the block lba of a file node, if it was imported from an old image. * * @param file * The file * @param lba * Will be filled with the kba * @param flag * Reserved for future usage, submit 0 * @return * 1 if lba is valid (file comes from old image), 0 if file was newly * added, i.e. it does not come from an old image, < 0 error * * @since 0.6.4 */ int iso_file_get_old_image_lba(IsoFile *file, uint32_t *lba, int flag) { int ret; int section_count; struct iso_file_section *sections = NULL; if (file == NULL || lba == NULL) { return ISO_NULL_POINTER; } ret = iso_file_get_old_image_sections(file, §ion_count, §ions, 0); if (ret <= 0) return ret; if (section_count != 1) { if (sections != NULL) free(sections); return ISO_WRONG_ARG_VALUE; } *lba = sections[0].block; free(sections); return 1; } /* * Like iso_file_get_old_image_lba(), but take an IsoNode. * * @return * 1 if lba is valid (file comes from old image), 0 if file was newly * added, i.e. it does not come from an old image, 2 node type has no * LBA (no regular file), < 0 error * * @since 0.6.4 */ int iso_node_get_old_image_lba(IsoNode *node, uint32_t *lba, int flag) { if (node == NULL) { return ISO_NULL_POINTER; } if (ISO_NODE_IS_FILE(node)) { return iso_file_get_old_image_lba((IsoFile*)node, lba, flag); } else { return 2; } } /** * Check if a given name is valid for an iso node. * * @return * 1 if yes, 0 if not */ int iso_node_is_valid_name(const char *name) { /* a name can't be NULL */ if (name == NULL) { return ISO_NULL_POINTER; } /* guard against the empty string or big names... */ if (name[0] == '\0') goto rr_reserved; if (strlen(name) > LIBISOFS_NODE_NAME_MAX) return ISO_RR_NAME_TOO_LONG; /* ...against "." and ".." names... */ if (!strcmp(name, ".") || !strcmp(name, "..")) goto rr_reserved; /* ...and against names with '/' */ if (strchr(name, '/') != NULL) goto rr_reserved; return 1; rr_reserved:; /* # define Libisofs_debug_rr_reserveD */ #ifdef Libisofs_debug_rr_reserveD fprintf(stderr, "libisofs_DEBUG: ISO_RR_NAME_RESERVED with '%s'\n", name); #endif return ISO_RR_NAME_RESERVED; } /** * Check if a given path is valid for the destination of a link. * * @return * 1 if yes, 0 if not */ int iso_node_is_valid_link_dest(const char *dest) { int ret; char *ptr, *brk_info, *component; /* a dest can't be NULL */ if (dest == NULL) { return ISO_NULL_POINTER; } /* guard against the empty string or big dest... */ if (dest[0] == '\0') { #ifdef Libisofs_debug_rr_reserveD fprintf(stderr, "libisofs_DEBUG: ISO_RR_NAME_RESERVED by empty link target\n"); #endif return ISO_RR_NAME_RESERVED; } if (strlen(dest) > LIBISOFS_NODE_PATH_MAX) return ISO_RR_PATH_TOO_LONG; /* check that all components are valid */ if (!strcmp(dest, "/")) { /* "/" is a valid component */ return 1; } ptr = strdup(dest); if (ptr == NULL) { return ISO_OUT_OF_MEM; } ret = 1; component = strtok_r(ptr, "/", &brk_info); while (component) { if (strcmp(component, ".") && strcmp(component, "..")) { ret = iso_node_is_valid_name(component); if (ret < 0) { break; } } component = strtok_r(NULL, "/", &brk_info); } free(ptr); return ret; } void iso_dir_find(IsoDir *dir, const char *name, IsoNode ***pos) { *pos = &(dir->children); while (**pos != NULL && strcmp((**pos)->name, name) < 0) { *pos = &((**pos)->next); } } int iso_dir_exists(IsoDir *dir, const char *name, IsoNode ***pos) { IsoNode **node; iso_dir_find(dir, name, &node); if (pos) { *pos = node; } return (*node != NULL && !strcmp((*node)->name, name)) ? 1 : 0; } int iso_dir_insert(IsoDir *dir, IsoNode *node, IsoNode **pos, enum iso_replace_mode replace) { if (*pos != NULL && !strcmp((*pos)->name, node->name)) { /* a node with same name already exists */ switch(replace) { case ISO_REPLACE_NEVER: return ISO_NODE_NAME_NOT_UNIQUE; case ISO_REPLACE_IF_NEWER: if ((*pos)->mtime >= node->mtime) { /* old file is newer */ return ISO_NODE_NAME_NOT_UNIQUE; } break; case ISO_REPLACE_IF_SAME_TYPE_AND_NEWER: if ((*pos)->mtime >= node->mtime) { /* old file is newer */ return ISO_NODE_NAME_NOT_UNIQUE; } /* fall down */ case ISO_REPLACE_IF_SAME_TYPE: if ((node->mode & S_IFMT) != ((*pos)->mode & S_IFMT)) { /* different file types */ return ISO_NODE_NAME_NOT_UNIQUE; } break; case ISO_REPLACE_ALWAYS: break; default: /* CAN'T HAPPEN */ return ISO_ASSERT_FAILURE; } /* if we are reach here we have to replace */ node->next = (*pos)->next; (*pos)->parent = NULL; (*pos)->next = NULL; iso_node_unref(*pos); *pos = node; node->parent = dir; return dir->nchildren; } node->next = *pos; *pos = node; node->parent = dir; return ++dir->nchildren; } /* iterators are stored in a linked list */ struct iter_reg_node { IsoDirIter *iter; struct iter_reg_node *next; }; /* list header */ static struct iter_reg_node *iter_reg = NULL; /** * Add a new iterator to the registry. The iterator register keeps track of * all iterators being used, and are notified when directory structure * changes. */ int iso_dir_iter_register(IsoDirIter *iter) { struct iter_reg_node *new; new = malloc(sizeof(struct iter_reg_node)); if (new == NULL) { return ISO_OUT_OF_MEM; } new->iter = iter; new->next = iter_reg; iter_reg = new; return ISO_SUCCESS; } /** * Unregister a directory iterator. */ void iso_dir_iter_unregister(IsoDirIter *iter) { struct iter_reg_node **pos; pos = &iter_reg; while (*pos != NULL && (*pos)->iter != iter) { pos = &(*pos)->next; } if (*pos) { struct iter_reg_node *tmp = (*pos)->next; free(*pos); *pos = tmp; } } void iso_notify_dir_iters(IsoNode *node, int flag) { struct iter_reg_node *pos = iter_reg; while (pos != NULL) { IsoDirIter *iter = pos->iter; if (iter->dir == node->parent) { iter->class->notify_child_taken(iter, node); } pos = pos->next; } } int iso_node_new_root(IsoDir **root) { IsoDir *dir; dir = calloc(1, sizeof(IsoDir)); if (dir == NULL) { return ISO_OUT_OF_MEM; } dir->node.refcount = 1; dir->node.type = LIBISO_DIR; dir->node.atime = dir->node.ctime = dir->node.mtime = time(NULL); dir->node.mode = S_IFDIR | 0555; /* set parent to itself, to prevent root to be added to another dir */ dir->node.parent = dir; *root = dir; return ISO_SUCCESS; } int iso_node_new_dir(char *name, IsoDir **dir) { IsoDir *new; int ret; if (dir == NULL || name == NULL) { return ISO_NULL_POINTER; } /* check if the name is valid */ ret = iso_node_is_valid_name(name); if (ret < 0) return ret; new = calloc(1, sizeof(IsoDir)); if (new == NULL) { return ISO_OUT_OF_MEM; } new->node.refcount = 1; new->node.type = LIBISO_DIR; new->node.name = name; new->node.mode = S_IFDIR; *dir = new; return ISO_SUCCESS; } int iso_node_new_file(char *name, IsoStream *stream, IsoFile **file) { IsoFile *new; int ret; if (file == NULL || name == NULL || stream == NULL) { return ISO_NULL_POINTER; } /* check if the name is valid */ ret = iso_node_is_valid_name(name); if (ret < 0) return ret; new = calloc(1, sizeof(IsoFile)); if (new == NULL) { return ISO_OUT_OF_MEM; } new->node.refcount = 1; new->node.type = LIBISO_FILE; new->node.name = name; new->node.mode = S_IFREG; new->from_old_session = 0; new->explicit_weight = 0; new->sort_weight = 0; new->stream = stream; *file = new; return ISO_SUCCESS; } int iso_node_new_symlink(char *name, char *dest, IsoSymlink **link) { IsoSymlink *new; int ret; if (link == NULL || name == NULL || dest == NULL) { return ISO_NULL_POINTER; } /* check if the name is valid */ ret = iso_node_is_valid_name(name); if (ret < 0) return ret; /* check if destination is valid */ ret = iso_node_is_valid_link_dest(dest); if (ret < 0) return ret; new = calloc(1, sizeof(IsoSymlink)); if (new == NULL) { return ISO_OUT_OF_MEM; } new->node.refcount = 1; new->node.type = LIBISO_SYMLINK; new->node.name = name; new->dest = dest; new->node.mode = S_IFLNK; new->fs_id = 0; new->st_dev = 0; new->st_ino = 0; *link = new; return ISO_SUCCESS; } int iso_node_new_special(char *name, mode_t mode, dev_t dev, IsoSpecial **special) { IsoSpecial *new; int ret; if (special == NULL || name == NULL) { return ISO_NULL_POINTER; } if (S_ISLNK(mode) || S_ISREG(mode) || S_ISDIR(mode)) { return ISO_WRONG_ARG_VALUE; } /* check if the name is valid */ ret = iso_node_is_valid_name(name); if (ret < 0) return ret; new = calloc(1, sizeof(IsoSpecial)); if (new == NULL) { return ISO_OUT_OF_MEM; } new->node.refcount = 1; new->node.type = LIBISO_SPECIAL; new->node.name = name; new->node.mode = mode; new->dev = dev; new->fs_id = 0; new->st_dev = 0; new->st_ino = 0; *special = new; return ISO_SUCCESS; } /* @param flag bit0= inverse: cleanout everything but del_name */ static int attrs_cleanout_name(char *del_name, size_t *num_attrs, char **names, size_t *value_lengths, char **values, int flag) { size_t i, w; for (w = i = 0; i < *num_attrs; i++) { if ((strcmp(names[i], del_name) == 0) ^ (flag & 1)) { if (names[i] != NULL) free(names[i]); if (values[i] != NULL) free(values[i]); names[i] = values[i] = NULL; continue; } if (w == i) { w++; continue; } names[w] = names[i]; value_lengths[w] = value_lengths[i]; values[w] = values[i]; names[i] = values[i] = NULL; value_lengths[i] = 0; w++; } *num_attrs = w; return 1; } /** * Backend of iso_node_get_attrs() with parameter node replaced by the * AAIP string from where to get the attribute list. * All other parameter specs apply. */ int iso_aa_get_attrs(unsigned char *aa_string, size_t *num_attrs, char ***names, size_t **value_lengths, char ***values, int flag) { struct aaip_state *aaip= NULL; unsigned char *rpt; size_t len, todo, consumed; int is_done = 0, first_round= 1, ret; if (flag & (1 << 15)) aaip_get_decoded_attrs(&aaip, num_attrs, names, value_lengths, values, 1 << 15); *num_attrs = 0; *names = NULL; *value_lengths = NULL; *values = NULL; if (flag & (1 << 15)) return 1; rpt = aa_string; len = aaip_count_bytes(rpt, 0); while (!is_done) { todo = len - (rpt - aa_string); if (todo > 2048) todo = 2048; if (todo == 0) { /* Out of data while still prompted to submit */ ret = ISO_AAIP_BAD_AASTRING; goto ex; } /* Allow 1 million bytes of memory consumption, 100,000 attributes */ ret = aaip_decode_attrs(&aaip, (size_t) 1000000, (size_t) 100000, rpt, todo, &consumed, first_round); rpt+= consumed; first_round= 0; if (ret == 1) continue; if (ret == 2) break; /* aaip_decode_attrs() reports error */ ret = ISO_AAIP_BAD_AASTRING; goto ex; } if ((size_t) (rpt - aa_string) != len) { /* aaip_decode_attrs() returns 2 but still bytes are left */ ret = ISO_AAIP_BAD_AASTRING; goto ex; } ret = aaip_get_decoded_attrs(&aaip, num_attrs, names, value_lengths, values, 0); if (ret != 1) { /* aaip_get_decoded_attrs() failed */ ret = ISO_AAIP_BAD_AASTRING; goto ex; } if (!(flag & 1)) { /* Clean out eventual ACL attribute resp. all other xattr */ attrs_cleanout_name("", num_attrs, *names, *value_lengths, *values, !!(flag & 4)); } ret = 1; ex:; aaip_decode_attrs(&aaip, (size_t) 1000000, (size_t) 100000, rpt, todo, &consumed, 1 << 15); return ret; } /** * Search given name. Eventually calloc() and copy value. Add trailing 0 byte * for caller convenience. * * @return 1= found , 0= not found , <0 error */ int iso_aa_lookup_attr(unsigned char *aa_string, char *name, size_t *value_length, char **value, int flag) { size_t num_attrs = 0, *value_lengths = NULL; char **names = NULL, **values = NULL; int i, ret = 0, found = 0; ret = iso_aa_get_attrs(aa_string, &num_attrs, &names, &value_lengths, &values, 0); if (ret < 0) return ret; for (i = 0; i < (int) num_attrs; i++) { if (strcmp(names[i], name)) continue; *value_length = value_lengths[i]; *value = calloc(*value_length + 1, 1); if (*value == NULL) { found = ISO_OUT_OF_MEM; break; } if (*value_length > 0) memcpy(*value, values[i], *value_length); (*value)[*value_length] = 0; found = 1; break; } iso_aa_get_attrs(aa_string, &num_attrs, &names, &value_lengths, &values, 1 << 15); return found; } /* API */ int iso_node_lookup_attr(IsoNode *node, char *name, size_t *value_length, char **value, int flag) { void *xipt; unsigned char *aa_string = NULL; int ret; *value_length= 0; *value= NULL; ret = iso_node_get_xinfo(node, aaip_xinfo_func, &xipt); if (ret != 1) return 0; aa_string = (unsigned char *) xipt; ret = iso_aa_lookup_attr(aa_string, name, value_length, value, 0); return ret; } /* API */ int iso_node_get_attrs(IsoNode *node, size_t *num_attrs, char ***names, size_t **value_lengths, char ***values, int flag) { void *xipt; unsigned char *aa_string = NULL; int ret; if (flag & (1 << 15)) { iso_aa_get_attrs(aa_string, num_attrs, names, value_lengths, values, 1 << 15); return 1; } *num_attrs = 0; *names = NULL; *value_lengths = NULL; *values = NULL; ret = iso_node_get_xinfo(node, aaip_xinfo_func, &xipt); if (ret != 1) return 1; aa_string = (unsigned char *) xipt; ret = iso_aa_get_attrs(aa_string, num_attrs, names, value_lengths, values, flag); return ret; } /* Enlarge attribute list */ static int attr_enlarge_list(char ***names, size_t **value_lengths, char ***values, size_t new_num, int flag) { void *newpt; newpt = realloc(*names, new_num * sizeof(char *)); if (newpt == NULL) return ISO_OUT_OF_MEM; *names = (char **) newpt; newpt = realloc(*values, new_num * sizeof(char *)); if (newpt == NULL) return ISO_OUT_OF_MEM; *values = (char **) newpt; newpt = realloc(*value_lengths, new_num * sizeof(size_t)); if (newpt == NULL) return ISO_OUT_OF_MEM; *value_lengths = (size_t *) newpt; return 1; } /* Merge attribute list of node and given new attribute list into attribute list returned by m_* parameters. The m_* paramters have finally to be freed by a call with bit15 set. @param flag Bitfield for control purposes bit0= delete all old names which begin by "user." (but not if bit2 is set) bit2= delete the given names rather than overwrite their content bit4= do not overwrite value of empty name bit5= do not overwrite isofs attributes bit15= release memory and return 1 */ static int iso_node_merge_xattr(IsoNode *node, size_t num_attrs, char **names, size_t *value_lengths, char **values, size_t *m_num_attrs, char ***m_names, size_t **m_value_lengths, char ***m_values, int flag) { int ret; size_t new_names = 0, deleted = 0, i, j, w; if (flag & (1 << 15)) { iso_node_get_attrs(node, m_num_attrs, m_names, m_value_lengths, m_values, 1 << 15); return 1; } ret = iso_node_get_attrs(node, m_num_attrs, m_names, m_value_lengths, m_values, 1); if (ret < 0) return ret; if ((flag & 1) && (!(flag & 4))) { /* Delete unmatched user space pairs */ for (j = 0; j < *m_num_attrs; j++) { if (strncmp((*m_names)[j], "user.", 5) != 0) continue; for (i = 0; i < num_attrs; i++) { if (names[i] == NULL || (*m_names)[j] == NULL) continue; if (strcmp(names[i], (*m_names)[j]) == 0) break; } if (i >= num_attrs) { /* Delete unmatched pair */ free((*m_names)[j]); (*m_names)[j] = NULL; deleted++; } } } /* Handle existing names, count non-existing names */ for (i = 0; i < num_attrs; i++) { if (names[i] == NULL) continue; if (names[i][0] == 0 && (flag & 16)) continue; if ((flag & 32) && strncmp(names[i], "isofs.", 6) == 0) continue; for (j = 0; j < *m_num_attrs; j++) { if ((*m_names)[j] == NULL) continue; if (strcmp(names[i], (*m_names)[j]) == 0) { if ((*m_values)[j] != NULL) free((*m_values)[j]); (*m_values)[j] = NULL; (*m_value_lengths)[j] = 0; if (flag & 4) { /* Delete pair */ free((*m_names)[j]); (*m_names)[j] = NULL; deleted++; } else { (*m_values)[j] = calloc(value_lengths[i] + 1, 1); if ((*m_values)[j] == NULL) return ISO_OUT_OF_MEM; memcpy((*m_values)[j], values[i], value_lengths[i]); (*m_values)[j][value_lengths[i]] = 0; (*m_value_lengths)[j] = value_lengths[i]; } break; } } if (j >= *m_num_attrs) new_names++; } if (new_names > 0 && (flag & 4)) { /* >>> warn of non-existing name on delete ? */; } else if (new_names > 0) { ret = attr_enlarge_list(m_names, m_value_lengths, m_values, *m_num_attrs + new_names, 0); if (ret < 0) return ret; /* Set new pairs */; w = *m_num_attrs; for (i = 0; i < num_attrs; i++) { if (names[i] == NULL) continue; if (names[i][0] == 0 && (flag & 16)) continue; if ((flag & 32) && strncmp(names[i], "isofs.", 6) == 0) continue; for (j = 0; j < *m_num_attrs; j++) { if ((*m_names)[j] == NULL) continue; if (strcmp(names[i], (*m_names)[j]) == 0) continue; } if (j < *m_num_attrs) /* Name is not new */ continue; (*m_names)[w] = strdup(names[i]); if ((*m_names)[w] == NULL) return ISO_OUT_OF_MEM; (*m_values)[w] = calloc(value_lengths[i] + 1, 1); if ((*m_values)[w] == NULL) return ISO_OUT_OF_MEM; memcpy((*m_values)[w], values[i], value_lengths[i]); (*m_values)[w][value_lengths[i]] = 0; (*m_value_lengths)[w] = value_lengths[i]; w++; } *m_num_attrs = w; } if (deleted > 0) { /* Garbage collection */ w = 0; for (j = 0; j < *m_num_attrs; j++) { if ((*m_names)[j] == NULL) continue; (*m_names)[w] = (*m_names)[j]; (*m_values)[w] = (*m_values)[j]; (*m_value_lengths)[w] = (*m_value_lengths)[j]; w++; } *m_num_attrs = w; } return 1; } int iso_node_set_attrs(IsoNode *node, size_t num_attrs, char **names, size_t *value_lengths, char **values, int flag) { int ret, acl_saved = 0; ssize_t sret; size_t result_len, m_num = 0, *m_value_lengths = NULL, i; unsigned char *result = NULL; char *a_acl = NULL, *d_acl = NULL, **m_names = NULL, **m_values = NULL; if (!(flag & 8)) for (i = 0; i < num_attrs; i++) if (strncmp(names[i], "user.", 5) != 0 && names[i][0] != 0) return ISO_AAIP_NON_USER_NAME; if ((flag & (2 | 4 | 16)) || !(flag & 8)) { /* Merge old and new lists */ ret = iso_node_merge_xattr( node, num_attrs, names, value_lengths, values, &m_num, &m_names, &m_value_lengths, &m_values, (flag & 4) | (!(flag & 2)) | ((!(flag & 1)) << 4) | ((flag & 16) << 1)); if (ret < 0) goto ex; num_attrs = m_num; names = m_names; value_lengths = m_value_lengths; values = m_values; } else if (!(flag & 1)) { iso_node_get_acl_text(node, &a_acl, &d_acl, 16); acl_saved = 1; } if (num_attrs == 0) { ret = iso_node_remove_xinfo(node, aaip_xinfo_func); if (ret < 0) goto ex; if (acl_saved && (a_acl != NULL || d_acl != NULL)) { ret = iso_node_set_acl_text(node, a_acl, d_acl, 0); if (ret < 0) goto ex; } ret = 1; goto ex; } sret = aaip_encode(num_attrs, names, value_lengths, values, &result_len, &result, 0); if (sret < 0) { ret = sret; goto ex; } ret = iso_node_remove_xinfo(node, aaip_xinfo_func); if (ret < 0) { if (result != NULL) free(result); goto ex; } if (sret > 0) { ret = iso_node_add_xinfo(node, aaip_xinfo_func, result); if (ret < 0) goto ex; if (ret == 0) { /* >>> something is messed up with xinfo: an aa_string still exists */; ret = ISO_ERROR; goto ex; } if (acl_saved) { ret = iso_node_set_acl_text(node, a_acl, d_acl, 0); if (ret < 0) goto ex; } } ret = 1; ex:; /* Dispose eventual merged list */ iso_node_merge_xattr(node, num_attrs, names, value_lengths, values, &m_num, &m_names, &m_value_lengths, &m_values, 1 << 15); return ret; } static int iso_decode_acl(unsigned char *v_data, size_t v_len, size_t *consumed, char **text, size_t *text_fill, int flag) { int ret; *text= NULL; ret = aaip_decode_acl(v_data, v_len, consumed, NULL, (size_t) 0, text_fill, 1); if (ret <= 0) return 0; if (*text_fill == 0) return ret; *text = calloc(*text_fill + 42, 1); /* 42 for aaip_update_acl_st_mode */ if (*text == NULL) return ISO_OUT_OF_MEM; ret = aaip_decode_acl(v_data, v_len, consumed, *text, *text_fill, text_fill, 0); if (ret <= 0) { free(*text); *text= NULL; return 0; } return ret; } /** * Backend of iso_node_get_acl_text() with parameter node replaced by the * attribute list from where to get the ACL and by the associated st_mode * permission bits. All other parameter specs apply. */ static int iso_attr_get_acl_text(size_t num_attrs, char **names, size_t *value_lengths, char **values, mode_t st_mode, char **access_text, char **default_text, int flag) { size_t i, consumed, text_fill = 0; size_t v_len; unsigned char *v_data; int ret, from_posix= 0; if (flag & (1 << 15)) { if (*access_text != NULL) free(*access_text); *access_text = NULL; if (*default_text != NULL) free(*default_text); *default_text = NULL; return 1; } *access_text = *default_text = NULL; for(i = 0; i < num_attrs; i++) { if (names[i][0]) /* searching the empty name */ continue; v_data = (unsigned char *) values[i]; v_len = value_lengths[i]; /* "access" ACL */ ret = iso_decode_acl(v_data, v_len, &consumed, access_text, &text_fill, 0); if (ret <= 0) goto bad_decode; if (ret == 2) { v_data += consumed; v_len -= consumed; ret = iso_decode_acl(v_data, v_len, &consumed, default_text, &text_fill, 0); if (ret == 0) goto bad_decode; } break; } if (*access_text == NULL && !(flag & 16)) { from_posix = 1; *access_text = calloc(42, 1); /* 42 for aaip_update_acl_st_mode */ } if (*access_text != NULL) { aaip_add_acl_st_mode(*access_text, st_mode, 0); text_fill = strlen(*access_text); } if (*access_text == NULL && *default_text == NULL) ret = 0; else ret = 1 + from_posix; ex:; return ret; bad_decode:; ret = ISO_AAIP_BAD_ACL; goto ex; } int iso_node_get_acl_text(IsoNode *node, char **access_text, char **default_text, int flag) { size_t num_attrs = 0, *value_lengths = NULL; char **names = NULL, **values = NULL; mode_t st_mode = 0; int ret; if (flag & (1 << 15)) { iso_attr_get_acl_text(num_attrs, names, value_lengths, values, st_mode, access_text, default_text, 1 << 15); return 1; } ret = iso_node_get_attrs(node, &num_attrs, &names, &value_lengths, &values, 1); if (ret < 0) return ret; st_mode = iso_node_get_permissions(node); ret = iso_attr_get_acl_text(num_attrs, names, value_lengths, values, st_mode, access_text, default_text, flag); iso_node_get_attrs(node, &num_attrs, &names, &value_lengths, &values, 1 << 15); /* free memory */ return ret; } int iso_aa_get_acl_text(unsigned char *aa_string, mode_t st_mode, char **access_text, char **default_text, int flag) { int ret; size_t num_attrs = 0, *value_lengths = NULL; char **names = NULL, **values = NULL; if (flag & (1 << 15)) { iso_attr_get_acl_text(num_attrs, names, value_lengths, values, st_mode, access_text, default_text, 1 << 15); return 1; } ret = iso_aa_get_attrs(aa_string, &num_attrs, &names, &value_lengths, &values, 1); if (ret < 0) goto ex; ret = iso_attr_get_acl_text(num_attrs, names, value_lengths, values, st_mode, access_text, default_text, flag); ex:; iso_aa_get_attrs(aa_string, &num_attrs, &names, &value_lengths, &values, 1 << 15); return ret; } int iso_node_set_acl_text(IsoNode *node, char *access_text, char *default_text, int flag) { size_t num_attrs = 0, *value_lengths = NULL, i, j, consumed; size_t a_text_fill = 0, d_text_fill = 0; size_t v_len, acl_len= 0; char **names = NULL, **values = NULL, *a_text = NULL, *d_text = NULL; unsigned char *v_data, *acl= NULL; int ret; mode_t st_mode; st_mode = iso_node_get_permissions(node); if (!(flag & 2)) { /* want not to update ACL by st_mode */ /* >>> validate and rectify text */; } ret = iso_node_get_attrs(node, &num_attrs, &names, &value_lengths, &values, 1); if (ret < 0) return ret; for(i = 0; i < num_attrs; i++) { if (names[i][0]) /* searching the empty name */ continue; v_data = (unsigned char *) values[i]; v_len = value_lengths[i]; if (flag & 2) { /* update "access" ACL by st_mode */ /* read "access" ACL */ ret = iso_decode_acl(v_data, v_len, &consumed, &a_text, &a_text_fill, 0); if (ret == 0) goto bad_decode; if (ret < 0) goto ex; if (ret == 2) { /* read "default" ACL */ v_data += consumed; v_len -= consumed; ret = iso_decode_acl(v_data, v_len, &consumed, &d_text, &d_text_fill, 0); if (ret == 0) goto bad_decode; if (ret < 0) goto ex; } /* Update "access" ACL by st_mode */ if (a_text == NULL) { ret = 1; goto ex; } ret = aaip_cleanout_st_mode(a_text, &st_mode, 8); if (ret < 0) { ret = ISO_AAIP_BAD_ACL_TEXT; goto ex; } ret = aaip_encode_both_acl(a_text, d_text, st_mode, &acl_len, &acl, 2 | 8); } else { ret = 1; if (access_text != NULL || default_text != NULL) ret = aaip_encode_both_acl(access_text, default_text, st_mode, &acl_len, &acl, 2 | 8); } if (ret == -1) ret = ISO_OUT_OF_MEM; else if (ret <= 0 && ret >= -3) ret = ISO_AAIP_BAD_ACL_TEXT; if (ret <= 0) goto ex; if(acl == NULL) { /* Delete whole ACL attribute */ /* Update S_IRWXG by eventual "group::" ACL entry. With ACL it reflected the "mask::" entry. */ if (a_text != NULL) free(a_text); ret = iso_decode_acl(v_data, v_len, &consumed, &a_text, &a_text_fill, 0); if (ret == 0) goto bad_decode; if (ret < 0) goto ex; ret = aaip_cleanout_st_mode(a_text, &st_mode, 4 | 16); if (ret < 0) goto ex; iso_node_set_perms_internal(node, st_mode, 1); /* Delete the attribute pair */ if (values[i] != NULL) free(values[i]); for (j = i + 1; j < num_attrs; j++) { names[j - 1] = names[j]; value_lengths[j - 1] = value_lengths[j]; values[j - 1] = values[j]; } num_attrs--; } else { /* replace variable value */; if (values[i] != NULL) free(values[i]); values[i] = (char *) acl; acl = NULL; value_lengths[i] = acl_len; } /* Encode attributes and attach to node */ ret = iso_node_set_attrs(node, num_attrs, names, value_lengths, values, 1 | 8); if (ret <= 0) goto ex; goto update_perms; } /* There is no ACL yet */ if ((flag & 2) || (access_text == NULL && default_text == NULL)) { /* thus no need to update ACL by st_mode or to delete ACL */ ret = 1; goto ex; } ret = aaip_encode_both_acl(access_text, default_text, st_mode, &acl_len, &acl, 2 | 8); if (ret < -3) goto ex; if (ret <= 0) { ret = ISO_AAIP_BAD_ACL_TEXT; goto ex; } ret = attr_enlarge_list(&names, &value_lengths, &values, num_attrs + 1, 0); if (ret < 0) goto ex; /* Set new ACL attribute */ names[num_attrs] = strdup(""); if (names[num_attrs] == NULL) { ret = ISO_OUT_OF_MEM; goto ex; } values[num_attrs] = (char *) acl; acl = NULL; value_lengths[num_attrs] = acl_len; num_attrs++; /* Encode attributes and attach to node */ ret = iso_node_set_attrs(node, num_attrs, names, value_lengths, values, 1 | 8); if (ret < 0) goto ex; update_perms:; if(access_text != NULL && !(flag & (1 | 2))) { /* Update node permissions by acl_text */ st_mode = iso_node_get_permissions(node); ret = aaip_cleanout_st_mode(access_text, &st_mode, 4); if (ret < 0) { ret = ISO_AAIP_BAD_ACL_TEXT; goto ex; } iso_node_set_perms_internal(node, st_mode, 1); } ret = 1; ex:; iso_node_get_attrs(node, &num_attrs, &names, &value_lengths, &values, 1 << 15); /* free memory */ if (a_text != NULL) free(a_text); if (d_text != NULL) free(d_text); if(acl != NULL) free(acl); return ret; bad_decode:; ret = ISO_AAIP_BAD_ACL; goto ex; } mode_t iso_node_get_perms_wo_acl(const IsoNode *node) { mode_t st_mode; int ret; char *a_text = NULL, *d_text = NULL; st_mode = iso_node_get_permissions(node); ret = iso_node_get_acl_text((IsoNode *) node, &a_text, &d_text, 16); if (ret != 1) goto ex; aaip_cleanout_st_mode(a_text, &st_mode, 4 | 16); ex:; iso_node_get_acl_text((IsoNode *) node, &a_text, &d_text, 1 << 15); return st_mode; } /* Function to identify and manage ZF parameters. * data is supposed to be a pointer to struct zisofs_zf_info */ int zisofs_zf_xinfo_func(void *data, int flag) { if (flag & 1) { free(data); } return 1; } /* The iso_node_xinfo_cloner function which gets associated to * zisofs_zf_xinfo_func by iso_init() resp. iso_init_with_flag() via * iso_node_xinfo_make_clonable() */ int zisofs_zf_xinfo_cloner(void *old_data, void **new_data, int flag) { *new_data = NULL; if (flag) return ISO_XINFO_NO_CLONE; if (old_data == NULL) return 0; *new_data = calloc(1, sizeof(struct zisofs_zf_info)); if (*new_data == NULL) return ISO_OUT_OF_MEM; memcpy(*new_data, old_data, sizeof(struct zisofs_zf_info)); return (int) sizeof(struct zisofs_zf_info); } /* Checks whether a file effectively bears a zisofs file header and eventually * marks this by a struct zisofs_zf_info as xinfo of the file node. * @param flag bit0= inquire the most original stream of the file * bit1= permission to overwrite existing zisofs_zf_info * bit2= if no zisofs header is found: * create xinfo with parameters which indicate no zisofs * @return 1= zf xinfo added, 0= no zisofs data found , * 2= found existing zf xinfo and flag bit1 was not set * <0 means error */ int iso_file_zf_by_magic(IsoFile *file, int flag) { int ret, stream_type, header_size_div4, block_size_log2; uint32_t uncompressed_size; IsoStream *stream, *input_stream; struct zisofs_zf_info *zf = NULL; void *xipt; /* Intimate friendship with this function in filters/zisofs.c */ int ziso_is_zisofs_stream(IsoStream *stream, int *stream_type, int *header_size_div4, int *block_size_log2, uint32_t *uncompressed_size, int flag); ret = iso_node_get_xinfo((IsoNode *) file, zisofs_zf_xinfo_func, &xipt); if (ret == 1) { if (!(flag & 2)) return 2; ret = iso_node_remove_xinfo((IsoNode *) file, zisofs_zf_xinfo_func); if (ret < 0) return ret; } input_stream = stream = iso_file_get_stream(file); while (flag & 1) { input_stream = iso_stream_get_input_stream(stream, 0); if (input_stream == NULL) break; stream = input_stream; } ret = ziso_is_zisofs_stream(stream, &stream_type, &header_size_div4, &block_size_log2, &uncompressed_size, 3); if (ret < 0) return ret; if (ret != 1 || stream_type != 2) { if (flag & 4) return 0; header_size_div4 = 0; block_size_log2 = 0; uncompressed_size = 0; } zf = calloc(1, sizeof(struct zisofs_zf_info)); if (zf == NULL) return ISO_OUT_OF_MEM; zf->uncompressed_size = uncompressed_size; zf->header_size_div4 = header_size_div4; zf->block_size_log2 = block_size_log2; ret = iso_node_add_xinfo((IsoNode *) file, zisofs_zf_xinfo_func, zf); return ret; } /* API */ int iso_node_zf_by_magic(IsoNode *node, int flag) { int ret = 1, total_ret = 0, hflag; IsoFile *file; IsoNode *pos; IsoDir *dir; if (node->type == LIBISO_FILE) return iso_file_zf_by_magic((IsoFile *) node, flag); if (node->type != LIBISO_DIR || (flag & 8)) return 0; dir = (IsoDir *) node; pos = dir->children; while (pos) { ret = 1; if (pos->type == LIBISO_FILE) { file = (IsoFile *) pos; if ((flag & 16) && file->from_old_session) return 0; if (!((flag & 1) && file->from_old_session)) { if (strncmp(file->stream->class->type, "ziso", 4) == 0) return 1; /* The stream is enough of marking */ if (strncmp(file->stream->class->type, "osiz", 4) == 0) { if (flag & 2) iso_node_remove_xinfo(pos, zisofs_zf_xinfo_func); return 0; /* Will not be zisofs format */ } } hflag = flag & ~6; if ((flag & 1) && file->from_old_session) hflag |= 1; ret = iso_file_zf_by_magic(file, hflag); } else if (pos->type == LIBISO_DIR) { ret = iso_node_zf_by_magic(pos, flag); } if (ret < 0) { total_ret = ret; ret = iso_msg_submit(-1, ret, 0, NULL); if (ret < 0) { return ret; /* cancel due error threshold */ } } else if (total_ret >= 0) { total_ret |= ret; } pos = pos->next; } return total_ret; } int iso_px_ino_xinfo_func(void *data, int flag) { if (flag == 1) { free(data); } return 1; } /* The iso_node_xinfo_cloner function which gets associated to * iso_px_ino_xinfo_func by iso_init() resp. iso_init_with_flag() via * iso_node_xinfo_make_clonable() */ int iso_px_ino_xinfo_cloner(void *old_data, void **new_data, int flag) { *new_data = NULL; if (flag) return ISO_XINFO_NO_CLONE; *new_data = calloc(1, sizeof(ino_t)); if (*new_data == NULL) return ISO_OUT_OF_MEM; memcpy(*new_data, old_data, sizeof(ino_t)); return (int) sizeof(ino_t); } /* * @param flag * bit0= do only retrieve id if node is in imported ISO image * or has an explicit xinfo inode number * @return * 1= reply is valid from stream, 2= reply is valid from xinfo * 0= no id available, <0= error * (fs_id, dev_id, ino_id) will be (0,0,0) in case of return <= 0 */ int iso_node_get_id(IsoNode *node, unsigned int *fs_id, dev_t *dev_id, ino_t *ino_id, int flag) { int ret; IsoFile *file; IsoSymlink *symlink; IsoSpecial *special; void *xipt; ret = iso_node_get_xinfo(node, iso_px_ino_xinfo_func, &xipt); if (ret < 0) goto no_id; if (ret == 1) { *fs_id = ISO_IMAGE_FS_ID; *dev_id = 0; *ino_id = *((ino_t *) xipt); return 2; } if (node->type == LIBISO_FILE) { file= (IsoFile *) node; iso_stream_get_id(file->stream, fs_id, dev_id, ino_id); if (*fs_id != ISO_IMAGE_FS_ID && (flag & 1)) { ret = 0; goto no_id; } return 1; } else if (node->type == LIBISO_SYMLINK) { symlink = (IsoSymlink *) node; if (symlink->fs_id != ISO_IMAGE_FS_ID && (flag & 1)) { ret = 0; goto no_id; } *fs_id = symlink->fs_id; *dev_id = symlink->st_dev; *ino_id = symlink->st_ino; return 1; } else if (node->type == LIBISO_SPECIAL) { special = (IsoSpecial *) node; if (special->fs_id != ISO_IMAGE_FS_ID && (flag & 1)) { ret = 0; goto no_id; } *fs_id = special->fs_id; *dev_id = special->st_dev; *ino_id = special->st_ino; return 1; } ret = 0; no_id:; *fs_id = 0; *dev_id = 0; *ino_id = 0; return ret; } static int iso_node_set_ino_xinfo(IsoNode *node, ino_t ino, int flag) { int ret; void *xipt; if (flag & 1) { ret = iso_node_remove_xinfo(node, iso_px_ino_xinfo_func); if (ret < 0) return ret; } xipt = calloc(1, sizeof(ino_t)); if (xipt == NULL) return ISO_OUT_OF_MEM; memcpy(xipt, &ino, sizeof(ino_t)); ret = iso_node_add_xinfo(node, iso_px_ino_xinfo_func, xipt); return ret; } int iso_node_set_ino(IsoNode *node, ino_t ino, int flag) { int ret; IsoFile *file; IsoSymlink *symlink; IsoSpecial *special; void *xipt; ret = iso_node_get_xinfo(node, iso_px_ino_xinfo_func, &xipt); if (ret < 0) return ret; if (ret == 1) { ret = iso_node_set_ino_xinfo(node, ino, 1); if (ret < 0) return ret; return 2; } if (node->type == LIBISO_FILE) { file= (IsoFile *) node; ret = iso_stream_set_image_ino(file->stream, ino, 0); if (ret < 0 || ret == 1) return ret; /* ret == 0 means that the stream is not from loaded ISO image */ } else if (node->type == LIBISO_SYMLINK) { symlink = (IsoSymlink *) node; if (symlink->fs_id == ISO_IMAGE_FS_ID) { symlink->st_ino = ino; return 1; } } else if (node->type == LIBISO_SPECIAL) { special = (IsoSpecial *) node; if (special->fs_id == ISO_IMAGE_FS_ID) { special->st_ino = ino; return 1; } } ret = iso_node_set_ino_xinfo(node, ino, 0); if (ret < 0) return ret; return 2; } int iso_node_set_unique_id(IsoNode *node, IsoImage *image, int flag) { int ret; ino_t ino; ino = img_give_ino_number(image, 0); ret = iso_node_set_ino(node, ino, 0); return ret; } /* * Note to programmers: It is crucial not to break the following constraints. * Anti-symmetry: cmp(X,Y) == - cmp(Y,X) * Transitivity : if cmp(A,B) < 0 && cmp(B,C) < 0 then cmp(A,C) < 0 * if cmp(A,B) == 0 && cmp(B,C) == 0 then cmp(A,C) == 0 * A big transitivity hazard are tests which do not apply to some nodes. * In this case for any A that is applicable and any B that is not applicable * the comparison must have the same non-zero result. I.e. a pair of applicable * and non-applicable node must return that non-zero result before the test * for a pair of applicable nodes would happen. * * @param flag * bit0= compare stat properties and attributes * bit1= treat all nodes with image ino == 0 as unique */ int iso_node_cmp_flag(IsoNode *n1, IsoNode *n2, int flag) { int ret1, ret2; unsigned int fs_id1, fs_id2; dev_t dev_id1, dev_id2; ino_t ino_id1, ino_id2; IsoFile *f1 = NULL, *f2 = NULL; IsoSymlink *l1 = NULL, *l2 = NULL; IsoSpecial *s1 = NULL, *s2 = NULL; void *x1, *x2; if (n1 == n2) return 0; if (n1->type != n2->type) return (n1->type < n2->type ? -1 : 1); /* Imported or explicite ISO image node id has priority */ ret1 = (iso_node_get_id(n1, &fs_id1, &dev_id1, &ino_id1, 1) > 0); ret2 = (iso_node_get_id(n2, &fs_id2, &dev_id2, &ino_id2, 1) > 0); if (ret1 != ret2) return (ret1 < ret2 ? -1 : 1); if (ret1) { /* fs_id and dev_id do not matter here. Both nodes have explicit inode numbers of the emerging image. */ if (ino_id1 != ino_id2) return (ino_id1 < ino_id2 ? -1 : 1); if (ino_id1 == 0) /* Image ino 0 is always unique */ return (n1 < n2 ? -1 : 1); goto image_inode_match; } if (n1->type == LIBISO_FILE) { f1 = (IsoFile *) n1; f2 = (IsoFile *) n2; ret1 = iso_stream_cmp_ino(f1->stream, f2->stream, 0); if (ret1) return ret1; goto inode_match; } else if (n1->type == LIBISO_SYMLINK) { l1 = (IsoSymlink *) n1; l2 = (IsoSymlink *) n2; fs_id1 = l1->fs_id; dev_id1 = l1->st_dev; ino_id1 = l1->st_ino; fs_id2 = l2->fs_id; dev_id2 = l2->st_dev; ino_id2 = l2->st_ino; } else if (n1->type == LIBISO_SPECIAL) { s1 = (IsoSpecial *) n1; s2 = (IsoSpecial *) n2; fs_id1 = s1->fs_id; dev_id1 = s1->st_dev; ino_id1 = s1->st_ino; fs_id2 = s2->fs_id; dev_id2 = s2->st_dev; ino_id2 = s2->st_ino; } else { return (n1 < n2 ? -1 : 1); /* case n1 == n2 is handled above */ } if (fs_id1 != fs_id2) return (fs_id1 < fs_id2 ? -1 : 1); if (dev_id1 != dev_id2) return (dev_id1 < dev_id2 ? -1 : 1); if (ino_id1 != ino_id2) return (ino_id1 < ino_id2 ? -1 : 1); if (fs_id1 == 0 && dev_id1 == 0 && ino_id1 == 0) return (n1 < n2 ? -1 : 1); inode_match:; if (flag & 2) { /* What comes here has no predefined image ino resp. image_ino == 0 . Regard this as not equal. */ return (n1 < n2 ? -1 : 1); } image_inode_match:; if (!(flag & 1)) return 0; if (n1->type == LIBISO_SYMLINK) { l1 = (IsoSymlink *) n1; l2 = (IsoSymlink *) n2; ret1 = strcmp(l1->dest, l2->dest); if (ret1) return ret1; } else if (n1->type == LIBISO_SPECIAL) { s1 = (IsoSpecial *) n1; s2 = (IsoSpecial *) n2; if (s1->dev != s2->dev) return (s1->dev < s2->dev ? -1 : 1); } if (n1->mode != n2->mode) return (n1->mode < n2->mode ? -1 : 1); if (n1->uid != n2->uid) return (n1->uid < n2->uid ? -1 : 1); if (n1->gid != n2->gid) return (n1->gid < n2->gid ? -1 : 1); if (n1->atime != n2->atime) return (n1->atime < n2->atime ? -1 : 1); if (n1->mtime != n2->mtime) return (n1->mtime < n2->mtime ? -1 : 1); if (n1->ctime != n2->ctime) return (n1->ctime < n2->ctime ? -1 : 1); /* Compare xinfo */ /* :( cannot compare general xinfo because data length is not known :( */ /* compare aa_string */ ret1 = iso_node_get_xinfo(n1, aaip_xinfo_func, &x1); ret2 = iso_node_get_xinfo(n2, aaip_xinfo_func, &x2); if (ret1 != ret2) return (ret1 < ret2 ? -1 : 1); if (ret1 == 1) { ret1 = aaip_count_bytes((unsigned char *) x1, 0); ret2 = aaip_count_bytes((unsigned char *) x2, 0); if (ret1 != ret2) return (ret1 < ret2 ? -1 : 1); ret1 = memcmp(x1, x2, ret1); if (ret1) return ret1; } return 0; } /* API */ int iso_node_cmp_ino(IsoNode *n1, IsoNode *n2, int flag) { return iso_node_cmp_flag(n1, n2, 1); } /* @param flag bit0= delete isofs.cx rather than setting it */ int iso_file_set_isofscx(IsoFile *file, unsigned int checksum_index, int flag) { static char *names = "isofs.cx"; static size_t value_lengths[1] = {4}; unsigned char value[4]; char *valuept; int i, ret; valuept= (char *) value; if (flag & 1) { ret = iso_node_set_attrs((IsoNode *) file, (size_t) 1, &names, value_lengths, &valuept, 4 | 8); return ret; } for(i = 0; i < 4; i++) value[3 - i] = (checksum_index >> (8 * i)) & 0xff; ret = iso_node_set_attrs((IsoNode *) file, (size_t) 1, &names, value_lengths, &valuept, 2 | 8); return ret; } int iso_root_set_isofsca(IsoNode *node, uint32_t start_lba, uint32_t end_lba, uint32_t count, uint32_t size, char *typetext, int flag) { char buffer[5 + 5 + 5 + 2 + 81], *wpt = buffer, *valuept = buffer; int result_len, ret; static char *names = "isofs.ca"; static size_t value_lengths[1]; /* Set value of isofs.ca with 4 byte START, 4 byte END, 4 byte COUNT, SIZE = 16, MD5 */ iso_util_encode_len_bytes(start_lba, wpt, 4, &result_len, 0); wpt += result_len; iso_util_encode_len_bytes(end_lba, wpt, 4, &result_len, 0); wpt += result_len; iso_util_encode_len_bytes(count, wpt, 4, &result_len, 0); wpt += result_len; iso_util_encode_len_bytes(size, wpt, 1, &result_len, 0); wpt += result_len; strncpy(wpt, typetext, 80); if (strlen(typetext) > 80) wpt += 80; else wpt += strlen(typetext); value_lengths[0] = wpt - buffer; ret = iso_node_set_attrs(node, (size_t) 1, &names, value_lengths, &valuept, 2 | 8); return ret; } int iso_root_get_isofsca(IsoNode *node, uint32_t *start_lba, uint32_t *end_lba, uint32_t *count, uint32_t *size, char typetext[81], int flag) { int ret, len; size_t value_len; char *value = NULL, *rpt; ret = iso_node_lookup_attr(node, "isofs.ca", &value_len, &value, 0); if (ret <= 0) goto ex; /* Parse value of isofs.ca with 4 byte START, 4 byte END, 4 byte COUNT, SIZE = 16, MD5 */ rpt = value; iso_util_decode_len_bytes(start_lba, rpt, &len, value_len - (rpt - value), 0); rpt += len + 1; iso_util_decode_len_bytes(end_lba, rpt, &len, value_len - (rpt - value), 0); rpt += len + 1; iso_util_decode_len_bytes(count, rpt, &len, value_len - (rpt - value), 0); rpt += len + 1; iso_util_decode_len_bytes(size, rpt, &len, value_len - (rpt - value), 0); rpt += len + 1; len = value_len - (rpt - value); if (len > 80) len = 80; memcpy(typetext, rpt, len); typetext[len] = 0; ret= ISO_SUCCESS; ex:; if (value != NULL) free(value); return ret; } int iso_root_set_isofsnt(IsoNode *node, uint32_t truncate_mode, uint32_t truncate_length, int flag) { char buffer[5 + 5], *wpt = buffer, *valuept = buffer; int result_len, ret; static char *names = "isofs.nt"; static size_t value_lengths[1]; iso_util_encode_len_bytes(truncate_mode, wpt, 0, &result_len, 0); wpt += result_len; iso_util_encode_len_bytes(truncate_length, wpt, 0, &result_len, 0); wpt += result_len; value_lengths[0] = wpt - buffer; ret = iso_node_set_attrs(node, (size_t) 1, &names, value_lengths, &valuept, 2 | 8); return ret; } int iso_root_get_isofsnt(IsoNode *node, uint32_t *truncate_mode, uint32_t *truncate_length, int flag) { int ret, len; size_t value_len; char *value = NULL, *rpt; ret = iso_node_lookup_attr(node, "isofs.nt", &value_len, &value, 0); if (ret <= 0) goto ex; rpt = value; iso_util_decode_len_bytes(truncate_mode, rpt, &len, value_len - (rpt - value), 0); rpt += len + 1; iso_util_decode_len_bytes(truncate_length, rpt, &len, value_len - (rpt - value), 0); ret= ISO_SUCCESS; ex:; if (value != NULL) free(value); return ret; } /* API */ int iso_file_get_md5(IsoImage *image, IsoFile *file, char md5[16], int flag) { int ret, i; size_t value_len; char *value = NULL; uint32_t idx = 0; void *xipt; /* xinfo MD5 overrides everything else */ ret = iso_node_get_xinfo((IsoNode *) file, checksum_md5_xinfo_func, &xipt); if (ret == 1) { memcpy(md5, (char *) xipt, 16); return 1; } if (image->checksum_array == NULL) return 0; ret = iso_node_lookup_attr((IsoNode *) file, "isofs.cx", &value_len, &value, 0); if (ret <= 0) goto ex; if (value_len > 4) { ret = 0; goto ex; } for (i = 0; i < (int) value_len; i++) idx = (idx << 8) | ((unsigned char *) value)[i]; if (idx == 0 || idx > image->checksum_idx_count - 1) { /* (last index is not MD5 of a file) */ ret = 0; goto ex; } if (!(flag & 1)) { memcpy(md5, image->checksum_array + ((size_t) 16) * ((size_t) idx), 16); } ret = 1; ex:; if (value != NULL) free(value); return ret; } /* API */ int iso_file_make_md5(IsoFile *file, int flag) { int ret, dig = 0; char *md5 = NULL; if (file->from_old_session) dig = 1; md5 = calloc(16, 1); if (md5 == NULL) return ISO_OUT_OF_MEM; ret = iso_stream_make_md5(file->stream, md5, dig); if (ret < 0) { free(md5); return ret; } iso_node_remove_xinfo((IsoNode *) file, checksum_md5_xinfo_func); ret = iso_node_add_xinfo((IsoNode *) file, checksum_md5_xinfo_func, md5); if (ret == 0) ret = ISO_ERROR; /* should not happen after iso_node_remove_xinfo() */ if (ret < 0) { free(md5); return ret; } return 1; } libisofs-1.4.2/libisofs/libiso_msgs.c0000644000175700017510000002436012321161425014553 00000000000000 /* libiso_msgs (generated from libdax_msgs : Fri Feb 22 19:42:52 CET 2008) Message handling facility of libisofs. Copyright (C) 2006 - 2008 Thomas Schmitt , provided under GPL version 2 or later */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif #include #include #include #include #include #include #include /* Only this single source module is entitled to do this */ #define LIBISO_MSGS_H_INTERNAL 1 /* All participants in the messaging system must do this */ #include "libiso_msgs.h" /* ----------------------------- libiso_msgs_item ------------------------- */ static int libiso_msgs_item_new(struct libiso_msgs_item **item, struct libiso_msgs_item *link, int flag) { int ret; struct libiso_msgs_item *o; struct timeval tv; struct timezone tz; (*item)= o= (struct libiso_msgs_item *) malloc(sizeof(struct libiso_msgs_item)); if(o==NULL) return(-1); o->timestamp= 0.0; ret= gettimeofday(&tv,&tz); if(ret==0) o->timestamp= tv.tv_sec+0.000001*tv.tv_usec; o->process_id= getpid(); o->origin= -1; o->severity= LIBISO_MSGS_SEV_ALL; o->priority= LIBISO_MSGS_PRIO_ZERO; o->error_code= 0; o->msg_text= NULL; o->os_errno= 0; o->prev= link; o->next= NULL; if(link!=NULL) { if(link->next!=NULL) { link->next->prev= o; o->next= link->next; } link->next= o; } return(1); } /** Detaches item from its queue and eventually readjusts start, end pointers of the queue */ int libiso_msgs_item_unlink(struct libiso_msgs_item *o, struct libiso_msgs_item **chain_start, struct libiso_msgs_item **chain_end, int flag) { if(o->prev!=NULL) o->prev->next= o->next; if(o->next!=NULL) o->next->prev= o->prev; if(chain_start!=NULL) if(*chain_start == o) *chain_start= o->next; if(chain_end!=NULL) if(*chain_end == o) *chain_end= o->prev; o->next= o->prev= NULL; return(1); } int libiso_msgs_item_destroy(struct libiso_msgs_item **item, int flag) { struct libiso_msgs_item *o; o= *item; if(o==NULL) return(0); libiso_msgs_item_unlink(o,NULL,NULL,0); if(o->msg_text!=NULL) free((char *) o->msg_text); free((char *) o); *item= NULL; return(1); } int libiso_msgs_item_get_msg(struct libiso_msgs_item *item, int *error_code, char **msg_text, int *os_errno, int flag) { *error_code= item->error_code; *msg_text= item->msg_text; *os_errno= item->os_errno; return(1); } int libiso_msgs_item_get_origin(struct libiso_msgs_item *item, double *timestamp, pid_t *process_id, int *origin, int flag) { *timestamp= item->timestamp; *process_id= item->process_id; *origin= item->origin; return(1); } int libiso_msgs_item_get_rank(struct libiso_msgs_item *item, int *severity, int *priority, int flag) { *severity= item->severity; *priority= item->priority; return(1); } /* ------------------------------- libiso_msgs ---------------------------- */ int libiso_msgs_new(struct libiso_msgs **m, int flag) { struct libiso_msgs *o; (*m)= o= (struct libiso_msgs *) malloc(sizeof(struct libiso_msgs)); if(o==NULL) return(-1); o->refcount= 1; o->oldest= NULL; o->youngest= NULL; o->count= 0; o->queue_severity= LIBISO_MSGS_SEV_ALL; o->print_severity= LIBISO_MSGS_SEV_NEVER; strcpy(o->print_id,"libiso: "); #ifndef LIBISO_MSGS_SINGLE_THREADED pthread_mutex_init(&(o->lock_mutex),NULL); #endif return(1); } static int libiso_msgs_lock(struct libiso_msgs *m, int flag) { #ifndef LIBISO_MSGS_SINGLE_THREADED int ret; ret= pthread_mutex_lock(&(m->lock_mutex)); if(ret!=0) return(0); #endif return(1); } static int libiso_msgs_unlock(struct libiso_msgs *m, int flag) { #ifndef LIBISO_MSGS_SINGLE_THREADED int ret; ret= pthread_mutex_unlock(&(m->lock_mutex)); if(ret!=0) return(0); #endif return(1); } int libiso_msgs_destroy(struct libiso_msgs **m, int flag) { struct libiso_msgs *o; struct libiso_msgs_item *item, *next_item; o= *m; if(o==NULL) return(0); if(o->refcount > 1) { if(libiso_msgs_lock(*m,0)<=0) return(-1); o->refcount--; libiso_msgs_unlock(*m,0); *m= NULL; return(1); } #ifndef LIBISO_MSGS_SINGLE_THREADED if(pthread_mutex_destroy(&(o->lock_mutex))!=0) { pthread_mutex_unlock(&(o->lock_mutex)); pthread_mutex_destroy(&(o->lock_mutex)); } #endif for(item= o->oldest; item!=NULL; item= next_item) { next_item= item->next; libiso_msgs_item_destroy(&item,0); } free((char *) o); *m= NULL; return(1); } int libiso_msgs_refer(struct libiso_msgs **pt, struct libiso_msgs *m, int flag) { if(libiso_msgs_lock(m,0)<=0) return(0); m->refcount++; *pt= m; libiso_msgs_unlock(m,0); return(1); } int libiso_msgs_set_severities(struct libiso_msgs *m, int queue_severity, int print_severity, char *print_id, int flag) { if(libiso_msgs_lock(m,0)<=0) return(0); m->queue_severity= queue_severity; m->print_severity= print_severity; strncpy(m->print_id,print_id,80); m->print_id[80]= 0; libiso_msgs_unlock(m,0); return(1); } int libiso_msgs__text_to_sev(char *severity_name, int *severity, int flag) { if(strncmp(severity_name,"NEVER",5)==0) *severity= LIBISO_MSGS_SEV_NEVER; else if(strncmp(severity_name,"ABORT",5)==0) *severity= LIBISO_MSGS_SEV_ABORT; else if(strncmp(severity_name,"FATAL",5)==0) *severity= LIBISO_MSGS_SEV_FATAL; else if(strncmp(severity_name,"FAILURE",7)==0) *severity= LIBISO_MSGS_SEV_FAILURE; else if(strncmp(severity_name,"MISHAP",6)==0) *severity= LIBISO_MSGS_SEV_MISHAP; else if(strncmp(severity_name,"SORRY",5)==0) *severity= LIBISO_MSGS_SEV_SORRY; else if(strncmp(severity_name,"WARNING",7)==0) *severity= LIBISO_MSGS_SEV_WARNING; else if(strncmp(severity_name,"HINT",4)==0) *severity= LIBISO_MSGS_SEV_HINT; else if(strncmp(severity_name,"NOTE",4)==0) *severity= LIBISO_MSGS_SEV_NOTE; else if(strncmp(severity_name,"UPDATE",6)==0) *severity= LIBISO_MSGS_SEV_UPDATE; else if(strncmp(severity_name,"DEBUG",5)==0) *severity= LIBISO_MSGS_SEV_DEBUG; else if(strncmp(severity_name,"ERRFILE",7)==0) *severity= LIBISO_MSGS_SEV_ERRFILE; else if(strncmp(severity_name,"ALL",3)==0) *severity= LIBISO_MSGS_SEV_ALL; else { *severity= LIBISO_MSGS_SEV_ALL; return(0); } return(1); } int libiso_msgs__sev_to_text(int severity, char **severity_name, int flag) { if(flag&1) { *severity_name= "ALL ERRFILE DEBUG UPDATE NOTE HINT WARNING SORRY MISHAP FAILURE FATAL ABORT NEVER"; return(1); } *severity_name= ""; if(severity>=LIBISO_MSGS_SEV_NEVER) *severity_name= "NEVER"; else if(severity>=LIBISO_MSGS_SEV_ABORT) *severity_name= "ABORT"; else if(severity>=LIBISO_MSGS_SEV_FATAL) *severity_name= "FATAL"; else if(severity>=LIBISO_MSGS_SEV_FAILURE) *severity_name= "FAILURE"; else if(severity>=LIBISO_MSGS_SEV_MISHAP) *severity_name= "MISHAP"; else if(severity>=LIBISO_MSGS_SEV_SORRY) *severity_name= "SORRY"; else if(severity>=LIBISO_MSGS_SEV_WARNING) *severity_name= "WARNING"; else if(severity>=LIBISO_MSGS_SEV_HINT) *severity_name= "HINT"; else if(severity>=LIBISO_MSGS_SEV_NOTE) *severity_name= "NOTE"; else if(severity>=LIBISO_MSGS_SEV_UPDATE) *severity_name= "UPDATE"; else if(severity>=LIBISO_MSGS_SEV_DEBUG) *severity_name= "DEBUG"; else if(severity>=LIBISO_MSGS_SEV_ERRFILE) *severity_name= "ERRFILE"; else if(severity>=LIBISO_MSGS_SEV_ALL) *severity_name= "ALL"; else { *severity_name= ""; return(0); } return(1); } int libiso_msgs_submit(struct libiso_msgs *m, int origin, int error_code, int severity, int priority, char *msg_text, int os_errno, int flag) { int ret; char *textpt,*sev_name,sev_text[81]; struct libiso_msgs_item *item= NULL; if(severity >= m->print_severity) { if(msg_text==NULL) textpt= ""; else textpt= msg_text; sev_text[0]= 0; ret= libiso_msgs__sev_to_text(severity,&sev_name,0); if(ret>0) sprintf(sev_text,"%s : ",sev_name); fprintf(stderr,"%s%s%s\n",m->print_id,sev_text,textpt); if(os_errno!=0) { ret= libiso_msgs_lock(m,0); if(ret<=0) return(-1); fprintf(stderr,"%s( Most recent system error: %d '%s' )\n", m->print_id,os_errno,strerror(os_errno)); libiso_msgs_unlock(m,0); } } if(severity < m->queue_severity) return(0); ret= libiso_msgs_lock(m,0); if(ret<=0) return(-1); ret= libiso_msgs_item_new(&item,m->youngest,0); if(ret<=0) goto failed; item->origin= origin; item->error_code= error_code; item->severity= severity; item->priority= priority; if(msg_text!=NULL) { item->msg_text= malloc(strlen(msg_text)+1); if(item->msg_text==NULL) goto failed; strcpy(item->msg_text,msg_text); } item->os_errno= os_errno; if(m->oldest==NULL) m->oldest= item; m->youngest= item; m->count++; libiso_msgs_unlock(m,0); /* fprintf(stderr,"libiso_experimental: message submitted to queue (now %d)\n", m->count); */ return(1); failed:; libiso_msgs_item_destroy(&item,0); libiso_msgs_unlock(m,0); return(-1); } int libiso_msgs_obtain(struct libiso_msgs *m, struct libiso_msgs_item **item, int severity, int priority, int flag) { int ret; struct libiso_msgs_item *im, *next_im= NULL; *item= NULL; ret= libiso_msgs_lock(m,0); if(ret<=0) return(-1); for(im= m->oldest; im!=NULL; im= next_im) { for(; im!=NULL; im= next_im) { next_im= im->next; if(im->severity>=severity) break; libiso_msgs_item_unlink(im,&(m->oldest),&(m->youngest),0); libiso_msgs_item_destroy(&im,0); /* severity too low: delete */ } if(im==NULL) break; if(im->priority>=priority) break; } if(im==NULL) {ret= 0; goto ex;} libiso_msgs_item_unlink(im,&(m->oldest),&(m->youngest),0); *item= im; ret= 1; ex:; libiso_msgs_unlock(m,0); return(ret); } int libiso_msgs_destroy_item(struct libiso_msgs *m, struct libiso_msgs_item **item, int flag) { int ret; ret= libiso_msgs_lock(m,0); if(ret<=0) return(-1); ret= libiso_msgs_item_destroy(item,0); libiso_msgs_unlock(m,0); return(ret); } libisofs-1.4.2/libisofs/aaip-os-freebsd.c0000644000175700017510000007111712557153127015217 00000000000000 /* aaip-os-freebsd.c Arbitrary Attribute Interchange Protocol , system adapter for getting and setting of ACLs and xattr. To be included by aaip_0_2.c for FreeBSD and NetBSD Copyright (c) 2009 - 2014 Thomas Schmitt, libburnia project, GPLv2+ */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif #include #include #include #include #include #include #include #include #ifdef Libisofs_with_aaip_acL #include #endif #ifdef Libisofs_with_freebsd_extattR #include #endif #include /* <<< Use old ACL adapter code that is unable to deal with extattr */ /* # define Libisofs_old_freebsd_acl_adapteR */ /* ------------------------------ Inquiry --------------------------------- */ /* See also API iso_local_attr_support(). @param flag Bitfield for control purposes bit0= inquire availability of ACL bit1= inquire availability of xattr bit2 - bit7= Reserved for future types. It is permissibile to set them to 1 already now. bit8 and higher: reserved, submit 0 @return Bitfield corresponding to flag. bit0= ACL adapter is enabled bit1= xattr adapter is enabled bit2 - bit7= Reserved for future types. bit8 and higher: reserved, do not interpret these */ int aaip_local_attr_support(int flag) { int ret= 0; #ifdef Libisofs_with_aaip_acL if(flag & 1) ret|= 1; #endif #ifdef Libisofs_with_freebsd_extattR if(flag & 2) ret|= 2; #endif return(ret); } #ifdef Libisofs_with_freebsd_extattR static int aaip_extattr_path_supp(char *path, int flag) { #ifdef MNT_EXTATTR int ret; struct statvfs statvfs_buf; ret = statvfs(path, &statvfs_buf); if(ret == -1) return(1); return(!!(statvfs_buf.f_flag & MNT_EXTATTR)); #else /* MNT_EXTATTR */ return(1); #endif /* ! MNT_EXTATTR */ } #endif /* Libisofs_with_freebsd_extattR */ /* ------------------------------ Getters --------------------------------- */ /* Obtain the ACL of the given file in long text form. @param path Path to the file @param text Will hold the result. This is a managed object which finally has to be freed by a call to this function with bit15 of flag. @param flag Bitfield for control purposes (bit0= obtain default ACL rather than access ACL) bit4= set *text = NULL and return 2 if the ACL matches st_mode permissions. bit5= in case of symbolic link: inquire link target bit15= free text and return 1 @return > 0 ok 0 ACL support not enabled at compile time or filesystem does not support ACL -1 failure of system ACL service (see errno) -2 attempt to inquire ACL of a symbolic link without bit4 or bit5 */ int aaip_get_acl_text(char *path, char **text, int flag) { #ifdef Libisofs_with_aaip_acL acl_t acl= NULL; #endif struct stat stbuf; int ret; if(flag & (1 << 15)) { if(*text != NULL) #ifdef Libisofs_with_aaip_acL acl_free(*text); #else free(*text); #endif *text= NULL; return(1); } *text= NULL; if(flag & 32) ret= stat(path, &stbuf); else ret= lstat(path, &stbuf); if(ret == -1) return(-1); if((stbuf.st_mode & S_IFMT) == S_IFLNK) { if(flag & 16) return(2); return(-2); } /* Note: no ACL_TYPE_DEFAULT in FreeBSD */ if(flag & 1) return(0); #ifdef Libisofs_with_aaip_acL acl= acl_get_file(path, ACL_TYPE_ACCESS); if(acl == NULL) { if(errno == EOPNOTSUPP) { /* filesystem does not support ACL */ if(flag & 16) return(2); /* >>> ??? fake ACL from POSIX permissions ? */; return(0); } return(-1); } *text= acl_to_text(acl, NULL); acl_free(acl); #else /* Libisofs_with_aaip_acL */ /* ??? >>> Fake ACL */; return(0); #endif /* ! Libisofs_with_aaip_acL */ if(*text == NULL) return(-1); if(flag & 16) { ret = aaip_cleanout_st_mode(*text, &(stbuf.st_mode), 2); if(!(ret & (7 | 64))) (*text)[0]= 0; if((*text)[0] == 0 || strcmp(*text, "\n") == 0) { #ifdef Libisofs_with_aaip_acL acl_free(*text); #else free(*text); #endif *text= NULL; return(2); } } return(1); } #ifndef Libisofs_old_freebsd_acl_adapteR #ifdef Libisofs_with_freebsd_extattR /* @param flag Bitfield for control purposes bit5= in case of symbolic link: inquire link target */ static int aaip_extattr_make_list(char *path, int attrnamespace, char **list, ssize_t *list_size, int flag) { *list= NULL; *list_size= 0; /* man 2 extattr_list_file: If data is NULL in a call to extattr_get_file() and extattr_list_file() then the size of defined extended attribute data will be returned, */ if(flag & 32) /* follow link */ *list_size= extattr_list_file(path, attrnamespace, NULL, (size_t) 0); else *list_size= extattr_list_link(path, attrnamespace, NULL, (size_t) 0); if(*list_size == -1) { if(! aaip_extattr_path_supp(path, 0)) { *list_size = 0; return(2); } return(0); } if(*list_size == 0) return(2); *list= calloc(*list_size, 1); if(*list == NULL) return(-1); if(flag & 32) *list_size= extattr_list_file(path, attrnamespace, *list, (size_t) *list_size); else *list_size= extattr_list_link(path, attrnamespace, *list, (size_t) *list_size); if(*list_size == -1) return(0); return(1); } /* @param flag Bitfield for control purposes bit0= preserve existing namelist content bit1= ignore names with NUL rather than returning error */ static int aaip_extattr_make_namelist(char *path, char *attrnamespace, char *list, ssize_t list_size, char **namelist, ssize_t *namelist_size, ssize_t *num_names, int flag) { int i, j, len, new_bytes= 0, space_len; char *new_list= NULL, *wpt; if(!(flag & 1)) { *namelist= NULL; *namelist_size= 0; *num_names= 0; } if(list_size <= 0) return(1); space_len= strlen(attrnamespace); for(i= 0; i < list_size; i+= len + 1) { len= *((unsigned char *) (list + i)); if(len == 0) return ISO_AAIP_BAD_ATTR_NAME; /* empty name is reserved for ACL */ for(j= 0; j < len; j++) if(list[i + 1 + j] == 0) { if(flag & 2) continue; return ISO_AAIP_BAD_ATTR_NAME; /* names may not contain 0-bytes */ } new_bytes+= space_len + 1 + len + 1; } if((flag & 1) && *namelist_size > 0) new_bytes+= *namelist_size; new_list= calloc(new_bytes, 1); if(new_list == NULL) return(ISO_OUT_OF_MEM); wpt= new_list; if((flag & 1) && *namelist_size > 0) { memcpy(new_list, *namelist, *namelist_size); wpt= new_list + *namelist_size; } for(i= 0; i < list_size; i+= len + 1) { len= *((unsigned char *) (list + i)); if(flag & 2) { for(j= 0; j < len; j++) if(list[i + j] == 0) continue; } memcpy(wpt, attrnamespace, space_len); wpt[space_len]= '.'; wpt+= space_len + 1; memcpy(wpt, list + i + 1, len); wpt+= len; *(wpt++)= 0; (*num_names)++; } if((flag & 1) && *namelist != NULL) free(*namelist); *namelist= new_list; *namelist_size= new_bytes; return(1); } #endif /* Libisofs_with_freebsd_extattR */ /* Obtain the Extended Attributes and/or the ACLs of the given file in a form that is ready for aaip_encode(). @param path Path to the file @param num_attrs Will return the number of name-value pairs @param names Will return an array of pointers to 0-terminated names @param value_lengths Will return an arry with the lenghts of values @param values Will return an array of pointers to 8-bit values @param flag Bitfield for control purposes bit0= obtain ACL (access and eventually default) bit1= use numeric ACL qualifiers rather than names bit2= do not obtain attributes other than ACL bit3= do not ignore eventual non-user attributes I.e. those with a name which does not begin by "user." bit4= do not return trivial ACL that matches st_mode bit5= in case of symbolic link: inquire link target bit15= free memory of names, value_lengths, values @return >0 ok <=0 error -1= out of memory -2= program error with prediction of result size -3= error with conversion of name to uid or gid */ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names, size_t **value_lengths, char ***values, int flag) { int ret; ssize_t i, num_names= 0, acl_names= 0; #ifdef Libisofs_with_aaip_acL unsigned char *a_acl= NULL; char *a_acl_text= NULL; size_t a_acl_len= 0; #endif #ifdef Libisofs_with_freebsd_extattR char *list= NULL, *user_list= NULL, *sys_list= NULL, *namept; ssize_t value_ret, retry= 0, list_size= 0, user_list_size= 0; ssize_t sys_list_size= 0; int attrnamespace; #endif if(flag & (1 << 15)) { /* Free memory */ {ret= 1; goto ex;} } *num_attrs= 0; *names= NULL; *value_lengths= NULL; *values= NULL; /* Set up arrays */ #ifdef Libisofs_with_freebsd_extattR if(!(flag & 4)) { /* Get extattr names */ /* Linux : Names are encoded as name NUL FreeBSD: Names are encoded as length_byte:chars (no NUL) AAIP demands names not to contain NUL bytes. */ /* Obtain lists of names Must be done separately for namespaces. See man 9 extattr : EXTATTR_NAMESPACE_USER , EXTATTR_NAMESPACE_SYSTEM Must then be marked by "user." and "system." for libisofs use. */ ret= aaip_extattr_make_list(path, EXTATTR_NAMESPACE_USER, &user_list, &user_list_size, flag & 32); if(ret <= 0) {ret= -1; goto ex;} if(flag & 8) { ret= aaip_extattr_make_list(path, EXTATTR_NAMESPACE_SYSTEM, &sys_list, &sys_list_size, flag & 32); if(ret <= 0) {ret= -1; goto ex;} } /* Check for NUL in names, convert into a linuxish list of namespace.name */ ret= aaip_extattr_make_namelist(path, "user", user_list, user_list_size, &list, &list_size, &num_names, 0); if(ret <= 0) goto ex; ret= aaip_extattr_make_namelist(path, "system", sys_list, sys_list_size, &list, &list_size, &num_names, 1); if(ret <= 0) goto ex; } #endif /* Libisofs_with_freebsd_extattR */ #ifdef Libisofs_with_aaip_acL if(flag & 1) { num_names++; acl_names= 1; } #endif if(num_names == 0) {ret= 1; goto ex;} (*names)= calloc(num_names, sizeof(char *)); (*value_lengths)= calloc(num_names, sizeof(size_t)); (*values)= calloc(num_names, sizeof(char *)); if(*names == NULL || *value_lengths == NULL || *values == NULL) {ret= -1; goto ex;} for(i= 0; i < num_names; i++) { (*names)[i]= NULL; (*values)[i]= NULL; (*value_lengths)[i]= 0; } #ifdef Libisofs_with_freebsd_extattR if(!(flag & 4)) { /* Get xattr values */ for(i= 0; i < list_size && (size_t) num_names - acl_names > *num_attrs; i+= strlen(list + i) + 1) { if(!(flag & 8)) if(strncmp(list + i, "user.", 5)) continue; (*names)[(*num_attrs)++]= strdup(list + i); if((*names)[(*num_attrs) - 1] == NULL) {ret= -1; goto ex;} } for(i= 0; (size_t) i < *num_attrs; i++) { if(strncmp((*names)[i], "user.", 5) == 0) { attrnamespace= EXTATTR_NAMESPACE_USER; namept= (*names)[i] + 5; } else { if(!(flag & 8)) continue; attrnamespace= EXTATTR_NAMESPACE_SYSTEM; namept= (*names)[i] + 7; } /* Predict length of value */ if(flag & 32) /* follow link */ value_ret= extattr_get_file(path, attrnamespace, namept, NULL, (size_t) 0); else value_ret= extattr_get_link(path, attrnamespace, namept, NULL, (size_t) 0); if(value_ret == -1) continue; (*values)[i]= calloc(value_ret + 1, 1); if((*values)[i] == NULL) {ret= -1; goto ex;} /* Obtain value */ if(flag & 32) /* follow link */ value_ret= extattr_get_file(path, attrnamespace, namept, (*values)[i], (size_t) value_ret); else value_ret= extattr_get_link(path, attrnamespace, namept, (*values)[i], (size_t) value_ret); if(value_ret == -1) { /* there could be a race condition */ if(retry++ > 5) {ret= -1; goto ex;} i--; continue; } (*value_lengths)[i]= value_ret; retry= 0; } } #endif /* Libisofs_with_freebsd_extattR */ #ifdef Libisofs_with_aaip_acL if(flag & 1) { /* Obtain ACL */ /* access-ACL */ aaip_get_acl_text(path, &a_acl_text, flag & (16 | 32)); if(a_acl_text == NULL) {ret= 1; goto ex;} /* empty ACL / only st_mode info was found in ACL */ ret= aaip_encode_acl(a_acl_text, (mode_t) 0, &a_acl_len, &a_acl, flag & 2); if(ret <= 0) goto ex; /* Note: There are no default-ACL in FreeBSD */ /* Set as attribute with empty name */; (*names)[*num_attrs]= strdup(""); if((*names)[*num_attrs] == NULL) {ret= -1; goto ex;} (*values)[*num_attrs]= (char *) a_acl; a_acl= NULL; (*value_lengths)[*num_attrs]= a_acl_len; (*num_attrs)++; } #endif /* Libisofs_with_aaip_acL */ ret= 1; ex:; #ifdef Libisofs_with_aaip_acL if(a_acl != NULL) free(a_acl); if(a_acl_text != NULL) aaip_get_acl_text("", &a_acl_text, 1 << 15); /* free */ #endif #ifdef Libisofs_with_freebsd_extattR if(list != NULL) free(list); if(user_list != NULL) free(user_list); if(sys_list != NULL) free(sys_list); #endif if(ret <= 0 || (flag & (1 << 15))) { if(*names != NULL) { for(i= 0; (size_t) i < *num_attrs; i++) free((*names)[i]); free(*names); } *names= NULL; if(*value_lengths != NULL) free(*value_lengths); *value_lengths= NULL; if(*values != NULL) { for(i= 0; (size_t) i < *num_attrs; i++) free((*values)[i]); free(*values); } *values= NULL; *num_attrs= 0; } return(ret); } #else /* ! Libisofs_old_freebsd_acl_adapteR */ /* Obtain the Extended Attributes and/or the ACLs of the given file in a form that is ready for aaip_encode(). Note: There are no Extended Attributes in FreeBSD. So only ACL will be obtained. @param path Path to the file @param num_attrs Will return the number of name-value pairs @param names Will return an array of pointers to 0-terminated names @param value_lengths Will return an arry with the lenghts of values @param values Will return an array of pointers to 8-bit values @param flag Bitfield for control purposes bit0= obtain ACL (access and eventually default) bit1= use numeric ACL qualifiers rather than names bit2= do not encode attributes other than ACL bit3= do not ignore eventual non-user attributes I.e. those which are not from name space EXTATTR_NAMESPACE_USER bit4= do not return trivial ACL that matches st_mode bit15= free memory of names, value_lengths, values @return >0 ok <=0 error -1= out of memory -2= program error with prediction of result size -3= error with conversion of name to uid or gid */ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names, size_t **value_lengths, char ***values, int flag) { int ret; ssize_t i, num_names; #ifdef Libisofs_with_aaip_acL size_t a_acl_len= 0; unsigned char *a_acl= NULL; char *acl_text= NULL; #endif if(flag & (1 << 15)) { /* Free memory */ {ret= 1; goto ex;} } *num_attrs= 0; *names= NULL; *value_lengths= NULL; *values= NULL; num_names= 0; if(flag & 1) num_names++; if(num_names == 0) {ret= 1; goto ex;} (*names)= calloc(num_names, sizeof(char *)); (*value_lengths)= calloc(num_names, sizeof(size_t)); (*values)= calloc(num_names, sizeof(char *)); if(*names == NULL || *value_lengths == NULL || *values == NULL) {ret= -1; goto ex;} for(i= 0; i < num_names; i++) { (*names)[i]= NULL; (*values)[i]= NULL; (*value_lengths)[i]= 0; } #ifdef Libisofs_with_aaip_acL if(flag & 1) { /* Obtain ACL */ /* access-ACL */ aaip_get_acl_text(path, &acl_text, flag & (16 | 32)); if(acl_text == NULL) {ret= 1; goto ex;} /* empty ACL / only st_mode info was found in ACL */ ret= aaip_encode_acl(acl_text, (mode_t) 0, &a_acl_len, &a_acl, flag & 2); if(ret <= 0) goto ex; aaip_get_acl_text("", &acl_text, 1 << 15); /* free */ /* Note: There are no default-ACL in FreeBSD */ /* Set as attribute with empty name */; (*names)[*num_attrs]= strdup(""); if((*names)[*num_attrs] == NULL) {ret= -1; goto ex;} (*values)[*num_attrs]= (char *) a_acl; a_acl= NULL; (*value_lengths)[*num_attrs]= a_acl_len; (*num_attrs)++; } #endif /* ! Libisofs_with_aaip_acL */ ret= 1; ex:; #ifdef Libisofs_with_aaip_acL if(a_acl != NULL) free(a_acl); if(acl_text != NULL) aaip_get_acl_text("", &acl_text, 1 << 15); /* free */ #endif /* Libisofs_with_aaip_acL */ if(ret <= 0 || (flag & (1 << 15))) { if(*names != NULL) { for(i= 0; i < (ssize_t) *num_attrs; i++) free((*names)[i]); free(*names); } *names= NULL; if(*value_lengths != NULL) free(*value_lengths); *value_lengths= NULL; if(*values != NULL) { for(i= 0; i < (ssize_t) *num_attrs; i++) free((*values)[i]); free(*values); } *values= NULL; *num_attrs= 0; } return(ret); } #endif /* Libisofs_old_freebsd_acl_adapteR */ /* ------------------------------ Setters --------------------------------- */ /* Set the ACL of the given file to a given list in long text form. @param path Path to the file @param text The input text (0 terminated, ACL long text form) @param flag Bitfield for control purposes bit0= set default ACL rather than access ACL bit5= in case of symbolic link: manipulate link target bit6= tolerate inappropriate presence or absence of directory default ACL @return > 0 ok 0 no suitable ACL manipulation adapter available -1 failure of system ACL service (see errno) -2 attempt to manipulate ACL of a symbolic link without bit5 or with no suitable link target */ int aaip_set_acl_text(char *path, char *text, int flag) { #ifdef Libisofs_with_aaip_acL int ret; acl_t acl= NULL; struct stat stbuf; if(flag & 32) ret= stat(path, &stbuf); else ret= lstat(path, &stbuf); if(ret == -1) return(-1); if((stbuf.st_mode & S_IFMT) == S_IFLNK) return(-2); acl= acl_from_text(text); if(acl == NULL) { ret= -1; goto ex; } /* Note: no ACL_TYPE_DEFAULT in FreeBSD */ if(flag & 1) {ret= 0; goto ex;} ret= acl_set_file(path, ACL_TYPE_ACCESS, acl); if(ret == -1) goto ex; ret= 1; ex: if(acl != NULL) acl_free(acl); return(ret); #else /* Libisofs_with_aaip_acL */ return(0); #endif /* ! Libisofs_with_aaip_acL */ } #ifndef Libisofs_old_freebsd_acl_adapteR #ifdef Libisofs_with_freebsd_extattR /* @param flag Bitfield for control purposes bit5= in case of symbolic link: manipulate link target */ static int aaip_extattr_delete_names(char *path, int attrnamespace, char *list, ssize_t list_size, int flag) { int len; char name[256]; ssize_t value_ret, i; for(i= 0; i < list_size; i+= len + 1) { len= *((unsigned char *) (list + i)); if(len > 0) strncpy(name, list + i + 1, len); name[len]= 0; if(flag & 32) value_ret= extattr_delete_file(path, attrnamespace, name); else value_ret= extattr_delete_file(path, attrnamespace, name); if(value_ret == -1) return(0); } return(1); } #endif /* Libisofs_with_freebsd_extattR */ /* Bring the given attributes and/or ACLs into effect with the given file. @param flag Bitfield for control purposes bit0= decode and set ACLs bit1= first clear all existing attributes of the file bit2= do not set attributes other than ACLs bit3= do not ignore eventual non-user attributes. I.e. those with a name which does not begin by "user." bit5= in case of symbolic link: manipulate link target bit6= tolerate inappropriate presence or absence of directory default ACL @return 1 success -1 error memory allocation -2 error with decoding of ACL -3 error with setting ACL -4 error with setting attribute -5 error with deleting attributes -6 support of xattr not enabled at compile time -7 support of ACL not enabled at compile time -8 unsupported xattr namespace ISO_AAIP_ACL_MULT_OBJ multiple entries of user::, group::, other:: */ int aaip_set_attr_list(char *path, size_t num_attrs, char **names, size_t *value_lengths, char **values, int flag) { int ret, has_default_acl= 0; size_t i, consumed, acl_text_fill, acl_idx= 0; char *acl_text= NULL; #ifdef Libisofs_with_freebsd_extattR char *user_list= NULL, *sys_list= NULL, *namept; ssize_t user_list_size= 0, sys_list_size= 0; int attrnamespace; #endif #ifdef Libisofs_with_freebsd_extattR if(flag & 2) { /* Delete all file attributes */ ret= aaip_extattr_make_list(path, EXTATTR_NAMESPACE_USER, &user_list, &user_list_size, flag & 32); if(ret <= 0) {ret= -1; goto ex;} ret= aaip_extattr_delete_names(path, EXTATTR_NAMESPACE_USER, user_list, user_list_size, flag & 32); if(ret <= 0) {ret= -5; goto ex;} if(flag & 8) { ret= aaip_extattr_make_list(path, EXTATTR_NAMESPACE_SYSTEM, &sys_list, &sys_list_size, flag & 32); if(ret <= 0) {ret= -5; goto ex;} ret= aaip_extattr_delete_names(path, EXTATTR_NAMESPACE_SYSTEM, sys_list, sys_list_size, flag & 32); if(ret <= 0) {ret= -5; goto ex;} } } #endif /* Libisofs_with_freebsd_extattR */ for(i= 0; i < num_attrs; i++) { if(names[i] == NULL || values[i] == NULL) continue; if(names[i][0] == 0) { /* ACLs */ if(flag & 1) acl_idx= i + 1; continue; } /* Extended Attribute */ if(flag & 4) continue; #ifdef Libisofs_with_freebsd_extattR if(strncmp(names[i], "user.", 5) == 0) { attrnamespace= EXTATTR_NAMESPACE_USER; namept= names[i] + 5; } else if(strncmp(names[i], "isofs.", 6) == 0 || !(flag & 8)) { continue; } else if(strncmp(names[i], "system.", 7) == 0) { attrnamespace= EXTATTR_NAMESPACE_SYSTEM; namept= names[i] + 7; } else { {ret= -8; goto ex;} } if(flag & 32) ret= extattr_set_file(path, attrnamespace, namept, values[i], value_lengths[i]); else ret= extattr_set_link(path, attrnamespace, namept, values[i], value_lengths[i]); if(ret == -1) {ret= -4; goto ex;} #else if(strncmp(names[i], "user.", 5) == 0) ; else if(strncmp(names[i], "isofs.", 6) == 0 || !(flag & 8)) continue; {ret= -6; goto ex;} #endif /* Libisofs_with_freebsd_extattR */ } /* Decode ACLs */ if(acl_idx == 0) {ret= 1; goto ex;} i= acl_idx - 1; ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i], &consumed, NULL, 0, &acl_text_fill, 1); if(ret < -3) goto ex; if(ret <= 0) {ret= -2; goto ex;} acl_text= calloc(acl_text_fill, 1); if(acl_text == NULL) {ret= -1; goto ex;} ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i], &consumed, acl_text, acl_text_fill, &acl_text_fill, 0); if(ret < -3) goto ex; if(ret <= 0) {ret= -2; goto ex;} has_default_acl= (ret == 2); #ifdef Libisofs_with_aaip_acL ret= aaip_set_acl_text(path, acl_text, flag & (32 | 64)); if(ret <= 0) {ret= -3; goto ex;} #else {ret= -7; goto ex;} #endif if(has_default_acl && !(flag & 64)) {ret= -3; goto ex;} ret= 1; ex:; if(acl_text != NULL) free(acl_text); #ifdef Libisofs_with_freebsd_extattR if(user_list != NULL) free(user_list); if(sys_list != NULL) free(sys_list); #endif /* Libisofs_with_freebsd_extattR */ return(ret); } #else /* ! Libisofs_old_freebsd_acl_adapteR */ /* Bring the given attributes and/or ACLs into effect with the given file. Note: There are no Extended Attributes in FreeBSD. So only ACL get set. @param flag Bitfield for control purposes bit0= decode and set ACLs ( bit1= first clear all existing attributes of the file ) ( bit2= do not set attributes other than ACLs ) ( bit3= do not ignore eventual non-user attributes. I.e. those with a name which does not begin by "user." ) @return 1 success -1 error memory allocation -2 error with decoding of ACL -3 error with setting ACL ( -4 error with setting attribute ) ( -5 error with deleting attribute ) -6 support of xattr not enabled at compile time -7 support of ACL not enabled at compile time */ int aaip_set_attr_list(char *path, size_t num_attrs, char **names, size_t *value_lengths, char **values, int flag) { int ret, has_default_acl= 0, was_xattr= 0; size_t i, consumed, acl_text_fill; char *acl_text= NULL, *list= NULL; for(i= 0; i < num_attrs; i++) { if(names[i] == NULL || values[i] == NULL) continue; if(names[i][0] == 0) { /* Decode ACLs */ /* access ACL */ if(!(flag & 1)) continue; ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i], &consumed, NULL, 0, &acl_text_fill, 1); if(ret <= 0) {ret= -2; goto ex;} acl_text= calloc(acl_text_fill, 1); if(acl_text == NULL) {ret= -1; goto ex;} ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i], &consumed, acl_text, acl_text_fill, &acl_text_fill, 0); if(ret <= 0) {ret= -2; goto ex;} has_default_acl= (ret == 2); #ifdef Libisofs_with_aaip_acL ret= aaip_set_acl_text(path, acl_text, flag & 32); if(ret <= 0) {ret= -3; goto ex;} #else {ret= -7; goto ex;} #endif /* "default" ACL */ if(has_default_acl) { free(acl_text); acl_text= NULL; ret= aaip_decode_acl((unsigned char *) (values[i] + consumed), value_lengths[i] - consumed, &consumed, NULL, 0, &acl_text_fill, 1); if(ret <= 0) {ret= -2; goto ex;} acl_text= calloc(acl_text_fill, 1); if(acl_text == NULL) {ret= -1; goto ex;} ret= aaip_decode_acl((unsigned char *) (values[i] + consumed), value_lengths[i] - consumed, &consumed, acl_text, acl_text_fill, &acl_text_fill, 0); if(ret <= 0) {ret= -2; goto ex;} ret= aaip_set_acl_text(path, acl_text, 1 | (flag & 32)); if(ret <= 0) {ret= -3; goto ex;} } } else { if(flag & 4) continue; if(!(flag & 8)) if(strncmp(names[i], "user.", 5)) continue; was_xattr= 1; } } ret= 1; if(was_xattr) ret= -6; ex:; if(acl_text != NULL) free(acl_text); if(list != NULL) free(list); return(ret); } #endif /* Libisofs_old_freebsd_acl_adapteR */ libisofs-1.4.2/libisofs/stream.c0000644000175700017510000007730712552010337013546 00000000000000/* * Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2009 - 2015 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif #include "libisofs.h" #include "stream.h" #include "fsource.h" #include "util.h" #include "node.h" #include #include #include #include #ifndef PATH_MAX #define PATH_MAX Libisofs_default_path_maX #endif ino_t serial_id = (ino_t)1; ino_t mem_serial_id = (ino_t)1; ino_t cut_out_serial_id = (ino_t)1; static int fsrc_open(IsoStream *stream) { int ret; struct stat info; off_t esize; IsoFileSource *src; if (stream == NULL) { return ISO_NULL_POINTER; } src = ((FSrcStreamData*)stream->data)->src; ret = iso_file_source_stat(src, &info); if (ret < 0) { return ret; } ret = iso_file_source_open(src); if (ret < 0) { return ret; } esize = ((FSrcStreamData*)stream->data)->size; if (info.st_size == esize) { return ISO_SUCCESS; } else { return (esize > info.st_size) ? 3 : 2; } } static int fsrc_close(IsoStream *stream) { IsoFileSource *src; if (stream == NULL) { return ISO_NULL_POINTER; } src = ((FSrcStreamData*)stream->data)->src; return iso_file_source_close(src); } static off_t fsrc_get_size(IsoStream *stream) { FSrcStreamData *data; data = (FSrcStreamData*)stream->data; return data->size; } static int fsrc_read(IsoStream *stream, void *buf, size_t count) { IsoFileSource *src; if (stream == NULL) { return ISO_NULL_POINTER; } src = ((FSrcStreamData*)stream->data)->src; return iso_file_source_read(src, buf, count); } static int fsrc_is_repeatable(IsoStream *stream) { int ret; struct stat info; FSrcStreamData *data; if (stream == NULL) { return ISO_NULL_POINTER; } data = (FSrcStreamData*)stream->data; /* mode is not cached, this function is only useful for filters */ ret = iso_file_source_stat(data->src, &info); if (ret < 0) { return ret; } if (S_ISREG(info.st_mode) || S_ISBLK(info.st_mode)) { return 1; } else { return 0; } } static void fsrc_get_id(IsoStream *stream, unsigned int *fs_id, dev_t *dev_id, ino_t *ino_id) { FSrcStreamData *data; IsoFilesystem *fs; data = (FSrcStreamData*)stream->data; fs = iso_file_source_get_filesystem(data->src); *fs_id = fs->get_id(fs); *dev_id = data->dev_id; *ino_id = data->ino_id; } static void fsrc_free(IsoStream *stream) { FSrcStreamData *data; data = (FSrcStreamData*)stream->data; iso_file_source_unref(data->src); free(data); } static int fsrc_update_size(IsoStream *stream) { int ret; struct stat info; IsoFileSource *src; if (stream == NULL) { return ISO_NULL_POINTER; } src = ((FSrcStreamData*)stream->data)->src; ret = iso_file_source_stat(src, &info); if (ret < 0) { return ret; } ((FSrcStreamData*)stream->data)->size = info.st_size; return ISO_SUCCESS; } static IsoStream *fsrc_get_input_stream(IsoStream *stream, int flag) { return NULL; } int fsrc_clone_stream(IsoStream *old_stream, IsoStream **new_stream, int flag) { FSrcStreamData *data, *new_data; IsoStream *stream; int ret; if (flag) return ISO_STREAM_NO_CLONE; /* unknown option required */ data = (FSrcStreamData*) old_stream->data; if (data->src->class->version < 2) return ISO_STREAM_NO_CLONE; /* No clone_src() method available */ *new_stream = NULL; stream = calloc(1, sizeof(IsoStream)); if (stream == NULL) return ISO_OUT_OF_MEM; new_data = calloc(1, sizeof(FSrcStreamData)); if (new_data == NULL) { free((char *) stream); return ISO_OUT_OF_MEM; } *new_stream = stream; stream->class = old_stream->class; stream->refcount = 1; stream->data = new_data; ret = data->src->class->clone_src(data->src, &(new_data->src), 0); if (ret < 0) { free((char *) stream); free((char *) new_data); return ret; } new_data->dev_id = data->dev_id; new_data->ino_id = data->ino_id; new_data->size = data->size; return ISO_SUCCESS; } static IsoStreamIface fsrc_stream_class = { 4, /* version */ "fsrc", fsrc_open, fsrc_close, fsrc_get_size, fsrc_read, fsrc_is_repeatable, fsrc_get_id, fsrc_free, fsrc_update_size, fsrc_get_input_stream, NULL, fsrc_clone_stream }; int iso_file_source_stream_new(IsoFileSource *src, IsoStream **stream) { int r; struct stat info; IsoStream *str; FSrcStreamData *data; if (src == NULL || stream == NULL) { return ISO_NULL_POINTER; } r = iso_file_source_stat(src, &info); if (r < 0) { return r; } if (S_ISDIR(info.st_mode)) { return ISO_FILE_IS_DIR; } /* check for read access to contents */ r = iso_file_source_access(src); if (r < 0) { return r; } str = malloc(sizeof(IsoStream)); if (str == NULL) { return ISO_OUT_OF_MEM; } data = malloc(sizeof(FSrcStreamData)); if (data == NULL) { free(str); return ISO_OUT_OF_MEM; } /* take the ref to IsoFileSource */ data->src = src; data->size = info.st_size; /* get the id numbers */ { IsoFilesystem *fs; unsigned int fs_id; fs = iso_file_source_get_filesystem(data->src); fs_id = fs->get_id(fs); if (fs_id == 0) { /* * the filesystem implementation is unable to provide valid * st_dev and st_ino fields. Use serial_id. */ data->dev_id = (dev_t) 0; data->ino_id = serial_id++; } else { data->dev_id = info.st_dev; data->ino_id = info.st_ino; } } str->refcount = 1; str->data = data; str->class = &fsrc_stream_class; *stream = str; return ISO_SUCCESS; } int iso_stream_get_src_zf(IsoStream *stream, int *header_size_div4, int *block_size_log2, uint32_t *uncompressed_size, int flag) { int ret; FSrcStreamData *data; IsoFileSource *src; /* Intimate friendship with libisofs/fs_image.c */ int iso_ifs_source_get_zf(IsoFileSource *src, int *header_size_div4, int *block_size_log2, uint32_t *uncompressed_size, int flag); if (stream->class != &fsrc_stream_class) return 0; data = stream->data; src = data->src; ret = iso_ifs_source_get_zf(src, header_size_div4, block_size_log2, uncompressed_size, 0); return ret; } struct cut_out_stream { IsoFileSource *src; /* key for file identification inside filesystem */ dev_t dev_id; ino_t ino_id; off_t offset; /**< offset where read begins */ off_t size; /**< size of this file */ off_t pos; /* position on the file for read */ }; static int cut_out_open(IsoStream *stream) { int ret; struct stat info; IsoFileSource *src; struct cut_out_stream *data; if (stream == NULL) { return ISO_NULL_POINTER; } data = stream->data; src = data->src; ret = iso_file_source_stat(data->src, &info); if (ret < 0) { return ret; } ret = iso_file_source_open(src); if (ret < 0) { return ret; } { off_t ret; if (data->offset > info.st_size) { /* file is smaller than expected */ ret = iso_file_source_lseek(src, info.st_size, 0); } else { ret = iso_file_source_lseek(src, data->offset, 0); } if (ret < 0) { return (int) ret; } } data->pos = 0; if (data->offset + data->size > info.st_size) { return 3; /* file smaller than expected */ } else { return ISO_SUCCESS; } } static int cut_out_close(IsoStream *stream) { IsoFileSource *src; if (stream == NULL) { return ISO_NULL_POINTER; } src = ((struct cut_out_stream*)stream->data)->src; return iso_file_source_close(src); } static off_t cut_out_get_size(IsoStream *stream) { struct cut_out_stream *data = stream->data; return data->size; } static int cut_out_read(IsoStream *stream, void *buf, size_t count) { struct cut_out_stream *data = stream->data; count = (size_t) MIN((size_t) (data->size - data->pos), count); if (count == 0) { return 0; } return iso_file_source_read(data->src, buf, count); } static int cut_out_is_repeatable(IsoStream *stream) { /* reg files are always repeatable */ return 1; } static void cut_out_get_id(IsoStream *stream, unsigned int *fs_id, dev_t *dev_id, ino_t *ino_id) { FSrcStreamData *data; IsoFilesystem *fs; data = (FSrcStreamData*)stream->data; fs = iso_file_source_get_filesystem(data->src); *fs_id = fs->get_id(fs); *dev_id = data->dev_id; *ino_id = data->ino_id; } static void cut_out_free(IsoStream *stream) { struct cut_out_stream *data = stream->data; iso_file_source_unref(data->src); free(data); } static int cut_out_update_size(IsoStream *stream) { return ISO_SUCCESS; } static IsoStream* cut_out_get_input_stream(IsoStream *stream, int flag) { return NULL; } static int cut_out_clone_stream(IsoStream *old_stream, IsoStream **new_stream, int flag) { struct cut_out_stream *data, *new_data; IsoStream *stream; int ret; if (flag) return ISO_STREAM_NO_CLONE; /* unknown option required */ data = (struct cut_out_stream *) old_stream->data; if (data->src->class->version < 2) return ISO_STREAM_NO_CLONE; /* No clone_src() method available */ *new_stream = NULL; stream = calloc(1, sizeof(IsoStream)); if (stream == NULL) return ISO_OUT_OF_MEM; stream->refcount = 1; stream->class = old_stream->class; new_data = calloc(1, sizeof(struct cut_out_stream)); if (new_data == NULL) { free((char *) stream); return ISO_OUT_OF_MEM; } ret = data->src->class->clone_src(data->src, &(new_data->src), 0); if (ret < 0) { free((char *) stream); free((char *) new_data); return ret; } new_data->dev_id = (dev_t) 0; new_data->ino_id = cut_out_serial_id++; new_data->offset = data->offset; new_data->size = data->size; new_data->pos = 0; stream->data = new_data; *new_stream = stream; return ISO_SUCCESS; } /* * TODO update cut out streams to deal with update_size(). Seems hard. */ static IsoStreamIface cut_out_stream_class = { 4, /* version */ "cout", cut_out_open, cut_out_close, cut_out_get_size, cut_out_read, cut_out_is_repeatable, cut_out_get_id, cut_out_free, cut_out_update_size, cut_out_get_input_stream, NULL, cut_out_clone_stream }; int iso_cut_out_stream_new(IsoFileSource *src, off_t offset, off_t size, IsoStream **stream) { int r; struct stat info; IsoStream *str; struct cut_out_stream *data; if (src == NULL || stream == NULL) { return ISO_NULL_POINTER; } if (size == 0) { return ISO_WRONG_ARG_VALUE; } r = iso_file_source_stat(src, &info); if (r < 0) { return r; } if (!S_ISREG(info.st_mode)) { return ISO_WRONG_ARG_VALUE; } if (offset > info.st_size) { return ISO_FILE_OFFSET_TOO_BIG; } /* check for read access to contents */ r = iso_file_source_access(src); if (r < 0) { return r; } str = malloc(sizeof(IsoStream)); if (str == NULL) { return ISO_OUT_OF_MEM; } data = malloc(sizeof(struct cut_out_stream)); if (data == NULL) { free(str); return ISO_OUT_OF_MEM; } /* take a new ref to IsoFileSource */ data->src = src; iso_file_source_ref(src); data->offset = offset; data->size = MIN(info.st_size - offset, size); /* get the id numbers */ data->dev_id = (dev_t) 0; data->ino_id = cut_out_serial_id++; str->refcount = 1; str->data = data; str->class = &cut_out_stream_class; *stream = str; return ISO_SUCCESS; } typedef struct { uint8_t *buf; ssize_t offset; /* -1 if stream closed */ ino_t ino_id; size_t size; } MemStreamData; static int mem_open(IsoStream *stream) { MemStreamData *data; if (stream == NULL) { return ISO_NULL_POINTER; } data = (MemStreamData*)stream->data; if (data->offset != -1) { return ISO_FILE_ALREADY_OPENED; } data->offset = 0; return ISO_SUCCESS; } static int mem_close(IsoStream *stream) { MemStreamData *data; if (stream == NULL) { return ISO_NULL_POINTER; } data = (MemStreamData*)stream->data; if (data->offset == -1) { return ISO_FILE_NOT_OPENED; } data->offset = -1; return ISO_SUCCESS; } static off_t mem_get_size(IsoStream *stream) { MemStreamData *data; data = (MemStreamData*)stream->data; return (off_t)data->size; } static int mem_read(IsoStream *stream, void *buf, size_t count) { size_t len; MemStreamData *data; if (stream == NULL || buf == NULL) { return ISO_NULL_POINTER; } if (count == 0) { return ISO_WRONG_ARG_VALUE; } data = stream->data; if (data->offset == -1) { return ISO_FILE_NOT_OPENED; } if (data->offset >= (ssize_t) data->size) { return 0; /* EOF */ } len = MIN(count, data->size - data->offset); memcpy(buf, data->buf + data->offset, len); data->offset += len; return len; } static int mem_is_repeatable(IsoStream *stream) { return 1; } static void mem_get_id(IsoStream *stream, unsigned int *fs_id, dev_t *dev_id, ino_t *ino_id) { MemStreamData *data; data = (MemStreamData*)stream->data; *fs_id = ISO_MEM_FS_ID; *dev_id = 0; *ino_id = data->ino_id; } static void mem_free(IsoStream *stream) { MemStreamData *data; data = (MemStreamData*)stream->data; if (data->buf != NULL) free(data->buf); free(data); } static int mem_update_size(IsoStream *stream) { return ISO_SUCCESS; } static IsoStream* mem_get_input_stream(IsoStream *stream, int flag) { return NULL; } static int mem_clone_stream(IsoStream *old_stream, IsoStream **new_stream, int flag) { MemStreamData *data, *new_data; IsoStream *stream; uint8_t *new_buf = NULL; if (flag) return ISO_STREAM_NO_CLONE; /* unknown option required */ *new_stream = NULL; stream = calloc(1, sizeof(IsoStream)); if (stream == NULL) return ISO_OUT_OF_MEM; stream->refcount = 1; stream->class = old_stream->class; new_data = calloc(1, sizeof(MemStreamData)); if (new_data == NULL) { free((char *) stream); return ISO_OUT_OF_MEM; } data = (MemStreamData *) old_stream->data; if (data->size > 0) { new_buf = calloc(1, data->size); if (new_buf == NULL) { free((char *) stream); free((char *) new_data); return ISO_OUT_OF_MEM; } memcpy(new_buf, data->buf, data->size); } new_data->buf = new_buf; new_data->offset = -1; new_data->ino_id = mem_serial_id++; new_data->size = data->size; stream->data = new_data; *new_stream = stream; return ISO_SUCCESS; } static IsoStreamIface mem_stream_class = { 4, /* version */ "mem ", mem_open, mem_close, mem_get_size, mem_read, mem_is_repeatable, mem_get_id, mem_free, mem_update_size, mem_get_input_stream, NULL, mem_clone_stream }; /** * Create a stream for reading from a arbitrary memory buffer. * When the Stream refcount reach 0, the buffer is free(3). * * @return * 1 success, < 0 error */ int iso_memory_stream_new(unsigned char *buf, size_t size, IsoStream **stream) { IsoStream *str; MemStreamData *data; if (buf == NULL || stream == NULL) { return ISO_NULL_POINTER; } str = malloc(sizeof(IsoStream)); if (str == NULL) { return ISO_OUT_OF_MEM; } data = malloc(sizeof(MemStreamData)); if (data == NULL) { free(str); return ISO_OUT_OF_MEM; } /* fill data */ data->buf = buf; data->size = size; data->offset = -1; data->ino_id = mem_serial_id++; str->refcount = 1; str->data = data; str->class = &mem_stream_class; *stream = str; return ISO_SUCCESS; } void iso_stream_ref(IsoStream *stream) { ++stream->refcount; } void iso_stream_unref(IsoStream *stream) { if (--stream->refcount == 0) { stream->class->free(stream); free(stream); } } inline int iso_stream_open(IsoStream *stream) { return stream->class->open(stream); } inline int iso_stream_close(IsoStream *stream) { return stream->class->close(stream); } inline off_t iso_stream_get_size(IsoStream *stream) { return stream->class->get_size(stream); } inline int iso_stream_read(IsoStream *stream, void *buf, size_t count) { return stream->class->read(stream, buf, count); } inline int iso_stream_is_repeatable(IsoStream *stream) { return stream->class->is_repeatable(stream); } inline int iso_stream_update_size(IsoStream *stream) { IsoStreamIface* class = stream->class; return (class->version >= 1) ? class->update_size(stream) : 0; } inline void iso_stream_get_id(IsoStream *stream, unsigned int *fs_id, dev_t *dev_id, ino_t *ino_id) { stream->class->get_id(stream, fs_id, dev_id, ino_id); } void iso_stream_get_file_name(IsoStream *stream, char *name) { char *type = stream->class->type; if (!strncmp(type, "fsrc", 4)) { FSrcStreamData *data = stream->data; char *path = iso_file_source_get_path(data->src); if (path == NULL) { name[0] = 0; return; } strncpy(name, path, PATH_MAX - 1); name[PATH_MAX - 1] = 0; free(path); } else if (!strncmp(type, "boot", 4)) { strcpy(name, "BOOT CATALOG"); } else if (!strncmp(type, "mem ", 4)) { strcpy(name, "MEM SOURCE"); } else if (!strncmp(type, "extf", 4)) { strcpy(name, "EXTERNAL FILTER"); } else { strcpy(name, "UNKNOWN SOURCE"); } } /* @param flag bit0= Obtain most fundamental stream */ IsoStream *iso_stream_get_input_stream(IsoStream *stream, int flag) { IsoStreamIface* class; IsoStream *result = NULL, *next; if (stream == NULL) { return NULL; } while (1) { class = stream->class; if (class->version < 2) return result; next = class->get_input_stream(stream, 0); if (next == NULL) return result; result = next; if (!(flag & 1)) return result; stream = result; } } char *iso_stream_get_source_path(IsoStream *stream, int flag) { char *path = NULL, ivd[80], *raw_path = NULL; if (stream == NULL) { return NULL; } if (stream->class == &fsrc_stream_class) { FSrcStreamData *fsrc_data = stream->data; path = iso_file_source_get_path(fsrc_data->src); } else if (stream->class == &cut_out_stream_class) { struct cut_out_stream *cout_data = stream->data; raw_path = iso_file_source_get_path(cout_data->src); sprintf(ivd, " %.f %.f", (double) cout_data->offset, (double) cout_data->size); path= calloc(strlen(raw_path) + strlen(ivd) + 1, 1); if (path == NULL) { goto ex; } strcpy(path, raw_path); strcat(path, ivd); } ex:; if (raw_path != NULL) free(raw_path); return path; } /* @param flag bit0= in case of filter stream do not dig for base stream @return 1 = ok , 0 = not an ISO image stream , <0 = error */ int iso_stream_set_image_ino(IsoStream *stream, ino_t ino, int flag) { IsoStream *base_stream; if (stream == NULL) { return ISO_NULL_POINTER; } if (!(flag & 1)) { base_stream = iso_stream_get_input_stream(stream, 1); if (base_stream != NULL) stream = base_stream; } if (stream->class == &fsrc_stream_class) { FSrcStreamData *fsrc_data = stream->data; fsrc_data->ino_id = ino; return 1; } return 0; } int iso_stream_cmp_ifs_sections(IsoStream *s1, IsoStream *s2, int *cmp_ret, int flag) { int ret; FSrcStreamData *fssd1, *fssd2; IsoFileSource *src1, *src2; /* Must keep any suspect in the game to preserve transitivity of the calling function by ranking applicable streams lower than non-applicable. ones. */ if (s1->class != &fsrc_stream_class && s2->class != &fsrc_stream_class) return 0; /* Compare eventual image data section LBA and sizes */ if (s1->class == &fsrc_stream_class) { fssd1= (FSrcStreamData *) s1->data; src1 = fssd1->src; } else { src1 = NULL; } if (s2->class == &fsrc_stream_class) { fssd2= (FSrcStreamData *) s2->data; src2 = fssd2->src; } else { src2 = NULL; } ret = iso_ifs_sections_cmp(src1, src2, cmp_ret, 1); if (ret <= 0) return 0; return 1; } /* Maintain and exploit a list of stream compare functions seen by iso_stream_cmp_ino(). This is needed to separate stream comparison families in order to keep iso_stream_cmp_ino() transitive while alternative stream->class->cmp_ino() decide inside the families. */ struct iso_streamcmprank { int (*cmp_func)(IsoStream *s1, IsoStream *s2); struct iso_streamcmprank *next; }; static struct iso_streamcmprank *streamcmpranks = NULL; static int iso_get_streamcmprank(int (*cmp_func)(IsoStream *s1, IsoStream *s2), int flag) { int idx; struct iso_streamcmprank *cpr, *last_cpr = NULL; idx = 0; for (cpr = streamcmpranks; cpr != NULL; cpr = cpr->next) { if (cpr->cmp_func == cmp_func) break; idx++; last_cpr = cpr; } if (cpr != NULL) return idx; LIBISO_ALLOC_MEM_VOID(cpr, struct iso_streamcmprank, 1); cpr->cmp_func = cmp_func; cpr->next = NULL; if (last_cpr != NULL) last_cpr->next = cpr; if (streamcmpranks == NULL) streamcmpranks = cpr; return idx; ex:; return -1; } static int iso_cmp_streamcmpranks(int (*cf1)(IsoStream *s1, IsoStream *s2), int (*cf2)(IsoStream *s1, IsoStream *s2)) { int rank1, rank2; rank1 = iso_get_streamcmprank(cf1, 0); rank2 = iso_get_streamcmprank(cf2, 0); return rank1 < rank2 ? -1 : 1; } int iso_stream_destroy_cmpranks(int flag) { struct iso_streamcmprank *cpr, *next; for (cpr = streamcmpranks; cpr != NULL; cpr = next) { next = cpr->next; LIBISO_FREE_MEM(cpr); } streamcmpranks = NULL; return ISO_SUCCESS; } /* API */ int iso_stream_cmp_ino(IsoStream *s1, IsoStream *s2, int flag) { int ret; unsigned int fs_id1, fs_id2; dev_t dev_id1, dev_id2; ino_t ino_id1, ino_id2; off_t size1, size2; /* #define Libisofs_stream_cmp_ino_debuG 1 */ #ifdef Libisofs_stream_cmp_ino_debuG static int report_counter = 0; static int debug = 1; #endif /* Libisofs_stream_cmp_ino_debuG */ if (s1 == s2) return 0; if (s1 == NULL) return -1; if (s2 == NULL) return 1; /* This stays transitive by the fact that iso_stream_cmp_ifs_sections() is transitive, returns > 0 if s1 or s2 are applicable, ret is -1 if s1 is applicable but s2 is not, ret is 1 if s1 is not applicable but s2 is. Proof: Be A the set of applicable streams, S and G transitive and antisymmetric relations in respect to outcome {-1, 0, 1}. The combined relation R shall be defined by I. R(a,b) = S(a,b) if a in A or b in A, else G(a,b) Further S shall have the property II. S(a,b) = -1 if a in A and b not in A Then R can be proven to be transitive: By enumerating the 8 combinations of a,b,c being in A or not, we get 5 cases of pure S or pure G. Three cases are mixed: a,b not in A, c in A : G(a,b) == -1, S(b,c) == -1 -> S(a,c) == -1 Impossible because S(b,c) == -1 contradicts II. a,c not in A, b in A : S(a,b) == -1, S(b,c) == -1 -> G(a,c) == -1 Impossible because S(a,b) == -1 contradicts II. b,c not in A, a in A : S(a,b) == -1, G(b,c) == -1 -> S(a,c) == -1 Always true because S(a,c) == -1 by definition II. */ if (iso_stream_cmp_ifs_sections(s1, s2, &ret, 0) > 0) return ret; /* Both are unfiltered from loaded ISO filesystem */ if (!(flag & 1)) { /* Filters may have smarter methods to compare themselves with others. Transitivity is ensured by ranking mixed pairs by the rank of their comparison functions, and by ranking streams with .cmp_ino lower than streams without. (One could merge (class->version < 3) and (cmp_ino == NULL).) Here we define S for "and" rather than "or" I. R(a,b) = S(a,b) if a in A and b in A, else G(a,b) and the function ranking in case of "exor" makes sure that II. G(a,b) = -1 if a in A and b not in A Again we get three mixed cases: a not in A, b,c in A : G(a,b) == -1, S(b,c) == -1 -> G(a,c) == -1 Impossible because G(a,b) == -1 contradicts II. b not in A, a,c in A : G(a,b) == -1, G(b,c) == -1 -> S(a,c) == -1 Impossible because G(b,c) == -1 contradicts II. c not in A, a,b in A : S(a,b) == -1, G(b,c) == -1 -> G(a,c) == -1 Always true because G(a,c) == -1 by definition II. */ if ((s1->class->version >= 3) ^ (s2->class->version >= 3)) { /* One of both has no own com_ino function. Rank it as larger. */ return s1->class->version >= 3 ? -1 : 1; } else if (s1->class->version >= 3) { if (s1->class->cmp_ino == s2->class->cmp_ino) { if (s1->class->cmp_ino == NULL) { /* Both are NULL. No decision by .cmp_ino(). */; } else { /* Both are compared by the same function */ ret = s1->class->cmp_ino(s1, s2); return ret; } } else { /* Not the same cmp_ino() function. Decide by list rank of function while building the list on the fly. */ ret = iso_cmp_streamcmpranks(s1->class->cmp_ino, s2->class->cmp_ino); return ret; } } } iso_stream_get_id(s1, &fs_id1, &dev_id1, &ino_id1); iso_stream_get_id(s2, &fs_id2, &dev_id2, &ino_id2); if (fs_id1 < fs_id2) { return -1; } else if (fs_id1 > fs_id2) { return 1; } /* files belong to the same fs */ if (dev_id1 > dev_id2) { return -1; } else if (dev_id1 < dev_id2) { return 1; } else if (ino_id1 < ino_id2) { return -1; } else if (ino_id1 > ino_id2) { return 1; } size1 = iso_stream_get_size(s1); size2 = iso_stream_get_size(s2); if (size1 < size2) { #ifdef Libisofs_stream_cmp_ino_debuG if (debug) { if (report_counter < 5) fprintf(stderr, "\n\nlibisofs_DEBUG : Program error: same ino but differing size\n\n\n"); else if (report_counter == 5) fprintf(stderr, "\n\nlibisofs_DEBUG : Inode error: more of same ino but differing size\n\n\n"); report_counter++; } #endif /* Libisofs_stream_cmp_ino_debuG */ return -1; } else if (size1 > size2) { #ifdef Libisofs_stream_cmp_ino_debuG if (debug) { if (report_counter < 5) fprintf(stderr, "\n\nlibisofs_DEBUG : Inode error: same ino but differing size\n\n\n"); else if (report_counter == 5) fprintf(stderr, "\n\nlibisofs_DEBUG : Program error: more of same ino but differing size\n\n\n"); report_counter++; } #endif /* Libisofs_stream_cmp_ino_debuG */ return 1; } if (s1->class != s2->class) return (s1->class < s2->class ? -1 : 1); if (fs_id1 == 0 && dev_id1 == 0 && ino_id1 == 0) { return (s1 < s2 ? -1 : 1); } return 0; } /** * @return * 1 ok, 0 EOF, < 0 error */ int iso_stream_read_buffer(IsoStream *stream, char *buf, size_t count, size_t *got) { ssize_t result; *got = 0; do { result = iso_stream_read(stream, buf + *got, count - *got); if (result < 0) { memset(buf + *got, 0, count - *got); return result; } if (result == 0) break; *got += result; } while (*got < count); if (*got < count) { /* eof */ memset(buf + *got, 0, count - *got); return 0; } return 1; } /* @param flag bit0= dig out most original stream (e.g. because from old image) @return 1=ok, md5 is valid, 0= not ok, <0 fatal error, abort */ int iso_stream_make_md5(IsoStream *stream, char md5[16], int flag) { int ret, is_open = 0; char * buffer = NULL; void *ctx= NULL; off_t file_size; uint32_t b, nblocks; size_t got_bytes; IsoStream *input_stream; LIBISO_ALLOC_MEM(buffer, char, 2048); if (flag & 1) { while(1) { input_stream = iso_stream_get_input_stream(stream, 0); if (input_stream == NULL) break; stream = input_stream; } } if (! iso_stream_is_repeatable(stream)) {ret = 0; goto ex;} ret = iso_md5_start(&ctx); if (ret < 0) goto ex; ret = iso_stream_open(stream); if (ret < 0) goto ex; is_open = 1; file_size = iso_stream_get_size(stream); nblocks = DIV_UP(file_size, 2048); for (b = 0; b < nblocks; ++b) { ret = iso_stream_read_buffer(stream, buffer, 2048, &got_bytes); if (ret < 0) { ret = 0; goto ex; } /* Do not use got_bytes to stay closer to IsoFileSrc processing */ if (file_size - b * 2048 > 2048) ret = 2048; else ret = file_size - b * 2048; iso_md5_compute(ctx, buffer, ret); } ret = 1; ex:; if (is_open) iso_stream_close(stream); if (ctx != NULL) iso_md5_end(&ctx, md5); LIBISO_FREE_MEM(buffer); return ret; } /* API */ int iso_stream_clone(IsoStream *old_stream, IsoStream **new_stream, int flag) { int ret; if (old_stream->class->version < 4) return ISO_STREAM_NO_CLONE; ret = old_stream->class->clone_stream(old_stream, new_stream, 0); return ret; } int iso_stream_clone_filter_common(IsoStream *old_stream, IsoStream **new_stream, IsoStream **new_input, int flag) { IsoStream *stream, *input_stream; int ret; *new_stream = NULL; *new_input = NULL; input_stream = iso_stream_get_input_stream(old_stream, 0); if (input_stream == NULL) return ISO_STREAM_NO_CLONE; stream = calloc(1, sizeof(IsoStream)); if (stream == NULL) return ISO_OUT_OF_MEM; ret = iso_stream_clone(input_stream, new_input, 0); if (ret < 0) { free((char *) stream); return ret; } stream->class = old_stream->class; stream->refcount = 1; stream->data = NULL; *new_stream = stream; return ISO_SUCCESS; } libisofs-1.4.2/libisofs/aaip_0_2.c0000644000175700017510000020721412607514631013624 00000000000000 /* Arbitrary Attribute Interchange Protocol , AAIP versions 0.2 , 1.0 , 2.0. Implementation of encoding and decoding xattr and ACL. See libisofs/aaip_0_2.h http://libburnia-project.org/wiki/AAIP Copyright (c) 2009 - 2015 Thomas Schmitt, libburnia project, GPLv2+ */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif #include #include #include #include #include #include #include #include #include #include "libisofs.h" #include "util.h" /* #define Aaip_encode_debuG 1 */ #include "aaip_0_2.h" #define Aaip_EXEC 1 #define Aaip_WRITE 2 #define Aaip_READ 4 #define Aaip_TRANSLATE 0 #define Aaip_ACL_USER_OBJ 1 #define Aaip_ACL_USER 2 #define Aaip_ACL_GROUP_OBJ 3 #define Aaip_ACL_GROUP 4 #define Aaip_ACL_MASK 5 #define Aaip_ACL_OTHER 6 #define Aaip_SWITCH_MARK 8 #define Aaip_ACL_USER_N 10 #define Aaip_ACL_GROUP_N 12 #define Aaip_FUTURE_VERSION 15 #define Aaip_with_short_namespaceS yes #define Aaip_max_named_spacE 0x06 #define Aaip_min_named_spacE 0x02 #define Aaip_maxdef_namespacE 0x1f #define Aaip_namespace_literaL 0x01 #define Aaip_namespace_systeM 0x02 #define Aaip_namespace_useR 0x03 #define Aaip_namespace_isofS 0x04 #define Aaip_namespace_trusteD 0x05 #define Aaip_namespace_securitY 0x06 /* maximum expansion: "security." */ #define Aaip_max_name_expansioN 9 static char Aaip_namespace_textS[][Aaip_max_name_expansioN + 1]= {"", "", "system.", "user.", "isofs.", "trusted.", "security."}; /* --------------------------------- Encoder ---------------------------- */ static int aaip_encode_pair(char *name, size_t attr_length, char *attr, unsigned int *num_recs, size_t *comp_size, unsigned char *result, size_t result_fill, int flag); /* Convert an array of Arbitrary Attributes into a series of AAIP fields. @param num_attrs Number of attributes @param names Array of pointers to 0 terminated name strings @param value_lengths Array of byte lengths for each value @param values Array of pointers to the value bytes @param result_len Number of bytes in the resulting SUSP field string @param result *result will point to the start of the result string. This is malloc() memory which needs to be freed when no longer needed @param flag Bitfield for control purposes bit0= set CONTINUE bit of last AAIP field to 1 @return >= 0 is the number of SUSP fields generated, < 0 means error */ ssize_t aaip_encode(size_t num_attrs, char **names, size_t *value_lengths, char **values, size_t *result_len, unsigned char **result, int flag) { size_t mem_size= 0, comp_size; ssize_t ret; unsigned int number_of_fields, i, num_recs; /* Predict memory needs, number of SUSP fields and component records */ *result = NULL; *result_len= 0; for(i= 0; i < num_attrs; i++) { ret= aaip_encode_pair(names[i], value_lengths[i], values[i], &num_recs, &comp_size, NULL, (size_t) 0, 1); if(ret < 0) return(ret); mem_size+= comp_size; } number_of_fields= mem_size / 250 + !!(mem_size % 250); if(number_of_fields == 0) return(0); mem_size+= number_of_fields * 5; #ifdef Aaip_encode_debuG *result= (unsigned char *) calloc(1, mem_size + 1024000); /* generous honeypot for overflows */ #else *result= (unsigned char *) calloc(1, mem_size); #endif if(*result == NULL) return ISO_OUT_OF_MEM; /* Encode pairs into result */ for(i= 0; i < num_attrs; i++) { ret= aaip_encode_pair(names[i], value_lengths[i], values[i], &num_recs, &comp_size, *result, *result_len, 0); if(ret < 0) { free(*result); *result = NULL; *result_len = 0; return(ret); } (*result_len)+= comp_size; } /* write the field headers */ for(i= 0; i < number_of_fields; i++) { (*result)[i * 255 + 0]= 'A'; (*result)[i * 255 + 1]= 'L'; if(i < number_of_fields - 1 || (mem_size % 255) == 0) (*result)[i * 255 + 2]= 255; else (*result)[i * 255 + 2]= mem_size % 255; (*result)[i * 255 + 3]= 1; (*result)[i * 255 + 4]= (flag & 1) || (i < number_of_fields - 1); } (*result_len)+= number_of_fields * 5; #ifdef Aaip_encode_debuG if(*result_len != mem_size) { fprintf(stderr, "aaip_encode(): MEMORY MISMATCH BY %d BYTES\n", (int) (mem_size - *result_len)); } else { unsigned char *hpt; hpt= malloc(*result_len); if(hpt != NULL) { memcpy(hpt, *result, *result_len); free(*result); *result= hpt; } } ret= 0; for(i= 0; i < *result_len; i+= ((unsigned char *) (*result))[i + 2]) ret++; if(ret != (int) number_of_fields) { fprintf(stderr, "aaip_encode(): WRONG NUMBER OF FIELDS %d <> %d\n", (int) number_of_fields, ret); } #endif /* Aaip_encode_debuG */ return(number_of_fields); } static void aaip_encode_byte(unsigned char *result, size_t *result_fill, unsigned char value) { result[(*result_fill / 250) * 255 + 5 + (*result_fill % 250)]= value; (*result_fill)++; } static int aaip_encode_comp(unsigned char *result, size_t *result_fill, int prefix, char *data, size_t l, int flag) { size_t todo; char *rpt, *comp_start; if(l == 0 && prefix <= 0) { aaip_encode_byte(result, result_fill, 0); aaip_encode_byte(result, result_fill, 0); return(1); } for(rpt= data; rpt - data < (ssize_t) l;) { todo= l - (rpt - data) + (prefix > 0); aaip_encode_byte(result, result_fill, (todo > 255)); if(todo > 255) todo= 255; aaip_encode_byte(result, result_fill, todo); if(prefix > 0) { aaip_encode_byte(result, result_fill, prefix); todo--; prefix= 0; } for(comp_start= rpt; rpt - comp_start < (ssize_t) todo; rpt++) aaip_encode_byte(result, result_fill, *((unsigned char *) rpt)); } return(1); } /* Write the component records for name and attr. Skip the positions of AAIP field headers. @param flag bit0= only count but do not produce result */ static int aaip_encode_pair(char *name, size_t attr_length, char *attr, unsigned int *num_recs, size_t *comp_size, unsigned char *result, size_t result_fill, int flag) { size_t l; int i, prefix= 0; #ifdef Aaip_with_short_namespaceS /* translate name into eventual short form */ for(i= Aaip_min_named_spacE; i <= Aaip_max_named_spacE; i++) if(strncmp(name, Aaip_namespace_textS[i], strlen(Aaip_namespace_textS[i])) == 0) { name+= strlen(Aaip_namespace_textS[i]); prefix= i; } /* Eventually prepend escape marker for strange names */ if(prefix <= 0 && name[0] > 0 && name[0] <= Aaip_maxdef_namespacE) prefix= Aaip_namespace_literaL; #endif /* Aaip_with_short_namespaceS */ l= strlen(name) + (prefix > 0); *num_recs= l / 255 + (!!(l % 255)) + (l == 0) + attr_length / 255 + (!!(attr_length % 255)) + (attr_length == 0); *comp_size= l + attr_length + 2 * *num_recs; if(flag & 1) return(1); aaip_encode_comp(result, &result_fill, prefix, name, l - (prefix > 0), 0); aaip_encode_comp(result, &result_fill, 0, attr, attr_length, 0); return(1); } /* ----------- Encoder for ACLs ----------- */ static ssize_t aaip_encode_acl_text(char *acl_text, mode_t st_mode, size_t result_size, unsigned char *result, int flag); /* Convert an ACL text as of acl_to_text(3) into the value of an Arbitrary Attribute. According to AAIP this value is to be stored together with an empty name. @param acl_text The ACL in long text form @param st_mode The stat(2) permission bits to be used with flag bit3 @param result_len Number of bytes in the resulting value @param result *result will point to the start of the result string. This is malloc() memory which needs to be freed when no longer needed @param flag Bitfield for control purposes bit0= count only bit1= use numeric qualifiers rather than names bit2= this is a default ACL, prepend SWITCH_MARK bit3= check for completeness of list and eventually fill up with entries deduced from st_mode @return >0 means ok <=0 means error -1= out of memory -2= program error with prediction of result size -3= error with conversion of name to uid or gid ISO_AAIP_ACL_MULT_OBJ= multiple entries of user::, group::, other:: */ int aaip_encode_acl(char *acl_text, mode_t st_mode, size_t *result_len, unsigned char **result, int flag) { ssize_t bytes; *result= NULL; *result_len= 0; bytes= aaip_encode_acl_text(acl_text, st_mode, (size_t) 0, NULL, 1 | (flag & (2 | 4 | 8))); if(bytes < -2) return(bytes); if(bytes < 0) return((int) bytes - 1); if(flag & 1) { *result_len= bytes; return(1); } *result= calloc(bytes + 1, 1); if(*result == NULL) return(-1); (*result)[bytes]= 0; *result_len= bytes; bytes= aaip_encode_acl_text(acl_text, st_mode, *result_len, *result, (flag & (2 | 4 | 8))); if(bytes < -2) return(bytes); if(bytes < 0) return((int) bytes - 1); if((size_t) bytes != *result_len) { *result_len= 0; return(-2); } return(1); } static double aaip_numeric_id(char *name, int flag) { double num; char *cpt; for(cpt= name; *cpt != 0; cpt++) if(*cpt < '0' || *cpt >'9') break; if(*cpt != 0) return(-1); sscanf(name, "%lf", &num); return(num); } static int aaip_make_aaip_perms(int r, int w, int x) { int perms; perms= 0; if(r) perms|= Aaip_READ; if(w) perms|= Aaip_WRITE; if(x) perms|= Aaip_EXEC; return(perms); } /* @param result_size Number of bytes to store result @param result Pointer to the start of the result string. @param flag Bitfield for control purposes bit0= count only, do not really produce bytes bit1= use numeric qualifiers bit2= this is a default ACL, prepend SWITCH_MARK 1 bit3= check for completeness of list and eventually fill up with entries deduced from st_mode @return >=0 number of bytes produced resp. counted <0 means error -1: result size overflow -2: conversion errror with user name or group name ISO_AAIP_ACL_MULT_OBJ: multiple entries of user::, group::, other:: */ static ssize_t aaip_encode_acl_text(char *acl_text, mode_t st_mode, size_t result_size, unsigned char *result, int flag) { char *rpt, *npt, *cpt; int qualifier= 0, perms, type, i, qualifier_len= 0, num_recs, needed= 0, ret; unsigned int has_u= 0, has_g= 0, has_o= 0, has_m= 0, is_trivial= 1; uid_t uid, huid; gid_t gid, hgid; ssize_t count= 0; struct passwd *pwd; struct group *grp; char *name = NULL; int name_size= 1024; double num; LIBISO_ALLOC_MEM(name, char, name_size); if(flag & 4) { /* set SWITCH_MARK to indicate a default ACL */; if(!(flag & 1)) { if((size_t) count >= result_size) {ret= -1; goto ex;} result[count]= (Aaip_SWITCH_MARK << 4) | Aaip_EXEC; } count++; } for(rpt= acl_text; *rpt != 0; rpt= npt) { npt= strchr(rpt, '\n'); if(npt == 0) npt= rpt + strlen(rpt); else npt++; if(*rpt == '#') continue; cpt= strchr(rpt, ':'); if(cpt == NULL) continue; cpt= strchr(cpt + 1, ':'); if(cpt == NULL) continue; qualifier= 0; if(strncmp(rpt, "user:", 5) == 0) { if(cpt - rpt == 5) { type= Aaip_ACL_USER_OBJ; if (has_u) { /* >>> Duplicate u:: entry. */; /* >>> ??? If it matches the previous one: ignore */ ret = ISO_AAIP_ACL_MULT_OBJ; goto ex; } has_u++; } else { if(cpt - (rpt + 5) >= name_size) continue; is_trivial= 0; strncpy(name, rpt + 5, cpt - (rpt + 5)); name[cpt - (rpt + 5)]= 0; if(flag & 2) { type= Aaip_ACL_USER_N; pwd= getpwnam(name); if(pwd == NULL) { num= aaip_numeric_id(name, 0); if(num <= 0) { /* ACL_USER is not part of AAIP 2.0 */ {ret= -2; goto ex;} } uid= huid= num; } else uid= huid= pwd->pw_uid; /* Convert uid into Qualifier Record */ for(i= 0; huid != 0; i++) huid= huid >> 8; qualifier_len= i; if(qualifier_len <= 0) qualifier_len= 1; for(i= 0; i < qualifier_len ; i++) name[i]= uid >> (8 * (qualifier_len - i - 1)); } else { type= Aaip_ACL_USER; qualifier_len= strlen(name); if(qualifier_len <= 0) qualifier_len= 1; } qualifier= 1; } } else if(strncmp(rpt, "group:", 6) == 0) { if(cpt - rpt == 6) { type= Aaip_ACL_GROUP_OBJ; if (has_g) { /* >>> Duplicate g:: entry. */; /* >>> ??? If it matches the previous one: ignore */ ret = ISO_AAIP_ACL_MULT_OBJ; goto ex; } has_g++; } else { if(cpt - (rpt + 6) >= name_size) continue; is_trivial= 0; strncpy(name, rpt + 6, cpt - (rpt + 6)); name[cpt - (rpt + 6)]= 0; if(flag & 2) { type= Aaip_ACL_GROUP_N; grp= getgrnam(name); if(grp == NULL) { num= aaip_numeric_id(name, 0); if(num <= 0) { /* ACL_GROUP is not part of AAIP 2.0 */ {ret= -2; goto ex;} } gid= hgid= num; } else gid= hgid= grp->gr_gid; /* Convert gid into Qualifier Record */ for(i= 0; hgid != 0; i++) hgid= hgid >> 8; qualifier_len= i; if(qualifier_len <= 0) qualifier_len= 1; for(i= 0; i < qualifier_len ; i++) name[i]= gid >> (8 * (qualifier_len - i - 1)); } else { type= Aaip_ACL_GROUP; qualifier_len= strlen(name); if(qualifier_len <= 0) qualifier_len= 1; } qualifier= 1; } } else if(strncmp(rpt, "other:", 6) == 0) { type= Aaip_ACL_OTHER; if (has_o) { /* >>> Duplicate o:: entry. */; /* >>> ??? If it matches the previous one: ignore */ ret = ISO_AAIP_ACL_MULT_OBJ; goto ex; } has_o++; } else if(strncmp(rpt, "mask:", 5) == 0) { type= Aaip_ACL_MASK; has_m++; } else continue; if(npt - cpt < 4) continue; perms= aaip_make_aaip_perms(cpt[1] == 'r', cpt[2] == 'w', cpt[3] == 'x'); if(!(flag & 1)) { if((size_t) count >= result_size) {ret= -1; goto ex;} result[count]= perms | ((!!qualifier) << 3) | (type << 4); } count++; if(qualifier) { num_recs= (qualifier_len / 127) + !!(qualifier_len % 127); if(!(flag & 1)) { if((size_t) (count + 1) > result_size) {ret= -1; goto ex;} for(i= 0; i < num_recs; i++) { if(i < num_recs - 1) result[count++]= 255; else { result[count++]= (qualifier_len % 127); if(result[count - 1] == 0) result[count - 1]= 127; } if((size_t) (count + (result[count - 1] & 127)) > result_size) {ret= -1; goto ex;} memcpy(result + count, name + i * 127, result[count - 1] & 127); count+= result[count - 1] & 127; } } else count+= qualifier_len + num_recs; } } if (flag & 8) { /* add eventually missing mandatory ACL entries */ needed= (!has_u) + (!has_g) + (!has_o) + !(is_trivial || has_m); if(flag & 1) count+= needed; else { if((size_t) (count + needed) > result_size) {ret= -1; goto ex;} } } if ((flag & 8) && needed > 0 && !(flag & 1)) { if(!has_u) { perms= aaip_make_aaip_perms(st_mode & S_IRUSR, st_mode & S_IWUSR, st_mode * S_IXUSR); result[count++]= perms | (Aaip_ACL_USER_OBJ << 4); } if(!has_g) { perms= aaip_make_aaip_perms(st_mode & S_IRGRP, st_mode & S_IWGRP, st_mode * S_IXGRP); result[count++]= perms | (Aaip_ACL_GROUP_OBJ << 4); } if(!has_o) { perms= aaip_make_aaip_perms(st_mode & S_IROTH, st_mode & S_IWOTH, st_mode * S_IXOTH); result[count++]= perms | (Aaip_ACL_OTHER << 4); } if(!(is_trivial | has_m)) { perms= aaip_make_aaip_perms(st_mode & S_IRGRP, st_mode & S_IWGRP, st_mode * S_IXGRP); result[count++]= perms | (Aaip_ACL_MASK << 4); } } ret= count; ex:; LIBISO_FREE_MEM(name); return(ret); } int aaip_encode_both_acl(char *a_acl_text, char *d_acl_text, mode_t st_mode, size_t *result_len, unsigned char **result, int flag) { int ret; size_t a_acl_len= 0, d_acl_len= 0, acl_len= 0; unsigned char *a_acl= NULL, *d_acl= NULL, *acl= NULL; if(a_acl_text != NULL) { ret= aaip_encode_acl(a_acl_text, st_mode, &a_acl_len, &a_acl, flag & 11); if(ret <= 0) goto ex; } if(d_acl_text != NULL) { ret= aaip_encode_acl(d_acl_text, (mode_t) 0, &d_acl_len, &d_acl, (flag & 3) | 4); if(ret <= 0) goto ex; } if(a_acl == NULL || a_acl_len == 0) { acl= d_acl; d_acl= NULL; acl_len= d_acl_len; } else if (d_acl == NULL || d_acl_len == 0) { acl= a_acl; a_acl= NULL; acl_len= a_acl_len; } else { acl= calloc(a_acl_len + d_acl_len, 1); if(acl == NULL) {ret = -1; goto ex;} memcpy(acl, a_acl, a_acl_len); memcpy(acl + a_acl_len, d_acl, d_acl_len); acl_len= a_acl_len + d_acl_len; } *result= acl; *result_len= acl_len; ret= 1; ex:; if(a_acl != NULL) free(a_acl); if(d_acl != NULL) free(d_acl); return(ret); } /* GNU/Linux man 5 acl says: The permissions defined by ACLs are a superset of the permissions speci- fied by the file permission bits. The permissions defined for the file owner correspond to the permissions of the ACL_USER_OBJ entry. The per- missions defined for the file group correspond to the permissions of the ACL_GROUP_OBJ entry, if the ACL has no ACL_MASK entry. If the ACL has an ACL_MASK entry, then the permissions defined for the file group corre- spond to the permissions of the ACL_MASK entry. The permissions defined for the other class correspond to the permissions of the ACL_OTHER_OBJ entry. Modification of the file permission bits results in the modification of the permissions in the associated ACL entries. Modification of the per- missions in the ACL entries results in the modification of the file per- mission bits. */ /* Analyze occurence of ACL tag types in long text form. If not disabled by parameter flag remove the entries of type "user::" , "group::" , "other::" , or "other:" from an ACL in long text form if they match the bits in st_mode as described by man 2 stat and man 5 acl. @param acl_text The text to be analyzed and eventually shortened. @param st_mode The component of struct stat which tells POSIX permission bits and eventually shall take equivalent bits as read from the ACL. The caller should submit a pointer to the st_mode variable which holds permissions as indicated by stat(2) resp. ECMA-119 and RRIP data. @param flag bit0= do not remove entries, only determine return value bit1= like bit0 but return immediately if a non-st_mode ACL entry is found bit2= update *st_mode by acl_text ("user::" -> S_IRWXU, "mask::"|"group::" -> S_IRWXG, "other::" -> S_IRWXO) bit3= update acl_text by *st_mode (same mapping as bit 2 but with reversed transfer direction) bit4= map "group::" <-> S_IRWXG in any case. I.e. ignore "mask::". @return <0 failure >=0 tells in its bits which tag types were found. The first three tell which types deviate from the corresponding st_mode settings: bit0= "other::" overrides S_IRWXO bit1= "group::" overrides S_IRWXG (no "mask::" found) bit2= "user::" overrides S_IRWXU The second three tell which types comply with st_mode: bit3= "other::" matches S_IRWXO bit4= "group::" matches S_IRWXG (no "mask::" found) bit5= "user::" matches S_IRWXU Given the nature of ACLs nearly all combinations are possible although some would come from invalid ACLs. bit6= other ACL tag types are present. Particularly: bit7= "user:...:" is present bit8= "group:...:" is present bit9= "mask::" is present */ int aaip_cleanout_st_mode(char *acl_text, mode_t *in_st_mode, int flag) { char *rpt, *wpt, *npt, *cpt; mode_t m, list_mode, st_mode; int tag_types= 0, has_mask= 0, do_cleanout = 0; list_mode= st_mode= *in_st_mode; do_cleanout = !(flag & 15); has_mask= strncmp(acl_text, "mask:", 5) == 0 || strstr(acl_text, "\nmask:") != NULL; if(has_mask && (flag & 2)) return(64 | 512); for(npt= wpt= rpt= acl_text; *npt != 0; rpt= npt + 1) { npt= strchr(rpt, '\n'); if(npt == NULL) npt= rpt + strlen(rpt); if(strncmp(rpt, "user:", 5) == 0) { if(rpt[5] == ':' && npt - rpt == 9) { cpt= rpt + 6; m= 0; if(cpt[0] == 'r') m|= S_IRUSR; if(cpt[1] == 'w') m|= S_IWUSR; if(cpt[2] == 'x') m|= S_IXUSR; list_mode= (list_mode & ~S_IRWXU) | m; if((st_mode & S_IRWXU) == (m & S_IRWXU)) { tag_types|= 32; continue; } if(flag & 8) { cpt[0]= st_mode & S_IRUSR ? 'r' : '-'; cpt[1]= st_mode & S_IWUSR ? 'w' : '-'; cpt[2]= st_mode & S_IXUSR ? 'x' : '-'; } tag_types|= 4; } else { tag_types|= 64 | 128; } } else if(strncmp(rpt, "group:", 6) == 0) { if(rpt[6] == ':' && npt - rpt == 10 && ((flag & 16) || !has_mask)) { /* oddly: mask overrides group in st_mode */ cpt= rpt + 7; m= 0; if(cpt[0] == 'r') m|= S_IRGRP; if(cpt[1] == 'w') m|= S_IWGRP; if(cpt[2] == 'x') m|= S_IXGRP; list_mode= (list_mode & ~S_IRWXG) | m; if((st_mode & S_IRWXG) == (m & S_IRWXG)) { tag_types|= 16; continue; } if(flag & 8) { cpt[0]= st_mode & S_IRGRP ? 'r' : '-'; cpt[1]= st_mode & S_IWGRP ? 'w' : '-'; cpt[2]= st_mode & S_IXGRP ? 'x' : '-'; } tag_types|= 2; } else { if(rpt[6] == ':' && npt - rpt == 10) tag_types|= 1024; else tag_types|= 64 | 256; } } else if(strncmp(rpt, "other::", 7) == 0 && npt - rpt == 10) { cpt= rpt + 7; others_st_mode:; m= 0; if(cpt[0] == 'r') m|= S_IROTH; if(cpt[1] == 'w') m|= S_IWOTH; if(cpt[2] == 'x') m|= S_IXOTH; list_mode= (list_mode & ~S_IRWXO) | m; if((st_mode & S_IRWXO) == (m & S_IRWXO)) { tag_types|= 8; continue; } if(flag & 8) { cpt[0]= st_mode & S_IROTH ? 'r' : '-'; cpt[1]= st_mode & S_IWOTH ? 'w' : '-'; cpt[2]= st_mode & S_IXOTH ? 'x' : '-'; } tag_types|= 1; } else if(strncmp(rpt, "other:", 6) == 0 && npt - rpt == 9) { cpt= rpt + 7; goto others_st_mode; } else if(strncmp(rpt, "mask::", 6) == 0 && npt - rpt == 9) { cpt= rpt + 6; mask_st_mode:; tag_types|= 64 | 512; if(!(flag & 16)) { /* oddly: mask overrides group in st_mode */ m= 0; if(cpt[0] == 'r') m|= S_IRGRP; if(cpt[1] == 'w') m|= S_IWGRP; if(cpt[2] == 'x') m|= S_IXGRP; list_mode= (list_mode & ~S_IRWXG) | m; if(flag & 8) { cpt[0]= st_mode & S_IRGRP ? 'r' : '-'; cpt[1]= st_mode & S_IWGRP ? 'w' : '-'; cpt[2]= st_mode & S_IXGRP ? 'x' : '-'; } } } else if(strncmp(rpt, "mask:", 5) == 0 && npt - rpt == 8) { cpt= rpt + 5; goto mask_st_mode; } else if(*rpt != 0) { tag_types|= 64; } if (flag & 2) goto ex; if(wpt == rpt) { wpt= npt + 1; continue; } if(do_cleanout) memmove(wpt, rpt, 1 + npt - rpt); wpt+= 1 + npt - rpt; } if(do_cleanout) { if(wpt == acl_text) *wpt= 0; else if(*(wpt - 1) != 0) *wpt= 0; } ex:; if(flag & 4) *in_st_mode= list_mode; return(tag_types); } /* Important: acl_text must provide 42 bytes more than its current length ! */ int aaip_add_acl_st_mode(char *acl_text, mode_t st_mode, int flag) { char *wpt; int tag_types= 0; tag_types = aaip_cleanout_st_mode(acl_text, &st_mode, 1); if(!(tag_types & (4 | 32))) { wpt= acl_text + strlen(acl_text); sprintf(wpt, "user::%c%c%c\n", st_mode & S_IRUSR ? 'r' : '-', st_mode & S_IWUSR ? 'w' : '-', st_mode & S_IXUSR ? 'x' : '-'); } if(!(tag_types & (2 | 16 | 1024))) { wpt= acl_text + strlen(acl_text); sprintf(wpt, "group::%c%c%c\n", st_mode & S_IRGRP ? 'r' : '-', st_mode & S_IWGRP ? 'w' : '-', st_mode & S_IXGRP ? 'x' : '-'); } if(!(tag_types & (1 | 8))) { wpt= acl_text + strlen(acl_text); sprintf(wpt, "other::%c%c%c\n", st_mode & S_IROTH ? 'r' : '-', st_mode & S_IWOTH ? 'w' : '-', st_mode & S_IXOTH ? 'x' : '-'); } if((tag_types & (128 | 256)) && !(tag_types & 512)) { wpt= acl_text + strlen(acl_text); sprintf(wpt, "mask::%c%c%c\n", st_mode & S_IRGRP ? 'r' : '-', st_mode & S_IWGRP ? 'w' : '-', st_mode & S_IXGRP ? 'x' : '-'); } return(1); } /* --------------------------------- Decoder ---------------------------- */ /* --- private --- */ /* Not less than 2 * 2048 */ #define Aaip_buffer_sizE 4096 /* Enough for one full component record and three empty ones which might get added in case of unclean end of attribute list. */ #define Aaip_buffer_reservE (257 + 3 * 2) struct aaip_state { /* AAIP field status */ int aa_head_missing; /* number of bytes needed to complete field header */ int aa_missing; /* number of bytes needed to complete current field */ int aa_ends; /* 0= still fields expected, 1= last field being processed, 2= all fields processed, 3= all is delivered */ /* Buffer for component records */ int recs_invalid; /* number of components to skip */ unsigned char recs[Aaip_buffer_sizE + Aaip_buffer_reservE]; size_t recs_fill; unsigned char *recs_start; int rec_head_missing; /* number of bytes needed to complete rec header */ int rec_missing; /* number of bytes needed to complete current rec */ int rec_ends; /* Counter for completed data */ unsigned int num_recs; size_t ready_bytes; /* Counter and meaning for completed components */ unsigned int num_components; size_t end_of_components; /* start index of eventual incomplete component */ int first_is_name; /* Last return value of aaip_decode_pair() */ int pair_status; unsigned int pairs_skipped; /* status of aaip_decode_attrs() */ size_t list_mem_used; size_t list_size; size_t list_num_attrs; char **list_names; size_t *list_value_lengths; char **list_values; char *name_buf; size_t name_buf_size; size_t name_buf_fill; char *value_buf; size_t value_buf_size; size_t value_buf_fill; int list_pending_pair; }; /* ------- functions ------ */ size_t aaip_count_bytes(unsigned char *data, int flag) { int done = 0; unsigned char *aapt; for(aapt= data; !done; aapt += aapt[2]) done = !(aapt[4] & 1); return((size_t) (aapt - data)); } size_t aaip_sizeof_aaip_state(void) { return((size_t) sizeof(struct aaip_state)); } int aaip_init_aaip_state(struct aaip_state *aaip, int flag) { aaip->aa_head_missing= 5; aaip->aa_missing= 0; aaip->recs_invalid= 0; memset(aaip->recs, 0, Aaip_buffer_sizE + Aaip_buffer_reservE); aaip->recs_fill= 0; aaip->recs_start= aaip->recs; aaip->rec_head_missing= 2; aaip->rec_missing= 0; aaip->rec_ends= 0; aaip->num_recs= 0; aaip->ready_bytes= 0; aaip->num_components= 0; aaip->end_of_components= 0; aaip->first_is_name= 1; aaip->pair_status= 2; aaip->pairs_skipped= 0; aaip->list_mem_used= 0; aaip->list_size= 0; aaip->list_num_attrs= 0; aaip->list_names= NULL; aaip->list_value_lengths= NULL; aaip->list_values= NULL; aaip->name_buf= NULL; aaip->name_buf_size= 0; aaip->name_buf_fill= 0; aaip->value_buf= NULL; aaip->value_buf_size= 0; aaip->value_buf_fill= 0; aaip->list_pending_pair= 0; return(1); } /* */ #define Aaip_with_ring_buffeR yes #ifdef Aaip_with_ring_buffeR /* Compute the one or two byte intervals in the ring buffer which form a given byte interval in the virtual shift fifo. @param idx The byte start index in the virtual shift fifo. @param todo Number of bytes to cover @param start_pt Will return the start address of the first interval @param at_start_pt Will return the size of the first interval @param at_recs Will return the size of the second interval which always starts at aaip->recs @param flag Bitfield for control purposes @return 1= next start_pt is *start_pt + *at_start_pt 2= next start_pt is aaip->recs + *at_recs */ static int aaip_ring_adr(struct aaip_state *aaip, size_t idx, size_t todo, unsigned char **start_pt, size_t *at_start_pt, size_t *at_recs, int flag) { size_t ahead; ahead= Aaip_buffer_sizE + Aaip_buffer_reservE - (aaip->recs_start - aaip->recs); if(idx < ahead) *start_pt= (aaip->recs_start + idx); else *start_pt= aaip->recs + (idx - ahead); ahead= Aaip_buffer_sizE + Aaip_buffer_reservE - (*start_pt - aaip->recs); if(todo >= ahead) { *at_start_pt= ahead; *at_recs= todo - ahead; return(2); } *at_start_pt= todo; *at_recs= 0; return(1); } /* @param flag Bitfield for control purposes bit0= count as ready_bytes */ static int aaip_push_to_recs(struct aaip_state *aaip, unsigned char *data, size_t todo, int flag) { unsigned char *start_pt; size_t at_start_pt, at_recs; aaip_ring_adr(aaip, aaip->recs_fill, todo, &start_pt, &at_start_pt, &at_recs, 0); if(at_start_pt > 0) memcpy(start_pt, data, at_start_pt); if(at_recs > 0) memcpy(aaip->recs, data + at_start_pt, at_recs); aaip->recs_fill+= todo; if(flag & 1) aaip->ready_bytes+= todo; return(1); } static int aaip_read_from_recs(struct aaip_state *aaip, size_t idx, unsigned char *data, size_t num_data, int flag) { unsigned char *start_pt; size_t at_start_pt, at_recs; aaip_ring_adr(aaip, idx, num_data, &start_pt, &at_start_pt, &at_recs, 0); if(at_start_pt > 0) memcpy(data, start_pt, at_start_pt); if(at_recs > 0) memcpy(data + at_start_pt, aaip->recs, at_recs); return(1); } static int aaip_set_buffer_byte(struct aaip_state *aaip, size_t idx, unsigned char data, int flag) { unsigned char *start_pt; size_t at_start_pt, at_recs; aaip_ring_adr(aaip, idx, 1, &start_pt, &at_start_pt, &at_recs, 0); *start_pt= data; return(1); } static int aaip_get_buffer_byte(struct aaip_state *aaip, size_t idx, int flag) { unsigned char *start_pt; size_t at_start_pt, at_recs; aaip_ring_adr(aaip, idx, 1, &start_pt, &at_start_pt, &at_recs, 0); return((int) *start_pt); } static int aaip_shift_recs(struct aaip_state *aaip, size_t todo, int flag) { int ret; unsigned char *start_pt; size_t at_start_pt, at_recs; if(todo < aaip->recs_fill) { ret= aaip_ring_adr(aaip, 0, todo, &start_pt, &at_start_pt, &at_recs, 0); if(ret == 1) aaip->recs_start= start_pt + todo; else aaip->recs_start= aaip->recs + at_recs; } else { aaip->recs_start= aaip->recs; } aaip->recs_fill-= todo; if(aaip->end_of_components >= todo) aaip->end_of_components-= todo; else aaip->end_of_components= 0; return(1); } #else /* Aaip_with_ring_buffeR */ /* @param flag Bitfield for control purposes bit0= count as ready_bytes */ static int aaip_push_to_recs(struct aaip_state *aaip, unsigned char *data, size_t todo, int flag) { memcpy(aaip->recs + aaip->recs_fill, data, todo); aaip->recs_fill+= todo; if(flag & 1) aaip->ready_bytes+= todo; return(1); } static int aaip_read_from_recs(struct aaip_state *aaip, size_t idx, unsigned char *data, size_t num_data, int flag) { memcpy(data, aaip->recs + idx, num_data); return(1); } static int aaip_set_buffer_byte(struct aaip_state *aaip, size_t idx, unsigned char data, int flag) { aaip->recs[idx]= data; return(1); } static int aaip_get_buffer_byte(struct aaip_state *aaip, size_t idx, int flag) { return((int) aaip->recs[idx]); } static int aaip_shift_recs(struct aaip_state *aaip, size_t todo, int flag) { if(todo < aaip->recs_fill) memmove(aaip->recs, aaip->recs + todo, aaip->recs_fill - todo); aaip->recs_fill-= todo; if(aaip->end_of_components >= todo) aaip->end_of_components-= todo; else aaip->end_of_components= 0; return(1); } #endif /* ! Aaip_with_ring_buffeR */ static int aaip_consume_rec_head(struct aaip_state *aaip, unsigned char **data, size_t *num_data, int flag) { size_t todo; todo= *num_data; if(todo > (size_t) aaip->aa_missing) todo= aaip->aa_missing; if(todo >= (size_t) aaip->rec_head_missing) todo= aaip->rec_head_missing; if(!aaip->recs_invalid) aaip_push_to_recs(aaip, *data, todo, 0); aaip->rec_head_missing-= todo; if(aaip->rec_head_missing == 0) { aaip->rec_missing= aaip_get_buffer_byte(aaip, aaip->recs_fill - 1, 0); aaip->rec_ends= !(aaip_get_buffer_byte(aaip, aaip->recs_fill - 2, 0) & 1); } aaip->aa_missing-= todo; (*num_data)-= todo; (*data)+= todo; return(1); } static int aaip_consume_rec_data(struct aaip_state *aaip, unsigned char **data, size_t *num_data, int flag) { size_t todo; todo= *num_data; if(todo > (size_t) aaip->aa_missing) todo= aaip->aa_missing; if(todo > (size_t) aaip->rec_missing) todo= aaip->rec_missing; if(!aaip->recs_invalid) aaip_push_to_recs(aaip, *data, todo, 1); aaip->rec_missing-= todo; aaip->aa_missing-= todo; (*num_data)-= todo; (*data)+= todo; if(aaip->rec_missing <= 0) { if(aaip->recs_invalid > 0) { if(aaip->rec_ends) aaip->recs_invalid--; } else { aaip->num_recs++; if(aaip->rec_ends) { aaip->num_components++; aaip->end_of_components= aaip->recs_fill; } } aaip->rec_head_missing= 2; } return(0); } static int aaip_consume_aa_head(struct aaip_state *aaip, unsigned char **data, size_t *num_data, int flag) { size_t todo; unsigned char aa_head[5]; todo= *num_data; if(todo >= (size_t) aaip->aa_head_missing) todo= aaip->aa_head_missing; aaip_push_to_recs(aaip, *data, todo, 0); aaip->aa_head_missing-= todo; if(aaip->aa_head_missing == 0) { aaip_read_from_recs(aaip, aaip->recs_fill - 5, aa_head, 5, 0); if(aa_head[0] != 'A' || (aa_head[1] != 'L' && aa_head[1] != 'A') || aa_head[3] != 1) return(-1); aaip->aa_missing= aa_head[2]; aaip->aa_ends= !(aa_head[4] & 1); aaip->recs_fill-= 5; /* AAIP field heads do not get delivered */ if(aaip->aa_missing >= 5) aaip->aa_missing-= 5; else aaip->aa_missing= 0; } (*num_data)-= todo; (*data)+= todo; return(1); } static int aaip_consume_aa_data(struct aaip_state *aaip, unsigned char **data, size_t *num_data, int flag) { size_t i; static unsigned char zero_char[2]= {0, 0}; while(*num_data > 0 && aaip->aa_missing > 0) { if(aaip->rec_head_missing > 0) { aaip_consume_rec_head(aaip, data, num_data, 0); if(*num_data == 0 || aaip->aa_missing <= 0) return(1); } aaip_consume_rec_data(aaip, data, num_data, 0); } if(aaip->aa_missing <= 0) { if(aaip->aa_ends) { /* Check for incomplete pair and eventually make emergency closure */ if(aaip->rec_head_missing != 2) { /* incomplete record detected */ if(aaip->rec_head_missing) { /* fake 0 length record */ aaip_set_buffer_byte(aaip, aaip->recs_fill - 1, (unsigned char) 0, 0); aaip_push_to_recs(aaip, zero_char, 1, 0); } else { /* fill in missing btes */ for(i= 0; (int) i < aaip->rec_missing; i++) aaip_push_to_recs(aaip, zero_char, 1, 1); } aaip->rec_head_missing= 2; aaip->rec_missing= 0; aaip->num_recs++; if(aaip->rec_ends) { aaip->num_components++; aaip->end_of_components= aaip->recs_fill; } } if(aaip->end_of_components != aaip->recs_fill && aaip->end_of_components != 0) { /* incomplete component detected */ /* add empty end record */ aaip_push_to_recs(aaip, zero_char, 2, 0); aaip->num_recs++; aaip->num_components++; aaip->end_of_components= aaip->recs_fill; } if(!(aaip->first_is_name ^ (aaip->num_components % 2))) { /* value component is missing */ /* add dummy component */ aaip_push_to_recs(aaip, zero_char, 2, 0); aaip->num_recs++; aaip->num_components++; aaip->end_of_components= aaip->recs_fill; } aaip->aa_ends= 2; } else aaip->aa_head_missing= 5; } return(0); } /* Submit small data chunk for decoding. The return value will tell whether data are pending for being fetched. @param aaip The AAIP decoder context @param data Not more than 2048 bytes input for the decoder @parm num_data Number of bytes in data 0 inquires the buffer status avoiding replies <= 0 @param ready_bytes Number of decoded bytes ready for delivery @param flag Bitfield for control purposes @return -1= non-AAIP field detected *ready_bytes gives number of consumed bytes in data 0= cannot accept data because buffer full 1= no component record complete, submit more data 2= component record complete, may be delivered 3= component complete, may be delivered 4= no component available, no more data expected, done */ int aaip_submit_data(struct aaip_state *aaip, unsigned char *data, size_t num_data, size_t *ready_bytes, int flag) { int ret; unsigned char *in_data; if(aaip->aa_ends == 3) return(4); in_data= data; if(num_data == 0) goto ex; if(aaip->recs_fill + num_data > Aaip_buffer_sizE) return(0); while(num_data > 0) { if(aaip->aa_head_missing > 0) { ret= aaip_consume_aa_head(aaip, &data, &num_data, 0); if(ret < 0) { *ready_bytes= data - in_data; return(-1); } if(num_data == 0 || aaip->aa_missing <= 0) goto ex; } aaip_consume_aa_data(aaip, &data, &num_data, 0); if(aaip->aa_missing) break; } ex:; *ready_bytes= aaip->ready_bytes; if(aaip->num_components > 0) return(3); if(aaip->num_recs > 0) return(2); if(aaip->aa_ends && aaip->aa_head_missing == 0 && aaip->aa_missing == 0) aaip->aa_ends= 2; if(aaip->aa_ends == 2 && aaip->num_recs == 0) aaip->aa_ends= 3; if(aaip->aa_ends == 3) return(4); return(1); } /* Fetch the available part of current component. The return value will tell whether it belongs to name or to value and whether that name or value is completed now. @param aaip The AAIP decoder context @param result Has to point to storage for the component data @param result_size Gives the amount of provided result storage @param num_result Will tell the number of fetched result bytes @param flag Bitfield for control purposes bit0= discard data rather than copying to result @return -2 = insufficient result_size -1 = no data ready for delivery 0 = result holds the final part of a name 1 = result holds an intermediate part of a name 2 = result holds the final part of a value 3 = result holds an intermediate part of a value */ int aaip_fetch_data(struct aaip_state *aaip, char *result, size_t result_size, size_t *num_result, int flag) { int ret= -1, complete= 0, payload; unsigned int i, num_bytes= 0, h; if(aaip->num_recs == 0) return(-1); /* Copy data until end of buffer or end of component */ h= 0; for(i= 0; i < aaip->num_recs && !complete; i++) { payload= aaip_get_buffer_byte(aaip, h + 1, 0); if(!(flag & 1)) { if(num_bytes + payload > result_size) return(-2); aaip_read_from_recs(aaip, h + 2, (unsigned char *) (result + num_bytes), payload, 0); *num_result= num_bytes + payload; } num_bytes+= payload; if(!(aaip_get_buffer_byte(aaip, h, 0) & 1)) complete= 1; h+= payload + 2; } aaip->ready_bytes-= num_bytes; aaip->num_recs-= i; /* Shift buffer */ aaip_shift_recs(aaip, h, 0); /* Compute reply */ ret= 2 * !aaip->first_is_name; if(complete) { aaip->first_is_name= !aaip->first_is_name; if(aaip->num_components > 0) aaip->num_components--; } else ret|= 1; return(ret); } /* Skip the current component and eventually the following value component. This has to be called if fetching of a component shall be aborted but the next component resp. pair shall be fetchable again. aaip_submit_data() will not indicate readiness for fetching until all bytes of the skipped components are submitted. Those bytes get discarded. @param aaip The AAIP decoder context @param flag Bitfield for control purposes bit0= do not skip value if current component is name @return <=0 error , 1= now in skip state, 2= not in skip state */ int aaip_skip_component(struct aaip_state *aaip, int flag) { int to_skip= 1; if(aaip->first_is_name && !(flag & 1)) to_skip= 2; if(aaip->recs_invalid) { aaip->recs_invalid+= to_skip; return(1); } if(aaip->num_components) { /* null-fetch */ aaip_fetch_data(aaip, NULL, (size_t) 0, NULL, 1); to_skip--; } if(aaip->num_components && to_skip) { /* null-fetch */ aaip_fetch_data(aaip, NULL, (size_t) 0, NULL, 1); to_skip--; } if(to_skip) { aaip->recs_fill= 0; aaip->num_recs= 0; aaip->ready_bytes= 0; } aaip->recs_invalid= to_skip; if(aaip->aa_ends == 2 && aaip->num_recs == 0) aaip->aa_ends= 3; return(1 + (aaip->num_recs > 0)); } /* ------------------------- Pair Level Interface ------------------------ */ /* @param flag Bitfield for control purposes bit0= do not skip oversized component but return -2 @return see aaip_decode_pair */ static int aaip_advance_pair(struct aaip_state *aaip, char *name, size_t name_size, size_t *name_fill, char *value, size_t value_size, size_t *value_fill, int flag) { int ret; char *wpt; size_t size, num; retry:; if(aaip->first_is_name) { wpt= name + *name_fill; size= name_size - *name_fill; } else { wpt= value + *value_fill; size= value_size - *value_fill; } ret= aaip_fetch_data(aaip, wpt, size, &num, 0); if(ret == -2) { /* insufficient result size */ if(flag & 1) return(-2); ret= aaip_skip_component(aaip, 0); *name_fill= *value_fill= 0; aaip->pairs_skipped++; if(ret == 2) /* Skip performed, valid data pending */ goto retry; } else if(ret == -1) { /* No data ready for delivery : may not happen */ return(-1); } else if(ret == 0) { /* result holds the final part of a name */ (*name_fill)+= num; /* peek for value data */ ret= aaip_submit_data(aaip, NULL, (size_t) 0, &num, 0); if(ret == 2 || ret == 3) { /* fetch value data */; ret= aaip_advance_pair(aaip, name, name_size, name_fill, value, value_size, value_fill, flag); return ret; } else if(ret == 4) return(5); } else if(ret == 1) { /* result holds an intermediate part of a name */ (*name_fill)+= num; } else if(ret == 2) { /* result holds the final part of a value */ (*value_fill)+= num; if(aaip->num_components >= 2) return(3); if(aaip->aa_ends == 2 && aaip->num_recs == 0) aaip->aa_ends= 3; if(aaip->aa_ends == 3) return(4); return(2); } else if(ret == 3) { /* result holds an intermediate part of a value */; (*value_fill)+= num; } else { return(-1); /* unknown reply from aaip_fetch_data() */ } return(1); } /* Accept raw input data and collect a pair of name and value. The return value will indicate whether the pair is complete, whether more pairs are complete or whether more data are desired. No input data will be accepted as long as complete pairs are pending. The end of the attribute list will be indicated. @param aaip The AAIP decoder context @param data The raw data to decode @param num_data Number of data bytes provided @param consumed Returns the number of consumed data bytes @param name Buffer to build the name string @param name_size Maximum number of bytes in name @param name_fill Holds the current buffer fill of name @param value Buffer to build the value string @param value_size Maximum number of bytes in value @param value_fill Holds the current buffer fill of value @param flag Bitfield for control purposes bit0= do not skip oversized pair but return -2 @return <0 error -3 buffer full (program error) -2 insufficient result_size (only with flag bit0) -1 non-AAIP field detected 0 data not accepted, first fetch pending pairs with num_data == 0 1 name and value are not valid yet, submit more data 2 name and value are valid, submit more data 3 name and value are valid, pairs pending, fetch with num_data == 0 4 name and value are valid, no more data expected 5 name and value are not valid, no more data expected */ int aaip_decode_pair(struct aaip_state *aaip, unsigned char *data, size_t num_data, size_t *consumed, char *name, size_t name_size, size_t *name_fill, char *value, size_t value_size, size_t *value_fill, int flag) { int ret; size_t ready_bytes= 0; #ifdef Aaip_with_short_namespaceS char prefix[Aaip_max_name_expansioN + 1]; size_t nl, pl; #endif *consumed= 0; if((aaip->pair_status < 0 && aaip->pair_status != -2) || aaip->pair_status == 4 || aaip->pair_status == 5) { /* dead ends */ ret= aaip->pair_status; goto ex; } else if(aaip->pair_status == 2 || aaip->pair_status == 3) { if(aaip->pair_status == 3 && num_data > 0) {ret= 0; goto ex;} /* Start a new pair */ if(!aaip->first_is_name) /* Eventually skip orphaned value */ aaip_fetch_data(aaip, NULL, (size_t) 0, NULL, 1); *name_fill= *value_fill= 0; } if(num_data > 0) { ret= aaip_submit_data(aaip, data, num_data, &ready_bytes, 0); } else { ret= 1; if(aaip->num_components) ret= 3; else if(aaip->num_recs) ret= 2; } if(ret < 0) { /* non-AAIP field detected */ *consumed= ready_bytes; {ret= -1; goto ex;} } else if(ret == 0) { /* buffer overflow */; /* should not happen with correct usage */ {ret= -3; goto ex;} } else if(ret == 1) { /* no component record complete */ goto ex; } else if(ret == 2) { /* component record complete, may be delivered */ ; } else if(ret == 3) { /* component complete, may be delivered */ ; } else if(ret == 4) { /* no component available, no more data expected */ {ret= 5; goto ex;} } else {ret= -1; goto ex;} /* unknown reply from aaip_submit_data() */ *consumed= num_data; ret= aaip_advance_pair(aaip, name, name_size - Aaip_max_name_expansioN, name_fill, value, value_size, value_fill, flag & 1); if(aaip->aa_ends == 3) { if(ret >= 2 && ret <= 4) ret= 4; else ret= 5; } ex:; #ifdef Aaip_with_short_namespaceS if(ret >= 2 && ret <= 4 && *name_fill > 0) { /* Translate name from eventual short form */ nl= *name_fill; if(name[0] > 0 && name[0] <= Aaip_maxdef_namespacE) { prefix[0]= 0; if(name[0] == Aaip_namespace_literaL) { if(nl > 1) { /* Remove first character of name */ memmove(name, name + 1, nl - 1); (*name_fill)--; } } else if(name[0] == Aaip_namespace_systeM || name[0] == Aaip_namespace_useR || name[0] == Aaip_namespace_isofS || name[0] == Aaip_namespace_trusteD || name[0] == Aaip_namespace_securitY ) { strcpy(prefix, Aaip_namespace_textS[(int) name[0]]); pl= strlen(prefix); memmove(name + pl, name + 1, nl - 1); memcpy(name, prefix, pl); *name_fill= pl + nl - 1; } } } #endif /* Aaip_with_short_namespaceS */ aaip->pair_status= ret; return(ret); } unsigned int aaip_get_pairs_skipped(struct aaip_state *aaip, int flag) { return(aaip->pairs_skipped); } /* ------------------------- List Level Interface ------------------------ */ #define Aaip_initial_name_leN 256 #define Aaip_initial_value_leN 256 #define Aaip_initial_list_sizE 2 #define Aaip_list_enlargeR 1.5 /* @param flag Bitfield for control purposes bit0= do not update *buf_size */ static int aaip_enlarge_buf(struct aaip_state *aaip, size_t memory_limit, size_t item_size, char **buf, size_t *buf_size, int flag) { size_t new_size; char *new_buf; new_size= *buf_size * Aaip_list_enlargeR; if(aaip->list_mem_used + (new_size - *buf_size) * item_size >= memory_limit) return(3); aaip->list_mem_used+= (new_size - *buf_size) * item_size; new_buf= realloc(*buf, new_size * item_size); if(new_buf == NULL) return(-1); *buf= new_buf; if(!(flag & 1)) *buf_size= new_size; return(1); } /* Accept raw input data and collect arrays of name pointers, value lengths and value pointers. A handle object will emerge which finally has to be be freed by a call with bit 15. @param handle The decoding context. It will be created by this call with flag bit 0 or if *handle == NULL. This handle has to be the same as long as decoding goes on and finally has to be freed by a call with bit15. @param memory_limit Maximum number of bytes to allocate @param num_attr_limit Maximum number of name-value pairs to allocate @param data The raw data to decode @param num_data Number of data bytes provided @param consumed Returns the number of consumed data bytes @param flag Bitfield for control purposes bit0= this is the first call with the given handle (also in effect if *handle is NULL) bit15= end decoding : Free handle and its intermediate list memory. @return <=0 error -4 interpretation stalled, no valid result -3 program error, unexpected reply from lower layers -2 non-AAIP-field detected, arrays are complete, call aaip_get_decoded_attrs() -1 out of memory 1 not complete yet, submit more data 2 arrays are complete, call aaip_get_decoded_attrs() 3 limit exceeded, not complete yet, enlarge memory_limit or call with bit15 and give up 4 limit exceeded, call aaip_get_decoded_attrs() and try again */ int aaip_decode_attrs(struct aaip_state **handle, size_t memory_limit, size_t num_attr_limit, unsigned char *data, size_t num_data, size_t *consumed, int flag) { int ret; struct aaip_state *aaip; size_t h_num, *h_lengths, i, new_mem, pair_consumed= 0; char **h_names, **h_values, *hpt; *consumed= 0; if(flag & (1 << 15)) { if(*handle == NULL) return(0); ret= aaip_get_decoded_attrs(handle, &h_num, &h_names, &h_lengths, &h_values, 0); if(ret > 0) aaip_get_decoded_attrs(handle, &h_num, &h_names, &h_lengths, &h_values, 1 << 15); if((*handle)->name_buf != NULL) free((*handle)->name_buf); if((*handle)->value_buf != NULL) free((*handle)->value_buf); free((char *) *handle); *handle= NULL; return(1); } aaip= *handle; if(aaip == NULL || (flag & 1)) { aaip= *handle= calloc(1, sizeof(struct aaip_state)); if(*handle == NULL) return(-1); aaip_init_aaip_state(*handle, 0); } if(aaip->list_names == NULL || aaip->list_values == NULL || aaip->list_value_lengths == NULL) { /* Initialize arrays */ aaip->list_size= Aaip_initial_list_sizE; if(num_attr_limit > 0 && num_attr_limit < aaip->list_size) aaip->list_size= num_attr_limit; new_mem= aaip->list_size * (2*sizeof(char *) + sizeof(size_t)) + Aaip_initial_name_leN + Aaip_initial_value_leN; if(aaip->list_mem_used + new_mem >= memory_limit) return(3); aaip->list_mem_used+= new_mem; aaip->list_names= calloc(sizeof(char *), aaip->list_size); aaip->list_value_lengths= calloc(sizeof(size_t), aaip->list_size); aaip->list_values= calloc(sizeof(char *), aaip->list_size); if(aaip->list_names == NULL || aaip->list_value_lengths == NULL || aaip->list_values == NULL) return(-1); for(i= 0; i < aaip->list_size; i++) { aaip->list_names[i]= NULL; aaip->list_value_lengths[i]= 0; aaip->list_values[i]= NULL; } } if(aaip->name_buf == NULL || aaip->value_buf == NULL) { new_mem= Aaip_initial_name_leN + Aaip_initial_value_leN; if(aaip->list_mem_used >= memory_limit) return(3); aaip->list_mem_used+= new_mem; aaip->name_buf= calloc(1, Aaip_initial_name_leN); aaip->value_buf= calloc(1, Aaip_initial_value_leN); if(aaip->name_buf == NULL || aaip->value_buf == NULL) return(-1); aaip->name_buf_size= Aaip_initial_name_leN; aaip->value_buf_size= Aaip_initial_name_leN; } while(1) { if(aaip->list_pending_pair > 0) { /* the buffer holds a complete pair from a previous memory limit refusal */ ret= aaip->list_pending_pair; aaip->list_pending_pair= 0; } else { ret= aaip_decode_pair(aaip, data, num_data, &pair_consumed, aaip->name_buf, aaip->name_buf_size, &aaip->name_buf_fill, aaip->value_buf, aaip->value_buf_size, &aaip->value_buf_fill, 1); *consumed+= pair_consumed; } if(ret == -2) { /* insufficient result_size */ if(aaip->first_is_name) ret= aaip_enlarge_buf(aaip, memory_limit, (size_t) 1, &(aaip->name_buf), &(aaip->name_buf_size), 0); else ret= aaip_enlarge_buf(aaip, memory_limit, (size_t) 1, &(aaip->value_buf), &(aaip->value_buf_size), 0); if(ret != 1) return(ret); } else if(ret == -1) { /* non-AAIP field detected */ if(pair_consumed <= 0) return(-4); /* interpretation did not advance */ } else if(ret < 0) { /* other error */ return(-3); } else if(ret == 0) { /* first fetch pending pairs with num_data == 0 */ /* should not happen, fetch more pairs */; } else if(ret == 1) { /* name and value are not valid yet, submit more data */ return(1); } else if(ret == 2 || ret == 3 || ret == 4) { /* name and value are valid, submit more data */ /* name and value are valid, pairs pending, fetch with num_data == 0 */ /* name and value are valid, no more data expected */ aaip->list_pending_pair= ret; if(aaip->list_num_attrs >= aaip->list_size) { hpt= (char *) aaip->list_names; ret= aaip_enlarge_buf(aaip, memory_limit, sizeof(char *), &hpt, &(aaip->list_size), 1); if(ret != 1) return(ret); aaip->list_names= (char **) hpt; hpt= (char *) aaip->list_values; ret= aaip_enlarge_buf(aaip, memory_limit, sizeof(char *), &hpt, &(aaip->list_size), 1); if(ret != 1) return(ret); aaip->list_values= (char **) hpt; hpt= (char *) aaip->list_value_lengths; ret= aaip_enlarge_buf(aaip, memory_limit, sizeof(size_t), &hpt, &(aaip->list_size), 0); if(ret != 1) return(ret); aaip->list_value_lengths= (size_t *) hpt; } /* Allocate name and value in list */; if(aaip->list_mem_used + aaip->name_buf_fill + aaip->value_buf_fill + 2 > memory_limit) { return(3); } aaip->list_mem_used+= aaip->name_buf_fill + aaip->value_buf_fill + 2; i= aaip->list_num_attrs; aaip->list_names[i]= calloc(aaip->name_buf_fill + 1, 1); aaip->list_values[i]= calloc(aaip->value_buf_fill + 1, 1); memcpy(aaip->list_names[i], aaip->name_buf, aaip->name_buf_fill); aaip->list_names[i][aaip->name_buf_fill]= 0; memcpy(aaip->list_values[i], aaip->value_buf, aaip->value_buf_fill); aaip->list_values[i][aaip->value_buf_fill]= 0; aaip->list_value_lengths[i]= aaip->value_buf_fill; aaip->list_num_attrs++; aaip->name_buf_fill= aaip->value_buf_fill= 0; ret= aaip->list_pending_pair; aaip->list_pending_pair= 0; if(ret == 2) return(1); if(ret == 4) break; } else if(ret == 5) break; else return(-2); num_data= 0; /* consume pending pairs */ } aaip->list_pending_pair= 5; return(2); } /* Obtain the resulting attributes when aaip_decode_attrs() indicates to be done or to have the maximum possible amount of result ready. The returned data objects finally have to be freed by a call with flag bit 15. @param handle The decoding context created by aaip_decode_attrs() @param num_attrs Will return the number of name-value pairs @param names Will return an array of pointers to 0-terminated names @param value_lengths Will return an arry with the lenghts of values @param values Will return an array of pointers to 8-bit values @param flag Bitfield for control purposes bit15= free memory of names, value_lengths, values @return <0 error 0 no attribute list ready 1 ok */ int aaip_get_decoded_attrs(struct aaip_state **handle, size_t *num_attrs, char ***names, size_t **value_lengths, char ***values, int flag) { size_t i; struct aaip_state *aaip; aaip= *((struct aaip_state **) handle); if(flag & (1 << 15)) { if(*names != NULL) { for(i= 0; i < *num_attrs; i++) { if((*names)[i] != NULL) free((*names)[i]); (*names)[i]= NULL; } free(*names); *names= NULL; } if(*values != NULL) { for(i= 0; i < *num_attrs; i++) { if((*values)[i] != NULL) free((*values)[i]); (*values)[i]= NULL; } free(*values); *values= NULL; } if(*value_lengths != NULL) free(*value_lengths); *value_lengths= NULL; *num_attrs= 0; return(1); } /* Check whether decoding is finished yet */ if(aaip->list_pending_pair != 5) return(0); *num_attrs= aaip->list_num_attrs; *names= aaip->list_names; *value_lengths= aaip->list_value_lengths; *values= aaip->list_values; /* Now the memory is owned by the caller */ aaip->list_num_attrs= 0; aaip->list_names= NULL; aaip->list_value_lengths= NULL; aaip->list_values= NULL; aaip->list_size= 0; aaip->list_pending_pair= 0; return(1); } /* ------ Decoder for ACLs ------ */ static int aaip_write_acl_line(char **result, size_t *result_size, char *tag_type, char *qualifier, char *permissions, int flag) { size_t needed, tag_len, perm_len, qualifier_len; tag_len= strlen(tag_type); qualifier_len= strlen(qualifier); perm_len= strlen(permissions); needed= tag_len + qualifier_len + perm_len + 3; if((flag & 1)) { (*result_size)+= needed; return(1); } if(needed + 1 > *result_size) /* +1 : want to append a trailing 0 */ return(-1); memcpy((*result), tag_type, tag_len); (*result)[tag_len]= ':'; memcpy((*result) + tag_len + 1, qualifier, qualifier_len); (*result)[tag_len + 1 + qualifier_len]= ':'; memcpy((*result) + tag_len + 1 + qualifier_len + 1, permissions, perm_len); (*result)[tag_len + 1 + qualifier_len + 1 + perm_len]= '\n'; (*result)[tag_len + 1 + qualifier_len + 1 + perm_len + 1] = 0; (*result)+= needed; (*result_size)-= needed; return(1); } static int aaip_read_qualifier(unsigned char *data, size_t num_data, char *name, size_t name_size, size_t *name_fill, int flag) { int is_done= 0; size_t rec_len= 0; unsigned char *rpt; *name_fill= 0; for(rpt= data; !is_done; rpt+= rec_len) { rec_len= (*rpt) & 127; is_done= !((*rpt) & 128); if(*name_fill + rec_len >= name_size || (size_t) (rpt + 1 + rec_len - data) > num_data) return(-1); memcpy(name + *name_fill, rpt + 1, rec_len); rpt+= 1 + rec_len; (*name_fill)+= rec_len; name[*name_fill]= 0; } return(1); } /* Convert an AAIP ACL attribute value into the long text form of ACL. @param data The raw data to decode @param num_data Number of data bytes provided @param consumed Returns the number of consumed data bytes @param acl_text Will be filled with ACL long text form @param acl_text_size Maximum number of bytes to be written to acl_text @param acl_text_fill Will return the number of bytes in acl_text @param flag Bitfield for control purposes bit0= count only, do not really produce bytes: acl_text will not be touched, acl_text_size will be ignored, *acl_text_fill will return the counted number plus 1 for a trailing zero. bit1= expected is a default ACL (see return value 2) @return 1 success 2 success, begin of default/access ACL encountered, submit data + *consumed for access/default ACL -1 error with reading of qualifier -2 error with writing of ACL text line -3 version mismatch -4 unknown tag type encountered */ int aaip_decode_acl(unsigned char *data, size_t num_data, size_t *consumed, char *acl_text, size_t acl_text_size, size_t *acl_text_fill, int flag) { unsigned char *rpt; char perm_text[4], *wpt, *name= NULL; int type, qualifier= 0, perm, ret, cnt, name_size= 1024; size_t w_size= 0, name_fill= 0, i; uid_t uid; gid_t gid; struct passwd *pwd; struct group *grp; LIBISO_ALLOC_MEM(name, char, name_size); cnt= flag & 1; *consumed= 0; wpt= acl_text; w_size= acl_text_size; *acl_text_fill= 0; for(rpt= data; (size_t) (rpt - data) < num_data; ) { perm= *rpt; strcpy(perm_text, "---"); if(perm & Aaip_READ) perm_text[0]= 'r'; if(perm & Aaip_WRITE) perm_text[1]= 'w'; if(perm & Aaip_EXEC) perm_text[2]= 'x'; type= (*rpt) >> 4; if(type == Aaip_FUTURE_VERSION) /* indicate to caller: version mismatch */ {ret = -3; goto ex;} qualifier= !!((*rpt) & 8); if(qualifier) { ret= aaip_read_qualifier(rpt + 1, num_data - (rpt + 1 - data), name, name_size, &name_fill, 0); if(ret <= 0) {ret = -1; goto ex;} } /* Advance read pointer */ (*consumed)+= 1 + (qualifier ? name_fill + 1 : 0); rpt+= 1 + (qualifier ? name_fill + 1 : 0); ret= 1; if(type == Aaip_TRANSLATE) { /* rightfully ignored yet */; continue; } else if(type == Aaip_ACL_USER_OBJ) { /* user::rwx */ ret= aaip_write_acl_line(&wpt, &w_size, "user", "", perm_text, cnt); } else if(type == Aaip_ACL_USER) { /* user::rwx */; ret= aaip_write_acl_line(&wpt, &w_size, "user", name, perm_text, cnt); } else if(type == Aaip_ACL_GROUP_OBJ) { /* user::rwx */ ret= aaip_write_acl_line(&wpt, &w_size, "group", "", perm_text, cnt); } else if(type == Aaip_ACL_GROUP) { /* group::rwx */; ret= aaip_write_acl_line(&wpt, &w_size, "group", name, perm_text, cnt); } else if(type == Aaip_ACL_MASK) { /* mask::rwx */ ret= aaip_write_acl_line(&wpt, &w_size, "mask", "", perm_text, cnt); } else if(type == Aaip_ACL_OTHER) { /* other::rwx */ ret= aaip_write_acl_line(&wpt, &w_size, "other", "", perm_text, cnt); } else if(type == Aaip_SWITCH_MARK) { /* Indicate to caller: end of desired ACL type access/default */ if((perm & Aaip_EXEC) ^ (!!(flag & 2))) {ret= 2; goto ex;} } else if(type == Aaip_ACL_USER_N) { /* determine username from uid */ uid= 0; for(i= 0; i < name_fill; i++) uid= (uid << 8) | ((unsigned char *) name)[i]; pwd= getpwuid(uid); if(pwd == NULL) sprintf(name, "%.f", (double) uid); else if(strlen(pwd->pw_name) >= (size_t) name_size) sprintf(name, "%.f", (double) uid); else strcpy(name, pwd->pw_name); /* user::rwx */; ret= aaip_write_acl_line(&wpt, &w_size, "user", name, perm_text, cnt); } else if(type == Aaip_ACL_GROUP_N) { /* determine username from gid */; gid= 0; for(i= 0; i < name_fill; i++) gid= (gid << 8) | ((unsigned char *) name)[i]; grp= getgrgid(gid); if(grp == NULL) sprintf(name, "%.f", (double) gid); else if(strlen(grp->gr_name) >= (size_t) name_size) sprintf(name, "%.f", (double) gid); else strcpy(name, grp->gr_name); /* user::rwx */; ret= aaip_write_acl_line(&wpt, &w_size, "group", name, perm_text, cnt); } else { /* indicate to caller: unknown type */ {ret = -4; goto ex;} } if(ret <= 0) {ret = -2; goto ex;} } ret= 1; ex:; *acl_text_fill= w_size; if(flag & 1) (*acl_text_fill)++; LIBISO_FREE_MEM(name); return(ret); } /* ----------------------- Adapter for operating systems ----------------- */ #ifdef __FreeBSD__ #include "aaip-os-freebsd.c" #else #ifdef __NetBSD__ #include "aaip-os-freebsd.c" #else #ifdef __linux #include "aaip-os-linux.c" /* August 2011: aaip-os-linux.c would also work for GNU/Hurd : ifdef __GNU__ Libraries and headers are present on Debian GNU/Hurd but there is no ACL or xattr support in the filesystems yet. Further, llistxattr() produces ENOSYS "Function not implemented". So it makes few sense to enable it here. */ #else #include "aaip-os-dummy.c" #endif /* ! __linux */ #endif /* ! __NetBSD__ */ #endif /* ! __FreeBSD__ */ libisofs-1.4.2/libisofs/fsource.h0000644000175700017510000000271612477360032013724 00000000000000/* * Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2009 - 2015 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ #ifndef LIBISO_FSOURCE_H_ #define LIBISO_FSOURCE_H_ /* * Definitions for the file sources. Most functions/structures related with * this were moved to libisofs.h. */ #include "libisofs.h" #define ISO_LOCAL_FS_ID 1 #define ISO_IMAGE_FS_ID 2 #define ISO_ELTORITO_FS_ID 3 #define ISO_MEM_FS_ID 4 #define ISO_FILTER_FS_ID 5 /** * Create a new IsoFilesystem to deal with local filesystem. * * @return * 1 sucess, < 0 error */ int iso_local_filesystem_new(IsoFilesystem **fs); /* Rank two IsoFileSource of ifs_class by their eventual old image LBAs. * @param cmp_ret will return the reply value -1, 0, or 1. * @return 1= *cmp_ret is a valid reply * 0= not both streams are of ifs_class, * *cmp_ret is only a rough estimation. */ int iso_ifs_sections_cmp(IsoFileSource *s1, IsoFileSource *s2, int *cmp_ret, int flag); /* Create an independent copy of an ifs_class IsoFileSource. */ int iso_ifs_source_clone(IsoFileSource *old_source, IsoFileSource **new_source, int flag); #endif /*LIBISO_FSOURCE_H_*/ libisofs-1.4.2/libisofs/iso1999.h0000644000175700017510000000250012321161425013364 00000000000000/* * Copyright (c) 2007 Vreixo Formoso * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ /** * Structures related to ISO/IEC 9660:1999, that is version 2 of ISO-9660 * "See doc/devel/cookbook/ISO 9660-1999" and * ISO/IEC DIS 9660:1999(E) "Information processing. Volume and file structure * of CD­-ROM for Information Interchange" * for further details. */ #ifndef LIBISO_ISO1999_H #define LIBISO_ISO1999_H #include "libisofs.h" #include "ecma119.h" enum iso1999_node_type { ISO1999_FILE, ISO1999_DIR }; struct iso1999_dir_info { Iso1999Node **children; size_t nchildren; size_t len; size_t block; }; struct iso1999_node { char *name; /**< Name chosen output charset. */ Iso1999Node *parent; IsoNode *node; /*< reference to the iso node */ enum iso1999_node_type type; union { IsoFileSrc *file; struct iso1999_dir_info *dir; } info; }; /** * Create a IsoWriter to deal with ISO 9660:1999 estructures, and add it to * the given target. * * @return * 1 on success, < 0 on error */ int iso1999_writer_create(Ecma119Image *target); #endif /* LIBISO_ISO1999_H */ libisofs-1.4.2/libisofs/system_area.h0000644000175700017510000002656212465116151014575 00000000000000/* * Copyright (c) 2008 Vreixo Formoso * Copyright (c) 2012 - 2015 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ /* * Functions for dealing with the system area, this is, the first 16 blocks * of the image. * * At this time, this is only used for hybrid boot images with isolinux. */ #ifndef SYSTEM_AREA_H_ #define SYSTEM_AREA_H_ #include "ecma119.h" /* * Create a MBR for an isohybrid enabled ISOLINUX boot image. * * It is assumed that the caller has verified the readiness of the boot image * by checking for 0xfb 0xc0 0x78 0x70 at bytes 0x40 to 0x43 of isolinux.bin. * * @param bin_lba The predicted LBA of isolinux.bin within the emerging ISO. * @param img_blocks The predicted number of 2048 byte blocks in the ISO. * It will get rounded up to full MBs and that many blocks * must really be written as ISO 9660 image. * @param mbr A buffer of at least 512 bytes to take the result which is * to be written as the very beginning of the ISO. * @param flag unused yet, submit 0 * @return <0 = fatal, 0 = failed , 1 = ok , 2 = ok with size warning */ int make_isohybrid_mbr(int bin_lba, int *img_blocks, char *mbr, int flag); /** * Write the system area for the given image to the given buffer. * * @param buf * A buffer with at least 32 K allocated * @return * 1 if success, < 0 on error */ int iso_write_system_area(Ecma119Image *t, uint8_t *buf); /** * Adjust t->tail_blocks to the eventual alignment needs of isohybrid booting. */ int iso_align_isohybrid(Ecma119Image *t, int flag); /** * Read the necessary ELF information from the first MIPS boot file. * See doc/boot_sectors.txt "DEC Boot Block" for "MIPS Little Endian". */ int iso_read_mipsel_elf(Ecma119Image *t, int flag); /* Compute size and position of appended partitions. */ int iso_compute_append_partitions(Ecma119Image *t, int flag); /* The parameter struct for production of a single MBR partition entry. See also the description of MBR in doc/boot_sectors.txt. No sorting by start sector and gap filling is done before the System Area gets written. But the entries may get assigned to a desired slot number in the table. Requested entries with block_count == 0 get expanded to the start of the next requested entry resp. to image end, if no entry follows. start_block of a follwing entry must be at least a high as the sum of start_block and block_count of the previous entry. Empty requested entries will be represented as 16 bytes of 0. */ struct iso_mbr_partition_request { /* Always given in blocks of 512 bytes */ uint64_t start_block; /* A block count of 0 means that the partition reaches up to the start of the next one. */ uint64_t block_count; /* Partition type */ uint8_t type_byte; /* 0x80 = bootable */ uint8_t status_byte; /* If >= 1 && <= 4 : The partition slot number in MBR. If more than one partition desires the same slot, then an error ISO_BOOT_MBR_COLLISION occurs at registration time. Use iso_mbr_entry_slot_is_free() to detect this in advance. If desired_slot is 0, then the partition entry is put into the lowest MBR slot that is not occupied by an entry with desired_slot > 0 or by an entry that was registered before this entry. */ int desired_slot; }; /* Copies the content of req and registers it in t.mbr_req[]. I.e. after the call the submitted storage of req can be disposed or re-used. Submit 0 as value flag. */ int iso_register_mbr_entry(struct iso_mbr_partition_request **req_array, int *mbr_req_count, struct iso_mbr_partition_request *req, int flag); /* Convenience frontend for iso_register_mbr_entry(). name and type are 0-terminated strings, which may get silently truncated. */ int iso_quick_mbr_entry(struct iso_mbr_partition_request **req_array, int *mbr_req_count, uint64_t start_block, uint64_t block_count, uint8_t type_byte, uint8_t status_byte, int desired_slot); /* Peek in advance whether a desired slot number is already occupied by a registered MBR entry. Parameter slot may be between 0 and 4. 0 always returns "free". Return value is 0 if occupied, 1 if free, and -1 if the slot number is out of range. */ int iso_mbr_entry_slot_is_free(struct iso_mbr_partition_request **req_array, int mbr_req_count, int slot); /* The parameter struct for production of a single Apple Partition Map entry. See also the partial APM description in doc/boot_sectors.txt. The list of entries is stored e.g. in Ecma119Image.apm_req, .apm_req_count. The size of a block can be chosen by setting Ecma119Image.apm_block_size. If an entry has start_block <=1, then its block_count will be adjusted to the final size of the partition map. If no such entry is requested, then it will be prepended automatically with name "Apple" and type "Apple_partition_map". The requested entries will get sorted and gaps will be filled by more entries. */ struct iso_apm_partition_request { /* Given in blocks of 2 KiB unless (Ecma119Image.apm_req_flags & 4). Written to the ISO image according to Ecma119Image.apm_block_size. */ uint64_t start_block; uint64_t block_count; /* All 32 bytes get copied to the system area. Take care to pad up short strings by 0. */ uint8_t name[32]; uint8_t type[32]; }; /* Copies the content of req and registers it in t.apm_req[]. I.e. after the call the submitted storage of req can be disposed or re-used. Submit 0 as value flag. */ int iso_register_apm_entry(struct iso_apm_partition_request **req_array, int *apm_req_count, struct iso_apm_partition_request *req, int flag); /* Convenience frontend for iso_register_apm_entry(). name and type are 0-terminated strings, which may get silently truncated. */ int iso_quick_apm_entry(struct iso_apm_partition_request **req_array, int *apm_req_count, uint32_t start_block, uint32_t block_count, char *name, char *type); /* These two pseudo-random generators produce byte strings which will surely not duplicate in the first 256 calls. If more calls are necessary in the same process, then one must wait until the output of gettimeofday(2) changes. It is advised to obtain them as late as possible, so that Ecma119Image *t can distinguish itself from other image production setups which might be run on other machines with the same process number at the same time. */ /* Produces a weakly random variation of a hardcoded real random uuid */ void iso_random_uuid(Ecma119Image *t, uint8_t uuid[16]); /* The parameter struct for production of a single GPT entry. See also the partial GPT description in doc/boot_sectors.txt. The list of entries is stored in Ecma119Image.gpt_req. The GPT header block at byte 0x200 will get produced automatically. The requested entries will get sorted and gaps will be filled by more entries. Overlapping partitions are allowed only if (Ecma119Image.gpt_req_flags & 1). The block_count will be truncated to the image size before the GPT backup. The GPT entries will be stored after the Apple Partition Map, if such gets generated too. Both partition descriptions must fit into the 32 KiB of the ISO 9660 System Area. GPT can be combined with APM only if (Ecma119Image.apm_block_size > 512). Otherwise, block 1 of APM and GPT header block would collide. So Ecma119Image.apm_block_size is set automatically to 2048 if at least one GPT entry is requested. (One could try 1024 ...). */ struct iso_gpt_partition_request { /* Always given in blocks of 512 bytes. */ uint64_t start_block; uint64_t block_count; /* The registered GUID which defines the partition type */ uint8_t type_guid[16]; /* An individual GUID which shall be unique to the partition. If the caller submits 0...0 then a (weak) random uuid will be generated. */ uint8_t partition_guid[16]; /* bit0= "System Partition" Do not alter, bit2= Legacy BIOS bootable (MBR partition type 0x80) bit60= read-only */ uint64_t flags; /* Fill with text encoded as UTF-16LE. All 72 bytes get copied to the system area. Take care to pad up short strings by 0. */ uint8_t name[72]; /* Only if read from imported image: Table index of partition (first = 1) */ uint32_t idx; }; /* Copies the content of req and registers it in t.gpt_req[]. I.e. after the call the submitted storage of req can be disposed or re-used. Submit 0 as value flag. */ int iso_register_gpt_entry(struct iso_gpt_partition_request **req_array, int *gpt_req_count, struct iso_gpt_partition_request *req, int flag); /* Convenience frontend for iso_register_gpt_entry(). name has to be already encoded as UTF-16LE. */ int iso_quick_gpt_entry(struct iso_gpt_partition_request **req_array, int *gpt_req_count, uint64_t start_block, uint64_t block_count, uint8_t type_guid[16], uint8_t partition_guid[16], uint64_t flags, uint8_t name[72]); /* Internal helper that will be used by system_area.c and make_isohybrid_mbr.c */ int iso_write_gpt_header_block(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf, uint32_t max_entries, uint32_t part_start, uint32_t p_arr_crc); /* The description of a loaded MIPS Big Endian Volume Directory Entry */ struct iso_mips_voldir_entry { char name[9]; uint32_t boot_block; uint32_t boot_bytes; }; /* The description of a loaded SUN Disk Label partition */ struct iso_sun_disk_label_entry { int idx; uint16_t id_tag; uint16_t permissions; uint32_t start_cyl; uint32_t num_blocks; }; /* Creates the Partition Prepend writer. */ int partprepend_writer_create(Ecma119Image *target); /* Creates the Inline Partition Append Writer */ int partappend_writer_create(Ecma119Image *target); /* Creates the GPT backup tail writer. */ int gpt_tail_writer_create(Ecma119Image *target); /* Not for execution but only to identify the writer by ( writer->write_vol_desc == gpt_tail_writer_write_vol_desc ) */ int gpt_tail_writer_write_vol_desc(IsoImageWriter *writer); /* Only for up to 36 characters ISO-8859-1 (or ASCII) input */ void iso_ascii_utf_16le(uint8_t gap_name[72]); /* Parameters of MBR patching for GRUB2 Might later become variables in Ecma119Image */ #define Libisofs_grub2_mbr_patch_poS 0x1b0 #define Libisofs_grub2_mbr_patch_offsT 4 /* Parameters of SUN Disk Label patching for GRUB2 See API iso_image_set_sparc_core(). */ #define Libisofs_grub2_sparc_patch_adr_poS 0x228 #define Libisofs_grub2_sparc_patch_size_poS 0x230 /* >>> It is unclear whether there is a use case for appended partitions inside the ISO filesystem range. # define Libisofs_appended_partitions_inlinE yes */ #endif /* SYSTEM_AREA_H_ */ libisofs-1.4.2/libisofs/util_rbtree.c0000644000175700017510000002101412551162460014557 00000000000000/* * Copyright (c) 2007 Vreixo Formoso * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif #include "util.h" #include "libisofs.h" #include /* * This implementation of Red-Black tree is based on the public domain * implementation of Julienne Walker. */ struct iso_rbnode { void *data; struct iso_rbnode *ch[2]; unsigned int red :1; }; struct iso_rbtree { struct iso_rbnode *root; size_t size; int (*compare)(const void *a, const void *b); }; /** * Create a new binary tree. libisofs binary trees allow you to add any data * passing it as a pointer. You must provide a function suitable for compare * two elements. * * @param compare * A function to compare two elements. It takes a pointer to both elements * and return 0, -1 or 1 if the first element is equal, less or greater * than the second one. * @param tree * Location where the tree structure will be stored. */ int iso_rbtree_new(int (*compare)(const void*, const void*), IsoRBTree **tree) { if (compare == NULL || tree == NULL) { return ISO_NULL_POINTER; } *tree = calloc(1, sizeof(IsoRBTree)); if (*tree == NULL) { return ISO_OUT_OF_MEM; } (*tree)->compare = compare; return ISO_SUCCESS; } static void rbtree_destroy_aux(struct iso_rbnode *root, void (*free_data)(void *)) { if (root == NULL) { return; } if (free_data != NULL) { free_data(root->data); } rbtree_destroy_aux(root->ch[0], free_data); rbtree_destroy_aux(root->ch[1], free_data); free(root); } /** * Destroy a given tree. * * Note that only the structure itself is deleted. To delete the elements, you * should provide a valid free_data function. It will be called for each * element of the tree, so you can use it to free any related data. */ void iso_rbtree_destroy(IsoRBTree *tree, void (*free_data)(void *)) { if (tree == NULL) { return; } rbtree_destroy_aux(tree->root, free_data); free(tree); } static inline int is_red(struct iso_rbnode *root) { return root != NULL && root->red; } static struct iso_rbnode *iso_rbtree_single(struct iso_rbnode *root, int dir) { struct iso_rbnode *save = root->ch[!dir]; root->ch[!dir] = save->ch[dir]; save->ch[dir] = root; root->red = 1; save->red = 0; return save; } static struct iso_rbnode *iso_rbtree_double(struct iso_rbnode *root, int dir) { root->ch[!dir] = iso_rbtree_single(root->ch[!dir], !dir); return iso_rbtree_single(root, dir); } static struct iso_rbnode *iso_rbnode_new(void *data) { struct iso_rbnode *rn = malloc(sizeof(struct iso_rbnode)); if (rn != NULL) { rn->data = data; rn->red = 1; rn->ch[0] = NULL; rn->ch[1] = NULL; } return rn; } /** * Inserts a given element in a Red-Black tree. * * @param tree * the tree where to insert * @param data * element to be inserted on the tree. It can't be NULL * @param item * if not NULL, it will point to a location where the tree element ptr * will be stored. If data was inserted, *item == data. If data was * already on the tree, *item points to the previously inserted object * that is equal to data. * @return * 1 success, 0 element already inserted, < 0 error */ int iso_rbtree_insert(IsoRBTree *tree, void *data, void **item) { struct iso_rbnode *new; int added = 0; /* has a new node been added? */ if (tree == NULL || data == NULL) { return ISO_NULL_POINTER; } if (tree->root == NULL) { /* Empty tree case */ tree->root = iso_rbnode_new(data); if (tree->root == NULL) { return ISO_OUT_OF_MEM; } new = data; added = 1; } else { struct iso_rbnode head = { 0, {NULL, NULL}, 0 }; /* False tree root */ struct iso_rbnode *g, *t; /* Grandparent & parent */ struct iso_rbnode *p, *q; /* Iterator & parent */ int dir = 0, last = 0; int comp; /* Set up helpers */ t = &head; g = p = NULL; q = t->ch[1] = tree->root; /* Search down the tree */ while (1) { if (q == NULL) { /* Insert new node at the bottom */ p->ch[dir] = q = iso_rbnode_new(data); if (q == NULL) { return ISO_OUT_OF_MEM; } added = 1; } else if (is_red(q->ch[0]) && is_red(q->ch[1])) { /* Color flip */ q->red = 1; q->ch[0]->red = 0; q->ch[1]->red = 0; } /* Fix red violation */ if (is_red(q) && is_red(p)) { int dir2 = (t->ch[1] == g); if (q == p->ch[last]) { t->ch[dir2] = iso_rbtree_single(g, !last); } else { t->ch[dir2] = iso_rbtree_double(g, !last); } } if (q->data == data) { comp = 0; } else { comp = tree->compare(q->data, data); } /* Stop if found */ if (comp == 0) { new = q->data; break; } last = dir; dir = (comp < 0); /* Update helpers */ if (g != NULL) t = g; g = p, p = q; q = q->ch[dir]; } /* Update root */ tree->root = head.ch[1]; } /* Make root black */ tree->root->red = 0; if (item != NULL) { *item = new; } if (added) { /* a new element has been added */ tree->size++; return 1; } else { return 0; } } /** * Get the number of elements in a given tree. */ size_t iso_rbtree_get_size(IsoRBTree *tree) { return tree->size; } static size_t rbtree_to_array_aux(struct iso_rbnode *root, void **array, size_t pos, int (*include_item)(void *)) { if (root == NULL) { return pos; } pos = rbtree_to_array_aux(root->ch[0], array, pos, include_item); if (include_item == NULL || include_item(root->data)) { array[pos++] = root->data; } pos = rbtree_to_array_aux(root->ch[1], array, pos, include_item); return pos; } /** * Get an array view of the elements of the tree. * * @param include_item * Function to select which elements to include in the array. It that takes * a pointer to an element and returns 1 if the element should be included, * 0 if not. If you want to add all elements to the array, you can pass a * NULL pointer. * @return * A sorted array with the contents of the tree, or NULL if there is not * enought memory to allocate the array. You should free(3) the array when * no more needed. Note that the array is NULL-terminated, and thus it * has size + 1 length. */ void ** iso_rbtree_to_array(IsoRBTree *tree, int (*include_item)(void *), size_t *size) { size_t pos; void **array, **new_array; array = malloc((tree->size + 1) * sizeof(void*)); if (array == NULL) { return NULL; } /* fill array */ pos = rbtree_to_array_aux(tree->root, array, 0, include_item); array[pos] = NULL; new_array = realloc(array, (pos + 1) * sizeof(void*)); if (new_array == NULL) { free((char *) array); return NULL; } array= new_array; if (size) { *size = pos; } return array; } static size_t rbtree_count_array_aux(struct iso_rbnode *root, size_t pos, int (*include_item)(void *)) { if (root == NULL) { return pos; } pos = rbtree_count_array_aux(root->ch[0], pos, include_item); if (include_item == NULL || include_item(root->data)) { /* { IsoFileSrc* src = (IsoFileSrc*) root->data; fprintf(stderr, "libisofs_DEBUG: rbtree_count_array_aux : not taken : '%s'\n", iso_stream_get_source_path(src->stream, 0)); } */ pos++; } pos = rbtree_count_array_aux(root->ch[1], pos, include_item); return pos; } size_t iso_rbtree_count_array(IsoRBTree *tree, size_t initial_count, int (*include_item)(void *)) { size_t pos; pos = rbtree_count_array_aux(tree->root, initial_count, include_item); return pos; } libisofs-1.4.2/libisofs/hfsplus.h0000644000175700017510000001067712321161425013740 00000000000000/* * Copyright (c) 2012 Vladimir Serbinenko * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ /** * Declare HFS+ related structures. */ #ifndef LIBISO_HFSPLUS_H #define LIBISO_HFSPLUS_H #include "libisofs.h" #include "ecma119.h" #define LIBISO_HFSPLUS_NAME_MAX 255 enum hfsplus_node_type { HFSPLUS_DIR = 1, HFSPLUS_FILE = 2, HFSPLUS_DIR_THREAD = 3, HFSPLUS_FILE_THREAD = 4 }; struct hfsplus_btree_node { uint32_t start; uint32_t cnt; uint32_t strlen; uint16_t *str; uint32_t parent_id; }; struct hfsplus_btree_level { uint32_t level_size; struct hfsplus_btree_node *nodes; }; struct hfsplus_node { /* Note: .type HFSPLUS_DIR_THREAD and HFSPLUS_FILE_THREAD do not own their .name and .cmp_name. They have copies of others, if ever. */ uint16_t *name; /* Name in UTF-16BE, decomposed. */ uint16_t *cmp_name; /* Name used for comparing. */ IsoNode *node; /*< reference to the iso node */ enum { UNIX_NONE, UNIX_SYMLINK, UNIX_SPECIAL } unix_type; uint32_t symlink_block; char *symlink_dest; enum hfsplus_node_type type; IsoFileSrc *file; uint32_t cat_id; uint32_t parent_id; uint32_t nchildren; uint32_t strlen; uint32_t used_size; }; int hfsplus_writer_create(Ecma119Image *target); int hfsplus_tail_writer_create(Ecma119Image *target); struct hfsplus_extent { /* The first block of a file on disk. */ uint32_t start; /* The amount of blocks described by this extent. */ uint32_t count; } __attribute__ ((packed)); struct hfsplus_forkdata { uint64_t size; uint32_t clumpsize; uint32_t blocks; struct hfsplus_extent extents[8]; } __attribute__ ((packed)); struct hfsplus_volheader { uint16_t magic; uint16_t version; uint32_t attributes; uint32_t last_mounted_version; uint32_t journal; uint32_t ctime; uint32_t utime; uint32_t backup_time; uint32_t fsck_time; uint32_t file_count; uint32_t folder_count; uint32_t blksize; uint32_t total_blocks; uint32_t free_blocks; uint32_t next_allocation; uint32_t rsrc_clumpsize; uint32_t data_clumpsize; uint32_t catalog_node_id; uint32_t write_count; uint64_t encodings_bitmap; uint32_t ppc_bootdir; uint32_t intel_bootfile; /* Folder opened when disk is mounted. */ uint32_t showfolder; uint32_t os9folder; uint32_t unused; uint32_t osxfolder; uint64_t num_serial; struct hfsplus_forkdata allocations_file; struct hfsplus_forkdata extents_file; struct hfsplus_forkdata catalog_file; struct hfsplus_forkdata attrib_file; struct hfsplus_forkdata startup_file; } __attribute__ ((packed)); struct hfsplus_btnode { uint32_t next; uint32_t prev; int8_t type; uint8_t height; uint16_t count; uint16_t unused; } __attribute__ ((packed)); /* The header of a HFS+ B+ Tree. */ struct hfsplus_btheader { uint16_t depth; uint32_t root; uint32_t leaf_records; uint32_t first_leaf_node; uint32_t last_leaf_node; uint16_t nodesize; uint16_t keysize; uint32_t total_nodes; uint32_t free_nodes; uint16_t reserved1; uint32_t clump_size; uint8_t btree_type; uint8_t key_compare; uint32_t attributes; uint32_t reserved[16]; } __attribute__ ((packed)); struct hfsplus_catfile_thread { uint16_t type; uint16_t reserved; uint32_t parentid; uint16_t namelen; } __attribute__ ((packed)); struct hfsplus_catfile_common { uint16_t type; uint16_t flags; uint32_t valence; /* for files: reserved. */ uint32_t fileid; uint32_t ctime; uint32_t mtime; uint32_t attr_mtime; uint32_t atime; uint32_t backup_time; uint32_t uid; uint32_t gid; uint8_t user_flags; uint8_t group_flags; uint16_t mode; uint32_t special; uint8_t file_type[4]; /* For folders: window size */ uint8_t file_creator[4]; /* For folders: window size */ uint8_t finder_info[24]; uint32_t text_encoding; uint32_t reserved; } __attribute__ ((packed)); #define HFSPLUS_MAX_DECOMPOSE_LEN 4 extern uint16_t (*hfsplus_decompose_pages[256])[HFSPLUS_MAX_DECOMPOSE_LEN + 1]; void make_hfsplus_decompose_pages(); extern uint16_t *hfsplus_class_pages[256]; void make_hfsplus_class_pages(); extern const uint16_t hfsplus_casefold[]; int iso_get_hfsplus_name(char *input_charset, int imgid, char *name, uint16_t **result, uint32_t *result_len, uint16_t **cmp_name); #endif /* LIBISO_HFSPLUS_H */ libisofs-1.4.2/libisofs/rockridge.h0000644000175700017510000002504612605712201014220 00000000000000/* * Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2007 Mario Danic * Copyright (c) 2009 - 2015 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ /** * This header defines the functions and structures needed to add RockRidge * extensions to an ISO image. It also handles AAIP and zisofs extensions. * * References: * * - SUSP (IEEE 1281). * System Use Sharing Protocol, draft standard version 1.12. * See ftp://ftp.ymi.com/pub/rockridge/susp112.ps * * - RRIP (IEEE 1282) * Rock Ridge Interchange Protocol, Draft Standard version 1.12. * See ftp://ftp.ymi.com/pub/rockridge/rrip112.ps * * - ECMA-119 (ISO-9660) * Volume and File Structure of CDROM for Information Interchange. See * http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-119.pdf * * - AAIP * Arbitrary Attribute Interchange Protocol. See doc/susp_aaip_2_0.txt * * - zisofs * Blockwise compression of data file content with transparent read support * in the Linux kernel. See doc/zisofs_format.txt * */ #ifndef LIBISO_ROCKRIDGE_H #define LIBISO_ROCKRIDGE_H #include "ecma119.h" #define SUSP_SIG(entry, a, b) ((entry->sig[0] == a) && (entry->sig[1] == b)) /** * This contains the information about the System Use Fields (SUSP, 4.1), * that will be written in the System Use Areas, both in the ISO directory * record System Use field (ECMA-119, 9.1.13) or in a Continuation Area as * defined by SUSP. */ struct susp_info { /** Number of SUSP fields in the System Use field */ size_t n_susp_fields; uint8_t **susp_fields; /** Length of the part of the SUSP area that fits in the dirent. */ int suf_len; /** Length of the part of the SUSP area that will go in a CE area. */ uint32_t ce_block; uint32_t ce_len; /* Storage for Continuation Area for a whole directory */ size_t n_ce_susp_fields; uint8_t **ce_susp_fields; /* The number of allocated members in ce_susp_fields */ size_t alloc_ce_susp_fields; /* Marks the start index in ce_susp_fields of the current node */ size_t current_ce_start; }; /* Step to increase allocated size of susp_info.ce_susp_fields */ #define ISO_SUSP_CE_ALLOC_STEP 16 /* SUSP 5.1 */ struct susp_CE { uint8_t block[8]; uint8_t offset[8]; uint8_t len[8]; }; /* SUSP 5.3 */ struct susp_SP { uint8_t be[1]; uint8_t ef[1]; uint8_t len_skp[1]; }; /* SUSP 5.5 */ struct susp_ER { uint8_t len_id[1]; uint8_t len_des[1]; uint8_t len_src[1]; uint8_t ext_ver[1]; uint8_t ext_id[1]; /*< up to len_id bytes */ /* ext_des, ext_src */ }; /** POSIX file attributes (RRIP, 4.1.1) */ struct rr_PX { uint8_t mode[8]; uint8_t links[8]; uint8_t uid[8]; uint8_t gid[8]; uint8_t serial[8]; }; /** Time stamps for a file (RRIP, 4.1.6) */ struct rr_TF { uint8_t flags[1]; uint8_t t_stamps[1]; }; /** Info for character and block device (RRIP, 4.1.2) */ struct rr_PN { uint8_t high[8]; uint8_t low[8]; }; /** Alternate name (RRIP, 4.1.4) */ struct rr_NM { uint8_t flags[1]; uint8_t name[1]; }; /** Link for a relocated directory (RRIP, 4.1.5.1) */ struct rr_CL { uint8_t child_loc[8]; }; /** Sim link (RRIP, 4.1.3) */ struct rr_SL { uint8_t flags[1]; uint8_t comps[1]; }; /** Outdated Arbitrary Attribute (AAIP, see doc/susp_aaip_1_0.txt) * It collided with pre-SUSP Apple AA field. */ struct aaip_AA { uint8_t flags[1]; uint8_t comps[1]; }; /** Arbitrary Attribute (AAIP, see doc/susp_aaip_2_0.txt) */ struct aaip_AL { uint8_t flags[1]; uint8_t comps[1]; }; /** zisofs entry (see doc/zisofs_format.txt) */ struct zisofs_ZF { uint8_t parameters[1]; /* begins with BP 5 */ }; /** * Struct for a SUSP System User Entry (SUSP, 4.1) */ struct susp_sys_user_entry { uint8_t sig[2]; uint8_t len_sue[1]; uint8_t version[1]; union { struct susp_CE CE; struct susp_SP SP; struct susp_ER ER; struct rr_PX PX; struct rr_TF TF; struct rr_PN PN; struct rr_NM NM; struct rr_CL CL; struct rr_SL SL; struct aaip_AA AA; struct aaip_AL AL; struct zisofs_ZF ZF; } data; /* 5 to 4+len_sue */ }; /** * Compute the length needed for write all RR and SUSP entries for a given * node. * * @param type * 0 normal entry, 1 "." entry for that node (it is a dir), 2 ".." * for that node (i.e., it will refer to the parent) * @param space * Available space in the System Use Area for the directory record. * @param ce * Will be filled with the space needed in a CE * @param base_ce * Fill of continuation area by previous nodes of same dir * @return * The size needed for the RR entries in the System Use Area */ size_t rrip_calc_len(Ecma119Image *t, Ecma119Node *n, int type, size_t space, size_t *ce, size_t base_ce); /** * Fill a struct susp_info with the RR/SUSP entries needed for a given * node. * * @param type * 0 normal entry, 1 "." entry for that node (it is a dir), 2 ".." * for that node (i.e., it will refer to the parent) * @param space * Available space in the System Use Area for the directory record. * @param info * Pointer to the struct susp_info where the entries will be stored. * If some entries need to go to a Continuation Area, they will be added * to the existing ce_susp_fields, and ce_len will be incremented * propertly. Please ensure ce_block is initialized propertly. * @return * 1 success, < 0 error */ int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type, size_t space, struct susp_info *info); /** * Write the given SUSP fields into buf. Note that Continuation Area * fields are not written. * If info does not contain any SUSP entry this function just return. * After written, the info susp_fields array will be freed, and the counters * updated propertly. */ void rrip_write_susp_fields(Ecma119Image *t, struct susp_info *info, uint8_t *buf); /** * Write the Continuation Area entries for the given struct susp_info, using * the iso_write() function. * After written, the ce_susp_fields array will be freed. */ int rrip_write_ce_fields(Ecma119Image *t, struct susp_info *info); /** * The SUSP iterator is used to iterate over the System User Entries * of a ECMA-168 directory record. * It takes care about Continuation Areas, handles the end of the different * system user entries and skip padding areas. Thus, using an iteration * we are accessing just to the meaning entries. */ typedef struct susp_iterator SuspIterator; SuspIterator * susp_iter_new(IsoDataSource *src, struct ecma119_dir_record *record, uint8_t len_skp, int msgid); /** * Get the next SUSP System User Entry using given iterator. * * @param sue * Pointer to the next susp entry. It refers to an internal buffer and * it's not guaranteed to be allocated after calling susp_iter_next() * again. Thus, if you need to keep some entry you have to do a copy. * @return * 1 on success, 0 if no more entries, < 0 error */ int susp_iter_next(SuspIterator *iter, struct susp_sys_user_entry **sue); /** * Free a given susp iterator. */ void susp_iter_free(SuspIterator *iter); /** * Fills a struct stat with the values of a Rock Ridge PX entry (RRIP, 4.1.1). * * @return * < 0 on error * 1 on success with no inode number, * 2 on success with inode number, */ int read_rr_PX(struct susp_sys_user_entry *px, struct stat *st); /** * Fills a struct stat with the values of a Rock Ridge TF entry (RRIP, 4.1.6) * * @return * 1 on success, < 0 on error */ int read_rr_TF(struct susp_sys_user_entry *tf, struct stat *st); /** * Read a RR NM entry (RRIP, 4.1.4), and appends the name stored there to * the given name. You can pass a pointer to NULL as name. * * @return * 1 on success, < 0 on error */ int read_rr_NM(struct susp_sys_user_entry *nm, char **name, int *cont); /** * Read a SL RR entry (RRIP, 4.1.3), checking if the destination continues. * * @param cont * 0 not continue, 1 continue, 2 continue component * @return * 1 on success, < 0 on error */ int read_rr_SL(struct susp_sys_user_entry *sl, char **dest, int *cont); /** * Fills a struct stat with the values of a Rock Ridge PN entry (RRIP, 4.1.2). * * @return * 1 on success, < 0 on error */ int read_rr_PN(struct susp_sys_user_entry *pn, struct stat *st); /** * Collects the AAIP field string from single AAIP fields. * (see doc/susp_aaip_1_0.txt) * @param aa_string Storage location of the emerging string. * Begin with *aa_string == NULL, or own malloc() storage. * @param aa_size Current allocated size of aa_string. * Begin with *aa_size == 0, or own storage size. * @param aa_len Current occupied size of aa_string. * Begin with *aa_len == 0 * @param prev_field Returns the index of start of the previous field * in the string. * @param is_done The current completion state of the AAIP field string. * Fields will be ignored as soon as it is 1. * Begin with *is_done == 0 * @param flag Unused yet. Submit 0. * @return * 1 on success, < 0 on error */ int read_aaip_AA(struct susp_sys_user_entry *sue, unsigned char **aa_string, size_t *aa_size, size_t *aa_len, size_t *prev_field, int *is_done, int flag); /** * Collects the AAIP field string from single AL fields. * (see doc/susp_aaip_2_0.txt) */ int read_aaip_AL(struct susp_sys_user_entry *sue, unsigned char **aa_string, size_t *aa_size, size_t *aa_len, size_t *prev_field, int *is_done, int flag); /** * Reads the zisofs parameters from a ZF field (see doc/zisofs_format.txt). * * @return * 1 on success, < 0 on error */ int read_zisofs_ZF(struct susp_sys_user_entry *zf, uint8_t algorithm[2], uint8_t *header_size_div4, uint8_t *block_size_log2, uint32_t *uncompressed_size, int flag); /** * Convert a RR filename to the requested charset. * @param flag bit0= do not issue error messages */ int iso_get_rr_name(IsoWriteOpts *opts, char *input_charset, char *output_charset, int imgid, char *str, char **name, int flag); #endif /* LIBISO_ROCKRIDGE_H */ libisofs-1.4.2/libisofs/ecma119.h0000644000175700017510000010524712534607512013422 00000000000000/* * Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2009 - 2015 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ #ifndef LIBISO_ECMA119_H_ #define LIBISO_ECMA119_H_ #include "libisofs.h" #include "util.h" #include "buffer.h" #ifdef HAVE_STDINT_H #include #else #ifdef HAVE_INTTYPES_H #include #endif #endif #include #define BLOCK_SIZE 2048 /* * Maximum file section size. Set to 4GB - 1 = 0xffffffff */ #define MAX_ISO_FILE_SECTION_SIZE 0xffffffff /* * When a file need to be splitted in several sections, the maximum size * of such sections, but the last one. Set to a multiple of BLOCK_SIZE. * Default to 4GB - 2048 = 0xFFFFF800 */ #define ISO_EXTENT_SIZE 0xFFFFF800 /* * The maximum number of partition images that can be registered. Depending * on the system area type, the effectively usable number may be smaller or * even 0. */ #define ISO_MAX_PARTITIONS 8 /* * The cylindersize with SUN Disk Label * (512 bytes/sector, 640 sectors/head, 1 head/cyl = 320 KiB). * Expressed in ECMA-119 blocks of 2048 bytes/block. */ #define ISO_SUN_CYL_SIZE 160 /* * Maximum length of a disc label text plus 1. */ #define ISO_DISC_LABEL_SIZE 129 /* The maximum lenght of an specs violating ECMA-119 file identifier. The theoretical limit is 254 - 34 - 28 (len of SUSP CE entry) = 192 Currently the practical limit is 254 - 34 - 96 (non-CE RR entries) - 28 (CE) */ #ifdef Libisofs_with_rrip_rR #define ISO_UNTRANSLATED_NAMES_MAX 92 #else #define ISO_UNTRANSLATED_NAMES_MAX 96 #endif /* The theoretical maximum number of Apple Partition Map entries in the System Area of an ISO image: Block0 plus 63 entries with block size 512 */ #define ISO_APM_ENTRIES_MAX 63 /* The maximum number of MBR partition table entries. */ #define ISO_MBR_ENTRIES_MAX 4 /* The theoretical maximum number of GPT entries in the System Area of an ISO image: MBR plus GPT header block plus 248 GPT entries of 128 bytes each. */ #define ISO_GPT_ENTRIES_MAX 248 /* How many warnings to issue about writing Joliet names which cannot be properly represented in UCS-2 and thus had to be defaultet to '_'. */ #define ISO_JOLIET_UCS2_WARN_MAX 3 /** * Holds the options for the image generation. */ struct iso_write_opts { int will_cancel; int iso_level; /**< ISO level to write at. (ECMA-119, 10) */ /** Which extensions to support. */ unsigned int rockridge :1; unsigned int joliet :1; unsigned int iso1999 :1; unsigned int hfsplus :1; unsigned int fat :1; unsigned int aaip :1; /* whether to write eventual ACL and EAs */ /* allways write timestamps in GMT */ unsigned int always_gmt :1; /* * Relaxed constraints. Setting any of these to 1 break the specifications, * but it is supposed to work on most moderns systems. Use with caution. */ /** * Convert directory names for ECMA-119 the same way as other file names * but do not force dots or add version numbers. * This violates ECMA-119 by allowing one "." and especially ISO level 1 * by allowing DOS style 8.3 names rather than only 8 characters. */ unsigned int allow_dir_id_ext :1; /** * Omit the version number (";1") at the end of the ISO-9660 identifiers. * Version numbers are usually not used. * bit0= ECMA-119 and Joliet (for historical reasons) * bit1= Joliet */ unsigned int omit_version_numbers :2; /** * Allow ISO-9660 directory hierarchy to be deeper than 8 levels. */ unsigned int allow_deep_paths :1; /** * Allow path in the ISO-9660 tree to have more than 255 characters. */ unsigned int allow_longer_paths :1; /** * Allow a single file or directory hierarchy to have up to 37 characters. * This is larger than the 31 characters allowed by ISO level 2, and the * extra space is taken from the version number, so this also forces * omit_version_numbers. */ unsigned int max_37_char_filenames :1; /** * ISO-9660 forces filenames to have a ".", that separates file name from * extension. libisofs adds it if original filename doesn't has one. Set * this to 1 to prevent this behavior * bit0= ECMA-119 * bit1= Joliet */ unsigned int no_force_dots :2; /** * Allow lowercase characters in ISO-9660 filenames. By default, only * uppercase characters, numbers and a few other characters are allowed. */ unsigned int allow_lowercase :1; /** * Allow all ASCII characters to be appear on an ISO-9660 filename. Note * that "/" and "\0" characters are never allowed, even in RR names. */ unsigned int allow_full_ascii :1; /** * If not allow_full_ascii is set: allow all 7 bit characters that would * be allowed by allow_full_ascii. But still map lowercase to uppercase if * not allow_lowercase is set to 1. */ unsigned int allow_7bit_ascii :1; /** * Allow all characters to be part of Volume and Volset identifiers on * the Primary Volume Descriptor. This breaks ISO-9660 contraints, but * should work on modern systems. */ unsigned int relaxed_vol_atts :1; /** * Allow paths in the Joliet tree to have more than 240 characters. */ unsigned int joliet_longer_paths :1; /** * Allow Joliet names up to 103 characters rather than 64. */ unsigned int joliet_long_names :1; /** * Use UTF-16BE rather than its subset UCS-2 */ unsigned int joliet_utf16 :1; /** * Write Rock Ridge info as of specification RRIP-1.10 rather than * RRIP-1.12: signature "RRIP_1991A" rather than "IEEE_1282", * field PX without file serial number */ unsigned int rrip_version_1_10 :1; /** * Write field PX with file serial number even with RRIP-1.10 */ unsigned int rrip_1_10_px_ino :1; /** * See iso_write_opts_set_hardlinks() */ unsigned int hardlinks:1; /** * Write AAIP as extension according to SUSP 1.10 rather than SUSP 1.12. * I.e. without announcing it by an ER field and thus without the need * to preceed the RRIP fields by an ES and to preceed the AA field by ES. * This saves bytes and might avoid problems with readers which dislike * ER fields other than the ones for RRIP. * On the other hand, SUSP 1.12 frowns on such unannounced extensions * and prescribes ER and ES. It does this since year 1994. * * In effect only if above flag .aaip is set to 1. */ unsigned int aaip_susp_1_10 :1; /** * Store as ECMA-119 Directory Record timestamp the mtime of the source * rather than the image creation time. (The ECMA-119 prescription seems * to expect that we do have a creation timestamp with the source. * mkisofs writes mtimes and the result seems more suitable if mounted * without Rock Ridge support.) * bit0= ECMA-119, bit1= Joliet, bit2= ISO 9660:1999 */ unsigned int dir_rec_mtime :3; /** * This describes the directory where to store Rock Ridge relocated * directories. * If not relaxation "allow_deep_paths" is in effect, it is necessary to * relocate directories so that no ECMA-119 file path has more than * 8 components. For Rock Ridge the relocated directories are linked forth * and back to a placeholder at their original position in path level 8 * (entries CL and PL). Directories marked by entry RE are to be considered * artefacts of relocation and shall not be read into a Rock Ridge tree. * For plain ECMA-119, the relocation directory is just a normal directory * which contains normal files and directories. */ char *rr_reloc_dir; /* IsoNode name in root directory */ int rr_reloc_flags; /* bit0= mark auto-created rr_reloc_dir by RE bit1= directory was auto-created (cannot be set via API) */ /** * Compute MD5 checksum for the whole session and record it as index 0 of * the checksum blocks after the data area of the session. The layout and * position of these blocks will be recorded in xattr "isofs.ca" of the * root node. See see also API call iso_image_get_session_md5(). */ unsigned int md5_session_checksum :1; /** * Compute MD5 checksums for IsoFile objects and write them to blocks * after the data area of the session. The layout and position of these * blocks will be recorded in xattr "isofs.ca" of the root node. * The indice of the MD5 sums will be recorded with the IsoFile directory * entries as xattr "isofs.cx". See also API call iso_file_get_md5(). * bit0= compute individual checksums * bit1= pre-compute checksum and compare it with actual one. * Raise MISHAP if mismatch. */ unsigned int md5_file_checksums :2; /** If files should be sorted based on their weight. */ unsigned int sort_files :1; /** * The following options set the default values for files and directory * permissions, gid and uid. All these take one of three values: 0, 1 or 2. * If 0, the corresponding attribute will be kept as setted in the IsoNode. * Unless you have changed it, it corresponds to the value on disc, so it * is suitable for backup purposes. If set to 1, the corresponding attrib. * will be changed by a default suitable value. Finally, if you set it to * 2, the attrib. will be changed with the value specified in the options * below. Note that for mode attributes, only the permissions are set, the * file type remains unchanged. */ unsigned int replace_dir_mode :2; unsigned int replace_file_mode :2; unsigned int replace_uid :2; unsigned int replace_gid :2; mode_t dir_mode; /** Mode to use on dirs when replace_dir_mode == 2. */ mode_t file_mode; /** Mode to use on files when replace_file_mode == 2. */ uid_t uid; /** uid to use when replace_uid == 2. */ gid_t gid; /** gid to use when replace_gid == 2. */ /** * See API call iso_write_opts_set_old_empty(). */ unsigned int old_empty :1; /** * Extra Caution: This option breaks any assumptions about names that * are supported by ECMA-119 specifications. * Omit any translation which would make a file name compliant to the * ECMA-119 rules. This includes and exceeds omit_version_numbers, * max_37_char_filenames, no_force_dots bit0, allow_lowercase. * The maximum name length is given by this variable. * There is a length limit of ISO_UNTRANSLATED_NAMES_MAX characters, * because ECMA-119 allows 254 byte in a directory record, some * of them are occupied by ECMA-119, some more are needed for SUSP CE, * and some are fixely occupied by libisofs Rock Ridge code. * The default value 0 disables this feature. */ unsigned int untranslated_name_len; /** * 0 to use IsoNode timestamps, 1 to use recording time, 2 to use * values from timestamp field. This has only meaning if RR extensions * are enabled. */ unsigned int replace_timestamps :2; time_t timestamp; /** * Charset for the RR filenames that will be created. * NULL to use default charset, the locale one. */ char *output_charset; /** * This flags control the type of the image to create. Libisofs support * two kind of images: stand-alone and appendable. * * A stand-alone image is an image that is valid alone, and that can be * mounted by its own. This is the kind of image you will want to create * in most cases. A stand-alone image can be burned in an empty CD or DVD, * or write to an .iso file for future burning or distribution. * * On the other side, an appendable image is not self contained, it refers * to serveral files that are stored outside the image. Its usage is for * multisession discs, where you add data in a new session, while the * previous session data can still be accessed. In those cases, the old * data is not written again. Instead, the new image refers to it, and thus * it's only valid when appended to the original. Note that in those cases * the image will be written after the original, and thus you will want * to use a ms_block greater than 0. * * Note that if you haven't import a previous image (by means of * iso_image_import()), the image will always be a stand-alone image, as * there is no previous data to refer to. */ unsigned int appendable : 1; /** * Start block of the image. It is supposed to be the lba where the first * block of the image will be written on disc. All references inside the * ISO image will take this into account, thus providing a mountable image. * * For appendable images, that are written to a new session, you should * pass here the lba of the next writable address on disc. * * In stand alone images this is usually 0. However, you may want to * provide a different ms_block if you don't plan to burn the image in the * first session on disc, such as in some CD-Extra disc whether the data * image is written in a new session after some audio tracks. */ uint32_t ms_block; /** * When not NULL, it should point to a buffer of at least 64KiB, where * libisofs will write the contents that should be written at the beginning * of a overwriteable media, to grow the image. The growing of an image is * a way, used by first time in growisofs by Andy Polyakov, to allow the * appending of new data to non-multisession media, such as DVD+RW, in the * same way you append a new session to a multisession disc, i.e., without * need to write again the contents of the previous image. * * Note that if you want this kind of image growing, you will also need to * set appendable to "1" and provide a valid ms_block after the previous * image. * * You should initialize the buffer either with 0s, or with the contents of * the first blocks of the image you're growing. In most cases, 0 is good * enought. */ uint8_t *overwrite; /** * Size, in number of blocks, of the FIFO buffer used between the writer * thread and the burn_source. You have to provide at least a 32 blocks * buffer. */ size_t fifo_size; /** * This is not an option setting but a value returned after the options * were used to compute the layout of the image. * It tells the LBA of the first plain file data block in the image. */ uint32_t data_start_lba; /** * If not empty: A text holding parameters "name" and "timestamp" for * a scdbackup stream checksum tag. See scdbackup/README appendix VERIFY. * It makes sense only for single session images which start at LBA 0. * Such a tag may be part of a libisofs checksum tag block after the * session tag line. It then covers the whole session up to its own start * position. */ char scdbackup_tag_parm[100]; /* If not NULL: A pointer to an application provided array with at least 512 characters. The effectively written scdbackup tag will be copied to this memory location. */ char *scdbackup_tag_written; /* * See ecma119_image : System Area related information */ char *system_area_data; int system_area_size; int system_area_options; /* User settable PVD time stamps */ time_t vol_creation_time; time_t vol_modification_time; time_t vol_expiration_time; time_t vol_effective_time; /* To eventually override vol_creation_time and vol_modification_time * by unconverted string with timezone 0 */ char vol_uuid[17]; /* The number of unclaimed 2K blocks before start of partition 1 as of the MBR in system area. Must be 0 or >= 16. (Actually >= number of voldescr + checksum tag) */ uint32_t partition_offset; /* Partition table parameter: 1 to 63, 0= disabled/default */ int partition_secs_per_head; /* 1 to 255, 0= disabled/default */ int partition_heads_per_cyl; #ifdef Libisofs_with_libjtE /* Parameters and state of Jigdo Template Export environment. */ struct libjte_env *libjte_handle; #endif /* Libisofs_with_libjtE */ /* A trailing padding of zero bytes which belongs to the image */ uint32_t tail_blocks; /* Eventual disk file path of a PreP partition which shall be prepended to HFS+/FAT and IsoFileSrc areas and marked by an MBR partition entry. */ char *prep_partition; int prep_part_flag; /* Eventual disk file path of an EFI system partition image which shall be prepended to HFS+/FAT and IsoFileSrc areas and marked by a GPT entry. */ char *efi_boot_partition; int efi_boot_part_flag; /* Eventual disk file paths of prepared images which shall be appended after the ISO image and described by partiton table entries in a MBR */ char *appended_partitions[ISO_MAX_PARTITIONS]; uint8_t appended_part_types[ISO_MAX_PARTITIONS]; int appended_part_flags[ISO_MAX_PARTITIONS]; /* If 1: With appended partitions: create protective MBR and mark by GPT */ int appended_as_gpt; /* Eventual name of the non-ISO aspect of the image. E.g. SUN ASCII label. */ char ascii_disc_label[ISO_DISC_LABEL_SIZE]; /* HFS+ image serial number. * 00...00 means that it shall be generated by libisofs. */ uint8_t hfsp_serial_number[8]; /* Allocation block size of HFS+ : 0= auto , 512, or 2048 */ int hfsp_block_size; /* Block size of and in APM : 0= auto , 512, or 2048 */ int apm_block_size; }; typedef struct ecma119_image Ecma119Image; typedef struct ecma119_node Ecma119Node; typedef struct joliet_node JolietNode; typedef struct iso1999_node Iso1999Node; typedef struct hfsplus_node HFSPlusNode; typedef struct Iso_File_Src IsoFileSrc; typedef struct Iso_Image_Writer IsoImageWriter; struct ecma119_image { int refcount; IsoImage *image; Ecma119Node *root; IsoWriteOpts *opts; /** Whether El Torito data will be produced */ unsigned int eltorito :1; /* The ECMA-119 directory node where to store Rock Ridge relocated directories. (Path is in IsoWriteOpts.rr_reloc_dir) */ Ecma119Node *rr_reloc_node; /* Directory node in ecma119_image */ /* * Mode replace. If one of these flags is set, the correspodent values are * replaced with values below. Both get computed from IsoWriteOpts. */ unsigned int replace_uid :1; unsigned int replace_gid :1; unsigned int replace_file_mode :1; unsigned int replace_dir_mode :1; unsigned int replace_timestamps :1; /* Mode replacement values. */ uid_t uid; gid_t gid; mode_t file_mode; mode_t dir_mode; time_t timestamp; /* Effective charsets */ char *input_charset; char *output_charset; time_t now; /**< Time at which writing began. */ /** Total size of the output. This only includes the current volume. */ off_t total_size; uint32_t vol_space_size; /* Bytes already written to image output */ off_t bytes_written; /* just for progress notification */ int percent_written; /* * Block being processed, either during image writing or structure * size calculation. */ uint32_t curblock; /* * The address to be used for the content pointer of empty data files. */ uint32_t empty_file_block; /* * The calculated block address after ECMA-119 tree and eventual * tree checksum tag. */ uint32_t tree_end_block; /* * number of dirs in ECMA-119 tree, computed together with dir position, * and needed for path table computation in a efficient way */ size_t ndirs; uint32_t path_table_size; uint32_t l_path_table_pos; uint32_t m_path_table_pos; /* * Joliet related information */ JolietNode *joliet_root; size_t joliet_ndirs; uint32_t joliet_path_table_size; uint32_t joliet_l_path_table_pos; uint32_t joliet_m_path_table_pos; size_t joliet_ucs2_failures; /* * HFS+ related information * (by Vladimir Serbinenko, see libisofs/hfsplus.c) */ HFSPlusNode *hfsp_leafs; struct hfsplus_btree_level *hfsp_levels; uint32_t hfsp_nlevels; uint32_t hfsp_part_start; uint32_t hfsp_nfiles; uint32_t hfsp_ndirs; uint32_t hfsp_cat_id; uint32_t hfsp_allocation_blocks; uint32_t hfsp_allocation_file_start; uint32_t hfsp_extent_file_start; uint32_t hfsp_catalog_file_start; uint32_t hfsp_total_blocks; uint32_t hfsp_allocation_size; uint32_t hfsp_nleafs; uint32_t hfsp_curleaf; uint32_t hfsp_nnodes; uint32_t hfsp_bless_id[ISO_HFSPLUS_BLESS_MAX]; uint32_t hfsp_collision_count; /* * ISO 9660:1999 related information */ Iso1999Node *iso1999_root; size_t iso1999_ndirs; uint32_t iso1999_path_table_size; uint32_t iso1999_l_path_table_pos; uint32_t iso1999_m_path_table_pos; /* * El-Torito related information */ struct el_torito_boot_catalog *catalog; IsoFileSrc *cat; /**< location of the boot catalog in the new image */ int num_bootsrc; IsoFileSrc **bootsrc; /* location of the boot images in the new image */ /* * System Area related information */ /* Content of an embedded boot image. Valid if not NULL. * In that case it must point to a memory buffer at least 32 kB. */ char *system_area_data; /* * bit0= Only with DOS MBR * Make bytes 446 - 512 of the system area a partition * table which reserves partition 1 from byte 63*512 to the * end of the ISO image. Assumed are 63 secs/hed, 255 head/cyl. * (GRUB protective msdos label.) * This works with and without system_area_data. * bit1= Only with DOS MBR * Apply isohybrid MBR patching to the system area. * This works only with system_area_data plus ISOLINUX boot image * and only if not bit0 is set. * bit2-7= System area type * 0= DOS MBR * 1= MIPS Big Endian Volume Header * 2= DEC Boot Block for MIPS Little Endian * 3= SUN Disk Label for SUN SPARC * bit8-9= Only with DOS MBR * Cylinder alignment mode eventually pads the image to make it * end at a cylinder boundary. * 0 = auto (align if bit1) * 1 = always align to cylinder boundary * 2 = never align to cylinder boundary * 3 = always align, additionally pad up and align partitions * which were appended by iso_write_opts_set_partition_img() * bit10-13= System area sub type * With type 0 = MBR: * Gets overridden by bit0 and bit1. * 0 = no particular sub type * 1 = CHRP: A single MBR partition of type 0x96 covers the * ISO image. Not compatible with any other feature * which needs to have own MBR partition entries. */ int system_area_options; /* * Number of pad blocks that we need to write. Padding blocks are blocks * filled by 0s that we put between the directory structures and the file * data. These padding blocks are added by libisofs to improve the handling * of image growing. The idea is that the first blocks in the image are * overwritten with the volume descriptors of the new image. These first * blocks usually correspond to the volume descriptors and directory * structure of the old image, and can be safety overwritten. However, * with very small images they might correspond to valid data. To ensure * this never happens, what we do is to add padding bytes, to ensure no * file data is written in the first 64 KiB, that are the bytes we usually * overwrite. */ uint32_t mspad_blocks; size_t nwriters; IsoImageWriter **writers; /* tree of files sources */ IsoRBTree *files; struct iso_filesrc_list_item *ecma119_hidden_list; unsigned int checksum_idx_counter; void *checksum_ctx; off_t checksum_counter; uint32_t checksum_rlsb_tag_pos; uint32_t checksum_sb_tag_pos; uint32_t checksum_tree_tag_pos; uint32_t checksum_tag_pos; char image_md5[16]; char *checksum_buffer; uint32_t checksum_array_pos; uint32_t checksum_range_start; uint32_t checksum_range_size; char *opts_overwrite; /* Points to IsoWriteOpts->overwrite. Use only underneath ecma119_image_new() and if not NULL*/ /* Buffer for communication between burn_source and writer thread */ IsoRingBuffer *buffer; /* writer thread descriptor */ pthread_t wthread; int wthread_is_running; pthread_attr_t th_attr; /* Effective partition table parameter: 1 to 63, 0= disabled/default */ int partition_secs_per_head; /* 1 to 255, 0= disabled/default */ int partition_heads_per_cyl; /* The currently applicable LBA offset. To be subtracted from any LBA * that is mentioned in volume descriptors, trees, path tables, * Either 0 or .partition_offset */ uint32_t eff_partition_offset; /* The second ECMA-119 directory tree and path tables */ Ecma119Node *partition_root; uint32_t partition_l_table_pos; uint32_t partition_m_table_pos; /* The second Joliet directory tree and path tables */ JolietNode *j_part_root; uint32_t j_part_l_path_table_pos; uint32_t j_part_m_path_table_pos; /* Memorized ELF parameters from MIPS Little Endian boot file */ uint32_t mipsel_e_entry; uint32_t mipsel_p_offset; uint32_t mipsel_p_vaddr; uint32_t mipsel_p_filesz; /* A data file of which the position and size shall be written after a SUN Disk Label. */ IsoFileSrc *sparc_core_src; /* Counted in blocks of 2048 */ uint32_t appended_part_prepad[ISO_MAX_PARTITIONS]; uint32_t appended_part_start[ISO_MAX_PARTITIONS]; uint32_t appended_part_size[ISO_MAX_PARTITIONS]; int have_appended_partitions; /* See IsoImage and libisofs.h */ IsoNode *hfsplus_blessed[ISO_HFSPLUS_BLESS_MAX]; /* Block sizes come from write options. Only change a block size if it is 0. Set only to 512 or 2048. If it stays 0 then it will become 512 or 2048 in time. */ /* Allocation block size of HFS+ May be defined to 512 or 2048 before hfsplus_writer_create(). */ int hfsp_cat_node_size; /* 2 * hfsp_block_size */ int hfsp_iso_block_fac; /* 2048 / hfsp_block_size */ /* Apple Partition Map description. To be composed during IsoImageWriter method ->compute_data_blocks() by calling iso_register_apm_entry(). Make sure that the composing writers get registered before the gpt_tail_writer. */ struct iso_apm_partition_request *apm_req[ISO_APM_ENTRIES_MAX]; int apm_req_count; /* bit1= Do not fill gaps in Apple Partition Map bit2= apm_req entries use apm_block_size in start_block and block_count. Normally these two parameters are counted in 2 KiB blocks. */ int apm_req_flags; /* MBR partition table description. To be composed during IsoImageWriter method ->compute_data_blocks() by calling iso_register_mbr_entry(). */ struct iso_mbr_partition_request *mbr_req[ISO_MBR_ENTRIES_MAX]; int mbr_req_count; /* Number of bytes which have to be added after the cylinder aligned end of the overall ISO partition because clinder size is not a multiple of 2048 */ int post_iso_part_pad; uint32_t prep_part_size; /* GPT description. To be composed during IsoImageWriter method ->compute_data_blocks() by calling iso_register_gpt_entry(). Make sure that the composing writers get registered before the gpt_tail_writer. */ struct iso_gpt_partition_request *gpt_req[ISO_GPT_ENTRIES_MAX]; int gpt_req_count; /* bit0= GPT partitions may overlap */ int gpt_req_flags; /* Whether the eventual backup GPT is not part of the ISO filesystem */ int gpt_backup_outside; uint32_t efi_boot_part_size; IsoFileSrc *efi_boot_part_filesrc; /* Just a pointer. Do not free. */ /* Messages from gpt_tail_writer_compute_data_blocks() to iso_write_system_area(). */ uint8_t gpt_disk_guid[16]; int gpt_disk_guid_set; /* Start of GPT entries in System Area, block size 512 */ uint32_t gpt_part_start; /* The ISO block number after the backup GPT header , block size 2048 */ uint32_t gpt_backup_end; uint32_t gpt_backup_size; uint32_t gpt_max_entries; int gpt_is_computed; /* Message from write_head_part1()/iso_write_system_area() to the write_data() methods of the writers. */ uint8_t sys_area_as_written[16 * BLOCK_SIZE]; int sys_area_already_written; /* Size of the filesrc_writer area (data file content). This is available before any IsoImageWriter.compute_data_blocks() is called. */ uint32_t filesrc_start; uint32_t filesrc_blocks; }; #define BP(a,b) [(b) - (a) + 1] /* ECMA-119, 8.4 */ struct ecma119_pri_vol_desc { uint8_t vol_desc_type BP(1, 1); uint8_t std_identifier BP(2, 6); uint8_t vol_desc_version BP(7, 7); uint8_t unused1 BP(8, 8); uint8_t system_id BP(9, 40); uint8_t volume_id BP(41, 72); uint8_t unused2 BP(73, 80); uint8_t vol_space_size BP(81, 88); uint8_t unused3 BP(89, 120); uint8_t vol_set_size BP(121, 124); uint8_t vol_seq_number BP(125, 128); uint8_t block_size BP(129, 132); uint8_t path_table_size BP(133, 140); uint8_t l_path_table_pos BP(141, 144); uint8_t opt_l_path_table_pos BP(145, 148); uint8_t m_path_table_pos BP(149, 152); uint8_t opt_m_path_table_pos BP(153, 156); uint8_t root_dir_record BP(157, 190); uint8_t vol_set_id BP(191, 318); uint8_t publisher_id BP(319, 446); uint8_t data_prep_id BP(447, 574); uint8_t application_id BP(575, 702); uint8_t copyright_file_id BP(703, 739); uint8_t abstract_file_id BP(740, 776); uint8_t bibliographic_file_id BP(777, 813); uint8_t vol_creation_time BP(814, 830); uint8_t vol_modification_time BP(831, 847); uint8_t vol_expiration_time BP(848, 864); uint8_t vol_effective_time BP(865, 881); uint8_t file_structure_version BP(882, 882); uint8_t reserved1 BP(883, 883); uint8_t app_use BP(884, 1395); uint8_t reserved2 BP(1396, 2048); }; /* ECMA-119, 8.5 */ struct ecma119_sup_vol_desc { uint8_t vol_desc_type BP(1, 1); uint8_t std_identifier BP(2, 6); uint8_t vol_desc_version BP(7, 7); uint8_t vol_flags BP(8, 8); uint8_t system_id BP(9, 40); uint8_t volume_id BP(41, 72); uint8_t unused2 BP(73, 80); uint8_t vol_space_size BP(81, 88); uint8_t esc_sequences BP(89, 120); uint8_t vol_set_size BP(121, 124); uint8_t vol_seq_number BP(125, 128); uint8_t block_size BP(129, 132); uint8_t path_table_size BP(133, 140); uint8_t l_path_table_pos BP(141, 144); uint8_t opt_l_path_table_pos BP(145, 148); uint8_t m_path_table_pos BP(149, 152); uint8_t opt_m_path_table_pos BP(153, 156); uint8_t root_dir_record BP(157, 190); uint8_t vol_set_id BP(191, 318); uint8_t publisher_id BP(319, 446); uint8_t data_prep_id BP(447, 574); uint8_t application_id BP(575, 702); uint8_t copyright_file_id BP(703, 739); uint8_t abstract_file_id BP(740, 776); uint8_t bibliographic_file_id BP(777, 813); uint8_t vol_creation_time BP(814, 830); uint8_t vol_modification_time BP(831, 847); uint8_t vol_expiration_time BP(848, 864); uint8_t vol_effective_time BP(865, 881); uint8_t file_structure_version BP(882, 882); uint8_t reserved1 BP(883, 883); uint8_t app_use BP(884, 1395); uint8_t reserved2 BP(1396, 2048); }; /* ECMA-119, 8.2 */ struct ecma119_boot_rec_vol_desc { uint8_t vol_desc_type BP(1, 1); uint8_t std_identifier BP(2, 6); uint8_t vol_desc_version BP(7, 7); uint8_t boot_sys_id BP(8, 39); uint8_t boot_id BP(40, 71); uint8_t boot_catalog BP(72, 75); uint8_t unused BP(76, 2048); }; /* ECMA-119, 9.1 */ struct ecma119_dir_record { uint8_t len_dr BP(1, 1); uint8_t len_xa BP(2, 2); uint8_t block BP(3, 10); uint8_t length BP(11, 18); uint8_t recording_time BP(19, 25); uint8_t flags BP(26, 26); uint8_t file_unit_size BP(27, 27); uint8_t interleave_gap_size BP(28, 28); uint8_t vol_seq_number BP(29, 32); uint8_t len_fi BP(33, 33); uint8_t file_id BP(34, 34); /* 34 to 33+len_fi */ /* padding field (if len_fi is even) */ /* system use (len_dr - len_su + 1 to len_dr) */ }; /* ECMA-119, 9.4 */ struct ecma119_path_table_record { uint8_t len_di BP(1, 1); uint8_t len_xa BP(2, 2); uint8_t block BP(3, 6); uint8_t parent BP(7, 8); uint8_t dir_id BP(9, 9); /* 9 to 8+len_di */ /* padding field (if len_di is odd) */ }; /* ECMA-119, 8.3 */ struct ecma119_vol_desc_terminator { uint8_t vol_desc_type BP(1, 1); uint8_t std_identifier BP(2, 6); uint8_t vol_desc_version BP(7, 7); uint8_t reserved BP(8, 2048); }; void ecma119_set_voldescr_times(IsoImageWriter *writer, struct ecma119_pri_vol_desc *vol); /* Copies a data file into the ISO image output stream */ int iso_write_partition_file(Ecma119Image *target, char *path, uint32_t prepad, uint32_t blocks, int flag); void issue_ucs2_warning_summary(size_t failures); #endif /*LIBISO_ECMA119_H_*/ libisofs-1.4.2/libisofs/filesrc.h0000644000175700017510000001061412534372033013677 00000000000000/* * Copyright (c) 2007 Vreixo Formoso * 2012 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ #ifndef LIBISO_FILESRC_H_ #define LIBISO_FILESRC_H_ #include "libisofs.h" #include "stream.h" #include "ecma119.h" #ifdef HAVE_STDINT_H #include #else #ifdef HAVE_INTTYPES_H #include #endif #endif /* Abstraction of data file content in the emerging image. */ struct Iso_File_Src { /* This marks an IsoFileSrc which shall only expose its extent addresses and sizes but shall not be counted or written by filesrc_writer. */ unsigned int no_write :1; /* Is 1 if the object was already put into the filelist array. */ unsigned int taken :1; unsigned int checksum_index :31; /** File Sections of the file in the image */ /* Special sections[0].block values while they are relative before filesrc_writer_compute_data_blocks(). Valid only with .no_write == 0: 0xfffffffe This Iso_File_Src is claimed as external partition. Others will take care of the content data. filesrc_writer shall neither count nor write it. At write_data time it is already converted to a fileadress between Ecma119Image.ms_block and Ecma119Image.filesrc_start - 1. 0xffffffff This is the block to which empty files shall point. Normal data files have relative addresses from 0 to 0xffffffdf. They cannot be higher, because mspad_writer forces the absolute filesrc addresses to start at least at 0x20. */ struct iso_file_section *sections; int nsections; int sort_weight; IsoStream *stream; }; int iso_file_src_cmp(const void *n1, const void *n2); /** * Create a new IsoFileSrc to get data from a specific IsoFile. * * The IsoFileSrc will be cached in a tree to prevent the same file for * being written several times to image. If you call again this function * with a node that refers to the same source file, the previously * created one will be returned. No new IsoFileSrc is created in that case. * * @param img * The image where this file is to be written * @param file * The IsoNode we want to write * @param src * Will be filled with a pointer to the IsoFileSrc * @return * 1 if new object was created, 0 if object existed, < 0 on error */ int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src); /** * Add a given IsoFileSrc to the given image target. * * The IsoFileSrc will be cached in a tree to prevent the same file for * being written several times to image. If you call again this function * with a node that refers to the same source file, the previously * created one will be returned. * * @param img * The image where this file is to be written * @param new * The IsoFileSrc to add * @param src * Will be filled with a pointer to the IsoFileSrc really present in * the tree. It could be different than new if the same file already * exists in the tree. * @return * 1 on success, 0 if file already exists on tree, < 0 error */ int iso_file_src_add(Ecma119Image *img, IsoFileSrc *new, IsoFileSrc **src); /** * Free the IsoFileSrc especific data */ void iso_file_src_free(void *node); /** * Get the size of the file this IsoFileSrc represents */ off_t iso_file_src_get_size(IsoFileSrc *file); /** * Create a Writer for file contents. * * It takes care of written the files in the correct order. */ int iso_file_src_writer_create(Ecma119Image *target); /** * Determine number of filesrc blocks in the image and compute extent addresses * relative to start of the file source writer area. * filesrc_writer_compute_data_blocks() later makes them absolute. */ int filesrc_writer_pre_compute(IsoImageWriter *writer); /** * Write the content of file into the output stream of t. * name must be NULL or offer at least PATH_MAX characters of storage. * buffer must be NULL or offer at least BLOCK_SIZE characters of storage. * flag is not used yet, submit 0. */ int iso_filesrc_write_data(Ecma119Image *t, IsoFileSrc *file, char *name, char *buffer, int flag); #endif /*LIBISO_FILESRC_H_*/ libisofs-1.4.2/libisofs/make_isohybrid_mbr.c0000644000175700017510000005512212523373360016101 00000000000000/* * Copyright (c) 2008 - 2015 Thomas Schmitt * with special credits to H. Peter Anvin for isohybrid * and to Matthew Garrett for isohybrid with GPT and APM * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif #include #ifdef HAVE_STDINT_H #include #else #ifdef HAVE_INTTYPES_H #include #endif #endif #include #include #include #include #include #include /* for gettimeofday() */ #include #include "filesrc.h" #include "ecma119.h" #include "eltorito.h" #include "system_area.h" /* This code stems from syslinux-3.72/utils/isohybrid, a perl script under GPL which is Copyright 2002-2008 H. Peter Anvin. Line numbers in comments refer to the lines of that script. It has been analyzed and re-written in C language 2008 by Thomas Schmitt, and is now under the licenses to which H.Peter Anvin agreed: http://syslinux.zytor.com/archives/2008-November/011105.html Date: Mon, 10 Nov 2008 08:36:46 -0800 From: H. Peter Anvin I hereby give permission for this code, translated to the C language, to be released under either the LGPL or the MIT/ISC/2-clause BSD licenses or both, at your option. Sincerely, H. Peter Anvin In the context of GNU xorriso, this code is under GPLv3+ derived from LGPL. In the context of libisofs this code derives its matching free software license from above stem licenses, typically from LGPL. In case its generosity is needed, here is the 2-clause BSD license: make_isohybrid_mbr.c is copyright 2002-2008 H. Peter Anvin and 2008-2014 Thomas Schmitt 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED `AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROVIDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* A helper function. One could replace it by one or two macros. */ static int lsb_to_buf(char **wpt, uint32_t value, int bits, int flag) { int b; for (b = 0; b < bits; b += 8) *((unsigned char *) ((*wpt)++)) = (value >> b) & 0xff; return (1); } /* ====================================================================== */ /* Deprecated Function */ /* ====================================================================== */ /* * Create a MBR for an isohybrid enabled ISOLINUX boot image. * * It is assumed that the caller has verified the readiness of the boot image * by checking for 0xfb 0xc0 0x78 0x70 at bytes 0x40 to 0x43 of isolinux.bin. * * @param bin_lba The predicted LBA of isolinux.bin within the emerging ISO. * @param img_blocks The predicted number of 2048 byte blocks in the ISO. * It will get rounded up to full MBs and that many blocks * must really be written as ISO 9660 image. * @param mbr A buffer of at least 512 bytes to take the result which is * to be written as the very beginning of the ISO. * @param flag unused yet, submit 0 * @return <0 = fatal, 0 = failed , 1 = ok , 2 = ok with size warning */ int make_isohybrid_mbr(int bin_lba, int *img_blocks, char *mbr, int flag) { /* According to H. Peter Anvin this binary code stems from syslinux-3.72/mbr/isohdpfx.S */ static int mbr_code_size = 271; static unsigned char mbr_code[271] = { 0xfa, 0x31, 0xc0, 0x8e, 0xd8, 0x8e, 0xd0, 0xbc, 0x00, 0x7c, 0x89, 0xe6, 0x06, 0x57, 0x52, 0x8e, 0xc0, 0xfb, 0xfc, 0xbf, 0x00, 0x06, 0xb9, 0x00, 0x01, 0xf3, 0xa5, 0xea, 0x20, 0x06, 0x00, 0x00, 0x52, 0xb4, 0x41, 0xbb, 0xaa, 0x55, 0x31, 0xc9, 0x30, 0xf6, 0xf9, 0xcd, 0x13, 0x72, 0x14, 0x81, 0xfb, 0x55, 0xaa, 0x75, 0x0e, 0x83, 0xe1, 0x01, 0x74, 0x09, 0x66, 0xc7, 0x06, 0xb4, 0x06, 0xb4, 0x42, 0xeb, 0x15, 0x5a, 0x51, 0xb4, 0x08, 0xcd, 0x13, 0x83, 0xe1, 0x3f, 0x51, 0x0f, 0xb6, 0xc6, 0x40, 0x50, 0xf7, 0xe1, 0x52, 0x50, 0xbb, 0x00, 0x7c, 0xb9, 0x04, 0x00, 0x66, 0xa1, 0xb0, 0x07, 0xe8, 0x40, 0x00, 0x72, 0x74, 0x66, 0x40, 0x80, 0xc7, 0x02, 0xe2, 0xf4, 0x66, 0x81, 0x3e, 0x40, 0x7c, 0xfb, 0xc0, 0x78, 0x70, 0x75, 0x07, 0xfa, 0xbc, 0xf4, 0x7b, 0xe9, 0xc6, 0x75, 0xe8, 0x79, 0x00, 0x69, 0x73, 0x6f, 0x6c, 0x69, 0x6e, 0x75, 0x78, 0x2e, 0x62, 0x69, 0x6e, 0x20, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x72, 0x20, 0x63, 0x6f, 0x72, 0x72, 0x75, 0x70, 0x74, 0x2e, 0x0d, 0x0a, 0x66, 0x60, 0x66, 0x31, 0xd2, 0x66, 0x52, 0x66, 0x50, 0x06, 0x53, 0x6a, 0x01, 0x6a, 0x10, 0x89, 0xe6, 0x66, 0xf7, 0x36, 0xf0, 0x7b, 0xc0, 0xe4, 0x06, 0x88, 0xe1, 0x88, 0xc5, 0x92, 0xf6, 0x36, 0xf6, 0x7b, 0x88, 0xc6, 0x08, 0xe1, 0x41, 0xb8, 0x01, 0x02, 0x8a, 0x16, 0xfa, 0x7b, 0xcd, 0x13, 0x8d, 0x64, 0x10, 0x66, 0x61, 0xc3, 0xe8, 0x1e, 0x00, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x20, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2e, 0x0d, 0x0a, 0x5e, 0xac, 0xb4, 0x0e, 0x8a, 0x3e, 0x62, 0x04, 0xb3, 0x07, 0xcd, 0x10, 0x3c, 0x0a, 0x75, 0xf1, 0xcd, 0x18, 0xf4, 0xeb, 0xfd }; static int h = 64, s = 32; int i, id; char *wpt; off_t imgsize, cylsize, frac, padding, c, cc; /* For generating a weak random number */ struct timeval tv; struct timezone tz; if (bin_lba < 0 || bin_lba >= (1 << 29)) return (0); /* 1 TB limit of signed 32 bit addressing of 512 byte blocks */ /* 84: Gets size of image in bytes. 89: */ imgsize = ((off_t) *img_blocks) * (off_t) 2048; /* 90: Computes $padding, size of padded image and number $c of pseudo-cylinders ($h and $s are constants set in line 24). 102: $cc is $c curbed to 1024. */ cylsize = h * s * 512; frac = imgsize % cylsize; padding = (frac > 0 ? cylsize - frac : 0); imgsize += padding; *img_blocks = imgsize / (off_t) 2048; c = imgsize / cylsize; if (c > 1024) { cc = 1024; } else cc = c; /* 107: Brings the hex-encoded bytes from the file __END__ into 113: the MBR buffer. (This function holds them in mbr_code[].) */ for (i = 0; i < mbr_code_size; i++) mbr[i] = mbr_code[i]; /* 118: Pads up to 432 */ for (i = mbr_code_size; i < 432; i++) mbr[i] = 0; /* From here on use write cursor wpt */ wpt = mbr + 432; /* 120: Converts LBA of isolinux.bin to blocksize 512 and writes to buffer. Appends 4 zero bytes. */ lsb_to_buf(&wpt, bin_lba * 4, 32, 0); lsb_to_buf(&wpt, 0, 32, 0); /* 121: I do not understand where $id should eventually come from. An environment variable ? 125: Whatever, i use some 32-bit random value with no crypto strength. */ gettimeofday(&tv, &tz); id = 0xffffffff & (tv.tv_sec ^ (tv.tv_usec * 2000)); /* 126: Adds 4 id bytes and 2 zero bytes. */ lsb_to_buf(&wpt, id, 32, 0); lsb_to_buf(&wpt, 0, 16, 0); /* 129: Composes 16 byte record from the parameters determined 147: so far. Appends it to buffer and add 48 zero bytes. */ /* There are 4 "partition slots". Only the first is non-zero here. In the perl script, the fields are set in variables and then written to buffer. I omit the variables. */ /* 0x80 */ lsb_to_buf(&wpt, 0x80, 8, 0); /* bhead */ lsb_to_buf(&wpt, 0, 8, 0); /* bsect */ lsb_to_buf(&wpt, 1, 8, 0); /* bcyl */ lsb_to_buf(&wpt, 0, 8, 0); /* fstype */ lsb_to_buf(&wpt, 0x83, 8, 0); /* ehead */ lsb_to_buf(&wpt, h - 1, 8, 0); /* esect */ lsb_to_buf(&wpt, s + (((cc - 1) & 0x300) >> 2), 8, 0); /* ecyl */ lsb_to_buf(&wpt, (cc - 1) & 0xff, 8, 0); /* 0 */ lsb_to_buf(&wpt, 0, 32, 0); /* psize */ lsb_to_buf(&wpt, c * h * s, 32, 0); /* Fill the other three slots with zeros */ for (i = 0; i < 3 * 4; i++) lsb_to_buf(&wpt, 0, 32, 0); /* 148: Appends bytes 0x55 , 0xAA. */ lsb_to_buf(&wpt, 0x55, 8, 0); lsb_to_buf(&wpt, 0xaa, 8, 0); return (1); } /* ====================================================================== */ /* The New MBR Producer */ /* ====================================================================== */ /* The new MBR producer for isohybrid is a slightly generalized version of the deprecated function make_isohybrid_mbr(). It complies to the urge of H.Peter Anvin not to hardcode MBR templates but rather to read a file from the Syslinux tree, and to patch it as was done with the old MBR producer. The old algorithm was clarified publicly by the following mail. Changes towards the old algorithm: - 512-byte LBA of boot image is extended to 64 bit (we stay with 32) - check for a magic number is now gone The new implementation tries to use similar terms as the mail in order to facilitate its future discussion with Syslinux developers. From hpa@zytor.com Thu Apr 1 08:32:52 2010 Date: Wed, 31 Mar 2010 14:53:51 -0700 From: H. Peter Anvin To: For discussion of Syslinux and tftp-hpa Cc: Thomas Schmitt Subject: Re: [syslinux] port syslinux isohybrid perl script to C [...] [me:] > Currently i lack of blob and prescriptions. The blobs are available in the Syslinux build tree under the names: mbr/isohdp[fp]x*.bin The default probably should be mbr/isohdppx.bin, but it's ultimately up to the user. User definable parameters: -> MBR ID (default random 32-bit number, or preserved from previous instance) -> Sector count (default 32, range 1-63) -> Head count (default 64, range 1-256) -> Partition offset (default 0, range 0-64) -> Partition number (default 1, range 1-4) -> Filesystem type (default 0x17, range 1-255) Note: the filesystem type is largely arbitrary, in theory it can be any value other than 0x00, 0x05, 0x0f, 0x85, 0xee, or 0xef. 0x17 ("Windows IFS Hidden") seems safeish, some people believe 0x83 (Linux) is better. Here is the prescriptions for how to install it: All numbers are littleendian. "word" means 16 bits, "dword" means 32 bits, "qword" means 64 bits. Common subroutine LBA_to_CHS(): s = (lba % sector_count) + 1 t = (lba / sector_count) h = (t % head_count) c = (t / head_count) if (c >= 1024): c = 1023 h = head_count s = sector_count s = s | ((c & 0x300) >> 2) c = c & 0xff write byte h write byte s write byte c Main: Pad image_size to a multiple of sector_count*head_count Use the input file unmodified for bytes 0..431 write qword boot_lba # Offset 432 write dword mbr_id # Offset 440 write word 0 # Offset 444 # Offset 446 For each partition entry 1..4: if this_partition != partition_number: write 16 zero bytes else: write byte 0x80 write LBA_to_CHS(partition_offset) write byte filesystem_type write LBA_to_CHS(image_size-1) write dword partition_offset write dword image_size # Offset 510 write word 0xaa55 Use the input file unmodified for bytes 512..32767 (pad with zero as necessary) [...] -hpa */ /* The new stuff about GPT and APM which was learned from Matthew Garret and isohybrid.c is described in doc/boot_sectord.txt chapter "SYSLINUX isohybrid for MBR, UEFI and x86-Mac" */ static int lba512chs_to_buf(char **wpt, off_t lba, int head_count, int sector_count) { int s, t, h, c; s = (lba % sector_count) + 1; t = (lba / sector_count); h = (t % head_count); c = (t / head_count); if (c >= 1024) { c = 1023; h = head_count; /* >>> not -1 ? Limits head_count to 255 */ s = sector_count; } s = s | ((c & 0x300) >> 2); c = c & 0xff; (*((unsigned char **) wpt))[0] = h; (*((unsigned char **) wpt))[1] = s; (*((unsigned char **) wpt))[2] = c; (*wpt)+= 3; return(1); } /* Find out whether GPT and APM are desired flag bit0 = register APM and GPT requests in Ecma119Image */ int assess_isohybrid_gpt_apm(Ecma119Image *t, int *gpt_count, int gpt_idx[128], int *apm_count, int flag) { int i, ilx_opts, j, ret, num_img; uint32_t block_count; uint8_t gpt_name[72]; static uint8_t zero_uuid[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static uint8_t basic_data_uuid[16] = { 0xa2, 0xa0, 0xd0, 0xeb, 0xe5, 0xb9, 0x33, 0x44, 0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7 }; static uint8_t hfs_uuid[16] = { 0x00, 0x53, 0x46, 0x48, 0x00, 0x00, 0xaa, 0x11, 0xaa, 0x11, 0x00, 0x30, 0x65, 0x43, 0xec, 0xac }; uint8_t *uuid; static uint64_t gpt_flags = (((uint64_t) 1) << 60) | 1; *gpt_count = 0; *apm_count = 0; if (t->catalog != NULL) num_img = t->catalog->num_bootimages; else num_img = 0; for (i = 0; i < num_img; i++) { ilx_opts = t->catalog->bootimages[i]->isolinux_options; if (((ilx_opts >> 2) & 63) == 1 || ((ilx_opts >> 2) & 63) == 2) { if (*gpt_count < 128) gpt_idx[*gpt_count]= i; (*gpt_count)++; if ((flag & 1) && t->bootsrc[i] != NULL) { /* Register GPT entry */ memset(gpt_name, 0, 72); sprintf((char *) gpt_name, "ISOHybrid%d", *gpt_count); iso_ascii_utf_16le(gpt_name); if (((ilx_opts >> 2) & 63) == 2) uuid = hfs_uuid; else uuid = basic_data_uuid; block_count = 0; for (j = 0; j < t->bootsrc[i]->nsections; j++) block_count += t->bootsrc[i]->sections[j].size / 2048; ret = iso_quick_gpt_entry( t->gpt_req, &(t->gpt_req_count), ((uint64_t) t->bootsrc[i]->sections[0].block) * 4, ((uint64_t) block_count) * 4, uuid, zero_uuid, gpt_flags, (uint8_t *) gpt_name); if (ret < 0) return ret; } } if (ilx_opts & 256) { (*apm_count)++; if ((flag & 1) && t->bootsrc[i] != NULL) { /* Register APM entry */ block_count = 0; for (j = 0; j < t->bootsrc[i]->nsections; j++) block_count += t->bootsrc[i]->sections[j].size / 2048; ret = iso_quick_apm_entry(t->apm_req, &(t->apm_req_count), t->bootsrc[i]->sections[0].block, block_count, "EFI", "Apple_HFS"); if (ret < 0) return ret; /* Prevent gap filling */ t->apm_req_flags |= 2; t->opts->apm_block_size = 2048; } } } if ((flag & 1) && *gpt_count > 0) { /* Register overall GPT partition */ memset(gpt_name, 0, 72); sprintf((char *) gpt_name, "ISOHybrid"); iso_ascii_utf_16le(gpt_name); /* Let it be open ended. iso_write_gpt() will truncate it as needed. */ block_count = 0xffffffff; ret = iso_quick_gpt_entry(t->gpt_req, &(t->gpt_req_count), (uint64_t) t->opts->partition_offset * 4, ((uint64_t) block_count) * 4, basic_data_uuid, zero_uuid, gpt_flags, (uint8_t *) gpt_name); if (ret < 0) return ret; /* Remove ban on GPT overlapping */ t->gpt_req_flags |= 1; } return ISO_SUCCESS; } /* Insert APM head into MBR */ static int insert_apm_head(uint8_t *buf, int apm_count) { int i; static uint8_t apm_mbr_start[32] = { 0x33, 0xed, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 }; static uint8_t apm_head[32] = { 0x45, 0x52, 0x08, 0x00, 0x00, 0x00, 0x90, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; if (apm_count) { for (i = 0; i < 32; i++) if(buf[i] != apm_mbr_start[i]) break; if (i < 32) { /* Maybe it is already patched by apm_head ? */ for (i = 0; i < 32; i++) if(buf[i] != apm_head[i]) break; } if (i < 32) { iso_msgs_submit(0, "MBR template file seems not prepared for Apple Partition Map.", 0, "FAILURE", 0); return ISO_ISOLINUX_CANT_PATCH; } for (i = 0; i < 32; i++) buf[i] = apm_head[i]; } return ISO_SUCCESS; } /* Describe GPT boot images as MBR partitions */ static int gpt_images_as_mbr_partitions(Ecma119Image *t, char *wpt, int gpt_idx[128], int *gpt_cursor) { int ilx_opts; off_t hd_blocks; static uint8_t dummy_chs[3] = { 0xfe, 0xff, 0xff, }; wpt[0] = 0; memcpy(wpt + 1, dummy_chs, 3); ilx_opts = t->catalog->bootimages[gpt_idx[*gpt_cursor]]->isolinux_options; if (((ilx_opts >> 2) & 63) == 2) wpt[4] = 0x00; /* HFS gets marked as "Empty" */ else ((unsigned char *) wpt)[4] = 0xef; /* "EFI (FAT-12/16/" */ memcpy(wpt + 5, dummy_chs, 3); /* Start LBA (in 512 blocks) */ wpt += 8; lsb_to_buf(&wpt, t->bootsrc[gpt_idx[*gpt_cursor]]->sections[0].block * 4, 32, 0); /* Number of blocks */ hd_blocks = t->bootsrc[gpt_idx[*gpt_cursor]]->sections[0].size; hd_blocks = hd_blocks / 512 + !!(hd_blocks % 512); lsb_to_buf(&wpt, (int) hd_blocks, 32, 0); (*gpt_cursor)++; return ISO_SUCCESS; } /* * @param flag bit0= make own random MBR Id from current time * bit1= create protective MBR as of UEFI/GPT specs */ int make_isolinux_mbr(uint32_t *img_blocks, Ecma119Image *t, int part_offset, int part_number, int fs_type, uint8_t *buf, int flag) { uint32_t id, part, nominal_part_size; off_t hd_img_blocks, hd_boot_lba; char *wpt; uint32_t boot_lba; int head_count, sector_count, ret; int gpt_count = 0, gpt_idx[128], apm_count = 0, gpt_cursor; /* For generating a weak random number */ struct timeval tv; struct timezone tz; if (flag & 2) { part_number = 1; part_offset = 1; } hd_img_blocks = ((off_t) *img_blocks) * (off_t) 4 - t->post_iso_part_pad / 512; boot_lba = t->bootsrc[0]->sections[0].block; head_count = t->partition_heads_per_cyl; sector_count = t->partition_secs_per_head; ret = assess_isohybrid_gpt_apm(t, &gpt_count, gpt_idx, &apm_count, 0); if (ret < 0) return ret; /* The rest of APM has already been written by iso_write_apm(). But the isohybrid APM head differs from the hfsplus_writer APM head. */ ret = insert_apm_head(buf, apm_count); if (ret < 0) return ret; /* Padding of image_size to a multiple of sector_count*head_count happens already at compute time and is implemented by an appropriate increase of Ecma119Image->tail_blocks. */ wpt = (char *) buf + 432; /* write qword boot_lba # Offset 432 */ hd_boot_lba = ((off_t) boot_lba) * (off_t) 4; lsb_to_buf(&wpt, hd_boot_lba & 0xffffffff, 32, 0); lsb_to_buf(&wpt, hd_boot_lba >> 32, 32, 0); /* write dword mbr_id # Offset 440 (here some 32-bit random value with no crypto strength) */ if (flag & 1) { gettimeofday(&tv, &tz); id = 0xffffffff & (tv.tv_sec ^ (tv.tv_usec * 2000)); lsb_to_buf(&wpt, id, 32, 0); } else { wpt+= 4; } /* write word 0 # Offset 444 */ lsb_to_buf(&wpt, 0, 16, 0); /* # Offset 446 */ gpt_cursor= 0; for (part = 1 ; part <= 4; part++) { if ((int) part != part_number) { /* if this_partition != partition_number: write 16 zero bytes (this is now overriden by the eventual desire to announce EFI and HFS boot images.) */ memset(wpt, 0, 16); if (gpt_cursor < gpt_count) { ret = gpt_images_as_mbr_partitions(t, wpt, gpt_idx, &gpt_cursor); if (ret < 0) return ret; } wpt+= 16; continue; } /* write byte 0x80 if bootable write LBA_to_CHS(partition_offset) write byte filesystem_type write LBA_to_CHS(image_size-1) write dword partition_offset write dword image_size */ if (flag & 2) lsb_to_buf(&wpt, 0x00, 8, 0); else lsb_to_buf(&wpt, 0x80, 8, 0); lba512chs_to_buf(&wpt, part_offset, head_count, sector_count); lsb_to_buf(&wpt, fs_type, 8, 0); lba512chs_to_buf(&wpt, hd_img_blocks - 1, head_count, sector_count); lsb_to_buf(&wpt, part_offset, 32, 0); if (hd_img_blocks - (off_t) part_offset > (off_t) 0xffffffff) nominal_part_size = 0xffffffff; else nominal_part_size = hd_img_blocks - (off_t) part_offset; lsb_to_buf(&wpt, nominal_part_size, 32, 0); } /* write word 0xaa55 # Offset 510 */ lsb_to_buf(&wpt, 0xaa55, 16, 0); return(1); } libisofs-1.4.2/libisofs/hfsplus_case.c0000644000175700017510000003036512321161425014722 00000000000000/* * Copyright (c) 2012 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ /** * Maps UTF-16BE double-byte characters to the representative of their * equivalence class under the relation of HFS+ case-insensitivity. */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif #include "libisofs.h" /* The translation list utf16be_transl was generated by a program which compared input and output of existing example code by Apple Inc. found published on http://developer.apple.com/legacy/mac/library/#technotes/tn/tn1150.html Each deviation was recorded as pair of byte pairs. The first pair gives the input, the second pair gives the output. If a byte pair is not mentioned in this list as input, then it gets mapped to itself. Pairs which get mapped to pair 0,0 shall be ignored with HFS+ comparisons. Another comparison run verified that both implementations yield the same character translation with all 65536 possible input bit patterns. */ static uint8_t utf16be_transl[] = { 0x00, 0x00, 0xff, 0xff, 0x00, 0x41, 0x00, 0x61, 0x00, 0x42, 0x00, 0x62, 0x00, 0x43, 0x00, 0x63, 0x00, 0x44, 0x00, 0x64, 0x00, 0x45, 0x00, 0x65, 0x00, 0x46, 0x00, 0x66, 0x00, 0x47, 0x00, 0x67, 0x00, 0x48, 0x00, 0x68, 0x00, 0x49, 0x00, 0x69, 0x00, 0x4a, 0x00, 0x6a, 0x00, 0x4b, 0x00, 0x6b, 0x00, 0x4c, 0x00, 0x6c, 0x00, 0x4d, 0x00, 0x6d, 0x00, 0x4e, 0x00, 0x6e, 0x00, 0x4f, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x70, 0x00, 0x51, 0x00, 0x71, 0x00, 0x52, 0x00, 0x72, 0x00, 0x53, 0x00, 0x73, 0x00, 0x54, 0x00, 0x74, 0x00, 0x55, 0x00, 0x75, 0x00, 0x56, 0x00, 0x76, 0x00, 0x57, 0x00, 0x77, 0x00, 0x58, 0x00, 0x78, 0x00, 0x59, 0x00, 0x79, 0x00, 0x5a, 0x00, 0x7a, 0x00, 0xc6, 0x00, 0xe6, 0x00, 0xd0, 0x00, 0xf0, 0x00, 0xd8, 0x00, 0xf8, 0x00, 0xde, 0x00, 0xfe, 0x01, 0x10, 0x01, 0x11, 0x01, 0x26, 0x01, 0x27, 0x01, 0x32, 0x01, 0x33, 0x01, 0x3f, 0x01, 0x40, 0x01, 0x41, 0x01, 0x42, 0x01, 0x4a, 0x01, 0x4b, 0x01, 0x52, 0x01, 0x53, 0x01, 0x66, 0x01, 0x67, 0x01, 0x81, 0x02, 0x53, 0x01, 0x82, 0x01, 0x83, 0x01, 0x84, 0x01, 0x85, 0x01, 0x86, 0x02, 0x54, 0x01, 0x87, 0x01, 0x88, 0x01, 0x89, 0x02, 0x56, 0x01, 0x8a, 0x02, 0x57, 0x01, 0x8b, 0x01, 0x8c, 0x01, 0x8e, 0x01, 0xdd, 0x01, 0x8f, 0x02, 0x59, 0x01, 0x90, 0x02, 0x5b, 0x01, 0x91, 0x01, 0x92, 0x01, 0x93, 0x02, 0x60, 0x01, 0x94, 0x02, 0x63, 0x01, 0x96, 0x02, 0x69, 0x01, 0x97, 0x02, 0x68, 0x01, 0x98, 0x01, 0x99, 0x01, 0x9c, 0x02, 0x6f, 0x01, 0x9d, 0x02, 0x72, 0x01, 0x9f, 0x02, 0x75, 0x01, 0xa2, 0x01, 0xa3, 0x01, 0xa4, 0x01, 0xa5, 0x01, 0xa7, 0x01, 0xa8, 0x01, 0xa9, 0x02, 0x83, 0x01, 0xac, 0x01, 0xad, 0x01, 0xae, 0x02, 0x88, 0x01, 0xb1, 0x02, 0x8a, 0x01, 0xb2, 0x02, 0x8b, 0x01, 0xb3, 0x01, 0xb4, 0x01, 0xb5, 0x01, 0xb6, 0x01, 0xb7, 0x02, 0x92, 0x01, 0xb8, 0x01, 0xb9, 0x01, 0xbc, 0x01, 0xbd, 0x01, 0xc4, 0x01, 0xc6, 0x01, 0xc5, 0x01, 0xc6, 0x01, 0xc7, 0x01, 0xc9, 0x01, 0xc8, 0x01, 0xc9, 0x01, 0xca, 0x01, 0xcc, 0x01, 0xcb, 0x01, 0xcc, 0x01, 0xe4, 0x01, 0xe5, 0x01, 0xf1, 0x01, 0xf3, 0x01, 0xf2, 0x01, 0xf3, 0x03, 0x91, 0x03, 0xb1, 0x03, 0x92, 0x03, 0xb2, 0x03, 0x93, 0x03, 0xb3, 0x03, 0x94, 0x03, 0xb4, 0x03, 0x95, 0x03, 0xb5, 0x03, 0x96, 0x03, 0xb6, 0x03, 0x97, 0x03, 0xb7, 0x03, 0x98, 0x03, 0xb8, 0x03, 0x99, 0x03, 0xb9, 0x03, 0x9a, 0x03, 0xba, 0x03, 0x9b, 0x03, 0xbb, 0x03, 0x9c, 0x03, 0xbc, 0x03, 0x9d, 0x03, 0xbd, 0x03, 0x9e, 0x03, 0xbe, 0x03, 0x9f, 0x03, 0xbf, 0x03, 0xa0, 0x03, 0xc0, 0x03, 0xa1, 0x03, 0xc1, 0x03, 0xa3, 0x03, 0xc3, 0x03, 0xa4, 0x03, 0xc4, 0x03, 0xa5, 0x03, 0xc5, 0x03, 0xa6, 0x03, 0xc6, 0x03, 0xa7, 0x03, 0xc7, 0x03, 0xa8, 0x03, 0xc8, 0x03, 0xa9, 0x03, 0xc9, 0x03, 0xe2, 0x03, 0xe3, 0x03, 0xe4, 0x03, 0xe5, 0x03, 0xe6, 0x03, 0xe7, 0x03, 0xe8, 0x03, 0xe9, 0x03, 0xea, 0x03, 0xeb, 0x03, 0xec, 0x03, 0xed, 0x03, 0xee, 0x03, 0xef, 0x04, 0x02, 0x04, 0x52, 0x04, 0x04, 0x04, 0x54, 0x04, 0x05, 0x04, 0x55, 0x04, 0x06, 0x04, 0x56, 0x04, 0x08, 0x04, 0x58, 0x04, 0x09, 0x04, 0x59, 0x04, 0x0a, 0x04, 0x5a, 0x04, 0x0b, 0x04, 0x5b, 0x04, 0x0f, 0x04, 0x5f, 0x04, 0x10, 0x04, 0x30, 0x04, 0x11, 0x04, 0x31, 0x04, 0x12, 0x04, 0x32, 0x04, 0x13, 0x04, 0x33, 0x04, 0x14, 0x04, 0x34, 0x04, 0x15, 0x04, 0x35, 0x04, 0x16, 0x04, 0x36, 0x04, 0x17, 0x04, 0x37, 0x04, 0x18, 0x04, 0x38, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1b, 0x04, 0x3b, 0x04, 0x1c, 0x04, 0x3c, 0x04, 0x1d, 0x04, 0x3d, 0x04, 0x1e, 0x04, 0x3e, 0x04, 0x1f, 0x04, 0x3f, 0x04, 0x20, 0x04, 0x40, 0x04, 0x21, 0x04, 0x41, 0x04, 0x22, 0x04, 0x42, 0x04, 0x23, 0x04, 0x43, 0x04, 0x24, 0x04, 0x44, 0x04, 0x25, 0x04, 0x45, 0x04, 0x26, 0x04, 0x46, 0x04, 0x27, 0x04, 0x47, 0x04, 0x28, 0x04, 0x48, 0x04, 0x29, 0x04, 0x49, 0x04, 0x2a, 0x04, 0x4a, 0x04, 0x2b, 0x04, 0x4b, 0x04, 0x2c, 0x04, 0x4c, 0x04, 0x2d, 0x04, 0x4d, 0x04, 0x2e, 0x04, 0x4e, 0x04, 0x2f, 0x04, 0x4f, 0x04, 0x60, 0x04, 0x61, 0x04, 0x62, 0x04, 0x63, 0x04, 0x64, 0x04, 0x65, 0x04, 0x66, 0x04, 0x67, 0x04, 0x68, 0x04, 0x69, 0x04, 0x6a, 0x04, 0x6b, 0x04, 0x6c, 0x04, 0x6d, 0x04, 0x6e, 0x04, 0x6f, 0x04, 0x70, 0x04, 0x71, 0x04, 0x72, 0x04, 0x73, 0x04, 0x74, 0x04, 0x75, 0x04, 0x78, 0x04, 0x79, 0x04, 0x7a, 0x04, 0x7b, 0x04, 0x7c, 0x04, 0x7d, 0x04, 0x7e, 0x04, 0x7f, 0x04, 0x80, 0x04, 0x81, 0x04, 0x90, 0x04, 0x91, 0x04, 0x92, 0x04, 0x93, 0x04, 0x94, 0x04, 0x95, 0x04, 0x96, 0x04, 0x97, 0x04, 0x98, 0x04, 0x99, 0x04, 0x9a, 0x04, 0x9b, 0x04, 0x9c, 0x04, 0x9d, 0x04, 0x9e, 0x04, 0x9f, 0x04, 0xa0, 0x04, 0xa1, 0x04, 0xa2, 0x04, 0xa3, 0x04, 0xa4, 0x04, 0xa5, 0x04, 0xa6, 0x04, 0xa7, 0x04, 0xa8, 0x04, 0xa9, 0x04, 0xaa, 0x04, 0xab, 0x04, 0xac, 0x04, 0xad, 0x04, 0xae, 0x04, 0xaf, 0x04, 0xb0, 0x04, 0xb1, 0x04, 0xb2, 0x04, 0xb3, 0x04, 0xb4, 0x04, 0xb5, 0x04, 0xb6, 0x04, 0xb7, 0x04, 0xb8, 0x04, 0xb9, 0x04, 0xba, 0x04, 0xbb, 0x04, 0xbc, 0x04, 0xbd, 0x04, 0xbe, 0x04, 0xbf, 0x04, 0xc3, 0x04, 0xc4, 0x04, 0xc7, 0x04, 0xc8, 0x04, 0xcb, 0x04, 0xcc, 0x05, 0x31, 0x05, 0x61, 0x05, 0x32, 0x05, 0x62, 0x05, 0x33, 0x05, 0x63, 0x05, 0x34, 0x05, 0x64, 0x05, 0x35, 0x05, 0x65, 0x05, 0x36, 0x05, 0x66, 0x05, 0x37, 0x05, 0x67, 0x05, 0x38, 0x05, 0x68, 0x05, 0x39, 0x05, 0x69, 0x05, 0x3a, 0x05, 0x6a, 0x05, 0x3b, 0x05, 0x6b, 0x05, 0x3c, 0x05, 0x6c, 0x05, 0x3d, 0x05, 0x6d, 0x05, 0x3e, 0x05, 0x6e, 0x05, 0x3f, 0x05, 0x6f, 0x05, 0x40, 0x05, 0x70, 0x05, 0x41, 0x05, 0x71, 0x05, 0x42, 0x05, 0x72, 0x05, 0x43, 0x05, 0x73, 0x05, 0x44, 0x05, 0x74, 0x05, 0x45, 0x05, 0x75, 0x05, 0x46, 0x05, 0x76, 0x05, 0x47, 0x05, 0x77, 0x05, 0x48, 0x05, 0x78, 0x05, 0x49, 0x05, 0x79, 0x05, 0x4a, 0x05, 0x7a, 0x05, 0x4b, 0x05, 0x7b, 0x05, 0x4c, 0x05, 0x7c, 0x05, 0x4d, 0x05, 0x7d, 0x05, 0x4e, 0x05, 0x7e, 0x05, 0x4f, 0x05, 0x7f, 0x05, 0x50, 0x05, 0x80, 0x05, 0x51, 0x05, 0x81, 0x05, 0x52, 0x05, 0x82, 0x05, 0x53, 0x05, 0x83, 0x05, 0x54, 0x05, 0x84, 0x05, 0x55, 0x05, 0x85, 0x05, 0x56, 0x05, 0x86, 0x10, 0xa0, 0x10, 0xd0, 0x10, 0xa1, 0x10, 0xd1, 0x10, 0xa2, 0x10, 0xd2, 0x10, 0xa3, 0x10, 0xd3, 0x10, 0xa4, 0x10, 0xd4, 0x10, 0xa5, 0x10, 0xd5, 0x10, 0xa6, 0x10, 0xd6, 0x10, 0xa7, 0x10, 0xd7, 0x10, 0xa8, 0x10, 0xd8, 0x10, 0xa9, 0x10, 0xd9, 0x10, 0xaa, 0x10, 0xda, 0x10, 0xab, 0x10, 0xdb, 0x10, 0xac, 0x10, 0xdc, 0x10, 0xad, 0x10, 0xdd, 0x10, 0xae, 0x10, 0xde, 0x10, 0xaf, 0x10, 0xdf, 0x10, 0xb0, 0x10, 0xe0, 0x10, 0xb1, 0x10, 0xe1, 0x10, 0xb2, 0x10, 0xe2, 0x10, 0xb3, 0x10, 0xe3, 0x10, 0xb4, 0x10, 0xe4, 0x10, 0xb5, 0x10, 0xe5, 0x10, 0xb6, 0x10, 0xe6, 0x10, 0xb7, 0x10, 0xe7, 0x10, 0xb8, 0x10, 0xe8, 0x10, 0xb9, 0x10, 0xe9, 0x10, 0xba, 0x10, 0xea, 0x10, 0xbb, 0x10, 0xeb, 0x10, 0xbc, 0x10, 0xec, 0x10, 0xbd, 0x10, 0xed, 0x10, 0xbe, 0x10, 0xee, 0x10, 0xbf, 0x10, 0xef, 0x10, 0xc0, 0x10, 0xf0, 0x10, 0xc1, 0x10, 0xf1, 0x10, 0xc2, 0x10, 0xf2, 0x10, 0xc3, 0x10, 0xf3, 0x10, 0xc4, 0x10, 0xf4, 0x10, 0xc5, 0x10, 0xf5, 0x20, 0x0c, 0x00, 0x00, 0x20, 0x0d, 0x00, 0x00, 0x20, 0x0e, 0x00, 0x00, 0x20, 0x0f, 0x00, 0x00, 0x20, 0x2a, 0x00, 0x00, 0x20, 0x2b, 0x00, 0x00, 0x20, 0x2c, 0x00, 0x00, 0x20, 0x2d, 0x00, 0x00, 0x20, 0x2e, 0x00, 0x00, 0x20, 0x6a, 0x00, 0x00, 0x20, 0x6b, 0x00, 0x00, 0x20, 0x6c, 0x00, 0x00, 0x20, 0x6d, 0x00, 0x00, 0x20, 0x6e, 0x00, 0x00, 0x20, 0x6f, 0x00, 0x00, 0x21, 0x60, 0x21, 0x70, 0x21, 0x61, 0x21, 0x71, 0x21, 0x62, 0x21, 0x72, 0x21, 0x63, 0x21, 0x73, 0x21, 0x64, 0x21, 0x74, 0x21, 0x65, 0x21, 0x75, 0x21, 0x66, 0x21, 0x76, 0x21, 0x67, 0x21, 0x77, 0x21, 0x68, 0x21, 0x78, 0x21, 0x69, 0x21, 0x79, 0x21, 0x6a, 0x21, 0x7a, 0x21, 0x6b, 0x21, 0x7b, 0x21, 0x6c, 0x21, 0x7c, 0x21, 0x6d, 0x21, 0x7d, 0x21, 0x6e, 0x21, 0x7e, 0x21, 0x6f, 0x21, 0x7f, 0xfe, 0xff, 0x00, 0x00, 0xff, 0x21, 0xff, 0x41, 0xff, 0x22, 0xff, 0x42, 0xff, 0x23, 0xff, 0x43, 0xff, 0x24, 0xff, 0x44, 0xff, 0x25, 0xff, 0x45, 0xff, 0x26, 0xff, 0x46, 0xff, 0x27, 0xff, 0x47, 0xff, 0x28, 0xff, 0x48, 0xff, 0x29, 0xff, 0x49, 0xff, 0x2a, 0xff, 0x4a, 0xff, 0x2b, 0xff, 0x4b, 0xff, 0x2c, 0xff, 0x4c, 0xff, 0x2d, 0xff, 0x4d, 0xff, 0x2e, 0xff, 0x4e, 0xff, 0x2f, 0xff, 0x4f, 0xff, 0x30, 0xff, 0x50, 0xff, 0x31, 0xff, 0x51, 0xff, 0x32, 0xff, 0x52, 0xff, 0x33, 0xff, 0x53, 0xff, 0x34, 0xff, 0x54, 0xff, 0x35, 0xff, 0x55, 0xff, 0x36, 0xff, 0x56, 0xff, 0x37, 0xff, 0x57, 0xff, 0x38, 0xff, 0x58, 0xff, 0x39, 0xff, 0x59, 0xff, 0x3a, 0xff, 0x5a, 0x00 }; static int utf16be_transl_count = 329; /* These are the start indice in utf16be_transl[] for the page numbers 0 to 9 as classified by function what_page(). As soon as the first byte of the input pair in utf16be_transl[] changes, the search can be ended and output is equal to input. If page -1 is returned by what_page(), then input is equal to output. */ static int utf16be_transl_starts[] = { 0, 31, 81, 112, 195, 233, 271, 286, 302, 303 }; static int what_page(uint16_t x) { switch(((uint8_t *) &x)[0]) { case 0: return 0; case 1: return 1; case 3: return 2; case 4: return 3; case 5: return 4; case 16: return 5; case 32: return 6; case 33: return 7; case 254: return 8; case 255: return 9; default: return -1; /* no mapping */ } } /* Accelerator for the ASCII subset which is expected to be the most frequently used one. */ static uint16_t cmp_name_page0(uint16_t x) { uint8_t *low; low = ((uint8_t *) &x) + 1; if (x == 0) return 0xffff; if (*low <= 0x40) ; else if (*low <= 0x5a) *low = *low + 0x20; else if (*low < 0xc6) ; else if (*low == 0xc6) *low = 0xe6; else if (*low == 0xd0) *low = 0xf0; else if (*low == 0xd8) *low = 0xf8; else if (*low == 0xde) *low = 0xfe; return x; } /* Converts a character into the representative of its HFS+ equivalence class. @param x The UTF-16BE character to be converted. @return 0 = ignore character with comparisons else the case-insensitive character. */ uint16_t iso_hfsplus_cichar(uint16_t x) { int page, i; uint16_t ret; uint8_t low, high; high = ((uint8_t *) &x)[0]; low = ((uint8_t *) &x)[1]; page = what_page(x); if (page < 0) return x; /* No translation needed */ if (page == 0) return cmp_name_page0(x); /* Accelerator for ASCII subset */ for (i = utf16be_transl_starts[page] * 4; i < utf16be_transl_count * 4; i += 4) { if (utf16be_transl[i] != high) break; if (utf16be_transl[i + 1] == low) { ((uint8_t *) &ret)[0] = utf16be_transl[i + 2]; ((uint8_t *) &ret)[1] = utf16be_transl[i + 3]; return ret; } } return x; } libisofs-1.4.2/libisofs/fs_local.c0000644000175700017510000005104612607671777014053 00000000000000/* * Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2009 - 2011 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ /* * Filesystem/FileSource implementation to access the local filesystem. */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif #include "fsource.h" #include "util.h" #include "aaip_0_2.h" #include #include #include #include #include #include #include #include #include /* O_BINARY is needed for Cygwin but undefined elsewhere */ #ifndef O_BINARY #define O_BINARY 0 #endif static int iso_file_source_new_lfs(IsoFileSource *parent, const char *name, IsoFileSource **src); /* * We can share a local filesystem object, as it has no private atts. */ IsoFilesystem *lfs= NULL; /* IMPORTANT: Any change must be reflected by lfs_clone_src() */ typedef struct { /** reference to the parent (if root it points to itself) */ IsoFileSource *parent; char *name; unsigned int openned :2; /* 0: not openned, 1: file, 2:dir */ union { int fd; DIR *dir; } info; } _LocalFsFileSource; static char* lfs_get_path(IsoFileSource *src) { _LocalFsFileSource *data; data = src->data; if (data->parent == src) { return strdup("/"); } else { char *path, *new_path; int pathlen; path = lfs_get_path(data->parent); if (path == NULL) return NULL; pathlen = strlen(path); new_path = realloc(path, pathlen + strlen(data->name) + 2); if (new_path == NULL) { free(path); return NULL; } path= new_path; if (pathlen != 1) { /* pathlen can only be 1 for root */ path[pathlen] = '/'; path[pathlen + 1] = '\0'; } return strcat(path, data->name); } } static char* lfs_get_name(IsoFileSource *src) { _LocalFsFileSource *data; data = src->data; return strdup(data->name); } static int lfs_lstat(IsoFileSource *src, struct stat *info) { char *path; if (src == NULL || info == NULL) { return ISO_NULL_POINTER; } path = lfs_get_path(src); if (path == NULL) return ISO_OUT_OF_MEM; if (lstat(path, info) != 0) { int err; /* error, choose an appropriate return code */ switch (errno) { case EACCES: err = ISO_FILE_ACCESS_DENIED; break; case ENOTDIR: case ENAMETOOLONG: case ELOOP: err = ISO_FILE_BAD_PATH; break; case ENOENT: err = ISO_FILE_DOESNT_EXIST; break; case EFAULT: case ENOMEM: err = ISO_OUT_OF_MEM; break; default: err = ISO_FILE_ERROR; break; } free(path); return err; } free(path); return ISO_SUCCESS; } static int lfs_stat(IsoFileSource *src, struct stat *info) { char *path; if (src == NULL || info == NULL) { return ISO_NULL_POINTER; } path = lfs_get_path(src); if (path == NULL) return ISO_OUT_OF_MEM; if (stat(path, info) != 0) { int err; /* error, choose an appropriate return code */ switch (errno) { case EACCES: err = ISO_FILE_ACCESS_DENIED; break; case ENOTDIR: case ENAMETOOLONG: case ELOOP: err = ISO_FILE_BAD_PATH; break; case ENOENT: err = ISO_FILE_DOESNT_EXIST; break; case EFAULT: case ENOMEM: err = ISO_OUT_OF_MEM; break; default: err = ISO_FILE_ERROR; break; } free(path); return err; } free(path); return ISO_SUCCESS; } static int lfs_access(IsoFileSource *src) { int ret; char *path; if (src == NULL) { return ISO_NULL_POINTER; } path = lfs_get_path(src); ret = iso_eaccess(path); free(path); return ret; } static int lfs_open(IsoFileSource *src) { int err; struct stat info; _LocalFsFileSource *data; char *path; if (src == NULL) { return ISO_NULL_POINTER; } data = src->data; if (data->openned) { return ISO_FILE_ALREADY_OPENED; } /* is a file or a dir ? */ err = lfs_stat(src, &info); if (err < 0) { return err; } path = lfs_get_path(src); if (S_ISDIR(info.st_mode)) { data->info.dir = opendir(path); data->openned = data->info.dir ? 2 : 0; } else { data->info.fd = open(path, O_RDONLY | O_BINARY); data->openned = data->info.fd != -1 ? 1 : 0; } free(path); /* * check for possible errors, note that many of possible ones are * parsed in the lstat call above */ if (data->openned == 0) { switch (errno) { case EACCES: err = ISO_FILE_ACCESS_DENIED; break; case EFAULT: case ENOMEM: err = ISO_OUT_OF_MEM; break; default: err = ISO_FILE_ERROR; break; } return err; } return ISO_SUCCESS; } static int lfs_close(IsoFileSource *src) { int ret; _LocalFsFileSource *data; if (src == NULL) { return ISO_NULL_POINTER; } data = src->data; switch (data->openned) { case 1: /* not dir */ ret = close(data->info.fd) == 0 ? ISO_SUCCESS : ISO_FILE_ERROR; break; case 2: /* directory */ ret = closedir(data->info.dir) == 0 ? ISO_SUCCESS : ISO_FILE_ERROR; break; default: ret = ISO_FILE_NOT_OPENED; break; } if (ret == ISO_SUCCESS) { data->openned = 0; } return ret; } static int lfs_read(IsoFileSource *src, void *buf, size_t count) { _LocalFsFileSource *data; size_t to_read, done = 0; int ret; uint8_t *buf8; if (src == NULL || buf == NULL) { return ISO_NULL_POINTER; } if (count == 0) { return ISO_WRONG_ARG_VALUE; } data = src->data; switch (data->openned) { case 1: /* not dir */ buf8 = (uint8_t *) buf; /* for pointer arithmetic */ for (to_read = count; to_read > 0; to_read = count - done) { if (to_read > 1024 * 1024) to_read = 1024 * 1024; ret = read(data->info.fd, buf8 + done, to_read); if (ret < 0) { /* error on read */ switch (errno) { case EINTR: return ISO_INTERRUPTED; case EFAULT: return ISO_OUT_OF_MEM; case EIO: return ISO_FILE_READ_ERROR; } return ISO_FILE_ERROR; } if (ret == 0) /* EOF */ break; done += ret; } return done; case 2: /* directory */ return ISO_FILE_IS_DIR; default: return ISO_FILE_NOT_OPENED; } } static off_t lfs_lseek(IsoFileSource *src, off_t offset, int flag) { _LocalFsFileSource *data; int whence; if (src == NULL) { return (off_t)ISO_NULL_POINTER; } switch (flag) { case 0: whence = SEEK_SET; break; case 1: whence = SEEK_CUR; break; case 2: whence = SEEK_END; break; default: return (off_t)ISO_WRONG_ARG_VALUE; } data = src->data; switch (data->openned) { case 1: /* not dir */ { off_t ret; ret = lseek(data->info.fd, offset, whence); if (ret < 0) { /* error on read */ switch (errno) { case ESPIPE: ret = (off_t)ISO_FILE_ERROR; break; default: ret = (off_t)ISO_ERROR; break; } } return ret; } case 2: /* directory */ return (off_t)ISO_FILE_IS_DIR; default: return (off_t)ISO_FILE_NOT_OPENED; } } static int lfs_readdir(IsoFileSource *src, IsoFileSource **child) { _LocalFsFileSource *data; if (src == NULL || child == NULL) { return ISO_NULL_POINTER; } data = src->data; switch (data->openned) { case 1: /* not dir */ return ISO_FILE_IS_NOT_DIR; case 2: /* directory */ { struct dirent *entry; int ret; /* while to skip "." and ".." dirs */ while (1) { entry = readdir(data->info.dir); if (entry == NULL) { if (errno == EBADF) return ISO_FILE_ERROR; else return 0; /* EOF */ } if (strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..")) { break; } } /* create the new FileSrc */ ret = iso_file_source_new_lfs(src, entry->d_name, child); return ret; } default: return ISO_FILE_NOT_OPENED; } } static int lfs_readlink(IsoFileSource *src, char *buf, size_t bufsiz) { int size, ret; char *path; if (src == NULL || buf == NULL) { return ISO_NULL_POINTER; } if (bufsiz <= 0) { return ISO_WRONG_ARG_VALUE; } path = lfs_get_path(src); /* * invoke readlink, with bufsiz -1 to reserve an space for * the NULL character */ size = readlink(path, buf, bufsiz); free(path); if (size < 0) { /* error */ switch (errno) { case EACCES: return ISO_FILE_ACCESS_DENIED; case ENOTDIR: case ENAMETOOLONG: case ELOOP: return ISO_FILE_BAD_PATH; case ENOENT: return ISO_FILE_DOESNT_EXIST; case EINVAL: return ISO_FILE_IS_NOT_SYMLINK; case EFAULT: case ENOMEM: return ISO_OUT_OF_MEM; default: return ISO_FILE_ERROR; } } /* NULL-terminate the buf */ ret = ISO_SUCCESS; if ((size_t) size >= bufsiz) { ret = ISO_RR_PATH_TOO_LONG; size = bufsiz - 1; } buf[size] = '\0'; return ret; } static IsoFilesystem* lfs_get_filesystem(IsoFileSource *src) { return src == NULL ? NULL : lfs; } static void lfs_free(IsoFileSource *src) { _LocalFsFileSource *data; data = src->data; /* close the file if it is already openned */ if (data->openned) { src->class->close(src); } if (data->parent != src) { iso_file_source_unref(data->parent); } free(data->name); free(data); iso_filesystem_unref(lfs); } static int lfs_get_aa_string(IsoFileSource *src, unsigned char **aa_string, int flag) { int ret; size_t num_attrs = 0, *value_lengths = NULL, result_len; ssize_t sret; char *path = NULL, **names = NULL, **values = NULL; unsigned char *result = NULL; *aa_string = NULL; if ((flag & 3 ) == 3) { ret = 1; goto ex; } /* Obtain EAs and ACLs ("access" and "default"). ACLs encoded according to AAIP ACL representation. Clean out st_mode ACL entries. */ path = iso_file_source_get_path(src); if (path == NULL) { ret = ISO_NULL_POINTER; goto ex; } ret = aaip_get_attr_list(path, &num_attrs, &names, &value_lengths, &values, (!(flag & 2)) | 2 | (flag & 4) | 16); if (ret <= 0) { if (ret == -2) ret = ISO_AAIP_NO_GET_LOCAL; else ret = ISO_FILE_ERROR; goto ex; } if (num_attrs == 0) result = NULL; else { sret = aaip_encode(num_attrs, names, value_lengths, values, &result_len, &result, 0); if (sret < 0) { ret = sret; goto ex; } } *aa_string = result; ret = 1; ex:; if (path != NULL) free(path); if (names != NULL || value_lengths != NULL || values != NULL) aaip_get_attr_list(NULL, &num_attrs, &names, &value_lengths, &values, 1 << 15); /* free memory */ return ret; } static int lfs_clone_src(IsoFileSource *old_source, IsoFileSource **new_source, int flag) { IsoFileSource *src = NULL; char *new_name = NULL; _LocalFsFileSource *old_data, *new_data = NULL; if (flag) return ISO_STREAM_NO_CLONE; /* unknown option required */ old_data = (_LocalFsFileSource *) old_source->data; *new_source = NULL; src = calloc(1, sizeof(IsoFileSource)); if (src == NULL) goto no_mem; new_name = strdup(old_data->name); if (new_name == NULL) goto no_mem; new_data = calloc(1, sizeof(_LocalFsFileSource)); if (new_data == NULL) goto no_mem; new_data->openned = 0; new_data->info.fd = -1; /* the value does not matter with (openned == 0) */ new_data->name = new_name; new_data->parent = old_data->parent; src->class = old_source->class; src->refcount = 1; src->data = new_data; *new_source = src; iso_file_source_ref(new_data->parent); iso_filesystem_ref(lfs); return ISO_SUCCESS; no_mem:; if (src != NULL) free((char *) src); if (new_data != NULL) free((char *) new_data); if (new_name != NULL) free(new_name); return ISO_OUT_OF_MEM; } IsoFileSourceIface lfs_class = { 2, /* version */ lfs_get_path, lfs_get_name, lfs_lstat, lfs_stat, lfs_access, lfs_open, lfs_close, lfs_read, lfs_readdir, lfs_readlink, lfs_get_filesystem, lfs_free, lfs_lseek, lfs_get_aa_string, lfs_clone_src }; /** * * @return * 1 success, < 0 error */ static int iso_file_source_new_lfs(IsoFileSource *parent, const char *name, IsoFileSource **src) { IsoFileSource *lfs_src; _LocalFsFileSource *data; if (src == NULL) { return ISO_NULL_POINTER; } if (lfs == NULL) { /* this should never happen */ return ISO_ASSERT_FAILURE; } /* allocate memory */ data = malloc(sizeof(_LocalFsFileSource)); if (data == NULL) { return ISO_OUT_OF_MEM; } lfs_src = malloc(sizeof(IsoFileSource)); if (lfs_src == NULL) { free(data); return ISO_OUT_OF_MEM; } /* fill struct */ data->name = name ? strdup(name) : NULL; data->openned = 0; if (parent) { data->parent = parent; iso_file_source_ref(parent); } else { data->parent = lfs_src; } lfs_src->refcount = 1; lfs_src->data = data; lfs_src->class = &lfs_class; /* take a ref to local filesystem */ iso_filesystem_ref(lfs); /* return */ *src = lfs_src; return ISO_SUCCESS; } static int lfs_get_root(IsoFilesystem *fs, IsoFileSource **root) { if (fs == NULL || root == NULL) { return ISO_NULL_POINTER; } return iso_file_source_new_lfs(NULL, NULL, root); } static int lfs_get_by_path(IsoFilesystem *fs, const char *path, IsoFileSource **file) { int ret; IsoFileSource *src; struct stat info; char *ptr, *brk_info, *component; if (fs == NULL || path == NULL || file == NULL) { return ISO_NULL_POINTER; } /* * first of all check that it is a valid path. */ if (lstat(path, &info) != 0) { int err; /* error, choose an appropriate return code */ switch (errno) { case EACCES: err = ISO_FILE_ACCESS_DENIED; break; case ENOTDIR: case ENAMETOOLONG: case ELOOP: err = ISO_FILE_BAD_PATH; break; case ENOENT: err = ISO_FILE_DOESNT_EXIST; break; case EFAULT: case ENOMEM: err = ISO_OUT_OF_MEM; break; default: err = ISO_FILE_ERROR; break; } return err; } /* ok, path is valid. create the file source */ ret = lfs_get_root(fs, &src); if (ret < 0) { return ret; } if (!strcmp(path, "/")) { /* we are looking for root */ *file = src; return ISO_SUCCESS; } ptr = strdup(path); if (ptr == NULL) { iso_file_source_unref(src); return ISO_OUT_OF_MEM; } component = strtok_r(ptr, "/", &brk_info); while (component) { IsoFileSource *child = NULL; if (!strcmp(component, ".")) { child = src; } else if (!strcmp(component, "..")) { child = ((_LocalFsFileSource*)src->data)->parent; iso_file_source_ref(child); iso_file_source_unref(src); } else { ret = iso_file_source_new_lfs(src, component, &child); iso_file_source_unref(src); if (ret < 0) { break; } } src = child; component = strtok_r(NULL, "/", &brk_info); } free(ptr); if (ret > 0) { *file = src; } return ret; } static unsigned int lfs_get_id(IsoFilesystem *fs) { return ISO_LOCAL_FS_ID; } static int lfs_fs_open(IsoFilesystem *fs) { /* open() operation is not needed */ return ISO_SUCCESS; } static int lfs_fs_close(IsoFilesystem *fs) { /* close() operation is not needed */ return ISO_SUCCESS; } static void lfs_fs_free(IsoFilesystem *fs) { lfs = NULL; } int iso_local_filesystem_new(IsoFilesystem **fs) { if (fs == NULL) { return ISO_NULL_POINTER; } if (lfs != NULL) { /* just take a new ref */ iso_filesystem_ref(lfs); } else { lfs = malloc(sizeof(IsoFilesystem)); if (lfs == NULL) { return ISO_OUT_OF_MEM; } /* fill struct */ strncpy(lfs->type, "file", 4); lfs->refcount = 1; lfs->version = 0; lfs->data = NULL; /* we don't need private data */ lfs->get_root = lfs_get_root; lfs->get_by_path = lfs_get_by_path; lfs->get_id = lfs_get_id; lfs->open = lfs_fs_open; lfs->close = lfs_fs_close; lfs->free = lfs_fs_free; } *fs = lfs; return ISO_SUCCESS; } int iso_local_attr_support(int flag) { int ret; ret= aaip_local_attr_support(flag & 255); return ret; } int iso_local_get_acl_text(char *disk_path, char **text, int flag) { int ret; ret = aaip_get_acl_text(disk_path, text, flag & (1 | 16 | 32 | (1 << 15))); return ret; } int iso_local_set_acl_text(char *disk_path, char *text, int flag) { int ret; ret = aaip_set_acl_text(disk_path, text, flag & (1 | 32)); if (ret < 0) return ISO_AAIP_NO_SET_LOCAL; return ret; } int iso_local_get_attrs(char *disk_path, size_t *num_attrs, char ***names, size_t **value_lengths, char ***values, int flag) { int ret; ret = aaip_get_attr_list(disk_path, num_attrs, names, value_lengths, values, (flag & (1 | 4 | 8 | 32 | (1 << 15))) | 2 | 16); if (ret <= 0) return ISO_AAIP_NO_GET_LOCAL; return 1; } int iso_local_set_attrs(char *disk_path, size_t num_attrs, char **names, size_t *value_lengths, char **values, int flag) { int ret; ret = aaip_set_attr_list(disk_path, num_attrs, names, value_lengths, values, (flag & (8 | 32 | 64)) | !(flag & 1)); if (ret <= 0) { if (ret == -1) return ISO_OUT_OF_MEM; if (ret == -2) return ISO_AAIP_BAD_AASTRING; if (ret >= -5) return ISO_AAIP_NO_SET_LOCAL; if (ret == -6 || ret == -7) return ISO_AAIP_NOT_ENABLED; if (ret == -8) return ISO_AAIP_BAD_ATTR_NAME; return ret; } return 1; } int iso_local_get_perms_wo_acl(char *disk_path, mode_t *st_mode, int flag) { struct stat stbuf; int ret; char *a_text = NULL; if (flag & 32) ret = stat(disk_path, &stbuf); else ret = lstat(disk_path, &stbuf); if (ret == -1) return -1; *st_mode = stbuf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); ret = iso_local_get_acl_text(disk_path, &a_text, 16 | (flag & 32)); if (a_text != NULL) { aaip_cleanout_st_mode(a_text, st_mode, 4 | 16); iso_local_get_acl_text(disk_path, &a_text, 1 << 15); /* free a_text */ } return 1; } libisofs-1.4.2/libisofs/util.h0000644000175700017510000005172412574006151013233 00000000000000/* * Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2009 - 2012 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ #ifndef LIBISO_UTIL_H_ #define LIBISO_UTIL_H_ #ifdef HAVE_STDINT_H #include #else #ifdef HAVE_INTTYPES_H #include #endif #endif #include #ifdef HAVE_STDLIB_H #include #endif #include #ifndef MAX # define MAX(a, b) (((a) > (b)) ? (a) : (b)) #endif #ifndef MIN # define MIN(a, b) (((a) < (b)) ? (a) : (b)) #endif #define DIV_UP(n,div) ((n + div - 1) / div) #define ROUND_UP(n,mul) (DIV_UP(n, mul) * mul) int int_pow(int base, int power); /** * Set up locale by LC_* environment variables. */ int iso_init_locale(int flag); /** * Convert the charset encoding of a given string. * * @param input * Input string * @param icharset * Input charset. Must be supported by iconv * @param ocharset * Output charset. Must be supported by iconv * @param output * Location where the pointer to the ouput string will be stored * @return * 1 on success, < 0 on error */ int strconv(const char *input, const char *icharset, const char *ocharset, char **output); /* Like strconv but processing len input bytes rather than strlen(input) */ int strnconv(const char *str, const char *icharset, const char *ocharset, size_t len, char **output); /* Like strnconv but also returning the number of bytes in *output. */ int strnconvl(const char *str, const char *icharset, const char *ocharset, size_t len, char **output, size_t *out_len); /** * Convert a given string from any input charset to ASCII * * @param icharset * Input charset. Must be supported by iconv * @param input * Input string * @param output * Location where the pointer to the ouput string will be stored * @return * 1 on success, < 0 on error */ int str2ascii(const char *icharset, const char *input, char **output); /** * Convert a given string from any input charset to UCS-2BE charset, * used for Joliet file identifiers. * * @param icharset * Input charset. Must be supported by iconv * @param input * Input string * @param output * Location where the pointer to the ouput string will be stored * @return * 1 on success, < 0 on error */ int str2ucs(const char *icharset, const char *input, uint16_t **output); /** * Convert a given string from any input charset to UTF-16BE charset, * used for HFS+ file identifiers. * (UTF-16 differs from older UCS-2 by having multi word characters.) * * @param icharset * Input charset. Must be supported by iconv * @param input * Input string * @param output * Location where the pointer to the ouput string will be stored * @return * 1 on success, < 0 on error */ int str2utf16be(const char *icharset, const char *input, uint16_t **output); /** * Create a level 1 directory identifier. * * @param src * The identifier, in ASCII encoding. * @param relaxed * 0 only allow d-characters, 1 allow also lowe case chars, * 2 allow all characters */ char *iso_1_dirid(const char *src, int relaxed); /** * Create a level 2 directory identifier. * * @param src * The identifier, in ASCII encoding. */ char *iso_2_dirid(const char *src); /** * Create a dir name suitable for an ISO image with relaxed constraints. * * @param src * The identifier, in ASCII encoding. * @param size * Max len for the name * @param relaxed * 0 only allow d-characters, 1 allow also lowe case chars, * 2 allow all characters */ char *iso_r_dirid(const char *src, int size, int relaxed); /** * Create a level 1 file identifier that consists of a name, in 8.3 * format. * Note that version number is not added to the file name * * @param src * The identifier, in ASCII encoding. * @param relaxed * 0 only allow d-characters, 1 allow also lowe case chars, * 2 allow all characters * @param force_dots * If 1 then prepend empty extension by SEPARATOR1 = '.' */ char *iso_1_fileid(const char *src, int relaxed, int force_dots); /** * Create a level 2 file identifier. * Note that version number is not added to the file name * * @param src * The identifier, in ASCII encoding. */ char *iso_2_fileid(const char *src); /** * Create a file name suitable for an ISO image with relaxed constraints. * * @param src * The identifier, in ASCII encoding. * @param len * Max len for the name, without taken the "." into account. * @param relaxed * 0 only allow d-characters, 1 allow also lowe case chars, * 2 allow all characters * @param forcedot * Whether to ensure that "." is added */ char *iso_r_fileid(const char *src, size_t len, int relaxed, int forcedot); /** * Create a Joliet file identifier that consists of name and extension. The * combined name and extension length will normally not exceed 64 characters * (= 128 bytes). The name and the extension will be separated (.). * All characters consist of 2 bytes and the resulting string is * NULL-terminated by a 2-byte NULL. * * Note that version number and (;1) is not appended. * @param flag * bit0= no_force_dots * bit1= allow 103 characters rather than 64 * @return * NULL if the original name and extension both are of length 0. */ uint16_t *iso_j_file_id(const uint16_t *src, int flag); /** * Create a Joliet directory identifier that consists of name and optionally * extension. The combined name and extension length will not exceed 128 bytes, * and the name and extension will be separated (.). All characters consist of * 2 bytes and the resulting string is NULL-terminated by a 2-byte NULL. * * @param flag * bit1= allow 103 characters rather than 64 * @return * NULL if the original name and extension both are of length 0. */ uint16_t *iso_j_dir_id(const uint16_t *src, int flag); /** * Like strlen, but for Joliet strings. */ size_t ucslen(const uint16_t *str); /** * Like strrchr, but for Joliet strings. */ uint16_t *ucsrchr(const uint16_t *str, char c); /** * Like strdup, but for Joliet strings. */ uint16_t *ucsdup(const uint16_t *str); /** * Like strcmp, but for Joliet strings. */ int ucscmp(const uint16_t *s1, const uint16_t *s2); /** * Like strcpy, but for Joliet strings. */ uint16_t *ucscpy(uint16_t *dest, const uint16_t *src); /** * Like strncpy, but for Joliet strings. * @param n * Maximum number of characters to copy (2 bytes per char). */ uint16_t *ucsncpy(uint16_t *dest, const uint16_t *src, size_t n); /** * Check whether utf_word is the first surrogate word of a pair. * If so, change it to UTF-16 character '_'. */ void iso_handle_split_utf16(uint16_t *utf_word); /** * Convert a given input string to d-chars. * @return * 1 on succes, < 0 error, 0 if input was null (output is set to null) */ int str2d_char(const char *icharset, const char *input, char **output); int str2a_char(const char *icharset, const char *input, char **output); void iso_lsb(uint8_t *buf, uint32_t num, int bytes); void iso_msb(uint8_t *buf, uint32_t num, int bytes); void iso_bb(uint8_t *buf, uint32_t num, int bytes); /* An alternative to iso_lsb() which advances the write pointer */ int iso_lsb_to_buf(char **wpt, uint32_t value, int bytes, int flag); uint32_t iso_read_lsb(const uint8_t *buf, int bytes); uint32_t iso_read_msb(const uint8_t *buf, int bytes); /** * if error != NULL it will be set to 1 if LSB and MSB integers don't match. */ uint32_t iso_read_bb(const uint8_t *buf, int bytes, int *error); uint64_t iso_read_lsb64(const uint8_t *buf); uint64_t iso_read_msb64(const uint8_t *buf); /** * Records the date/time into a 7 byte buffer (ECMA-119, 9.1.5) * * @param buf * Buffer where the date will be written * @param t * The time to be written * @param always_gmt * Always write the date in GMT and not in local time. */ void iso_datetime_7(uint8_t *buf, time_t t, int always_gmt); /** Records the date/time into a 17 byte buffer (ECMA-119, 8.4.26.1) */ void iso_datetime_17(uint8_t *buf, time_t t, int always_gmt); time_t iso_datetime_read_7(const uint8_t *buf); time_t iso_datetime_read_17(const uint8_t *buf); /** * Check whether the caller process has read access to the given local file. * * @return * 1 on success (i.e, the process has read access), < 0 on error * (including ISO_FILE_ACCESS_DENIED on access denied to the specified file * or any directory on the path). */ int iso_eaccess(const char *path); /** * Copy up to \p len chars from \p buf and return this newly allocated * string. The new string is null-terminated. */ char *iso_util_strcopy(const char *buf, size_t len); /** * Copy up to \p len chars from \p buf and return this newly allocated * string. The new string is null-terminated. * Any trailing blanks will be removed. */ char *iso_util_strcopy_untail(const char *buf, size_t len); /** * Copy up to \p max characters from \p src to \p dest. If \p src has less than * \p max characters, we pad dest with " " characters. */ void strncpy_pad(char *dest, const char *src, size_t max); /** * Convert a Joliet string with a length of \p len bytes to a new string * in local charset. */ char *ucs2str(const char *buf, size_t len); typedef struct iso_rbtree IsoRBTree; typedef struct iso_htable IsoHTable; typedef unsigned int (*hash_funtion_t)(const void *key); typedef int (*compare_function_t)(const void *a, const void *b); typedef void (*hfree_data_t)(void *key, void *data); /** * Create a new binary tree. libisofs binary trees allow you to add any data * passing it as a pointer. You must provide a function suitable for compare * two elements. * * @param compare * A function to compare two keys. It takes a pointer to both keys * and return 0, -1 or 1 if the first key is equal, less or greater * than the second one. * @param tree * Location where the tree structure will be stored. */ int iso_rbtree_new(int (*compare)(const void*, const void*), IsoRBTree **tree); /** * Destroy a given tree. * * Note that only the structure itself is deleted. To delete the elements, you * should provide a valid free_data function. It will be called for each * element of the tree, so you can use it to free any related data. */ void iso_rbtree_destroy(IsoRBTree *tree, void (*free_data)(void *)); /** * Inserts a given element in a Red-Black tree. * * @param tree * the tree where to insert * @param data * element to be inserted on the tree. It can't be NULL * @param item * if not NULL, it will point to a location where the tree element ptr * will be stored. If data was inserted, *item == data. If data was * already on the tree, *item points to the previously inserted object * that is equal to data. * @return * 1 success, 0 element already inserted, < 0 error */ int iso_rbtree_insert(IsoRBTree *tree, void *data, void **item); /** * Get the number of elements in a given tree. */ size_t iso_rbtree_get_size(IsoRBTree *tree); /** * Get an array view of the elements of the tree. * * @param include_item * Function to select which elements to include in the array. It that takes * a pointer to an element and returns 1 if the element should be included, * 0 if not. If you want to add all elements to the array, you can pass a * NULL pointer. * @param size * If not null, will be filled with the number of elements in the array, * without counting the final NULL item. * @return * A sorted array with the contents of the tree, or NULL if there is not * enought memory to allocate the array. You should free(3) the array when * no more needed. Note that the array is NULL-terminated, and thus it * has size + 1 length. */ void **iso_rbtree_to_array(IsoRBTree *tree, int (*include_item)(void *), size_t *size); /** Predict the size of the array which gets returned by iso_rbtree_to_array(). */ size_t iso_rbtree_count_array(IsoRBTree *tree, size_t initial_count, int (*include_item)(void *)); /** * Create a new hash table. * * @param size * Number of slots in table. * @param hash * Function used to generate */ int iso_htable_create(size_t size, hash_funtion_t hash, compare_function_t compare, IsoHTable **table); /** * Put an element in a Hash Table. The element will be identified by * the given key, that you should use to retrieve the element again. * * This function allow duplicates, i.e., two items with the same key. In those * cases, the value returned by iso_htable_get() is undefined. If you don't * want to allow duplicates, use iso_htable_put() instead; * * Both the key and data pointers will be stored internally, so you should * free the objects they point to. Use iso_htable_remove() to delete an * element from the table. */ int iso_htable_add(IsoHTable *table, void *key, void *data); /** * Like iso_htable_add(), but this doesn't allow dulpicates. * * @return * 1 success, 0 if an item with the same key already exists, < 0 error */ int iso_htable_put(IsoHTable *table, void *key, void *data); /** * Retrieve an element from the given table. * * @param table * Hash table * @param key * Key of the element that will be removed * @param data * Will be filled with the element found. Remains untouched if no * element with the given key is found. * @return * 1 if found, 0 if not, < 0 on error */ int iso_htable_get(IsoHTable *table, void *key, void **data); /** * Remove an item with the given key from the table. In tables that allow * duplicates, it is undefined the element that will be deleted. * * @param table * Hash table * @param key * Key of the element that will be removed * @param free_data * Function that will be called passing as parameters both the key and * the element that will be deleted. The user can use it to free the * element. You can pass NULL if you don't want to delete the item itself. * @return * 1 success, 0 no element exists with the given key, < 0 error */ int iso_htable_remove(IsoHTable *table, void *key, hfree_data_t free_data); /** * Like remove, but instead of checking for key equality using the compare * function, it just compare the key pointers. If the table allows duplicates, * and you provide different keys (i.e. different pointers) to elements * with same key (i.e. same content), this function ensure the exact element * is removed. * * It has the problem that you must provide the same key pointer, and not just * a key whose contents are equal. Moreover, if you use the same key (same * pointer) to identify several objects, what of those are removed is * undefined. * * @param table * Hash table * @param key * Key of the element that will be removed * @param free_data * Function that will be called passing as parameters both the key and * the element that will be deleted. The user can use it to free the * element. You can pass NULL if you don't want to delete the item itself. * @return * 1 success, 0 no element exists with the given key, < 0 error */ int iso_htable_remove_ptr(IsoHTable *table, void *key, hfree_data_t free_data); /** * Destroy the given hash table. * * Note that you're responsible to actually destroy the elements by providing * a valid free_data function. You can pass NULL if you only want to delete * the hash structure. */ void iso_htable_destroy(IsoHTable *table, hfree_data_t free_data); /** * Hash function suitable for keys that are char strings. */ unsigned int iso_str_hash(const void *key); /** * Encode an integer as LEN,BYTES for being a component in certain AAIP * attribute values. */ int iso_util_encode_len_bytes(uint32_t data, char *buffer, int data_len, int *result_len, int flag); /** * Decode an integer as LEN,BYTES for being a component in certain AAIP * attribute values. * @param data returns the decoded value * @param buffer contains the encoded value * @param data_len returns the number of value bytes (without len byte) * @param buffer_len tells the number of valid buffer bytes */ int iso_util_decode_len_bytes(uint32_t *data, char *buffer, int *data_len, int buffer_len, int flag); /* Evaluate a data block whether it is a libisofs session checksum tag of desired type and eventually use it to verify the MD5 checksum computed so far. @param block The data block to be evaluated @param desired Bit map which tells what tag types are expected (0 to 30) @param lba The address from where block was read @param ctx The checksum context computed so far @param ctx_start_lba The block address where checksum computing started @param tag_type Returns the tag type (0 means invalid tag type) @param flag Bitfield for control purposes, unused yet, submit 0 @return 1= tag is desired and matches 0= not a recognizable tag or a undesired tag <0 is error or mismatch */ int iso_util_eval_md5_tag(char *block, int desired, uint32_t lba, void *ctx, uint32_t ctx_start_lba, int *tag_type, uint32_t *next_tag, int flag); int iso_util_tag_magic(int tag_type, char **tag_magic, int *len, int flag); int iso_util_bin_to_hex(char *target, uint8_t *bytes, int num_bytes, int flag); int iso_util_hex_to_bin(char *hex, char *bin, int bin_size, int *bin_count, int flag); int iso_truncate_rr_name(int truncate_mode, int truncate_length, char *name, int flag); /* ------------------------------------------------------------------------- */ /* In md5.h these function prototypes would be neighbors of (Ecma119Image *) which needs inclusion of ecma119.h and more. So, being generic, they ended up here. */ /* Function to identify and manage md5sum indice of the old image. * data is supposed to be a 4 byte integer, bit 31 shall be 0, * value 0 of this integer means that it is not a valid index. */ int checksum_cx_xinfo_func(void *data, int flag); /* The iso_node_xinfo_cloner function which gets associated to * checksum_cx_xinfo_func by iso_init() resp. iso_init_with_flag() via * iso_node_xinfo_make_clonable() */ int checksum_cx_xinfo_cloner(void *old_data, void **new_data, int flag); /* Function to identify and manage md5 sums of unspecified providence stored * directly in this xinfo. This is supposed to override any other recorded * MD5 of the node unless data get copied and checksummed during that copying. */ int checksum_md5_xinfo_func(void *data, int flag); /* The iso_node_xinfo_cloner function which gets associated to * checksum_md5_xinfo_func by iso_init() resp. iso_init_with_flag() via * iso_node_xinfo_make_clonable() */ int checksum_md5_xinfo_cloner(void *old_data, void **new_data, int flag); /* The iso_node_xinfo_cloner function which gets associated to * iso_hfsplus_xinfo_func by iso_init() resp. iso_init_with_flag() via * iso_node_xinfo_make_clonable() */ int iso_hfsplus_xinfo_cloner(void *old_data, void **new_data, int flag); /* ------------------------------------------------------------------------- */ void *iso_alloc_mem(size_t size, size_t count, int flag); #define LIBISO_ALLOC_MEM(pt, typ, count) { \ pt= (typ *) iso_alloc_mem(sizeof(typ), (size_t) (count), 0); \ if(pt == NULL) { \ ret= ISO_OUT_OF_MEM; goto ex; \ } } #define LIBISO_ALLOC_MEM_VOID(pt, typ, count) { \ pt= (typ *) iso_alloc_mem(sizeof(typ), (size_t) (count), 0); \ if(pt == NULL) { \ goto ex; \ } } #define LIBISO_FREE_MEM(pt) { \ if(pt != NULL) \ free((char *) pt); \ } /* @param in Valid memory or NULL @param out Returns valid memory or NULL @param size Number of bytes to copy. 0 means strlen(in)+1 if not NULL. @return 1 or ISO_OUT_OF_MEM */ int iso_clone_mem(char *in, char **out, size_t size); /* Like iso_clone_mem but first freeing *out if not NULL */ int iso_clone_mgtd_mem(char *in, char **out, size_t size); /** Convert a text into a number of type double and multiply it by unit code [kmgt] (2^10 to 2^40) or [s] (2048) or [d] (512). (Also accepts capital letters.) @param text Input like "42", "223062s", "3m" or "-1g" @param flag Bitfield for control purposes: bit0= return -1 rathern than 0 on failure bit1= if scaled then compute the last byte of the last unit @return The derived value */ off_t iso_scanf_io_size(char *text, int flag); /* ------------------------------------------------------------------------- */ /* To avoid the need to include more system header files */ uint16_t iso_ntohs(uint16_t v); uint16_t iso_htons(uint16_t v); #endif /*LIBISO_UTIL_H_*/ libisofs-1.4.2/libisofs/tree.h0000644000175700017510000000137012326673530013213 00000000000000/* * Copyright (c) 2007 Vreixo Formoso * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ #ifndef LIBISO_IMAGE_TREE_H_ #define LIBISO_IMAGE_TREE_H_ #include "image.h" /** * Recursively add a given directory to the image tree. * * @return * 1 continue, 0 stop, < 0 error */ int iso_add_dir_src_rec(IsoImage *image, IsoDir *parent, IsoFileSource *dir); int iso_tree_get_node_of_block(IsoImage *image, IsoDir *dir, uint32_t block, IsoNode **found, uint32_t *next_above, int flag); #endif /*LIBISO_IMAGE_TREE_H_*/ libisofs-1.4.2/libisofs/buffer.c0000644000175700017510000002266612321161425013521 00000000000000/* * Copyright (c) 2007 Vreixo Formoso * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ /* * Synchronized ring buffer, works with a writer thread and a read thread. * * TODO #00010 : optimize ring buffer * - write/read at the end of buffer requires a second mutex_lock, even if * there's enought space/data at the beginning * - pre-buffer for writes < BLOCK_SIZE * */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif /* Use the copy of the struct burn_source definition in libisofs.h */ #define LIBISOFS_WITHOUT_LIBBURN yes #include "libisofs.h" #include "buffer.h" #include "ecma119.h" #include #include #ifndef MIN # define MIN(a, b) (((a) < (b)) ? (a) : (b)) #endif struct iso_ring_buffer { uint8_t *buf; /* * Max number of bytes in buffer */ size_t cap; /* * Number of bytes available. */ size_t size; /* position for reading and writing, offset from buf */ size_t rpos; size_t wpos; /* * flags to report if read or writer threads ends execution * 0 not finished, 1 finished ok, 2 finish with error */ unsigned int rend :2; unsigned int wend :2; /* just for statistical purposes */ unsigned int times_full; unsigned int times_empty; pthread_mutex_t mutex; pthread_cond_t empty; pthread_cond_t full; }; /** * Create a new buffer. * * The created buffer should be freed with iso_ring_buffer_free() * * @param size * Number of blocks in buffer. You should supply a number >= 32, otherwise * size will be ignored and 32 will be used by default, which leads to a * 64 KiB buffer. * @return * 1 success, < 0 error */ int iso_ring_buffer_new(size_t size, IsoRingBuffer **rbuf) { IsoRingBuffer *buffer; if (rbuf == NULL) { return ISO_NULL_POINTER; } buffer = malloc(sizeof(IsoRingBuffer)); if (buffer == NULL) { return ISO_OUT_OF_MEM; } buffer->cap = (size > 32 ? size : 32) * BLOCK_SIZE; buffer->buf = malloc(buffer->cap); if (buffer->buf == NULL) { free(buffer); return ISO_OUT_OF_MEM; } buffer->size = 0; buffer->wpos = 0; buffer->rpos = 0; buffer->times_full = 0; buffer->times_empty = 0; buffer->rend = buffer->wend = 0; /* init mutex and waiting queues */ pthread_mutex_init(&buffer->mutex, NULL); pthread_cond_init(&buffer->empty, NULL); pthread_cond_init(&buffer->full, NULL); *rbuf = buffer; return ISO_SUCCESS; } void iso_ring_buffer_free(IsoRingBuffer *buf) { if (buf == NULL) { return; } free(buf->buf); pthread_mutex_destroy(&buf->mutex); pthread_cond_destroy(&buf->empty); pthread_cond_destroy(&buf->full); free(buf); } /** * Write count bytes into buffer. It blocks until all bytes where written or * reader close the buffer. * * @param buf * the buffer * @param data * pointer to a memory region of at least coun bytes, from which data * will be read. * @param * Number of bytes to write * @return * 1 succes, 0 read finished, < 0 error */ int iso_ring_buffer_write(IsoRingBuffer *buf, uint8_t *data, size_t count) { size_t len; size_t bytes_write = 0; if (buf == NULL || data == NULL) { return ISO_NULL_POINTER; } while (bytes_write < count) { pthread_mutex_lock(&buf->mutex); while (buf->size == buf->cap) { /* * Note. There's only a writer, so we have no race conditions. * Thus, the while(buf->size == buf->cap) is used here * only to propertly detect the reader has been cancelled */ if (buf->rend) { /* the read procces has been finished */ pthread_mutex_unlock(&buf->mutex); return 0; } buf->times_full++; /* wait until space available */ pthread_cond_wait(&buf->full, &buf->mutex); } len = MIN(count - bytes_write, buf->cap - buf->size); if (buf->wpos + len > buf->cap) { len = buf->cap - buf->wpos; } memcpy(buf->buf + buf->wpos, data + bytes_write, len); buf->wpos = (buf->wpos + len) % (buf->cap); bytes_write += len; buf->size += len; /* wake up reader */ pthread_cond_signal(&buf->empty); pthread_mutex_unlock(&buf->mutex); } return ISO_SUCCESS; } /** * Read count bytes from the buffer into dest. It blocks until the desired * bytes has been read. If the writer finishes before outputting enought * bytes, 0 (EOF) is returned, the number of bytes already read remains * unknown. * * @return * 1 success, 0 EOF, < 0 error */ int iso_ring_buffer_read(IsoRingBuffer *buf, uint8_t *dest, size_t count) { size_t len; size_t bytes_read = 0; if (buf == NULL || dest == NULL) { return ISO_NULL_POINTER; } while (bytes_read < count) { pthread_mutex_lock(&buf->mutex); while (buf->size == 0) { /* * Note. There's only a reader, so we have no race conditions. * Thus, the while(buf->size == 0) is used here just to ensure * a reader detects the EOF propertly if the writer has been * canceled while the reader was waiting */ if (buf->wend) { /* the writer procces has been finished */ pthread_mutex_unlock(&buf->mutex); return 0; /* EOF */ } buf->times_empty++; /* wait until data available */ pthread_cond_wait(&buf->empty, &buf->mutex); } len = MIN(count - bytes_read, buf->size); if (buf->rpos + len > buf->cap) { len = buf->cap - buf->rpos; } memcpy(dest + bytes_read, buf->buf + buf->rpos, len); buf->rpos = (buf->rpos + len) % (buf->cap); bytes_read += len; buf->size -= len; /* wake up the writer */ pthread_cond_signal(&buf->full); pthread_mutex_unlock(&buf->mutex); } return ISO_SUCCESS; } void iso_ring_buffer_writer_close(IsoRingBuffer *buf, int error) { pthread_mutex_lock(&buf->mutex); buf->wend = error ? 2 : 1; /* ensure no reader is waiting */ pthread_cond_signal(&buf->empty); pthread_mutex_unlock(&buf->mutex); } void iso_ring_buffer_reader_close(IsoRingBuffer *buf, int error) { pthread_mutex_lock(&buf->mutex); if (buf->rend) { /* reader already closed */ pthread_mutex_unlock(&buf->mutex); return; } buf->rend = error ? 2 : 1; /* ensure no writer is waiting */ pthread_cond_signal(&buf->full); pthread_mutex_unlock(&buf->mutex); } /** * Get the times the buffer was full. */ unsigned int iso_ring_buffer_get_times_full(IsoRingBuffer *buf) { return buf->times_full; } /** * Get the times the buffer was empty. */ unsigned int iso_ring_buffer_get_times_empty(IsoRingBuffer *buf) { return buf->times_empty; } /** Internal via buffer.h * * Get the status of a ring buffer. * * @param buf * The ring buffer object to inquire * @param size * Will be filled with the total size of the buffer, in bytes * @param free_bytes * Will be filled with the bytes currently available in buffer * @return * < 0 error, > 0 state: * 1="active" : input and consumption are active * 2="ending" : input has ended without error * 3="failing" : input had error and ended, * 5="abandoned" : consumption has ended prematurely * 6="ended" : consumption has ended without input error * 7="aborted" : consumption has ended after input error */ int iso_ring_buffer_get_buf_status(IsoRingBuffer *buf, size_t *size, size_t *free_bytes) { int ret; if (buf == NULL) { return ISO_NULL_POINTER; } /* get mutex */ pthread_mutex_lock(&buf->mutex); if (size) { *size = buf->cap; } if (free_bytes) { *free_bytes = buf->cap - buf->size; } ret = (buf->rend ? 4 : 0) + (buf->wend + 1); pthread_mutex_unlock(&buf->mutex); return ret; } /** API via libisofs.h * * Get the status of the buffer used by a burn_source. * * @param b * A burn_source previously obtained with * iso_image_create_burn_source(). * @param size * Will be filled with the total size of the buffer, in bytes * @param free_bytes * Will be filled with the bytes currently available in buffer * @return * < 0 error, > 0 state: * 1="active" : input and consumption are active * 2="ending" : input has ended without error * 3="failing" : input had error and ended, * 5="abandoned" : consumption has ended prematurely * 6="ended" : consumption has ended without input error * 7="aborted" : consumption has ended after input error */ int iso_ring_buffer_get_status(struct burn_source *b, size_t *size, size_t *free_bytes) { int ret; IsoRingBuffer *buf; if (b == NULL) { return ISO_NULL_POINTER; } buf = ((Ecma119Image*)(b->data))->buffer; ret = iso_ring_buffer_get_buf_status(buf, size, free_bytes); return ret; } libisofs-1.4.2/libisofs/writer.h0000644000175700017510000000203712321161425013557 00000000000000/* * Copyright (c) 2007 Vreixo Formoso * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ #ifndef LIBISO_IMAGE_WRITER_H_ #define LIBISO_IMAGE_WRITER_H_ #include "ecma119.h" struct Iso_Image_Writer { /** * */ int (*compute_data_blocks)(IsoImageWriter *writer); int (*write_vol_desc)(IsoImageWriter *writer); int (*write_data)(IsoImageWriter *writer); int (*free_data)(IsoImageWriter *writer); void *data; Ecma119Image *target; }; /** * This is the function all Writers shoudl call to write data to image. * Currently, it is just a wrapper for write(2) Unix system call. * * It is implemented in ecma119.c * * @return * 1 on sucess, < 0 error */ int iso_write(Ecma119Image *target, void *buf, size_t count); int ecma119_writer_create(Ecma119Image *target); #endif /*LIBISO_IMAGE_WRITER_H_*/ libisofs-1.4.2/libisofs/hfsplus_decompose.c0000644000175700017510000007340512321161425015767 00000000000000/* * Copyright (c) 2012 Vladimir Serbinenko * Copyright (c) 2012 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif #include #include "hfsplus.h" /* Based on tn1150 (HFS+ format specification) */ /* This encodes a matrix of page and character, with a number of HFSPLUS_MAX_DECOMPOSE_LEN + 1 elements of 16 bit each. Initially the matrix is filled with zeros. 1: The first element is the page number. If it is equal or lower than the previous one, then the matrix is done. 2: The next element is the character number If it is equal or lower than the previous one, the page is done. Goto 1. 3: The next elements are matrix elements. If element 0 is encountered, then the character is done. Goto 2. */ static const uint16_t decompose_page_data[] = { /* page00 */ 0x00, 0xc0, 0x0041, 0x0300, 0, 0xc1, 0x0041, 0x0301, 0, 0xc2, 0x0041, 0x0302, 0, 0xc3, 0x0041, 0x0303, 0, 0xc4, 0x0041, 0x0308, 0, 0xc5, 0x0041, 0x030A, 0, 0xc7, 0x0043, 0x0327, 0, 0xc8, 0x0045, 0x0300, 0, 0xc9, 0x0045, 0x0301, 0, 0xca, 0x0045, 0x0302, 0, 0xcb, 0x0045, 0x0308, 0, 0xcc, 0x0049, 0x0300, 0, 0xcd, 0x0049, 0x0301, 0, 0xce, 0x0049, 0x0302, 0, 0xcf, 0x0049, 0x0308, 0, 0xd1, 0x004E, 0x0303, 0, 0xd2, 0x004F, 0x0300, 0, 0xd3, 0x004F, 0x0301, 0, 0xd4, 0x004F, 0x0302, 0, 0xd5, 0x004F, 0x0303, 0, 0xd6, 0x004F, 0x0308, 0, 0xd9, 0x0055, 0x0300, 0, 0xda, 0x0055, 0x0301, 0, 0xdb, 0x0055, 0x0302, 0, 0xdc, 0x0055, 0x0308, 0, 0xdd, 0x0059, 0x0301, 0, 0xe0, 0x0061, 0x0300, 0, 0xe1, 0x0061, 0x0301, 0, 0xe2, 0x0061, 0x0302, 0, 0xe3, 0x0061, 0x0303, 0, 0xe4, 0x0061, 0x0308, 0, 0xe5, 0x0061, 0x030A, 0, 0xe7, 0x0063, 0x0327, 0, 0xe8, 0x0065, 0x0300, 0, 0xe9, 0x0065, 0x0301, 0, 0xea, 0x0065, 0x0302, 0, 0xeb, 0x0065, 0x0308, 0, 0xec, 0x0069, 0x0300, 0, 0xed, 0x0069, 0x0301, 0, 0xee, 0x0069, 0x0302, 0, 0xef, 0x0069, 0x0308, 0, 0xf1, 0x006E, 0x0303, 0, 0xf2, 0x006F, 0x0300, 0, 0xf3, 0x006F, 0x0301, 0, 0xf4, 0x006F, 0x0302, 0, 0xf5, 0x006F, 0x0303, 0, 0xf6, 0x006F, 0x0308, 0, 0xf9, 0x0075, 0x0300, 0, 0xfa, 0x0075, 0x0301, 0, 0xfb, 0x0075, 0x0302, 0, 0xfc, 0x0075, 0x0308, 0, 0xfd, 0x0079, 0x0301, 0, 0xff, 0x0079, 0x0308, 0, 0x00, /* page01 */ 0x01, 0x00, 0x0041, 0x0304, 0, 0x01, 0x0061, 0x0304, 0, 0x02, 0x0041, 0x0306, 0, 0x03, 0x0061, 0x0306, 0, 0x04, 0x0041, 0x0328, 0, 0x05, 0x0061, 0x0328, 0, 0x06, 0x0043, 0x0301, 0, 0x07, 0x0063, 0x0301, 0, 0x08, 0x0043, 0x0302, 0, 0x09, 0x0063, 0x0302, 0, 0x0a, 0x0043, 0x0307, 0, 0x0b, 0x0063, 0x0307, 0, 0x0c, 0x0043, 0x030C, 0, 0x0d, 0x0063, 0x030C, 0, 0x0e, 0x0044, 0x030C, 0, 0x0f, 0x0064, 0x030C, 0, 0x12, 0x0045, 0x0304, 0, 0x13, 0x0065, 0x0304, 0, 0x14, 0x0045, 0x0306, 0, 0x15, 0x0065, 0x0306, 0, 0x16, 0x0045, 0x0307, 0, 0x17, 0x0065, 0x0307, 0, 0x18, 0x0045, 0x0328, 0, 0x19, 0x0065, 0x0328, 0, 0x1a, 0x0045, 0x030C, 0, 0x1b, 0x0065, 0x030C, 0, 0x1c, 0x0047, 0x0302, 0, 0x1d, 0x0067, 0x0302, 0, 0x1e, 0x0047, 0x0306, 0, 0x1f, 0x0067, 0x0306, 0, 0x20, 0x0047, 0x0307, 0, 0x21, 0x0067, 0x0307, 0, 0x22, 0x0047, 0x0327, 0, 0x23, 0x0067, 0x0327, 0, 0x24, 0x0048, 0x0302, 0, 0x25, 0x0068, 0x0302, 0, 0x28, 0x0049, 0x0303, 0, 0x29, 0x0069, 0x0303, 0, 0x2a, 0x0049, 0x0304, 0, 0x2b, 0x0069, 0x0304, 0, 0x2c, 0x0049, 0x0306, 0, 0x2d, 0x0069, 0x0306, 0, 0x2e, 0x0049, 0x0328, 0, 0x2f, 0x0069, 0x0328, 0, 0x30, 0x0049, 0x0307, 0, 0x34, 0x004A, 0x0302, 0, 0x35, 0x006A, 0x0302, 0, 0x36, 0x004B, 0x0327, 0, 0x37, 0x006B, 0x0327, 0, 0x39, 0x004C, 0x0301, 0, 0x3a, 0x006C, 0x0301, 0, 0x3b, 0x004C, 0x0327, 0, 0x3c, 0x006C, 0x0327, 0, 0x3d, 0x004C, 0x030C, 0, 0x3e, 0x006C, 0x030C, 0, 0x43, 0x004E, 0x0301, 0, 0x44, 0x006E, 0x0301, 0, 0x45, 0x004E, 0x0327, 0, 0x46, 0x006E, 0x0327, 0, 0x47, 0x004E, 0x030C, 0, 0x48, 0x006E, 0x030C, 0, 0x4c, 0x004F, 0x0304, 0, 0x4d, 0x006F, 0x0304, 0, 0x4e, 0x004F, 0x0306, 0, 0x4f, 0x006F, 0x0306, 0, 0x50, 0x004F, 0x030B, 0, 0x51, 0x006F, 0x030B, 0, 0x54, 0x0052, 0x0301, 0, 0x55, 0x0072, 0x0301, 0, 0x56, 0x0052, 0x0327, 0, 0x57, 0x0072, 0x0327, 0, 0x58, 0x0052, 0x030C, 0, 0x59, 0x0072, 0x030C, 0, 0x5a, 0x0053, 0x0301, 0, 0x5b, 0x0073, 0x0301, 0, 0x5c, 0x0053, 0x0302, 0, 0x5d, 0x0073, 0x0302, 0, 0x5e, 0x0053, 0x0327, 0, 0x5f, 0x0073, 0x0327, 0, 0x60, 0x0053, 0x030C, 0, 0x61, 0x0073, 0x030C, 0, 0x62, 0x0054, 0x0327, 0, 0x63, 0x0074, 0x0327, 0, 0x64, 0x0054, 0x030C, 0, 0x65, 0x0074, 0x030C, 0, 0x68, 0x0055, 0x0303, 0, 0x69, 0x0075, 0x0303, 0, 0x6a, 0x0055, 0x0304, 0, 0x6b, 0x0075, 0x0304, 0, 0x6c, 0x0055, 0x0306, 0, 0x6d, 0x0075, 0x0306, 0, 0x6e, 0x0055, 0x030A, 0, 0x6f, 0x0075, 0x030A, 0, 0x70, 0x0055, 0x030B, 0, 0x71, 0x0075, 0x030B, 0, 0x72, 0x0055, 0x0328, 0, 0x73, 0x0075, 0x0328, 0, 0x74, 0x0057, 0x0302, 0, 0x75, 0x0077, 0x0302, 0, 0x76, 0x0059, 0x0302, 0, 0x77, 0x0079, 0x0302, 0, 0x78, 0x0059, 0x0308, 0, 0x79, 0x005A, 0x0301, 0, 0x7a, 0x007A, 0x0301, 0, 0x7b, 0x005A, 0x0307, 0, 0x7c, 0x007A, 0x0307, 0, 0x7d, 0x005A, 0x030C, 0, 0x7e, 0x007A, 0x030C, 0, 0xa0, 0x004F, 0x031B, 0, 0xa1, 0x006F, 0x031B, 0, 0xaf, 0x0055, 0x031B, 0, 0xb0, 0x0075, 0x031B, 0, 0xcd, 0x0041, 0x030C, 0, 0xce, 0x0061, 0x030C, 0, 0xcf, 0x0049, 0x030C, 0, 0xd0, 0x0069, 0x030C, 0, 0xd1, 0x004F, 0x030C, 0, 0xd2, 0x006F, 0x030C, 0, 0xd3, 0x0055, 0x030C, 0, 0xd4, 0x0075, 0x030C, 0, 0xd5, 0x0055, 0x0308, 0x0304, 0, 0xd6, 0x0075, 0x0308, 0x0304, 0, 0xd7, 0x0055, 0x0308, 0x0301, 0, 0xd8, 0x0075, 0x0308, 0x0301, 0, 0xd9, 0x0055, 0x0308, 0x030C, 0, 0xda, 0x0075, 0x0308, 0x030C, 0, 0xdb, 0x0055, 0x0308, 0x0300, 0, 0xdc, 0x0075, 0x0308, 0x0300, 0, 0xde, 0x0041, 0x0308, 0x0304, 0, 0xdf, 0x0061, 0x0308, 0x0304, 0, 0xe0, 0x0041, 0x0307, 0x0304, 0, 0xe1, 0x0061, 0x0307, 0x0304, 0, 0xe2, 0x00C6, 0x0304, 0, 0xe3, 0x00E6, 0x0304, 0, 0xe6, 0x0047, 0x030C, 0, 0xe7, 0x0067, 0x030C, 0, 0xe8, 0x004B, 0x030C, 0, 0xe9, 0x006B, 0x030C, 0, 0xea, 0x004F, 0x0328, 0, 0xeb, 0x006F, 0x0328, 0, 0xec, 0x004F, 0x0328, 0x0304, 0, 0xed, 0x006F, 0x0328, 0x0304, 0, 0xee, 0x01B7, 0x030C, 0, 0xef, 0x0292, 0x030C, 0, 0xf0, 0x006A, 0x030C, 0, 0xf4, 0x0047, 0x0301, 0, 0xf5, 0x0067, 0x0301, 0, 0xfa, 0x0041, 0x030A, 0x0301, 0, 0xfb, 0x0061, 0x030A, 0x0301, 0, 0xfc, 0x00C6, 0x0301, 0, 0xfd, 0x00E6, 0x0301, 0, 0xfe, 0x00D8, 0x0301, 0, 0xff, 0x00F8, 0x0301, 0, 0x00, /* page02 */ 0x02, 0x00, 0x0041, 0x030F, 0, 0x01, 0x0061, 0x030F, 0, 0x02, 0x0041, 0x0311, 0, 0x03, 0x0061, 0x0311, 0, 0x04, 0x0045, 0x030F, 0, 0x05, 0x0065, 0x030F, 0, 0x06, 0x0045, 0x0311, 0, 0x07, 0x0065, 0x0311, 0, 0x08, 0x0049, 0x030F, 0, 0x09, 0x0069, 0x030F, 0, 0x0a, 0x0049, 0x0311, 0, 0x0b, 0x0069, 0x0311, 0, 0x0c, 0x004F, 0x030F, 0, 0x0d, 0x006F, 0x030F, 0, 0x0e, 0x004F, 0x0311, 0, 0x0f, 0x006F, 0x0311, 0, 0x10, 0x0052, 0x030F, 0, 0x11, 0x0072, 0x030F, 0, 0x12, 0x0052, 0x0311, 0, 0x13, 0x0072, 0x0311, 0, 0x14, 0x0055, 0x030F, 0, 0x15, 0x0075, 0x030F, 0, 0x16, 0x0055, 0x0311, 0, 0x17, 0x0075, 0x0311, 0, 0x00, /* page03 */ 0x03, 0x10, 0x0306, 0x0307, 0, 0x40, 0x0300, 0, 0x41, 0x0301, 0, 0x43, 0x0313, 0, 0x44, 0x0308, 0x030D, 0, 0x74, 0x02B9, 0, 0x7e, 0x003B, 0, 0x85, 0x00A8, 0x030D, 0, 0x86, 0x0391, 0x030D, 0, 0x87, 0x00B7, 0, 0x88, 0x0395, 0x030D, 0, 0x89, 0x0397, 0x030D, 0, 0x8a, 0x0399, 0x030D, 0, 0x8c, 0x039F, 0x030D, 0, 0x8e, 0x03A5, 0x030D, 0, 0x8f, 0x03A9, 0x030D, 0, 0x90, 0x03B9, 0x0308, 0x030D, 0, 0xaa, 0x0399, 0x0308, 0, 0xab, 0x03A5, 0x0308, 0, 0xac, 0x03B1, 0x030D, 0, 0xad, 0x03B5, 0x030D, 0, 0xae, 0x03B7, 0x030D, 0, 0xaf, 0x03B9, 0x030D, 0, 0xb0, 0x03C5, 0x0308, 0x030D, 0, 0xca, 0x03B9, 0x0308, 0, 0xcb, 0x03C5, 0x0308, 0, 0xcc, 0x03BF, 0x030D, 0, 0xcd, 0x03C5, 0x030D, 0, 0xce, 0x03C9, 0x030D, 0, 0xd3, 0x03D2, 0x030D, 0, 0xd4, 0x03D2, 0x0308, 0, 0x00, /* page04 */ 0x04, 0x01, 0x0415, 0x0308, 0, 0x03, 0x0413, 0x0301, 0, 0x07, 0x0406, 0x0308, 0, 0x0c, 0x041A, 0x0301, 0, 0x0e, 0x0423, 0x0306, 0, 0x19, 0x0418, 0x0306, 0, 0x39, 0x0438, 0x0306, 0, 0x51, 0x0435, 0x0308, 0, 0x53, 0x0433, 0x0301, 0, 0x57, 0x0456, 0x0308, 0, 0x5c, 0x043A, 0x0301, 0, 0x5e, 0x0443, 0x0306, 0, 0x76, 0x0474, 0x030F, 0, 0x77, 0x0475, 0x030F, 0, 0xc1, 0x0416, 0x0306, 0, 0xc2, 0x0436, 0x0306, 0, 0xd0, 0x0410, 0x0306, 0, 0xd1, 0x0430, 0x0306, 0, 0xd2, 0x0410, 0x0308, 0, 0xd3, 0x0430, 0x0308, 0, 0xd4, 0x00C6, 0, 0xd5, 0x00E6, 0, 0xd6, 0x0415, 0x0306, 0, 0xd7, 0x0435, 0x0306, 0, 0xd8, 0x018F, 0, 0xd9, 0x0259, 0, 0xda, 0x018F, 0x0308, 0, 0xdb, 0x0259, 0x0308, 0, 0xdc, 0x0416, 0x0308, 0, 0xdd, 0x0436, 0x0308, 0, 0xde, 0x0417, 0x0308, 0, 0xdf, 0x0437, 0x0308, 0, 0xe0, 0x01B7, 0, 0xe1, 0x0292, 0, 0xe2, 0x0418, 0x0304, 0, 0xe3, 0x0438, 0x0304, 0, 0xe4, 0x0418, 0x0308, 0, 0xe5, 0x0438, 0x0308, 0, 0xe6, 0x041E, 0x0308, 0, 0xe7, 0x043E, 0x0308, 0, 0xe8, 0x019F, 0, 0xe9, 0x0275, 0, 0xea, 0x019F, 0x0308, 0, 0xeb, 0x0275, 0x0308, 0, 0xee, 0x0423, 0x0304, 0, 0xef, 0x0443, 0x0304, 0, 0xf0, 0x0423, 0x0308, 0, 0xf1, 0x0443, 0x0308, 0, 0xf2, 0x0423, 0x030B, 0, 0xf3, 0x0443, 0x030B, 0, 0xf4, 0x0427, 0x0308, 0, 0xf5, 0x0447, 0x0308, 0, 0xf8, 0x042B, 0x0308, 0, 0xf9, 0x044B, 0x0308, 0, 0x00, /* page09 */ 0x09, 0x29, 0x0928, 0x093C, 0, 0x31, 0x0930, 0x093C, 0, 0x34, 0x0933, 0x093C, 0, 0x58, 0x0915, 0x093C, 0, 0x59, 0x0916, 0x093C, 0, 0x5a, 0x0917, 0x093C, 0, 0x5b, 0x091C, 0x093C, 0, 0x5c, 0x0921, 0x093C, 0, 0x5d, 0x0922, 0x093C, 0, 0x5e, 0x092B, 0x093C, 0, 0x5f, 0x092F, 0x093C, 0, 0xb0, 0x09AC, 0x09BC, 0, 0xcb, 0x09C7, 0x09BE, 0, 0xcc, 0x09C7, 0x09D7, 0, 0xdc, 0x09A1, 0x09BC, 0, 0xdd, 0x09A2, 0x09BC, 0, 0xdf, 0x09AF, 0x09BC, 0, 0x00, /* page0a */ 0x0a, 0x59, 0x0A16, 0x0A3C, 0, 0x5a, 0x0A17, 0x0A3C, 0, 0x5b, 0x0A1C, 0x0A3C, 0, 0x5c, 0x0A21, 0x0A3C, 0, 0x5e, 0x0A2B, 0x0A3C, 0, 0x00, /* page0b */ 0x0b, 0x48, 0x0B47, 0x0B56, 0, 0x4b, 0x0B47, 0x0B3E, 0, 0x4c, 0x0B47, 0x0B57, 0, 0x5c, 0x0B21, 0x0B3C, 0, 0x5d, 0x0B22, 0x0B3C, 0, 0x5f, 0x0B2F, 0x0B3C, 0, 0x94, 0x0B92, 0x0BD7, 0, 0xca, 0x0BC6, 0x0BBE, 0, 0xcb, 0x0BC7, 0x0BBE, 0, 0xcc, 0x0BC6, 0x0BD7, 0, 0x00, /* page0c */ 0x0c, 0x48, 0x0C46, 0x0C56, 0, 0xc0, 0x0CBF, 0x0CD5, 0, 0xc7, 0x0CC6, 0x0CD5, 0, 0xc8, 0x0CC6, 0x0CD6, 0, 0xca, 0x0CC6, 0x0CC2, 0, 0xcb, 0x0CC6, 0x0CC2, 0x0CD5, 0, 0x00, /* page0d */ 0x0d, 0x4a, 0x0D46, 0x0D3E, 0, 0x4b, 0x0D47, 0x0D3E, 0, 0x4c, 0x0D46, 0x0D57, 0, 0x00, /* page0e */ 0x0e, 0x33, 0x0E4D, 0x0E32, 0, 0xb3, 0x0ECD, 0x0EB2, 0, 0x00, /* page0f */ 0x0f, 0x43, 0x0F42, 0x0FB7, 0, 0x4d, 0x0F4C, 0x0FB7, 0, 0x52, 0x0F51, 0x0FB7, 0, 0x57, 0x0F56, 0x0FB7, 0, 0x5c, 0x0F5B, 0x0FB7, 0, 0x69, 0x0F40, 0x0FB5, 0, 0x73, 0x0F72, 0x0F71, 0, 0x75, 0x0F74, 0x0F71, 0, 0x76, 0x0FB2, 0x0F80, 0, 0x77, 0x0FB2, 0x0F80, 0x0F71, 0, 0x78, 0x0FB3, 0x0F80, 0, 0x79, 0x0FB3, 0x0F80, 0x0F71, 0, 0x81, 0x0F80, 0x0F71, 0, 0x93, 0x0F92, 0x0FB7, 0, 0x9d, 0x0F9C, 0x0FB7, 0, 0xa2, 0x0FA1, 0x0FB7, 0, 0xa7, 0x0FA6, 0x0FB7, 0, 0xac, 0x0FAB, 0x0FB7, 0, 0xb9, 0x0F90, 0x0FB5, 0, 0x00, /* page1e */ 0x1e, 0x00, 0x0041, 0x0325, 0, 0x01, 0x0061, 0x0325, 0, 0x02, 0x0042, 0x0307, 0, 0x03, 0x0062, 0x0307, 0, 0x04, 0x0042, 0x0323, 0, 0x05, 0x0062, 0x0323, 0, 0x06, 0x0042, 0x0331, 0, 0x07, 0x0062, 0x0331, 0, 0x08, 0x0043, 0x0327, 0x0301, 0, 0x09, 0x0063, 0x0327, 0x0301, 0, 0x0a, 0x0044, 0x0307, 0, 0x0b, 0x0064, 0x0307, 0, 0x0c, 0x0044, 0x0323, 0, 0x0d, 0x0064, 0x0323, 0, 0x0e, 0x0044, 0x0331, 0, 0x0f, 0x0064, 0x0331, 0, 0x10, 0x0044, 0x0327, 0, 0x11, 0x0064, 0x0327, 0, 0x12, 0x0044, 0x032D, 0, 0x13, 0x0064, 0x032D, 0, 0x14, 0x0045, 0x0304, 0x0300, 0, 0x15, 0x0065, 0x0304, 0x0300, 0, 0x16, 0x0045, 0x0304, 0x0301, 0, 0x17, 0x0065, 0x0304, 0x0301, 0, 0x18, 0x0045, 0x032D, 0, 0x19, 0x0065, 0x032D, 0, 0x1a, 0x0045, 0x0330, 0, 0x1b, 0x0065, 0x0330, 0, 0x1c, 0x0045, 0x0327, 0x0306, 0, 0x1d, 0x0065, 0x0327, 0x0306, 0, 0x1e, 0x0046, 0x0307, 0, 0x1f, 0x0066, 0x0307, 0, 0x20, 0x0047, 0x0304, 0, 0x21, 0x0067, 0x0304, 0, 0x22, 0x0048, 0x0307, 0, 0x23, 0x0068, 0x0307, 0, 0x24, 0x0048, 0x0323, 0, 0x25, 0x0068, 0x0323, 0, 0x26, 0x0048, 0x0308, 0, 0x27, 0x0068, 0x0308, 0, 0x28, 0x0048, 0x0327, 0, 0x29, 0x0068, 0x0327, 0, 0x2a, 0x0048, 0x032E, 0, 0x2b, 0x0068, 0x032E, 0, 0x2c, 0x0049, 0x0330, 0, 0x2d, 0x0069, 0x0330, 0, 0x2e, 0x0049, 0x0308, 0x0301, 0, 0x2f, 0x0069, 0x0308, 0x0301, 0, 0x30, 0x004B, 0x0301, 0, 0x31, 0x006B, 0x0301, 0, 0x32, 0x004B, 0x0323, 0, 0x33, 0x006B, 0x0323, 0, 0x34, 0x004B, 0x0331, 0, 0x35, 0x006B, 0x0331, 0, 0x36, 0x004C, 0x0323, 0, 0x37, 0x006C, 0x0323, 0, 0x38, 0x004C, 0x0323, 0x0304, 0, 0x39, 0x006C, 0x0323, 0x0304, 0, 0x3a, 0x004C, 0x0331, 0, 0x3b, 0x006C, 0x0331, 0, 0x3c, 0x004C, 0x032D, 0, 0x3d, 0x006C, 0x032D, 0, 0x3e, 0x004D, 0x0301, 0, 0x3f, 0x006D, 0x0301, 0, 0x40, 0x004D, 0x0307, 0, 0x41, 0x006D, 0x0307, 0, 0x42, 0x004D, 0x0323, 0, 0x43, 0x006D, 0x0323, 0, 0x44, 0x004E, 0x0307, 0, 0x45, 0x006E, 0x0307, 0, 0x46, 0x004E, 0x0323, 0, 0x47, 0x006E, 0x0323, 0, 0x48, 0x004E, 0x0331, 0, 0x49, 0x006E, 0x0331, 0, 0x4a, 0x004E, 0x032D, 0, 0x4b, 0x006E, 0x032D, 0, 0x4c, 0x004F, 0x0303, 0x0301, 0, 0x4d, 0x006F, 0x0303, 0x0301, 0, 0x4e, 0x004F, 0x0303, 0x0308, 0, 0x4f, 0x006F, 0x0303, 0x0308, 0, 0x50, 0x004F, 0x0304, 0x0300, 0, 0x51, 0x006F, 0x0304, 0x0300, 0, 0x52, 0x004F, 0x0304, 0x0301, 0, 0x53, 0x006F, 0x0304, 0x0301, 0, 0x54, 0x0050, 0x0301, 0, 0x55, 0x0070, 0x0301, 0, 0x56, 0x0050, 0x0307, 0, 0x57, 0x0070, 0x0307, 0, 0x58, 0x0052, 0x0307, 0, 0x59, 0x0072, 0x0307, 0, 0x5a, 0x0052, 0x0323, 0, 0x5b, 0x0072, 0x0323, 0, 0x5c, 0x0052, 0x0323, 0x0304, 0, 0x5d, 0x0072, 0x0323, 0x0304, 0, 0x5e, 0x0052, 0x0331, 0, 0x5f, 0x0072, 0x0331, 0, 0x60, 0x0053, 0x0307, 0, 0x61, 0x0073, 0x0307, 0, 0x62, 0x0053, 0x0323, 0, 0x63, 0x0073, 0x0323, 0, 0x64, 0x0053, 0x0301, 0x0307, 0, 0x65, 0x0073, 0x0301, 0x0307, 0, 0x66, 0x0053, 0x030C, 0x0307, 0, 0x67, 0x0073, 0x030C, 0x0307, 0, 0x68, 0x0053, 0x0323, 0x0307, 0, 0x69, 0x0073, 0x0323, 0x0307, 0, 0x6a, 0x0054, 0x0307, 0, 0x6b, 0x0074, 0x0307, 0, 0x6c, 0x0054, 0x0323, 0, 0x6d, 0x0074, 0x0323, 0, 0x6e, 0x0054, 0x0331, 0, 0x6f, 0x0074, 0x0331, 0, 0x70, 0x0054, 0x032D, 0, 0x71, 0x0074, 0x032D, 0, 0x72, 0x0055, 0x0324, 0, 0x73, 0x0075, 0x0324, 0, 0x74, 0x0055, 0x0330, 0, 0x75, 0x0075, 0x0330, 0, 0x76, 0x0055, 0x032D, 0, 0x77, 0x0075, 0x032D, 0, 0x78, 0x0055, 0x0303, 0x0301, 0, 0x79, 0x0075, 0x0303, 0x0301, 0, 0x7a, 0x0055, 0x0304, 0x0308, 0, 0x7b, 0x0075, 0x0304, 0x0308, 0, 0x7c, 0x0056, 0x0303, 0, 0x7d, 0x0076, 0x0303, 0, 0x7e, 0x0056, 0x0323, 0, 0x7f, 0x0076, 0x0323, 0, 0x80, 0x0057, 0x0300, 0, 0x81, 0x0077, 0x0300, 0, 0x82, 0x0057, 0x0301, 0, 0x83, 0x0077, 0x0301, 0, 0x84, 0x0057, 0x0308, 0, 0x85, 0x0077, 0x0308, 0, 0x86, 0x0057, 0x0307, 0, 0x87, 0x0077, 0x0307, 0, 0x88, 0x0057, 0x0323, 0, 0x89, 0x0077, 0x0323, 0, 0x8a, 0x0058, 0x0307, 0, 0x8b, 0x0078, 0x0307, 0, 0x8c, 0x0058, 0x0308, 0, 0x8d, 0x0078, 0x0308, 0, 0x8e, 0x0059, 0x0307, 0, 0x8f, 0x0079, 0x0307, 0, 0x90, 0x005A, 0x0302, 0, 0x91, 0x007A, 0x0302, 0, 0x92, 0x005A, 0x0323, 0, 0x93, 0x007A, 0x0323, 0, 0x94, 0x005A, 0x0331, 0, 0x95, 0x007A, 0x0331, 0, 0x96, 0x0068, 0x0331, 0, 0x97, 0x0074, 0x0308, 0, 0x98, 0x0077, 0x030A, 0, 0x99, 0x0079, 0x030A, 0, 0x9b, 0x017F, 0x0307, 0, 0xa0, 0x0041, 0x0323, 0, 0xa1, 0x0061, 0x0323, 0, 0xa2, 0x0041, 0x0309, 0, 0xa3, 0x0061, 0x0309, 0, 0xa4, 0x0041, 0x0302, 0x0301, 0, 0xa5, 0x0061, 0x0302, 0x0301, 0, 0xa6, 0x0041, 0x0302, 0x0300, 0, 0xa7, 0x0061, 0x0302, 0x0300, 0, 0xa8, 0x0041, 0x0302, 0x0309, 0, 0xa9, 0x0061, 0x0302, 0x0309, 0, 0xaa, 0x0041, 0x0302, 0x0303, 0, 0xab, 0x0061, 0x0302, 0x0303, 0, 0xac, 0x0041, 0x0323, 0x0302, 0, 0xad, 0x0061, 0x0323, 0x0302, 0, 0xae, 0x0041, 0x0306, 0x0301, 0, 0xaf, 0x0061, 0x0306, 0x0301, 0, 0xb0, 0x0041, 0x0306, 0x0300, 0, 0xb1, 0x0061, 0x0306, 0x0300, 0, 0xb2, 0x0041, 0x0306, 0x0309, 0, 0xb3, 0x0061, 0x0306, 0x0309, 0, 0xb4, 0x0041, 0x0306, 0x0303, 0, 0xb5, 0x0061, 0x0306, 0x0303, 0, 0xb6, 0x0041, 0x0323, 0x0306, 0, 0xb7, 0x0061, 0x0323, 0x0306, 0, 0xb8, 0x0045, 0x0323, 0, 0xb9, 0x0065, 0x0323, 0, 0xba, 0x0045, 0x0309, 0, 0xbb, 0x0065, 0x0309, 0, 0xbc, 0x0045, 0x0303, 0, 0xbd, 0x0065, 0x0303, 0, 0xbe, 0x0045, 0x0302, 0x0301, 0, 0xbf, 0x0065, 0x0302, 0x0301, 0, 0xc0, 0x0045, 0x0302, 0x0300, 0, 0xc1, 0x0065, 0x0302, 0x0300, 0, 0xc2, 0x0045, 0x0302, 0x0309, 0, 0xc3, 0x0065, 0x0302, 0x0309, 0, 0xc4, 0x0045, 0x0302, 0x0303, 0, 0xc5, 0x0065, 0x0302, 0x0303, 0, 0xc6, 0x0045, 0x0323, 0x0302, 0, 0xc7, 0x0065, 0x0323, 0x0302, 0, 0xc8, 0x0049, 0x0309, 0, 0xc9, 0x0069, 0x0309, 0, 0xca, 0x0049, 0x0323, 0, 0xcb, 0x0069, 0x0323, 0, 0xcc, 0x004F, 0x0323, 0, 0xcd, 0x006F, 0x0323, 0, 0xce, 0x004F, 0x0309, 0, 0xcf, 0x006F, 0x0309, 0, 0xd0, 0x004F, 0x0302, 0x0301, 0, 0xd1, 0x006F, 0x0302, 0x0301, 0, 0xd2, 0x004F, 0x0302, 0x0300, 0, 0xd3, 0x006F, 0x0302, 0x0300, 0, 0xd4, 0x004F, 0x0302, 0x0309, 0, 0xd5, 0x006F, 0x0302, 0x0309, 0, 0xd6, 0x004F, 0x0302, 0x0303, 0, 0xd7, 0x006F, 0x0302, 0x0303, 0, 0xd8, 0x004F, 0x0323, 0x0302, 0, 0xd9, 0x006F, 0x0323, 0x0302, 0, 0xda, 0x004F, 0x031B, 0x0301, 0, 0xdb, 0x006F, 0x031B, 0x0301, 0, 0xdc, 0x004F, 0x031B, 0x0300, 0, 0xdd, 0x006F, 0x031B, 0x0300, 0, 0xde, 0x004F, 0x031B, 0x0309, 0, 0xdf, 0x006F, 0x031B, 0x0309, 0, 0xe0, 0x004F, 0x031B, 0x0303, 0, 0xe1, 0x006F, 0x031B, 0x0303, 0, 0xe2, 0x004F, 0x031B, 0x0323, 0, 0xe3, 0x006F, 0x031B, 0x0323, 0, 0xe4, 0x0055, 0x0323, 0, 0xe5, 0x0075, 0x0323, 0, 0xe6, 0x0055, 0x0309, 0, 0xe7, 0x0075, 0x0309, 0, 0xe8, 0x0055, 0x031B, 0x0301, 0, 0xe9, 0x0075, 0x031B, 0x0301, 0, 0xea, 0x0055, 0x031B, 0x0300, 0, 0xeb, 0x0075, 0x031B, 0x0300, 0, 0xec, 0x0055, 0x031B, 0x0309, 0, 0xed, 0x0075, 0x031B, 0x0309, 0, 0xee, 0x0055, 0x031B, 0x0303, 0, 0xef, 0x0075, 0x031B, 0x0303, 0, 0xf0, 0x0055, 0x031B, 0x0323, 0, 0xf1, 0x0075, 0x031B, 0x0323, 0, 0xf2, 0x0059, 0x0300, 0, 0xf3, 0x0079, 0x0300, 0, 0xf4, 0x0059, 0x0323, 0, 0xf5, 0x0079, 0x0323, 0, 0xf6, 0x0059, 0x0309, 0, 0xf7, 0x0079, 0x0309, 0, 0xf8, 0x0059, 0x0303, 0, 0xf9, 0x0079, 0x0303, 0, 0x00, /* page1f */ 0x1f, 0x00, 0x03B1, 0x0313, 0, 0x01, 0x03B1, 0x0314, 0, 0x02, 0x03B1, 0x0313, 0x0300, 0, 0x03, 0x03B1, 0x0314, 0x0300, 0, 0x04, 0x03B1, 0x0313, 0x0301, 0, 0x05, 0x03B1, 0x0314, 0x0301, 0, 0x06, 0x03B1, 0x0313, 0x0342, 0, 0x07, 0x03B1, 0x0314, 0x0342, 0, 0x08, 0x0391, 0x0313, 0, 0x09, 0x0391, 0x0314, 0, 0x0a, 0x0391, 0x0313, 0x0300, 0, 0x0b, 0x0391, 0x0314, 0x0300, 0, 0x0c, 0x0391, 0x0313, 0x0301, 0, 0x0d, 0x0391, 0x0314, 0x0301, 0, 0x0e, 0x0391, 0x0313, 0x0342, 0, 0x0f, 0x0391, 0x0314, 0x0342, 0, 0x10, 0x03B5, 0x0313, 0, 0x11, 0x03B5, 0x0314, 0, 0x12, 0x03B5, 0x0313, 0x0300, 0, 0x13, 0x03B5, 0x0314, 0x0300, 0, 0x14, 0x03B5, 0x0313, 0x0301, 0, 0x15, 0x03B5, 0x0314, 0x0301, 0, 0x18, 0x0395, 0x0313, 0, 0x19, 0x0395, 0x0314, 0, 0x1a, 0x0395, 0x0313, 0x0300, 0, 0x1b, 0x0395, 0x0314, 0x0300, 0, 0x1c, 0x0395, 0x0313, 0x0301, 0, 0x1d, 0x0395, 0x0314, 0x0301, 0, 0x20, 0x03B7, 0x0313, 0, 0x21, 0x03B7, 0x0314, 0, 0x22, 0x03B7, 0x0313, 0x0300, 0, 0x23, 0x03B7, 0x0314, 0x0300, 0, 0x24, 0x03B7, 0x0313, 0x0301, 0, 0x25, 0x03B7, 0x0314, 0x0301, 0, 0x26, 0x03B7, 0x0313, 0x0342, 0, 0x27, 0x03B7, 0x0314, 0x0342, 0, 0x28, 0x0397, 0x0313, 0, 0x29, 0x0397, 0x0314, 0, 0x2a, 0x0397, 0x0313, 0x0300, 0, 0x2b, 0x0397, 0x0314, 0x0300, 0, 0x2c, 0x0397, 0x0313, 0x0301, 0, 0x2d, 0x0397, 0x0314, 0x0301, 0, 0x2e, 0x0397, 0x0313, 0x0342, 0, 0x2f, 0x0397, 0x0314, 0x0342, 0, 0x30, 0x03B9, 0x0313, 0, 0x31, 0x03B9, 0x0314, 0, 0x32, 0x03B9, 0x0313, 0x0300, 0, 0x33, 0x03B9, 0x0314, 0x0300, 0, 0x34, 0x03B9, 0x0313, 0x0301, 0, 0x35, 0x03B9, 0x0314, 0x0301, 0, 0x36, 0x03B9, 0x0313, 0x0342, 0, 0x37, 0x03B9, 0x0314, 0x0342, 0, 0x38, 0x0399, 0x0313, 0, 0x39, 0x0399, 0x0314, 0, 0x3a, 0x0399, 0x0313, 0x0300, 0, 0x3b, 0x0399, 0x0314, 0x0300, 0, 0x3c, 0x0399, 0x0313, 0x0301, 0, 0x3d, 0x0399, 0x0314, 0x0301, 0, 0x3e, 0x0399, 0x0313, 0x0342, 0, 0x3f, 0x0399, 0x0314, 0x0342, 0, 0x40, 0x03BF, 0x0313, 0, 0x41, 0x03BF, 0x0314, 0, 0x42, 0x03BF, 0x0313, 0x0300, 0, 0x43, 0x03BF, 0x0314, 0x0300, 0, 0x44, 0x03BF, 0x0313, 0x0301, 0, 0x45, 0x03BF, 0x0314, 0x0301, 0, 0x48, 0x039F, 0x0313, 0, 0x49, 0x039F, 0x0314, 0, 0x4a, 0x039F, 0x0313, 0x0300, 0, 0x4b, 0x039F, 0x0314, 0x0300, 0, 0x4c, 0x039F, 0x0313, 0x0301, 0, 0x4d, 0x039F, 0x0314, 0x0301, 0, 0x50, 0x03C5, 0x0313, 0, 0x51, 0x03C5, 0x0314, 0, 0x52, 0x03C5, 0x0313, 0x0300, 0, 0x53, 0x03C5, 0x0314, 0x0300, 0, 0x54, 0x03C5, 0x0313, 0x0301, 0, 0x55, 0x03C5, 0x0314, 0x0301, 0, 0x56, 0x03C5, 0x0313, 0x0342, 0, 0x57, 0x03C5, 0x0314, 0x0342, 0, 0x59, 0x03A5, 0x0314, 0, 0x5b, 0x03A5, 0x0314, 0x0300, 0, 0x5d, 0x03A5, 0x0314, 0x0301, 0, 0x5f, 0x03A5, 0x0314, 0x0342, 0, 0x60, 0x03C9, 0x0313, 0, 0x61, 0x03C9, 0x0314, 0, 0x62, 0x03C9, 0x0313, 0x0300, 0, 0x63, 0x03C9, 0x0314, 0x0300, 0, 0x64, 0x03C9, 0x0313, 0x0301, 0, 0x65, 0x03C9, 0x0314, 0x0301, 0, 0x66, 0x03C9, 0x0313, 0x0342, 0, 0x67, 0x03C9, 0x0314, 0x0342, 0, 0x68, 0x03A9, 0x0313, 0, 0x69, 0x03A9, 0x0314, 0, 0x6a, 0x03A9, 0x0313, 0x0300, 0, 0x6b, 0x03A9, 0x0314, 0x0300, 0, 0x6c, 0x03A9, 0x0313, 0x0301, 0, 0x6d, 0x03A9, 0x0314, 0x0301, 0, 0x6e, 0x03A9, 0x0313, 0x0342, 0, 0x6f, 0x03A9, 0x0314, 0x0342, 0, 0x70, 0x03B1, 0x0300, 0, 0x71, 0x03B1, 0x0301, 0, 0x72, 0x03B5, 0x0300, 0, 0x73, 0x03B5, 0x0301, 0, 0x74, 0x03B7, 0x0300, 0, 0x75, 0x03B7, 0x0301, 0, 0x76, 0x03B9, 0x0300, 0, 0x77, 0x03B9, 0x0301, 0, 0x78, 0x03BF, 0x0300, 0, 0x79, 0x03BF, 0x0301, 0, 0x7a, 0x03C5, 0x0300, 0, 0x7b, 0x03C5, 0x0301, 0, 0x7c, 0x03C9, 0x0300, 0, 0x7d, 0x03C9, 0x0301, 0, 0x80, 0x03B1, 0x0345, 0x0313, 0, 0x81, 0x03B1, 0x0345, 0x0314, 0, 0x82, 0x03B1, 0x0345, 0x0313, 0x0300, 0, 0x83, 0x03B1, 0x0345, 0x0314, 0x0300, 0, 0x84, 0x03B1, 0x0345, 0x0313, 0x0301, 0, 0x85, 0x03B1, 0x0345, 0x0314, 0x0301, 0, 0x86, 0x03B1, 0x0345, 0x0313, 0x0342, 0, 0x87, 0x03B1, 0x0345, 0x0314, 0x0342, 0, 0x88, 0x0391, 0x0345, 0x0313, 0, 0x89, 0x0391, 0x0345, 0x0314, 0, 0x8a, 0x0391, 0x0345, 0x0313, 0x0300, 0, 0x8b, 0x0391, 0x0345, 0x0314, 0x0300, 0, 0x8c, 0x0391, 0x0345, 0x0313, 0x0301, 0, 0x8d, 0x0391, 0x0345, 0x0314, 0x0301, 0, 0x8e, 0x0391, 0x0345, 0x0313, 0x0342, 0, 0x8f, 0x0391, 0x0345, 0x0314, 0x0342, 0, 0x90, 0x03B7, 0x0345, 0x0313, 0, 0x91, 0x03B7, 0x0345, 0x0314, 0, 0x92, 0x03B7, 0x0345, 0x0313, 0x0300, 0, 0x93, 0x03B7, 0x0345, 0x0314, 0x0300, 0, 0x94, 0x03B7, 0x0345, 0x0313, 0x0301, 0, 0x95, 0x03B7, 0x0345, 0x0314, 0x0301, 0, 0x96, 0x03B7, 0x0345, 0x0313, 0x0342, 0, 0x97, 0x03B7, 0x0345, 0x0314, 0x0342, 0, 0x98, 0x0397, 0x0345, 0x0313, 0, 0x99, 0x0397, 0x0345, 0x0314, 0, 0x9a, 0x0397, 0x0345, 0x0313, 0x0300, 0, 0x9b, 0x0397, 0x0345, 0x0314, 0x0300, 0, 0x9c, 0x0397, 0x0345, 0x0313, 0x0301, 0, 0x9d, 0x0397, 0x0345, 0x0314, 0x0301, 0, 0x9e, 0x0397, 0x0345, 0x0313, 0x0342, 0, 0x9f, 0x0397, 0x0345, 0x0314, 0x0342, 0, 0xa0, 0x03C9, 0x0345, 0x0313, 0, 0xa1, 0x03C9, 0x0345, 0x0314, 0, 0xa2, 0x03C9, 0x0345, 0x0313, 0x0300, 0, 0xa3, 0x03C9, 0x0345, 0x0314, 0x0300, 0, 0xa4, 0x03C9, 0x0345, 0x0313, 0x0301, 0, 0xa5, 0x03C9, 0x0345, 0x0314, 0x0301, 0, 0xa6, 0x03C9, 0x0345, 0x0313, 0x0342, 0, 0xa7, 0x03C9, 0x0345, 0x0314, 0x0342, 0, 0xa8, 0x03A9, 0x0345, 0x0313, 0, 0xa9, 0x03A9, 0x0345, 0x0314, 0, 0xaa, 0x03A9, 0x0345, 0x0313, 0x0300, 0, 0xab, 0x03A9, 0x0345, 0x0314, 0x0300, 0, 0xac, 0x03A9, 0x0345, 0x0313, 0x0301, 0, 0xad, 0x03A9, 0x0345, 0x0314, 0x0301, 0, 0xae, 0x03A9, 0x0345, 0x0313, 0x0342, 0, 0xaf, 0x03A9, 0x0345, 0x0314, 0x0342, 0, 0xb0, 0x03B1, 0x0306, 0, 0xb1, 0x03B1, 0x0304, 0, 0xb2, 0x03B1, 0x0345, 0x0300, 0, 0xb3, 0x03B1, 0x0345, 0, 0xb4, 0x03B1, 0x0345, 0x0301, 0, 0xb6, 0x03B1, 0x0342, 0, 0xb7, 0x03B1, 0x0345, 0x0342, 0, 0xb8, 0x0391, 0x0306, 0, 0xb9, 0x0391, 0x0304, 0, 0xba, 0x0391, 0x0300, 0, 0xbb, 0x0391, 0x0301, 0, 0xbc, 0x0391, 0x0345, 0, 0xbe, 0x03B9, 0, 0xc1, 0x00A8, 0x0342, 0, 0xc2, 0x03B7, 0x0345, 0x0300, 0, 0xc3, 0x03B7, 0x0345, 0, 0xc4, 0x03B7, 0x0345, 0x0301, 0, 0xc6, 0x03B7, 0x0342, 0, 0xc7, 0x03B7, 0x0345, 0x0342, 0, 0xc8, 0x0395, 0x0300, 0, 0xc9, 0x0395, 0x0301, 0, 0xca, 0x0397, 0x0300, 0, 0xcb, 0x0397, 0x0301, 0, 0xcc, 0x0397, 0x0345, 0, 0xcd, 0x1FBF, 0x0300, 0, 0xce, 0x1FBF, 0x0301, 0, 0xcf, 0x1FBF, 0x0342, 0, 0xd0, 0x03B9, 0x0306, 0, 0xd1, 0x03B9, 0x0304, 0, 0xd2, 0x03B9, 0x0308, 0x0300, 0, 0xd3, 0x03B9, 0x0308, 0x0301, 0, 0xd6, 0x03B9, 0x0342, 0, 0xd7, 0x03B9, 0x0308, 0x0342, 0, 0xd8, 0x0399, 0x0306, 0, 0xd9, 0x0399, 0x0304, 0, 0xda, 0x0399, 0x0300, 0, 0xdb, 0x0399, 0x0301, 0, 0xdd, 0x1FFE, 0x0300, 0, 0xde, 0x1FFE, 0x0301, 0, 0xdf, 0x1FFE, 0x0342, 0, 0xe0, 0x03C5, 0x0306, 0, 0xe1, 0x03C5, 0x0304, 0, 0xe2, 0x03C5, 0x0308, 0x0300, 0, 0xe3, 0x03C5, 0x0308, 0x0301, 0, 0xe4, 0x03C1, 0x0313, 0, 0xe5, 0x03C1, 0x0314, 0, 0xe6, 0x03C5, 0x0342, 0, 0xe7, 0x03C5, 0x0308, 0x0342, 0, 0xe8, 0x03A5, 0x0306, 0, 0xe9, 0x03A5, 0x0304, 0, 0xea, 0x03A5, 0x0300, 0, 0xeb, 0x03A5, 0x0301, 0, 0xec, 0x03A1, 0x0314, 0, 0xed, 0x00A8, 0x0300, 0, 0xee, 0x00A8, 0x0301, 0, 0xef, 0x0060, 0, 0xf2, 0x03C9, 0x0345, 0x0300, 0, 0xf3, 0x03C9, 0x0345, 0, 0xf4, 0x03BF, 0x0345, 0x0301, 0, 0xf6, 0x03C9, 0x0342, 0, 0xf7, 0x03C9, 0x0345, 0x0342, 0, 0xf8, 0x039F, 0x0300, 0, 0xf9, 0x039F, 0x0301, 0, 0xfa, 0x03A9, 0x0300, 0, 0xfb, 0x03A9, 0x0301, 0, 0xfc, 0x03A9, 0x0345, 0, 0xfd, 0x00B4, 0, 0x00, /* page30 */ 0x30, 0x4c, 0x304B, 0x3099, 0, 0x4e, 0x304D, 0x3099, 0, 0x50, 0x304F, 0x3099, 0, 0x52, 0x3051, 0x3099, 0, 0x54, 0x3053, 0x3099, 0, 0x56, 0x3055, 0x3099, 0, 0x58, 0x3057, 0x3099, 0, 0x5a, 0x3059, 0x3099, 0, 0x5c, 0x305B, 0x3099, 0, 0x5e, 0x305D, 0x3099, 0, 0x60, 0x305F, 0x3099, 0, 0x62, 0x3061, 0x3099, 0, 0x65, 0x3064, 0x3099, 0, 0x67, 0x3066, 0x3099, 0, 0x69, 0x3068, 0x3099, 0, 0x70, 0x306F, 0x3099, 0, 0x71, 0x306F, 0x309A, 0, 0x73, 0x3072, 0x3099, 0, 0x74, 0x3072, 0x309A, 0, 0x76, 0x3075, 0x3099, 0, 0x77, 0x3075, 0x309A, 0, 0x79, 0x3078, 0x3099, 0, 0x7a, 0x3078, 0x309A, 0, 0x7c, 0x307B, 0x3099, 0, 0x7d, 0x307B, 0x309A, 0, 0x94, 0x3046, 0x3099, 0, 0x9e, 0x309D, 0x3099, 0, 0xac, 0x30AB, 0x3099, 0, 0xae, 0x30AD, 0x3099, 0, 0xb0, 0x30AF, 0x3099, 0, 0xb2, 0x30B1, 0x3099, 0, 0xb4, 0x30B3, 0x3099, 0, 0xb6, 0x30B5, 0x3099, 0, 0xb8, 0x30B7, 0x3099, 0, 0xba, 0x30B9, 0x3099, 0, 0xbc, 0x30BB, 0x3099, 0, 0xbe, 0x30BD, 0x3099, 0, 0xc0, 0x30BF, 0x3099, 0, 0xc2, 0x30C1, 0x3099, 0, 0xc5, 0x30C4, 0x3099, 0, 0xc7, 0x30C6, 0x3099, 0, 0xc9, 0x30C8, 0x3099, 0, 0xd0, 0x30CF, 0x3099, 0, 0xd1, 0x30CF, 0x309A, 0, 0xd3, 0x30D2, 0x3099, 0, 0xd4, 0x30D2, 0x309A, 0, 0xd6, 0x30D5, 0x3099, 0, 0xd7, 0x30D5, 0x309A, 0, 0xd9, 0x30D8, 0x3099, 0, 0xda, 0x30D8, 0x309A, 0, 0xdc, 0x30DB, 0x3099, 0, 0xdd, 0x30DB, 0x309A, 0, 0xf4, 0x30A6, 0x3099, 0, 0xf7, 0x30EF, 0x3099, 0, 0xf8, 0x30F0, 0x3099, 0, 0xf9, 0x30F1, 0x3099, 0, 0xfa, 0x30F2, 0x3099, 0, 0xfe, 0x30FD, 0x3099, 0, 0x00, /* pagefb */ 0xfb, 0x1f, 0x05F2, 0x05B7, 0, 0x2a, 0x05E9, 0x05C1, 0, 0x2b, 0x05E9, 0x05C2, 0, 0x2c, 0x05E9, 0x05BC, 0x05C1, 0, 0x2d, 0x05E9, 0x05BC, 0x05C2, 0, 0x2e, 0x05D0, 0x05B7, 0, 0x2f, 0x05D0, 0x05B8, 0, 0x30, 0x05D0, 0x05BC, 0, 0x31, 0x05D1, 0x05BC, 0, 0x32, 0x05D2, 0x05BC, 0, 0x33, 0x05D3, 0x05BC, 0, 0x34, 0x05D4, 0x05BC, 0, 0x35, 0x05D5, 0x05BC, 0, 0x36, 0x05D6, 0x05BC, 0, 0x38, 0x05D8, 0x05BC, 0, 0x39, 0x05D9, 0x05BC, 0, 0x3a, 0x05DA, 0x05BC, 0, 0x3b, 0x05DB, 0x05BC, 0, 0x3c, 0x05DC, 0x05BC, 0, 0x3e, 0x05DE, 0x05BC, 0, 0x40, 0x05E0, 0x05BC, 0, 0x41, 0x05E1, 0x05BC, 0, 0x43, 0x05E3, 0x05BC, 0, 0x44, 0x05E4, 0x05BC, 0, 0x46, 0x05E6, 0x05BC, 0, 0x47, 0x05E7, 0x05BC, 0, 0x48, 0x05E8, 0x05BC, 0, 0x49, 0x05E9, 0x05BC, 0, 0x4a, 0x05EA, 0x05BC, 0, 0x4b, 0x05D5, 0x05B9, 0, 0x4c, 0x05D1, 0x05BF, 0, 0x4d, 0x05DB, 0x05BF, 0, 0x4e, 0x05E4, 0x05BF, 0, 0x00, /* end of list */ 0x00 }; #define HFSPLUS_DECOMPOSE_PAGE_SIZE (256 * (HFSPLUS_MAX_DECOMPOSE_LEN + 1)) static uint16_t decompose_pages[16 * 256][HFSPLUS_MAX_DECOMPOSE_LEN + 1]; uint16_t (*hfsplus_decompose_pages[256])[HFSPLUS_MAX_DECOMPOSE_LEN + 1]; void make_hfsplus_decompose_pages() { int page_idx = -1, char_idx, i; uint16_t *rpt, *page_pt, *value_pt; int page_count = 0; memset(decompose_pages, 0, 16 * HFSPLUS_DECOMPOSE_PAGE_SIZE); for (i = 0; i < 256; i++) hfsplus_decompose_pages[i] = NULL; rpt = (uint16_t *) decompose_page_data; page_pt = (uint16_t *) decompose_pages; while (1) { if (*rpt <= page_idx) break; page_count++; page_idx = *(rpt++); char_idx = -1; while (1) { if(*rpt <= char_idx) break; char_idx = *(rpt++); value_pt = page_pt + char_idx * (HFSPLUS_MAX_DECOMPOSE_LEN + 1); while (1) { if(*rpt == 0) break; *(value_pt++) = *(rpt++); } rpt++; } rpt++; hfsplus_decompose_pages[page_idx] = decompose_pages + (page_count - 1) * 256; page_pt += HFSPLUS_DECOMPOSE_PAGE_SIZE; } } libisofs-1.4.2/libisofs/node.h0000644000175700017510000004135612601765214013206 00000000000000/* * Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2009 - 2011 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ #ifndef LIBISO_NODE_H_ #define LIBISO_NODE_H_ /* * Definitions for the public iso tree */ #include "libisofs.h" #include "stream.h" #include #include #include #ifdef HAVE_STDINT_H #include #else #ifdef HAVE_INTTYPES_H #include #endif #endif /* Maximum length of a leaf name in the libisofs node tree. This is currently restricted by the implemented maximum length of a Rock Ridge name. This might later become larger and may then be limited to smaller values. Rock Ridge specs do not impose an explicit limit on name length. But 255 is also specified by http://pubs.opengroup.org/onlinepubs/009695399/basedefs/limits.h.html which says NAME_MAX >= _XOPEN_NAME_MAX = 255 */ #define LIBISOFS_NODE_NAME_MAX 255 /* Maximum length of a path in the libisofs node tree. Rock Ridge specs do not impose an explicit limit on path length. http://pubs.opengroup.org/onlinepubs/009695399/basedefs/limits.h.html says PATH_MAX >= _XOPEN_PATH_MAX = 1024 */ #define LIBISOFS_NODE_PATH_MAX 1024 /** * The extended information is a way to attach additional information to each * IsoNode. External applications may want to use this extension system to * store application specific information related to each node. On the other * side, libisofs may make use of this struct to attach information to nodes in * some particular, uncommon, cases, without incrementing the size of the * IsoNode struct. * * It is implemented like a chained list. */ typedef struct iso_extended_info IsoExtendedInfo; struct iso_extended_info { /** * Next struct in the chain. NULL if it is the last item */ IsoExtendedInfo *next; /** * Function to handle this particular extended information. The function * pointer acts as an identifier for the type of the information. Structs * with same information type must use the same function. * * @param data * Attached data * @param flag * What to do with the data. At this time the following values are * defined: * -> 1 the data must be freed * @return * 1 */ iso_node_xinfo_func process; /** * Pointer to information specific data. */ void *data; }; /** * */ struct Iso_Node { /* * Initialized to 1, originally owned by user, until added to another node. * Then it is owned by the parent node, so the user must take his own ref * if needed. With the exception of the creation functions, none of the * other libisofs functions that return an IsoNode increment its * refcount. This is responsablity of the client, if (s)he needs it. */ int refcount; /** Type of the IsoNode, do not confuse with mode */ enum IsoNodeType type; char *name; /**< Real name, in default charset */ mode_t mode; /**< protection */ uid_t uid; /**< user ID of owner */ gid_t gid; /**< group ID of owner */ /* TODO #00001 : consider adding new timestamps */ time_t atime; /**< time of last access */ time_t mtime; /**< time of last modification */ time_t ctime; /**< time of last status change */ int hidden; /**< whether the node will be hidden, see IsoHideNodeFlag */ IsoDir *parent; /**< parent node, NULL for root */ /* * Pointer to the linked list of children in a dir. */ IsoNode *next; /** * Extended information for the node. */ IsoExtendedInfo *xinfo; }; struct Iso_Dir { IsoNode node; size_t nchildren; /**< The number of children of this directory. */ IsoNode *children; /**< list of children. ptr to first child */ }; /* IMPORTANT: Any change must be reflected by iso_tree_clone_file. */ struct Iso_File { IsoNode node; /* 1 = The node was loaded from an existing ISO image and still refers to its data content there. */ unsigned int from_old_session : 1; /* 1 = The node got attributed a weight by iso_node_set_sort_weight(). */ unsigned int explicit_weight : 1; /** * It sorts the order in which the file data is written to the CD image. * Higher weighting files are written at the beginning of image */ int sort_weight; IsoStream *stream; /* Knows fs_id, st_dev, and st_ino */ }; struct Iso_Symlink { IsoNode node; char *dest; /* If the IsoNode represents an object in an existing filesystem then the following three numbers should unique identify it. (0,0,0) will always be taken as unique. */ unsigned int fs_id; dev_t st_dev; ino_t st_ino; }; struct Iso_Special { IsoNode node; dev_t dev; /* If the IsoNode represents an object in an existing filesystem then the following three numbers should unique identify it. (0,0,0) will always be taken as unique. */ unsigned int fs_id; dev_t st_dev; ino_t st_ino; }; struct iso_dir_iter_iface { int (*next)(IsoDirIter *iter, IsoNode **node); int (*has_next)(IsoDirIter *iter); void (*free)(IsoDirIter *iter); int (*take)(IsoDirIter *iter); int (*remove)(IsoDirIter *iter); /** * This is called just before remove a node from a directory. The iterator * may want to update its internal state according to this. */ void (*notify_child_taken)(IsoDirIter *iter, IsoNode *node); }; /** * An iterator for directory children. */ struct Iso_Dir_Iter { struct iso_dir_iter_iface *class; /* the directory this iterator iterates over */ IsoDir *dir; void *data; }; int iso_node_new_root(IsoDir **root); /** * Create a new IsoDir. Attributes, uid/gid, timestamps, etc are set to * default (0) values. You must set them. * * @param name * Name for the node. It is not strdup() so you shouldn't use this * reference when this function returns successfully. NULL is not * allowed. * @param dir * * @return * 1 on success, < 0 on error. */ int iso_node_new_dir(char *name, IsoDir **dir); /** * Create a new file node. Attributes, uid/gid, timestamps, etc are set to * default (0) values. You must set them. * * @param name * Name for the node. It is not strdup() so you shouldn't use this * reference when this function returns successfully. NULL is not * allowed. * @param stream * Source for file contents. The reference is taken by the node, * you must call iso_stream_ref() if you need your own ref. * @return * 1 on success, < 0 on error. */ int iso_node_new_file(char *name, IsoStream *stream, IsoFile **file); /** * Creates a new IsoSymlink node. Attributes, uid/gid, timestamps, etc are set * to default (0) values. You must set them. * * @param name * name for the new symlink. It is not strdup() so you shouldn't use this * reference when this function returns successfully. NULL is not * allowed. * @param dest * destination of the link. It is not strdup() so you shouldn't use this * reference when this function returns successfully. NULL is not * allowed. * @param link * place where to store a pointer to the newly created link. * @return * 1 on success, < 0 otherwise */ int iso_node_new_symlink(char *name, char *dest, IsoSymlink **link); /** * Create a new special file node. As far as libisofs concerns, * an special file is a block device, a character device, a FIFO (named pipe) * or a socket. You can choose the specific kind of file you want to add * by setting mode propertly (see man 2 stat). * * Note that special files are only written to image when Rock Ridge * extensions are enabled. Moreover, a special file is just a directory entry * in the image tree, no data is written beyond that. * * Owner and hidden atts are taken from parent. You can modify any of them * later. * * @param name * name for the new special file. It is not strdup() so you shouldn't use * this reference when this function returns successfully. NULL is not * allowed. * @param mode * file type and permissions for the new node. Note that you can't * specify any kind of file here, only special types are allowed. i.e, * S_IFSOCK, S_IFBLK, S_IFCHR and S_IFIFO are valid types; S_IFLNK, * S_IFREG and S_IFDIR aren't. * @param dev * device ID, equivalent to the st_rdev field in man 2 stat. * @param special * place where to store a pointer to the newly created special file. * @return * 1 on success, < 0 otherwise */ int iso_node_new_special(char *name, mode_t mode, dev_t dev, IsoSpecial **special); /** * Check if a given name is valid for an iso node. * * @return * 1 if yes, <0 if not. The value is a specific ISO_* error code. */ int iso_node_is_valid_name(const char *name); /** * Check if a given path is valid for the destination of a link. * * @return * 1 if yes, 0 if not */ int iso_node_is_valid_link_dest(const char *dest); /** * Find the position where to insert a node * * @param dir * A valid dir. It can't be NULL * @param name * The node name to search for. It can't be NULL * @param pos * Will be filled with the position where to insert. It can't be NULL */ void iso_dir_find(IsoDir *dir, const char *name, IsoNode ***pos); /** * Check if a node with the given name exists in a dir. * * @param dir * A valid dir. It can't be NULL * @param name * The node name to search for. It can't be NULL * @param pos * If not NULL, will be filled with the position where to insert. If the * node exists, (**pos) will refer to the given node. * @return * 1 if node exists, 0 if not */ int iso_dir_exists(IsoDir *dir, const char *name, IsoNode ***pos); /** * Inserts a given node in a dir, at the specified position. * * @param dir * Dir where to insert. It can't be NULL * @param node * The node to insert. It can't be NULL * @param pos * Position where the node will be inserted. It is a pointer previously * obtained with a call to iso_dir_exists() or iso_dir_find(). * It can't be NULL. * @param replace * Whether to replace an old node with the same name with the new node. * @return * If success, number of children in dir. < 0 on error */ int iso_dir_insert(IsoDir *dir, IsoNode *node, IsoNode **pos, enum iso_replace_mode replace); /** * Add a new iterator to the registry. The iterator register keeps track of * all iterators being used, and are notified when directory structure * changes. */ int iso_dir_iter_register(IsoDirIter *iter); /** * Unregister a directory iterator. */ void iso_dir_iter_unregister(IsoDirIter *iter); void iso_notify_dir_iters(IsoNode *node, int flag); /** * See API function iso_node_set_permissions() * * @param flag bit0= do not adjust ACL * @return >0 success , <0 error */ int iso_node_set_perms_internal(IsoNode *node, mode_t mode, int flag); /** * Like iso_node_get_acl_text() with param node replaced by aa_string and * st_mode from where to obtain the ACLs. All other parameter specs apply. */ int iso_aa_get_acl_text(unsigned char *aa_string, mode_t st_mode, char **access_text, char **default_text, int flag); /** * Backend of iso_node_get_attrs() with parameter node replaced by the * AAIP string from where to get the attribute list. * All other parameter specs apply. */ int iso_aa_get_attrs(unsigned char *aa_string, size_t *num_attrs, char ***names, size_t **value_lengths, char ***values, int flag); /** * Search given name. Eventually calloc() and copy value. Add trailing 0 byte * for caller convenience. * * @return 1= found , 0= not found , <0 error */ int iso_aa_lookup_attr(unsigned char *aa_string, char *name, size_t *value_length, char **value, int flag); /** * Function to identify and manage ZF parameters which do not stem from ZF * fields (those are known to the FileSource) and do not stem from filters * ("ziso" knows them globally, "osiz" knows them individually) but rather * from an inspection of the file content header for zisofs magic number and * plausible parameters. * The parameters get attached in struct zisofs_zf_info as xinfo to an IsoNode. */ int zisofs_zf_xinfo_func(void *data, int flag); /** * Parameter structure which is to be managed by zisofs_zf_xinfo_func. */ struct zisofs_zf_info { uint32_t uncompressed_size; uint8_t header_size_div4; uint8_t block_size_log2; }; /** * Checks whether a file effectively bears a zisofs file header and eventually * marks this by a struct zisofs_zf_info as xinfo of the file node. * @param flag bit0= inquire the most original stream of the file * bit1= permission to overwrite existing zisofs_zf_info * bit2= if no zisofs header is found: create xinfo with parameters which indicate no zisofs * @return 1= zf xinfo added, 0= no zisofs data found , * 2= found existing zf xinfo and flag bit1 was not set * <0 means error */ int iso_file_zf_by_magic(IsoFile *file, int flag); /* * @param flag * bit0= do only retrieve id if node is in imported ISO image * or has an explicit xinfo inode number * @return * 1= reply is valid from stream, 2= reply is valid from xinfo * 0= no id available, <0= error * (fs_id, dev_id, ino_id) will be (0,0,0) in case of return <= 0 */ int iso_node_get_id(IsoNode *node, unsigned int *fs_id, dev_t *dev_id, ino_t *ino_id, int flag); /* Set a new unique inode ISO image number to the given node. * This number shall eventually persist during image generation. */ int iso_node_set_unique_id(IsoNode *node, IsoImage *image, int flag); /* Use this with extreme care. Duplicate inode numbers will indicate hardlink * relationship between the nodes. */ int iso_node_set_ino(IsoNode *node, ino_t ino, int flag); /* * @param flag * bit0= compare stat properties and attributes * bit1= treat all nodes with image ino == 0 as unique * (those with 0,0,0 are treated as unique anyway) */ int iso_node_cmp_flag(IsoNode *n1, IsoNode *n2, int flag); /** * Set the checksum index (typically comming from IsoFileSrc.checksum_index) * of a regular file node. The index is encoded as xattr "isofs.cx" with * four bytes of value. */ int iso_file_set_isofscx(IsoFile *file, unsigned int checksum_index, int flag); /** * Set the checksum area description. node should be the root node. * It is encoded as xattr "isofs.ca". */ int iso_root_set_isofsca(IsoNode *node, uint32_t start_lba, uint32_t end_lba, uint32_t count, uint32_t size, char *typetext, int flag); /** * Get the checksum area description. node should be the root node. * It is encoded as xattr "isofs.ca". */ int iso_root_get_isofsca(IsoNode *node, uint32_t *start_lba, uint32_t *end_lba, uint32_t *count, uint32_t *size, char typetext[81], int flag); /** * Record and get truncation parameters as of iso_image_set_truncate_mode() by * "isofs.nt". */ int iso_root_set_isofsnt(IsoNode *node, uint32_t truncate_mode, uint32_t truncate_length, int flag); int iso_root_get_isofsnt(IsoNode *node, uint32_t *truncate_mode, uint32_t *truncate_length, int flag); /** * Copy the xinfo list from one node to the another. */ int iso_node_clone_xinfo(IsoNode *from_node, IsoNode *to_node, int flag); /** * The iso_node_xinfo_func instance which governs the storing of the inode * number from Rock Ridge field PX. */ int iso_px_ino_xinfo_func(void *data, int flag); /* The iso_node_xinfo_cloner function which gets associated to * iso_px_ino_xinfo_func by iso_init() resp. iso_init_with_flag() via * iso_node_xinfo_make_clonable() */ int iso_px_ino_xinfo_cloner(void *old_data, void **new_data, int flag); /* Function to identify and manage ZF parameters of zisofs compression. * data is supposed to be a pointer to struct zisofs_zf_info */ int zisofs_zf_xinfo_func(void *data, int flag); /* The iso_node_xinfo_cloner function which gets associated to * zisofs_zf_xinfo_func by iso_init() resp. iso_init_with_flag() via * iso_node_xinfo_make_clonable() */ int zisofs_zf_xinfo_cloner(void *old_data, void **new_data, int flag); /* Performing search for possibly truncated node name. */ int iso_dir_get_node_trunc(IsoDir *dir, int truncate_length, const char *name, IsoNode **node); #endif /*LIBISO_NODE_H_*/ libisofs-1.4.2/libisofs/system_area.c0000644000175700017510000026756412523410574014602 00000000000000/* * Copyright (c) 2008 Vreixo Formoso * Copyright (c) 2010 - 2015 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif #include "libisofs.h" #include "system_area.h" #include "eltorito.h" #include "filesrc.h" #include "ecma119_tree.h" #include "image.h" #include "messages.h" #include "ecma119.h" #include "writer.h" #include #include #include #include #include #include /* for gettimeofday() */ #include /* >>> Need ./configure test for uuid_generate() which checks for: uuid_t, uuid_generate, the need for -luuid */ /* #define Libisofs_with_uuid_generatE 1 */ #ifdef Libisofs_with_uuid_generatE #include #endif /* O_BINARY is needed for Cygwin but undefined elsewhere */ #ifndef O_BINARY #define O_BINARY 0 #endif /* * Create a MBR for an isohybrid enabled ISOLINUX boot image. * See libisofs/make_isohybrid_mbr.c * Deprecated. */ int make_isohybrid_mbr(int bin_lba, int *img_blocks, char *mbr, int flag); /* * The New ISOLINUX MBR Producer. * Be cautious with changing parameters. Only few combinations are tested. * */ int make_isolinux_mbr(uint32_t *img_blocks, Ecma119Image *t, int part_offset, int part_number, int fs_type, uint8_t *buf, int flag); /* Find out whether GPT and APM are desired by isohybrid flag bit0 = register APM and GPT requests in Ecma119Image */ int assess_isohybrid_gpt_apm(Ecma119Image *t, int *gpt_count, int gpt_idx[128], int *apm_count, int flag); static int precompute_gpt(Ecma119Image *t); /* * @param flag bit0= img_blocks is start address rather than end address: do not subtract 1 bit1= img_blocks is counted in 512-byte units rather than 2 KiB */ static void iso_compute_cyl_head_sec(uint64_t img_blocks, int hpc, int sph, uint32_t *end_lba, uint32_t *end_sec, uint32_t *end_head, uint32_t *end_cyl, int flag) { uint64_t secs; if(flag & 2) secs = img_blocks; else secs = img_blocks * 4; if (secs > (uint64_t) 0xfffffffc) secs = 0xfffffffc; /* truncate rather than roll over */ if (flag & 1) *end_lba = secs; /* first valid 512-lba */ else secs = *end_lba = secs - 1; /* last valid 512-lba */ *end_cyl = secs / (sph * hpc); secs -= *end_cyl * sph * hpc; *end_head = secs / sph; *end_sec = secs - *end_head * sph + 1; /* Sector count starts by 1 */ if (*end_cyl >= 1024) { *end_cyl = 1023; *end_head = hpc - 1; *end_sec = sph; } } /* @param flag bit0= The path contains instructions for the interval reader */ static int compute_partition_size(Ecma119Image *t, char *disk_path, uint32_t *size, int flag) { int ret; off_t num; struct stat stbuf; struct iso_interval_reader *ivr; off_t byte_count; if (flag & 1) { ret = iso_interval_reader_new(t->image, disk_path, &ivr, &byte_count, 0); if (ret < 0) return ret; *size = (byte_count + BLOCK_SIZE - 1) / BLOCK_SIZE; iso_interval_reader_destroy(&ivr, 0); return ISO_SUCCESS; } *size = 0; ret = stat(disk_path, &stbuf); if (ret == -1) return ISO_BAD_PARTITION_FILE; if (! S_ISREG(stbuf.st_mode)) return ISO_BAD_PARTITION_FILE; num = ((stbuf.st_size + 2047) / 2048); if (num > 0x3fffffff || num == 0) return ISO_BAD_PARTITION_FILE; *size = num; return ISO_SUCCESS; } /* Compute size and position of appended partitions. @param flag bit0= Partitions inside ISO : update t->curblock */ int iso_compute_append_partitions(Ecma119Image *t, int flag) { int ret, i, sa_type, cyl_align, cyl_size = 0; uint32_t pos, size, add_pos = 0; sa_type = (t->system_area_options >> 2) & 0x3f; cyl_align = (t->system_area_options >> 8) & 0x3; if (sa_type == 0 && cyl_align == 3) { cyl_size = t->partition_heads_per_cyl * t->partition_secs_per_head; if (cyl_size % 4) cyl_size = 0; else cyl_size /= 4; } pos = (t->vol_space_size + t->opts->ms_block); for (i = 0; i < ISO_MAX_PARTITIONS; i++) { if (t->opts->appended_partitions[i] == NULL) continue; if (t->opts->appended_partitions[i][0] == 0) continue; ret = compute_partition_size(t, t->opts->appended_partitions[i], &size, t->opts->appended_part_flags[i]); if (ret < 0) return ret; add_pos = 0; if (sa_type == 3 && (pos % ISO_SUN_CYL_SIZE)) { add_pos = ISO_SUN_CYL_SIZE - (pos % ISO_SUN_CYL_SIZE); } else if (cyl_size > 0 && (pos % cyl_size)) { add_pos = cyl_size - (pos % cyl_size); } t->appended_part_prepad[i] = add_pos; t->appended_part_start[i] = pos + add_pos; if (cyl_size > 0 && (size % cyl_size)) { /* Obey cylinder alignment (missing data will be written as zeros by iso_write_partition_file()) */ size += cyl_size - (size % cyl_size); } t->appended_part_size[i] = size; pos += add_pos + size; t->total_size += (add_pos + size) * 2048; if (flag & 1) t->curblock = pos; } return ISO_SUCCESS; } /* @param flag bit1= partition_offset and partition_size are counted in blocks of 512 rather than 2048 */ static int write_mbr_partition_entry(int partition_number, int partition_type, uint64_t partition_offset, uint64_t partition_size, int sph, int hpc, uint8_t *buf, int flag) { uint8_t *wpt; uint32_t end_lba, end_sec, end_head, end_cyl; uint32_t start_lba, start_sec, start_head, start_cyl; uint32_t after_end; int i; after_end = partition_offset + partition_size; iso_compute_cyl_head_sec((uint64_t) partition_offset, hpc, sph, &start_lba, &start_sec, &start_head, &start_cyl, 1 | (flag & 2)); iso_compute_cyl_head_sec((uint64_t) after_end, hpc, sph, &end_lba, &end_sec, &end_head, &end_cyl, (flag & 2)); wpt = buf + 446 + (partition_number - 1) * 16; /* Not bootable */ *(wpt++) = 0x00; /* C/H/S of the start */ *(wpt++) = start_head; *(wpt++) = start_sec | ((start_cyl & 0x300) >> 2); *(wpt++) = start_cyl & 0xff; /* (partition type) */ *(wpt++) = partition_type; /* 3 bytes of C/H/S end */ *(wpt++) = end_head; *(wpt++) = end_sec | ((end_cyl & 0x300) >> 2); *(wpt++) = end_cyl & 0xff; /* LBA start in little endian */ for (i = 0; i < 4; i++) *(wpt++) = (start_lba >> (8 * i)) & 0xff; /* Number of sectors in partition, little endian */ end_lba = end_lba - start_lba + 1; for (i = 0; i < 4; i++) *(wpt++) = (end_lba >> (8 * i)) & 0xff; /* Afaik, partition tables are recognize donly with MBR signature */ buf[510] = 0x55; buf[511] = 0xAA; return ISO_SUCCESS; } /* This is the gesture of grub-mkisofs --protective-msdos-label as explained by Vladimir Serbinenko , 2 April 2010, on grub-devel@gnu.org "Currently we use first and not last entry. You need to: 1) Zero-fill 446-510 2) Put 0x55, 0xAA into 510-512 3) Put 0x80 (for bootable partition), 0, 2, 0 (C/H/S of the start), 0xcd (partition type), [3 bytes of C/H/S end], 0x01, 0x00, 0x00, 0x00 (LBA start in little endian), [LBA end in little endian] at 446-462 " "C/H/S end" means the CHS address of the last block in the partition. It seems that not "[LBA end in little endian]" but "number of blocks" should go into bytes 458-461. But with a start lba of 1, this is the same number. See also http://en.wikipedia.org/wiki/Master_boot_record flag bit0= do not write 0x55, 0xAA to 510,511 bit1= do not mark partition as bootable */ static int make_grub_msdos_label(uint32_t img_blocks, int sph, int hpc, uint8_t part_type, uint8_t *buf, int flag) { uint8_t *wpt; uint32_t end_lba, end_sec, end_head, end_cyl; int i; iso_compute_cyl_head_sec((uint64_t) img_blocks, hpc, sph, &end_lba, &end_sec, &end_head, &end_cyl, 0); /* 1) Zero-fill 446-510 */ wpt = buf + 446; memset(wpt, 0, 64); if (!(flag & 1)) { /* 2) Put 0x55, 0xAA into 510-512 (actually 510-511) */ buf[510] = 0x55; buf[511] = 0xAA; } if (!(flag & 2)) { /* 3) Put 0x80 (for bootable partition), */ *(wpt++) = 0x80; } else { *(wpt++) = 0; } /* 0, 2, 0 (C/H/S of the start), */ *(wpt++) = 0; *(wpt++) = 2; *(wpt++) = 0; /* 0xcd (partition type) */ *(wpt++) = part_type; /* [3 bytes of C/H/S end], */ *(wpt++) = end_head; *(wpt++) = end_sec | ((end_cyl & 0x300) >> 2); *(wpt++) = end_cyl & 0xff; /* 0x01, 0x00, 0x00, 0x00 (LBA start in little endian), */ *(wpt++) = 0x01; *(wpt++) = 0x00; *(wpt++) = 0x00; *(wpt++) = 0x00; /* [LBA end in little endian] */ for (i = 0; i < 4; i++) *(wpt++) = (end_lba >> (8 * i)) & 0xff; /* at 446-462 */ if (wpt - buf != 462) { fprintf(stderr, "libisofs: program error in make_grub_msdos_label: \"assert 462\"\n"); return ISO_ASSERT_FAILURE; } return ISO_SUCCESS; } /* @param flag bit0= zeroize partitions entries 2, 3, 4 bit1= UEFI protective MBR: start LBA = 1 */ static int iso_offset_partition_start(uint32_t img_blocks, int post_part_pad, uint32_t partition_offset, int sph, int hpc, uint8_t *buf, int flag) { uint8_t *wpt; uint32_t end_lba, end_sec, end_head, end_cyl; uint32_t start_lba, start_sec, start_head, start_cyl; uint64_t img_hd_blocks; int i; iso_compute_cyl_head_sec((uint64_t) partition_offset, hpc, sph, &start_lba, &start_sec, &start_head, &start_cyl, 1); img_hd_blocks = ((uint64_t) img_blocks) * 4 - post_part_pad / 512; iso_compute_cyl_head_sec(img_hd_blocks, hpc, sph, &end_lba, &end_sec, &end_head, &end_cyl, 2); if (flag & 2) { start_lba = 1; start_sec = 2; start_head = start_cyl = 0; } wpt = buf + 446; /* Let pass only legal bootability values */ if (*wpt != 0 && *wpt != 0x80) (*wpt) = 0; wpt++; /* C/H/S of the start */ *(wpt++) = start_head; *(wpt++) = start_sec | ((start_cyl & 0x300) >> 2); *(wpt++) = start_cyl & 0xff; /* (partition type) */ wpt++; /* 3 bytes of C/H/S end */ *(wpt++) = end_head; *(wpt++) = end_sec | ((end_cyl & 0x300) >> 2); *(wpt++) = end_cyl & 0xff; /* LBA start in little endian */ for (i = 0; i < 4; i++) *(wpt++) = (start_lba >> (8 * i)) & 0xff; /* Number of sectors in partition, little endian */ end_lba = end_lba - start_lba + 1; for (i = 0; i < 4; i++) *(wpt++) = (end_lba >> (8 * i)) & 0xff; if (wpt - buf != 462) { fprintf(stderr, "libisofs: program error in iso_offset_partition_start: \"assert 462\"\n"); return ISO_ASSERT_FAILURE; } if (flag & 1) /* zeroize the other partition entries */ memset(wpt, 0, 3 * 16); return ISO_SUCCESS; } static int boot_nodes_from_iso_path(Ecma119Image *t, char *path, IsoNode **iso_node, Ecma119Node **ecma_node, char *purpose, int flag) { int ret; ret = iso_tree_path_to_node(t->image, path, iso_node); if (ret <= 0) { iso_msg_submit(t->image->id, ISO_BOOT_FILE_MISSING, 0, "Cannot find in ISO image: %s '%s'", purpose, path); return ISO_BOOT_FILE_MISSING; } if ((*iso_node)->type != LIBISO_FILE) { iso_msg_submit(t->image->id, ISO_BOOT_IMAGE_NOT_VALID, 0, "Designated boot file is not a data file: '%s'", path); return ISO_BOOT_IMAGE_NOT_VALID; } *ecma_node= ecma119_search_iso_node(t, *iso_node); if (*ecma_node == NULL) { iso_msg_submit(t->image->id, ISO_BOOT_IMAGE_NOT_VALID, 0, "Program error: IsoFile has no Ecma119Node: '%s'", path); return ISO_ASSERT_FAILURE; } else { if ((*ecma_node)->type != ECMA119_FILE) { iso_msg_submit(t->image->id, ISO_BOOT_IMAGE_NOT_VALID, 0, "Program error: Ecma119Node of IsoFile is no ECMA119_FILE: '%s'", path); return ISO_ASSERT_FAILURE; } } return ISO_SUCCESS; } /* This function was implemented according to doc/boot_sectors.txt section "MIPS Volume Header" which was derived by Thomas Schmitt from cdrkit-1.1.10/genisoimage/boot-mips.c by Steve McIntyre which is based on work of Florian Lohoff and Thiemo Seufer who possibly learned from documents of MIPS Computer Systems, Inc. and Silicon Graphics Computer Systems, Inc. This function itself is entirely under copyright (C) 2010 Thomas Schmitt. */ static int make_mips_volume_header(Ecma119Image *t, uint8_t *buf, int flag) { char *namept, *name_field; uint32_t num_cyl, idx, blocks, num, checksum; off_t image_size; static uint32_t bps = 512, spt = 32; Ecma119Node *ecma_node; IsoNode *node; IsoStream *stream; off_t file_size; uint32_t file_lba; int ret; /* Bytes 512 to 32767 may come from image or external file */ memset(buf, 0, 512); image_size = t->curblock * 2048; /* 0 - 3 | 0x0be5a941 | Magic number */ iso_msb(buf, 0x0be5a941, 4); /* 28 - 29 | num_cyl_l | Number of usable cylinder, lower two bytes */ num_cyl = (image_size + (bps * spt) - 1) / (bps * spt); iso_msb(buf + 28, num_cyl & 0xffff, 2); /* 32 - 33 | 1 | Number of tracks per cylinder */ iso_msb(buf + 32, 1, 2); /* 35 - 35 | num_cyl_h | Number of usable cylinders, high byte */ buf[35] = (num_cyl >> 16) & 0xff; /* 38 - 39 | 32 | Sectors per track */ iso_msb(buf + 38, spt, 2); /* 40 - 41 | 512 | Bytes per sector */ iso_msb(buf + 40, bps, 2); /* 44 - 47 | 0x00000034 | Controller characteristics */ iso_msb(buf + 44, 0x00000034, 4); /* 72 - 87 | ========== | Volume Directory Entry 1 */ /* 72 - 79 | boot_name | Boot file basename */ /* 80 - 83 | boot_block | ISO 9660 LBA of boot file * 4 */ /* 84 - 87 | boot_bytes | File length in bytes */ /* 88 - 311 | 0 | Volume Directory Entries 2 to 15 */ for (idx = 0; (int) idx < t->image->num_mips_boot_files; idx++) { ret = boot_nodes_from_iso_path(t, t->image->mips_boot_file_paths[idx], &node, &ecma_node, "MIPS boot file", 0); if (ret < 0) return ret; namept = (char *) iso_node_get_name(node); name_field = (char *) (buf + (72 + 16 * idx)); strncpy(name_field, namept, 8); file_lba = ecma_node->info.file->sections[0].block; iso_msb(buf + (72 + 16 * idx) + 8, file_lba * 4, 4); stream = iso_file_get_stream((IsoFile *) node); file_size = iso_stream_get_size(stream); /* Shall i really round up to 2048 ? Steve says yes.*/ iso_msb(buf + (72 + 16 * idx) + 12, ((file_size + 2047) / 2048 ) * 2048, 4); } /* 408 - 411 | part_blks | Number of 512 byte blocks in partition */ blocks = (image_size + bps - 1) / bps; iso_msb(buf + 408, blocks, 4); /* 416 - 419 | 0 | Partition is volume header */ iso_msb(buf + 416, 0, 4); /* 432 - 435 | part_blks | Number of 512 byte blocks in partition */ iso_msb(buf + 432, blocks, 4); iso_msb(buf + 444, 6, 4); /* 504 - 507 | head_chk | Volume header checksum The two's complement of bytes 0 to 503 read as big endian unsigned 32 bit: sum(32-bit-words) + head_chk == 0 */ checksum = 0; for (idx = 0; idx < 504; idx += 4) { num = iso_read_msb(buf + idx, 4); /* Addition modulo a natural number is commutative and associative. Thus the inverse of a sum is the sum of the inverses of the addends. */ checksum -= num; } iso_msb(buf + 504, checksum, 4); return ISO_SUCCESS; } /* The following two functions were implemented according to doc/boot_sectors.txt section "MIPS Little Endian" which was derived by Thomas Schmitt from cdrkit-1.1.10/genisoimage/boot-mipsel.c by Steve McIntyre which is based on work of Florian Lohoff and Thiemo Seufer, and from by Free Software Foundation, Inc. Both functions are entirely under copyright (C) 2010 Thomas Schmitt. */ /** * Read the necessary ELF information from the first MIPS boot file. * This is done before image writing starts. */ int iso_read_mipsel_elf(Ecma119Image *t, int flag) { uint32_t phdr_adr, todo, count; int ret; uint8_t *elf_buf = NULL; IsoNode *iso_node; Ecma119Node *ecma_node; IsoStream *stream; if (t->image->num_mips_boot_files <= 0) {ret = ISO_SUCCESS; goto ex;} LIBISO_ALLOC_MEM(elf_buf, uint8_t, 2048); ret = boot_nodes_from_iso_path(t, t->image->mips_boot_file_paths[0], &iso_node, &ecma_node, "MIPS boot file", 0); if (ret < 0) goto ex; stream = iso_file_get_stream((IsoFile *) iso_node); ret = iso_stream_open(stream); if (ret < 0) { iso_msg_submit(t->image->id, ret, 0, "Cannot open designated MIPS boot file '%s'", t->image->mips_boot_file_paths[0]); goto ex; } ret = iso_stream_read(stream, elf_buf, 32); if (ret != 32) { cannot_read:; iso_stream_close(stream); iso_msg_submit(t->image->id, ret, 0, "Cannot read from designated MIPS boot file '%s'", t->image->mips_boot_file_paths[0]); goto ex; } /* 24 - 27 | e_entry | Entry point virtual address */ t->mipsel_e_entry = iso_read_lsb(elf_buf + 24, 4); /* 28 - 31 | e_phoff | Program header table file offset */ phdr_adr = iso_read_lsb(elf_buf + 28, 4); /* Skip stream up to byte address phdr_adr */ todo = phdr_adr - 32; while (todo > 0) { if (todo > 2048) count = 2048; else count = todo; todo -= count; ret = iso_stream_read(stream, elf_buf, count); if (ret != (int) count) goto cannot_read; } ret = iso_stream_read(stream, elf_buf, 20); if (ret != 20) goto cannot_read; /* 4 - 7 | p_offset | Segment file offset */ t->mipsel_p_offset = iso_read_lsb(elf_buf + 4, 4); /* 8 - 11 | p_vaddr | Segment virtual address */ t->mipsel_p_vaddr = iso_read_lsb(elf_buf + 8, 4); /* 16 - 19 | p_filesz | Segment size in file */ t->mipsel_p_filesz = iso_read_lsb(elf_buf + 16, 4); iso_stream_close(stream); ret = ISO_SUCCESS; ex:; LIBISO_FREE_MEM(elf_buf); return ret; } /** * Write DEC Bootblock from previously read ELF parameters. * This is done when image writing has already begun. */ static int make_mipsel_boot_block(Ecma119Image *t, uint8_t *buf, int flag) { int ret; uint32_t seg_size, seg_start; IsoNode *iso_node; Ecma119Node *ecma_node; /* Bytes 512 to 32767 may come from image or external file */ memset(buf, 0, 512); if (t->image->num_mips_boot_files <= 0) return ISO_SUCCESS; ret = boot_nodes_from_iso_path(t, t->image->mips_boot_file_paths[0], &iso_node, &ecma_node, "MIPS boot file", 0); if (ret < 0) return ret; /* 8 - 11 | 0x0002757a | Magic number */ iso_lsb(buf + 8, 0x0002757a, 4); /* 12 - 15 | 1 | Mode 1: Multi extent boot */ iso_lsb(buf + 12, 1, 4); /* 16 - 19 | load_adr | Load address */ iso_lsb(buf + 16, t->mipsel_p_vaddr, 4); /* 20 - 23 | exec_adr | Execution address */ iso_lsb(buf + 20, t->mipsel_e_entry, 4); /* 24 - 27 | seg_size | Segment size in file. */ seg_size = (t->mipsel_p_filesz + 511) / 512; iso_lsb(buf + 24, seg_size, 4); /* 28 - 31 | seg_start | Segment file offset */ seg_start = ecma_node->info.file->sections[0].block * 4 + (t->mipsel_p_offset + 511) / 512; iso_lsb(buf + 28, seg_start, 4); return ISO_SUCCESS; } /* The following two functions were implemented according to doc/boot_sectors.txt section "SUN Disk Label and boot images" which was derived by Thomas Schmitt from cdrtools-2.01.01a77/mkisofs/sunlabel.h cdrtools-2.01.01a77/mkisofs/mkisofs.8 by Joerg Schilling Both functions are entirely under copyright (C) 2010 Thomas Schmitt. */ /* @parm flag bit0= copy from next lower valid partition table entry */ static int write_sun_partition_entry(int partition_number, char *appended_partitions[], uint32_t partition_offset[], uint32_t partition_size[], uint32_t cyl_size, uint8_t *buf, int flag) { uint8_t *wpt; int read_idx, i; if (partition_number < 1 || partition_number > 8) return ISO_ASSERT_FAILURE; /* 142 - 173 | ========== | 8 partition entries of 4 bytes */ wpt = buf + 142 + (partition_number - 1) * 4; if (partition_number == 1) iso_msb(wpt, 4, 2); /* 4 = User partition */ else iso_msb(wpt, 2, 2); /* 2 = Root partition with boot image */ iso_msb(wpt + 2, 0x10, 2); /* Permissions: 0x10 = read-only */ /* 444 - 507 | ========== | Partition table */ wpt = buf + 444 + (partition_number - 1) * 8; read_idx = partition_number - 1; if (flag & 1) { /* Search next lower valid partition table entry. #1 is default */ for (read_idx = partition_number - 2; read_idx > 0; read_idx--) if (appended_partitions[read_idx] != NULL) if (appended_partitions[read_idx][0] != 0) break; } iso_msb(wpt, partition_offset[read_idx] / (uint32_t) ISO_SUN_CYL_SIZE, 4); iso_msb(wpt + 4, partition_size[read_idx] * 4, 4); /* 510 - 511 | checksum | The result of exoring 2-byte words 0 to 254 */ buf[510] = buf[511] = 0; for (i = 0; i < 510; i += 2) { buf[510] ^= buf[i]; buf[511] ^= buf[i + 1]; } return ISO_SUCCESS; } /** * Write SUN Disk Label with ISO in partition 1 and unused 2 to 8 */ static int make_sun_disk_label(Ecma119Image *t, uint8_t *buf, int flag) { int ret, i; uint64_t blk; /* Bytes 512 to 32767 may come from image or external file */ memset(buf, 0, 512); /* 0 - 127 | label | ASCII Label */ if (t->opts->ascii_disc_label[0]) strncpy((char *) buf, t->opts->ascii_disc_label, 128); else strcpy((char *) buf, "CD-ROM Disc with Sun sparc boot created by libisofs"); /* 128 - 131 | 1 | Layout version */ iso_msb(buf + 128, 1, 4); /* 140 - 141 | 8 | Number of partitions */ iso_msb(buf + 140, 8, 2); /* 188 - 191 | 0x600ddeee | vtoc sanity */ iso_msb(buf + 188, 0x600ddeee, 4); /* 420 - 421 | 350 | Rotations per minute */ iso_msb(buf + 420, 350, 2); /* 422 - 423 | 2048 | Number of physical cylinders (fixely 640 MB) */ iso_msb(buf + 422, 2048, 2); /* 430 - 431 | 1 | interleave factor */ iso_msb(buf + 430, 1, 2); /* 432 - 433 | 2048 | Number of data cylinders (fixely 640 MB) */ iso_msb(buf + 432, 2048, 2); /* 436 - 437 | 1 | Number of heads per cylinder (1 cyl = 320 kB)*/ iso_msb(buf + 436, 1, 2); /* 438 - 439 | 640 | Number of sectors per head (1 head = 320 kB) */ iso_msb(buf + 438, 640, 2); /* 508 - 509 | 0xdabe | Magic Number */ iso_msb(buf + 508, 0xdabe, 2); if (t->sparc_core_src != NULL) { /* May be used for grub-sparc. */ blk= ((uint64_t) t->sparc_core_src->sections[0].block) * (uint64_t) 2048; for (i = 0; i < 8; i++) buf[Libisofs_grub2_sparc_patch_adr_poS + i] = blk >> ((7 - i) * 8); iso_msb(buf + Libisofs_grub2_sparc_patch_size_poS, t->sparc_core_src->sections[0].size, 4); } /* Set partition 1 to describe ISO image and compute checksum */ t->appended_part_start[0] = 0; t->appended_part_size[0] = t->curblock; ret = write_sun_partition_entry(1, t->opts->appended_partitions, t->appended_part_start, t->appended_part_size, ISO_SUN_CYL_SIZE, buf, 0); if (ret < 0) return ret; return ISO_SUCCESS; } static int hppa_palo_get_filepar(Ecma119Image *t, char *path, uint32_t *adr, uint32_t *len, int flag) { int ret; IsoNode *iso_node; Ecma119Node *ecma_node; off_t adr64; ret = boot_nodes_from_iso_path(t, path, &iso_node, &ecma_node, "HP-PA PALO boot file", 0); if (ret < 0) return ret; if (iso_node_get_type(iso_node) != LIBISO_FILE) { iso_msg_submit(t->image->id, ISO_HPPA_PALO_NOTREG, 0, "HP-PA PALO file is not a data file"); return ISO_HPPA_PALO_NOTREG; } adr64 = ((off_t) 2048) * (off_t) ecma_node->info.file->sections[0].block; if (adr64 > 0x7fffffff) { iso_msg_submit(t->image->id, ISO_HPPA_PALO_OFLOW, 0, "HP-PA PALO boot address exceeds 2 GB"); return ISO_HPPA_PALO_OFLOW; } *adr = adr64; *len = ecma_node->info.file->sections[0].size; return ISO_SUCCESS; } /** * Write HP-PA PALO boot sector. See doc/boot_sectors.txt * * learned from cdrkit-1.1.10/genisoimage/boot-hppa.c * by Steve McIntyre * who states "Heavily inspired by palo" * Public mail conversations with Helge Deller, beginning with * https://lists.debian.org/debian-hppa/2014/01/msg00016.html * http://git.kernel.org/cgit/linux/kernel/git/deller/palo.git/tree/lib/ * (especially struct firstblock in common.h and struct partition in part.h) * */ static int make_hppa_palo_sector(Ecma119Image *t, uint8_t *buf, int hdrversion, int flag) { int ret; IsoImage *img; uint32_t adr, len; img = t->image; if (img->hppa_cmdline == NULL && img->hppa_bootloader == NULL && img->hppa_kernel_32 == NULL && img->hppa_kernel_64 == NULL && img->hppa_ramdisk == NULL) return ISO_SUCCESS; if (img->hppa_cmdline == NULL || img->hppa_bootloader == NULL || img->hppa_kernel_32 == NULL || img->hppa_kernel_64 == NULL || img->hppa_ramdisk == NULL) { iso_msg_submit(img->id, ISO_HPPA_PALO_INCOMPL, 0, "Incomplete HP-PA PALO boot parameters"); return ISO_HPPA_PALO_INCOMPL; } if (hdrversion == 4) { /* Bytes 256 to 32767 may come from loaded ISO image or external file */ memset(buf, 0, 256); } else if(hdrversion == 5) { memset(buf, 0, 512); memset(buf + 1024, 0, 1024); } else { iso_msg_submit(img->id, ISO_WRONG_ARG_VALUE, 0, "Unsupported HP-PA PALO header version %d (can do 4 or 5)", hdrversion); return ISO_WRONG_ARG_VALUE; } /* Magic */ iso_msb(buf + 0, 0x8000, 2); /* Name of boot loader */ memcpy(buf + 2, "PALO", 5); /* Version */ buf[7] = hdrversion; /* Byte address and byte count of the "HPPA 32-bit kernel" file */ ret = hppa_palo_get_filepar(t, img->hppa_kernel_32, &adr, &len, 0); if (ret < 0) return ret; iso_msb(buf + 8, adr, 4); iso_msb(buf + 12, len, 4); /* Byte address and byte count of the "HPPA ramdisk" file */ ret = hppa_palo_get_filepar(t, img->hppa_ramdisk, &adr, &len, 0); if (ret < 0) return ret; iso_msb(buf + 16, adr, 4); iso_msb(buf + 20, len, 4); if (hdrversion == 4) { /* "Command line" */ if (strlen(img->hppa_cmdline) > 127) { iso_msg_submit(img->id, ISO_HPPA_PALO_CMDLEN, 0, "HP-PA PALO command line too long"); return ISO_HPPA_PALO_CMDLEN; } memcpy(buf + 24, img->hppa_cmdline, strlen(img->hppa_cmdline) + 1); } /* Byte address and byte count of the "HPPA 64-bit kernel" file */ ret = hppa_palo_get_filepar(t, img->hppa_kernel_64, &adr, &len, 0); if (ret < 0) return ret; iso_msb(buf + 232, adr, 4); iso_msb(buf + 236, len, 4); /* Byte address and byte count of the "HPPA bootloader" file */ ret = hppa_palo_get_filepar(t, img->hppa_bootloader, &adr, &len, 0); if (ret < 0) return ret; iso_msb(buf + 240, adr, 4); iso_msb(buf + 244, len, 4); if (hdrversion == 5) { if (strlen(img->hppa_cmdline) > 1023) { iso_msg_submit(img->id, ISO_HPPA_PALO_CMDLEN, 0, "HP-PA PALO command line too long"); return ISO_HPPA_PALO_CMDLEN; } memcpy(buf + 1024, img->hppa_cmdline, strlen(img->hppa_cmdline) + 1); } return ISO_SUCCESS; } /** * Write DEC Alpha boot sector. See doc/boot_sectors.txt * * learned from cdrkit-1.1.10/genisoimage/boot-alpha.c * by Steve McIntyre * who states "Heavily inspired by isomarkboot by David Mosberger in 1996" * */ static int make_dec_alpha_sector(Ecma119Image *t, uint8_t *buf, int flag) { int ret, i; IsoImage *img; IsoNode *iso_node; Ecma119Node *ecma_node; uint64_t size, lba, checksum = 0; img = t->image; if (img->alpha_boot_image == NULL) return ISO_SUCCESS; ret = boot_nodes_from_iso_path(t, img->alpha_boot_image, &iso_node, &ecma_node, "DEC Alpha boot file", 0); if (ret < 0) return ret; memset(buf, 0, 512); strcpy((char *) buf, "Linux/Alpha aboot for ISO filesystem."); lba = ecma_node->info.file->sections[0].block * 4; size = ecma_node->info.file->sections[0].size / 512 + !!(ecma_node->info.file->sections[0].size % 512); iso_lsb(buf + 480, size & 0xffffffff, 4); iso_lsb(buf + 484, (size >> 32) & 0xffffffff, 4); iso_lsb(buf + 488, lba & 0xffffffff, 4); iso_lsb(buf + 492, (lba >> 32) & 0xffffffff, 4); for (i = 0; i < 63; i++) checksum += iso_read_lsb64(buf + 8 * i); iso_lsb(buf + 504, checksum & 0xffffffff, 4); iso_lsb(buf + 508, (checksum >> 32) & 0xffffffff, 4); return ISO_SUCCESS; } /* Convenience frontend for iso_register_apm_entry(). name and type are 0-terminated strings. */ int iso_quick_apm_entry(struct iso_apm_partition_request **req_array, int *apm_req_count, uint32_t start_block, uint32_t block_count, char *name, char *type) { int ret; struct iso_apm_partition_request *entry; entry = calloc(1, sizeof(struct iso_apm_partition_request)); if (entry == NULL) return ISO_OUT_OF_MEM; entry->start_block = start_block; entry->block_count = block_count; strncpy((char *) entry->name, name, 32); strncpy((char *) entry->type, type, 32); ret = iso_register_apm_entry(req_array, apm_req_count, entry, 0); free(entry); return ret; } /* Convenience frontend for iso_register_gpt_entry(). name has to be already encoded as UTF-16LE. */ int iso_quick_gpt_entry(struct iso_gpt_partition_request **req_array, int *gpt_req_count, uint64_t start_block, uint64_t block_count, uint8_t type_guid[16], uint8_t partition_guid[16], uint64_t flags, uint8_t name[72]) { int ret; struct iso_gpt_partition_request *entry; entry = calloc(1, sizeof(struct iso_gpt_partition_request)); if (entry == NULL) return ISO_OUT_OF_MEM; entry->start_block = start_block; entry->block_count = block_count; memcpy(entry->type_guid, type_guid, 16); memcpy(entry->partition_guid, partition_guid, 16); entry->flags = flags; memcpy(entry->name, name, 72); ret = iso_register_gpt_entry(req_array, gpt_req_count, entry, 0); free(entry); return ret; } int iso_quick_mbr_entry(struct iso_mbr_partition_request **req_array, int *mbr_req_count, uint64_t start_block, uint64_t block_count, uint8_t type_byte, uint8_t status_byte, int desired_slot) { int ret; struct iso_mbr_partition_request *entry; ret = iso_mbr_entry_slot_is_free(req_array, *mbr_req_count, desired_slot); if (ret < 0) desired_slot = 0; else if (ret == 0) return ISO_BOOT_MBR_COLLISION; entry = calloc(1, sizeof(struct iso_mbr_partition_request)); if (entry == NULL) return ISO_OUT_OF_MEM; entry->start_block = start_block; entry->block_count = block_count; entry->type_byte = type_byte; entry->status_byte = status_byte; entry->desired_slot = desired_slot; ret = iso_register_mbr_entry(req_array, mbr_req_count, entry, 0); free(entry); return ret; } int iso_mbr_entry_slot_is_free(struct iso_mbr_partition_request **req_array, int mbr_req_count, int slot) { int i; if (slot < 0 || slot > ISO_MBR_ENTRIES_MAX) return -1; if (slot == 0) return 1; for (i = 0; i < mbr_req_count; i++) if (req_array[i]->desired_slot == slot) return 0; return 1; } /** * Compare the block interval positions of two iso_apm_partition_request */ static int cmp_partition_request(const void *f1, const void *f2) { struct iso_partition_request { uint64_t start_block; uint64_t block_count; } *r1, *r2; r1 = *((struct iso_partition_request **) f1); r2 = *((struct iso_partition_request **) f2); if (r1->start_block < r2->start_block) return -1; if (r1->start_block > r2->start_block) return 1; /* In case of overlapping the largest partition shall be first */ if (r1->block_count > r2->block_count) return -1; if (r1->block_count < r2->block_count) return 1; return 0; } /* @param flag bit0= This is the entry in block 1. Its blocks are already in the desired apm_block_size unit. Set block_fac to 1. Set flags to 3 rather than 0x13. */ static int iso_write_apm_entry(Ecma119Image *t, int apm_block_size, struct iso_apm_partition_request *req, uint8_t *buf, int map_entries, int flag) { uint8_t *wpt; uint32_t flags; int block_fac; if ((flag & 1) || (t->apm_req_flags & 4)) block_fac = 1; else block_fac = 2048 / apm_block_size; memset(buf, 0, apm_block_size); wpt = buf; /* Signature */ wpt[0] = 'P'; wpt[1] = 'M'; wpt+= 2; /* reserved */ wpt += 2; /* Number of partition entries */ iso_msb(wpt, (uint32_t) map_entries, 4); wpt += 4; /* Physical block start of partition */ iso_msb(wpt, (uint32_t) (req->start_block * block_fac), 4); wpt += 4; /* Physical block count of partition */ iso_msb(wpt, (uint32_t) (req->block_count * block_fac), 4); wpt += 4; /* Partition name */ memcpy(wpt, req->name, 32); wpt += 32; /* Type string */ memcpy(wpt, req->type, 32); wpt += 32; /* Logical block start */ iso_msb(wpt, (uint32_t) 0, 4); wpt += 4; /* Logical block count */ iso_msb(wpt, (uint32_t) (req->block_count * block_fac), 4); wpt += 4; /* Status flags : bit0= entry is valid , bit1= entry is allocated bit4= partition is readable , bit5= partition is writable bit30= automatic mount (legacy Mac) */ if (flag & 1) { flags = 3; } else { flags = 0x13; if (strncmp((char *) req->type, "Apple_HFS", 9) == 0 && req->type[9] == 0) flags |= 0x40000000; } iso_msb(wpt, flags, 4); wpt += 4; /* boot_block , boot_bytes , processor , reserved : are all 0 */ return ISO_SUCCESS; } /* Sort and fill gaps in requested APM */ static int fill_apm_gaps(Ecma119Image *t, uint32_t img_blocks) { int i, ret, gap_counter = 0, up_to; uint32_t part_end, goal, block_fac = 1; char gap_name[33]; if (t->apm_req_flags & 4) { if (t->opts->apm_block_size == 0) t->opts->apm_block_size = 2048; block_fac = 2048 / t->opts->apm_block_size; } /* Find out whether an entry with start_block <= 1 is requested */ for (i = 0; i < t->apm_req_count; i++) { if (t->apm_req[i]->start_block <= 1) break; } if (i >= t->apm_req_count) { ret = iso_quick_apm_entry(t->apm_req, &(t->apm_req_count), 1, 0, "Apple", "Apple_partition_map"); if (ret < 0) return ret; } qsort(t->apm_req, t->apm_req_count, sizeof(struct iso_apm_partition_request *), cmp_partition_request); /* t->apm_req_count will grow during the loop */ up_to = t->apm_req_count + 1; for (i = 1; i < up_to; i++) { if (i < up_to - 1) goal = (uint32_t) t->apm_req[i]->start_block; else goal = img_blocks * block_fac; if (i == 1) { /* Description of APM itself */ /* Actual APM size is not yet known. Protection begins at PVD */ part_end = 16 * block_fac; if (goal < part_end && goal> 1) part_end = goal; } else { part_end = t->apm_req[i - 1]->start_block + t->apm_req[i - 1]->block_count; } if (part_end > goal) { iso_msg_submit(t->image->id, ISO_BOOT_APM_OVERLAP, 0, "Program error: APM partitions %d and %d overlap by %lu blocks", i - 1, i, part_end - goal); return ISO_BOOT_APM_OVERLAP; } if (t->apm_req_flags & 2) /* Do not fill gaps */ continue; if (part_end < goal || i == up_to - 1) { /* Always add a final entry */ sprintf(gap_name, "Gap%d", gap_counter); gap_counter++; ret = iso_quick_apm_entry(t->apm_req, &(t->apm_req_count), part_end, goal - part_end, gap_name, "ISO9660_data"); if (ret < 0) return ret; } } /* Merge list of gap partitions with list of already sorted entries */ if (!(t->apm_req_flags & 2)) /* No gaps were filled */ qsort(t->apm_req, t->apm_req_count, sizeof(struct iso_apm_partition_request *), cmp_partition_request); return 1; } static int rectify_apm(Ecma119Image *t) { int ret; #ifdef NIX /* Disabled */ /* <<< ts B20526 : Dummy mock-up */ if (t->apm_req_count <= 0) { /* ret = iso_quick_apm_entry(t->apm_req, &(t->apm_req_count), 16, 20, "Test1_name_16_20", "Test1_type"); / * >>> Caution: Size 90 causes intentional partition overlap error * / ret = iso_quick_apm_entry(t->apm_req, &(t->apm_req_count), 30, 90, "BAD_30_90_BAD", "Test1_type"); */ ret = iso_quick_apm_entry(t->apm_req, &(t->apm_req_count), 30, 20, "Test1_name_30_20", "Test1_type"); if (ret < 0) return ret; ret = iso_quick_apm_entry(t->apm_req, &(t->apm_req_count), 100, 400, "Test2_name_100_400", "Test2_type"); if (ret < 0) return ret; } #endif /* NIX */ if (t->apm_req_count == 0) return 1; if (t->gpt_req_count > 0 && t->opts->apm_block_size != 2048 && t->apm_req_count > 0) { iso_msgs_submit(0, "GPT and APM requested. APM block size would have to be 2048.", 0, "FAILURE", 0); return ISO_BOOT_APM_GPT_BSIZE; } if (t->apm_req_count > 0) { ret = fill_apm_gaps(t, t->curblock); if (ret < 0) return ret; } return 1; } /* flag bit0= do not write Block0 */ static int iso_write_apm(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf, int flag) { int i, ret; uint32_t block_fac = 1; /* This is a micro mock-up of an APM Block0 and also harmless x86 machine code. */ static uint8_t block0_template[8] = { 0x45, 0x52, 0x02, 0x00, 0xeb, 0x02, 0xff, 0xff }; if (t->apm_req_count <= 0) return 2; if (t->opts->apm_block_size == 0) { /* One cannot be sure that all GPT partitions are registered already. So it is necessary to choose the block size which is combinable with GPT but not mountable on Linux. */ t->opts->apm_block_size = 2048; } if (t->apm_req_flags & 4) block_fac = 2048 / t->opts->apm_block_size; if (!(t->apm_req_flags & 2)) { /* Gaps have been filled. Care for the final one */ /* Adjust last partition to img_size. This size was not known when the number of APM partitions was determined. */ t->apm_req[t->apm_req_count - 1]->block_count = img_blocks * block_fac - t->apm_req[t->apm_req_count - 1]->start_block; /* If it is still empty, remove it */ if(t->apm_req[t->apm_req_count - 1]->block_count == 0) { free(t->apm_req[t->apm_req_count - 1]); t->apm_req_count--; } } /* If block size is larger than 512, then not all 63 entries will fit */ if ((t->apm_req_count + 1) * t->opts->apm_block_size > 32768) return ISO_BOOT_TOO_MANY_APM; /* Block 1 describes the APM itself */ t->apm_req[0]->start_block = 1; t->apm_req[0]->block_count = t->apm_req_count; if (!(flag & 1)) { /* Write APM block 0. Very sparse, not to overwrite much of possible MBR. */ memcpy(buf, block0_template, 8); buf[2]= (t->opts->apm_block_size >> 8) & 0xff; buf[3]= 0; } /* Write APM Block 1 to t->apm_req_count */ for (i = 0; i < t->apm_req_count; i++) { ret = iso_write_apm_entry(t, t->opts->apm_block_size, t->apm_req[i], buf + (i + 1) * t->opts->apm_block_size, t->apm_req_count, i == 0); if (ret < 0) return ret; } return ISO_SUCCESS; } static int iso_write_mbr(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf) { int i, ret, req_of_slot[ISO_MBR_ENTRIES_MAX], q, j; #ifdef NIX /* Disabled */ /* <<< Dummy mock-up */ if (t->mbr_req_count <= 0) { ret = iso_quick_mbr_entry(t->mbr_req, &(t->mbr_req_count), (uint64_t) 0, (uint64_t) 0, 0xee, 0, 0); if (ret < 0) return ret; ret = iso_quick_mbr_entry(t->mbr_req, &(t->mbr_req_count), ((uint64_t) 100) * 4, (uint64_t) 0, 0x0c, 0x80, 1); if (ret < 0) return ret; } #endif /* NIX */ if (t->mbr_req_count <= 0) return 2; /* >>> Sort by start block ? */ /* Adjust partition ends */ for (i = 0; i < t->mbr_req_count; i++) { if (i > 0) { if (t->mbr_req[i]->start_block <= t->mbr_req[i - 1]->start_block && !(t->mbr_req[i]->block_count == 0 && t->mbr_req[i]->start_block == t->mbr_req[i - 1]->start_block)) return ISO_BOOT_MBR_OVERLAP; if (t->mbr_req[i - 1]->start_block + t->mbr_req[i - 1]->block_count > t->mbr_req[i]->start_block) return ISO_BOOT_MBR_OVERLAP; } if (t->mbr_req[i]->block_count != 0) continue; if (i < t->mbr_req_count - 1) t->mbr_req[i]->block_count = t->mbr_req[i + 1]->start_block - t->mbr_req[i]->start_block; else t->mbr_req[i]->block_count = ((uint64_t) img_blocks) * 4 - t->mbr_req[i]->start_block; } /* Assign requested entries to slot numbers */ for (i = 0; i < ISO_MBR_ENTRIES_MAX; i++) req_of_slot[i] = -1; for (i = 0; i < t->mbr_req_count; i++) { if (t->mbr_req[i]->desired_slot < 1 || t->mbr_req[i]->desired_slot > ISO_MBR_ENTRIES_MAX) continue; if (req_of_slot[t->mbr_req[i]->desired_slot - 1] >= 0) return ISO_BOOT_MBR_COLLISION; req_of_slot[t->mbr_req[i]->desired_slot - 1] = i; } for (i = 0; i < t->mbr_req_count; i++) { if (t->mbr_req[i]->desired_slot > 0) continue; for (j = 0; j < ISO_MBR_ENTRIES_MAX; j++) if (req_of_slot[j] < 0) break; if (j >= ISO_MBR_ENTRIES_MAX) return ISO_BOOT_TOO_MANY_MBR; req_of_slot[j] = i; } /* Write partition slots */ for (i = 0; i < ISO_MBR_ENTRIES_MAX; i++) { memset(buf + 446 + i * 16, 0, 16); q = req_of_slot[i]; if (q < 0) continue; if (t->mbr_req[q]->block_count == 0) continue; ret = write_mbr_partition_entry(i + 1, (int) t->mbr_req[q]->type_byte, t->mbr_req[q]->start_block, t->mbr_req[q]->block_count, t->partition_secs_per_head, t->partition_heads_per_cyl, buf, 2); if (ret < 0) return ret; buf[446 + i * 16] = t->mbr_req[q]->status_byte; } return ISO_SUCCESS; } static void iso_write_gpt_entry(Ecma119Image *t, uint8_t *buf, uint8_t type_guid[16], uint8_t part_uuid[16], uint64_t start_lba, uint64_t end_lba, uint64_t flags, uint8_t name[72]) { char *wpt; int i; wpt = (char *) buf; memcpy(wpt, type_guid, 16); wpt += 16; for (i = 0; i < 16; i++) if (part_uuid[i]) break; if (i == 16) iso_random_uuid(t, part_uuid); memcpy(wpt, part_uuid, 16); wpt += 16; iso_lsb_to_buf(&wpt, start_lba & 0xffffffff, 4, 0); iso_lsb_to_buf(&wpt, (start_lba >> 32) & 0xffffffff, 4, 0); iso_lsb_to_buf(&wpt, end_lba & 0xffffffff, 4, 0); iso_lsb_to_buf(&wpt, (end_lba >> 32) & 0xffffffff, 4, 0); iso_lsb_to_buf(&wpt, flags & 0xffffffff, 4, 0); iso_lsb_to_buf(&wpt, (flags >> 32) & 0xffffffff, 4, 0); memcpy(wpt, name, 72); } int iso_write_gpt_header_block(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf, uint32_t max_entries, uint32_t part_start, uint32_t p_arr_crc) { static char *sig = "EFI PART"; static char revision[4] = {0x00, 0x00, 0x01, 0x00}; char *wpt; uint32_t crc; off_t back_lba; memset(buf, 0, 512); wpt = (char *) buf; /* >>> Make signature adjustable */ memcpy(wpt, sig, 8); /* no trailing 0 */ wpt += 8; memcpy(wpt, revision, 4); wpt += 4; iso_lsb_to_buf(&wpt, 92, 4, 0); /* CRC will be inserted later */ wpt += 4; /* reserved */ iso_lsb_to_buf(&wpt, 0, 4, 0); /* Own LBA low 32 */ iso_lsb_to_buf(&wpt, 1, 4, 0); /* Own LBA high 32 */ iso_lsb_to_buf(&wpt, 0, 4, 0); /* Backup header LBA is 1 hd block before backup GPT area end */ back_lba = t->gpt_backup_end * 4 - 1; iso_lsb_to_buf(&wpt, (uint32_t) (back_lba & 0xffffffff), 4, 1); iso_lsb_to_buf(&wpt, (uint32_t) (back_lba >> 32), 4, 1); /* First usable LBA for partitions (4 entries per hd block) */ iso_lsb_to_buf(&wpt, part_start + max_entries / 4, 4, 0); iso_lsb_to_buf(&wpt, 0, 4, 0); /* Last usable LBA for partitions is 1 hd block before first backup entry*/ iso_lsb_to_buf(&wpt, (uint32_t) ((back_lba - max_entries / 4 - 1) & 0xffffffff), 4, 1); iso_lsb_to_buf(&wpt, (uint32_t) ((back_lba - max_entries / 4 - 1) >> 32), 4, 1); /* Disk GUID */ /* >>> Make adjustable */ if (!t->gpt_disk_guid_set) iso_random_uuid(t, t->gpt_disk_guid); t->gpt_disk_guid_set = 1; memcpy(wpt, t->gpt_disk_guid, 16); wpt += 16; /* Partition entries start */ iso_lsb_to_buf(&wpt, part_start, 4, 0); iso_lsb_to_buf(&wpt, 0, 4, 0); /* Number of partition entries */ iso_lsb_to_buf(&wpt, max_entries, 4, 0); /* Size of a partition entry */ iso_lsb_to_buf(&wpt, 128, 4, 0); /* CRC-32 of the partition array */ iso_lsb_to_buf(&wpt, p_arr_crc, 4, 0); /* <<< Only for a first test */ if (wpt - (char *) buf != 92) { iso_msgs_submit(0, "program error : write_gpt_header_block : wpt != 92", 0, "FATAL", 0); return ISO_ISOLINUX_CANT_PATCH; } /* CRC-32 of this header while head_crc is 0 */ crc = iso_crc32_gpt((unsigned char *) buf, 92, 0); wpt = ((char *) buf) + 16; iso_lsb_to_buf(&wpt, crc, 4, 0); return ISO_SUCCESS; } /* Only for up to 36 characters ISO-8859-1 (or ASCII) input */ void iso_ascii_utf_16le(uint8_t gap_name[72]) { int i; for (i = strlen((char *) gap_name) - 1; i >= 0; i--) { gap_name[2 * i] = gap_name[i]; gap_name[2 * i + 1] = 0; } } static int iso_write_gpt(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf) { static uint8_t basic_data_uuid[16] = { 0xa2, 0xa0, 0xd0, 0xeb, 0xe5, 0xb9, 0x33, 0x44, 0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7 }; uint32_t p_arr_crc = 0; uint64_t start_lba, end_lba, goal, part_end, next_end, backup_end_lba; int ret, i, gap_counter = 0, up_to; struct iso_gpt_partition_request *req; uint8_t gpt_name[72]; static uint8_t zero_uuid[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static uint64_t gpt_flags = (((uint64_t) 1) << 60) | 1; if (t->gpt_req_count == 0) return 2; backup_end_lba = ((uint64_t) t->gpt_backup_end - t->gpt_backup_size) * 4; /* Sort and fill gaps */ qsort(t->gpt_req, t->gpt_req_count, sizeof(struct iso_gpt_partition_request *), cmp_partition_request); /* t->gpt_req_count will grow during the loop */ up_to = t->gpt_req_count + 1; goal = 0; part_end = 0; for (i = 0; i < up_to; i++) { if (i < up_to - 1) { goal = t->gpt_req[i]->start_block; } else { goal = ((uint64_t) img_blocks) * 4; if (goal > backup_end_lba) goal = backup_end_lba; } if (i == 0) { if (goal <= 16 * 4) continue; next_end = 16 * 4; } else { next_end = t->gpt_req[i - 1]->start_block + t->gpt_req[i - 1]->block_count; } if (next_end > part_end) part_end = next_end; if (part_end > goal) { if (!(t->gpt_req_flags & 1)) { iso_msg_submit(t->image->id, ISO_BOOT_GPT_OVERLAP, 0, "Program error: GPT partitions %d and %d overlap by %.f blocks", i - 1, i, (double) (part_end - goal)); return ISO_BOOT_GPT_OVERLAP; } } else if (part_end < goal) { memset(gpt_name, 0, 72); if (goal == t->vol_space_size * (uint64_t) 4 && part_end == t->opts->partition_offset * (uint64_t) 4) sprintf((char *) gpt_name, "ISO9660"); else sprintf((char *) gpt_name, "Gap%d", gap_counter); iso_ascii_utf_16le(gpt_name); gap_counter++; ret = iso_quick_gpt_entry(t->gpt_req, &(t->gpt_req_count), part_end, goal - part_end, basic_data_uuid, zero_uuid, gpt_flags, gpt_name); if (ret < 0) return ret; } } /* Merge list of gap partitions with list of already sorted entries */ qsort(t->gpt_req, t->gpt_req_count, sizeof(struct iso_gpt_partition_request *), cmp_partition_request); if ((int) t->gpt_max_entries < t->gpt_req_count) return ISO_BOOT_TOO_MANY_GPT; /* Write the GPT entries to buf */ for (i = 0; i < t->gpt_req_count; i++) { req = t->gpt_req[i]; start_lba = req->start_block; end_lba = req->start_block + req->block_count; if (req->start_block == t->opts->partition_offset * ((uint64_t) 4) && req->block_count == ((uint64_t) 4) * 0xffffffff) end_lba = t->vol_space_size * 4; if (end_lba > backup_end_lba) end_lba = backup_end_lba; end_lba = end_lba - 1; iso_write_gpt_entry(t, buf + 512 * t->gpt_part_start + 128 * i, req->type_guid, req->partition_guid, start_lba, end_lba, req->flags, req->name); } for (; i < (int) t->gpt_max_entries; i++) memset(buf + 512 * t->gpt_part_start + 128 * i, 0, 128); p_arr_crc = iso_crc32_gpt((unsigned char *) buf + 512 * t->gpt_part_start, 128 * t->gpt_max_entries, 0); ret = iso_write_gpt_header_block(t, img_blocks, buf + 512, t->gpt_max_entries, t->gpt_part_start, p_arr_crc); if (ret < 0) return ret; return ISO_SUCCESS; } int iso_write_system_area(Ecma119Image *t, uint8_t *buf) { int ret, int_img_blocks, sa_type, i, will_append = 0, do_isohybrid = 0; int first_partition = 1, last_partition = 4, apm_flag, part_type = 0; int gpt_count = 0, gpt_idx[128], apm_count = 0, no_boot_mbr = 0; int offset_flag = 0; uint32_t img_blocks, gpt_blocks, mbrp1_blocks, pml_blocks; uint64_t blk; uint8_t *wpt; if ((t == NULL) || (buf == NULL)) { return ISO_NULL_POINTER; } /* set buf to 0s */ memset(buf, 0, 16 * BLOCK_SIZE); sa_type = (t->system_area_options >> 2) & 0x3f; if (sa_type == 3) { first_partition = 2; last_partition = 8; } for (i = first_partition - 1; i <= last_partition - 1; i++) if (t->opts->appended_partitions[i] != NULL) { will_append = 1; break; } img_blocks = t->curblock; if (t->system_area_data != NULL) { /* Write more or less opaque boot image */ memcpy(buf, t->system_area_data, 16 * BLOCK_SIZE); } else if (sa_type == 0 && t->catalog != NULL && (t->catalog->bootimages[0]->isolinux_options & 0x0a) == 0x02) { /* Check for isolinux image with magic number of 3.72 and produce an MBR from our built-in template. (Deprecated since 31 Mar 2010) */ if (img_blocks < 0x80000000) { int_img_blocks= img_blocks; } else { int_img_blocks= 0x7ffffff0; } ret = make_isohybrid_mbr(t->bootsrc[0]->sections[0].block, &int_img_blocks, (char*)buf, 0); if (ret != 1) { /* error, it should never happen */ return ISO_ASSERT_FAILURE; } return ISO_SUCCESS; } /* If APM entries were submitted to iso_register_apm_entry(), then they get sprinkled over the system area after the system area template was loaded and before any other data get inserted. Note that if APM and MBR get combined, then the first 8 bytes of the MBR template must be replaceable by: {0x45, 0x52, 0x08 0x00, 0xeb, 0x02, 0xff, 0xff} >>> ts B20526 >>> This does not care for eventual image enlargements in last minute. >>> A sa_type, that does this, will have to adjust the last APM entry >>> if exactness matters. */ apm_flag = 0; if (sa_type == 0 && (t->system_area_options & 3) == 2) { do_isohybrid = 1; /* >>> Coordinate with partprepend writer */ /* <<< provisory trap */ if (t->mbr_req_count > 0) return ISO_BOOT_MBR_OVERLAP; /* If own APM is desired, set flag bit0 to prevent writing of Block0 which would interfere with the own Block0 of isohybrid. */ ret = assess_isohybrid_gpt_apm(t, &gpt_count, gpt_idx, &apm_count, 0); if (ret < 0) return ret; if (apm_count > 0) apm_flag |= 1; } ret = iso_write_apm(t, img_blocks, buf, apm_flag); if (ret < 0) { iso_msg_submit(t->image->id, ret, 0, "Cannot set up Apple Partition Map"); return ret; } ret = iso_write_mbr(t, img_blocks, buf); if (ret < 0) { iso_msg_submit(t->image->id, ret, 0, "Cannot set up MBR partition table"); return ret; } if (t->mbr_req_count > 0 && sa_type != 0) return ISO_NON_MBR_SYS_AREA; if (t->gpt_backup_outside) gpt_blocks = t->total_size / BLOCK_SIZE + t->opts->ms_block; else gpt_blocks = img_blocks; ret = iso_write_gpt(t, gpt_blocks, buf); if (ret < 0) { iso_msg_submit(t->image->id, ret, 0, "Cannot set up GPT"); return ret; } if (sa_type == 0 && (t->system_area_options & 1)) { if (t->mbr_req_count == 0){ /* Write GRUB protective msdos label, i.e. a simple partition table */ if (t->gpt_req_count > 0) { part_type = 0xee; pml_blocks = gpt_blocks; } else { part_type = 0xcd; pml_blocks = img_blocks; } ret = make_grub_msdos_label(pml_blocks, t->partition_secs_per_head, t->partition_heads_per_cyl, (uint8_t) part_type, buf, 0); if (ret != ISO_SUCCESS) /* error should never happen */ return ISO_ASSERT_FAILURE; } } else if (do_isohybrid) { /* Patch externally provided system area as isohybrid MBR */ if (t->catalog == NULL || t->system_area_data == NULL) { /* isohybrid makes only sense together with ISOLINUX boot image and externally provided System Area. */ return ISO_ISOLINUX_CANT_PATCH; } if (gpt_count > 0 || apm_count > 0) part_type = 0x00; else part_type = 0x17; if (t->opts->appended_as_gpt && t->have_appended_partitions) { part_type = 0xee; img_blocks = gpt_blocks; no_boot_mbr = 2; } /* >>> ??? Why is partition_offset 0 here ? It gets adjusted later by iso_offset_partition_start() Would it harm to give the real offset here ? */; ret = make_isolinux_mbr(&img_blocks, t, 0, 1, part_type, buf, 1 | no_boot_mbr); if (ret != 1) return ret; } else if (sa_type == 1) { ret = make_mips_volume_header(t, buf, 0); if (ret != ISO_SUCCESS) return ret; } else if (sa_type == 2) { ret = make_mipsel_boot_block(t, buf, 0); if (ret != ISO_SUCCESS) return ret; } else if (sa_type == 3) { ret = make_sun_disk_label(t, buf, 0); if (ret != ISO_SUCCESS) return ret; } else if (sa_type == 4 || sa_type == 5) { /* (By coincidence, sa_type and PALO header versions match) */ ret = make_hppa_palo_sector(t, buf, sa_type, 0); if (ret != ISO_SUCCESS) return ret; } else if (sa_type == 6) { ret = make_dec_alpha_sector(t, buf, 0); if (ret != ISO_SUCCESS) return ret; } else if ((t->opts->partition_offset > 0 || will_append) && sa_type == 0 && t->mbr_req_count == 0) { /* Write a simple partition table. */ ret = make_grub_msdos_label(img_blocks, t->partition_secs_per_head, t->partition_heads_per_cyl, (uint8_t) 0xcd, buf, 2); if (ret != ISO_SUCCESS) /* error should never happen */ return ISO_ASSERT_FAILURE; if (t->opts->appended_as_gpt && t->have_appended_partitions) { /* Re-write partion entry 1 : protective MBR for GPT */ part_type = 0xee; ret = write_mbr_partition_entry(1, part_type, (uint64_t) 1, ((uint64_t) gpt_blocks) * 4 - 1, t->partition_secs_per_head, t->partition_heads_per_cyl, buf, 2); if (ret < 0) return ret; } else if (t->opts->partition_offset == 0) { /* Re-write partion entry 1 : start at 0, type Linux */ blk = ((uint64_t) img_blocks) * 4 - t->post_iso_part_pad / 512; ret = write_mbr_partition_entry(1, 0x83, (uint64_t) 0, blk, t->partition_secs_per_head, t->partition_heads_per_cyl, buf, 2); if (ret < 0) return ret; } } if (t->opts->partition_offset > 0 && sa_type == 0 && t->mbr_req_count == 0) { /* Adjust partition table to partition offset. With t->mbr_req_count > 0 this has already been done, */ img_blocks = t->curblock; /* value might be altered */ if (part_type == 0xee) { mbrp1_blocks = t->total_size / BLOCK_SIZE + t->opts->ms_block; offset_flag |= 2 | 1; /* protective MBR, no other partitions */ } else { mbrp1_blocks = img_blocks; } ret = iso_offset_partition_start(mbrp1_blocks, t->post_iso_part_pad, t->opts->partition_offset, t->partition_secs_per_head, t->partition_heads_per_cyl, buf, offset_flag); if (ret != ISO_SUCCESS) /* error should never happen */ return ISO_ASSERT_FAILURE; } /* This eventually overwrites the non-mbr_req partition table entries made so far. Overwriting those from t->mbr_req is not allowed. */ if (sa_type == 3 || !t->opts->appended_as_gpt) { for (i = first_partition - 1; i <= last_partition - 1; i++) { if (t->opts->appended_partitions[i] == NULL) continue; if (i < t->mbr_req_count) return ISO_BOOT_MBR_COLLISION; if (sa_type == 3) { ret = write_sun_partition_entry(i + 1, t->opts->appended_partitions, t->appended_part_start, t->appended_part_size, ISO_SUN_CYL_SIZE, buf, t->opts->appended_partitions[i][0] == 0); } else { ret = write_mbr_partition_entry(i + 1, t->opts->appended_part_types[i], (uint64_t) t->appended_part_start[i], (uint64_t) t->appended_part_size[i], t->partition_secs_per_head, t->partition_heads_per_cyl, buf, 0); } if (ret < 0) return ret; } } if (sa_type == 0 && (t->system_area_options & 0x4000) && !do_isohybrid) { /* Patch MBR for GRUB2 */ blk = t->bootsrc[0]->sections[0].block * 4 + Libisofs_grub2_mbr_patch_offsT; wpt = buf + Libisofs_grub2_mbr_patch_poS; for (i = 0; i < 8; i++) wpt[i] = blk >> (i * 8); } return ISO_SUCCESS; } /* Choose *heads_per_cyl so that - *heads_per_cyl * secs_per_head * 1024 >= imgsize / 512 - *heads_per_cyl * secs_per_head is divisible by 4 - it is as small as possible (to reduce alignment overhead) - it is <= 255 @return 1= success , 0= cannot achieve goals */ static int try_sph(off_t imgsize, int secs_per_head, int *heads_per_cyl, int flag) { off_t hd_blocks, hpc; hd_blocks= imgsize / 512; hpc = hd_blocks / secs_per_head / 1024; if (hpc * secs_per_head * 1024 < hd_blocks) hpc++; if ((secs_per_head % 4) == 0) { ; } else if ((secs_per_head % 2) == 0) { hpc += (hpc % 2); } else if(hpc % 4) { hpc += 4 - (hpc % 4); } if (hpc > 255) return 0; *heads_per_cyl = hpc; return 1; } int iso_align_isohybrid(Ecma119Image *t, int flag) { int sa_type, ret, always_align; uint32_t img_blocks; off_t imgsize, cylsize = 0, frac; char *msg = NULL; LIBISO_ALLOC_MEM(msg, char, 160); sa_type = (t->system_area_options >> 2) & 0x3f; if (sa_type != 0) {ret = ISO_SUCCESS; goto ex;} always_align = (t->system_area_options >> 8) & 3; if (!t->gpt_backup_outside) { /* Take into account the backup GPT */; ret = precompute_gpt(t); if (ret < 0) goto ex; } img_blocks = t->curblock + t->opts->tail_blocks + t->gpt_backup_size; imgsize = ((off_t) img_blocks) * (off_t) 2048; if ((!(t->opts->appended_as_gpt && t->have_appended_partitions)) && ((t->system_area_options & 3) || always_align) && (off_t) (t->partition_heads_per_cyl * t->partition_secs_per_head * 1024) * (off_t) 512 < imgsize) { /* Choose small values which can represent the image size */ /* First try 32 sectors per head */ ret = try_sph(imgsize, 32, &(t->partition_heads_per_cyl), 0); if (ret == 1) { t->partition_secs_per_head = 32; } else { /* Did not work with 32. Try 63 */ t->partition_secs_per_head = 63; ret = try_sph(imgsize, 63, &(t->partition_heads_per_cyl), 0); if (ret != 1) t->partition_heads_per_cyl = 255; } cylsize = t->partition_heads_per_cyl * t->partition_secs_per_head *512; frac = imgsize % cylsize; sprintf(msg, "Automatically adjusted MBR geometry to %d/%d/%d", (int) (imgsize / cylsize + !!frac), t->partition_heads_per_cyl, t->partition_secs_per_head); iso_msgs_submit(0, msg, 0, "NOTE", 0); } if (always_align == 2) {ret = ISO_SUCCESS; goto ex;} cylsize = 0; if (t->catalog != NULL && (t->catalog->bootimages[0]->isolinux_options & 0x0a) == 0x02) { /* Check for isolinux image with magic number of 3.72 and produce an MBR from our built-in template. (Deprecated since 31 Mar 2010) */ if (img_blocks >= 0x40000000) {ret = ISO_SUCCESS; goto ex;} cylsize = 64 * 32 * 512; } else if (t->system_area_options & 2) { /* Patch externally provided system area as isohybrid MBR */ if (t->catalog == NULL || t->system_area_data == NULL) { /* isohybrid makes only sense together with ISOLINUX boot image and externally provided System Area. */ {ret = ISO_ISOLINUX_CANT_PATCH; goto ex;} } cylsize = t->partition_heads_per_cyl * t->partition_secs_per_head * 512; } else if (always_align) { cylsize = t->partition_heads_per_cyl * t->partition_secs_per_head * 512; } if (cylsize == 0) {ret = ISO_SUCCESS; goto ex;} if (((double) imgsize) / (double) cylsize > 1024.0) { iso_msgs_submit(0, "Image size exceeds 1024 cylinders. Cannot align partition.", 0, "WARNING", 0); iso_msgs_submit(0, "There are said to be BIOSes which will not boot this via MBR.", 0, "WARNING", 0); {ret = ISO_SUCCESS; goto ex;} } frac = imgsize % cylsize; imgsize += (frac > 0 ? cylsize - frac : 0); frac = imgsize - ((off_t) img_blocks) * (off_t) 2048; if (frac == 0) {ret = ISO_SUCCESS; goto ex;} t->post_iso_part_pad = 0; if (frac % 2048) { t->post_iso_part_pad = 2048 - frac % 2048; sprintf(msg, "Cylinder aligned image size is not divisible by 2048. Have to add %d bytes.", t->post_iso_part_pad); iso_msgs_submit(0, msg, 0, "WARNING", 0); } t->opts->tail_blocks += (frac + 2047) / 2048; ret = ISO_SUCCESS; ex:; LIBISO_FREE_MEM(msg); return ret; } int iso_register_apm_entry(struct iso_apm_partition_request **req_array, int *apm_req_count, struct iso_apm_partition_request *req, int flag) { struct iso_apm_partition_request *entry; if (*apm_req_count >= ISO_APM_ENTRIES_MAX) return ISO_BOOT_TOO_MANY_APM; entry = calloc(1, sizeof(struct iso_apm_partition_request)); if (entry == NULL) return ISO_OUT_OF_MEM; memcpy(entry, req, sizeof(struct iso_apm_partition_request)); req_array[*apm_req_count] = entry; (*apm_req_count)++; return ISO_SUCCESS; } int iso_register_mbr_entry(struct iso_mbr_partition_request **req_array, int *mbr_req_count, struct iso_mbr_partition_request *req, int flag) { struct iso_mbr_partition_request *entry; if (*mbr_req_count >= ISO_MBR_ENTRIES_MAX) return ISO_BOOT_TOO_MANY_MBR; entry = calloc(1, sizeof(struct iso_mbr_partition_request)); if (entry == NULL) return ISO_OUT_OF_MEM; memcpy(entry, req, sizeof(struct iso_mbr_partition_request)); req_array[*mbr_req_count] = entry; (*mbr_req_count)++; return ISO_SUCCESS; } int iso_register_gpt_entry(struct iso_gpt_partition_request **req_array, int *gpt_req_count, struct iso_gpt_partition_request *req, int flag) { struct iso_gpt_partition_request *entry; if (*gpt_req_count >= ISO_GPT_ENTRIES_MAX) return ISO_BOOT_TOO_MANY_GPT; entry = calloc(1, sizeof(struct iso_gpt_partition_request)); if (entry == NULL) return ISO_OUT_OF_MEM; memcpy(entry, req, sizeof(struct iso_gpt_partition_request)); req_array[*gpt_req_count] = entry; (*gpt_req_count)++; return ISO_SUCCESS; } #ifdef Libisofs_with_uuid_generatE static void swap_uuid(void *u_pt) { uint8_t tr, *u; u = (uint8_t *) u_pt; tr = u[0]; u[0] = u[3]; u[3] = tr; tr = u[1]; u[1] = u[2]; u[2] = tr; tr = u[4]; u[4] = u[5]; u[5] = tr; tr = u[6]; u[6] = u[7]; u[7] = tr; } #endif /* Libisofs_with_uuid_generatE */ /* CRC-32 as of GPT and Ethernet. Parameters are deduced from a table driven implementation in isohybrid.c */ uint32_t iso_crc32_gpt(unsigned char *data, int count, int flag) { unsigned int acc, top, result = 0; long int i; /* Chosen so that the CRC of 0 bytes of input is 0x00000000 */ acc = 0x46af6449; /* Process data bits and flush numerator by 32 zero bits */ for (i = 0; i < count * 8 + 32; i++) { top = acc & 0x80000000; acc = (acc << 1); if (i < count * 8) /* The least significant bits of input bytes get processed first */ acc |= ((data[i / 8] >> (i % 8)) & 1); if (top) /* Division by the generating polynomial */ acc ^= 0x04c11db7; } /* Mirror residue bits */ for (i = 0; i < 32; i++) if (acc & (1 << i)) result |= 1 << (31 - i); /* Return bit complement */ return result ^ 0xffffffff; } void iso_random_uuid(Ecma119Image *t, uint8_t uuid[16]) { #ifdef Libisofs_with_uuid_generatE uuid_t u; #else uint8_t u[16]; /* produced by uuid_generate() and byte-swapped to isohybrid.c habits */ static uint8_t uuid_template[16] = { 0xee, 0x29, 0x9d, 0xfc, 0x65, 0xcc, 0x7c, 0x40, 0x92, 0x61, 0x5b, 0xcd, 0x6f, 0xed, 0x08, 0x34 }; static uint8_t uuid_urandom[16]; uint32_t rnd, salt; struct timeval tv; struct timezone tz; pid_t pid; static int counter = 0, use_urandom = 0; int i, ret, fd; #endif #ifdef Libisofs_with_uuid_generatE uuid_generate(u); swap_uuid((void *) u); memcpy(uuid, u, 16); #else /* First try /dev/urandom. (Weakening the result by 8 bit saves a lot of pool entropy.) */ if ((counter & 0xff) == 0) { fd = open("/dev/urandom", O_RDONLY | O_BINARY); if (fd == -1) goto fallback; ret = read(fd, uuid_urandom, 16); if (ret != 16) { close(fd); goto fallback; } /* Mark as UUID version 4 */ uuid_urandom[7] = (uuid_urandom[7] & 0x0f) | 0x40; uuid_urandom[8] = (uuid_urandom[8] & 0x3f) | 0x80; close(fd); use_urandom = 1; } if (!use_urandom) goto fallback; memcpy(uuid, uuid_urandom, 16); uuid[9] ^= counter & 0xff; counter++; return; fallback:; pid = getpid(); salt = iso_crc32_gpt((unsigned char *) t, sizeof(Ecma119Image), 0) ^ pid; /* This relies on the uniqueness of the template and the rareness of bootable ISO image production via libisofs. Estimated 53 bits of entropy should influence the production of a single day. So first collisions are to be expected with about 100 million images per day. */ memcpy(u, uuid_template, 16); gettimeofday(&tv, &tz); for (i = 0; i < 4; i++) u[i] = (salt >> (8 * i)) & 0xff; for (i = 0; i < 2; i++) u[4 + i] = (pid >> (8 * i)) & 0xff; u[6] = ((salt >> 8) ^ (pid >> 16)) & 0xff; rnd = ((0xffffff & tv.tv_sec) << 8) | (((tv.tv_usec >> 16) ^ (salt & 0xf0)) & 0xff); u[9] ^= counter & 0xff; for (i = 0; i < 4; i++) u[10 + i] ^= (rnd >> (8 * i)) & 0xff; u[14] ^= (tv.tv_usec >> 8) & 0xff; u[15] ^= tv.tv_usec & 0xff; counter++; memcpy(uuid, u, 16); #endif /* ! Libisofs_with_uuid_generatE */ } int assess_appended_gpt(Ecma119Image *t, int flag) { static uint8_t basic_data_uuid[16] = { 0xa2, 0xa0, 0xd0, 0xeb, 0xe5, 0xb9, 0x33, 0x44, 0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7 }; static uint8_t efi_sys_uuid[16] = { 0x28, 0x73, 0x2a, 0xc1, 0x1f, 0xf8, 0xd2, 0x11, 0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b }; static uint8_t zero_uuid[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; int i, ret; uint8_t gpt_name[72], *type_uuid; #ifndef Libisofs_appended_partitions_inlinE if (!t->gpt_backup_outside) return 2; #endif /* Represent in GPT only if other GPT partitions are already registered or if appended partitions are explicitely desired for GPT-only. */ if (t->gpt_req_count == 0 && !(t->have_appended_partitions && t->opts->appended_as_gpt)) return 2; /* Represent appended partitions */ for (i = 0; i <= 3; i++) { if (t->opts->appended_partitions[i] == NULL) continue; memset(gpt_name, 0, 72); sprintf((char *) gpt_name, "Appended%d", i + 1); iso_ascii_utf_16le(gpt_name); if (t->opts->appended_part_types[i] == 0xef) type_uuid = efi_sys_uuid; else type_uuid = basic_data_uuid; ret = iso_quick_gpt_entry(t->gpt_req, &(t->gpt_req_count), ((uint64_t) t->appended_part_start[i]) * 4, ((uint64_t) t->appended_part_size[i]) * 4, type_uuid, zero_uuid, (uint64_t) 0, gpt_name); if (ret < 0) return ret; } return ISO_SUCCESS; } /* Probably already called by tail_writer_compute_data_blocks via iso_align_isohybrid */ static int precompute_gpt(Ecma119Image *t) { uint32_t gpt_part_start; int ret, sa_type; int gpt_count, gpt_idx[128], apm_count; /* Avoid repetition by gpt_tail_writer_compute_data_blocks */ t->gpt_is_computed = 1; /* Assess APM and GPT requests of isohybrid */ sa_type = (t->system_area_options >> 2) & 0x3f; if (sa_type == 0 && (t->system_area_options & 3) == 2) { /* >>> ISOHYBRID : Shall isohybrid be combinable with other APM and GPT requesters ? */; /* <<< provisorily: Not compatible */ ret = assess_isohybrid_gpt_apm(t, &gpt_count, gpt_idx, &apm_count, 0); if (ret < 0) return ret; if (t->gpt_req_count > 0 && gpt_count > 0) return ISO_BOOT_GPT_OVERLAP; if (t->apm_req_count > 0 && apm_count > 0) return ISO_BOOT_APM_OVERLAP; /* Register the GPT and APM partition entries */ ret = assess_isohybrid_gpt_apm(t, &gpt_count, gpt_idx, &apm_count, 1); if (ret < 0) return ret; } /* Rectify APM requests early in order to learn the size of GPT. iso_write_apm() relies on this being already done here. So perform even if no GPT is required. */ ret = rectify_apm(t); if (ret < 0) return ret; /* Assess impact of appended partitions on GPT */ ret = assess_appended_gpt(t, 0); #ifdef NIX /* Disabled */ /* <<< ts B20526 : Dummy mock-up */ if (t->gpt_req_count <= 0) { /* <<< ??? Move to system_area.h and publish as macro ? Or to make_isohybrid_mbr.c ? */ static uint8_t hfs_uuid[16] = { 0x00, 0x53, 0x46, 0x48, 0x00, 0x00, 0xaa, 0x11, 0xaa, 0x11, 0x00, 0x30, 0x65, 0x43, 0xec, 0xac }; static uint8_t basic_data_uuid[16] = { 0xa2, 0xa0, 0xd0, 0xeb, 0xe5, 0xb9, 0x33, 0x44, 0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7 }; uint8_t gpt_name[72]; static uint8_t zero_uuid[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static uint64_t gpt_flags = (((uint64_t) 1) << 60) | 1; memset(gpt_name, 0, 72); gpt_name[0] = 'T'; gpt_name[2] = '1'; strcpy((char *) gpt_name, "GPT Test 1"); iso_ascii_utf_16le(gpt_name); /* ret = iso_quick_gpt_entry(t->gpt_req, &(t->gpt_req_count), (uint64_t) (16 * 4), (uint64_t) (20 * 4), hfs_uuid, zero_uuid, gpt_flags, gpt_name); / * Caution: Size 90 causes intentional partition overlap error * / ret = iso_quick_gpt_entry(t->gpt_req, &(t->gpt_req_count), (uint64_t) (30 * 4), (uint64_t) (90 * 4), hfs_uuid, zero_uuid, gpt_flags, gpt_name); */ ret = iso_quick_gpt_entry(t->gpt_req, &(t->gpt_req_count), (uint64_t) (30 * 4), (uint64_t) (40 * 4), hfs_uuid, zero_uuid, gpt_flags, gpt_name); if (ret < 0) return ret; strcpy((char *) gpt_name, "GPT Test 2"); iso_ascii_utf_16le(gpt_name); ret = iso_quick_gpt_entry(t->gpt_req, &(t->gpt_req_count), (uint64_t) (110 * 4), (uint64_t) (60 * 4), basic_data_uuid, zero_uuid, gpt_flags, gpt_name); if (ret < 0) return ret; } #endif /* NIX */ /* Is a GPT requested ? */ t->gpt_backup_end = 0; t->gpt_max_entries = 0; if (t->gpt_req_count == 0) return ISO_SUCCESS; /* Determine GPT partition start in System Area, */ gpt_part_start = 0; if (t->apm_req_count > 0) { if (t->opts->apm_block_size == 0) t->opts->apm_block_size = 2048; gpt_part_start = (t->apm_req_count + 1) * (t->opts->apm_block_size / 512); } if (gpt_part_start < 2) gpt_part_start = 2; else if (gpt_part_start >= 64) return ISO_BOOT_TOO_MANY_GPT; t->gpt_part_start = gpt_part_start; /* Necessary number of 2K blocks */ t->gpt_max_entries = (64 - t->gpt_part_start) * 4; t->gpt_backup_size = ((t->gpt_max_entries / 4 + 1) * 512 + 2047) / 2048; return ISO_SUCCESS; } int gpt_tail_writer_compute_data_blocks(IsoImageWriter *writer) { Ecma119Image *t; int ret; if (writer == NULL) return ISO_ASSERT_FAILURE; t = writer->target; if (! t->gpt_is_computed) { ret = precompute_gpt(t); if (ret < 0) return ret; } if (t->gpt_backup_outside) { t->total_size += t->gpt_backup_size * 2048; /* The ISO block number after the backup GPT header */ t->gpt_backup_end = t->total_size / BLOCK_SIZE + t->opts->ms_block; } else { t->curblock += t->gpt_backup_size; /* The ISO block number after the backup GPT header */ t->gpt_backup_end = t->curblock; } return ISO_SUCCESS; } int gpt_tail_writer_write_vol_desc(IsoImageWriter *writer) { return ISO_SUCCESS; } static int gpt_tail_writer_write_data(IsoImageWriter *writer) { Ecma119Image *t; uint8_t *head, *new_head, *entries; uint8_t *backup_buf = NULL; uint32_t crc, i; uint64_t part_start; int ret; t = writer->target; if (t->gpt_backup_end == 0 || t->gpt_max_entries == 0) return ISO_SUCCESS; /* No backup GPT area reserved by compute_data() */ backup_buf = calloc(1, t->gpt_backup_size * 2048); if (backup_buf == NULL) return ISO_OUT_OF_MEM; memset(backup_buf, 0, t->gpt_backup_size * 2048); /* Check whether GPT header block came through */ head = t->sys_area_as_written + 512; if (strncmp((char *) head, "EFI PART", 8) != 0) { tampered_head:; /* Send error message but do not prevent further image production */ iso_msgs_submit(0, "GPT header block was altered before writing to System Area.", 0, "FAILURE", 0); goto write_zeros; } for (i = 92; i < 512; i++) if (head[i]) goto tampered_head; /* Patch memorized header block */ new_head = backup_buf + t->gpt_backup_size * 2048 - 512; memcpy(new_head, head, 512); /* Exchange "Location of this header" and "Location of header backup" */ memcpy(new_head + 24, head + 32, 8); memcpy(new_head + 32, head + 24, 8); /* Point to the backup partition entries */ part_start = ((uint64_t) t->gpt_backup_end) * 4 - 1 - t->gpt_max_entries / 4; iso_lsb(new_head + 72, part_start & 0xffffffff, 4); iso_lsb(new_head + 76, (part_start >> 32) & 0xffffffff, 4); /* Compute new header CRC */ memset(new_head + 16, 0, 4); crc = iso_crc32_gpt((unsigned char *) new_head, 92, 0); iso_lsb(new_head + 16, crc, 4); /* Copy GPT entries */ entries = t->sys_area_as_written + t->gpt_part_start * 512; memcpy(new_head - t->gpt_max_entries * 128, entries, t->gpt_max_entries * 128); ret = iso_write(t, backup_buf, t->gpt_backup_size * 2048); free(backup_buf); if (ret < 0) return ret; if (!t->gpt_backup_outside) { /* >>> Why isn't t->curblock updated ? */; } return ISO_SUCCESS; write_zeros:; ret = iso_write(t, backup_buf, t->gpt_backup_size * 2048); free(backup_buf); if (ret < 0) return ret; return ISO_SUCCESS; } static int gpt_tail_writer_free_data(IsoImageWriter *writer) { return ISO_SUCCESS; } int gpt_tail_writer_create(Ecma119Image *target) { IsoImageWriter *writer; writer = calloc(1, sizeof(IsoImageWriter)); if (writer == NULL) { return ISO_OUT_OF_MEM; } writer->compute_data_blocks = gpt_tail_writer_compute_data_blocks; writer->write_vol_desc = gpt_tail_writer_write_vol_desc; writer->write_data = gpt_tail_writer_write_data; writer->free_data = gpt_tail_writer_free_data; writer->data = NULL; writer->target = target; /* add this writer to image */ target->writers[target->nwriters++] = writer; return ISO_SUCCESS; } /* ---------------------- Partition Prepend Writer --------------------- */ static int partprepend_writer_compute_data_blocks(IsoImageWriter *writer) { Ecma119Image *t; IsoFileSrc *src; int ret, will_have_gpt = 0, with_chrp = 0, i; static uint8_t zero_uuid[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static uint64_t gpt_flags = (((uint64_t) 1) << 60) | 1; uint8_t gpt_name[72]; /* <<< ??? Move to system_area.h and publish as macro ? */ static uint8_t efi_sys_uuid[16] = { 0x28, 0x73, 0x2a, 0xc1, 0x1f, 0xf8, 0xd2, 0x11, 0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b }; if (writer == NULL) return ISO_ASSERT_FAILURE; t = writer->target; with_chrp = ((t->system_area_options & 0x3cff) == 0x0400); if (t->opts->efi_boot_partition != NULL || (t->opts->hfsplus && !with_chrp) || t->gpt_req_count > 0) will_have_gpt = 1; if (t->opts->efi_boot_partition != NULL) { if (t->efi_boot_part_filesrc != NULL) { /* A file in the emerging ISO image shall store its content as prepended partition. Install absolute block addresses and determine partition size. */ src = t->efi_boot_part_filesrc; t->efi_boot_part_size = 0; for (i = 0; i < src->nsections; i++) { src->sections[i].block = t->curblock + t->efi_boot_part_size; t->efi_boot_part_size += (src->sections[i].size + 2047) / 2048; } } else { ret = compute_partition_size(t, t->opts->efi_boot_partition, &(t->efi_boot_part_size), t->opts->efi_boot_part_flag & 1); if (ret < 0) return ret; } memset(gpt_name, 0, 72); strcpy((char *) gpt_name, "EFI boot partition"); iso_ascii_utf_16le(gpt_name); ret = iso_quick_gpt_entry(t->gpt_req, &(t->gpt_req_count), ((uint64_t) t->curblock) * 4, ((uint64_t) t->efi_boot_part_size) * 4, efi_sys_uuid, zero_uuid, gpt_flags, gpt_name); if (ret < 0) return ret; t->curblock += t->efi_boot_part_size; } if (with_chrp) { /* CHRP is not compatible with any other partition in MBR */ if (t->opts->prep_partition != NULL || t->opts->fat || will_have_gpt || t->mbr_req_count > 0) return ISO_BOOT_MBR_OVERLAP; ret = iso_quick_mbr_entry(t->mbr_req, &(t->mbr_req_count), (uint64_t) 0, (uint64_t) 0, 0x96, 0x80, 0); if (ret < 0) return ret; return ISO_SUCCESS; } if (t->opts->prep_partition != NULL) { ret = compute_partition_size(t, t->opts->prep_partition, &(t->prep_part_size), t->opts->prep_part_flag & 1); if (ret < 0) return ret; } if (t->prep_part_size > 0 || t->opts->fat || will_have_gpt) { /* Protecting MBR entry for ISO start or whole ISO */ ret = iso_quick_mbr_entry(t->mbr_req, &(t->mbr_req_count), will_have_gpt ? (uint64_t) 1 : ((uint64_t) t->opts->partition_offset) * 4, (uint64_t) 0, will_have_gpt ? 0xee : 0xcd, 0, 0); if (ret < 0) return ret; } if (t->prep_part_size > 0) { ret = iso_quick_mbr_entry(t->mbr_req, &(t->mbr_req_count), ((uint64_t) t->curblock) * 4, ((uint64_t) t->prep_part_size) * 4, 0x41, 0, 0); if (ret < 0) return ret; t->curblock += t->prep_part_size; } if (t->prep_part_size > 0 || t->opts->fat) { /* FAT partition or protecting MBR entry for ISO end */ ret = iso_quick_mbr_entry(t->mbr_req, &(t->mbr_req_count), ((uint64_t) t->curblock) * 4, (uint64_t) 0, t->opts->fat ? 0x0c : 0xcd, 0, 0); if (ret < 0) return ret; } return ISO_SUCCESS; } static int partprepend_writer_write_vol_desc(IsoImageWriter *writer) { return ISO_SUCCESS; } static int partprepend_writer_write_data(IsoImageWriter *writer) { Ecma119Image *t; int ret; t = writer->target; if (t->opts->efi_boot_partition != NULL && t->efi_boot_part_size) { if (t->efi_boot_part_filesrc != NULL) { ret = iso_filesrc_write_data(t, t->efi_boot_part_filesrc, NULL, NULL, 0); } else { ret = iso_write_partition_file(t, t->opts->efi_boot_partition, (uint32_t) 0, t->efi_boot_part_size, t->opts->efi_boot_part_flag & 1); } if (ret < 0) return ret; } if (t->opts->prep_partition != NULL && t->prep_part_size) { ret = iso_write_partition_file(t, t->opts->prep_partition, (uint32_t) 0, t->prep_part_size, t->opts->prep_part_flag & 1); if (ret < 0) return ret; } return ISO_SUCCESS; } static int partprepend_writer_free_data(IsoImageWriter *writer) { return ISO_SUCCESS; } int partprepend_writer_create(Ecma119Image *target) { IsoImageWriter *writer; writer = calloc(1, sizeof(IsoImageWriter)); if (writer == NULL) { return ISO_OUT_OF_MEM; } writer->compute_data_blocks = partprepend_writer_compute_data_blocks; writer->write_vol_desc = partprepend_writer_write_vol_desc; writer->write_data = partprepend_writer_write_data; writer->free_data = partprepend_writer_free_data; writer->data = NULL; writer->target = target; /* add this writer to image */ target->writers[target->nwriters++] = writer; return ISO_SUCCESS; } #ifdef Libisofs_appended_partitions_inlinE /* ----------------- Inline Partition Append Writer ------------------ */ static int partappend_writer_compute_data_blocks(IsoImageWriter *writer) { int ret; ret = iso_compute_append_partitions(writer->target, 1); return ret; } static int partappend_writer_write_vol_desc(IsoImageWriter *writer) { return ISO_SUCCESS; } static int partappend_writer_write_data(IsoImageWriter *writer) { Ecma119Image *target; int res, first_partition = 1, last_partition = 0, sa_type; int i; target = writer->target; /* Append partition data */ sa_type = (target->system_area_options >> 2) & 0x3f; if (sa_type == 0) { /* MBR */ first_partition = 1; last_partition = 4; } else if (sa_type == 3) { /* SUN Disk Label */ first_partition = 2; last_partition = 8; } for (i = first_partition - 1; i <= last_partition - 1; i++) { if (target->opts->appended_partitions[i] == NULL) continue; if (target->opts->appended_partitions[i][0] == 0) continue; res = iso_write_partition_file(target, target->opts->appended_partitions[i], target->appended_part_prepad[i], target->appended_part_size[i], target->appended_part_flags[i] & 1); if (res < 0) return res; target->curblock += target->appended_part_size[i]; } return ISO_SUCCESS; } static int partappend_writer_free_data(IsoImageWriter *writer) { return ISO_SUCCESS; } int partappend_writer_create(Ecma119Image *target) { IsoImageWriter *writer; writer = calloc(1, sizeof(IsoImageWriter)); if (writer == NULL) { return ISO_OUT_OF_MEM; } writer->compute_data_blocks = partappend_writer_compute_data_blocks; writer->write_vol_desc = partappend_writer_write_vol_desc; writer->write_data = partappend_writer_write_data; writer->free_data = partappend_writer_free_data; writer->data = NULL; writer->target = target; /* add this writer to image */ target->writers[target->nwriters++] = writer; return ISO_SUCCESS; } #endif /* Libisofs_appended_partitions_inlinE */ libisofs-1.4.2/libisofs/filters/0000755000175700017510000000000012626306721013630 500000000000000libisofs-1.4.2/libisofs/filters/zisofs.c0000644000175700017510000010622112562346646015244 00000000000000/* * Copyright (c) 2009 - 2011 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. * * It implements a filter facility which can pipe a IsoStream into zisofs * compression resp. uncompression, read its output and forward it as IsoStream * output to an IsoFile. * The zisofs format was invented by H. Peter Anvin. See doc/zisofs_format.txt * It is writeable and readable by zisofs-tools, readable by Linux kernels. * */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif #include "../libisofs.h" #include "../filter.h" #include "../fsource.h" #include "../util.h" #include "../stream.h" #include #include #include #include #include #include #include #ifdef Libisofs_with_zliB #include #else /* If zlib is not available then this code is a dummy */ #endif /* * A filter that encodes or decodes the content of zisofs compressed files. */ /* --------------------------- ZisofsFilterRuntime ------------------------- */ /* Sizes to be used for compression. Decompression learns from input header. */ static uint8_t ziso_block_size_log2 = 15; static int ziso_block_size = 32768; /* Individual runtime properties exist only as long as the stream is opened. */ typedef struct { int state; /* processing: 0= header, 1= block pointers, 2= data blocks */ int block_size; int block_pointer_fill; int block_pointer_rpos; uint32_t *block_pointers; /* These are in use only with uncompression. Compression streams hold the pointer in their persistent data. */ char *read_buffer; char *block_buffer; int buffer_size; int buffer_fill; int buffer_rpos; off_t block_counter; off_t in_counter; off_t out_counter; int error_ret; } ZisofsFilterRuntime; static int ziso_running_destroy(ZisofsFilterRuntime **running, int flag) { ZisofsFilterRuntime *o= *running; if (o == NULL) return 0; if (o->block_pointers != NULL) free(o->block_pointers); if (o->read_buffer != NULL) free(o->read_buffer); if (o->block_buffer != NULL) free(o->block_buffer); free((char *) o); *running = NULL; return 1; } /* * @param flag bit0= do not set block_size, do not allocate buffers */ static int ziso_running_new(ZisofsFilterRuntime **running, int flag) { ZisofsFilterRuntime *o; *running = o = calloc(sizeof(ZisofsFilterRuntime), 1); if (o == NULL) { return ISO_OUT_OF_MEM; } o->state = 0; o->block_size= 0; o->block_pointer_fill = 0; o->block_pointer_rpos = 0; o->block_pointers = NULL; o->read_buffer = NULL; o->block_buffer = NULL; o->buffer_size = 0; o->buffer_fill = 0; o->buffer_rpos = 0; o->block_counter = 0; o->in_counter = 0; o->out_counter = 0; o->error_ret = 0; if (flag & 1) return 1; o->block_size = ziso_block_size; #ifdef Libisofs_with_zliB o->buffer_size = compressBound((uLong) ziso_block_size); #else o->buffer_size = 2 * ziso_block_size; #endif o->read_buffer = calloc(o->block_size, 1); o->block_buffer = calloc(o->buffer_size, 1); if (o->block_buffer == NULL || o->read_buffer == NULL) goto failed; return 1; failed: ziso_running_destroy(running, 0); return -1; } /* ---------------------------- ZisofsFilterStreamData --------------------- */ /* The first 8 bytes of a zisofs compressed data file */ static unsigned char zisofs_magic[9] = {0x37, 0xE4, 0x53, 0x96, 0xC9, 0xDB, 0xD6, 0x07}; /* Counts the number of active compression filters */ static off_t ziso_ref_count = 0; /* Counts the number of active uncompression filters */ static off_t ziso_osiz_ref_count = 0; #ifdef Libisofs_with_zliB /* Parameter for compress2() , see */ static int ziso_compression_level = 6; #endif /* Libisofs_with_zliB */ /* * The common data payload of an individual Zisofs Filter IsoStream * IMPORTANT: Any change must be reflected by ziso_clone_stream(). */ typedef struct { IsoStream *orig; off_t size; /* -1 means that the size is unknown yet */ ZisofsFilterRuntime *running; /* is non-NULL when open */ ino_t id; } ZisofsFilterStreamData; /* * The data payload of an individual Zisofs Filter Compressor IsoStream * IMPORTANT: Any change must be reflected by ziso_clone_stream(). */ typedef struct { ZisofsFilterStreamData std; uint32_t orig_size; uint32_t *block_pointers; /* Cache for output block addresses. They get written before the data and so need 2 passes. This cache avoids surplus passes. */ } ZisofsComprStreamData; /* * The data payload of an individual Zisofs Filter Uncompressor IsoStream * IMPORTANT: Any change must be reflected by ziso_clone_stream(). */ typedef struct { ZisofsFilterStreamData std; unsigned char header_size_div4; unsigned char block_size_log2; } ZisofsUncomprStreamData; /* Each individual ZisofsFilterStreamData needs a unique id number. */ /* >>> This is very suboptimal: The counter can rollover. */ static ino_t ziso_ino_id = 0; /* * Methods for the IsoStreamIface of an Zisofs Filter object. */ static int ziso_stream_uncompress(IsoStream *stream, void *buf, size_t desired); /* * @param flag bit0= original stream is not open */ static int ziso_stream_close_flag(IsoStream *stream, int flag) { ZisofsFilterStreamData *data; if (stream == NULL) { return ISO_NULL_POINTER; } data = stream->data; if (data->running == NULL) { return 1; } ziso_running_destroy(&(data->running), 0); if (flag & 1) return 1; return iso_stream_close(data->orig); } static int ziso_stream_close(IsoStream *stream) { return ziso_stream_close_flag(stream, 0); } /* * @param flag bit0= do not run .get_size() if size is < 0 */ static int ziso_stream_open_flag(IsoStream *stream, int flag) { ZisofsFilterStreamData *data; ZisofsFilterRuntime *running = NULL; int ret; if (stream == NULL) { return ISO_NULL_POINTER; } data = (ZisofsFilterStreamData*) stream->data; if (data->running != NULL) { return ISO_FILE_ALREADY_OPENED; } if (data->size < 0 && !(flag & 1)) { /* Do the size determination run now, so that the size gets cached and .get_size() will not fail on an opened stream. */ stream->class->get_size(stream); } ret = ziso_running_new(&running, stream->class->read == &ziso_stream_uncompress); if (ret < 0) { return ret; } data->running = running; ret = iso_stream_open(data->orig); if (ret < 0) { return ret; } return 1; } static int ziso_stream_open(IsoStream *stream) { return ziso_stream_open_flag(stream, 0); } static int ziso_stream_compress(IsoStream *stream, void *buf, size_t desired) { #ifdef Libisofs_with_zliB int ret, todo, i; ZisofsComprStreamData *data; ZisofsFilterRuntime *rng; size_t fill = 0; off_t orig_size, next_pt; char *cbuf = buf; uLongf buf_len; if (stream == NULL) { return ISO_NULL_POINTER; } data = stream->data; rng= data->std.running; if (rng == NULL) { return ISO_FILE_NOT_OPENED; } if (rng->error_ret < 0) { return rng->error_ret; } while (1) { if (rng->state == 0) { /* Delivering file header */ if (rng->buffer_fill == 0) { memcpy(rng->block_buffer, zisofs_magic, 8); orig_size = iso_stream_get_size(data->std.orig); if (orig_size > 4294967295.0) { return (rng->error_ret = ISO_ZISOFS_TOO_LARGE); } data->orig_size = orig_size; iso_lsb((unsigned char *) (rng->block_buffer + 8), (uint32_t) orig_size, 4); rng->block_buffer[12] = 4; rng->block_buffer[13] = ziso_block_size_log2; rng->block_buffer[14] = rng->block_buffer[15] = 0; rng->buffer_fill = 16; rng->buffer_rpos = 0; } else if (rng->buffer_rpos >= rng->buffer_fill) { rng->buffer_fill = rng->buffer_rpos = 0; rng->state = 1; /* header is delivered */ } } if (rng->state == 1) { /* Delivering block pointers */; if (rng->block_pointer_fill == 0) { /* Initialize block pointer writing */ rng->block_pointer_rpos = 0; rng->block_pointer_fill = data->orig_size / rng->block_size + 1 + !!(data->orig_size % rng->block_size); if (data->block_pointers == NULL) { /* On the first pass, create pointer array with all 0s */ data->block_pointers = calloc(rng->block_pointer_fill, 4); if (data->block_pointers == NULL) { rng->block_pointer_fill = 0; return (rng->error_ret = ISO_OUT_OF_MEM); } } } if (rng->buffer_rpos >= rng->buffer_fill) { if (rng->block_pointer_rpos >= rng->block_pointer_fill) { rng->buffer_fill = rng->buffer_rpos = 0; rng->block_counter = 0; data->block_pointers[0] = 16 + rng->block_pointer_fill * 4; rng->state = 2; /* block pointers are delivered */ } else { /* Provide a buffer full of block pointers */ todo = rng->block_pointer_fill - rng->block_pointer_rpos; if (todo * 4 > rng->buffer_size) todo = rng->buffer_size / 4; memcpy(rng->block_buffer, data->block_pointers + rng->block_pointer_rpos, todo * 4); rng->buffer_rpos = 0; rng->buffer_fill = todo * 4; rng->block_pointer_rpos += todo; } } } if (rng->state == 2 && rng->buffer_rpos >= rng->buffer_fill) { /* Delivering data blocks */; ret = iso_stream_read(data->std.orig, rng->read_buffer, rng->block_size); if (ret > 0) { rng->in_counter += ret; if (rng->in_counter > data->orig_size) { /* Input size became larger */ return (rng->error_ret = ISO_FILTER_WRONG_INPUT); } /* Check whether all 0 : represent as 0-length block */; for (i = 0; i < ret; i++) if (rng->read_buffer[i]) break; if (i >= ret) { /* All 0-bytes. Bypass compression. */ buf_len = 0; } else { buf_len = rng->buffer_size; ret = compress2((Bytef *) rng->block_buffer, &buf_len, (Bytef *) rng->read_buffer, (uLong) ret, ziso_compression_level); if (ret != Z_OK) { return (rng->error_ret = ISO_ZLIB_COMPR_ERR); } } rng->buffer_fill = buf_len; rng->buffer_rpos = 0; next_pt = data->block_pointers[rng->block_counter] + buf_len; if (data->std.size >= 0 && next_pt > data->std.size) { /* Compression yields more bytes than on first run */ return (rng->error_ret = ISO_FILTER_WRONG_INPUT); } /* Record resp. check block pointer */ rng->block_counter++; if (data->block_pointers[rng->block_counter] > 0) { if (next_pt != data->block_pointers[rng->block_counter] ) { /* block pointers mismatch , content has changed */ return (rng->error_ret = ISO_FILTER_WRONG_INPUT); } } else { data->block_pointers[rng->block_counter] = next_pt; } } else if (ret == 0) { rng->state = 3; if (rng->in_counter != data->orig_size) { /* Input size shrunk */ return (rng->error_ret = ISO_FILTER_WRONG_INPUT); } return fill; } else return (rng->error_ret = ret); if (rng->buffer_fill == 0) { continue; } } if (rng->state == 3 && rng->buffer_rpos >= rng->buffer_fill) { return 0; /* EOF */ } /* Transfer from rng->block_buffer to buf */ todo = desired - fill; if (todo > rng->buffer_fill - rng->buffer_rpos) todo = rng->buffer_fill - rng->buffer_rpos; memcpy(cbuf + fill, rng->block_buffer + rng->buffer_rpos, todo); fill += todo; rng->buffer_rpos += todo; rng->out_counter += todo; if (fill >= desired) { return fill; } } return ISO_FILE_READ_ERROR; /* should never be hit */ #else return ISO_ZLIB_NOT_ENABLED; #endif } static int ziso_parse_zisofs_head(IsoStream *stream, int *header_size_div4, int *block_size_log2, uint32_t *uncompressed_size, int flag) { int ret; char zisofs_head[16]; ret = iso_stream_read(stream, zisofs_head, 16); if (ret < 0) return ret; *header_size_div4 = ((unsigned char *) zisofs_head)[12]; *block_size_log2 = ((unsigned char *) zisofs_head)[13]; if (ret != 16 || memcmp(zisofs_head, zisofs_magic, 8) != 0 || *header_size_div4 < 4 || *block_size_log2 < 15 || *block_size_log2 > 17) { return ISO_ZISOFS_WRONG_INPUT; } *uncompressed_size = iso_read_lsb(((uint8_t *) zisofs_head) + 8, 4); return 1; } /* Note: A call with desired==0 directly after .open() only checks the file head and loads the uncompressed size from that head. */ static int ziso_stream_uncompress(IsoStream *stream, void *buf, size_t desired) { #ifdef Libisofs_with_zliB int ret, todo, i, header_size, bs_log2, block_max = 1; ZisofsFilterStreamData *data; ZisofsFilterRuntime *rng; ZisofsUncomprStreamData *nstd; size_t fill = 0; char *cbuf = buf; uLongf buf_len; uint32_t uncompressed_size; char waste_word[4]; if (stream == NULL) { return ISO_NULL_POINTER; } data = stream->data; nstd = stream->data; rng= data->running; if (rng == NULL) { return ISO_FILE_NOT_OPENED; } if (rng->error_ret < 0) { return rng->error_ret; } while (1) { if (rng->state == 0) { /* Reading file header */ ret = ziso_parse_zisofs_head(data->orig, &header_size, &bs_log2, &uncompressed_size, 0); if (ret < 0) return (rng->error_ret = ret); nstd->header_size_div4 = header_size; header_size *= 4; data->size = uncompressed_size; nstd->block_size_log2 = bs_log2; rng->block_size = 1 << bs_log2; for (i = 16; i < header_size; i += 4) { /* Skip surplus header words */ ret = iso_stream_read(data->orig, waste_word, 4); if (ret < 0) return (rng->error_ret = ret); if (ret != 4) return (rng->error_ret = ISO_ZISOFS_WRONG_INPUT); } if (desired == 0) { return 0; } /* Create and read pointer array */ rng->block_pointer_rpos = 0; rng->block_pointer_fill = data->size / rng->block_size + 1 + !!(data->size % rng->block_size); rng->block_pointers = calloc(rng->block_pointer_fill, 4); if (rng->block_pointers == NULL) { rng->block_pointer_fill = 0; return (rng->error_ret = ISO_OUT_OF_MEM); } ret = iso_stream_read(data->orig, rng->block_pointers, rng->block_pointer_fill * 4); if (ret < 0) return (rng->error_ret = ret); if (ret != rng->block_pointer_fill * 4) return (rng->error_ret = ISO_ZISOFS_WRONG_INPUT); for (i = 0; i < rng->block_pointer_fill; i++) { rng->block_pointers[i] = iso_read_lsb((uint8_t *) (rng->block_pointers + i), 4); if (i > 0) if ((int) (rng->block_pointers[i] - rng->block_pointers[i - 1]) > block_max) block_max = rng->block_pointers[i] - rng->block_pointers[i - 1]; } rng->read_buffer = calloc(block_max, 1); rng->block_buffer = calloc(rng->block_size, 1); if (rng->read_buffer == NULL || rng->block_buffer == NULL) return (rng->error_ret = ISO_OUT_OF_MEM); rng->state = 2; /* block pointers are read */ rng->buffer_fill = rng->buffer_rpos = 0; } if (rng->state == 2 && rng->buffer_rpos >= rng->buffer_fill) { /* Delivering data blocks */; i = ++(rng->block_pointer_rpos); if (i >= rng->block_pointer_fill) { if (rng->out_counter == data->size) { rng->state = 3; rng->block_pointer_rpos--; return fill; } /* More data blocks needed than announced */ return (rng->error_ret = ISO_FILTER_WRONG_INPUT); } todo = rng->block_pointers[i] - rng->block_pointers[i- 1]; if (todo == 0) { memset(rng->block_buffer, 0, rng->block_size); rng->buffer_fill = rng->block_size; if (rng->out_counter + rng->buffer_fill > data->size && i == rng->block_pointer_fill - 1) rng->buffer_fill = data->size - rng->out_counter; } else { ret = iso_stream_read(data->orig, rng->read_buffer, todo); if (ret > 0) { rng->in_counter += ret; buf_len = rng->block_size; ret = uncompress((Bytef *) rng->block_buffer, &buf_len, (Bytef *) rng->read_buffer, (uLong) ret); if (ret != Z_OK) return (rng->error_ret = ISO_ZLIB_COMPR_ERR); rng->buffer_fill = buf_len; if ((int) buf_len < rng->block_size && i != rng->block_pointer_fill - 1) return (rng->error_ret = ISO_ZISOFS_WRONG_INPUT); } else if(ret == 0) { rng->state = 3; if (rng->out_counter != data->size) { /* Input size shrunk */ return (rng->error_ret = ISO_FILTER_WRONG_INPUT); } return fill; } else return (rng->error_ret = ret); } rng->buffer_rpos = 0; if (rng->out_counter + rng->buffer_fill > data->size) { /* Uncompression yields more bytes than announced by header */ return (rng->error_ret = ISO_FILTER_WRONG_INPUT); } } if (rng->state == 3 && rng->buffer_rpos >= rng->buffer_fill) { return 0; /* EOF */ } /* Transfer from rng->block_buffer to buf */ todo = desired - fill; if (todo > rng->buffer_fill - rng->buffer_rpos) todo = rng->buffer_fill - rng->buffer_rpos; memcpy(cbuf + fill, rng->block_buffer + rng->buffer_rpos, todo); fill += todo; rng->buffer_rpos += todo; rng->out_counter += todo; if (fill >= desired) { return fill; } } return (rng->error_ret = ISO_FILE_READ_ERROR); /* should never be hit */ #else return ISO_ZLIB_NOT_ENABLED; #endif } static off_t ziso_stream_get_size(IsoStream *stream) { int ret, ret_close; off_t count = 0; ZisofsFilterStreamData *data; char buf[64 * 1024]; size_t bufsize = 64 * 1024; if (stream == NULL) { return ISO_NULL_POINTER; } data = stream->data; if (data->size >= 0) { return data->size; } /* Run filter command and count output bytes */ ret = ziso_stream_open_flag(stream, 1); if (ret < 0) { return ret; } if (stream->class->read == &ziso_stream_uncompress) { /* It is enough to read the header part of a compressed file */ ret = ziso_stream_uncompress(stream, buf, 0); count = data->size; } else { /* The size of the compression result has to be counted */ while (1) { ret = stream->class->read(stream, buf, bufsize); if (ret <= 0) break; count += ret; } } ret_close = ziso_stream_close(stream); if (ret < 0) return ret; if (ret_close < 0) return ret_close; data->size = count; return count; } static int ziso_stream_is_repeatable(IsoStream *stream) { /* Only repeatable streams are accepted as orig */ return 1; } static void ziso_stream_get_id(IsoStream *stream, unsigned int *fs_id, dev_t *dev_id, ino_t *ino_id) { ZisofsFilterStreamData *data; data = stream->data; *fs_id = ISO_FILTER_FS_ID; *dev_id = ISO_FILTER_ZISOFS_DEV_ID; *ino_id = data->id; } static void ziso_stream_free(IsoStream *stream) { ZisofsFilterStreamData *data; ZisofsComprStreamData *nstd; if (stream == NULL) { return; } data = stream->data; if (data->running != NULL) { ziso_stream_close(stream); } if (stream->class->read == &ziso_stream_uncompress) { if (--ziso_osiz_ref_count < 0) ziso_osiz_ref_count = 0; } else { nstd = stream->data; if (nstd->block_pointers != NULL) free((char *) nstd->block_pointers); if (--ziso_ref_count < 0) ziso_ref_count = 0; } iso_stream_unref(data->orig); free(data); } static int ziso_update_size(IsoStream *stream) { /* By principle size is determined only once */ return 1; } static IsoStream *ziso_get_input_stream(IsoStream *stream, int flag) { ZisofsFilterStreamData *data; if (stream == NULL) { return NULL; } data = stream->data; return data->orig; } static int ziso_clone_stream(IsoStream *old_stream, IsoStream **new_stream, int flag) { int ret; IsoStream *new_input_stream = NULL, *stream = NULL; ZisofsFilterStreamData *stream_data, *old_stream_data; ZisofsUncomprStreamData *uncompr, *old_uncompr; ZisofsComprStreamData *compr, *old_compr; if (flag) return ISO_STREAM_NO_CLONE; /* unknown option required */ ret = iso_stream_clone_filter_common(old_stream, &stream, &new_input_stream, 0); if (ret < 0) return ret; if (old_stream->class->read == &ziso_stream_uncompress) { uncompr = calloc(1, sizeof(ZisofsUncomprStreamData)); if (uncompr == NULL) goto no_mem; stream_data = (ZisofsFilterStreamData *) uncompr; old_uncompr = (ZisofsUncomprStreamData *) old_stream->data; uncompr->header_size_div4 = old_uncompr->header_size_div4; uncompr->block_size_log2 = old_uncompr->block_size_log2; } else { compr = calloc(1, sizeof(ZisofsComprStreamData)); if (compr == NULL) goto no_mem; stream_data = (ZisofsFilterStreamData *) compr; old_compr = (ZisofsComprStreamData *) old_stream->data; compr->orig_size = old_compr->orig_size; compr->block_pointers = NULL; } old_stream_data = (ZisofsFilterStreamData *) old_stream->data; stream_data->orig = new_input_stream; stream_data->size = old_stream_data->size; stream_data->running = NULL; stream_data->id = ++ziso_ino_id; stream->data = stream_data; *new_stream = stream; return ISO_SUCCESS; no_mem: if (new_input_stream != NULL) iso_stream_unref(new_input_stream); if (stream != NULL) iso_stream_unref(stream); return ISO_OUT_OF_MEM; } static int ziso_cmp_ino(IsoStream *s1, IsoStream *s2); static int ziso_uncompress_cmp_ino(IsoStream *s1, IsoStream *s2); IsoStreamIface ziso_stream_compress_class = { 4, "ziso", ziso_stream_open, ziso_stream_close, ziso_stream_get_size, ziso_stream_compress, ziso_stream_is_repeatable, ziso_stream_get_id, ziso_stream_free, ziso_update_size, ziso_get_input_stream, ziso_cmp_ino, ziso_clone_stream }; IsoStreamIface ziso_stream_uncompress_class = { 4, "osiz", ziso_stream_open, ziso_stream_close, ziso_stream_get_size, ziso_stream_uncompress, ziso_stream_is_repeatable, ziso_stream_get_id, ziso_stream_free, ziso_update_size, ziso_get_input_stream, ziso_uncompress_cmp_ino, ziso_clone_stream }; static int ziso_cmp_ino(IsoStream *s1, IsoStream *s2) { /* This function may rely on being called by iso_stream_cmp_ino() only with s1, s2 which both point to it as their .cmp_ino() function. It would be a programming error to let any other than ziso_stream_compress_class point to ziso_cmp_ino(). */ if (s1->class != s2->class || (s1->class != &ziso_stream_compress_class && s2->class != &ziso_stream_uncompress_class)) iso_stream_cmp_ino(s1, s2, 1); /* Both streams apply the same treatment to their input streams */ return iso_stream_cmp_ino(iso_stream_get_input_stream(s1, 0), iso_stream_get_input_stream(s2, 0), 0); } static int ziso_uncompress_cmp_ino(IsoStream *s1, IsoStream *s2) { /* This function may rely on being called by iso_stream_cmp_ino() only with s1, s2 which both point to it as their .cmp_ino() function. It would be a programming error to let any other than ziso_stream_uncompress_class point to ziso_uncompress_cmp_ino(). This fallback endangers transitivity of iso_stream_cmp_ino(). */ if (s1->class != s2->class || (s1->class != &ziso_stream_uncompress_class && s2->class != &ziso_stream_uncompress_class)) iso_stream_cmp_ino(s1, s2, 1); /* Both streams apply the same treatment to their input streams */ return iso_stream_cmp_ino(iso_stream_get_input_stream(s1, 0), iso_stream_get_input_stream(s2, 0), 0); } /* ------------------------------------------------------------------------- */ #ifdef Libisofs_with_zliB static void ziso_filter_free(FilterContext *filter) { /* no data are allocated */; } /* * @param flag bit1= Install a decompression filter */ static int ziso_filter_get_filter(FilterContext *filter, IsoStream *original, IsoStream **filtered, int flag) { IsoStream *str; ZisofsFilterStreamData *data; ZisofsComprStreamData *cnstd = NULL; ZisofsUncomprStreamData *unstd = NULL; if (filter == NULL || original == NULL || filtered == NULL) { return ISO_NULL_POINTER; } str = calloc(sizeof(IsoStream), 1); if (str == NULL) { return ISO_OUT_OF_MEM; } if (flag & 2) { unstd = calloc(sizeof(ZisofsUncomprStreamData), 1); data = (ZisofsFilterStreamData *) unstd; } else { cnstd = calloc(sizeof(ZisofsComprStreamData), 1); data = (ZisofsFilterStreamData *) cnstd; } if (data == NULL) { free(str); return ISO_OUT_OF_MEM; } /* These data items are not owned by this filter object */ data->id = ++ziso_ino_id; data->orig = original; data->size = -1; data->running = NULL; /* get reference to the source */ iso_stream_ref(data->orig); str->refcount = 1; str->data = data; if (flag & 2) { unstd->header_size_div4 = 0; unstd->block_size_log2 = 0; str->class = &ziso_stream_uncompress_class; ziso_osiz_ref_count++; } else { cnstd->orig_size = 0; cnstd->block_pointers = NULL; str->class = &ziso_stream_compress_class; ziso_ref_count++; } *filtered = str; return ISO_SUCCESS; } /* To be called by iso_file_add_filter(). * The FilterContext input parameter is not furtherly needed for the * emerging IsoStream. */ static int ziso_filter_get_compressor(FilterContext *filter, IsoStream *original, IsoStream **filtered) { return ziso_filter_get_filter(filter, original, filtered, 0); } static int ziso_filter_get_uncompressor(FilterContext *filter, IsoStream *original, IsoStream **filtered) { return ziso_filter_get_filter(filter, original, filtered, 2); } /* Produce a parameter object suitable for iso_file_add_filter(). * It may be disposed by free() after all those calls are made. * * This is quite a dummy as it does not carry individual data. * @param flag bit1= Install a decompression filter */ static int ziso_create_context(FilterContext **filter, int flag) { FilterContext *f; *filter = f = calloc(1, sizeof(FilterContext)); if (f == NULL) { return ISO_OUT_OF_MEM; } f->refcount = 1; f->version = 0; f->data = NULL; f->free = ziso_filter_free; if (flag & 2) f->get_filter = ziso_filter_get_uncompressor; else f->get_filter = ziso_filter_get_compressor; return ISO_SUCCESS; } #endif /* Libisofs_with_zliB */ /* * @param flag bit0= if_block_reduction rather than if_reduction * bit1= Install a decompression filter * bit2= only inquire availability of zisofs filtering * bit3= do not inquire size */ int ziso_add_filter(IsoFile *file, int flag) { #ifdef Libisofs_with_zliB int ret; FilterContext *f = NULL; IsoStream *stream; off_t original_size = 0, filtered_size = 0; if (flag & 4) return 2; original_size = iso_file_get_size(file); if (!(flag & 2)) { if (original_size <= 0 || ((flag & 1) && original_size <= 2048)) { return 2; } if (original_size > 4294967295.0) { return ISO_ZISOFS_TOO_LARGE; } } ret = ziso_create_context(&f, flag & 2); if (ret < 0) { return ret; } ret = iso_file_add_filter(file, f, 0); free(f); if (ret < 0) { return ret; } if (flag & 8) /* size will be filled in by caller */ return ISO_SUCCESS; /* Run a full filter process getsize so that the size is cached */ stream = iso_file_get_stream(file); filtered_size = iso_stream_get_size(stream); if (filtered_size < 0) { iso_file_remove_filter(file, 0); return filtered_size; } if ((filtered_size >= original_size || ((flag & 1) && filtered_size / 2048 >= original_size / 2048)) && !(flag & 2)){ ret = iso_file_remove_filter(file, 0); if (ret < 0) { return ret; } return 2; } return ISO_SUCCESS; #else return ISO_ZLIB_NOT_ENABLED; #endif /* ! Libisofs_with_zliB */ } /* API function */ int iso_file_add_zisofs_filter(IsoFile *file, int flag) { return ziso_add_filter(file, flag & ~8); } /* API function */ int iso_zisofs_get_refcounts(off_t *ziso_count, off_t *osiz_count, int flag) { *ziso_count = ziso_ref_count; *osiz_count = ziso_osiz_ref_count; return ISO_SUCCESS; } int ziso_add_osiz_filter(IsoFile *file, uint8_t header_size_div4, uint8_t block_size_log2, uint32_t uncompressed_size, int flag) { #ifdef Libisofs_with_zliB int ret; ZisofsUncomprStreamData *unstd; ret = ziso_add_filter(file, 2 | 8); if (ret < 0) return ret; unstd = iso_file_get_stream(file)->data; unstd->header_size_div4 = header_size_div4; unstd->block_size_log2 = block_size_log2; unstd->std.size = uncompressed_size; return ISO_SUCCESS; #else return ISO_ZLIB_NOT_ENABLED; #endif /* ! Libisofs_with_zliB */ } /* Determine stream type : 1=ziso , -1=osiz , 0=other , 2=ziso_by_content and eventual ZF field parameters @param flag bit0= allow ziso_by_content which is based on content reading bit1= do not inquire stream->class for filters */ int ziso_is_zisofs_stream(IsoStream *stream, int *stream_type, int *header_size_div4, int *block_size_log2, uint32_t *uncompressed_size, int flag) { int ret, close_ret; ZisofsFilterStreamData *data; ZisofsComprStreamData *cnstd; ZisofsUncomprStreamData *unstd; *stream_type = 0; if (stream->class == &ziso_stream_compress_class && !(flag & 2)) { *stream_type = 1; cnstd = stream->data; *header_size_div4 = 4; *block_size_log2 = ziso_block_size_log2; *uncompressed_size = cnstd->orig_size; return 1; } else if(stream->class == &ziso_stream_uncompress_class && !(flag & 2)) { *stream_type = -1; data = stream->data; unstd = stream->data; *header_size_div4 = unstd->header_size_div4; *block_size_log2 = unstd->block_size_log2; *uncompressed_size = data->size; return 1; } if (!(flag & 1)) return 0; ret = iso_stream_open(stream); if (ret < 0) return ret; ret = ziso_parse_zisofs_head(stream, header_size_div4, block_size_log2, uncompressed_size, 0); if (ret == 1) { *stream_type = 2; } else { ret = 0; } close_ret = iso_stream_close(stream); if (close_ret < 0) return close_ret; return ret; } int iso_zisofs_set_params(struct iso_zisofs_ctrl *params, int flag) { #ifdef Libisofs_with_zliB if (params->compression_level < 0 || params->compression_level > 9 || params->block_size_log2 < 15 || params->block_size_log2 > 17) { return ISO_WRONG_ARG_VALUE; } if (ziso_ref_count > 0) { return ISO_ZISOFS_PARAM_LOCK; } ziso_compression_level = params->compression_level; ziso_block_size_log2 = params->block_size_log2; ziso_block_size = 1 << ziso_block_size_log2; return 1; #else return ISO_ZLIB_NOT_ENABLED; #endif /* ! Libisofs_with_zliB */ } int iso_zisofs_get_params(struct iso_zisofs_ctrl *params, int flag) { #ifdef Libisofs_with_zliB params->compression_level = ziso_compression_level; params->block_size_log2 = ziso_block_size_log2; return 1; #else return ISO_ZLIB_NOT_ENABLED; #endif /* ! Libisofs_with_zliB */ } libisofs-1.4.2/libisofs/filters/external.c0000644000175700017510000005231412607143621015540 00000000000000/* * Copyright (c) 2009 - 2011 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. * * It implements a filter facility which can pipe a IsoStream into an external * process, read its output and forward it as IsoStream output to an IsoFile. * The external processes get started according to an IsoExternalFilterCommand * which is described in libisofs.h. * */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif #include "../libisofs.h" #include "../filter.h" #include "../fsource.h" #include "../stream.h" #include #include #include #include #include #include #include #include #include #ifdef Libisofs_external_filters_selecT #include #endif /* * A filter that starts an external process and uses its stdin and stdout * for classical pipe filtering. */ /* IMPORTANT: Any change must be reflected by extf_clone_stream() */ /* * Individual runtime properties exist only as long as the stream is opened. */ typedef struct { int send_fd; int recv_fd; pid_t pid; off_t in_counter; int in_eof; off_t out_counter; int out_eof; uint8_t pipebuf[2048]; /* buffers in case of EAGAIN on write() */ int pipebuf_fill; } ExternalFilterRuntime; static int extf_running_new(ExternalFilterRuntime **running, int send_fd, int recv_fd, pid_t child_pid, int flag) { ExternalFilterRuntime *o; *running = o = calloc(sizeof(ExternalFilterRuntime), 1); if (o == NULL) { return ISO_OUT_OF_MEM; } o->send_fd = send_fd; o->recv_fd = recv_fd; o->pid = child_pid; o->in_counter = 0; o->in_eof = 0; o->out_counter = 0; o->out_eof = 0; memset(o->pipebuf, 0, sizeof(o->pipebuf)); o->pipebuf_fill = 0; return 1; } /* * The data payload of an individual IsoStream from External Filter */ typedef struct { ino_t id; IsoStream *orig; IsoExternalFilterCommand *cmd; off_t size; /* -1 means that the size is unknown yet */ ExternalFilterRuntime *running; /* is non-NULL when open */ } ExternalFilterStreamData; /* Each individual ExternalFilterStreamData needs a unique id number. */ /* >>> This is very suboptimal: The counter can rollover. */ static ino_t extf_ino_id = 0; /* <<< */ static int print_fd= 0; /* * Methods for the IsoStreamIface of an External Filter object. */ /* * @param flag bit0= original stream is not open */ static int extf_stream_close_flag(IsoStream *stream, int flag) { int ret, status; ExternalFilterStreamData *data; if (stream == NULL) { return ISO_NULL_POINTER; } data = stream->data; if (data->running == NULL) { return 1; } /* <<< */ if (print_fd) { fprintf(stderr, "libisofs_DEBUG: filter close in = %d , ic= %.f\n", data->running->recv_fd, (double) data->running->in_counter); fprintf(stderr, "libisofs_DEBUG: filter close out = %d , oc= %.f\n", data->running->send_fd, (double) data->running->out_counter); } if(data->running->recv_fd != -1) close(data->running->recv_fd); if(data->running->send_fd != -1) close(data->running->send_fd); ret = waitpid(data->running->pid, &status, WNOHANG); if (ret == 0 && data->running->pid != 0) { kill(data->running->pid, SIGKILL); waitpid(data->running->pid, &status, 0); } free(data->running); data->running = NULL; if (flag & 1) return 1; return iso_stream_close(data->orig); } static int extf_stream_close(IsoStream *stream) { return extf_stream_close_flag(stream, 0); } /* * @param flag bit0= do not run .get_size() if size is < 0 */ static int extf_stream_open_flag(IsoStream *stream, int flag) { ExternalFilterStreamData *data; ExternalFilterRuntime *running = NULL; pid_t child_pid; int send_pipe[2], recv_pipe[2], ret, stream_open = 0; send_pipe[0] = send_pipe[1] = recv_pipe[0] = recv_pipe[1] = -1; if (stream == NULL) { return ISO_NULL_POINTER; } data = (ExternalFilterStreamData*)stream->data; if (data->running != NULL) { return ISO_FILE_ALREADY_OPENED; } if (data->size < 0 && !(flag & 1)) { /* Do the size determination run now, so that the size gets cached and .get_size() will not fail on an opened stream. */ stream->class->get_size(stream); } ret = pipe(send_pipe); if (ret == -1) { ret = ISO_OUT_OF_MEM; goto parent_failed; } ret = pipe(recv_pipe); if (ret == -1) { ret = ISO_OUT_OF_MEM; goto parent_failed; } child_pid= fork(); if (child_pid == -1) { ret = ISO_DATA_SOURCE_FATAL; goto parent_failed; } if (child_pid != 0) { /* parent */ ret = extf_running_new(&running, send_pipe[1], recv_pipe[0], child_pid, 0); if (ret < 0) { goto parent_failed; } data->running = running; /* <<< */ if (print_fd) { fprintf(stderr, "libisofs_DEBUG: filter parent in = %d\n", data->running->recv_fd); fprintf(stderr, "libisofs_DEBUG: filter parent out = %d\n", data->running->send_fd); } /* Give up the child-side pipe ends */ close(send_pipe[0]); close(recv_pipe[1]); /* Open stream only after forking so that the child does not know the pipe inlets of eventually underlying other filter streams. They would stay open and prevent those underlying filter children from seeing EOF at their input. */ ret = iso_stream_open(data->orig); /* <<< TEST <<< ret= ISO_FILE_READ_ERROR; */ if (ret < 0) { /* Dispose pipes and child */ extf_stream_close_flag(stream, 1); return ret; } stream_open = 1; /* Make filter outlet non-blocking */ ret = fcntl(recv_pipe[0], F_GETFL); if (ret != -1) { ret |= O_NONBLOCK; fcntl(recv_pipe[0], F_SETFL, ret); } /* Make filter sink non-blocking */ ret = fcntl(send_pipe[1], F_GETFL); if (ret != -1) { ret |= O_NONBLOCK; fcntl(send_pipe[1], F_SETFL, ret); } return 1; } /* child */ /* Give up the parent-side pipe ends */ close(send_pipe[1]); close(recv_pipe[0]); /* attach pipe ends to stdin and stdout */; close(0); ret = dup2(send_pipe[0], 0); if (ret == -1) { goto child_failed; } close(1); ret = dup2(recv_pipe[1], 1); if (ret == -1) { goto child_failed; } /* <<< */ if (print_fd) { fprintf(stderr, "libisofs_DEBUG: filter child in = %d\n", send_pipe[0]); fprintf(stderr, "libisofs_DEBUG: filter child out = %d\n", recv_pipe[1]); } /* Self conversion into external program */ execv(data->cmd->path, data->cmd->argv); /* should never come back */ child_failed:; fprintf(stderr,"--- execution of external filter command failed:\n"); fprintf(stderr," %s\n", data->cmd->path); exit(127); parent_failed:; /* <<< */ if (print_fd) { fprintf(stderr, "libisofs_DEBUG: FAILED : filter parent in = %d\n", recv_pipe[0]); fprintf(stderr, "libisofs_DEBUG: FAILED : filter parent out = %d\n", send_pipe[1]); } if (stream_open) iso_stream_close(data->orig); if(send_pipe[0] != -1) close(send_pipe[0]); if(send_pipe[1] != -1) close(send_pipe[1]); if(recv_pipe[0] != -1) close(recv_pipe[0]); if(recv_pipe[1] != -1) close(recv_pipe[1]); return ret; } static int extf_stream_open(IsoStream *stream) { return extf_stream_open_flag(stream, 0); } #ifdef Libisofs_external_filters_selecT /* Performance is weaker than with non-blocking i/o and usleep(). */ static int extf_wait_for_io(int fd_in, int fd_out, int microsec, int flag) { struct timeval wt; fd_set rds,wts,exs; int ready, fd_max; fd_max = fd_out; if (fd_in > fd_out) fd_max = fd_in; FD_ZERO(&rds); FD_ZERO(&wts); FD_ZERO(&exs); if (fd_in >= 0) { FD_SET(fd_in,&rds); FD_SET(fd_in,&exs); } if (fd_out >= 0) { FD_SET(fd_out,&rds); FD_SET(fd_in,&exs); } wt.tv_sec = microsec/1000000; wt.tv_usec = microsec%1000000; ready = select(fd_max + 1, &rds, &wts, &exs, &wt); if (ready <= 0) return 0; if (fd_in >= 0) { if (FD_ISSET(fd_in, &rds)) return 1; } if (fd_out >= 0) { if (FD_ISSET(fd_out, &rds)) return 2; } if (fd_in >= 0) { if (FD_ISSET(fd_in, &exs)) return -1; } if (fd_out >= 0) { if (FD_ISSET(fd_out, &exs)) return -2; } return(0); } #endif /* Libisofs_external_filters_selecT */ static int extf_stream_read(IsoStream *stream, void *buf, size_t desired) { int ret, blocking = 0; ExternalFilterStreamData *data; ExternalFilterRuntime *running; size_t fill = 0; if (stream == NULL) { return ISO_NULL_POINTER; } data = stream->data; running= data->running; if (running == NULL) { return ISO_FILE_NOT_OPENED; } if (running->out_eof) { return 0; } while (1) { if (running->in_eof && !blocking) { /* Make filter outlet blocking */ ret = fcntl(running->recv_fd, F_GETFL); if (ret != -1) { ret &= ~O_NONBLOCK; fcntl(running->recv_fd, F_SETFL, ret); } blocking = 1; } /* Try to read desired amount from filter */; while (1) { ret = read(running->recv_fd, ((char *) buf) + fill, desired - fill); if (ret < 0) { if (errno == EAGAIN) break; return ISO_FILE_READ_ERROR; } fill += ret; if (ret == 0) { running->out_eof = 1; } if (ret == 0 || fill >= desired) { running->out_counter += fill; return fill; } } if (running->in_eof) { usleep(1000); /* just in case it is still non-blocking */ continue; } if (running->pipebuf_fill) { ret = running->pipebuf_fill; running->pipebuf_fill = 0; } else { ret = iso_stream_read(data->orig, running->pipebuf, sizeof(running->pipebuf)); if (ret > 0) running->in_counter += ret; } if (ret < 0) { running->in_eof = 1; return ret; } if (ret == 0) { /* <<< */ if (print_fd) { fprintf(stderr, "libisofs_DEBUG: filter close out = %d , ic= %.f\n", running->send_fd, (double) running->in_counter); } running->in_eof = 1; close(running->send_fd); /* Tell the filter: it is over */ running->send_fd = -1; } else { running->pipebuf_fill = ret; ret = write(running->send_fd, running->pipebuf, running->pipebuf_fill); if (ret == -1) { if (errno == EAGAIN) { #ifdef Libisofs_external_filters_selecT /* This select() based waiting saves 10 % CPU load but needs 50 % more real time */ ret = extf_wait_for_io(running->recv_fd, running->send_fd, 100000, 0); if (ret < 0) usleep(1000); /* To make sure sufficient laziness */ #else /* No sleeping needs 90 % more CPU and saves 6 % time */ usleep(1000); /* go lazy because the filter is slow */ #endif /* ! Libisofs_external_filters_selecT */ continue; } /* From the view of the caller it _is_ a read error */ running->in_eof = 1; return ISO_FILE_READ_ERROR; } running->pipebuf_fill = 0; } } return ISO_FILE_READ_ERROR; /* should never be hit */ } static off_t extf_stream_get_size(IsoStream *stream) { int ret, ret_close; off_t count = 0; ExternalFilterStreamData *data; char buf[64 * 1024]; size_t bufsize = 64 * 1024; if (stream == NULL) { return ISO_NULL_POINTER; } data = stream->data; if (data->size >= 0) { return data->size; } /* Run filter command and count output bytes */ ret = extf_stream_open_flag(stream, 1); if (ret < 0) { return ret; } while (1) { ret = extf_stream_read(stream, buf, bufsize); if (ret <= 0) break; count += ret; } ret_close = extf_stream_close(stream); if (ret < 0) return ret; if (ret_close < 0) return ret_close; data->size = count; return count; } static int extf_stream_is_repeatable(IsoStream *stream) { /* Only repeatable streams are accepted as orig */ return 1; } static void extf_stream_get_id(IsoStream *stream, unsigned int *fs_id, dev_t *dev_id, ino_t *ino_id) { ExternalFilterStreamData *data; data = stream->data; *fs_id = ISO_FILTER_FS_ID; *dev_id = ISO_FILTER_EXTERNAL_DEV_ID; *ino_id = data->id; } static void extf_stream_free(IsoStream *stream) { ExternalFilterStreamData *data; if (stream == NULL) { return; } data = stream->data; if (data->running != NULL) { extf_stream_close(stream); } iso_stream_unref(data->orig); if (data->cmd->refcount > 0) data->cmd->refcount--; free(data); } static int extf_update_size(IsoStream *stream) { /* By principle size is determined only once */ return 1; } static IsoStream *extf_get_input_stream(IsoStream *stream, int flag) { ExternalFilterStreamData *data; if (stream == NULL) { return NULL; } data = stream->data; return data->orig; } static int extf_clone_stream(IsoStream *old_stream, IsoStream **new_stream, int flag) { int ret; IsoStream *new_input_stream, *stream; ExternalFilterStreamData *stream_data, *old_stream_data; if (flag) return ISO_STREAM_NO_CLONE; /* unknown option required */ stream_data = calloc(1, sizeof(ExternalFilterStreamData)); if (stream_data == NULL) return ISO_OUT_OF_MEM; ret = iso_stream_clone_filter_common(old_stream, &stream, &new_input_stream, 0); if (ret < 0) { free((char *) stream_data); return ret; } old_stream_data = (ExternalFilterStreamData *) old_stream->data; stream_data->id = ++extf_ino_id; stream_data->orig = new_input_stream; stream_data->cmd = old_stream_data->cmd; stream_data->cmd->refcount++; stream_data->size = old_stream_data->size; stream_data->running = NULL; stream->data = stream_data; *new_stream = stream; return ISO_SUCCESS; } static int extf_cmp_ino(IsoStream *s1, IsoStream *s2); /* Function is defined after definition of extf_stream_class */ IsoStreamIface extf_stream_class = { 4, "extf", extf_stream_open, extf_stream_close, extf_stream_get_size, extf_stream_read, extf_stream_is_repeatable, extf_stream_get_id, extf_stream_free, extf_update_size, extf_get_input_stream, extf_cmp_ino, extf_clone_stream }; static int extf_cmp_ino(IsoStream *s1, IsoStream *s2) { int i; ExternalFilterStreamData *data1, *data2; IsoExternalFilterCommand *cmd1, *cmd2; /* This function may rely on being called by iso_stream_cmp_ino() only with s1, s2 which both point to it as their .cmp_ino() function. It would be a programming error to let any other than extf_stream_class point to extf_cmp_ino(). This fallback endangers transitivity of iso_stream_cmp_ino(). */ if (s1->class != &extf_stream_class || s2->class != &extf_stream_class) return iso_stream_cmp_ino(s1, s2, 1); data1 = (ExternalFilterStreamData*) s1->data; data2 = (ExternalFilterStreamData*) s2->data; cmd1 = data1->cmd; cmd2 = data2->cmd; if (cmd1 != cmd2) { if (strcmp(cmd1->name, cmd2->name) != 0) return strcmp(cmd1->name, cmd2->name); if (strcmp(cmd1->path, cmd2->path) != 0) return strcmp(cmd1->path, cmd2->path); if (cmd1->argc != cmd2->argc) return cmd1->argc < cmd2->argc ? -1 : 1; for (i = 0; i < cmd1->argc; i++) { if (strcmp(cmd1->argv[i], cmd2->argv[i]) != 0) return strcmp(cmd1->argv[i], cmd2->argv[i]); } if (cmd1->behavior != cmd2->behavior) return cmd1->behavior < cmd2->behavior ? -1 : 1; if (strcmp(cmd1->suffix, cmd2->suffix) != 0) return strcmp(cmd1->suffix, cmd2->suffix); } /* Both streams apply the same treatment to their input streams */ return iso_stream_cmp_ino(data1->orig, data2->orig, 0); } /* ------------------------------------------------------------------------- */ static void extf_filter_free(FilterContext *filter) { /* no data are allocated */; } /* To be called by iso_file_add_filter(). * The FilterContext input parameter is not furtherly needed for the * emerging IsoStream. */ static int extf_filter_get_filter(FilterContext *filter, IsoStream *original, IsoStream **filtered) { IsoStream *str; ExternalFilterStreamData *data; IsoExternalFilterCommand *cmd; if (filter == NULL || original == NULL || filtered == NULL) { return ISO_NULL_POINTER; } cmd = (IsoExternalFilterCommand *) filter->data; if (cmd->refcount + 1 <= 0) { return ISO_EXTF_TOO_OFTEN; } str = malloc(sizeof(IsoStream)); if (str == NULL) { return ISO_OUT_OF_MEM; } data = malloc(sizeof(ExternalFilterStreamData)); if (data == NULL) { free(str); return ISO_OUT_OF_MEM; } /* These data items are not owned by this filter object */ data->id = ++extf_ino_id; data->orig = original; data->cmd = cmd; data->size = -1; data->running = NULL; /* get reference to the source */ iso_stream_ref(data->orig); str->refcount = 1; str->data = data; str->class = &extf_stream_class; *filtered = str; cmd->refcount++; return ISO_SUCCESS; } /* Produce a parameter object suitable for iso_file_add_filter(). * It may be disposed by free() after all those calls are made. * * This is an internal call of libisofs to be used by an API call that * attaches an IsoExternalFilterCommand to one or more IsoFile objects. * See libisofs.h for IsoExternalFilterCommand. */ static int extf_create_context(IsoExternalFilterCommand *cmd, FilterContext **filter, int flag) { FilterContext *f; *filter = f = calloc(1, sizeof(FilterContext)); if (f == NULL) { return ISO_OUT_OF_MEM; } f->refcount = 1; f->version = 0; f->data = cmd; f->free = extf_filter_free; f->get_filter = extf_filter_get_filter; return ISO_SUCCESS; } /* * A function which adds a filter to an IsoFile shall create a temporary * FilterContext by iso_extf_create_context(), use it in one or more calls * of filter.c:iso_file_add_filter() and finally dispose it by free(). */ int iso_file_add_external_filter(IsoFile *file, IsoExternalFilterCommand *cmd, int flag) { int ret; FilterContext *f = NULL; IsoStream *stream; off_t original_size = 0, filtered_size = 0; if (cmd->behavior & (1 | 2 | 4)) { original_size = iso_file_get_size(file); if (original_size <= 0 || ((cmd->behavior & 4) && original_size <= 2048)) { return 2; } } ret = extf_create_context(cmd, &f, 0); if (ret < 0) { return ret; } ret = iso_file_add_filter(file, f, 0); free(f); if (ret < 0) { return ret; } /* Run a full filter process getsize so that the size is cached */ stream = iso_file_get_stream(file); filtered_size = iso_stream_get_size(stream); if (filtered_size < 0) { iso_file_remove_filter(file, 0); return filtered_size; } if (((cmd->behavior & 2) && filtered_size >= original_size) || ((cmd->behavior & 4) && filtered_size / 2048 >= original_size / 2048)){ ret = iso_file_remove_filter(file, 0); if (ret < 0) { return ret; } return 2; } return ISO_SUCCESS; } int iso_stream_get_external_filter(IsoStream *stream, IsoExternalFilterCommand **cmd, int flag) { ExternalFilterStreamData *data; if (stream->class != &extf_stream_class) return 0; data = stream->data; *cmd = data->cmd; return 1; } libisofs-1.4.2/libisofs/filters/gzip.c0000644000175700017510000004705312547205012014667 00000000000000/* * Copyright (c) 2009 - 2011 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. * * It implements a filter facility which can pipe a IsoStream into gzip * compression resp. uncompression, read its output and forward it as IsoStream * output to an IsoFile. * The gzip compression is done via zlib by Jean-loup Gailly and Mark Adler * who state in : * "The data format used by the zlib library is described by RFCs (Request for * Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt * (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format)." * */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif #include "../libisofs.h" #include "../filter.h" #include "../fsource.h" #include "../util.h" #include "../stream.h" #include #include #include #include #include #include #include #ifdef Libisofs_with_zliB #include #else /* If zlib is not available then this code is a dummy */ #endif /* * A filter that encodes or decodes the content of gzip compressed files. */ /* --------------------------- GzipFilterRuntime ------------------------- */ /* Individual runtime properties exist only as long as the stream is opened. */ typedef struct { #ifdef Libisofs_with_zliB z_stream strm; /* The zlib processing context */ #endif char *in_buffer; char *out_buffer; int in_buffer_size; int out_buffer_size; char *rpt; /* out_buffer + read_bytes */ off_t in_counter; off_t out_counter; int do_flush; /* flush mode for deflate() changes at end of input */ int error_ret; } GzipFilterRuntime; #ifdef Libisofs_with_zliB static int gzip_running_destroy(GzipFilterRuntime **running, int flag) { GzipFilterRuntime *o= *running; if (o == NULL) return 0; if (o->in_buffer != NULL) free(o->in_buffer); if (o->out_buffer != NULL) free(o->out_buffer); free((char *) o); *running = NULL; return 1; } static int gzip_running_new(GzipFilterRuntime **running, int flag) { GzipFilterRuntime *o; *running = o = calloc(sizeof(GzipFilterRuntime), 1); if (o == NULL) { return ISO_OUT_OF_MEM; } memset(&(o->strm), 0, sizeof(o->strm)); o->in_buffer = NULL; o->out_buffer = NULL; o->in_buffer_size = 0; o->out_buffer_size = 0; o->rpt = NULL; o->in_counter = 0; o->out_counter = 0; o->do_flush = Z_NO_FLUSH; o->error_ret = 1; o->in_buffer_size= 2048; o->out_buffer_size= 2048; o->in_buffer = calloc(o->in_buffer_size, 1); o->out_buffer = calloc(o->out_buffer_size, 1); if (o->in_buffer == NULL || o->out_buffer == NULL) goto failed; o->rpt = o->out_buffer; return 1; failed: gzip_running_destroy(running, 0); return -1; } #endif /* Libisofs_with_zliB */ /* ---------------------------- GzipFilterStreamData --------------------- */ /* Counts the number of active compression filters */ static off_t gzip_ref_count = 0; /* Counts the number of active uncompression filters */ static off_t gunzip_ref_count = 0; #ifdef Libisofs_with_zliB /* Parameter for deflateInit2() , see */ /* ??? get this from zisofs.c ziso_compression_level ? * ??? have an own global parameter API ? * For now level 6 seems to be a fine compromise between speed and size. */ static int gzip_compression_level = 6; #endif /* Libisofs_with_zliB */ /* * The data payload of an individual Gzip Filter IsoStream */ /* IMPORTANT: Any change must be reflected by gzip_clone_stream() */ typedef struct { IsoStream *orig; off_t size; /* -1 means that the size is unknown yet */ GzipFilterRuntime *running; /* is non-NULL when open */ ino_t id; } GzipFilterStreamData; #ifdef Libisofs_with_zliB /* Each individual GzipFilterStreamData needs a unique id number. */ /* >>> This is very suboptimal: The counter can rollover. */ static ino_t gzip_ino_id = 0; #endif /* Libisofs_with_zliB */ static int gzip_stream_uncompress(IsoStream *stream, void *buf, size_t desired); /* * Methods for the IsoStreamIface of a Gzip Filter object. */ /* * @param flag bit0= original stream is not open */ static int gzip_stream_close_flag(IsoStream *stream, int flag) { #ifdef Libisofs_with_zliB GzipFilterStreamData *data; if (stream == NULL) { return ISO_NULL_POINTER; } data = stream->data; if (data->running == NULL) { return 1; } if (stream->class->read == &gzip_stream_uncompress) { inflateEnd(&(data->running->strm)); } else { deflateEnd(&(data->running->strm)); } gzip_running_destroy(&(data->running), 0); if (flag & 1) return 1; return iso_stream_close(data->orig); #else return ISO_ZLIB_NOT_ENABLED; #endif } static int gzip_stream_close(IsoStream *stream) { return gzip_stream_close_flag(stream, 0); } /* * @param flag bit0= do not run .get_size() if size is < 0 */ static int gzip_stream_open_flag(IsoStream *stream, int flag) { #ifdef Libisofs_with_zliB GzipFilterStreamData *data; GzipFilterRuntime *running = NULL; int ret; z_stream *strm; if (stream == NULL) { return ISO_NULL_POINTER; } data = (GzipFilterStreamData*) stream->data; if (data->running != NULL) { return ISO_FILE_ALREADY_OPENED; } if (data->size < 0 && !(flag & 1)) { /* Do the size determination run now, so that the size gets cached and .get_size() will not fail on an opened stream. */ stream->class->get_size(stream); } ret = gzip_running_new(&running, stream->class->read == &gzip_stream_uncompress); if (ret < 0) { return ret; } data->running = running; /* Start up zlib compression context */ strm = &(running->strm); strm->zalloc = Z_NULL; strm->zfree = Z_NULL; strm->opaque = Z_NULL; if (stream->class->read == &gzip_stream_uncompress) { ret = inflateInit2(strm, 15 | 16); } else { ret = deflateInit2(strm, gzip_compression_level, Z_DEFLATED, 15 | 16, 8, Z_DEFAULT_STRATEGY); } if (ret != Z_OK) return ISO_ZLIB_COMPR_ERR; strm->next_out = (Bytef *) running->out_buffer; strm->avail_out = running->out_buffer_size; /* Open input stream */ ret = iso_stream_open(data->orig); if (ret < 0) { return ret; } return 1; #else return ISO_ZLIB_NOT_ENABLED; #endif } static int gzip_stream_open(IsoStream *stream) { return gzip_stream_open_flag(stream, 0); } /* * @param flag bit1= uncompress rather than compress */ static int gzip_stream_convert(IsoStream *stream, void *buf, size_t desired, int flag) { #ifdef Libisofs_with_zliB int ret, todo, cnv_ret, c_bytes; GzipFilterStreamData *data; GzipFilterRuntime *rng; size_t fill = 0; z_stream *strm; if (stream == NULL) { return ISO_NULL_POINTER; } data = stream->data; rng= data->running; if (rng == NULL) { return ISO_FILE_NOT_OPENED; } strm = &(rng->strm); if (rng->error_ret < 0) { return rng->error_ret; } else if (rng->error_ret == 0) { if (rng->out_buffer_size - strm->avail_out - (rng->rpt - rng->out_buffer) <= 0) return 0; } while (1) { /* Transfer eventual converted bytes from strm to buf */ c_bytes = rng->out_buffer_size - strm->avail_out - (rng->rpt - rng->out_buffer); if (c_bytes > 0) { todo = desired - fill; if (todo > c_bytes) todo = c_bytes; memcpy(((char *) buf) + fill, rng->rpt, todo); rng->rpt += todo; fill += todo; rng->out_counter += todo; } if (fill >= desired || rng->error_ret == 0) return fill; /* All buffered out data are consumed now */ rng->rpt = rng->out_buffer; strm->next_out = (Bytef *) rng->out_buffer; strm->avail_out = rng->out_buffer_size; if (strm->avail_in == 0) { /* All pending input is consumed. Get new input. */ ret = iso_stream_read(data->orig, rng->in_buffer, rng->in_buffer_size); if (ret < 0) return (rng->error_ret = ret); if (ret == 0) { if (flag & 2) { /* Early input EOF */ return (rng->error_ret = ISO_ZLIB_EARLY_EOF); } else { /* Tell zlib by the next call that it is over */ rng->do_flush = Z_FINISH; } } strm->next_in = (Bytef *) rng->in_buffer; strm->avail_in = ret; rng->in_counter += ret; } /* Submit input and fetch output until input is consumed */ while (1) { if (flag & 2) { cnv_ret = inflate(strm, rng->do_flush); } else { cnv_ret = deflate(strm, rng->do_flush); } if (cnv_ret == Z_STREAM_ERROR || cnv_ret == Z_BUF_ERROR) { return (rng->error_ret = ISO_ZLIB_COMPR_ERR); } if ((int) strm->avail_out < rng->out_buffer_size) break; /* output is available */ if (strm->avail_in == 0) /* all pending input consumed */ break; } if (cnv_ret == Z_STREAM_END) rng->error_ret = 0; } return fill; #else return ISO_ZLIB_NOT_ENABLED; #endif } static int gzip_stream_compress(IsoStream *stream, void *buf, size_t desired) { return gzip_stream_convert(stream, buf, desired, 0); } static int gzip_stream_uncompress(IsoStream *stream, void *buf, size_t desired) { return gzip_stream_convert(stream, buf, desired, 2); } static off_t gzip_stream_get_size(IsoStream *stream) { int ret, ret_close; off_t count = 0; GzipFilterStreamData *data; char buf[64 * 1024]; size_t bufsize = 64 * 1024; if (stream == NULL) { return ISO_NULL_POINTER; } data = stream->data; if (data->size >= 0) { return data->size; } /* Run filter command and count output bytes */ ret = gzip_stream_open_flag(stream, 1); if (ret < 0) { return ret; } while (1) { ret = stream->class->read(stream, buf, bufsize); if (ret <= 0) break; count += ret; } ret_close = gzip_stream_close(stream); if (ret < 0) return ret; if (ret_close < 0) return ret_close; data->size = count; return count; } static int gzip_stream_is_repeatable(IsoStream *stream) { /* Only repeatable streams are accepted as orig */ return 1; } static void gzip_stream_get_id(IsoStream *stream, unsigned int *fs_id, dev_t *dev_id, ino_t *ino_id) { GzipFilterStreamData *data; data = stream->data; *fs_id = ISO_FILTER_FS_ID; *dev_id = ISO_FILTER_GZIP_DEV_ID; *ino_id = data->id; } static void gzip_stream_free(IsoStream *stream) { GzipFilterStreamData *data; if (stream == NULL) { return; } data = stream->data; if (data->running != NULL) { gzip_stream_close(stream); } if (stream->class->read == &gzip_stream_uncompress) { if (--gunzip_ref_count < 0) gunzip_ref_count = 0; } else { if (--gzip_ref_count < 0) gzip_ref_count = 0; } iso_stream_unref(data->orig); free(data); } static int gzip_update_size(IsoStream *stream) { /* By principle size is determined only once */ return 1; } static IsoStream *gzip_get_input_stream(IsoStream *stream, int flag) { GzipFilterStreamData *data; if (stream == NULL) { return NULL; } data = stream->data; return data->orig; } static int gzip_clone_stream(IsoStream *old_stream, IsoStream **new_stream, int flag) { #ifdef Libisofs_with_zliB int ret; IsoStream *new_input_stream, *stream; GzipFilterStreamData *stream_data, *old_stream_data; if (flag) return ISO_STREAM_NO_CLONE; /* unknown option required */ stream_data = calloc(1, sizeof(GzipFilterStreamData)); if (stream_data == NULL) return ISO_OUT_OF_MEM; ret = iso_stream_clone_filter_common(old_stream, &stream, &new_input_stream, 0); if (ret < 0) { free((char *) stream_data); return ret; } old_stream_data = (GzipFilterStreamData *) old_stream->data; stream_data->orig = new_input_stream; stream_data->size = old_stream_data->size; stream_data->running = NULL; stream_data->id = ++gzip_ino_id; stream->data = stream_data; *new_stream = stream; return ISO_SUCCESS; #else /* Libisofs_with_zliB */ return ISO_STREAM_NO_CLONE; #endif /* ! Libisofs_with_zliB */ } static int gzip_cmp_ino(IsoStream *s1, IsoStream *s2); static int gzip_uncompress_cmp_ino(IsoStream *s1, IsoStream *s2); IsoStreamIface gzip_stream_compress_class = { 4, "gzip", gzip_stream_open, gzip_stream_close, gzip_stream_get_size, gzip_stream_compress, gzip_stream_is_repeatable, gzip_stream_get_id, gzip_stream_free, gzip_update_size, gzip_get_input_stream, gzip_cmp_ino, gzip_clone_stream }; IsoStreamIface gzip_stream_uncompress_class = { 4, "pizg", gzip_stream_open, gzip_stream_close, gzip_stream_get_size, gzip_stream_uncompress, gzip_stream_is_repeatable, gzip_stream_get_id, gzip_stream_free, gzip_update_size, gzip_get_input_stream, gzip_uncompress_cmp_ino, gzip_clone_stream }; static int gzip_cmp_ino(IsoStream *s1, IsoStream *s2) { /* This function may rely on being called by iso_stream_cmp_ino() only with s1, s2 which both point to it as their .cmp_ino() function. It would be a programming error to let any other than gzip_stream_compress_class point to gzip_cmp_ino(). This fallback endangers transitivity of iso_stream_cmp_ino(). */ if (s1->class != s2->class || (s1->class != &gzip_stream_compress_class && s2->class != &gzip_stream_compress_class)) return iso_stream_cmp_ino(s1, s2, 1); /* Both streams apply the same treatment to their input streams */ return iso_stream_cmp_ino(iso_stream_get_input_stream(s1, 0), iso_stream_get_input_stream(s2, 0), 0); } static int gzip_uncompress_cmp_ino(IsoStream *s1, IsoStream *s2) { /* This function may rely on being called by iso_stream_cmp_ino() only with s1, s2 which both point to it as their .cmp_ino() function. It would be a programming error to let any other than gzip_stream_uncompress_class point to gzip_uncompress_cmp_ino(). */ if (s1->class != s2->class || (s1->class != &gzip_stream_uncompress_class && s2->class != &gzip_stream_uncompress_class)) return iso_stream_cmp_ino(s1, s2, 1); /* Both streams apply the same treatment to their input streams */ return iso_stream_cmp_ino(iso_stream_get_input_stream(s1, 0), iso_stream_get_input_stream(s2, 0), 0); } /* ------------------------------------------------------------------------- */ #ifdef Libisofs_with_zliB static void gzip_filter_free(FilterContext *filter) { /* no data are allocated */; } /* * @param flag bit1= Install a decompression filter */ static int gzip_filter_get_filter(FilterContext *filter, IsoStream *original, IsoStream **filtered, int flag) { IsoStream *str; GzipFilterStreamData *data; if (filter == NULL || original == NULL || filtered == NULL) { return ISO_NULL_POINTER; } str = calloc(sizeof(IsoStream), 1); if (str == NULL) { return ISO_OUT_OF_MEM; } data = calloc(sizeof(GzipFilterStreamData), 1); if (data == NULL) { free(str); return ISO_OUT_OF_MEM; } /* These data items are not owned by this filter object */ data->id = ++gzip_ino_id; data->orig = original; data->size = -1; data->running = NULL; /* get reference to the source */ iso_stream_ref(data->orig); str->refcount = 1; str->data = data; if (flag & 2) { str->class = &gzip_stream_uncompress_class; gunzip_ref_count++; } else { str->class = &gzip_stream_compress_class; gzip_ref_count++; } *filtered = str; return ISO_SUCCESS; } /* To be called by iso_file_add_filter(). * The FilterContext input parameter is not furtherly needed for the * emerging IsoStream. */ static int gzip_filter_get_compressor(FilterContext *filter, IsoStream *original, IsoStream **filtered) { return gzip_filter_get_filter(filter, original, filtered, 0); } static int gzip_filter_get_uncompressor(FilterContext *filter, IsoStream *original, IsoStream **filtered) { return gzip_filter_get_filter(filter, original, filtered, 2); } /* Produce a parameter object suitable for iso_file_add_filter(). * It may be disposed by free() after all those calls are made. * * This is quite a dummy as it does not carry individual data. * @param flag bit1= Install a decompression filter */ static int gzip_create_context(FilterContext **filter, int flag) { FilterContext *f; *filter = f = calloc(1, sizeof(FilterContext)); if (f == NULL) { return ISO_OUT_OF_MEM; } f->refcount = 1; f->version = 0; f->data = NULL; f->free = gzip_filter_free; if (flag & 2) f->get_filter = gzip_filter_get_uncompressor; else f->get_filter = gzip_filter_get_compressor; return ISO_SUCCESS; } #endif /* Libisofs_with_zliB */ /* * @param flag bit0= if_block_reduction rather than if_reduction * bit1= Install a decompression filter * bit2= only inquire availability of gzip filtering * bit3= do not inquire size */ int gzip_add_filter(IsoFile *file, int flag) { #ifdef Libisofs_with_zliB int ret; FilterContext *f = NULL; IsoStream *stream; off_t original_size = 0, filtered_size = 0; if (flag & 4) return 2; original_size = iso_file_get_size(file); ret = gzip_create_context(&f, flag & 2); if (ret < 0) { return ret; } ret = iso_file_add_filter(file, f, 0); free(f); if (ret < 0) { return ret; } if (flag & 8) /* size will be filled in by caller */ return ISO_SUCCESS; /* Run a full filter process getsize so that the size is cached */ stream = iso_file_get_stream(file); filtered_size = iso_stream_get_size(stream); if (filtered_size < 0) { iso_file_remove_filter(file, 0); return filtered_size; } if ((filtered_size >= original_size || ((flag & 1) && filtered_size / 2048 >= original_size / 2048)) && !(flag & 2)){ ret = iso_file_remove_filter(file, 0); if (ret < 0) { return ret; } return 2; } return ISO_SUCCESS; #else return ISO_ZLIB_NOT_ENABLED; #endif /* ! Libisofs_with_zliB */ } /* API function */ int iso_file_add_gzip_filter(IsoFile *file, int flag) { return gzip_add_filter(file, flag & ~8); } /* API function */ int iso_gzip_get_refcounts(off_t *gzip_count, off_t *gunzip_count, int flag) { *gzip_count = gzip_ref_count; *gunzip_count = gunzip_ref_count; return ISO_SUCCESS; } libisofs-1.4.2/libisofs/eltorito.h0000644000175700017510000001231012562123645014110 00000000000000/* * Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2010 - 2014 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ /** * Declare El-Torito related structures. * References: * "El Torito" Bootable CD-ROM Format Specification Version 1.0 (1995) */ #ifndef LIBISO_ELTORITO_H #define LIBISO_ELTORITO_H #include "ecma119.h" #include "node.h" /** * A node that acts as a placeholder for an El-Torito catalog. */ struct Iso_Boot { IsoNode node; /* Want to get content of loaded boot catalog. Vreixo took care not to make it an IsoFile at load time. So this is implemented independently of IsoStream. */ uint32_t lba; off_t size; char *content; }; /* Not more than 32 so that all entries fit into 2048 bytes */ #define Libisofs_max_boot_imageS 32 struct el_torito_boot_catalog { IsoBoot *node; /* node of the catalog */ int num_bootimages; struct el_torito_boot_image *bootimages[Libisofs_max_boot_imageS]; /* [0]= default boot image */ /* Weight value for image sorting */ int sort_weight; }; struct el_torito_boot_image { IsoFile *image; unsigned int bootable:1; /**< If the entry is bootable. */ /** * Whether the boot image seems to contain a boot_info_table */ unsigned int seems_boot_info_table:1; unsigned int seems_grub2_boot_info:1; /** * Whether the boot image seems to be capable of isohybrid */ unsigned int seems_isohybrid_capable:1; /** * isolinux options * bit 0 -> whether to patch image * bit 1 -> whether to put built-in isolinux 3.72 isohybrid-MBR into image * System Area (deprecated) * * bit2-7= Mentioning in isohybrid GPT * 0= do not mention in GPT * 1= mention as EFI partition * 2= Mention as HFS+ partition * bit8= Mention in isohybrid Apple partition map */ unsigned int isolinux_options; unsigned char type; /**< The type of image */ unsigned char partition_type; /**< type of partition for HD-emul images */ uint16_t load_seg; /**< Load segment for the initial boot image. */ uint16_t load_size; /**< Number of sectors to load. */ /* Byte 1 of Validation Entry or Section Header Entry: 0= 80x86, 1= PowerPC, 2= Mac, 0xef= EFI */ uint8_t platform_id; uint8_t id_string[28]; uint8_t selection_crit[20]; }; /** El-Torito, 2.1 */ struct el_torito_validation_entry { uint8_t header_id BP(1, 1); uint8_t platform_id BP(2, 2); uint8_t reserved BP(3, 4); uint8_t id_string BP(5, 28); uint8_t checksum BP(29, 30); uint8_t key_byte1 BP(31, 31); uint8_t key_byte2 BP(32, 32); }; /** El-Torito, 2.2 */ struct el_torito_default_entry { uint8_t boot_indicator BP(1, 1); uint8_t boot_media_type BP(2, 2); uint8_t load_seg BP(3, 4); uint8_t system_type BP(5, 5); uint8_t unused1 BP(6, 6); uint8_t sec_count BP(7, 8); uint8_t block BP(9, 12); uint8_t unused2 BP(13, 32); }; /** El-Torito, 2.3 */ struct el_torito_section_header { uint8_t header_indicator BP(1, 1); uint8_t platform_id BP(2, 2); uint8_t num_entries BP(3, 4); uint8_t id_string BP(5, 32); }; /** El-Torito, 2.4 */ struct el_torito_section_entry { uint8_t boot_indicator BP(1, 1); uint8_t boot_media_type BP(2, 2); uint8_t load_seg BP(3, 4); uint8_t system_type BP(5, 5); uint8_t unused1 BP(6, 6); uint8_t sec_count BP(7, 8); uint8_t block BP(9, 12); uint8_t selec_criteria BP(13, 13); uint8_t vendor_sc BP(14, 32); }; void el_torito_boot_catalog_free(struct el_torito_boot_catalog *cat); /** * Create a IsoFileSrc for writing the el-torito catalog for the given * target, and add it to target. If the target already has a src for the * catalog, it just returns. */ int el_torito_catalog_file_src_create(Ecma119Image *target, IsoFileSrc **src); /** * Create a writer for el-torito information. */ int eltorito_writer_create(Ecma119Image *target); /** * Insert boot info table content into buf. * * @return * 1 on success, 0 error (but continue), < 0 error */ int make_boot_info_table(uint8_t *buf, uint32_t pvd_lba, uint32_t boot_lba, uint32_t imgsize); /* Patch the boot images if indicated. */ int iso_patch_eltoritos(Ecma119Image *t); /* Parameters for patch_grub2_boot_image() Might later become variables in struct el_torito_boot_image. */ #define Libisofs_grub2_elto_patch_poS (512 * 5 - 12) #define Libisofs_grub2_elto_patch_offsT 5 /* Maximum size of a boot image which is marked by el_torito_set_isolinux_options() for patching (boot info table, GRUB2 boot info, maybe others). */ #define Libisofs_elto_max_patchablE (32 * 1024 * 1024) #endif /* LIBISO_ELTORITO_H */ libisofs-1.4.2/libisofs/ecma119_tree.h0000644000175700017510000000576412534611344014442 00000000000000/* * Copyright (c) 2007 Vreixo Formoso * 2012 - 2014 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ #ifndef LIBISO_ECMA119_TREE_H_ #define LIBISO_ECMA119_TREE_H_ #include "libisofs.h" #include "ecma119.h" enum ecma119_node_type { ECMA119_FILE, ECMA119_DIR, ECMA119_SYMLINK, ECMA119_SPECIAL, ECMA119_PLACEHOLDER }; /** * Struct with info about a node representing a directory */ struct ecma119_dir_info { /* Block where the directory entries will be written on image */ size_t block; size_t nchildren; Ecma119Node **children; /* * Size of the dir, i.e., sum of the lengths of all directory records. * It is computed by calc_dir_size() [ecma119.c]. * Note that this don't include the length of any SUSP Continuation * Area needed by the dir, but it includes the size of the SUSP entries * than fit in the directory records System Use Field. */ size_t len; /** * Real parent if the dir has been reallocated. NULL otherwise. */ Ecma119Node *real_parent; }; /** * A node for a tree containing all the information necessary for writing * an ISO9660 volume. */ struct ecma119_node { /** * Name in ASCII, conforming to selected ISO level. * Version number is not include, it is added on the fly */ char *iso_name; Ecma119Node *parent; IsoNode *node; /*< reference to the iso node */ uint32_t ino; nlink_t nlink; /**< file, symlink, special, directory or placeholder */ enum ecma119_node_type type; union { IsoFileSrc *file; struct ecma119_dir_info *dir; /** this field points to the relocated directory. */ Ecma119Node *real_me; } info; }; /* For recording files which are hidden in ECMA-119 */ struct iso_filesrc_list_item { IsoFileSrc *src; struct iso_filesrc_list_item *next; }; int iso_filesrc_list_destroy(struct iso_filesrc_list_item **start_item); /** * */ int ecma119_tree_create(Ecma119Image *img); /** * Free an Ecma119Node, and its children if node is a dir */ void ecma119_node_free(Ecma119Node *node); /** * Search the tree for a certain IsoNode and return its owning Ecma119Node * or NULL. */ Ecma119Node *ecma119_search_iso_node(Ecma119Image *img, IsoNode *node); /** * Tell whether node is a dedicated relocation directory which only contains * relocated directories. */ int ecma119_is_dedicated_reloc_dir(Ecma119Image *img, Ecma119Node *node); /** * Determines the ECMA-119 name from node name. * @param flag bit0= Do not issue error messages */ int iso_get_ecma119_name(IsoWriteOpts *opts, char *input_charset, int imgid, char *node_name, enum IsoNodeType node_type, char **name, int flag); #endif /*LIBISO_ECMA119_TREE_H_*/ libisofs-1.4.2/libisofs/messages.h0000644000175700017510000000307112321161425014051 00000000000000/* * Copyright (c) 2007 Vreixo Formoso * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ /* * Message handling for libisofs */ #ifndef MESSAGES_H_ #define MESSAGES_H_ /** * Take and increment this variable to get a valid identifier for message * origin. */ extern int iso_message_id; /** * Submit a debug message. */ void iso_msg_debug(int imgid, const char *fmt, ...); /** * Inquire whether the given error code triggers the abort threshold */ int iso_msg_is_abort(int errcode); /** * * @param errcode * The error code. * @param causedby * Error that was caused the errcode. If this error is a FATAL error, * < 0 will be returned in any case. Use 0 if there is no previous * cause for the error. * @return * 0 on success, < 0 if function must abort asap. */ int iso_msg_submit(int imgid, int errcode, int causedby, const char *fmt, ...); /* To be called with events which report incidents with individual input files from the local filesystem. Not with image nodes, files containing an image or similar file-like objects. */ int iso_report_errfile(char *path, int error_code, int os_errno, int flag); /* Drains the libjte message list and puts out the messages via iso_msg_submit() */ int iso_libjte_forward_msgs(void *libjte_handle, int imgid, int errcode, int flag); #endif /*MESSAGES_H_*/ libisofs-1.4.2/libisofs/ecma119_tree.c0000644000175700017510000011343212607227573014435 00000000000000/* * Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2009 - 2014 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif /* Must be before ecma119.h because of eventual Libisofs_with_rrip_rR */ #include "libisofs.h" #include "ecma119_tree.h" #include "ecma119.h" #include "node.h" #include "util.h" #include "filesrc.h" #include "messages.h" #include "image.h" #include "stream.h" #include "eltorito.h" #include #include #include /* @param flag bit0= Do not issue error messages */ int iso_get_ecma119_name(IsoWriteOpts *opts, char *input_charset, int imgid, char *node_name, enum IsoNodeType node_type, char **name, int flag) { int ret, relaxed, free_ascii_name = 0, force_dots = 0; char *ascii_name; char *isoname = NULL; if (node_name == NULL) { /* it is not necessarily an error, it can be the root */ return ISO_SUCCESS; } if (opts->untranslated_name_len > 0) { ascii_name = node_name; ret = 1; } else { ret = str2ascii(input_charset, node_name, &ascii_name); free_ascii_name = 1; } if (ret < 0) { if (!(flag & 512)) iso_msg_submit(imgid, ret, 0, "Cannot convert name '%s' to ASCII", node_name); return ret; } if (opts->allow_full_ascii) { relaxed = 2; } else { relaxed = (int)opts->allow_lowercase; } if (opts->allow_7bit_ascii) relaxed |= 4; if (node_type == LIBISO_DIR && !(opts->allow_dir_id_ext)) { if (opts->untranslated_name_len > 0) { if (strlen(ascii_name) > opts->untranslated_name_len) { needs_transl:; if (!(flag & 512)) iso_msg_submit(imgid, ISO_NAME_NEEDS_TRANSL, 0, "File name too long (%d > %d) for untranslated recording: '%s'", strlen(ascii_name), opts->untranslated_name_len, ascii_name); return ISO_NAME_NEEDS_TRANSL; } isoname = strdup(ascii_name); } else if (opts->max_37_char_filenames) { isoname = iso_r_dirid(ascii_name, 37, relaxed); } else if (opts->iso_level == 1) { #ifdef Libisofs_old_ecma119_nameS if (relaxed) { isoname = iso_r_dirid(ascii_name, 8, relaxed); } else { isoname = iso_1_dirid(ascii_name, 0); } #else /* Libisofs_old_ecma119_nameS */ isoname = iso_1_dirid(ascii_name, relaxed); #endif /* ! Libisofs_old_ecma119_nameS */ } else { if (relaxed) { isoname = iso_r_dirid(ascii_name, 31, relaxed); } else { isoname = iso_2_dirid(ascii_name); } } } else { force_dots = !((opts->no_force_dots & 1) || node_type == LIBISO_DIR); if (opts->untranslated_name_len > 0) { if (strlen(ascii_name) > opts->untranslated_name_len) goto needs_transl; isoname = strdup(ascii_name); } else if (opts->max_37_char_filenames) { isoname = iso_r_fileid(ascii_name, 36, relaxed, force_dots); } else if (opts->iso_level == 1) { #ifdef Libisofs_old_ecma119_nameS int max_len; if (relaxed) { if (strchr(ascii_name, '.') == NULL) max_len = 8; else max_len = 11; isoname = iso_r_fileid(ascii_name, max_len, relaxed, force_dots); } else { isoname = iso_1_fileid(ascii_name, 0, force_dots); } #else /* Libisofs_old_ecma119_nameS */ isoname = iso_1_fileid(ascii_name, relaxed, force_dots); #endif /* ! Libisofs_old_ecma119_nameS */ } else { if (relaxed || !force_dots) { isoname = iso_r_fileid(ascii_name, 30, relaxed, force_dots); } else { isoname = iso_2_fileid(ascii_name); } } } if (free_ascii_name) free(ascii_name); if (isoname != NULL) { *name = isoname; return ISO_SUCCESS; } else { /* * only possible if mem error, as check for empty names is done * in public tree */ return ISO_OUT_OF_MEM; } } static int get_iso_name(Ecma119Image *img, IsoNode *iso, char **name) { int ret; ret = iso_get_ecma119_name(img->opts, img->input_charset, img->image->id, iso->name, iso->type, name, 0); return ret; } int ecma119_is_dedicated_reloc_dir(Ecma119Image *img, Ecma119Node *node) { if (img->rr_reloc_node == node && node != img->root && node != img->partition_root && (img->opts->rr_reloc_flags & 2)) return 1; return 0; } static int create_ecma119_node(Ecma119Image *img, IsoNode *iso, Ecma119Node **node) { Ecma119Node *ecma; ecma = calloc(1, sizeof(Ecma119Node)); if (ecma == NULL) { return ISO_OUT_OF_MEM; } ecma->node = iso; iso_node_ref(iso); ecma->nlink = 1; *node = ecma; return ISO_SUCCESS; } /** * Create a new ECMA-119 node representing a directory from a iso directory * node. */ static int create_dir(Ecma119Image *img, IsoDir *iso, Ecma119Node **node) { int ret; Ecma119Node **children = NULL; struct ecma119_dir_info *dir_info; if (iso->nchildren > 0) { children = calloc(1, sizeof(void*) * iso->nchildren); if (children == NULL) return ISO_OUT_OF_MEM; } dir_info = calloc(1, sizeof(struct ecma119_dir_info)); if (dir_info == NULL) { if (children != NULL) free(children); return ISO_OUT_OF_MEM; } ret = create_ecma119_node(img, (IsoNode*)iso, node); if (ret < 0) { if (children != NULL) free(children); free(dir_info); return ret; } (*node)->type = ECMA119_DIR; (*node)->info.dir = dir_info; (*node)->info.dir->nchildren = 0; (*node)->info.dir->children = children; return ISO_SUCCESS; } static int create_file_src(Ecma119Image *img, IsoFile *iso, IsoFileSrc **src) { int ret; off_t size; size = iso_stream_get_size(iso->stream); if (size > (off_t)MAX_ISO_FILE_SECTION_SIZE && img->opts->iso_level != 3) { char *ipath = iso_tree_get_node_path(ISO_NODE(iso)); ret = iso_msg_submit(img->image->id, ISO_FILE_TOO_BIG, 0, "File \"%s\" can't be added to image because " "is greater than 4GB", ipath); free(ipath); return ret; } ret = iso_file_src_create(img, iso, src); if (ret < 0) { return ret; } return 0; } /** * Create a new ECMA-119 node representing a regular file from a iso file * node. */ static int create_file(Ecma119Image *img, IsoFile *iso, Ecma119Node **node) { int ret; IsoFileSrc *src; ret = create_file_src(img, iso, &src); if (ret < 0) { return ret; } ret = create_ecma119_node(img, (IsoNode*)iso, node); if (ret < 0) { /* * the src doesn't need to be freed, it is free together with * the Ecma119Image */ return ret; } (*node)->type = ECMA119_FILE; (*node)->info.file = src; return ret; } /** * Create a new ECMA-119 node representing a regular file from an El-Torito * boot catalog */ static int create_boot_cat(Ecma119Image *img, IsoBoot *iso, Ecma119Node **node) { int ret; IsoFileSrc *src; ret = el_torito_catalog_file_src_create(img, &src); if (ret < 0) { return ret; } ret = create_ecma119_node(img, (IsoNode*)iso, node); if (ret < 0) { /* * the src doesn't need to be freed, it is free together with * the Ecma119Image */ return ret; } (*node)->type = ECMA119_FILE; (*node)->info.file = src; return ret; } /** * Create a new ECMA-119 node representing a symbolic link from a iso symlink * node. */ static int create_symlink(Ecma119Image *img, IsoSymlink *iso, Ecma119Node **node) { int ret; ret = create_ecma119_node(img, (IsoNode*)iso, node); if (ret < 0) { return ret; } (*node)->type = ECMA119_SYMLINK; return ISO_SUCCESS; } /** * Create a new ECMA-119 node representing a special file. */ static int create_special(Ecma119Image *img, IsoSpecial *iso, Ecma119Node **node) { int ret; ret = create_ecma119_node(img, (IsoNode*)iso, node); if (ret < 0) { return ret; } (*node)->type = ECMA119_SPECIAL; return ISO_SUCCESS; } void ecma119_node_free(Ecma119Node *node) { if (node == NULL) { return; } if (node->type == ECMA119_DIR) { size_t i; for (i = 0; i < node->info.dir->nchildren; i++) { ecma119_node_free(node->info.dir->children[i]); } if (node->info.dir->children != NULL) free(node->info.dir->children); free(node->info.dir); } free(node->iso_name); iso_node_unref(node->node); free(node); } static int add_to_hidden_list(Ecma119Image *image, IsoFileSrc *src) { int ret; struct iso_filesrc_list_item *item; LIBISO_ALLOC_MEM(item, struct iso_filesrc_list_item, 1); item->src = src; item->next = image->ecma119_hidden_list; image->ecma119_hidden_list = item; ret = ISO_SUCCESS; ex: return ret; } int iso_filesrc_list_destroy(struct iso_filesrc_list_item **start_item) { struct iso_filesrc_list_item *item, *next; for (item = *start_item; item != NULL; item = next) { next = item->next; LIBISO_FREE_MEM(item); } return ISO_SUCCESS; } /** * @param flag * bit0= iso is in a hidden directory. Thus hide it. * @return * 1 success, 0 node ignored, < 0 error * */ static int create_tree(Ecma119Image *image, IsoNode *iso, Ecma119Node **tree, int depth, int pathlen, int flag) { int ret, hidden; Ecma119Node *node = NULL; int max_path; char *iso_name= NULL, *ipath = NULL; IsoFileSrc *src = NULL; IsoWriteOpts *opts; if (image == NULL || iso == NULL || tree == NULL) { return ISO_NULL_POINTER; } opts = image->opts; *tree = NULL; hidden = flag & 1; if (iso->hidden & LIBISO_HIDE_ON_RR) { hidden = 1; if (!((iso->hidden & LIBISO_HIDE_BUT_WRITE) || iso->type == LIBISO_BOOT)) { return 0; /* file will be ignored */ } } if (hidden) { max_path= pathlen; } else { ret = get_iso_name(image, iso, &iso_name); if (ret < 0) { iso_name = NULL; /* invalid, do not free */ goto ex; } max_path = pathlen + 1 + (iso_name ? strlen(iso_name) : 0); if (!opts->rockridge) { if ((iso->type == LIBISO_DIR && depth > 8) && !opts->allow_deep_paths) { ipath = iso_tree_get_node_path(iso); ret = iso_msg_submit(image->image->id, ISO_FILE_IMGPATH_WRONG, 0, "File \"%s\" can't be added, " "because directory depth " "is greater than 8.", ipath); goto ex; } else if (max_path > 255 && !opts->allow_longer_paths) { ipath = iso_tree_get_node_path(iso); ret = iso_msg_submit(image->image->id, ISO_FILE_IMGPATH_WRONG, 0, "File \"%s\" can't be added, " "because path length " "is greater than 255 characters", ipath); goto ex; } } } switch (iso->type) { case LIBISO_FILE: if (hidden) { ret = create_file_src(image, (IsoFile *) iso, &src); if (ret <= 0) goto ex; ret = add_to_hidden_list(image, src); } else { ret = create_file(image, (IsoFile*)iso, &node); } break; case LIBISO_SYMLINK: if (hidden) { ret = 0; /* Hidden means non-existing */ goto ex; } if (opts->rockridge) { ret = create_symlink(image, (IsoSymlink*)iso, &node); } else { /* symlinks are only supported when RR is enabled */ char *ipath = iso_tree_get_node_path(iso); ret = iso_msg_submit(image->image->id, ISO_FILE_IGNORED, 0, "File \"%s\" ignored. Symlinks need RockRidge extensions.", ipath); free(ipath); } break; case LIBISO_SPECIAL: if (hidden) { ret = 0; /* Hidden means non-existing */ goto ex; } if (opts->rockridge) { ret = create_special(image, (IsoSpecial*)iso, &node); } else { /* special files are only supported when RR is enabled */ char *ipath = iso_tree_get_node_path(iso); ret = iso_msg_submit(image->image->id, ISO_FILE_IGNORED, 0, "File \"%s\" ignored. Special files need RockRidge extensions.", ipath); free(ipath); } break; case LIBISO_BOOT: if (image->eltorito) { if (hidden) { ret = el_torito_catalog_file_src_create(image, &src); if (ret <= 0) goto ex; ret = add_to_hidden_list(image, src); } else { ret = create_boot_cat(image, (IsoBoot*)iso, &node); } } else { /* log and ignore */ ret = iso_msg_submit(image->image->id, ISO_FILE_IGNORED, 0, "El-Torito catalog found on a image without El-Torito."); } break; case LIBISO_DIR: { IsoNode *pos; IsoDir *dir = (IsoDir*)iso; if (!hidden) { ret = create_dir(image, dir, &node); if (ret < 0) { goto ex; } if (depth == 1) { /* root is default */ image->rr_reloc_node = node; } else if (depth == 2) { /* Directories in root may be used as relocation dir */ if (opts->rr_reloc_dir != NULL) if (opts->rr_reloc_dir[0] != 0 && strcmp(iso->name, opts->rr_reloc_dir) == 0) image->rr_reloc_node = node; } } ret = ISO_SUCCESS; pos = dir->children; while (pos) { int cret; Ecma119Node *child; cret = create_tree(image, pos, &child, depth + 1, max_path, !!hidden); if (cret < 0) { /* error */ ret = cret; break; } else if (cret == ISO_SUCCESS && !hidden) { /* add child to this node */ int nchildren = node->info.dir->nchildren++; node->info.dir->children[nchildren] = child; child->parent = node; } pos = pos->next; } } break; default: /* should never happen */ ret = ISO_ASSERT_FAILURE; goto ex; } if (ret <= 0) { goto ex; } if (!hidden) { node->iso_name = iso_name; iso_name = NULL; /* now owned by node, do not free */ *tree = node; node = NULL; /* now owned by caller, do not free */ } ret = ISO_SUCCESS; ex: if (iso_name != NULL) free(iso_name); if (ipath != NULL) free(ipath); if (node != NULL) ecma119_node_free(node); if (hidden && ret == ISO_SUCCESS) ret = 0; /* The sources of hidden files are now owned by the rb-tree */ return ret; } /** * Compare the iso name of two ECMA-119 nodes */ static int cmp_node_name(const void *f1, const void *f2) { Ecma119Node *f = *((Ecma119Node**)f1); Ecma119Node *g = *((Ecma119Node**)f2); return strcmp(f->iso_name, g->iso_name); } /** * Sorts a the children of each directory in the ECMA-119 tree represented * by \p root, acording to the order specified in ECMA-119, section 9.3. */ static void sort_tree(Ecma119Node *root) { size_t i; if (root->info.dir->children == NULL) return; qsort(root->info.dir->children, root->info.dir->nchildren, sizeof(void*), cmp_node_name); for (i = 0; i < root->info.dir->nchildren; i++) { if (root->info.dir->children[i]->type == ECMA119_DIR) sort_tree(root->info.dir->children[i]); } } /** * Ensures that the ISO name of each children of the given dir is unique, * changing some of them if needed. * It also ensures that resulting filename is always <= than given * max_name_len, including extension. If needed, the extension will be reduced, * but never under 3 characters. */ static int mangle_single_dir(Ecma119Image *img, Ecma119Node *dir, int max_file_len, int max_dir_len) { int ret; int i, nchildren; Ecma119Node **children; IsoHTable *table; int need_sort = 0; nchildren = dir->info.dir->nchildren; children = dir->info.dir->children; if (nchildren <= 0) return ISO_SUCCESS; /* nothing to do */ /* a hash table will temporary hold the names, for fast searching */ ret = iso_htable_create((nchildren * 100) / 80, iso_str_hash, (compare_function_t)strcmp, &table); if (ret < 0) { return ret; } for (i = 0; i < nchildren; ++i) { char *name = children[i]->iso_name; ret = iso_htable_add(table, name, name); if (ret < 0) { goto mangle_cleanup; } } for (i = 0; i < nchildren; ++i) { char *name, *ext; char full_name[40]; const int full_max_len = 40 - 1; int max; /* computed max len for name, without extension */ int j = i; int digits = 1; /* characters to change per name */ /* first, find all child with same name */ while (j + 1 < nchildren && !cmp_node_name(children + i, children + j + 1)) { ++j; } if (j == i) { /* name is unique */ continue; } if (img->opts->untranslated_name_len) { /* This should not happen because no two IsoNode names should be identical and only unaltered IsoNode names should be seen here. Thus the Ema119Node names should be unique. */ iso_msg_submit(img->image->id, ISO_NAME_NEEDS_TRANSL, 0, "ECMA-119 file name collision: '%s'", children[i]->iso_name); ret = ISO_NAME_NEEDS_TRANSL; goto mangle_cleanup; } /* * A max of 7 characters is good enought, it allows handling up to * 9,999,999 files with same name. We can increment this to * max_name_len, but the int_pow() function must then be modified * to return a bigger integer. */ while (digits < 8) { int ok, k; char *dot; int change = 0; /* number to be written */ /* copy name to buffer */ strncpy(full_name, children[i]->iso_name, full_max_len); full_name[full_max_len] = 0; /* compute name and extension */ dot = strrchr(full_name, '.'); if (dot != NULL && (children[i]->type != ECMA119_DIR || img->opts->allow_dir_id_ext)) { /* * File (normally not dir) with extension * Note that we don't need to check for placeholders, as * tree reparent happens later, so no placeholders can be * here at this time. */ int extlen; full_name[dot - full_name] = '\0'; name = full_name; ext = dot + 1; /* * For iso level 1 we force ext len to be 3, as name * can't grow on the extension space */ extlen = (max_file_len == 12) ? 3 : strlen(ext); max = max_file_len - extlen - 1 - digits; if (max <= 0) { /* this can happen if extension is too long */ if (extlen + max > 3) { /* * reduce extension len, to give name an extra char * note that max is negative or 0 */ extlen = extlen + max - 1; ext[extlen] = '\0'; max = max_file_len - extlen - 1 - digits; } else { /* * error, we don't support extensions < 3 * This can't happen with current limit of digits. */ ret = ISO_ERROR; goto mangle_cleanup; } } /* ok, reduce name by digits */ if (name + max < dot) { name[max] = '\0'; } } else { /* Directory (normally), or file without extension */ if (children[i]->type == ECMA119_DIR) { max = max_dir_len - digits; dot = NULL; /* dots (normally) have no meaning in dirs */ } else { max = max_file_len - digits; } name = full_name; if ((size_t) max < strlen(name)) { name[max] = '\0'; } /* let ext be an empty string */ ext = name + strlen(name); } ok = 1; /* change name of each file */ for (k = i; k <= j; ++k) { char tmp[40]; char fmt[16]; if (dot != NULL) { sprintf(fmt, "%%s%%0%dd.%%s", digits); } else { sprintf(fmt, "%%s%%0%dd%%s", digits); } while (1) { sprintf(tmp, fmt, name, change, ext); ++change; if (change > int_pow(10, digits)) { ok = 0; break; } if (!iso_htable_get(table, tmp, NULL)) { /* the name is unique, so it can be used */ break; } } if (ok) { char *new = strdup(tmp); if (new == NULL) { ret = ISO_OUT_OF_MEM; goto mangle_cleanup; } #ifdef Libisofs_extra_verbose_debuG iso_msg_debug(img->image->id, "\"%s\" renamed to \"%s\"", children[k]->iso_name, new); #endif iso_htable_remove_ptr(table, children[k]->iso_name, NULL); free(children[k]->iso_name); children[k]->iso_name = new; iso_htable_add(table, new, new); /* * if we change a name we need to sort again children * at the end */ need_sort = 1; } else { /* we need to increment digits */ break; } } if (ok) { break; } else { ++digits; } } if (digits == 8) { ret = ISO_MANGLE_TOO_MUCH_FILES; goto mangle_cleanup; } i = j; } /* * If needed, sort again the files inside dir */ if (need_sort) { qsort(children, nchildren, sizeof(void*), cmp_node_name); } ret = ISO_SUCCESS; mangle_cleanup : ; iso_htable_destroy(table, NULL); return ret; } static int mangle_dir(Ecma119Image *img, Ecma119Node *dir, int max_file_len, int max_dir_len) { int ret; size_t i; ret = mangle_single_dir(img, dir, max_file_len, max_dir_len); if (ret < 0) { return ret; } /* recurse */ for (i = 0; i < dir->info.dir->nchildren; ++i) { if (dir->info.dir->children[i]->type == ECMA119_DIR) { ret = mangle_dir(img, dir->info.dir->children[i], max_file_len, max_dir_len); if (ret < 0) { /* error */ return ret; } } } return ISO_SUCCESS; } static int mangle_tree(Ecma119Image *img, Ecma119Node *dir, int recurse) { int max_file, max_dir; Ecma119Node *root; if (img->opts->untranslated_name_len > 0) { max_file = max_dir = img->opts->untranslated_name_len; } else if (img->opts->max_37_char_filenames) { max_file = max_dir = 37; } else if (img->opts->iso_level == 1) { max_file = 12; /* 8 + 3 + 1 */ max_dir = 8; } else { max_file = max_dir = 31; } if (dir != NULL) { root = dir; } else if (img->eff_partition_offset > 0) { root = img->partition_root; } else { root = img->root; } if (recurse) { return mangle_dir(img, root, max_file, max_dir); } else { return mangle_single_dir(img, root, max_file, max_dir); } } /** * Create a new ECMA-119 node representing a placeholder for a relocated * dir. * * See IEEE P1282, section 4.1.5 for details */ static int create_placeholder(Ecma119Node *parent, Ecma119Node *real, Ecma119Node **node) { Ecma119Node *ret; ret = calloc(1, sizeof(Ecma119Node)); if (ret == NULL) { return ISO_OUT_OF_MEM; } /* * TODO * If real is a dir, while placeholder is a file, ISO name restricctions * are different, what to do? */ ret->iso_name = strdup(real->iso_name); if (ret->iso_name == NULL) { free(ret); return ISO_OUT_OF_MEM; } /* take a ref to the IsoNode */ ret->node = real->node; iso_node_ref(real->node); ret->parent = parent; ret->type = ECMA119_PLACEHOLDER; ret->info.real_me = real; ret->ino = real->ino; ret->nlink = real->nlink; *node = ret; return ISO_SUCCESS; } static size_t max_child_name_len(Ecma119Node *dir) { size_t ret = 0, i; for (i = 0; i < dir->info.dir->nchildren; i++) { size_t len = strlen(dir->info.dir->children[i]->iso_name); ret = MAX(ret, len); } return ret; } /** * Relocates a directory, as specified in Rock Ridge Specification * (see IEEE P1282, section 4.1.5). This is needed when the number of levels * on a directory hierarchy exceeds 8, or the length of a path is higher * than 255 characters, as specified in ECMA-119, section 6.8.2.1 */ static int reparent(Ecma119Node *child, Ecma119Node *parent) { int ret; size_t i; Ecma119Node *placeholder; /* replace the child in the original parent with a placeholder */ for (i = 0; i < child->parent->info.dir->nchildren; i++) { if (child->parent->info.dir->children[i] == child) { ret = create_placeholder(child->parent, child, &placeholder); if (ret < 0) { return ret; } child->parent->info.dir->children[i] = placeholder; break; } } /* just for debug, this should never happen... */ if (i == child->parent->info.dir->nchildren) { return ISO_ASSERT_FAILURE; } /* keep track of the real parent */ child->info.dir->real_parent = child->parent; /* add the child to its new parent */ child->parent = parent; parent->info.dir->nchildren++; parent->info.dir->children = realloc(parent->info.dir->children, sizeof(void*) * parent->info.dir->nchildren); parent->info.dir->children[parent->info.dir->nchildren - 1] = child; return ISO_SUCCESS; } /** * Reorder the tree, if necessary, to ensure that * - the depth is at most 8 * - each path length is at most 255 characters * This restriction is imposed by ECMA-119 specification (ECMA-119, 6.8.2.1). * * @param dir * Dir we are currently processing * @param level * Level of the directory in the hierarchy * @param pathlen * Length of the path until dir, including it * @return * 1 success, < 0 error */ static int reorder_tree(Ecma119Image *img, Ecma119Node *dir, int dir_level, int dir_pathlen) { int ret, level, pathlen, newpathlen; size_t max_path, i; Ecma119Node *reloc, *child; /* might change by relocation */ level = dir_level; pathlen = dir_pathlen; max_path = pathlen + 1 + max_child_name_len(dir); if (level > 8 || max_path > 255) { reloc = img->rr_reloc_node; if (reloc == NULL) { if (img->eff_partition_offset > 0) { reloc = img->partition_root; } else { reloc = img->root; } } ret = reparent(dir, reloc); if (ret < 0) { return ret; } if (reloc == img->root || reloc == img->partition_root) { /* * we are appended to the root's children now, so there is no * need to recurse (the root will hit us again) */ return ISO_SUCCESS; } /* dir is now the relocated Ecma119Node */ pathlen = 37 + 1; /* The dir name might get longer by mangling */ level = 2; if (img->opts->rr_reloc_dir != NULL) { pathlen += strlen(img->rr_reloc_node->iso_name) + 1; if(img->opts->rr_reloc_dir[0] != 0) level = 3; } } if (ecma119_is_dedicated_reloc_dir(img, (Ecma119Node *) dir)) return ISO_SUCCESS; for (i = 0; i < dir->info.dir->nchildren; i++) { child = dir->info.dir->children[i]; if (child->type == ECMA119_DIR) { newpathlen = pathlen + 1 + strlen(child->iso_name); ret = reorder_tree(img, child, level + 1, newpathlen); if (ret < 0) return ret; } } return ISO_SUCCESS; } /* * @param flag * bit0= recursion * bit1= count nodes rather than fill them into *nodes * @return * <0 error * bit0= saw ino == 0 * bit1= saw ino != 0 */ static int make_node_array(Ecma119Image *img, Ecma119Node *dir, Ecma119Node **nodes, size_t nodes_size, size_t *node_count, int flag) { int ret, result = 0; size_t i; Ecma119Node *child; if (!(flag & 1)) { *node_count = 0; if (!(flag & 2)) { /* Register the tree root node */ if (*node_count >= nodes_size) { iso_msg_submit(img->image->id, ISO_ASSERT_FAILURE, 0, "Programming error: Overflow of hardlink sort array"); return ISO_ASSERT_FAILURE; } nodes[*node_count] = dir; } result|= (dir->ino == 0 ? 1 : 2); (*node_count)++; } for (i = 0; i < dir->info.dir->nchildren; i++) { child = dir->info.dir->children[i]; if (!(flag & 2)) { if (*node_count >= nodes_size) { iso_msg_submit(img->image->id, ISO_ASSERT_FAILURE, 0, "Programming error: Overflow of hardlink sort array"); return ISO_ASSERT_FAILURE; } nodes[*node_count] = child; } result|= (child->ino == 0 ? 1 : 2); (*node_count)++; if (child->type == ECMA119_DIR) { ret = make_node_array(img, child, nodes, nodes_size, node_count, flag | 1); if (ret < 0) return ret; } } return result; } /* * @param flag * bit0= compare stat properties and attributes * bit1= treat all nodes with image ino == 0 as unique */ static int ecma119_node_cmp_flag(const void *v1, const void *v2, int flag) { int ret; Ecma119Node *n1, *n2; n1 = *((Ecma119Node **) v1); n2 = *((Ecma119Node **) v2); if (n1 == n2) return 0; ret = iso_node_cmp_flag(n1->node, n2->node, flag & (1 | 2)); return ret; } static int ecma119_node_cmp_hard(const void *v1, const void *v2) { return ecma119_node_cmp_flag(v1, v2, 1); } static int ecma119_node_cmp_nohard(const void *v1, const void *v2) { return ecma119_node_cmp_flag(v1, v2, 1 | 2); } static int family_set_ino(Ecma119Image *img, Ecma119Node **nodes, size_t family_start, size_t next_family, ino_t img_ino, ino_t prev_ino, int flag) { size_t i; if (img_ino != 0) { /* Check whether this is the same img_ino as in the previous family (e.g. by property divergence of imported hardlink). */ if (img_ino == prev_ino) img_ino = 0; /* Accept only if it is within the 32 bit range. */ if (((uint64_t) img_ino) > 0xffffffff) img_ino = 0; } if (img_ino == 0) { img_ino = img_give_ino_number(img->image, 0); } for (i = family_start; i < next_family; i++) { nodes[i]->ino = img_ino; nodes[i]->nlink = next_family - family_start; } return 1; } static int match_hardlinks(Ecma119Image *img, Ecma119Node *dir, int flag) { int ret; size_t nodes_size = 0, node_count = 0, i, family_start; Ecma119Node **nodes = NULL; unsigned int fs_id; dev_t dev_id; ino_t img_ino = 0, prev_ino = 0; ret = make_node_array(img, dir, nodes, nodes_size, &node_count, 2); if (ret < 0) return ret; nodes_size = node_count; nodes = (Ecma119Node **) calloc(sizeof(Ecma119Node *), nodes_size); if (nodes == NULL) return ISO_OUT_OF_MEM; ret = make_node_array(img, dir, nodes, nodes_size, &node_count, 0); if (ret < 0) goto ex; /* Sort according to id tuples, IsoFileSrc identity, properties, xattr. */ if (img->opts->hardlinks) qsort(nodes, node_count, sizeof(Ecma119Node *), ecma119_node_cmp_hard); else qsort(nodes, node_count, sizeof(Ecma119Node *), ecma119_node_cmp_nohard); /* Hand out image inode numbers to all Ecma119Node.ino == 0 . Same sorting rank gets same inode number. Split those image inode number families where the sort criterion differs. */ iso_node_get_id(nodes[0]->node, &fs_id, &dev_id, &img_ino, 1); family_start = 0; for (i = 1; i < node_count; i++) { if (nodes[i]->type != ECMA119_DIR && ecma119_node_cmp_hard(nodes + (i - 1), nodes + i) == 0) { /* Still in same ino family */ if (img_ino == 0) { /* Just in case any member knows its img_ino */ iso_node_get_id(nodes[0]->node, &fs_id, &dev_id, &img_ino, 1); } continue; } family_set_ino(img, nodes, family_start, i, img_ino, prev_ino, 0); prev_ino = img_ino; iso_node_get_id(nodes[i]->node, &fs_id, &dev_id, &img_ino, 1); family_start = i; } family_set_ino(img, nodes, family_start, i, img_ino, prev_ino, 0); ret = ISO_SUCCESS; ex:; if (nodes != NULL) free((char *) nodes); return ret; } int ecma119_tree_create(Ecma119Image *img) { int ret; Ecma119Node *root; ret = create_tree(img, (IsoNode*)img->image->root, &root, 1, 0, 0); if (ret <= 0) { if (ret == 0) { /* unexpected error, root ignored!! This can't happen */ ret = ISO_ASSERT_FAILURE; } return ret; } if (img->eff_partition_offset > 0) { img->partition_root = root; } else { img->root = root; } iso_msg_debug(img->image->id, "Matching hardlinks..."); ret = match_hardlinks(img, root, 0); if (ret < 0) { return ret; } iso_msg_debug(img->image->id, "Sorting the low level tree..."); sort_tree(root); iso_msg_debug(img->image->id, "Mangling names..."); ret = mangle_tree(img, NULL, 1); if (ret < 0) { return ret; } if (img->opts->rockridge && !img->opts->allow_deep_paths) { /* Relocate deep directories, acording to RRIP, 4.1.5 */ ret = reorder_tree(img, root, 1, 0); if (ret < 0) { return ret; } /* * and we need to remangle the root directory, as the function * above could insert new directories into the relocation directory. * Note that recurse = 0, as we don't need to recurse. */ ret = mangle_tree(img, img->rr_reloc_node, 0); if (ret < 0) { return ret; } } return ISO_SUCCESS; } /** * Search the tree for a certain IsoNode and return its owning Ecma119Node * or NULL. */ static Ecma119Node *search_iso_node(Ecma119Node *root, IsoNode *node) { size_t i; Ecma119Node *res = NULL; if (root->node == node) return root; for (i = 0; i < root->info.dir->nchildren && res == NULL; i++) { if (root->info.dir->children[i]->type == ECMA119_DIR) res = search_iso_node(root->info.dir->children[i], node); else if (root->info.dir->children[i]->node == node) res = root->info.dir->children[i]; } return res; } Ecma119Node *ecma119_search_iso_node(Ecma119Image *img, IsoNode *node) { Ecma119Node *res = NULL; if (img->root != NULL) res = search_iso_node(img->root, node); return res; } libisofs-1.4.2/libisofs/rockridge.c0000644000175700017510000021353312606516670014230 00000000000000/* * Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2007 Mario Danic * Copyright (c) 2009 - 2015 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif #include #include #include "rockridge.h" #include "node.h" #include "ecma119_tree.h" #include "writer.h" #include "messages.h" #include "image.h" #include "aaip_0_2.h" #include "libisofs.h" #ifdef Libisofs_with_rrip_rR #define ISO_ROCKRIDGE_IN_DIR_REC 128 #else #define ISO_ROCKRIDGE_IN_DIR_REC 124 #endif #define ISO_CE_ENTRY_SIZE 28 static int susp_add_ES(Ecma119Image *t, struct susp_info *susp, int to_ce, int seqno); static int susp_make_CE(Ecma119Image *t, uint8_t **CE, uint32_t block_offset, uint32_t byte_offset, uint32_t size); static int susp_append(Ecma119Image *t, struct susp_info *susp, uint8_t *data) { susp->n_susp_fields++; susp->susp_fields = realloc(susp->susp_fields, sizeof(void*) * susp->n_susp_fields); if (susp->susp_fields == NULL) { return ISO_OUT_OF_MEM; } susp->susp_fields[susp->n_susp_fields - 1] = data; susp->suf_len += data[2]; return ISO_SUCCESS; } static int susp_append_ce(Ecma119Image *t, struct susp_info *susp, uint8_t *data) { int to_alloc = 1, ret; unsigned char *pad; uint8_t *CE; size_t next_alloc; if (data[0] && (susp->ce_len + data[2] + ISO_CE_ENTRY_SIZE - 1) / BLOCK_SIZE != susp->ce_len / BLOCK_SIZE) { /* Linux fs/isofs wants byte_offset + ce_len <= BLOCK_SIZE. So this Continuation Area needs to end by a CE which points to the start of the next block. */ to_alloc = 2; if ((susp->ce_len + ISO_CE_ENTRY_SIZE) % BLOCK_SIZE) to_alloc = 3; /* need a PAD pseudo entry */ } if (susp->ce_susp_fields == NULL) susp->alloc_ce_susp_fields = 0; if (susp->n_ce_susp_fields + to_alloc > susp->alloc_ce_susp_fields) { next_alloc = susp->alloc_ce_susp_fields; while (susp->n_ce_susp_fields + to_alloc > next_alloc) next_alloc += ISO_SUSP_CE_ALLOC_STEP; susp->ce_susp_fields = realloc(susp->ce_susp_fields, sizeof(uint8_t *) * next_alloc); if (susp->ce_susp_fields == NULL) return ISO_OUT_OF_MEM; susp->alloc_ce_susp_fields = next_alloc; } if (to_alloc >= 2) { /* Insert CE entry (actual CE size later by susp_update_CE_sizes) */ ret = susp_make_CE(t, &CE, (uint32_t) (susp->ce_block + susp->ce_len / BLOCK_SIZE + 1), (uint32_t) 0, (uint32_t) 2048); if (ret < 0) return ret; susp->ce_susp_fields[susp->n_ce_susp_fields] = CE; susp->ce_len += ISO_CE_ENTRY_SIZE; susp->n_ce_susp_fields++; } if (to_alloc >= 3) { #ifdef Libisofs_ce_calc_debuG fprintf(stderr, "\nlibburn_DEBUG: Inserting %d bytes of CE padding\n\n", (int) (BLOCK_SIZE - (susp->ce_len % BLOCK_SIZE))); #endif /* Libisofs_ce_calc_debuG */ pad = malloc(1); if (pad == NULL) return ISO_OUT_OF_MEM; pad[0] = 0; susp->ce_susp_fields[susp->n_ce_susp_fields] = pad; if (susp->ce_len % BLOCK_SIZE) susp->ce_len += BLOCK_SIZE - (susp->ce_len % BLOCK_SIZE); susp->n_ce_susp_fields++; } susp->ce_susp_fields[susp->n_ce_susp_fields] = data; susp->n_ce_susp_fields++; if (data[0] == 0) { if (susp->ce_len % BLOCK_SIZE) susp->ce_len += BLOCK_SIZE - (susp->ce_len % BLOCK_SIZE); } else { susp->ce_len += data[2]; } return ISO_SUCCESS; } static uid_t px_get_uid(Ecma119Image *t, Ecma119Node *n) { if (t->replace_uid) { return t->uid; } else { return n->node->uid; } } static uid_t px_get_gid(Ecma119Image *t, Ecma119Node *n) { if (t->replace_gid) { return t->gid; } else { return n->node->gid; } } static mode_t px_get_mode(Ecma119Image *t, Ecma119Node *n) { if ((n->type == ECMA119_DIR || n->type == ECMA119_PLACEHOLDER)) { if (t->replace_dir_mode) { return (n->node->mode & S_IFMT) | t->dir_mode; } } else { if (t->replace_file_mode) { return (n->node->mode & S_IFMT) | t->file_mode; } } return n->node->mode; } /** * Add a PX System Use Entry. The PX System Use Entry is used to add POSIX * file attributes, such as access permissions or user and group id, to a * ECMA 119 directory record. (RRIP, 4.1.1) */ static int rrip_add_PX(Ecma119Image *t, Ecma119Node *n, struct susp_info *susp) { uint8_t *PX = malloc(44); if (PX == NULL) { return ISO_OUT_OF_MEM; } PX[0] = 'P'; PX[1] = 'X'; if (t->opts->rrip_1_10_px_ino || !t->opts->rrip_version_1_10 ) { PX[2] = 44; } else { PX[2] = 36; } PX[3] = 1; iso_bb(&PX[4], (uint32_t) px_get_mode(t, n), 4); iso_bb(&PX[12], (uint32_t) n->nlink, 4); iso_bb(&PX[20], (uint32_t) px_get_uid(t, n), 4); iso_bb(&PX[28], (uint32_t) px_get_gid(t, n), 4); if (t->opts->rrip_1_10_px_ino || !t->opts->rrip_version_1_10) { iso_bb(&PX[36], (uint32_t) n->ino, 4); } return susp_append(t, susp, PX); } /** * Add to the given tree node a TF System Use Entry, used to record some * time stamps related to the file (RRIP, 4.1.6). */ static int rrip_add_TF(Ecma119Image *t, Ecma119Node *n, struct susp_info *susp) { IsoNode *iso; uint8_t *TF = malloc(5 + 3 * 7); if (TF == NULL) { return ISO_OUT_OF_MEM; } TF[0] = 'T'; TF[1] = 'F'; TF[2] = 5 + 3 * 7; TF[3] = 1; TF[4] = (1 << 1) | (1 << 2) | (1 << 3); iso = n->node; iso_datetime_7(&TF[5], t->replace_timestamps ? t->timestamp : iso->mtime, t->opts->always_gmt); iso_datetime_7(&TF[12], t->replace_timestamps ? t->timestamp : iso->atime, t->opts->always_gmt); iso_datetime_7(&TF[19], t->replace_timestamps ? t->timestamp : iso->ctime, t->opts->always_gmt); return susp_append(t, susp, TF); } /** * Add a PL System Use Entry, used to record the location of the original * parent directory of a directory which has been relocated. * * This is special because it doesn't modify the susp fields of the directory * that gets passed to it; it modifies the susp fields of the ".." entry in * that directory. * * See RRIP, 4.1.5.2 for more details. */ static int rrip_add_PL(Ecma119Image *t, Ecma119Node *n, struct susp_info *susp) { uint8_t *PL; if (n->type != ECMA119_DIR || n->info.dir->real_parent == NULL) { /* should never occur */ return ISO_ASSERT_FAILURE; } PL = malloc(12); if (PL == NULL) { return ISO_OUT_OF_MEM; } PL[0] = 'P'; PL[1] = 'L'; PL[2] = 12; PL[3] = 1; /* write the location of the real parent, already computed */ iso_bb(&PL[4], n->info.dir->real_parent->info.dir->block - t->eff_partition_offset, 4); return susp_append(t, susp, PL); } /** * Add a RE System Use Entry to the given tree node. The purpose of the * this System Use Entry is to indicate to an RRIP-compliant receiving * system that the Directory Record in which an "RE" System Use Entry is * recorded has been relocated from another position in the original * Directory Hierarchy. * * See RRIP, 4.1.5.3 for more details. */ static int rrip_add_RE(Ecma119Image *t, Ecma119Node *n, struct susp_info *susp) { uint8_t *RE = malloc(4); if (RE == NULL) { return ISO_OUT_OF_MEM; } RE[0] = 'R'; RE[1] = 'E'; RE[2] = 4; RE[3] = 1; return susp_append(t, susp, RE); } /** * Add a PN System Use Entry to the given tree node. * The PN System Use Entry is used to store the device number, and it's * mandatory if the tree node corresponds to a character or block device. * * See RRIP, 4.1.2 for more details. */ static int rrip_add_PN(Ecma119Image *t, Ecma119Node *n, struct susp_info *susp) { IsoSpecial *node; uint8_t *PN; int high_shift= 0; node = (IsoSpecial*)n->node; if (node->node.type != LIBISO_SPECIAL) { /* should never occur */ return ISO_ASSERT_FAILURE; } PN = malloc(20); if (PN == NULL) { return ISO_OUT_OF_MEM; } PN[0] = 'P'; PN[1] = 'N'; PN[2] = 20; PN[3] = 1; /* (dev_t >> 32) causes compiler warnings on FreeBSD. RRIP 1.10 4.1.2 prescribes PN "Dev_t High" to be 0 on 32 bit dev_t. */ if (sizeof(node->dev) > 4) { high_shift = 32; iso_bb(&PN[4], (uint32_t) (node->dev >> high_shift), 4); } else iso_bb(&PN[4], 0, 4); iso_bb(&PN[12], (uint32_t) (node->dev & 0xffffffff), 4); return susp_append(t, susp, PN); } /** * Add to the given tree node a CL System Use Entry, that is used to record * the new location of a directory which has been relocated. * * See RRIP, 4.1.5.1 for more details. */ static int rrip_add_CL(Ecma119Image *t, Ecma119Node *n, struct susp_info *susp) { uint8_t *CL; if (n->type != ECMA119_PLACEHOLDER) { /* should never occur */ return ISO_ASSERT_FAILURE; } CL = malloc(12); if (CL == NULL) { return ISO_OUT_OF_MEM; } CL[0] = 'C'; CL[1] = 'L'; CL[2] = 12; CL[3] = 1; iso_bb(&CL[4], n->info.real_me->info.dir->block - t->eff_partition_offset, 4); return susp_append(t, susp, CL); } /** * Convert a RR filename to the requested charset. On any conversion error, * the original name will be used. * @param flag bit0= do not issue error messages */ int iso_get_rr_name(IsoWriteOpts *opts, char *input_charset, char *output_charset, int imgid, char *str, char **name, int flag) { int ret; if (!strcmp(input_charset, output_charset)) { /* no conversion needed */ ret = iso_clone_mem(str, name, 0); return ret; } ret = strconv(str, input_charset, output_charset, name); if (ret < 0) { /* TODO we should check for possible cancelation */ if (!(flag & 1)) iso_msg_submit(imgid, ISO_FILENAME_WRONG_CHARSET, ret, "Charset conversion error. Cannot convert %s from %s to %s", str, input_charset, output_charset); *name = NULL; return ISO_FILENAME_WRONG_CHARSET; } return ISO_SUCCESS; } static char *get_rr_fname(Ecma119Image *t, char *str) { int ret; char *name = NULL; ret = iso_get_rr_name(t->opts, t->input_charset, t->output_charset, t->image->id, str, &name, 0); if (ret < 0) return NULL; return name; } /** * Add a NM System Use Entry to the given tree node. The purpose of this * System Use Entry is to store the content of an Alternate Name to support * POSIX-style or other names. * * See RRIP, 4.1.4 for more details. * * @param size * Length of the name to be included into the NM * @param flags * @param ce * Whether to add or not to CE */ static int rrip_add_NM(Ecma119Image *t, struct susp_info *susp, char *name, int size, int flags, int ce) { uint8_t *NM; if (size > 250) return ISO_ASSERT_FAILURE; NM = malloc(size + 5); if (NM == NULL) { return ISO_OUT_OF_MEM; } NM[0] = 'N'; NM[1] = 'M'; NM[2] = size + 5; NM[3] = 1; NM[4] = flags; if (size) { memcpy(&NM[5], name, size); } if (ce) { return susp_append_ce(t, susp, NM); } else { return susp_append(t, susp, NM); } } /** * Add a new SL component (RRIP, 4.1.3.1) to a list of components. * * @param n * Number of components. It will be updated. * @param compos * Pointer to the list of components. * @param s * The component content * @param size * Size of the component content * @param fl * Flags * @return * 1 on success, < 0 on error */ static int rrip_SL_append_comp(size_t *n, uint8_t ***comps, char *s, int size, char fl) { uint8_t *comp = malloc(size + 2); if (comp == NULL) { return ISO_OUT_OF_MEM; } (*n)++; comp[0] = fl; comp[1] = size; *comps = realloc(*comps, (*n) * sizeof(void*)); if (*comps == NULL) { free(comp); return ISO_OUT_OF_MEM; } (*comps)[(*n) - 1] = comp; if (size) { memcpy(&comp[2], s, size); } return ISO_SUCCESS; } #ifdef Libisofs_with_rrip_rR /** * Add a RR System Use Entry to the given tree node. This is an obsolete * entry from before RRIP-1.10. Nevertheless mkisofs produces it. There * is the suspicion that some operating systems could take it as indication * for Rock Ridge. * * The meaning of the payload byte is documented e.g. in * /usr/src/linux/fs/isofs/rock.h * It announces the presence of entries PX, PN, SL, NM, CL, PL, RE, TF * by payload byte bits 0 to 7. */ static int rrip_add_RR(Ecma119Image *t, Ecma119Node *n, struct susp_info *susp) { uint8_t *RR; RR = malloc(5); if (RR == NULL) { return ISO_OUT_OF_MEM; } RR[0] = 'R'; RR[1] = 'R'; RR[2] = 5; RR[3] = 1; /* <<< ts B20307 : Not all directories have NM, many files have more entries */ RR[4] = 0x89; /* TF, NM , PX */ /* >>> ts B20307 : find out whether n carries PX, PN, SL, NM, CL, PL, RE, TF and mark by bit0 to bit7 in RR[4] */ return susp_append(t, susp, RR); } #endif /* Libisofs_with_rrip_rR */ /** * Add a SL System Use Entry to the given tree node. This is used to store * the content of a symbolic link, and is mandatory if the tree node * indicates a symbolic link (RRIP, 4.1.3). * * @param comp * Components of the SL System Use Entry. If they don't fit in a single * SL, more than one SL will be added. * @param n * Number of components in comp * @param ce * Whether to add to a continuation area or system use field. */ static int rrip_add_SL(Ecma119Image *t, struct susp_info *susp, uint8_t **comp, size_t n, int ce) { int ret; size_t i, j; int total_comp_len = 0; size_t pos, written = 0; uint8_t *SL; for (i = 0; i < n; i++) { total_comp_len += comp[i][1] + 2; if (total_comp_len > 250) { /* we need a new SL entry */ total_comp_len -= comp[i][1] + 2; SL = malloc(total_comp_len + 5); if (SL == NULL) { return ISO_OUT_OF_MEM; } SL[0] = 'S'; SL[1] = 'L'; SL[2] = total_comp_len + 5; SL[3] = 1; SL[4] = 1; /* CONTINUE */ pos = 5; for (j = written; j < i; j++) { memcpy(&SL[pos], comp[j], comp[j][1] + 2); pos += comp[j][1] + 2; } /* * In this case we are sure we're writting to CE. Check for * debug purposes */ if (ce == 0) { free(SL); return ISO_ASSERT_FAILURE; } ret = susp_append_ce(t, susp, SL); if (ret < 0) { free(SL); return ret; } SL = NULL; /* now owned by susp */ written = i; total_comp_len = comp[i][1] + 2; } } SL = malloc(total_comp_len + 5); if (SL == NULL) { return ISO_OUT_OF_MEM; } SL[0] = 'S'; SL[1] = 'L'; SL[2] = total_comp_len + 5; SL[3] = 1; SL[4] = 0; pos = 5; for (j = written; j < n; j++) { memcpy(&SL[pos], comp[j], comp[j][1] + 2); pos += comp[j][1] + 2; } if (ce) { ret = susp_append_ce(t, susp, SL); } else { ret = susp_append(t, susp, SL); } return ret; } /* @param flag bit1= care about crossing block boundaries */ static int susp_calc_add_to_ce(size_t *ce, size_t base_ce, int add, int flag) { if (flag & 2) { /* Account for inserted CE before size exceeds block size */ if ((*ce + base_ce + add + ISO_CE_ENTRY_SIZE - 1) / BLOCK_SIZE != (*ce + base_ce) / BLOCK_SIZE) { /* Insert CE and padding */ *ce += ISO_CE_ENTRY_SIZE; if ((*ce + base_ce) % BLOCK_SIZE) *ce += BLOCK_SIZE - ((*ce + base_ce) % BLOCK_SIZE); } } *ce += add; return ISO_SUCCESS; } /* @param flag bit0= only account sizes in sua_free resp. ce_len. Parameter susp may be NULL in this case bit1= account for crossing block boundaries (implied by bit0 == 0) @param ce_len counts the freshly added CA size of the current node @param ce_mem tells the CA size of previous nodes in the same directory */ static int aaip_add_AL(Ecma119Image *t, struct susp_info *susp, uint8_t **data, size_t num_data, size_t *sua_free, size_t *ce_len, size_t ce_mem, int flag) { int ret, done = 0, len, es_extra = 0; uint8_t *aapt, *cpt; size_t count = 0; if (!(flag & 1)) flag |= 2; if (!t->opts->aaip_susp_1_10) es_extra = 5; if (*sua_free < num_data + es_extra || *ce_len > 0) { if (es_extra > 0) susp_calc_add_to_ce(ce_len, ce_mem, es_extra, flag & 2); done = 0; for (aapt = *data; !done; aapt += aapt[2]) { done = !(aapt[4] & 1); len = aapt[2]; susp_calc_add_to_ce(ce_len, ce_mem, len, flag & 2); count += len; } } else { *sua_free -= num_data + es_extra; } if (flag & 1) return ISO_SUCCESS; /* If AAIP enabled and announced by ER : Write ES field to announce AAIP */ if (t->opts->aaip && !t->opts->aaip_susp_1_10) { ret = susp_add_ES(t, susp, (*ce_len > 0), 1); if (ret < 0) return ret; } aapt = *data; if (!(aapt[4] & 1)) { /* Single field can be handed over directly */ if (*ce_len > 0) { ret = susp_append_ce(t, susp, aapt); } else { ret = susp_append(t, susp, aapt); } *data = NULL; return ISO_SUCCESS; } /* Multiple fields have to be handed over as single field copies */ done = 0; for (aapt = *data; !done; aapt += aapt[2]) { done = !(aapt[4] & 1); len = aapt[2]; cpt = calloc(aapt[2], 1); if (cpt == NULL) return ISO_OUT_OF_MEM; memcpy(cpt, aapt, len); if (*ce_len > 0) { ret = susp_append_ce(t, susp, cpt); } else { ret = susp_append(t, susp, cpt); } if (ret == -1) return ret; } free(*data); *data = NULL; return ISO_SUCCESS; } /** * Add a SUSP "ER" System Use Entry to identify the Rock Ridge specification. * * The "ER" System Use Entry is used to uniquely identify a specification * compliant with SUSP. This method adds to the given tree node "." entry * the "ER" corresponding to the RR protocol. * * See SUSP, 5.5 and RRIP, 4.3 for more details. */ static int rrip_add_ER(Ecma119Image *t, struct susp_info *susp) { unsigned char *ER; if (!t->opts->rrip_version_1_10) { /* According to RRIP 1.12 this is the future form: 4.3 "Specification of the ER System Use Entry Values for RRIP" talks of "IEEE_P1282" in each of the three strings and finally states "Note: Upon adoption as an IEEE standard, these lengths will each decrease by 1." So "IEEE_P1282" would be the new form, "RRIP_1991A" is the old form. */ ER = malloc(182); if (ER == NULL) { return ISO_OUT_OF_MEM; } ER[0] = 'E'; ER[1] = 'R'; ER[2] = 182; ER[3] = 1; ER[4] = 9; ER[5] = 72; ER[6] = 93; ER[7] = 1; memcpy(&ER[8], "IEEE_1282", 9); memcpy(&ER[17], "THE IEEE 1282 PROTOCOL PROVIDES SUPPORT FOR POSIX " "FILE SYSTEM SEMANTICS.", 72); memcpy(&ER[89], "PLEASE CONTACT THE IEEE STANDARDS DEPARTMENT, " "PISCATAWAY, NJ, USA FOR THE 1282 SPECIFICATION.", 93); } else { /* RRIP 1.09 and 1.10: 4.3 Specification of the ER System Use Field Values for RRIP The Extension Version number for the version of the RRIP defined herein shall be 1. The content of the Extension Identifier field shall be "RRIP_1991A". The Identifier Length shall be 10. The recommended content of the Extension Descriptor shall be "THE ROCK RIDGE INTERCHANGE PROTOCOL PROVIDES SUPPORT FOR POSIX FILE SYSTEM SEMANTICS." The corresponding Description Length is 84. The recommended content of the Extension Source shall be "PLEASE CONTACT DISC PUBLISHER FOR SPECIFICATION SOURCE. SEE PUBLISHER IDENTIFIER IN PRIMARY VOLUME DESCRIPTOR FOR CONTACT INFORMATION." The corresponding Source Length is 135. */ ER = malloc(237); if (ER == NULL) { return ISO_OUT_OF_MEM; } ER[0] = 'E'; ER[1] = 'R'; ER[2] = 237; ER[3] = 1; ER[4] = 10; ER[5] = 84; ER[6] = 135; ER[7] = 1; memcpy(&ER[8], "RRIP_1991A", 10); memcpy(&ER[18], "THE ROCK RIDGE INTERCHANGE PROTOCOL PROVIDES SUPPORT FOR POSIX FILE SYSTEM SEMANTICS", 84); memcpy(&ER[102], "PLEASE CONTACT DISC PUBLISHER FOR SPECIFICATION SOURCE. SEE PUBLISHER IDENTIFIER IN PRIMARY VOLUME DESCRIPTOR FOR CONTACT INFORMATION.", 135); } /** This always goes to continuation area */ return susp_append_ce(t, susp, ER); } static int aaip_add_ER(Ecma119Image *t, struct susp_info *susp, int flag) { unsigned char *ER; ER = malloc(160); if (ER == NULL) { return ISO_OUT_OF_MEM; } ER[0] = 'E'; ER[1] = 'R'; ER[2] = 160; ER[3] = 1; ER[4] = 9; ER[5] = 81; ER[6] = 62; ER[7] = 1; memcpy(ER + 8, "AAIP_0200", 9); memcpy(ER + 17, "AL PROVIDES VIA AAIP 2.0 SUPPORT FOR ARBITRARY FILE ATTRIBUTES" " IN ISO 9660 IMAGES", 81); memcpy(ER + 98, "PLEASE CONTACT THE LIBBURNIA PROJECT VIA LIBBURNIA-PROJECT.ORG", 62); /** This always goes to continuation area */ return susp_append_ce(t, susp, ER); } /** * Create the byte representation of a CE entry. * (SUSP, 5.1). */ static int susp_make_CE(Ecma119Image *t, uint8_t **CE, uint32_t block_offset, uint32_t byte_offset, uint32_t size) { uint8_t *data; *CE = NULL; data = calloc(1, 28); if (data == NULL) return ISO_OUT_OF_MEM; *CE = data; data[0] = 'C'; data[1] = 'E'; data[2] = 28; data[3] = 1; iso_bb(&data[4], block_offset - t->eff_partition_offset, 4); iso_bb(&data[12], byte_offset, 4); iso_bb(&data[20], size, 4); return ISO_SUCCESS; } /** * Add a CE System Use Entry to the given tree node. A "CE" is used to add * a continuation area, where additional System Use Entry can be written. * (SUSP, 5.1). */ static int susp_add_CE(Ecma119Image *t, size_t ce_len, struct susp_info *susp) { uint32_t block_offset, byte_offset; uint8_t *CE; int ret; /* Linux fs/isofs wants byte_offset + ce_len <= BLOCK_SIZE * Here the byte_offset is reduced to the minimum. */ block_offset = susp->ce_block + susp->ce_len / BLOCK_SIZE; byte_offset = susp->ce_len % BLOCK_SIZE; ret = susp_make_CE(t, &CE, block_offset, byte_offset, (uint32_t) ce_len); if (ret < 0) return ret; return susp_append(t, susp, CE); } /** * Add a SP System Use Entry. The SP provide an identifier that the SUSP is * used within the volume. The SP shall be recorded in the "." entry of the * root directory. See SUSP, 5.3 for more details. */ static int susp_add_SP(Ecma119Image *t, struct susp_info *susp) { unsigned char *SP = malloc(7); if (SP == NULL) { return ISO_OUT_OF_MEM; } SP[0] = 'S'; SP[1] = 'P'; SP[2] = (char)7; SP[3] = (char)1; SP[4] = 0xbe; SP[5] = 0xef; SP[6] = 0; return susp_append(t, susp, SP); } /** * SUSP 1.12: [...] shall specify as an 8-bit number the Extension * Sequence Number of the extension specification utilized in the entries * immediately following this System Use Entry. The Extension Sequence * Numbers of multiple extension specifications on a volume shall correspond to * the order in which their "ER" System Use Entries are recorded [...] */ static int susp_add_ES(Ecma119Image *t, struct susp_info *susp, int to_ce, int seqno) { unsigned char *ES = malloc(5); if (ES == NULL) { return ISO_OUT_OF_MEM; } ES[0] = 'E'; ES[1] = 'S'; ES[2] = (unsigned char) 5; ES[3] = (unsigned char) 1; ES[4] = (unsigned char) seqno; if (to_ce) { return susp_append_ce(t, susp, ES); } else { return susp_append(t, susp, ES); } } /** * A field beginning by 0 causes rrip_write_ce_fields() to pad up to the * next block. */ static int pseudo_susp_add_PAD(Ecma119Image *t, struct susp_info *susp) { unsigned char *pad; int ret; pad = malloc(1); if (pad == NULL) return ISO_OUT_OF_MEM; pad[0] = 0; ret = susp_append_ce(t, susp, pad); if (ret < 0) return ret; return ISO_SUCCESS; } /** * see doc/zisofs_format.txt : "ZF System Use Entry Format" */ static int zisofs_add_ZF(Ecma119Image *t, struct susp_info *susp, int to_ce, int header_size_div4, int block_size_log2, uint32_t uncompressed_size, int flag) { unsigned char *ZF = malloc(16); if (ZF == NULL) { return ISO_OUT_OF_MEM; } ZF[0] = 'Z'; ZF[1] = 'F'; ZF[2] = (unsigned char) 16; ZF[3] = (unsigned char) 1; ZF[4] = (unsigned char) 'p'; ZF[5] = (unsigned char) 'z'; ZF[6] = (unsigned char) header_size_div4; ZF[7] = (unsigned char) block_size_log2; iso_bb(&ZF[8], uncompressed_size, 4); if (to_ce) { return susp_append_ce(t, susp, ZF); } else { return susp_append(t, susp, ZF); } } /* @param flag bit0= Do not add data but only count sua_free and ce_len bit1= account for crossing block boundaries (implied by bit0 == 0) */ static int add_zf_field(Ecma119Image *t, Ecma119Node *n, struct susp_info *info, size_t *sua_free, size_t *ce_len, size_t base_ce, int flag) { int ret, will_copy = 1, stream_type = 0, do_zf = 0; int header_size_div4 = 0, block_size_log2 = 0; uint32_t uncompressed_size = 0; IsoStream *stream = NULL, *input_stream, *last_stream, *first_stream; IsoStream *first_filter = NULL; IsoFile *file; void *xipt; struct zisofs_zf_info *zf; /* Intimate friendship with this function in filters/zisofs.c */ int ziso_is_zisofs_stream(IsoStream *stream, int *stream_type, int *header_size_div4, int *block_size_log2, uint32_t *uncompressed_size, int flag); if (!(flag & 1)) flag |= 2; if (iso_node_get_type(n->node) != LIBISO_FILE) return 2; file = (IsoFile *) n->node; /* Inspect: last_stream < ... < first_filter < first_stream */ /* The content is in zisofs format if: It gets copied and the last stream is a ziso stream, or it had a ZF entry and is unfiltered or it has a zf xinfo record (because its last stream delivered a zisofs file header when inquired) or it stays uncopied and the first filter is an osiz stream, or it had a ZF entry or it has a zf xinfo record (because its first stream delivered a zisofs file header when inquired) */ if (t->opts->appendable && file->from_old_session) will_copy = 0; first_filter = first_stream = last_stream = iso_file_get_stream(file); while (1) { input_stream = iso_stream_get_input_stream(first_stream, 0); if (input_stream == NULL) break; first_filter = first_stream; first_stream = input_stream; } if (will_copy) { stream = last_stream; } else { /* (the eventual osiz filter on the image stream) */ stream = first_filter; } /* Determine stream type : 1=ziso , -1=osiz , 0=other */ ret = ziso_is_zisofs_stream(stream, &stream_type, &header_size_div4, &block_size_log2, &uncompressed_size, 0); if (ret < 0) return ret; if (stream_type == 1 && will_copy) { do_zf = 1; } else if (stream_type == -1 && !will_copy) { do_zf = 1; } else if(first_stream == last_stream || !will_copy) { /* Try whether the image side stream remembers a ZF field */ ret = iso_stream_get_src_zf(first_stream, &header_size_div4, &block_size_log2, &uncompressed_size, 0); if (ret == 1 && header_size_div4 > 0) do_zf = 1; } if (!do_zf) { /* Look for an xinfo mark of a zisofs header */ ret = iso_node_get_xinfo((IsoNode *) file, zisofs_zf_xinfo_func, &xipt); if (ret == 1) { zf = xipt; header_size_div4 = zf->header_size_div4; block_size_log2 = zf->block_size_log2; uncompressed_size = zf->uncompressed_size; if (header_size_div4 > 0) do_zf = 1; } } if (!do_zf) return 2; /* Account for field size */ if (*sua_free < 16 || *ce_len > 0) { susp_calc_add_to_ce(ce_len, base_ce, 16, flag & 2); } else { *sua_free -= 16; } if (flag & 1) return 1; /* write ZF field */ ret = zisofs_add_ZF(t, info, (*ce_len > 0), header_size_div4, block_size_log2, uncompressed_size, 0); if (ret < 0) return ret; return 1; } /* API */ int aaip_xinfo_func(void *data, int flag) { if (flag & 1) { free(data); } return 1; } /* API */ int aaip_xinfo_cloner(void *old_data, void **new_data, int flag) { size_t aa_size; *new_data = NULL; if (old_data == NULL) return 0; aa_size = aaip_count_bytes((unsigned char *) old_data, 0); if (aa_size <= 0) return ISO_AAIP_BAD_AASTRING; *new_data = calloc(1, aa_size); if (*new_data == NULL) return ISO_OUT_OF_MEM; memcpy(*new_data, old_data, aa_size); return (int) aa_size; } /** * Compute SUA length and eventual Continuation Area length of field NM and * eventually fields SL and AL. Because CA usage makes necessary the use of * a CE entry of 28 bytes in SUA, this computation fails if not the 28 bytes * are taken into account at start. In this case the caller should retry with * bit0 set. * If the resulting *ce added to base_ce is in a different block than base_ce, * then computation with bit0 fails and the caller should finally try bit1. * * @param flag bit0= assume CA usage (else return 0 on SUA overflow) * bit1= let CA start at block start (else return 0 if * *ce crosses a block boundary) * @return 1= ok, computation of *su_size and *ce is valid * 0= not ok, CA usage is necessary but bit0 was not set * or *ce crosses boundary and bit1 was not set * (*su_size and *ce stay unaltered in this case) * <0= error: * -1= not enough SUA space for 28 bytes of CE entry * -2= out of memory */ static int susp_calc_nm_sl_al(Ecma119Image *t, Ecma119Node *n, size_t space, size_t *su_size, size_t *ce, size_t base_ce, int flag) { char *name; size_t namelen, su_mem, ce_mem; void *xipt; size_t num_aapt = 0, sua_free = 0; int ret; uint8_t *aapt; #ifdef Libisofs_ce_calc_debug_extrA if (n->node->name != NULL) fprintf(stderr, "libburn_DEBUG: susp_calc_nm_sl_al : %.f %s \n", (double) base_ce, n->node->name); #endif /* Libisofs_ce_calc_debug_extrA */ su_mem = *su_size; ce_mem = *ce; if (*ce > 0 && !(flag & 1)) goto unannounced_ca; if (flag & 2) { flag |= 1; if (base_ce % BLOCK_SIZE) { #ifdef Libisofs_ce_calc_debuG fprintf(stderr, "\nlibburn_DEBUG: Accounting for %d bytes CE padding : %s\n\n", (int) (BLOCK_SIZE - (base_ce % BLOCK_SIZE)), n->node->name); #endif /* Libisofs_ce_calc_debuG */ *ce += BLOCK_SIZE - (base_ce % BLOCK_SIZE); } } namelen = 0; name = get_rr_fname(t, n->node->name); if (name != NULL) { namelen = strlen(name); free(name); } if (flag & 1) { /* Account for 28 bytes of CE field */ if (*su_size + 28 > space) return -1; *su_size += 28; } /* NM entry */ if (*su_size + 5 + namelen <= space) { /* ok, it fits in System Use Area */ *su_size += 5 + namelen; } else { /* the NM will be divided in a CA */ if (!(flag & 1)) goto unannounced_ca; namelen = namelen - (space - *su_size - 5); /* >>> SUPER_LONG_RR: Need to handle CA part lengths > 250 (This cannot happen with name lengths <= 256, as a part of the name will always fit into the directory entry.) */; susp_calc_add_to_ce(ce, base_ce, 5 + namelen, flag & 2); *su_size = space; } if (n->type == ECMA119_SYMLINK) { /* * for symlinks, we also need to write the SL */ char *dest, *cur, *prev; size_t sl_len = 5; int cew = (*ce != 0); /* are we writing to CA ? */ dest = get_rr_fname(t, ((IsoSymlink*)n->node)->dest); if (dest == NULL) return -2; prev = dest; cur = strchr(prev, '/'); while (1) { size_t clen; if (cur) { clen = cur - prev; } else { /* last component */ clen = strlen(prev); } if (clen == 1 && prev[0] == '.') { clen = 0; } else if (clen == 2 && prev[0] == '.' && prev[1] == '.') { clen = 0; } /* flags and len for each component record (RRIP, 4.1.3.1) */ clen += 2; if (!cew) { /* we are still writing to the SUA */ if (*su_size + sl_len + clen > space) { /* * ok, we need a Continuation Area anyway * TODO this can be handled better, but for now SL * will be completelly moved into the CA */ if (!(flag & 1)) { free(dest); goto unannounced_ca; } cew = 1; } else { sl_len += clen; } } if (cew) { if (sl_len + clen > 255) { /* we need an additional SL entry */ if (clen > 250) { /* * case 1, component too large to fit in a * single SL entry. Thus, the component need * to be divided anyway. * Note than clen can be up to 255 + 2 = 257. * * First, we check how many bytes fit in current * SL field */ ssize_t fit = 255 - sl_len - 2; if ((ssize_t) (clen - 250) <= fit) { /* * the component can be divided between this * and another SL entry */ /* Will fill up old SL and write it */ susp_calc_add_to_ce(ce, base_ce, 255, flag & 2); sl_len = 5 + (clen - fit); /* Start new SL */ } else { /* * the component will need a 2rd SL entry in * any case, so we prefer to don't write * anything in this SL */ /* Will write non-full old SL */ susp_calc_add_to_ce(ce, base_ce, sl_len, flag & 2); /* Will write another full SL */ susp_calc_add_to_ce(ce, base_ce, 255, flag & 2); sl_len = 5 + (clen - 250) + 2; /* Start new SL */ } } else { /* case 2, create a new SL entry */ /* Will write non-full old SL */ susp_calc_add_to_ce(ce, base_ce, sl_len, flag & 2); sl_len = 5 + clen; /* Start new SL */ } } else { sl_len += clen; } } if (!cur || cur[1] == '\0') { /* cur[1] can be \0 if dest ends with '/' */ break; } prev = cur + 1; cur = strchr(prev, '/'); } free(dest); /* and finally write the pending SL field */ if (!cew) { /* the whole SL fits into the SUA */ *su_size += sl_len; } else { susp_calc_add_to_ce(ce, base_ce, sl_len, flag & 2); } } /* Find out whether ZF is to be added and account for its bytes */ sua_free = space - *su_size; add_zf_field(t, n, NULL, &sua_free, ce, base_ce, 1 | (flag & 2)); *su_size = space - sua_free; if (*ce > 0 && !(flag & 1)) goto unannounced_ca; /* obtain num_aapt from node */ xipt = NULL; num_aapt = 0; if (t->opts->aaip) { ret = iso_node_get_xinfo(n->node, aaip_xinfo_func, &xipt); if (ret == 1) { num_aapt = aaip_count_bytes((unsigned char *) xipt, 0); } } /* let the expert decide where to add num_aapt */ if (num_aapt > 0) { sua_free = space - *su_size; aapt = (uint8_t *) xipt; aaip_add_AL(t, NULL, &aapt, num_aapt, &sua_free, ce, base_ce, 1 | (flag & 2)); *su_size = space - sua_free; if (*ce > 0 && !(flag & 1)) goto unannounced_ca; } #ifdef Libisofs_ce_calc_debug_filetraP if (n->node->name != NULL) if (strcmp(n->node->name, "...insert.leaf.name.here...") == 0) fprintf(stderr, "libburn_DEBUG: filename breakpoint susp_calc_nm_sl_al\n"); #endif /* Libisofs_ce_calc_debug_filetraP */ if (*ce > 0 && !(flag & 2)) { if (base_ce / BLOCK_SIZE != (base_ce + *ce + ISO_CE_ENTRY_SIZE - 1) / BLOCK_SIZE) { #ifdef Libisofs_ce_calc_debuG fprintf(stderr, "\nlibburn_DEBUG: Crossed block boundary: %.f (%lu) -> %.f (%lu) : %s\n\n", (double) base_ce, (unsigned long) (base_ce / BLOCK_SIZE), (double) (base_ce + *ce - 1), (unsigned long) ((base_ce + *ce + ISO_CE_ENTRY_SIZE - 1) / BLOCK_SIZE), n->node->name); #endif /* Libisofs_ce_calc_debuG */ /* Crossed a block boundary */ *su_size = su_mem; *ce = ce_mem; return 0; } } return 1; unannounced_ca:; *su_size = su_mem; *ce = ce_mem; return 0; } /* @param flag bit0= Do not add data but only count sua_free and ce_len param info may be NULL in this case bit1= account for crossing block boundaries (implied by bit0 == 0) */ static int add_aa_string(Ecma119Image *t, Ecma119Node *n, struct susp_info *info, size_t *sua_free, size_t *ce_len, size_t base_ce, int flag) { int ret; uint8_t *aapt; void *xipt; size_t num_aapt= 0; if (!t->opts->aaip) return 1; ret = iso_node_get_xinfo(n->node, aaip_xinfo_func, &xipt); if (ret == 1) { num_aapt = aaip_count_bytes((unsigned char *) xipt, 0); if (num_aapt > 0) { if (flag & 1) { aapt = (unsigned char *) xipt; ret = aaip_add_AL(t, NULL, &aapt, num_aapt, sua_free, ce_len, base_ce, flag & (1 | 2)); } else { aapt = malloc(num_aapt); if (aapt == NULL) return ISO_OUT_OF_MEM; memcpy(aapt, xipt, num_aapt); ret = aaip_add_AL(t, info, &aapt, num_aapt, sua_free, ce_len, base_ce, 0); /* aapt is NULL now and the memory is owned by t */ } if (ret < 0) return ret; } } return 1; } /** * Compute the length needed for write all RR and SUSP entries for a given * node. * * @param type * 0 normal entry, 1 "." entry for that node (it is a dir), 2 ".." * for that node (i.e., it will refer to the parent) * @param used_up * Already occupied space in the directory record. * @param ce * Will be filled with the space needed in a CE * @param base_ce * Predicted fill of continuation area by previous nodes of same dir * @return * The size needed for the RR entries in the System Use Area */ size_t rrip_calc_len(Ecma119Image *t, Ecma119Node *n, int type, size_t used_up, size_t *ce, size_t base_ce) { size_t su_size, space; int ret; size_t aaip_sua_free= 0, aaip_len= 0; /* Directory record length must be even (ECMA-119, 9.1.13). Maximum is 254. */ space = 254 - used_up - (used_up % 2); if (type < 0 || type > 2 || space < ISO_ROCKRIDGE_IN_DIR_REC) { iso_msg_submit(t->image->id, ISO_ASSERT_FAILURE, 0, "Unknown node type %d or short RR space %d < %d in directory record", type, (int) space, ISO_ROCKRIDGE_IN_DIR_REC); return ISO_ASSERT_FAILURE; } *ce = 0; su_size = 0; /* If AAIP enabled and announced by ER : account for 5 bytes of ES */; if (t->opts->aaip && !t->opts->aaip_susp_1_10) su_size += 5; #ifdef Libisofs_with_rrip_rR /* obsolete RR field (once in RRIP-1.09) */ su_size += 5; #endif /* PX and TF, we are sure they always fit in SUA */ if (t->opts->rrip_1_10_px_ino || !t->opts->rrip_version_1_10) { su_size += 44 + 26; } else { su_size += 36 + 26; } if (n->type == ECMA119_DIR) { if (n->info.dir->real_parent != NULL) { /* it is a reallocated entry */ if (type == 2) { /* we need to add a PL entry */ su_size += 12; } else if (type == 0) { /* we need to add a RE entry */ su_size += 4; } } else if(ecma119_is_dedicated_reloc_dir(t, n) && (t->opts->rr_reloc_flags & 1)) { /* The dedicated relocation directory shall be marked by RE */ su_size += 4; } } else if (n->type == ECMA119_SPECIAL) { if (S_ISBLK(n->node->mode) || S_ISCHR(n->node->mode)) { /* block or char device, we need a PN entry */ su_size += 20; } } else if (n->type == ECMA119_PLACEHOLDER) { /* we need the CL entry */ su_size += 12; } if (type == 0) { /* Try without CE */ ret = susp_calc_nm_sl_al(t, n, space, &su_size, ce, base_ce, 0); if (ret == 0) /* Retry with CE but no block crossing */ ret = susp_calc_nm_sl_al(t, n, space, &su_size, ce, base_ce, 1); if (ret == 0) /* Retry with aligned CE and block hopping */ ret = susp_calc_nm_sl_al(t, n, space, &su_size, ce, base_ce, 1 | 2); if (ret == -2) return ISO_OUT_OF_MEM; } else { /* "." or ".." entry */ if (!t->opts->rrip_version_1_10) su_size += 5; /* NM field */ if (type == 1 && n->parent == NULL) { /* * "." for root directory * we need to write SP and ER entries. The first fits in SUA, * ER needs a Continuation Area, thus we also need a CE entry */ su_size += 7 + 28; /* SP + CE */ /* ER of RRIP */ if (t->opts->rrip_version_1_10) { *ce = 237; } else { *ce = 182; } if (t->opts->aaip && !t->opts->aaip_susp_1_10) { *ce += 160; /* ER of AAIP */ } /* Compute length of AAIP string of root node. Will write all AIIP to CA, which already starts at block boundary. So no need for three tries. */ aaip_sua_free= 0; ret = add_aa_string(t, n, NULL, &aaip_sua_free, &aaip_len, base_ce, 1 | 2); if (ret < 0) return ret; *ce += aaip_len; } } /* * The System Use field inside the directory record must be padded if * it is an odd number (ECMA-119, 9.1.13) */ su_size += (su_size % 2); return su_size; } /** * Free all info in a struct susp_info. */ static void susp_info_free(struct susp_info* susp) { size_t i; for (i = 0; i < susp->n_susp_fields; ++i) { free(susp->susp_fields[i]); } free(susp->susp_fields); for (i = 0; i < susp->n_ce_susp_fields; ++i) { free(susp->ce_susp_fields[i]); } free(susp->ce_susp_fields); } /** * Fill a struct susp_info with the RR/SUSP entries needed for a given * node. * * @param type * 0 normal entry, 1 "." entry for that node (it is a dir), 2 ".." * for that node (i.e., it will refer to the parent) * @param used_up * Already occupied space in the directory record. * @param info * Pointer to the struct susp_info where the entries will be stored. * If some entries need to go to a Continuation Area, they will be added * to the existing ce_susp_fields, and ce_len will be incremented * propertly. Please ensure ce_block is initialized propertly. * @return * 1 success, < 0 error */ int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type, size_t used_up, struct susp_info *info) { int ret; size_t i; Ecma119Node *node; char *name = NULL; char *dest = NULL; size_t aaip_er_len= 0; size_t rrip_er_len= 182; size_t su_size_pd, ce_len_pd; /* predicted sizes of SUA and CA */ int ce_is_predicted = 0; size_t aaip_sua_free= 0, aaip_len= 0, ce_mem; int space; if (t == NULL || n == NULL || info == NULL) { return ISO_NULL_POINTER; } /* Directory record length must be even (ECMA-119, 9.1.13). Maximum is 254. */ space = 254 - used_up - (used_up % 2); if (type < 0 || type > 2 || space < ISO_ROCKRIDGE_IN_DIR_REC) { iso_msg_submit(t->image->id, ISO_ASSERT_FAILURE, 0, "Unknown node type %d or short RR space %d < %d in directory record", type, space, ISO_ROCKRIDGE_IN_DIR_REC); return ISO_ASSERT_FAILURE; } /* Mark start index of node's continuation area for later update */ info->current_ce_start = info->n_ce_susp_fields; ce_mem = info->ce_len; #ifdef Libisofs_ce_calc_debug_filetraP if (n->node->name != NULL) if (strcmp(n->node->name, "...put.leafname.here...") == 0) fprintf(stderr, "libburn_DEBUG: filename breakpoint\n"); #endif /* Libisofs_ce_calc_debug_filetraP */ if (type == 2 && n->parent != NULL) { node = n->parent; } else { node = n; } /* * SP must be the first entry for the "." record of the root directory * (SUSP, 5.3) */ if (type == 1 && n->parent == NULL) { ret = susp_add_SP(t, info); if (ret < 0) { goto add_susp_cleanup; } } /* If AAIP enabled and announced by ER : Announce RRIP by ES */ if (t->opts->aaip && !t->opts->aaip_susp_1_10) { ret = susp_add_ES(t, info, 0, 0); if (ret < 0) goto add_susp_cleanup; } #ifdef Libisofs_with_rrip_rR ret = rrip_add_RR(t, node, info); if (ret < 0) { goto add_susp_cleanup; } #endif /* Libisofs_with_rrip_rR */ /* PX and TF, we are sure they always fit in SUA */ ret = rrip_add_PX(t, node, info); if (ret < 0) { goto add_susp_cleanup; } ret = rrip_add_TF(t, node, info); if (ret < 0) { goto add_susp_cleanup; } if (n->type == ECMA119_DIR) { if (n->info.dir->real_parent != NULL) { /* it is a reallocated entry */ if (type == 2) { /* * we need to add a PL entry * Note that we pass "n" as parameter, not "node" */ ret = rrip_add_PL(t, n, info); if (ret < 0) { goto add_susp_cleanup; } } else if (type == 0) { /* we need to add a RE entry */ ret = rrip_add_RE(t, node, info); if (ret < 0) { goto add_susp_cleanup; } } } else if(ecma119_is_dedicated_reloc_dir(t, n) && (t->opts->rr_reloc_flags & 1)) { /* The dedicated relocation directory shall be marked by RE */ ret = rrip_add_RE(t, node, info); if (ret < 0) goto add_susp_cleanup; } } else if (n->type == ECMA119_SPECIAL) { if (S_ISBLK(n->node->mode) || S_ISCHR(n->node->mode)) { /* block or char device, we need a PN entry */ ret = rrip_add_PN(t, node, info); if (ret < 0) { goto add_susp_cleanup; } } } else if (n->type == ECMA119_PLACEHOLDER) { /* we need the CL entry */ ret = rrip_add_CL(t, node, info); if (ret < 0) { goto add_susp_cleanup; } } if (info->suf_len + 28 > space) { iso_msg_submit(t->image->id, ISO_ASSERT_FAILURE, 0, "Directory Record overflow. name='%s' , suf_len=%d > space=%d - 28\n", node->iso_name, (int) info->suf_len, space); return ISO_ASSERT_FAILURE; } if (type == 0) { size_t sua_free; /* free space in the SUA */ int nm_type = 0; /* 0 whole entry in SUA, 1 part in CE */ size_t ce_len = 0; /* len of the CE */ size_t namelen; /* this two are only defined for symlinks */ uint8_t **comps= NULL; /* components of the SL field */ size_t n_comp = 0; /* number of components */ namelen = 0; name = get_rr_fname(t, n->node->name); if (name == NULL) name = strdup(""); if (name == NULL) { ret = ISO_OUT_OF_MEM; goto add_susp_cleanup; } namelen = strlen(name); sua_free = space - info->suf_len; /* Try whether NM, SL, AL will fit into SUA */ su_size_pd = info->suf_len; ce_len_pd = ce_len; ret = susp_calc_nm_sl_al(t, n, (size_t) space, &su_size_pd, &ce_len_pd, info->ce_len, 0); if (ret == 0) { /* Have to use CA. 28 bytes of CE are necessary */ ret = susp_calc_nm_sl_al(t, n, (size_t) space, &su_size_pd, &ce_len_pd, info->ce_len, 1); if (ret == 0) /* Retry with aligned CE and block hopping */ ret = susp_calc_nm_sl_al(t, n, (size_t) space, &su_size_pd, &ce_len_pd, info->ce_len, 1 | 2); sua_free -= 28; ce_is_predicted = 1; } if (ret == -2) { ret = ISO_OUT_OF_MEM; goto add_susp_cleanup; } /* NM entry */ if (5 + namelen <= sua_free) { /* ok, it fits in System Use Area */ sua_free -= (5 + namelen); nm_type = 0; } else { /* the NM will be divided in a CE */ nm_type = 1; namelen = namelen - (sua_free - 5); ce_len = 5 + namelen; sua_free = 0; } if (n->type == ECMA119_SYMLINK) { /* * for symlinks, we also need to write the SL */ char *cur, *prev; size_t sl_len = 5; int cew = (nm_type == 1); /* are we writing to CE? */ dest = get_rr_fname(t, ((IsoSymlink*)n->node)->dest); if (dest == NULL) dest = strdup(""); if (dest == NULL) { ret = ISO_OUT_OF_MEM; goto add_susp_cleanup; } prev = dest; cur = strchr(prev, '/'); while (1) { size_t clen; char cflag = 0; /* component flag (RRIP, 4.1.3.1) */ if (cur) { clen = cur - prev; } else { /* last component */ clen = strlen(prev); } if (clen == 0) { /* this refers to the roor directory, '/' */ cflag = 1 << 3; } if (clen == 1 && prev[0] == '.') { clen = 0; cflag = 1 << 1; } else if (clen == 2 && prev[0] == '.' && prev[1] == '.') { clen = 0; cflag = 1 << 2; } /* flags and len for each component record (RRIP, 4.1.3.1) */ clen += 2; if (!cew) { /* we are still writing to the SUA */ if (sl_len + clen > sua_free) { /* * ok, we need a Continuation Area anyway * TODO this can be handled better, but for now SL * will be completelly moved into the CA */ /* sua_free, ce_len, nm_type already account for CE */ cew = 1; } else { /* add the component */ ret = rrip_SL_append_comp(&n_comp, &comps, prev, clen - 2, cflag); if (ret < 0) { goto add_susp_cleanup; } sl_len += clen; } } if (cew) { if (sl_len + clen > 255) { /* we need an addition SL entry */ if (clen > 250) { /* * case 1, component too large to fit in a * single SL entry. Thus, the component need * to be divided anyway. * Note than clen can be up to 255 + 2 = 257. * * First, we check how many bytes fit in current * SL field */ ssize_t fit = 255 - sl_len - 2; if ((ssize_t) (clen - 250) <= fit) { /* * the component can be divided between this * and another SL entry */ ret = rrip_SL_append_comp(&n_comp, &comps, prev, fit, 0x01); if (ret < 0) { goto add_susp_cleanup; } /* * and another component, that will go in * other SL entry */ ret = rrip_SL_append_comp(&n_comp, &comps, prev + fit, clen - fit - 2, 0); if (ret < 0) { goto add_susp_cleanup; } ce_len += 255; /* this SL, full */ sl_len = 5 + (clen - fit); } else { /* * the component will need a 2rd SL entry in * any case, so we prefer to don't write * anything in this SL */ ret = rrip_SL_append_comp(&n_comp, &comps, prev, 248, 0x01); if (ret < 0) { goto add_susp_cleanup; } ret = rrip_SL_append_comp(&n_comp, &comps, prev + 248, strlen(prev + 248), 0x00); if (ret < 0) { goto add_susp_cleanup; } ce_len += sl_len + 255; sl_len = 5 + (clen - 250) + 2; } } else { /* case 2, create a new SL entry */ ret = rrip_SL_append_comp(&n_comp, &comps, prev, clen - 2, cflag); if (ret < 0) { goto add_susp_cleanup; } ce_len += sl_len; sl_len = 5 + clen; } } else { /* the component fit in the SL entry */ ret = rrip_SL_append_comp(&n_comp, &comps, prev, clen - 2, cflag); if (ret < 0) { goto add_susp_cleanup; } sl_len += clen; } } if (!cur || cur[1] == '\0') { /* cur[1] can be \0 if dest ends with '/' */ break; } prev = cur + 1; cur = strchr(prev, '/'); } if (cew) { ce_len += sl_len; } } /* * We we reach here: * - We know if NM fill in the SUA (nm_type == 0) * - If SL needs an to be written in CE (ce_len > 0) * - The components for SL entry (or entries) */ if (nm_type == 0) { /* the full NM fills in SUA */ ret = rrip_add_NM(t, info, name, strlen(name), 0, 0); if (ret < 0) { goto add_susp_cleanup; } } else { /* * Write the NM part that fits in SUA... Note that CE * entry and NM in the continuation area is added below */ namelen = space - info->suf_len - 28 * (!!ce_is_predicted) - 5; ret = rrip_add_NM(t, info, name, namelen, 1, 0); if (ret < 0) { goto add_susp_cleanup; } } if (ce_is_predicted) { if ((info->ce_len % BLOCK_SIZE) && (info->ce_len + ce_len_pd - 1 ) / BLOCK_SIZE != info->ce_len / BLOCK_SIZE) { /* Linux fs/isofs wants byte_offset + ce_len <= BLOCK_SIZE * Insert padding to shift CE offset to next block start */ #ifdef Libisofs_ce_calc_debuG fprintf(stderr, "\nlibburn_DEBUG: Inserting %d bytes of CE padding : %s\n\n", (int) (BLOCK_SIZE - (info->ce_len % BLOCK_SIZE)), n->node->name); #endif /* Libisofs_ce_calc_debuG */ ret = pseudo_susp_add_PAD(t, info); if (ret < 0) goto add_susp_cleanup; } /* Add the CE entry */ ret = susp_add_CE(t, ce_len_pd, info); if (ret < 0) { goto add_susp_cleanup; } } if (nm_type == 1) { /* * ..and the part that goes to continuation area. */ /* >>> SUPER_LONG_RR : Need a loop to handle CA lengths > 250 (This cannot happen with name lengths <= 256, as a part of the name will always fit into the directory entry.) */; ret = rrip_add_NM(t, info, name + namelen, strlen(name + namelen), 0, 1); if (ret < 0) { goto add_susp_cleanup; } } if (n->type == ECMA119_SYMLINK) { /* add the SL entry (or entries) */ ret = rrip_add_SL(t, info, comps, n_comp, (ce_len > 0)); /* free the components */ for (i = 0; i < n_comp; i++) { free(comps[i]); } free(comps); if (ret < 0) { goto add_susp_cleanup; } } /* Eventually write zisofs ZF field */ ret = add_zf_field(t, n, info, &sua_free, &ce_len, ce_mem, 0); if (ret < 0) goto add_susp_cleanup; /* Eventually obtain AAIP field string from node and write it to directory entry or CE area. */ ret = add_aa_string(t, n, info, &sua_free, &ce_len, ce_mem, 0); if (ret < 0) goto add_susp_cleanup; } else { /* "." or ".." entry */ /* write the NM entry */ if (t->opts->rrip_version_1_10) { /* RRIP-1.10: "NM" System Use Fields recorded for the ISO 9660 directory records with names (00) and (01), used to designate the current and parent directories, respectively, should be ignored. Instead, the receiving system should convert these names to the appropriate receiving system-dependent designations for the current and parent directories. */ /* mkisofs obviously writes no NM for '.' and '..' . Program isoinfo shows empty names with records as of RRIP-1.12 */ /* no op */; } else { /* RRIP-1.12: If the ISO 9660 Directory Record File Identifier is (00), then the CURRENT bit of the "NM" Flags field [...], if present, shall be set to ONE. If the ISO 9660 Directory Record File Identifier is (01), then the PARENT bit of the "NM" Flags field [...], if present, shall be set to ONE. [...] "BP 3 - Length (LEN_NM)" shall specify as an 8-bit number the length in bytes [...]. If bit position 1, 2, or 5 of the "NM" Flags is set to ONE, the value of this field shall be 5 and no Name Content shall be recorded. [The CURRENT bit has position 1. The PARENT bit has position 2.] */ ret = rrip_add_NM(t, info, NULL, 0, 1 << type, 0); if (ret < 0) goto add_susp_cleanup; } if (type == 1 && n->parent == NULL) { /* * "." for root directory * we need to write SP and ER entries. The first fits in SUA, * ER needs a Continuation Area, thus we also need a CE entry. * Note that SP entry was already added above */ if (t->opts->rrip_version_1_10) { rrip_er_len = 237; } else { rrip_er_len = 182; } if (t->opts->aaip && !t->opts->aaip_susp_1_10) { aaip_er_len = 160; } /* Compute length of AAIP string of root node */ aaip_sua_free= 0; ret = add_aa_string(t, n, NULL, &aaip_sua_free, &aaip_len, ce_mem, 1 | 2); if (ret < 0) goto add_susp_cleanup; /* Allocate the necessary CE space */ ret = susp_add_CE(t, rrip_er_len + aaip_er_len + aaip_len, info); if (ret < 0) { goto add_susp_cleanup; } ret = rrip_add_ER(t, info); if (ret < 0) { goto add_susp_cleanup; } if (t->opts->aaip && !t->opts->aaip_susp_1_10) { ret = aaip_add_ER(t, info, 0); if (ret < 0) { goto add_susp_cleanup; } } /* Write AAIP string of root node */ aaip_sua_free= aaip_len= 0; ret = add_aa_string(t, n, info, &aaip_sua_free, &aaip_len, ce_mem, 0); if (ret < 0) goto add_susp_cleanup; } } /* * The System Use field inside the directory record must be padded if * it is an odd number (ECMA-119, 9.1.13) */ info->suf_len += (info->suf_len % 2); free(name); free(dest); return ISO_SUCCESS; add_susp_cleanup: ; if (name != NULL) free(name); if (dest != NULL) free(dest); susp_info_free(info); return ret; } /* Update the sizes of CE fields at end of info->susp_fields and in single node range of info->ce_susp_fields. */ static int susp_update_CE_sizes(Ecma119Image *t, struct susp_info *info, int flag) { size_t i, curr_pos; uint8_t *curr_ce; uint32_t size; if (info->n_susp_fields == 0 || info->n_ce_susp_fields - info->current_ce_start == 0) return ISO_SUCCESS; for (i = 0; i < info->n_susp_fields; i++) if (info->susp_fields[i][0] == 'C') if(info->susp_fields[i][1] == 'E') break; if (i >= info->n_susp_fields) { iso_msg_submit(t->image->id, ISO_ASSERT_FAILURE, 0, "System Use Area field contains no CE, but there are fields in Continuation Area"); return ISO_ASSERT_FAILURE; } curr_ce = info->susp_fields[i]; curr_pos = 0; for (i = info->current_ce_start; i < info->n_ce_susp_fields; i++) { if (info->ce_susp_fields[i][0] == 0) { curr_pos = 0; /* pseudo SUSP PAD */ continue; } if (info->ce_susp_fields[i][0] == 'C' && info->ce_susp_fields[i][1] == 'E') { size = (curr_pos + info->ce_susp_fields[i][2]) % BLOCK_SIZE; if (size == 0) size = BLOCK_SIZE; iso_bb(curr_ce + 20, size, 4); curr_ce = info->ce_susp_fields[i]; } curr_pos = (curr_pos + info->ce_susp_fields[i][2]) % 2048; } if (curr_pos > 0) { size = curr_pos % BLOCK_SIZE; iso_bb(curr_ce + 20, size, 4); } return ISO_SUCCESS; } /** * Write the given SUSP fields into buf. Note that Continuation Area * fields are not written. * If info does not contain any SUSP entry this function just return. * After written, the info susp_fields array will be freed, and the counters * updated propertly. */ void rrip_write_susp_fields(Ecma119Image *t, struct susp_info *info, uint8_t *buf) { size_t i; size_t pos = 0; int ret; if (info->n_susp_fields == 0) { return; } ret = susp_update_CE_sizes(t, info, 0); if (ret < 0) return; for (i = 0; i < info->n_susp_fields; i++) { memcpy(buf + pos, info->susp_fields[i], info->susp_fields[i][2]); pos += info->susp_fields[i][2]; } /* free susp_fields */ for (i = 0; i < info->n_susp_fields; ++i) { free(info->susp_fields[i]); } free(info->susp_fields); info->susp_fields = NULL; info->n_susp_fields = 0; info->suf_len = 0; } /** * Write the Continuation Area entries for the given struct susp_info, using * the iso_write() function. * After written, the ce_susp_fields array will be freed. */ int rrip_write_ce_fields(Ecma119Image *t, struct susp_info *info) { size_t i; uint8_t *padding = NULL; int ret= ISO_SUCCESS; uint64_t written = 0, pad_size; if (info->n_ce_susp_fields == 0) { goto ex; } LIBISO_ALLOC_MEM(padding, uint8_t, BLOCK_SIZE); for (i = 0; i < info->n_ce_susp_fields; i++) { if (info->ce_susp_fields[i][0] == 0) { /* Pseudo field: pad up to next block boundary */ pad_size = BLOCK_SIZE - (written % BLOCK_SIZE); if (pad_size == BLOCK_SIZE) continue; memset(padding, 0, pad_size); ret = iso_write(t, padding, pad_size); if (ret < 0) goto write_ce_field_cleanup; written += pad_size; continue; } ret = iso_write(t, info->ce_susp_fields[i], info->ce_susp_fields[i][2]); if (ret < 0) { goto write_ce_field_cleanup; } written += info->ce_susp_fields[i][2]; } /* pad continuation area until block size */ i = BLOCK_SIZE - (info->ce_len % BLOCK_SIZE); if (i > 0 && i < BLOCK_SIZE) { memset(padding, 0, i); ret = iso_write(t, padding, i); if (ret < 0) goto write_ce_field_cleanup; written += i; } write_ce_field_cleanup: ; /* free ce_susp_fields */ for (i = 0; i < info->n_ce_susp_fields; ++i) { free(info->ce_susp_fields[i]); } free(info->ce_susp_fields); info->ce_susp_fields = NULL; info->n_ce_susp_fields = 0; info->alloc_ce_susp_fields = 0; info->ce_len = 0; ex:; LIBISO_FREE_MEM(padding); return ret; } libisofs-1.4.2/libisofs/libiso_msgs.h0000644000175700017510000007140012557153247014573 00000000000000 /* libiso_msgs (generated from libdax_msgs : Fri Feb 22 19:42:52 CET 2008) Message handling facility of libisofs. Copyright (C) 2006-2008 Thomas Schmitt , provided under GPL version 2 or later */ /* *Never* set this macro outside libiso_msgs.c ! The entrails of the message handling facility are not to be seen by the other library components or the applications. */ #ifdef LIBISO_MSGS_H_INTERNAL #ifndef LIBISO_MSGS_SINGLE_THREADED #include #endif struct libiso_msgs_item { double timestamp; pid_t process_id; int origin; int severity; int priority; /* Apply for your developer's error code range at libburn-hackers@pykix.org Report introduced codes in the list below. */ int error_code; char *msg_text; int os_errno; struct libiso_msgs_item *prev,*next; }; struct libiso_msgs { int refcount; struct libiso_msgs_item *oldest; struct libiso_msgs_item *youngest; int count; int queue_severity; int print_severity; char print_id[81]; #ifndef LIBISO_MSGS_SINGLE_THREADED pthread_mutex_t lock_mutex; #endif }; #endif /* LIBISO_MSGS_H_INTERNAL */ #ifndef LIBISO_MSGS_H_INCLUDED #define LIBISO_MSGS_H_INCLUDED 1 #ifndef LIBISO_MSGS_H_INTERNAL /* Architectural aspects */ /* libdax_msgs is designed to serve in libraries which want to offer their applications a way to control the output of library messages. It shall be incorporated by an owner, i.e. a software entity which encloses the code of the .c file. Owner of libdax_msgs is libburn. A fully compatible variant named libiso_msgs is owned by libisofs and can get generated by a script of the libburn project: libburn/libiso_msgs_to_xyz_msgs.sh . Reason: One cannot link two owners of the same variant together because both would offer the same functions to the linker. For that situation one has to create a compatible variant as it is done for libisofs. Compatible variants may get plugged together by call combinations like burn_set_messenger(iso_get_messenger()); A new variant would demand a _set_messenger() function if it has to work with libisofs. If only libburn is planned as link partner then a simple _get_messenger() does suffice. Take care to shutdown libburn before its provider of the *_msgs object gets shut down. */ /* Public Opaque Handles */ /** A pointer to this is a opaque handle to a message handling facility */ struct libiso_msgs; /** A pointer to this is a opaque handle to a single message item */ struct libiso_msgs_item; #endif /* ! LIBISO_MSGS_H_INTERNAL */ /* Public Macros */ /* Registered Severities */ /* It is well advisable to let applications select severities via strings and forwarded functions libiso_msgs__text_to_sev(), libiso_msgs__sev_to_text(). These macros are for use by the owner of libiso_msgs. */ /** Use this to get messages of any severity. Do not use for submitting. */ #define LIBISO_MSGS_SEV_ALL 0x00000000 /** Messages of this severity shall transport plain disk file paths whenever an event of severity SORRY or above is related with an individual disk file. No message text shall be added to the file path. The ERRFILE message shall be issued before the human readable message which carries the true event severity. That message should contain the file path so it can be found by strstr(message, path)!=NULL. The error code shall be the same as with the human readable message. */ #define LIBISO_MSGS_SEV_ERRFILE 0x08000000 /** Debugging messages not to be visible to normal users by default */ #define LIBISO_MSGS_SEV_DEBUG 0x10000000 /** Update of a progress report about long running actions */ #define LIBISO_MSGS_SEV_UPDATE 0x20000000 /** Not so usual events which were gracefully handled */ #define LIBISO_MSGS_SEV_NOTE 0x30000000 /** Possibilities to achieve a better result */ #define LIBISO_MSGS_SEV_HINT 0x40000000 /** Warnings about problems which could not be handled optimally */ #define LIBISO_MSGS_SEV_WARNING 0x50000000 /** Non-fatal error messages indicating that parts of an action failed but processing may go on if one accepts deviations from the desired result. SORRY may also be the severity for incidents which are severe enough for FAILURE but happen within already started irrevocable actions, like ISO image generation. A precondition for such a severity ease is that the action can be continued after the incident. See below MISHAP for what xorriso would need instead of this kind of SORRY and generates for itself in case of libisofs image generation. E.g.: A pattern yields no result. A speed setting cannot be made. A libisofs input file is inaccessible during image generation. After SORRY a function should try to go on if that makes any sense and if no threshold prescribes abort on SORRY. The function should nevertheless indicate some failure in its return value. It should - but it does not have to. */ #define LIBISO_MSGS_SEV_SORRY 0x60000000 /** A FAILURE (see below) which can be tolerated during long lasting operations just because they cannot simply be stopped or revoked. xorriso converts libisofs SORRY messages issued during image generation into MISHAP messages in order to allow its evaluators to distinguish image generation problems from minor image composition problems. E.g.: A libisofs input file is inaccessible during image generation. After a MISHAP a function should behave like after SORRY. */ #define LIBISO_MSGS_SEV_MISHAP 0x64000000 /** Non-fatal error indicating that an important part of an action failed and that only a new setup of preconditions will give hope for sufficient success. E.g.: No media is inserted in the output drive. No write mode can be found for inserted media. A libisofs input file is inaccessible during grafting. After FAILURE a function should end with a return value indicating failure. It is at the discretion of the function whether it ends immediately in any case or whether it tries to go on if the eventual threshold allows. */ #define LIBISO_MSGS_SEV_FAILURE 0x68000000 /** An error message which puts the whole operation of the program in question E.g.: Not enough memory for essential temporary objects. Irregular errors from resources. Programming errors (soft assert). After FATAL a function should end very soon with a return value indicating severe failure. */ #define LIBISO_MSGS_SEV_FATAL 0x70000000 /** A message from an abort handler which will finally finish libburn */ #define LIBISO_MSGS_SEV_ABORT 0x71000000 /** A severity to exclude or discard any possible message. Do not use this severity for submitting. */ #define LIBISO_MSGS_SEV_NEVER 0x7fffffff /* Registered Priorities */ /* Priorities are to be selected by the programmers and not by the user. */ #define LIBISO_MSGS_PRIO_ZERO 0x00000000 #define LIBISO_MSGS_PRIO_LOW 0x10000000 #define LIBISO_MSGS_PRIO_MEDIUM 0x20000000 #define LIBISO_MSGS_PRIO_HIGH 0x30000000 #define LIBISO_MSGS_PRIO_TOP 0x7ffffffe /* Do not use this priority for submitting */ #define LIBISO_MSGS_PRIO_NEVER 0x7fffffff /* Origin numbers of libburn drives may range from 0 to 1048575 */ #define LIBISO_MSGS_ORIGIN_DRIVE_BASE 0 #define LIBISO_MSGS_ORIGIN_DRIVE_TOP 0xfffff /* Origin numbers of libisofs images may range from 1048575 to 2097152 */ #define LIBISO_MSGS_ORIGIN_IMAGE_BASE 0x100000 #define LIBISO_MSGS_ORIGIN_IMAGE_TOP 0x1fffff /* Public Functions */ /* Calls initiated from inside the direct owner (e.g. from libburn) */ /** Create new empty message handling facility with queue and issue a first official reference to it. @param flag Bitfield for control purposes (unused yet, submit 0) @return >0 success, <=0 failure */ int libiso_msgs_new(struct libiso_msgs **m, int flag); /** Destroy a message handling facility and all its eventual messages. The submitted pointer gets set to NULL. Actually only the last destroy call of all offical references to the object will really dispose it. All others just decrement the reference counter. Call this function only with official reference pointers obtained by libiso_msgs_new() or libiso_msgs_refer(), and only once per such pointer. @param flag Bitfield for control purposes (unused yet, submit 0) @return 1 for success, 0 for pointer to NULL, -1 for fatal error */ int libiso_msgs_destroy(struct libiso_msgs **m, int flag); /** Create an official reference to an existing libiso_msgs object. The references keep the object alive at least until it is released by a matching number of destroy calls. So each reference MUST be revoked by exactly one call to libiso_msgs_destroy(). @param pt The pointer to be set and registered @param m A pointer to the existing object @param flag Bitfield for control purposes (unused yet, submit 0) @return 1 for success, 0 for failure */ int libiso_msgs_refer(struct libiso_msgs **pt, struct libiso_msgs *o, int flag); /** Submit a message to a message handling facility. @param origin program specific identification number of the originator of a message. E.g. drive number. Programs should have an own range of origin numbers. See above LIBISO_MSGS_ORIGIN_*_BASE Use -1 if no number is known. @param error_code Unique error code. Use only registered codes. See below. The same unique error_code may be issued at different occasions but those should be equivalent out of the view of a libiso_msgs application. (E.g. "cannot open ATA drive" versus "cannot open SCSI drive" would be equivalent.) @param severity The LIBISO_MSGS_SEV_* of the event. @param priority The LIBISO_MSGS_PRIO_* number of the event. @param msg_text Printable and human readable message text. @param os_errno Eventual error code from operating system (0 if none) @param flag Bitfield for control purposes (unused yet, submit 0) @return 1 on success, 0 on rejection, <0 for severe errors */ int libiso_msgs_submit(struct libiso_msgs *m, int origin, int error_code, int severity, int priority, char *msg_text, int os_errno, int flag); /* Calls from applications (to be forwarded by direct owner) */ /** Convert a registered severity number into a severity name @param flag Bitfield for control purposes: bit0= list all severity names in a blank separated string @return >0 success, <=0 failure */ int libiso_msgs__sev_to_text(int severity, char **severity_name, int flag); /** Convert a severity name into a severity number, @param flag Bitfield for control purposes (unused yet, submit 0) @return >0 success, <=0 failure */ int libiso_msgs__text_to_sev(char *severity_name, int *severity, int flag); /** Set minimum severity for messages to be queued (default LIBISO_MSGS_SEV_ALL) and for messages to be printed directly to stderr (default LIBISO_MSGS_SEV_NEVER). @param print_id A text of at most 80 characters to be printed before any eventually printed message (default is "libiso: "). @param flag Bitfield for control purposes (unused yet, submit 0) @return always 1 for now */ int libiso_msgs_set_severities(struct libiso_msgs *m, int queue_severity, int print_severity, char *print_id, int flag); /** Obtain a message item that has at least the given severity and priority. Usually all older messages of lower severity are discarded then. If no item of sufficient severity was found, all others are discarded from the queue. @param flag Bitfield for control purposes (unused yet, submit 0) @return 1 if a matching item was found, 0 if not, <0 for severe errors */ int libiso_msgs_obtain(struct libiso_msgs *m, struct libiso_msgs_item **item, int severity, int priority, int flag); /** Destroy a message item obtained by libiso_msgs_obtain(). The submitted pointer gets set to NULL. Caution: Copy eventually obtained msg_text before destroying the item, if you want to use it further. @param flag Bitfield for control purposes (unused yet, submit 0) @return 1 for success, 0 for pointer to NULL, <0 for severe errors */ int libiso_msgs_destroy_item(struct libiso_msgs *m, struct libiso_msgs_item **item, int flag); /** Obtain from a message item the three application oriented components as submitted with the originating call of libiso_msgs_submit(). Caution: msg_text becomes a pointer into item, not a copy. @param flag Bitfield for control purposes (unused yet, submit 0) @return 1 on success, 0 on invalid item, <0 for servere errors */ int libiso_msgs_item_get_msg(struct libiso_msgs_item *item, int *error_code, char **msg_text, int *os_errno, int flag); /** Obtain from a message item the submitter identification submitted with the originating call of libiso_msgs_submit(). @param flag Bitfield for control purposes (unused yet, submit 0) @return 1 on success, 0 on invalid item, <0 for servere errors */ int libiso_msgs_item_get_origin(struct libiso_msgs_item *item, double *timestamp, pid_t *process_id, int *origin, int flag); /** Obtain from a message item severity and priority as submitted with the originating call of libiso_msgs_submit(). @param flag Bitfield for control purposes (unused yet, submit 0) @return 1 on success, 0 on invalid item, <0 for servere errors */ int libiso_msgs_item_get_rank(struct libiso_msgs_item *item, int *severity, int *priority, int flag); #ifdef LIDBAX_MSGS_________________ /* Registered Error Codes */ Format: error_code (LIBISO_MSGS_SEV_*,LIBISO_MSGS_PRIO_*) = explanation If no severity or priority are fixely associated, use "(,)". ------------------------------------------------------------------------------ Range "libiso_msgs" : 0x00000000 to 0x0000ffff 0x00000000 (ALL,ZERO) = Initial setting in new libiso_msgs_item 0x00000001 (DEBUG,ZERO) = Test error message 0x00000002 (DEBUG,ZERO) = Debugging message 0x00000003 (FATAL,HIGH) = Out of virtual memory ------------------------------------------------------------------------------ Range "elmom" : 0x00010000 to 0x0001ffff ------------------------------------------------------------------------------ Range "scdbackup" : 0x00020000 to 0x0002ffff Acessing and defending drives: 0x00020001 (SORRY,LOW) = Cannot open busy device 0x00020002 (SORRY,HIGH) = Encountered error when closing drive 0x00020003 (SORRY,HIGH) = Could not grab drive 0x00020004 (NOTE,HIGH) = Opened O_EXCL scsi sibling 0x00020005 (SORRY,HIGH) = Failed to open device 0x00020006 (FATAL,HIGH) = Too many scsi siblings 0x00020007 (NOTE,HIGH) = Closed O_EXCL scsi siblings 0x00020008 (SORRY,HIGH) = Device busy. Failed to fcntl-lock 0x00020009 (SORRY,HIGH) = Neither stdio-path nor its directory exist General library operations: 0x00020101 (WARNING,HIGH) = Cannot find given worker item 0x00020102 (SORRY,HIGH) = A drive operation is still going on 0x00020103 (WARNING,HIGH) = After scan a drive operation is still going on 0x00020104 (SORRY,HIGH) = NULL pointer caught 0x00020105 (SORRY,HIGH) = Drive is already released 0x00020106 (SORRY,HIGH) = Drive is busy on attempt to close 0x00020107 (WARNING,HIGH) = A drive is still busy on shutdown of library 0x00020108 (SORRY,HIGH) = Drive is not grabbed on disc status inquiry 0x00020108 (FATAL,HIGH) = Could not allocate new drive object 0x00020109 (FATAL,HIGH) = Library not running 0x0002010a (FATAL,HIGH) = Unsuitable track mode 0x0002010b (FATAL,HIGH) = Burn run failed 0x0002010c (FATAL,HIGH) = Failed to transfer command to drive 0x0002010d (DEBUG,HIGH) = Could not inquire TOC 0x0002010e (FATAL,HIGH) = Attempt to read ATIP from ungrabbed drive 0x0002010f (DEBUG,HIGH) = SCSI error condition on command 0x00020110 (FATAL,HIGH) = Persistent drive address too long 0x00020111 (FATAL,HIGH) = Could not allocate new auxiliary object 0x00020112 (SORRY,HIGH) = Bad combination of write_type and block_type 0x00020113 (FATAL,HIGH) = Drive capabilities not inquired yet 0x00020114 (SORRY,HIGH) = Attempt to set ISRC with bad data 0x00020115 (SORRY,HIGH) = Attempt to set track mode to unusable value 0x00020116 (FATAL,HIGH) = Track mode has unusable value 0x00020117 (FATAL,HIGH) = toc_entry of drive is already in use 0x00020118 (DEBUG,HIGH) = Closing track 0x00020119 (DEBUG,HIGH) = Closing session 0x0002011a (NOTE,HIGH) = Padding up track to minimum size 0x0002011b (FATAL,HIGH) = Attempt to read track info from ungrabbed drive 0x0002011c (FATAL,HIGH) = Attempt to read track info from busy drive 0x0002011d (FATAL,HIGH) = SCSI error on write 0x0002011e (SORRY,HIGH) = Unsuitable media detected 0x0002011f (SORRY,HIGH) = Burning is restricted to a single track 0x00020120 (NOTE,HIGH) = FORMAT UNIT ignored 0x00020121 (FATAL,HIGH) = Write preparation setup failed 0x00020122 (FATAL,HIGH) = SCSI error on format_unit 0x00020123 (SORRY,HIGH) = DVD Media are unsuitable for desired track type 0x00020124 (SORRY,HIGH) = SCSI error on set_streaming 0x00020125 (SORRY,HIGH) = Write start address not supported 0x00020126 (SORRY,HIGH) = Write start address not properly aligned 0x00020127 (NOTE,HIGH) = Write start address is ... 0x00020128 (FATAL,HIGH) = Unsupported inquiry_type with mmc_get_performance 0x00020129 (SORRY,HIGH) = Will not format media type 0x0002012a (FATAL,HIGH) = Cannot inquire write mode capabilities 0x0002012b (FATAL,HIGH) = Drive offers no suitable write mode with this job 0x0002012c (SORRY,HIGH) = Too many logical tracks recorded 0x0002012d (FATAL,HIGH) = Exceeding range of permissible write addresses 0x0002012e (NOTE,HIGH) = Activated track default size 0x0002012f (SORRY,HIGH) = SAO is restricted to single fixed size session 0x00020130 (SORRY,HIGH) = Drive and media state unsuitable for blanking 0x00020131 (SORRY,HIGH) = No suitable formatting type offered by drive 0x00020132 (SORRY,HIGH) = Selected format is not suitable for libburn 0x00020133 (SORRY,HIGH) = Cannot mix data and audio in SAO mode 0x00020134 (NOTE,HIGH) = Defaulted TAO to DAO 0x00020135 (SORRY,HIGH) = Cannot perform TAO, job unsuitable for DAO 0x00020136 (SORRY,HIGH) = DAO burning restricted to single fixed size track 0x00020137 (HINT,HIGH) = TAO would be possible 0x00020138 (FATAL,HIGH) = Cannot reserve track 0x00020139 (SORRY,HIGH) = Write job parameters are unsuitable 0x0002013a (FATAL,HIGH) = No suitable media detected 0x0002013b (DEBUG,HIGH) = SCSI command indicates host or driver error 0x0002013c (SORRY,HIGH) = Malformed capabilities page 2Ah received 0x0002013d (DEBUG,LOW) = Waiting for free buffer space takes long time 0x0002013e (SORRY,HIGH) = Timeout with waiting for free buffer. Now disabled 0x0002013f (DEBUG,LOW) = Reporting total time spent with waiting for buffer 0x00020140 (FATAL,HIGH) = Drive is busy on attempt to write random access 0x00020141 (SORRY,HIGH) = Write data count not properly aligned 0x00020142 (FATAL,HIGH) = Drive is not grabbed on random access write 0x00020143 (SORRY,HIGH) = Read start address not properly aligned 0x00020144 (SORRY,HIGH) = SCSI error on read 0x00020145 (FATAL,HIGH) = Drive is busy on attempt to read data 0x00020146 (FATAL,HIGH) = Drive is a virtual placeholder 0x00020147 (SORRY,HIGH) = Cannot address start byte 0x00020148 (SORRY,HIGH) = Cannot write desired amount of data 0x00020149 (SORRY,HIGH) = Unsuitable filetype for pseudo-drive 0x0002014a (SORRY,HIGH) = Cannot read desired amount of data 0x0002014b (SORRY,HIGH) = Drive is already registered and scanned 0x0002014c (FATAL,HIGH) = Emulated drive caught in SCSI function 0x0002014d (SORRY,HIGH) = Asynchromous SCSI error 0x0002014f (SORRY,HIGH) = Timeout with asynchromous SCSI command 0x00020150 (DEBUG,LOW) = Reporting asynchronous waiting time 0x00020151 (FATAL,HIGH) = Read attempt on write-only drive 0x00020152 (FATAL,HIGH) = Cannot start fifo thread 0x00020153 (SORRY,HIGH) = Read error on fifo input 0x00020154 (NOTE,HIGH) = Forwarded input error ends output 0x00020155 (SORRY,HIGH) = Desired fifo buffer too large 0x00020156 (SORRY,HIGH) = Desired fifo buffer too small 0x00020157 (FATAL,HIGH) = burn_source is not a fifo object 0x00020158 (DEBUG,LOW) = Reporting thread disposal precautions 0x00020159 (DEBUG,HIGH) = TOC Format 0 returns inconsistent data libiso_audioxtr: 0x00020200 (SORRY,HIGH) = Cannot open audio source file 0x00020201 (SORRY,HIGH) = Audio source file has unsuitable format 0x00020202 (SORRY,HIGH) = Failed to prepare reading of audio data ------------------------------------------------------------------------------ Range "vreixo" : 0x00030000 to 0x0003ffff 0x0003ffff (FAILURE,HIGH) = Operation canceled 0x0003fffe (FATAL,HIGH) = Unknown or unexpected fatal error 0x0003fffd (FAILURE,HIGH) = Unknown or unexpected error 0x0003fffc (FATAL,HIGH) = Internal programming error 0x0003fffb (FAILURE,HIGH) = NULL pointer where NULL not allowed 0x0003fffa (FATAL,HIGH) = Memory allocation error 0x0003fff9 (FATAL,HIGH) = Interrupted by a signal 0x0003fff8 (FAILURE,HIGH) = Invalid parameter value 0x0003fff7 (FATAL,HIGH) = Cannot create a needed thread 0x0003fff6 (FAILURE,HIGH) = Write error 0x0003fff5 (FAILURE,HIGH) = Buffer read error 0x0003ffc0 (FAILURE,HIGH) = Trying to add a node already added to another dir 0x0003ffbf (FAILURE,HIGH) = Node with same name already exist 0x0003ffbe (FAILURE,HIGH) = Trying to remove a node that was not added to dir 0x0003ffbd (FAILURE,HIGH) = A requested node does not exist 0x0003ffbc (FAILURE,HIGH) = Image already bootable 0x0003ffbb (FAILURE,HIGH) = Trying to use an invalid file as boot image 0x0003ff80 (FAILURE,HIGH) = Error on file operation 0x0003ff7f (FAILURE,HIGH) = Trying to open an already openned file 0x0003ff7e (FAILURE,HIGH) = Access to file is not allowed 0x0003ff7d (FAILURE,HIGH) = Incorrect path to file 0x0003ff7c (FAILURE,HIGH) = The file does not exist in the filesystem 0x0003ff7b (FAILURE,HIGH) = Trying to read or close a file not openned 0x0003ff7a (FAILURE,HIGH) = Directory used where no dir is expected 0x0003ff79 (FAILURE,HIGH) = File read error 0x0003ff78 (FAILURE,HIGH) = Not dir used where a dir is expected 0x0003ff77 (FAILURE,HIGH) = Not symlink used where a symlink is expected 0x0003ff76 (FAILURE,HIGH) = Cannot seek to specified location 0x0003ff75 (HINT,MEDIUM) = File not supported in ECMA-119 tree and ignored 0x0003ff74 (HINT,MEDIUM) = File bigger than supported by used standard 0x0003ff73 (MISHAP,HIGH) = File read error during image creation 0x0003ff72 (HINT,MEDIUM) = Cannot convert filename to requested charset 0x0003ff71 (SORRY,HIGH) = File cannot be added to the tree 0x0003ff70 (HINT,MEDIUM) = File path breaks specification constraints 0x0003ff00 (FAILURE,HIGH) = Charset conversion error 0x0003feff (FAILURE,HIGH) = Too much files to mangle 0x0003fec0 (FAILURE,HIGH) = Wrong or damaged Primary Volume Descriptor 0x0003febf (SORRY,HIGH) = Wrong or damaged RR entry 0x0003febe (SORRY,HIGH) = Unsupported RR feature 0x0003febd (FAILURE,HIGH) = Wrong or damaged ECMA-119 0x0003febc (FAILURE,HIGH) = Unsupported ECMA-119 feature 0x0003febb (SORRY,HIGH) = Wrong or damaged El-Torito catalog 0x0003feba (SORRY,HIGH) = Unsupported El-Torito feature 0x0003feb9 (SORRY,HIGH) = Cannot patch isolinux boot image 0x0003feb8 (SORRY,HIGH) = Unsupported SUSP feature 0x0003feb7 (WARNING,HIGH) = Error on a RR entry that can be ignored 0x0003feb6 (HINT,MEDIUM) = Error on a RR entry that can be ignored 0x0003feb5 (WARNING,HIGH) = Multiple ER SUSP entries found 0x0003feb4 (HINT,MEDIUM) = Unsupported volume descriptor found 0x0003feb3 (WARNING,HIGH) = El-Torito related warning 0x0003feb2 (MISHAP,HIGH) = Image write cancelled 0x0003feb1 (WARNING,HIGH) = El-Torito image is hidden Outdated codes which may not be re-used for other purposes than re-instating them, if ever: X 0x00031001 (SORRY,HIGH) = Cannot read file (ignored) X 0x00031002 (FATAL,HIGH) = Cannot read file (operation canceled) X 0x00031000 (FATAL,HIGH) = Unsupported ISO-9660 image X 0x00031001 (HINT,MEDIUM) = Unsupported Vol Desc that will be ignored X 0x00031002 (FATAL,HIGH) = Damaged ISO-9660 image X 0x00031003 (SORRY,HIGH) = Cannot read previous image file X 0x00030101 (HINT,MEDIUM) = Unsupported SUSP entry that will be ignored X 0x00030102 (SORRY,HIGH) = Wrong/damaged SUSP entry X 0x00030103 (WARNING,MEDIUM)= Multiple SUSP ER entries where found X 0x00030111 (SORRY,HIGH) = Unsupported RR feature X 0x00030112 (SORRY,HIGH) = Error in a Rock Ridge entry X 0x00030201 (HINT,MEDIUM) = Unsupported Boot Vol Desc that will be ignored X 0x00030202 (SORRY,HIGH) = Wrong El-Torito catalog X 0x00030203 (HINT,MEDIUM) = Unsupported El-Torito feature X 0x00030204 (SORRY,HIGH) = Invalid file to be an El-Torito image X 0x00030205 (WARNING,MEDIUM)= Cannot properly patch isolinux image X 0x00030206 (WARNING,MEDIUM)= Copying El-Torito from a previous image without X enought info about it X 0x00030301 (NOTE,MEDIUM) = Unsupported file type for Joliet tree ------------------------------------------------------------------------------ Range "application" : 0x00040000 to 0x0004ffff 0x00040000 (ABORT,HIGH) : Application supplied message 0x00040001 (FATAL,HIGH) : Application supplied message 0x00040002 (SORRY,HIGH) : Application supplied message 0x00040003 (WARNING,HIGH) : Application supplied message 0x00040004 (HINT,HIGH) : Application supplied message 0x00040005 (NOTE,HIGH) : Application supplied message 0x00040006 (UPDATE,HIGH) : Application supplied message 0x00040007 (DEBUG,HIGH) : Application supplied message 0x00040008 (*,HIGH) : Application supplied message ------------------------------------------------------------------------------ Range "libisofs-xorriso" : 0x00050000 to 0x0005ffff This is an alternative representation of libisofs.so.6 error codes in xorriso. If values returned by iso_error_get_code() do not fit into 0x30000 to 0x3ffff then they get truncated to 16 bit and mapped into this range. (This should never need to happen, of course.) ------------------------------------------------------------------------------ Range "libisoburn" : 0x00060000 to 0x00006ffff 0x00060000 (*,*) : Message which shall be attributed to libisoburn >>> the messages of libisoburn need to be registered individually ------------------------------------------------------------------------------ #endif /* LIDBAX_MSGS_________________ */ #ifdef LIBISO_MSGS_H_INTERNAL /* Internal Functions */ /** Lock before doing side effect operations on m */ static int libiso_msgs_lock(struct libiso_msgs *m, int flag); /** Unlock after effect operations on m are done */ static int libiso_msgs_unlock(struct libiso_msgs *m, int flag); /** Create new empty message item. @param link Previous item in queue @param flag Bitfield for control purposes (unused yet, submit 0) @return >0 success, <=0 failure */ static int libiso_msgs_item_new(struct libiso_msgs_item **item, struct libiso_msgs_item *link, int flag); /** Destroy a message item obtained by libiso_msgs_obtain(). The submitted pointer gets set to NULL. @param flag Bitfield for control purposes (unused yet, submit 0) @return 1 for success, 0 for pointer to NULL */ static int libiso_msgs_item_destroy(struct libiso_msgs_item **item, int flag); #endif /* LIBISO_MSGS_H_INTERNAL */ #endif /* ! LIBISO_MSGS_H_INCLUDED */ libisofs-1.4.2/libisofs/hfsplus_classes.c0000644000175700017510000001723212321161425015442 00000000000000/* * * Based on Unicode 3.2.0. * See http://www.unicode.org/copyright.html * Quote from there: * "Copyright (c) 1991-2012 Unicode, Inc. All rights reserved. * [...] * Permission is hereby granted, free of charge, to any person obtaining a * copy of the Unicode data files and any associated documentation * (the "Data Files") or Unicode software and any associated documentation * (the "Software") to deal in the Data Files or Software without restriction, * including without limitation the rights to use, copy, modify, merge, publish, * distribute, and/or sell copies of the Data Files or Software, and to permit * persons to whom the Data Files or Software are furnished to do so, provided * that (a) the above copyright notice(s) and this permission notice appear * with all copies of the Data Files or Software, (b) both the above copyright * notice(s) and this permission notice appear in associated documentation, * and (c) there is clear notice in each modified Data File or in the Software * as well as in the documentation associated with the Data File(s) or * Software that the data or software has been modified." * * * For this particular implementation: * * Copyright (c) 2012 Vladimir Serbinenko * Copyright (c) 2012 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif #include #include "hfsplus.h" /* This encodes a matrix of page and character, with 16-bit words as elements. Initially the matrix is filled with zeros. 1: The first element is the page number. If it is equal or lower than the previous one, then the matrix is done. 2: The next element is the character number If it is equal or lower than the previous one, the page is done. Goto 1. 3: The next element is the byte value. Goto 2. */ static uint16_t class_page_data[] = { /* page 03 */ 0x03, 0x00, 0x230, 0x01, 0x230, 0x02, 0x230, 0x03, 0x230, 0x04, 0x230, 0x05, 0x230, 0x06, 0x230, 0x07, 0x230, 0x08, 0x230, 0x09, 0x230, 0x0a, 0x230, 0x0b, 0x230, 0x0c, 0x230, 0x0d, 0x230, 0x0e, 0x230, 0x0f, 0x230, 0x10, 0x230, 0x11, 0x230, 0x12, 0x230, 0x13, 0x230, 0x14, 0x230, 0x15, 0x232, 0x16, 0x220, 0x17, 0x220, 0x18, 0x220, 0x19, 0x220, 0x1a, 0x232, 0x1b, 0x216, 0x1c, 0x220, 0x1d, 0x220, 0x1e, 0x220, 0x1f, 0x220, 0x20, 0x220, 0x21, 0x202, 0x22, 0x202, 0x23, 0x220, 0x24, 0x220, 0x25, 0x220, 0x26, 0x220, 0x27, 0x202, 0x28, 0x202, 0x29, 0x220, 0x2a, 0x220, 0x2b, 0x220, 0x2c, 0x220, 0x2d, 0x220, 0x2e, 0x220, 0x2f, 0x220, 0x30, 0x220, 0x31, 0x220, 0x32, 0x220, 0x33, 0x220, 0x34, 0x1, 0x35, 0x1, 0x36, 0x1, 0x37, 0x1, 0x38, 0x1, 0x39, 0x220, 0x3a, 0x220, 0x3b, 0x220, 0x3c, 0x220, 0x3d, 0x230, 0x3e, 0x230, 0x3f, 0x230, 0x40, 0x230, 0x41, 0x230, 0x42, 0x230, 0x43, 0x230, 0x44, 0x230, 0x45, 0x240, 0x46, 0x230, 0x47, 0x220, 0x48, 0x220, 0x49, 0x220, 0x4a, 0x230, 0x4b, 0x230, 0x4c, 0x230, 0x4d, 0x220, 0x4e, 0x220, 0x60, 0x234, 0x61, 0x234, 0x62, 0x233, 0x63, 0x230, 0x64, 0x230, 0x65, 0x230, 0x66, 0x230, 0x67, 0x230, 0x68, 0x230, 0x69, 0x230, 0x6a, 0x230, 0x6b, 0x230, 0x6c, 0x230, 0x6d, 0x230, 0x6e, 0x230, 0x6f, 0x230, 0x00, /* page04 */ 0x04, 0x83, 0x230, 0x84, 0x230, 0x85, 0x230, 0x86, 0x230, 0x00, /* page05 */ 0x05, 0x91, 0x220, 0x92, 0x230, 0x93, 0x230, 0x94, 0x230, 0x95, 0x230, 0x96, 0x220, 0x97, 0x230, 0x98, 0x230, 0x99, 0x230, 0x9a, 0x222, 0x9b, 0x220, 0x9c, 0x230, 0x9d, 0x230, 0x9e, 0x230, 0x9f, 0x230, 0xa0, 0x230, 0xa1, 0x230, 0xa3, 0x220, 0xa4, 0x220, 0xa5, 0x220, 0xa6, 0x220, 0xa7, 0x220, 0xa8, 0x230, 0xa9, 0x230, 0xaa, 0x220, 0xab, 0x230, 0xac, 0x230, 0xad, 0x222, 0xae, 0x228, 0xaf, 0x230, 0xb0, 0x10, 0xb1, 0x11, 0xb2, 0x12, 0xb3, 0x13, 0xb4, 0x14, 0xb5, 0x15, 0xb6, 0x16, 0xb7, 0x17, 0xb8, 0x18, 0xb9, 0x19, 0xbb, 0x20, 0xbc, 0x21, 0xbd, 0x22, 0xbf, 0x23, 0xc1, 0x24, 0xc2, 0x25, 0xc4, 0x230, 0x00, /* page06 */ 0x06, 0x4b, 0x27, 0x4c, 0x28, 0x4d, 0x29, 0x4e, 0x30, 0x4f, 0x31, 0x50, 0x32, 0x51, 0x33, 0x52, 0x34, 0x53, 0x230, 0x54, 0x230, 0x55, 0x220, 0x70, 0x35, 0xd6, 0x230, 0xd7, 0x230, 0xd8, 0x230, 0xd9, 0x230, 0xda, 0x230, 0xdb, 0x230, 0xdc, 0x230, 0xdf, 0x230, 0xe0, 0x230, 0xe1, 0x230, 0xe2, 0x230, 0xe3, 0x220, 0xe4, 0x230, 0xe7, 0x230, 0xe8, 0x230, 0xea, 0x220, 0xeb, 0x230, 0xec, 0x230, 0xed, 0x220, 0x00, /* page07 */ 0x07, 0x11, 0x36, 0x30, 0x230, 0x31, 0x220, 0x32, 0x230, 0x33, 0x230, 0x34, 0x220, 0x35, 0x230, 0x36, 0x230, 0x37, 0x220, 0x38, 0x220, 0x39, 0x220, 0x3a, 0x230, 0x3b, 0x220, 0x3c, 0x220, 0x3d, 0x230, 0x3e, 0x220, 0x3f, 0x230, 0x40, 0x230, 0x41, 0x230, 0x42, 0x220, 0x43, 0x230, 0x44, 0x220, 0x45, 0x230, 0x46, 0x220, 0x47, 0x230, 0x48, 0x220, 0x49, 0x230, 0x4a, 0x230, 0x00, /* page09 */ 0x09, 0x3c, 0x7, 0x4d, 0x9, 0x51, 0x230, 0x52, 0x220, 0x53, 0x230, 0x54, 0x230, 0xbc, 0x7, 0xcd, 0x9, 0x00, /* page0a */ 0x0a, 0x3c, 0x7, 0x4d, 0x9, 0xbc, 0x7, 0xcd, 0x9, 0x00, /* page0b */ 0x0b, 0x3c, 0x7, 0x4d, 0x9, 0xcd, 0x9, 0x00, /* page0c */ 0x0c, 0x4d, 0x9, 0x55, 0x84, 0x56, 0x91, 0xcd, 0x9, 0x00, /* page0d */ 0x0d, 0x4d, 0x9, 0xca, 0x9, 0x00, /* page0e */ 0x0e, 0x38, 0x103, 0x39, 0x103, 0x3a, 0x9, 0x48, 0x107, 0x49, 0x107, 0x4a, 0x107, 0x4b, 0x107, 0xb8, 0x118, 0xb9, 0x118, 0xc8, 0x122, 0xc9, 0x122, 0xca, 0x122, 0xcb, 0x122, 0x00, /* page0f */ 0x0f, 0x18, 0x220, 0x19, 0x220, 0x35, 0x220, 0x37, 0x220, 0x39, 0x216, 0x71, 0x129, 0x72, 0x130, 0x74, 0x132, 0x7a, 0x130, 0x7b, 0x130, 0x7c, 0x130, 0x7d, 0x130, 0x80, 0x130, 0x82, 0x230, 0x83, 0x230, 0x84, 0x9, 0x86, 0x230, 0x87, 0x230, 0xc6, 0x220, 0x00, /* page10 */ 0x10, 0x37, 0x7, 0x39, 0x9, 0x00, /* page17 */ 0x17, 0x14, 0x9, 0x34, 0x9, 0xd2, 0x9, 0x00, /* page18 */ 0x18, 0xa9, 0x228, 0x00, /* page20 */ 0x20, 0xd0, 0x230, 0xd1, 0x230, 0xd2, 0x1, 0xd3, 0x1, 0xd4, 0x230, 0xd5, 0x230, 0xd6, 0x230, 0xd7, 0x230, 0xd8, 0x1, 0xd9, 0x1, 0xda, 0x1, 0xdb, 0x230, 0xdc, 0x230, 0xe1, 0x230, 0xe5, 0x1, 0xe6, 0x1, 0xe7, 0x230, 0xe8, 0x220, 0xe9, 0x230, 0xea, 0x1, 0x00, /* page30 */ 0x30, 0x2a, 0x218, 0x2b, 0x228, 0x2c, 0x232, 0x2d, 0x222, 0x2e, 0x224, 0x2f, 0x224, 0x99, 0x8, 0x9a, 0x8, 0x00, /* pagefb */ 0xfb, 0x1e, 0x26, 0x00, /* pagefe */ 0xfe, 0x20, 0x230, 0x21, 0x230, 0x22, 0x230, 0x23, 0x230, }; uint16_t *hfsplus_class_pages[256]; static uint16_t class_pages[19][256]; void make_hfsplus_class_pages() { int page_idx = -1, char_idx, i; uint16_t *rpt, *page_pt; int page_count = 0; memset(class_pages, 0, 19 * 256); for (i = 0; i < 256; i++) hfsplus_class_pages[i] = NULL; rpt = (uint16_t *) class_page_data; page_pt = (uint16_t *) class_pages; while (1) { if (*rpt <= page_idx) break; page_count++; page_idx = *(rpt++); char_idx = -1; while (1) { if(*rpt <= char_idx) break; char_idx = *(rpt++); page_pt[char_idx] = *(rpt++); } rpt++; hfsplus_class_pages[page_idx] = class_pages[page_count - 1]; page_pt += 256; } } libisofs-1.4.2/libisofs/md5.h0000644000175700017510000000252612321161425012733 00000000000000/* * Copyright (c) 2009 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ #ifndef LIBISO_MD5_H_ #define LIBISO_MD5_H_ /* The MD5 computation API is in libisofs.h : iso_md5_start() et.al. */ /** Create a writer object for checksums and add it to the writer list of the given Ecma119Image. */ int checksum_writer_create(Ecma119Image *target); /* Write stream detectable checksum tag to extra block. * All tag ranges start at the beginning of the System Area (i.e. t->ms_block) * and stem from the same MD5 computation context. Tag types 2 and 3 are * intermediate checksums. Type 2 announces the existence of type 3. * If both match, then at least the directory tree is trustworthy. * Type 1 is written at the very end of the session. If it matches, then * the whole image is trustworthy. * @param t The image being written * @flag bit0-7= tag type * 1= session tag (End checksumming.) * 2= superblock tag (System Area and Volume Descriptors) * 3= tree tag (ECMA-119 and Rock Ridge tree) */ int iso_md5_write_tag(Ecma119Image *t, int flag); #endif /* ! LIBISO_MD5_H_ */ libisofs-1.4.2/libisofs/fs_image.c0000644000175700017510000064167012606673163014041 00000000000000/* * Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2009 - 2015 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ /* * Filesystem/FileSource implementation to access an ISO image, using an * IsoDataSource to read image data. */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif #include "libisofs.h" #include "ecma119.h" #include "messages.h" #include "rockridge.h" #include "image.h" #include "tree.h" #include "eltorito.h" #include "node.h" #include "aaip_0_2.h" #include "system_area.h" #include #include #include #include #include #include #include /* Enable this and write the correct absolute path into the include statement below in order to test the pending contribution to syslinux: http://www.syslinux.org/archives/2013-March/019755.html # def ine Libisofs_syslinux_tesT 1 */ #ifdef Libisofs_syslinux_tesT #define Isolinux_rockridge_in_libisofS 1 #include "/reiser/syslinux/core/fs/iso9660/susp_rr.c" /* # inc lude "/home/thomas/projekte/cdrskin_dir/libisoburn-develop/test/susp_rr.c" */ #endif /* Libisofs_syslinux_tesT */ /** * Options for image reading. * There are four kind of options: * - Related to multisession support. * In most cases, an image begins at LBA 0 of the data source. However, * in multisession discs, the later image begins in the last session on * disc. The block option can be used to specify the start of that last * session. * - Related to the tree that will be read. * As default, when Rock Ridge extensions are present in the image, that * will be used to get the tree. If RR extensions are not present, libisofs * will use the Joliet extensions if available. Finally, the plain ISO-9660 * tree is used if neither RR nor Joliet extensions are available. With * norock, nojoliet, and preferjoliet options, you can change this * default behavior. * - Related to default POSIX attributes. * When Rock Ridege extensions are not used, libisofs can't figure out what * are the the permissions, uid or gid for the files. You should supply * default values for that. */ struct iso_read_opts { /** * Block where the image begins, usually 0, can be different on a * multisession disc. */ uint32_t block; unsigned int norock : 1; /*< Do not read Rock Ridge extensions */ unsigned int nojoliet : 1; /*< Do not read Joliet extensions */ unsigned int noiso1999 : 1; /*< Do not read ISO 9660:1999 enhanced tree */ unsigned int noaaip : 1; /* Do not read AAIP extension for xattr and ACL */ unsigned int nomd5 : 2; /* Do not read MD5 array */ /** * Hand out new inode numbers and overwrite eventually read PX inode * numbers. This will split apart any hardlinks. */ unsigned int make_new_ino : 1 ; /** * When both Joliet and RR extensions are present, the RR tree is used. * If you prefer using Joliet, set this to 1. */ unsigned int preferjoliet : 1; /** * If neither Rock Ridge nor Joliet is used, the ECMA-119 names are mapped * according to one of these rules * 0 = unmapped: show name as recorded in ECMA-119 directory record * (not suitable for writing them to a new ISO filesystem) * 1 = stripped: like unmapped, but strip off trailing ";1" or ".;1" * 2 = uppercase: like stripped, but {a-z} mapped to {A-Z} * 3 = lowercase: like stripped, but {A-Z} mapped to {a-z} */ unsigned int ecma119_map : 2; uid_t uid; /**< Default uid when no RR */ gid_t gid; /**< Default uid when no RR */ mode_t dir_mode; /**< Default mode when no RR (only permissions) */ mode_t file_mode; /* TODO #00024 : option to convert names to lower case for iso reading */ /** * Input charset for RR file names. NULL to use default locale charset. */ char *input_charset; /** * Enable or disable methods to automatically choose an input charset. * This eventually overrides input_charset. * * bit0= allow to set the input character set automatically from * attribute "isofs.cs" of root directory */ int auto_input_charset; /** * Enable or disable loading of the first 32768 bytes of the session and * submission by iso_write_opts_set_system_area(data, 0). */ int load_system_area; /** * Keep data source of imported ISO filesystem in IsoImage.import_src */ int keep_import_src; /** * What to do in case of name longer than truncate_length: * 0= throw FAILURE * 1= truncate to truncate_length with MD5 of whole name at end */ int truncate_mode; int truncate_length; }; /** * Return information for image. * Both size, hasRR and hasJoliet will be filled by libisofs with suitable * values. */ struct iso_read_image_features { /** * Will be filled with the size (in 2048 byte block) of the image, as * reported in the PVM. */ uint32_t size; /** It will be set to 1 if RR extensions are present, to 0 if not. */ unsigned int hasRR :1; /** It will be set to 1 if Joliet extensions are present, to 0 if not. */ unsigned int hasJoliet :1; /** * It will be set to 1 if the image is an ISO 9660:1999, i.e. it has * a version 2 Enhanced Volume Descriptor. */ unsigned int hasIso1999 :1; /** It will be set to 1 if El-Torito boot record is present, to 0 if not.*/ unsigned int hasElTorito :1; }; static int ifs_fs_open(IsoImageFilesystem *fs); static int ifs_fs_close(IsoImageFilesystem *fs); static int iso_file_source_new_ifs(IsoImageFilesystem *fs, IsoFileSource *parent, struct ecma119_dir_record *record, IsoFileSource **src, int flag); /** unique identifier for each image */ unsigned int fs_dev_id = 0; /** * Should the RR extensions be read? */ enum read_rr_ext { RR_EXT_NO = 0, /*< Do not use RR extensions */ RR_EXT_110 = 1, /*< RR extensions conforming version 1.10 */ RR_EXT_112 = 2 /*< RR extensions conforming version 1.12 */ }; /** * Private data for the image IsoFilesystem */ typedef struct { /** DataSource from where data will be read */ IsoDataSource *src; /** unique id for the each image (filesystem instance) */ unsigned int id; /** * Counter of the times the filesystem has been openned still pending of * close. It is used to keep track of when we need to actually open or * close the IsoDataSource. */ unsigned int open_count; uid_t uid; /**< Default uid when no RR */ gid_t gid; /**< Default uid when no RR */ mode_t dir_mode; /**< Default mode when no RR (only permissions) */ mode_t file_mode; int msgid; char *input_charset; /**< Input charset for RR names */ char *local_charset; /**< For RR names, will be set to the locale one */ /** * Enable or disable methods to automatically choose an input charset. * This eventually overrides input_charset. * * bit0= allow to set the input character set automatically from * attribute "isofs.cs" of root directory */ int auto_input_charset; /** * Will be filled with the block lba of the extend for the root directory * of the hierarchy that will be read, either from the PVD (ISO, RR) or * from the SVD (Joliet) */ uint32_t iso_root_block; /** * Will be filled with the block lba of the extend for the root directory, * as read from the PVM */ uint32_t pvd_root_block; /** * Will be filled with the block lba of the extend for the root directory, * as read from the SVD */ uint32_t svd_root_block; /** * Will be filled with the block lba of the extend for the root directory, * as read from the enhanced volume descriptor (ISO 9660:1999) */ uint32_t evd_root_block; /** * If we need to read RR extensions. i.e., if the image contains RR * extensions, and the user wants to read them. */ enum read_rr_ext rr; /** * Bytes skipped within the System Use field of a directory record, before * the beginning of the SUSP system user entries. See IEEE 1281, SUSP. 5.3. */ uint8_t len_skp; /* Volume attributes */ char *volset_id; char *volume_id; /**< Volume identifier. */ char *publisher_id; /**< Volume publisher. */ char *data_preparer_id; /**< Volume data preparer. */ char *system_id; /**< Volume system identifier. */ char *application_id; /**< Volume application id */ char *copyright_file_id; char *abstract_file_id; char *biblio_file_id; char *creation_time; char *modification_time; char *expiration_time; char *effective_time; /* extension information */ /** * RR version being used in image. * 0 no RR extension, 1 RRIP 1.10, 2 RRIP 1.12 */ enum read_rr_ext rr_version; /** If Joliet extensions are available on image */ unsigned int joliet : 1; /** If ISO 9660:1999 is available on image */ unsigned int iso1999 : 1; /** * See struct iso_read_opts. */ int truncate_mode; int truncate_length; unsigned int ecma119_map : 2; /** Whether AAIP info shall be loaded if it is present. * 1 = yes , 0 = no */ int aaip_load; /** Whether the MD5 array shall be read if available. * 2 = yes, but do not check tags , 1 = yes , 0 = no */ int md5_load; /** Whether AAIP is present. Version major.minor = major * 100 + minor * Value -1 means that no AAIP ER was detected yet. */ int aaip_version; /** * Number of blocks of the volume, as reported in the PVM. */ uint32_t nblocks; /* el-torito information */ unsigned int eltorito : 1; /* is el-torito available */ int num_bootimgs; unsigned char platform_ids[Libisofs_max_boot_imageS]; unsigned char id_strings[Libisofs_max_boot_imageS][28]; unsigned char selection_crits[Libisofs_max_boot_imageS][20]; unsigned char boot_flags[Libisofs_max_boot_imageS]; /* bit0= bootable */ unsigned char media_types[Libisofs_max_boot_imageS]; unsigned char partition_types[Libisofs_max_boot_imageS]; short load_segs[Libisofs_max_boot_imageS]; short load_sizes[Libisofs_max_boot_imageS]; /** Block addresses of for El-Torito boot images. Needed to recognize them when the get read from the directory tree. */ uint32_t bootblocks[Libisofs_max_boot_imageS]; uint32_t catblock; /**< Block for El-Torito catalog */ off_t catsize; /* Size of boot catalog in bytes */ char *catcontent; /* Whether inode numbers from PX entries shall be discarded */ unsigned int make_new_ino : 1 ; /* Inode number generator counter. 32 bit because for Rock Ridge PX. */ uint32_t inode_counter; /* PX inode number status bit0= there were nodes with PX inode numbers bit1= there were nodes with PX but without inode numbers bit2= there were nodes without PX bit3= there were nodes with faulty PX */ int px_ino_status; /* Which Rock Ridge error messages already have occured bit0= Invalid PX entry bit1= Invalid TF entry bit2= New NM entry found without previous CONTINUE flag bit3= Invalid NM entry bit4= New SL entry found without previous CONTINUE flag bit5= Invalid SL entry bit6= Invalid SL entry, no child location bit7= Invalid PN entry bit8= Sparse files not supported bit9= SP entry found in a directory entry other than '.' entry of root bit10= ER entry found in a directory entry other than '.' entry of root bit11= Invalid AA entry bit12= Invalid AL entry bit13= Invalid ZF entry bit14= Rock Ridge PX entry is not present or invalid bit15= Incomplete NM bit16= Incomplete SL bit17= Charset conversion error bit18= Link without destination */ int rr_err_reported; int rr_err_repeated; size_t joliet_ucs2_failures; } _ImageFsData; typedef struct image_fs_data ImageFileSourceData; /* IMPORTANT: Any change must be reflected by ifs_clone_src */ struct image_fs_data { IsoImageFilesystem *fs; /**< reference to the image it belongs to */ IsoFileSource *parent; /**< reference to the parent (NULL if root) */ struct stat info; /**< filled struct stat */ char *name; /**< name of this file */ /** * Location of file extents. */ struct iso_file_section *sections; int nsections; unsigned int opened : 2; /**< 0 not opened, 1 opened file, 2 opened dir */ #ifdef Libisofs_with_zliB uint8_t header_size_div4; uint8_t block_size_log2; uint32_t uncompressed_size; #endif /* info for content reading */ struct { /** * - For regular files, once opened it points to a temporary data * buffer of 2048 bytes. * - For dirs, once opened it points to a IsoFileSource* array with * its children * - For symlinks, it points to link destination */ void *content; /** * - For regular files, number of bytes already read. */ off_t offset; } data; /** * malloc() storage for the string of AAIP fields which represent * ACLs and XFS-style Extended Attributes. (Not to be confused with * ECMA-119 Extended Attributes.) */ unsigned char *aa_string; }; struct child_list { IsoFileSource *file; struct child_list *next; }; void child_list_free(struct child_list *list) { struct child_list *temp; struct child_list *next = list; while (next != NULL) { temp = next->next; iso_file_source_unref(next->file); free(next); next = temp; } } static char* ifs_get_path(IsoFileSource *src) { ImageFileSourceData *data; data = src->data; if (data->parent == NULL) { return strdup(""); } else { char *path, *new_path; int pathlen; if (data->name == NULL) return NULL; path = ifs_get_path(data->parent); if (path == NULL) return NULL; pathlen = strlen(path); new_path = realloc(path, pathlen + strlen(data->name) + 2); if (new_path == NULL) { free(path); return NULL; } path= new_path; path[pathlen] = '/'; path[pathlen + 1] = '\0'; return strcat(path, data->name); } } static char* ifs_get_name(IsoFileSource *src) { ImageFileSourceData *data; data = src->data; return data->name == NULL ? NULL : strdup(data->name); } static int ifs_lstat(IsoFileSource *src, struct stat *info) { ImageFileSourceData *data; if (src == NULL || info == NULL) { return ISO_NULL_POINTER; } data = src->data; if (data == NULL) return ISO_NULL_POINTER; *info = data->info; return ISO_SUCCESS; } static int ifs_stat(IsoFileSource *src, struct stat *info) { ImageFileSourceData *data; if (src == NULL || info == NULL || src->data == NULL) { return ISO_NULL_POINTER; } data = (ImageFileSourceData*)src->data; if (S_ISLNK(data->info.st_mode)) { /* TODO #00012 : support follow symlinks on image filesystem */ return ISO_FILE_BAD_PATH; } *info = data->info; return ISO_SUCCESS; } static int ifs_access(IsoFileSource *src) { /* we always have access, it is controlled by DataSource */ return ISO_SUCCESS; } /** * Read all directory records in a directory, and creates an IsoFileSource for * each of them, storing them in the data field of the IsoFileSource for the * given dir. */ static int read_dir(ImageFileSourceData *data) { int ret; uint32_t size; uint32_t block; IsoImageFilesystem *fs; _ImageFsData *fsdata; struct ecma119_dir_record *record; uint8_t *buffer = NULL; IsoFileSource *child = NULL; uint32_t pos = 0; uint32_t tlen = 0; if (data == NULL) { ret = ISO_NULL_POINTER; goto ex; } LIBISO_ALLOC_MEM(buffer, uint8_t, BLOCK_SIZE); fs = data->fs; fsdata = fs->data; /* a dir has always a single extent */ block = data->sections[0].block; ret = fsdata->src->read_block(fsdata->src, block, buffer); if (ret < 0) { goto ex; } /* "." entry, get size of the dir and skip */ record = (struct ecma119_dir_record *)(buffer + pos); size = iso_read_bb(record->length, 4, NULL); tlen += record->len_dr[0]; pos += record->len_dr[0]; /* skip ".." */ record = (struct ecma119_dir_record *)(buffer + pos); tlen += record->len_dr[0]; pos += record->len_dr[0]; while (tlen < size) { record = (struct ecma119_dir_record *)(buffer + pos); if (pos == 2048 || record->len_dr[0] == 0) { /* * The directory entries are splitted in several blocks * read next block */ ret = fsdata->src->read_block(fsdata->src, ++block, buffer); if (ret < 0) { goto ex; } tlen += 2048 - pos; pos = 0; continue; } /* (Vreixo:) * What about ignoring files with existence flag? * if (record->flags[0] & 0x01) * continue; * ts B20306 : >>> One should rather record that flag and write it * >>> to the new image. */ #ifdef Libisofs_wrongly_skip_rr_moveD /* ts B20306 : This skipping by name is wrong resp. redundant: If no rr reading is enabled, then it is the only access point for the content of relocated directories. So one should not ignore it. If rr reading is enabled, then the RE entry of mkisofs' RR_MOVED will cause it to be skipped. */ /* (Vreixo:) * For a extrange reason, mkisofs relocates directories under * a RR_MOVED dir. It seems that it is only used for that purposes, * and thus it should be removed from the iso tree before * generating a new image with libisofs, that don't uses it. */ if (data->parent == NULL && record->len_fi[0] == 8 && !strncmp((char*)record->file_id, "RR_MOVED", 8)) { iso_msg_debug(fsdata->msgid, "Skipping RR_MOVE entry."); tlen += record->len_dr[0]; pos += record->len_dr[0]; continue; } #endif /* Libisofs_wrongly_skip_rr_moveD */ /* * We pass a NULL parent instead of dir, to prevent the circular * reference from child to parent. */ ret = iso_file_source_new_ifs(fs, NULL, record, &child, 0); if (ret < 0) { if (child) { /* * This can only happen with multi-extent files. */ ImageFileSourceData *ifsdata = child->data; free(ifsdata->sections); free(ifsdata->name); free(ifsdata); free(child); } goto ex; } /* add to the child list */ if (ret == 1) { struct child_list *node; node = malloc(sizeof(struct child_list)); if (node == NULL) { iso_file_source_unref(child); {ret = ISO_OUT_OF_MEM; goto ex;} } /* * Note that we insert in reverse order. This leads to faster * addition here, but also when adding to the tree, as insertion * will be done, sorted, in the first position of the list. */ node->next = data->data.content; node->file = child; data->data.content = node; child = NULL; } tlen += record->len_dr[0]; pos += record->len_dr[0]; } ret = ISO_SUCCESS; ex:; LIBISO_FREE_MEM(buffer); return ret; } static int ifs_open(IsoFileSource *src) { int ret; ImageFileSourceData *data; if (src == NULL || src->data == NULL) { return ISO_NULL_POINTER; } data = (ImageFileSourceData*)src->data; if (data->opened) { return ISO_FILE_ALREADY_OPENED; } if (S_ISDIR(data->info.st_mode)) { /* ensure fs is openned */ ret = data->fs->open(data->fs); if (ret < 0) { return ret; } /* * Cache all directory entries. * This can waste more memory, but improves as disc is read in much more * sequencially way, thus reducing jump between tracks on disc */ ret = read_dir(data); data->fs->close(data->fs); if (ret < 0) { /* free probably allocated children */ child_list_free((struct child_list*)data->data.content); } else { data->opened = 2; } return ret; } else if (S_ISREG(data->info.st_mode)) { /* ensure fs is openned */ ret = data->fs->open(data->fs); if (ret < 0) { return ret; } data->data.content = malloc(BLOCK_SIZE); if (data->data.content == NULL) { return ISO_OUT_OF_MEM; } data->data.offset = 0; data->opened = 1; } else { /* symlinks and special files inside image can't be openned */ return ISO_FILE_ERROR; } return ISO_SUCCESS; } static int ifs_close(IsoFileSource *src) { ImageFileSourceData *data; if (src == NULL || src->data == NULL) { return ISO_NULL_POINTER; } data = (ImageFileSourceData*)src->data; if (!data->opened) { return ISO_FILE_NOT_OPENED; } if (data->opened == 2) { /* * close a dir, free all pending pre-allocated children. * not that we don't need to close the filesystem, it was already * closed */ child_list_free((struct child_list*) data->data.content); data->data.content = NULL; data->opened = 0; } else if (data->opened == 1) { /* close regular file */ free(data->data.content); data->fs->close(data->fs); data->data.content = NULL; data->opened = 0; } else { /* TODO only dirs and files supported for now */ return ISO_ERROR; } return ISO_SUCCESS; } /** * Computes the block where the given offset should start. */ static uint32_t block_from_offset(int nsections, struct iso_file_section *sections, off_t offset) { int section = 0; off_t bytes = 0; do { if ( (offset - bytes) < (off_t) sections[section].size ) { return sections[section].block + (offset - bytes) / BLOCK_SIZE; } else { bytes += (off_t) sections[section].size; section++; } } while(section < nsections); return 0; /* should never happen */ } /** * Get the size available for reading on the corresponding block */ static uint32_t size_available(int nsections, struct iso_file_section *sections, off_t offset) { int section = 0; off_t bytes = 0; do { if ( (offset - bytes) < (off_t) sections[section].size ) { uint32_t curr_section_offset = (uint32_t)(offset - bytes); uint32_t curr_section_left = sections[section].size - curr_section_offset; uint32_t available = BLOCK_SIZE - curr_section_offset % BLOCK_SIZE; return MIN(curr_section_left, available); } else { bytes += (off_t) sections[section].size; section++; } } while(section < nsections); return 0; /* should never happen */ } /** * Get the block offset for reading the given file offset */ static uint32_t block_offset(int nsections, struct iso_file_section *sections, off_t offset) { int section = 0; off_t bytes = 0; do { if ( (offset - bytes) < (off_t) sections[section].size ) { return (uint32_t)(offset - bytes) % BLOCK_SIZE; } else { bytes += (off_t) sections[section].size; section++; } } while(section < nsections); return 0; /* should never happen */ } /** * Attempts to read up to count bytes from the given source into * the buffer starting at buf. * * The file src must be open() before calling this, and close() when no * more needed. Not valid for dirs. On symlinks it reads the destination * file. * * @return * number of bytes read, 0 if EOF, < 0 on error * Error codes: * ISO_FILE_ERROR * ISO_NULL_POINTER * ISO_FILE_NOT_OPENED * ISO_FILE_IS_DIR * ISO_OUT_OF_MEM * ISO_INTERRUPTED */ static int ifs_read(IsoFileSource *src, void *buf, size_t count) { int ret; ImageFileSourceData *data; uint32_t read = 0; if (src == NULL || src->data == NULL || buf == NULL) { return ISO_NULL_POINTER; } if (count == 0) { return ISO_WRONG_ARG_VALUE; } data = (ImageFileSourceData*)src->data; if (!data->opened) { return ISO_FILE_NOT_OPENED; } else if (data->opened != 1) { return ISO_FILE_IS_DIR; } while (read < count && data->data.offset < data->info.st_size) { size_t bytes; uint8_t *orig; if (block_offset(data->nsections, data->sections, data->data.offset) == 0) { /* we need to buffer next block */ uint32_t block; _ImageFsData *fsdata; if (data->data.offset >= data->info.st_size) { /* EOF */ break; } fsdata = data->fs->data; block = block_from_offset(data->nsections, data->sections, data->data.offset); ret = fsdata->src->read_block(fsdata->src, block, data->data.content); if (ret < 0) { return ret; } } /* how much can I read */ bytes = MIN(size_available(data->nsections, data->sections, data->data.offset), count - read); if (data->data.offset + (off_t)bytes > data->info.st_size) { bytes = data->info.st_size - data->data.offset; } orig = data->data.content; orig += block_offset(data->nsections, data->sections, data->data.offset); memcpy((uint8_t*)buf + read, orig, bytes); read += bytes; data->data.offset += (off_t)bytes; } return read; } static off_t ifs_lseek(IsoFileSource *src, off_t offset, int flag) { ImageFileSourceData *data; if (src == NULL) { return (off_t)ISO_NULL_POINTER; } if (offset < (off_t)0) { return (off_t)ISO_WRONG_ARG_VALUE; } data = src->data; if (!data->opened) { return (off_t)ISO_FILE_NOT_OPENED; } else if (data->opened != 1) { return (off_t)ISO_FILE_IS_DIR; } switch (flag) { case 0: /* SEEK_SET */ data->data.offset = offset; break; case 1: /* SEEK_CUR */ data->data.offset += offset; break; case 2: /* SEEK_END */ /* do this make sense? */ data->data.offset = data->info.st_size + offset; break; default: return (off_t)ISO_WRONG_ARG_VALUE; } /* * We check for block_offset != 0 because if it is already 0, the block * will be read from image in the read function */ if (block_offset(data->nsections, data->sections, data->data.offset) != 0) { /* we need to buffer the block */ uint32_t block; _ImageFsData *fsdata; if (data->data.offset < data->info.st_size) { int ret; fsdata = data->fs->data; block = block_from_offset(data->nsections, data->sections, data->data.offset); ret = fsdata->src->read_block(fsdata->src, block, data->data.content); if (ret < 0) { return (off_t)ret; } } } return data->data.offset; } static int ifs_readdir(IsoFileSource *src, IsoFileSource **child) { ImageFileSourceData *data, *cdata; struct child_list *children; if (src == NULL || src->data == NULL || child == NULL) { return ISO_NULL_POINTER; } data = (ImageFileSourceData*)src->data; if (!data->opened) { return ISO_FILE_NOT_OPENED; } else if (data->opened != 2) { return ISO_FILE_IS_NOT_DIR; } /* return the first child and free it */ if (data->data.content == NULL) { return 0; /* EOF */ } children = (struct child_list*)data->data.content; *child = children->file; cdata = (ImageFileSourceData*)(*child)->data; /* set the ref to the parent */ cdata->parent = src; iso_file_source_ref(src); /* free the first element of the list */ data->data.content = children->next; free(children); return ISO_SUCCESS; } /** * Read the destination of a symlink. You don't need to open the file * to call this. * * @param buf * allocated buffer of at least bufsiz bytes. * The dest. will be copied there, and it will be NULL-terminated * @param bufsiz * characters to be copied. Destination link will be truncated if * it is larger than given size. This include the \0 character. * @return * 1 on success, < 0 on error * Error codes: * ISO_FILE_ERROR * ISO_NULL_POINTER * ISO_WRONG_ARG_VALUE -> if bufsiz <= 0 * ISO_FILE_IS_NOT_SYMLINK * ISO_OUT_OF_MEM * ISO_FILE_BAD_PATH * ISO_FILE_DOESNT_EXIST * */ static int ifs_readlink(IsoFileSource *src, char *buf, size_t bufsiz) { char *dest; size_t len; int ret; ImageFileSourceData *data; if (src == NULL || buf == NULL || src->data == NULL) { return ISO_NULL_POINTER; } if (bufsiz <= 0) { return ISO_WRONG_ARG_VALUE; } data = (ImageFileSourceData*)src->data; if (!S_ISLNK(data->info.st_mode)) { return ISO_FILE_IS_NOT_SYMLINK; } dest = (char*)data->data.content; len = strlen(dest); ret = ISO_SUCCESS; if (len >= bufsiz) { ret = ISO_RR_PATH_TOO_LONG; len = bufsiz - 1; } strncpy(buf, dest, len); buf[len] = '\0'; return ret; } static IsoFilesystem* ifs_get_filesystem(IsoFileSource *src) { ImageFileSourceData *data; if (src == NULL) { return NULL; } data = src->data; return data->fs; } static void ifs_free(IsoFileSource *src) { ImageFileSourceData *data; data = src->data; /* close the file if it is already openned */ if (data->opened) { src->class->close(src); } /* free destination if it is a link */ if (S_ISLNK(data->info.st_mode)) { free(data->data.content); } iso_filesystem_unref(data->fs); if (data->parent != NULL) { iso_file_source_unref(data->parent); } free(data->sections); free(data->name); if (data->aa_string != NULL) free(data->aa_string); free(data); } static int ifs_get_aa_string(IsoFileSource *src, unsigned char **aa_string, int flag) { size_t len; ImageFileSourceData *data; data = src->data; if ((flag & 1) || data->aa_string == NULL) { *aa_string = data->aa_string; data->aa_string = NULL; } else { len = aaip_count_bytes(data->aa_string, 0); *aa_string = calloc(len, 1); if (*aa_string == NULL) return ISO_OUT_OF_MEM; memcpy(*aa_string, data->aa_string, len); } return 1; } static int ifs_clone_src(IsoFileSource *old_source, IsoFileSource **new_source, int flag) { IsoFileSource *src = NULL; ImageFileSourceData *old_data, *new_data = NULL; char *new_name = NULL; struct iso_file_section *new_sections = NULL; void *new_aa_string = NULL; int i, ret; if (flag) return ISO_STREAM_NO_CLONE; /* unknown option required */ old_data = (ImageFileSourceData *) old_source->data; *new_source = NULL; src = calloc(1, sizeof(IsoFileSource)); if (src == NULL) goto no_mem; new_name = strdup(old_data->name); if (new_name == NULL) goto no_mem; new_data = calloc(1, sizeof(ImageFileSourceData)); if (new_data == NULL) goto no_mem; if (old_data->nsections > 0) { new_sections = calloc(old_data->nsections, sizeof(struct iso_file_section)); if (new_sections == NULL) goto no_mem; } ret = aaip_xinfo_cloner(old_data->aa_string, &new_aa_string, 0); if (ret < 0) goto no_mem; new_data->fs = old_data->fs; new_data->parent = old_data->parent; memcpy(&(new_data->info), &(old_data->info), sizeof(struct stat)); new_data->name = new_name; new_data->sections = new_sections; new_data->nsections = old_data->nsections; for (i = 0; i < new_data->nsections; i++) memcpy(new_data->sections + i, old_data->sections + i, sizeof(struct iso_file_section)); new_data->opened = old_data->opened; #ifdef Libisofs_with_zliB new_data->header_size_div4 = old_data->header_size_div4; new_data->block_size_log2 = old_data->block_size_log2; new_data->uncompressed_size = old_data->uncompressed_size; #endif new_data->data.content = NULL; new_data->aa_string = (unsigned char *) new_aa_string; src->class = old_source->class; src->refcount = 1; src->data = new_data; *new_source = src; iso_file_source_ref(new_data->parent); iso_filesystem_ref(new_data->fs); return ISO_SUCCESS; no_mem:; if (src != NULL) free((char *) src); if (new_data != NULL) free((char *) new_data); if (new_name != NULL) free(new_name); if (new_sections != NULL) free((char *) new_sections); if (new_aa_string != NULL) aaip_xinfo_func(new_aa_string, 1); return ISO_OUT_OF_MEM; } IsoFileSourceIface ifs_class = { 2, /* version */ ifs_get_path, ifs_get_name, ifs_lstat, ifs_stat, ifs_access, ifs_open, ifs_close, ifs_read, ifs_readdir, ifs_readlink, ifs_get_filesystem, ifs_free, ifs_lseek, ifs_get_aa_string, ifs_clone_src }; /* Used from libisofs/stream.c : iso_stream_get_src_zf() */ int iso_ifs_source_get_zf(IsoFileSource *src, int *header_size_div4, int *block_size_log2, uint32_t *uncompressed_size, int flag) { #ifdef Libisofs_with_zliB ImageFileSourceData *data; if (src->class != &ifs_class) return 0; data = src->data; *header_size_div4 = data->header_size_div4; *block_size_log2 = data->block_size_log2; *uncompressed_size = data->uncompressed_size; return 1; #else return 0; #endif /* ! Libisofs_with_zliB */ } static int make_hopefully_unique_name(_ImageFsData *fsdata, char *str, size_t len, char **name) { int ret, name_len, i; char c, *smashed = NULL, md5[16]; void *md5_context = NULL; /* Shorten so that 32 characters of MD5 fit. If shorter than 8, pad up to 8 by '_'. Smash characters to [0-9A-Za-z_.]. Append MD5 of original str as hex digits. */ name_len = len > 223 ? 223 : len; LIBISO_ALLOC_MEM(smashed, char, (name_len >= 8 ? name_len : 8) + 32 + 1); memcpy(smashed, str, name_len); for (; name_len < 8; name_len++) smashed[name_len] = '_'; smashed[name_len] = 0; for (i = 0; i < name_len; i++) { c = smashed[i]; if (c == '.' || (c >= '0' && c <= '9') || c == '_' || (c >= 'a' && c <= 'z')) continue; smashed[i] = '_'; } ret = iso_md5_start(&md5_context); if (ret != 1) goto ex; ret = iso_md5_compute(md5_context, str, len); if (ret != 1) goto ex; ret = iso_md5_end(&md5_context, md5); if (ret != 1) goto ex; for (i = 0; i < 16; i++) sprintf(smashed + i * 2 + name_len, "%2.2x", ((unsigned char *) md5)[i]); name_len += 32; smashed[name_len] = 0; *name = smashed; smashed = NULL; ret = ISO_SUCCESS; ex: LIBISO_FREE_MEM(smashed); if (md5_context != NULL) iso_md5_end(&md5_context, md5); return ret; } /** * Read a file name from a directory record, doing the needed charset * conversion */ static char *get_name(_ImageFsData *fsdata, char *str, size_t len) { int ret; char *name = NULL, *from_ucs = NULL; if (strcmp(fsdata->local_charset, fsdata->input_charset)) { /* charset conversion needed */ ret = strnconv(str, fsdata->input_charset, fsdata->local_charset, len, &name); if (ret == 1) { if (fsdata->iso_root_block == fsdata->svd_root_block) { /* Reading from Joliet : Check whether UTF-16 was needed */ ret = strnconv(str, "UCS-2BE", fsdata->local_charset, len, &from_ucs); if (ret == 1) ret = (strcmp(name, from_ucs) == 0); if (ret != 1) { fsdata->joliet_ucs2_failures++; if (fsdata->joliet_ucs2_failures <= ISO_JOLIET_UCS2_WARN_MAX) iso_msg_submit(-1, ISO_NAME_NOT_UCS2, 0, "Joliet filename valid only with character set UTF-16 : \"%s\"", name); } if (from_ucs != NULL) free(from_ucs); } return name; } else { ret = iso_msg_submit(fsdata->msgid, ISO_FILENAME_WRONG_CHARSET, ret, "Cannot convert from charset %s to %s", fsdata->input_charset, fsdata->local_charset); if (ret < 0) { return NULL; /* aborted */ } /* fallback */ ret = make_hopefully_unique_name(fsdata, str, len, &name); if (ret == ISO_SUCCESS) return name; return NULL; } } /* we reach here when the charset conversion is not needed */ name = malloc(len + 1); if (name == NULL) { return NULL; } memcpy(name, str, len); name[len] = '\0'; return name; } static int iso_rr_msg_submit(_ImageFsData *fsdata, int rr_err_bit, int errcode, int causedby, const char *msg) { int ret; if ((fsdata->rr_err_reported & (1 << rr_err_bit)) && (fsdata->rr_err_repeated & (1 << rr_err_bit))) { if (iso_msg_is_abort(errcode)) return ISO_CANCELED; return 0; } if (fsdata->rr_err_reported & (1 << rr_err_bit)) { ret = iso_msg_submit(fsdata->msgid, errcode, causedby, "MORE THAN ONCE : %s", msg); fsdata->rr_err_repeated |= (1 << rr_err_bit); } else { ret = iso_msg_submit(fsdata->msgid, errcode, causedby, "%s", msg); fsdata->rr_err_reported |= (1 << rr_err_bit); } return ret; } /** * * @param src * if not-NULL, it points to a multi-extent file returned by a previous * call to this function. * @param flag * bit0= this is the root node attribute load call * (parameter parent is not reliable for this) * @return * 2 node is still incomplete (multi-extent) * 1 success, 0 record ignored (not an error, can be a relocated dir), * < 0 error */ static int iso_file_source_new_ifs(IsoImageFilesystem *fs, IsoFileSource *parent, struct ecma119_dir_record *record, IsoFileSource **src, int flag) { int ret, ecma119_map, skip_nm = 0; struct stat atts; time_t recorded; _ImageFsData *fsdata; IsoFileSource *ifsrc = NULL; ImageFileSourceData *ifsdata = NULL; int namecont = 0; /* 1 if found a NM with CONTINUE flag */ char *name = NULL; /* 1 if found a SL with CONTINUE flag, * 2 if found a component with continue flag */ int linkdestcont = 0; char *linkdest = NULL; uint32_t relocated_dir = 0; unsigned char *aa_string = NULL; size_t aa_size = 0, aa_len = 0, prev_field = 0; int aa_done = 0; char *msg = NULL; uint8_t *buffer = NULL; char *cpt; int has_px = 0; #ifdef Libisofs_with_zliB uint8_t zisofs_alg[2], zisofs_hs4 = 0, zisofs_bsl2 = 0; uint32_t zisofs_usize = 0; #endif if (fs == NULL || fs->data == NULL || record == NULL || src == NULL) { ret = ISO_NULL_POINTER; goto ex; } fsdata = (_ImageFsData*)fs->data; memset(&atts, 0, sizeof(struct stat)); atts.st_nlink = 1; /* Set preliminary file type */ if (record->flags[0] & 0x02) { atts.st_mode = S_IFDIR; } else { atts.st_mode = S_IFREG; } /* * First of all, check for unsupported ECMA-119 features */ /* check for unsupported interleaved mode */ if (record->file_unit_size[0] || record->interleave_gap_size[0]) { iso_msg_submit(fsdata->msgid, ISO_UNSUPPORTED_ECMA119, 0, "Unsupported image. This image has at least one file recorded " "in interleaved mode. We do not support this mode, as we think " "it is not used. If you are reading this, then we are wrong :) " "Please contact libisofs developers, so we can fix this."); {ret = ISO_UNSUPPORTED_ECMA119; goto ex;} } /* TODO #00013 : check for unsupported flags when reading a dir record */ /* * If src is not-NULL, it refers to more extents of this file. We ensure * name matches, otherwise it means we are dealing with wrong image */ if (*src != NULL) { ImageFileSourceData* data = (*src)->data; char* new_name = get_name(fsdata, (char*)record->file_id, record->len_fi[0]); if (new_name == NULL) { iso_msg_submit(fsdata->msgid, ISO_WRONG_ECMA119, 0, "Cannot retrieve file name"); {ret = ISO_WRONG_ECMA119; goto ex;} } if (strcmp(new_name, data->name)) { iso_msg_submit(fsdata->msgid, ISO_WRONG_ECMA119, 0, "Multi-extent file lacks last entry."); free(new_name); {ret = ISO_WRONG_ECMA119; goto ex;} } free(new_name); } /* check for multi-extent */ if (record->flags[0] & 0x80) { iso_msg_debug(fsdata->msgid, "Found multi-extent file"); /* * Directory entries can only have one section (ECMA-119, 6.8.1) */ if ((record->flags[0] & 0x02) || (flag & 1)) { iso_msg_submit(fsdata->msgid, ISO_WRONG_ECMA119, 0, "Directories with more than one section are not allowed."); {ret = ISO_WRONG_ECMA119; goto ex;} } if (*src == NULL) { ifsdata = calloc(1, sizeof(ImageFileSourceData)); if (ifsdata == NULL) { ret = ISO_OUT_OF_MEM; goto ifs_cleanup; } ifsrc = calloc(1, sizeof(IsoFileSource)); if (ifsrc == NULL) { ret = ISO_OUT_OF_MEM; goto ifs_cleanup; } ifsrc->data = ifsdata; ifsdata->name = get_name(fsdata, (char*)record->file_id, record->len_fi[0]); if (ifsdata->name == NULL) { iso_msg_submit(fsdata->msgid, ISO_WRONG_ECMA119, 0, "Cannot retrieve file name"); ret = ISO_WRONG_ECMA119; goto ifs_cleanup; } *src = ifsrc; } else { ifsdata = (*src)->data; } /* store current extent */ ifsdata->sections = realloc(ifsdata->sections, (1 + ifsdata->nsections) * sizeof(struct iso_file_section)); if (ifsdata->sections == NULL) { free(ifsdata->name); ret = ISO_OUT_OF_MEM; goto ifs_cleanup; } ifsdata->sections[ifsdata->nsections].block = iso_read_bb(record->block, 4, NULL) + record->len_xa[0]; ifsdata->sections[ifsdata->nsections].size = iso_read_bb(record->length, 4, NULL); ifsdata->info.st_size += (off_t) ifsdata->sections[ifsdata->nsections].size; ifsdata->nsections++; {ret = 2; goto ex;} } /* * The idea is to read all the RR entries (if we want to do that and RR * extensions exist on image), storing the info we want from that. * Then, we need some sanity checks. * Finally, we select what kind of node it is, and set values properly. */ if (fsdata->rr) { struct susp_sys_user_entry *sue; SuspIterator *iter; iter = susp_iter_new(fsdata->src, record, fsdata->len_skp, fsdata->msgid); if (iter == NULL) { {ret = ISO_OUT_OF_MEM; goto ex;} } while ((ret = susp_iter_next(iter, &sue)) > 0) { /* ignore entries from different version */ if (sue->version[0] != 1) continue; if (SUSP_SIG(sue, 'P', 'X')) { has_px = 1; ret = read_rr_PX(sue, &atts); if (ret < 0) { /* notify and continue */ ret = iso_rr_msg_submit(fsdata, 0, ISO_WRONG_RR_WARN, ret, "Invalid PX entry"); fsdata->px_ino_status |= 8; } if (ret == 2) { if (fsdata->inode_counter < atts.st_ino) fsdata->inode_counter = atts.st_ino; fsdata->px_ino_status |= 1; } else { fsdata->px_ino_status |= 2; } } else if (SUSP_SIG(sue, 'T', 'F')) { ret = read_rr_TF(sue, &atts); if (ret < 0) { /* notify and continue */ ret = iso_rr_msg_submit(fsdata, 1, ISO_WRONG_RR_WARN, ret, "Invalid TF entry"); } } else if (SUSP_SIG(sue, 'N', 'M')) { if (skip_nm) continue; /* in NM error bailout mode */ if (name != NULL && namecont == 0) { /* ups, RR standard violation */ ret = iso_rr_msg_submit(fsdata, 2, ISO_WRONG_RR_WARN, 0, "New NM entry found without previous" "CONTINUE flag. Ignored"); skip_nm = 1; continue; } ret = read_rr_NM(sue, &name, &namecont); if (ret < 0) { /* notify and continue */ ret = iso_rr_msg_submit(fsdata, 3, ISO_WRONG_RR_WARN, ret, "Invalid NM entry"); continue; } if (name != NULL) if (strlen(name) > 4095) { /* Preliminarily truncate totally oversized name */ ret = iso_rr_msg_submit(fsdata, 3, ISO_WRONG_RR_WARN, ret, "Totally oversized NM list"); skip_nm = 1; continue; } #ifdef Libisofs_syslinux_tesT if (name != NULL && !namecont) { struct device syslinux_dev; struct iso_sb_info syslinux_sbi; struct fs_info syslinux_fsi; char *syslinux_name = NULL; int syslinux_name_len; syslinux_dev.src = fsdata->src; memset(&(syslinux_sbi.root), 0, 256); syslinux_sbi.do_rr = 1; syslinux_sbi.susp_skip = 0; syslinux_fsi.fs_dev = &syslinux_dev; syslinux_fsi.fs_info = &syslinux_sbi; ret = susp_rr_get_nm(&syslinux_fsi, (char *) record, &syslinux_name, &syslinux_name_len); if (ret == 1) { if (name == NULL || syslinux_name == NULL) fprintf(stderr, "################ Hoppla. NULL\n"); else if(strcmp(syslinux_name, name) != 0) fprintf(stderr, "################ libisofs '%s' != '%s' susp_rr_get_nm()\n", name, syslinux_name); } else if (ret == 0) { fprintf(stderr, "################ '%s' not found by susp_rr_get_nm()\n", name); } else { fprintf(stderr, "################ 'susp_rr_get_nm() returned error\n"); } if (syslinux_name != NULL) free(syslinux_name); } #endif /* Libisofs_syslinux_tesT */ } else if (SUSP_SIG(sue, 'S', 'L')) { if (linkdest != NULL && linkdestcont == 0) { /* ups, RR standard violation */ ret = iso_rr_msg_submit(fsdata, 4, ISO_WRONG_RR_WARN, 0, "New SL entry found without previous" "CONTINUE flag. Ignored"); continue; } ret = read_rr_SL(sue, &linkdest, &linkdestcont); if (ret < 0) { /* notify and continue */ ret = iso_rr_msg_submit(fsdata, 5, ISO_WRONG_RR_WARN, ret, "Invalid SL entry"); } } else if (SUSP_SIG(sue, 'R', 'E')) { /* * this directory entry refers to a relocated directory. * We simply ignore it, as it will be correctly handled * when found the CL */ susp_iter_free(iter); free(name); {ret = 0; goto ex;} /* it's not an error */ } else if (SUSP_SIG(sue, 'C', 'L')) { /* * This entry is a placeholder for a relocated dir. * We need to ignore other entries, with the exception of NM. * Then we create a directory node that represents the * relocated dir, and iterate over its children. */ relocated_dir = iso_read_bb(sue->data.CL.child_loc, 4, NULL); if (relocated_dir == 0) { ret = iso_rr_msg_submit(fsdata, 6, ISO_WRONG_RR, 0, "Invalid SL entry, no child location"); break; } } else if (SUSP_SIG(sue, 'P', 'N')) { ret = read_rr_PN(sue, &atts); if (ret < 0) { /* notify and continue */ ret = iso_rr_msg_submit(fsdata, 7, ISO_WRONG_RR_WARN, ret, "Invalid PN entry"); } } else if (SUSP_SIG(sue, 'S', 'F')) { ret = iso_rr_msg_submit(fsdata, 8, ISO_UNSUPPORTED_RR, 0, "Sparse files not supported."); break; } else if (SUSP_SIG(sue, 'R', 'R')) { /* This was an optional flag byte in RRIP 1.09 which told the reader what other RRIP fields to expect. mkisofs emits it. We don't. */ continue; } else if (SUSP_SIG(sue, 'S', 'P')) { /* * Ignore this, to prevent the hint message, if we are dealing * with root node (SP is only valid in "." of root node) */ if (!(flag & 1)) { /* notify and continue */ ret = iso_rr_msg_submit(fsdata, 9, ISO_WRONG_RR, 0, "SP entry found in a directory entry other " "than '.' entry of root node"); } continue; } else if (SUSP_SIG(sue, 'E', 'R')) { /* * Ignore this, to prevent the hint message, if we are dealing * with root node (ER is only valid in "." of root node) */ if (!(flag & 1)) { /* notify and continue */ ret = iso_rr_msg_submit(fsdata, 10, ISO_WRONG_RR, 0, "ER entry found in a directory entry other " "than '.' entry of root node"); } continue; /* Need to read AA resp. AL in any case so it is available for S_IRWXG mapping in case that fsdata->aaip_load != 1 */ } else if (SUSP_SIG(sue, 'A', 'A')) { ret = read_aaip_AA(sue, &aa_string, &aa_size, &aa_len, &prev_field, &aa_done, 0); if (ret < 0) { /* notify and continue */ ret = iso_rr_msg_submit(fsdata, 11, ISO_WRONG_RR_WARN, ret, "Invalid AA entry"); continue; } } else if (SUSP_SIG(sue, 'A', 'L')) { ret = read_aaip_AL(sue, &aa_string, &aa_size, &aa_len, &prev_field, &aa_done, 0); if (ret < 0) { /* notify and continue */ ret = iso_rr_msg_submit(fsdata, 12, ISO_WRONG_RR_WARN, ret, "Invalid AL entry"); continue; } #ifdef Libisofs_with_zliB } else if (SUSP_SIG(sue, 'Z', 'F')) { ret = read_zisofs_ZF(sue, zisofs_alg, &zisofs_hs4, &zisofs_bsl2, &zisofs_usize, 0); if (ret < 0 || zisofs_alg[0] != 'p' || zisofs_alg[1] != 'z') { /* notify and continue */ ret = iso_rr_msg_submit(fsdata, 13, ISO_WRONG_RR_WARN, ret, "Invalid ZF entry"); zisofs_hs4 = 0; continue; } #endif /* Libisofs_with_zliB */ /* This message is inflationary */ /* } else { ret = iso_msg_submit(fsdata->msgid, ISO_SUSP_UNHANDLED, 0, "Unhandled SUSP entry %c%c.", sue->sig[0], sue->sig[1]); */ } } susp_iter_free(iter); /* check for RR problems */ if (ret < 0) { /* error was already submitted above */ iso_msg_debug(fsdata->msgid, "Error parsing RR entries"); } else if (!relocated_dir && atts.st_mode == (mode_t) 0 ) { ret = iso_rr_msg_submit(fsdata, 14, ISO_WRONG_RR, 0, "Mandatory " "Rock Ridge PX entry is not present or it " "contains invalid values."); } else { /* ensure both name and link dest are finished */ if (namecont != 0) { ret = iso_rr_msg_submit(fsdata, 15, ISO_WRONG_RR, 0, "Incomplete Rock Ridge name, last NM entry continues"); } if (linkdestcont != 0) { ret = iso_rr_msg_submit(fsdata, 16, ISO_WRONG_RR, 0, "Incomplete link destination, last SL entry continues"); } } if (ret < 0) { free(name); goto ex; } /* convert name to needed charset */ if (strcmp(fsdata->input_charset, fsdata->local_charset) && name) { /* we need to convert name charset */ char *newname = NULL; ret = strconv(name, fsdata->input_charset, fsdata->local_charset, &newname); if (ret < 0) { /* its just a hint message */ LIBISO_FREE_MEM(msg); LIBISO_ALLOC_MEM(msg, char, 160); sprintf(msg, "Cannot convert from charset %.40s to %.40s", fsdata->input_charset, fsdata->local_charset); ret = iso_rr_msg_submit(fsdata, 17, ISO_FILENAME_WRONG_CHARSET, ret, msg); free(newname); if (ret < 0) { free(name); goto ex; } } else { free(name); name = newname; } } /* convert link destination to needed charset */ if (strcmp(fsdata->input_charset, fsdata->local_charset) && linkdest) { /* we need to convert name charset */ char *newlinkdest = NULL; ret = strconv(linkdest, fsdata->input_charset, fsdata->local_charset, &newlinkdest); if (ret < 0) { LIBISO_FREE_MEM(msg); LIBISO_ALLOC_MEM(msg, char, 160); sprintf(msg, "Charset conversion error. Cannot convert from %.40s to %.40s", fsdata->input_charset, fsdata->local_charset); ret = iso_rr_msg_submit(fsdata, 17, ISO_FILENAME_WRONG_CHARSET, ret, msg); free(newlinkdest); if (ret < 0) { free(name); goto ex; } } else { free(linkdest); linkdest = newlinkdest; } } } else { /* RR extensions are not read / used */ atts.st_gid = fsdata->gid; atts.st_uid = fsdata->uid; if (record->flags[0] & 0x02) { atts.st_mode = S_IFDIR | fsdata->dir_mode; } else { atts.st_mode = S_IFREG | fsdata->file_mode; } } if (!has_px) { fsdata->px_ino_status |= 4; } /* * if we haven't RR extensions, or no NM entry is present, * we use the name in directory record */ if (!name) { size_t len; if (record->len_fi[0] == 1 && record->file_id[0] == 0) { /* "." entry, we can call this for root node, so... */ if (!(atts.st_mode & S_IFDIR)) { ret = iso_msg_submit(fsdata->msgid, ISO_WRONG_ECMA119, 0, "Wrong ISO file name. \".\" not dir"); goto ex; } } else { name = get_name(fsdata, (char*)record->file_id, record->len_fi[0]); if (name == NULL) { ret = iso_msg_submit(fsdata->msgid, ISO_WRONG_ECMA119, 0, "Cannot retrieve file name"); goto ex; } /* remove trailing version number */ len = strlen(name); ecma119_map = fsdata->ecma119_map; if (fsdata->iso_root_block == fsdata->svd_root_block) ecma119_map = 0; if (ecma119_map >= 1 && ecma119_map <= 3 && len > 2 && name[len-2] == ';' && name[len-1] == '1') { if (len > 3 && name[len-3] == '.') { /* * the "." is mandatory, so in most cases is included only * for standard compliance */ name[len-3] = '\0'; } else { name[len-2] = '\0'; } } if (ecma119_map == 2 || ecma119_map == 3) { for (cpt = name; *cpt != 0; cpt++) { if (ecma119_map == 2) { if (islower(*cpt)) *cpt = toupper(*cpt); } else { if (isupper(*cpt)) *cpt = tolower(*cpt); } } } } } if (name != NULL) { if ((int) strlen(name) > fsdata->truncate_length) { ret = iso_truncate_rr_name(fsdata->truncate_mode, fsdata->truncate_length, name, 0); if (ret < 0) goto ex; } } if (relocated_dir) { /* * We are dealing with a placeholder for a relocated dir. * Thus, we need to read attributes for this directory from the "." * entry of the relocated dir. */ LIBISO_ALLOC_MEM(buffer, uint8_t, BLOCK_SIZE); ret = fsdata->src->read_block(fsdata->src, relocated_dir, buffer); if (ret < 0) { goto ex; } ret = iso_file_source_new_ifs(fs, parent, (struct ecma119_dir_record*) buffer, src, 0); if (ret <= 0) { goto ex; } /* but the real name is the name of the placeholder */ ifsdata = (ImageFileSourceData*) (*src)->data; ifsdata->name = name; {ret = ISO_SUCCESS; goto ex;} } /* Production of missing inode numbers is delayed until the image is complete. Then all nodes which shall get a new inode number will be served. */ /* * if we haven't RR extensions, or a needed TF time stamp is not present, * we use plain iso recording time */ recorded = iso_datetime_read_7(record->recording_time); if (atts.st_atime == (time_t) 0) { atts.st_atime = recorded; } if (atts.st_ctime == (time_t) 0) { atts.st_ctime = recorded; } if (atts.st_mtime == (time_t) 0) { atts.st_mtime = recorded; } /* the size is read from iso directory record */ atts.st_size = iso_read_bb(record->length, 4, NULL); /* Fill last entries */ atts.st_dev = fsdata->id; atts.st_blksize = BLOCK_SIZE; atts.st_blocks = DIV_UP(atts.st_size, BLOCK_SIZE); /* TODO #00014 : more sanity checks to ensure dir record info is valid */ if (S_ISLNK(atts.st_mode) && (linkdest == NULL)) { ret = iso_rr_msg_submit(fsdata, 18, ISO_WRONG_RR, 0, "Link without destination."); free(name); goto ex; } /* ok, we can now create the file source */ if (*src == NULL) { ifsdata = calloc(1, sizeof(ImageFileSourceData)); if (ifsdata == NULL) { ret = ISO_OUT_OF_MEM; goto ifs_cleanup; } ifsrc = calloc(1, sizeof(IsoFileSource)); if (ifsrc == NULL) { ret = ISO_OUT_OF_MEM; goto ifs_cleanup; } } else { ifsdata = (*src)->data; ifsrc = (*src); free(ifsdata->name); /* we will assign a new one */ ifsdata->name = NULL; atts.st_size += (off_t)ifsdata->info.st_size; if (ifsdata->aa_string != NULL) free(ifsdata->aa_string); ifsdata->aa_string = NULL; } /* fill data */ ifsdata->fs = fs; iso_filesystem_ref(fs); if (parent != NULL) { ifsdata->parent = parent; iso_file_source_ref(parent); } ifsdata->info = atts; ifsdata->name = name; ifsdata->aa_string = aa_string; #ifdef Libisofs_with_zliB if (zisofs_hs4 > 0) { ifsdata->header_size_div4 = zisofs_hs4; ifsdata->block_size_log2 = zisofs_bsl2; ifsdata->uncompressed_size = zisofs_usize; } else { ifsdata->header_size_div4 = 0; } #endif /* save extents */ ifsdata->sections = realloc(ifsdata->sections, (1 + ifsdata->nsections) * sizeof(struct iso_file_section)); if (ifsdata->sections == NULL) { free(ifsdata->name); ret = ISO_OUT_OF_MEM; goto ifs_cleanup; } ifsdata->sections[ifsdata->nsections].block = iso_read_bb(record->block, 4, NULL) + record->len_xa[0]; ifsdata->sections[ifsdata->nsections].size = iso_read_bb(record->length, 4, NULL); ifsdata->nsections++; if (S_ISLNK(atts.st_mode)) { ifsdata->data.content = linkdest; } ifsrc->class = &ifs_class; ifsrc->data = ifsdata; ifsrc->refcount = 1; *src = ifsrc; {ret = ISO_SUCCESS; goto ex;} ifs_cleanup: ; free(name); free(linkdest); free(ifsdata); free(ifsrc); ex:; LIBISO_FREE_MEM(msg); LIBISO_FREE_MEM(buffer); return ret; } static int ifs_get_root(IsoFilesystem *fs, IsoFileSource **root) { int ret; _ImageFsData *data; uint8_t *buffer = NULL; if (fs == NULL || fs->data == NULL || root == NULL) { ret = ISO_NULL_POINTER; goto ex; } LIBISO_ALLOC_MEM(buffer, uint8_t, BLOCK_SIZE); data = (_ImageFsData*)fs->data; /* open the filesystem */ ret = ifs_fs_open((IsoImageFilesystem*)fs); if (ret < 0) { goto ex; } /* read extend for root record */ ret = data->src->read_block(data->src, data->iso_root_block, buffer); if (ret < 0) { ifs_fs_close((IsoImageFilesystem*)fs); goto ex; } /* get root attributes from "." entry */ *root = NULL; ret = iso_file_source_new_ifs((IsoImageFilesystem*)fs, NULL, (struct ecma119_dir_record*) buffer, root, 1); ifs_fs_close((IsoImageFilesystem*)fs); ex:; LIBISO_FREE_MEM(buffer); return ret; } /** * Find a file inside a node. * * @param file * it is not modified if requested file is not found * @return * 1 success, 0 not found, < 0 error */ static int ifs_get_file(IsoFileSource *dir, const char *name, IsoFileSource **file) { int ret; IsoFileSource *src; ret = iso_file_source_open(dir); if (ret < 0) { return ret; } while ((ret = iso_file_source_readdir(dir, &src)) == 1) { char *fname = iso_file_source_get_name(src); if (!strcmp(name, fname)) { free(fname); *file = src; ret = ISO_SUCCESS; break; } free(fname); iso_file_source_unref(src); } iso_file_source_close(dir); return ret; } static int ifs_get_by_path(IsoFilesystem *fs, const char *path, IsoFileSource **file) { int ret; IsoFileSource *src = NULL; char *ptr, *brk_info, *component; if (fs == NULL || fs->data == NULL || path == NULL || file == NULL) { return ISO_NULL_POINTER; } if (path[0] != '/') { /* only absolute paths supported */ return ISO_FILE_BAD_PATH; } /* open the filesystem */ ret = ifs_fs_open((IsoImageFilesystem*)fs); if (ret < 0) { return ret; } ret = ifs_get_root(fs, &src); if (ret < 0) { return ret; } if (!strcmp(path, "/")) { /* we are looking for root */ *file = src; ret = ISO_SUCCESS; goto get_path_exit; } ptr = strdup(path); if (ptr == NULL) { iso_file_source_unref(src); ret = ISO_OUT_OF_MEM; goto get_path_exit; } component = strtok_r(ptr, "/", &brk_info); while (component) { IsoFileSource *child = NULL; ImageFileSourceData *fdata; fdata = src->data; if (!S_ISDIR(fdata->info.st_mode)) { ret = ISO_FILE_BAD_PATH; break; } ret = ifs_get_file(src, component, &child); iso_file_source_unref(src); src = NULL; if (ret <= 0) { break; } src = child; component = strtok_r(NULL, "/", &brk_info); } free(ptr); if (ret < 0) { if (src != NULL) iso_file_source_unref(src); } else if (ret == 0) { ret = ISO_FILE_DOESNT_EXIST; } else { *file = src; } get_path_exit:; ifs_fs_close((IsoImageFilesystem*)fs); return ret; } unsigned int ifs_get_id(IsoFilesystem *fs) { return ISO_IMAGE_FS_ID; } static int ifs_fs_open(IsoImageFilesystem *fs) { _ImageFsData *data; if (fs == NULL || fs->data == NULL) { return ISO_NULL_POINTER; } data = (_ImageFsData*)fs->data; if (data->open_count == 0) { /* we need to actually open the data source */ int res = data->src->open(data->src); if (res < 0) { return res; } } ++data->open_count; return ISO_SUCCESS; } static int ifs_fs_close(IsoImageFilesystem *fs) { _ImageFsData *data; if (fs == NULL || fs->data == NULL) { return ISO_NULL_POINTER; } data = (_ImageFsData*)fs->data; if (--data->open_count == 0) { /* we need to actually close the data source */ return data->src->close(data->src); } return ISO_SUCCESS; } static void ifs_fs_free(IsoFilesystem *fs) { _ImageFsData *data; data = (_ImageFsData*) fs->data; /* close data source if already openned */ if (data->open_count > 0) { data->src->close(data->src); } /* free our ref to datasource */ iso_data_source_unref(data->src); /* free volume atts */ free(data->volset_id); free(data->volume_id); free(data->publisher_id); free(data->data_preparer_id); free(data->system_id); free(data->application_id); free(data->copyright_file_id); free(data->abstract_file_id); free(data->biblio_file_id); free(data->creation_time); free(data->modification_time); free(data->expiration_time); free(data->effective_time); free(data->input_charset); free(data->local_charset); if(data->catcontent != NULL) free(data->catcontent); free(data); } /** * Read the SUSP system user entries of the "." entry of the root directory, * indentifying when Rock Ridge extensions are being used. * * @return * 1 success, 0 ignored, < 0 error */ static int read_root_susp_entries(_ImageFsData *data, uint32_t block) { int ret; unsigned char *buffer = NULL; struct ecma119_dir_record *record; struct susp_sys_user_entry *sue; SuspIterator *iter; LIBISO_ALLOC_MEM(buffer, unsigned char, 2048); ret = data->src->read_block(data->src, block, buffer); if (ret < 0) { goto ex; } /* record will be the "." directory entry for the root record */ record = (struct ecma119_dir_record *)buffer; #ifdef Libisofs_syslinux_tesT { struct device syslinux_dev; struct iso_sb_info syslinux_sbi; struct fs_info syslinux_fsi; syslinux_dev.src = data->src; memcpy(&(syslinux_sbi.root), (char *) record, 256); syslinux_sbi.do_rr = 1; syslinux_sbi.susp_skip = 0; syslinux_fsi.fs_dev = &syslinux_dev; syslinux_fsi.fs_info = &syslinux_sbi; ret = susp_rr_check_signatures(&syslinux_fsi, 1); fprintf(stderr, "--------- susp_rr_check_signatures == %d , syslinux_sbi.do_rr == %d\n", ret, syslinux_sbi.do_rr); } #endif /* Libisofs_syslinux_tesT */ /* * TODO #00015 : take care of CD-ROM XA discs when reading SP entry * SUSP specification claims that for CD-ROM XA the SP entry * is not at position BP 1, but at BP 15. Is that used? * In that case, we need to set info->len_skp to 15!! */ iter = susp_iter_new(data->src, record, data->len_skp, data->msgid); if (iter == NULL) { ret = ISO_OUT_OF_MEM; goto ex; } /* first entry must be an SP system use entry */ ret = susp_iter_next(iter, &sue); if (ret < 0) { /* error */ susp_iter_free(iter); goto ex; } else if (ret == 0 || !SUSP_SIG(sue, 'S', 'P') ) { iso_msg_debug(data->msgid, "SUSP/RR is not being used."); susp_iter_free(iter); {ret = ISO_SUCCESS; goto ex;} } /* it is a SP system use entry */ if (sue->version[0] != 1 || sue->data.SP.be[0] != 0xBE || sue->data.SP.ef[0] != 0xEF) { susp_iter_free(iter); ret = iso_msg_submit(data->msgid, ISO_UNSUPPORTED_SUSP, 0, "SUSP SP system use entry seems to be wrong. " "Ignoring Rock Ridge Extensions."); goto ex; } iso_msg_debug(data->msgid, "SUSP/RR is being used."); /* * The LEN_SKP field, defined in IEEE 1281, SUSP. 5.3, specifies the * number of bytes to be skipped within each System Use field. * I think this will be always 0, but given that support this standard * feature is easy... */ data->len_skp = sue->data.SP.len_skp[0]; /* * Ok, now search for ER entry. * Just notice that the attributes for root dir are read elsewhere. * * TODO #00016 : handle non RR ER entries * * if several ER are present, we need to identify the position of * what refers to RR, and then look for corresponding ES entry in * each directory record. I have not implemented this (it's not used, * no?), but if we finally need it, it can be easily implemented in * the iterator, transparently for the rest of the code. */ while ((ret = susp_iter_next(iter, &sue)) > 0) { /* ignore entries from different version */ if (sue->version[0] != 1) continue; if (SUSP_SIG(sue, 'E', 'R')) { /* * it seems that Rock Ridge can be identified with any * of the following */ if ( sue->data.ER.len_id[0] == 10 && !strncmp((char*)sue->data.ER.ext_id, "RRIP_1991A", 10) ) { iso_msg_debug(data->msgid, "Suitable Rock Ridge ER found. Version 1.10."); data->rr_version = RR_EXT_110; } else if ( (sue->data.ER.len_id[0] == 10 && !strncmp((char*)sue->data.ER.ext_id, "IEEE_P1282", 10)) || (sue->data.ER.len_id[0] == 9 && !strncmp((char*)sue->data.ER.ext_id, "IEEE_1282", 9)) ) { iso_msg_debug(data->msgid, "Suitable Rock Ridge ER found. Version 1.12."); data->rr_version = RR_EXT_112; } else if (sue->data.ER.len_id[0] == 9 && (strncmp((char*)sue->data.ER.ext_id, "AAIP_0002", 9) == 0 || strncmp((char*)sue->data.ER.ext_id, "AAIP_0100", 9) == 0 || strncmp((char*)sue->data.ER.ext_id, "AAIP_0200", 9) == 0)) { /* Tolerate AAIP ER even if not supported */ iso_msg_debug(data->msgid, "Suitable AAIP ER found."); if (strncmp((char*)sue->data.ER.ext_id, "AAIP_0200", 9) == 0) data->aaip_version = 200; else if (((char*)sue->data.ER.ext_id)[6] == '1') data->aaip_version = 100; else data->aaip_version = 2; if (!data->aaip_load) iso_msg_submit(data->msgid, ISO_AAIP_IGNORED, 0, "Identifier for extension AAIP found, but loading is not enabled."); } else { ret = iso_msg_submit(data->msgid, ISO_SUSP_MULTIPLE_ER, 0, "Unknown Extension Signature found in ER.\n" "It will be ignored, but can cause problems in " "image reading. Please notify us about this."); if (ret < 0) { break; } } } } susp_iter_free(iter); if (ret < 0) { goto ex; } ret = ISO_SUCCESS; ex: LIBISO_FREE_MEM(buffer); return ret; } static int read_pvd_block(IsoDataSource *src, uint32_t block, uint8_t *buffer, uint32_t *image_size) { int ret; struct ecma119_pri_vol_desc *pvm; ret = src->read_block(src, block, buffer); if (ret < 0) return ret; pvm = (struct ecma119_pri_vol_desc *)buffer; /* sanity checks */ if (pvm->vol_desc_type[0] != 1 || pvm->vol_desc_version[0] != 1 || strncmp((char*)pvm->std_identifier, "CD001", 5) || pvm->file_structure_version[0] != 1) { return ISO_WRONG_PVD; } if (image_size != NULL) *image_size = iso_read_bb(pvm->vol_space_size, 4, NULL); return ISO_SUCCESS; } static int read_pvm(_ImageFsData *data, uint32_t block) { int ret; struct ecma119_pri_vol_desc *pvm; struct ecma119_dir_record *rootdr; uint8_t *buffer = NULL; LIBISO_ALLOC_MEM(buffer, uint8_t, BLOCK_SIZE); ret = read_pvd_block(data->src, block, buffer, NULL); if (ret < 0) goto ex; /* ok, it is a valid PVD */ pvm = (struct ecma119_pri_vol_desc *)buffer; /* fill volume attributes */ /* TODO take care of input charset */ data->volset_id = iso_util_strcopy_untail((char*)pvm->vol_set_id, 128); data->volume_id = iso_util_strcopy_untail((char*)pvm->volume_id, 32); data->publisher_id = iso_util_strcopy_untail((char*)pvm->publisher_id, 128); data->data_preparer_id = iso_util_strcopy_untail((char*)pvm->data_prep_id, 128); data->system_id = iso_util_strcopy_untail((char*)pvm->system_id, 32); data->application_id = iso_util_strcopy_untail((char*)pvm->application_id, 128); data->copyright_file_id = iso_util_strcopy_untail((char*) pvm->copyright_file_id, 37); data->abstract_file_id = iso_util_strcopy_untail((char*) pvm->abstract_file_id, 37); data->biblio_file_id = iso_util_strcopy_untail((char*) pvm->bibliographic_file_id, 37); if (data->copyright_file_id[0] == '_' && data->copyright_file_id[1] == 0 && data->abstract_file_id[0] == '_' && data->abstract_file_id[1] == 0 && data->biblio_file_id[0] == '_' && data->biblio_file_id[1] == 0) { /* This is bug output from libisofs <= 0.6.23 . The texts mean file names and should have been empty to indicate that there are no such files. It is obvious that not all three roles can be fulfilled by one file "_" so that one cannot spoil anything by assuming them empty now. */ data->copyright_file_id[0] = 0; data->abstract_file_id[0] = 0; data->biblio_file_id[0] = 0; } data->creation_time = iso_util_strcopy_untail((char*) pvm->vol_creation_time, 17); data->modification_time = iso_util_strcopy_untail((char*) pvm->vol_modification_time, 17); data->expiration_time = iso_util_strcopy_untail((char*) pvm->vol_expiration_time, 17); data->effective_time = iso_util_strcopy_untail((char*) pvm->vol_effective_time, 17); data->nblocks = iso_read_bb(pvm->vol_space_size, 4, NULL); rootdr = (struct ecma119_dir_record*) pvm->root_dir_record; data->pvd_root_block = iso_read_bb(rootdr->block, 4, NULL) + rootdr->len_xa[0]; /* * TODO #00017 : take advantage of other atts of PVD * PVD has other things that could be interesting, but that don't have a * member in IsoImage, such as creation date. In a multisession disc, we * could keep the creation date and update the modification date, for * example. */ ret = ISO_SUCCESS; ex:; LIBISO_FREE_MEM(buffer); return ret; } /** * @return * 1 success, 0 ignored, < 0 error */ static int read_el_torito_boot_catalog(_ImageFsData *data, uint32_t block) { int ret, i, rx, last_done, idx, bufsize; struct el_torito_validation_entry *ve; struct el_torito_section_header *sh; struct el_torito_section_entry *entry; /* also usable as default_entry */ unsigned char *buffer = NULL, *rpt; LIBISO_ALLOC_MEM(buffer, unsigned char, BLOCK_SIZE); data->num_bootimgs = 0; data->catsize = 0; ret = data->src->read_block(data->src, block, buffer); if (ret < 0) { goto ex; } ve = (struct el_torito_validation_entry*)buffer; /* check if it is a valid catalog (TODO: check also the checksum)*/ if ( (ve->header_id[0] != 1) || (ve->key_byte1[0] != 0x55) || (ve->key_byte2[0] != 0xAA) ) { iso_msg_submit(data->msgid, ISO_WRONG_EL_TORITO, 0, "Wrong or damaged El-Torito Catalog. El-Torito info " "will be ignored."); {ret = ISO_WRONG_EL_TORITO; goto ex;} } /* check for a valid platform */ if (ve->platform_id[0] != 0 && ve->platform_id[0] != 0xef) { iso_msg_submit(data->msgid, ISO_UNSUPPORTED_EL_TORITO, 0, "Unsupported El-Torito platform. Only 80x86 and EFI are " "supported. El-Torito info will be ignored."); {ret = ISO_UNSUPPORTED_EL_TORITO; goto ex;} } /* ok, once we are here we assume it is a valid catalog */ /* parse the default entry */ entry = (struct el_torito_section_entry *)(buffer + 32); data->eltorito = 1; /* The Default Entry is declared mandatory */ data->catsize = 64; data->num_bootimgs = 1; data->platform_ids[0] = ve->platform_id[0]; memcpy(data->id_strings[0], ve->id_string, 24); memset(data->id_strings[0] + 24, 0, 4); data->boot_flags[0] = entry->boot_indicator[0] ? 1 : 0; data->media_types[0] = entry->boot_media_type[0]; data->partition_types[0] = entry->system_type[0]; data->load_segs[0] = iso_read_lsb(entry->load_seg, 2); data->load_sizes[0] = iso_read_lsb(entry->sec_count, 2); data->bootblocks[0] = iso_read_lsb(entry->block, 4); /* The Default Entry has no selection criterion */ memset(data->selection_crits[0], 0, 20); /* Read eventual more entries from the boot catalog */ last_done = 0; for (rx = 64; (buffer[rx] & 0xfe) == 0x90 && !last_done; rx += 32) { last_done = buffer[rx] & 1; /* Read Section Header */ /* >>> ts B10703 : load a new buffer if needed */; sh = (struct el_torito_section_header *) (buffer + rx); data->catsize += 32; for (i = 0; i < sh->num_entries[0]; i++) { rx += 32; data->catsize += 32; /* >>> ts B10703 : load a new buffer if needed */; if (data->num_bootimgs >= Libisofs_max_boot_imageS) { /* >>> ts B10703 : need to continue rather than abort */; iso_msg_submit(data->msgid, ISO_EL_TORITO_WARN, 0, "Too many boot images found. List truncated."); goto after_bootblocks; } /* Read bootblock from section entry */ entry = (struct el_torito_section_entry *)(buffer + rx); idx = data->num_bootimgs; data->platform_ids[idx] = sh->platform_id[0]; memcpy(data->id_strings[idx], sh->id_string, 28); data->boot_flags[idx] = entry->boot_indicator[0] ? 1 : 0; data->media_types[idx] = entry->boot_media_type[0]; data->partition_types[idx] = entry->system_type[0]; data->load_segs[idx] = iso_read_lsb(entry->load_seg, 2); data->load_sizes[idx] = iso_read_lsb(entry->sec_count, 2); data->bootblocks[idx] = iso_read_lsb(entry->block, 4); data->selection_crits[idx][0] = entry->selec_criteria[0]; memcpy(data->selection_crits[idx] + 1, entry->vendor_sc, 19); data->num_bootimgs++; } } after_bootblocks:; if(data->catsize > 0) { if(data->catcontent != NULL) free(data->catcontent); if(data->catsize > 10 * BLOCK_SIZE) data->catsize = 10 * BLOCK_SIZE; bufsize = data->catsize; if (bufsize % BLOCK_SIZE) bufsize += BLOCK_SIZE - (bufsize % BLOCK_SIZE); data->catcontent = calloc(bufsize , 1); if(data->catcontent == NULL) { data->catsize = 0; ret = ISO_OUT_OF_MEM; goto ex; } for(rx = 0; rx < bufsize; rx += BLOCK_SIZE) { rpt = (unsigned char *) (data->catcontent + rx); ret = data->src->read_block(data->src, block + rx / BLOCK_SIZE, rpt); if (ret < 0) goto ex; } } ret = ISO_SUCCESS; ex:; LIBISO_FREE_MEM(buffer); return ret; } /* @return 1= ok, checked, go on with loading 2= no checksum tags found, go on with loading <0= libisofs error especially ISO_SB_TREE_CORRUPTED */ static int iso_src_check_sb_tree(IsoDataSource *src, uint32_t start_lba, int flag) { int tag_type, ret; char *block = NULL, md5[16]; int desired = (1 << 2); void *ctx = NULL; uint32_t next_tag = 0, i; LIBISO_ALLOC_MEM(block, char, 2048); ret = iso_md5_start(&ctx); if (ret < 0) goto ex; if (start_lba == 0) desired |= (1 << 4); for (i = 0; i < 32; i++) { ret = src->read_block(src, start_lba + i, (uint8_t *) block); if (ret < 0) goto ex; ret = 0; if (i >= 16) ret = iso_util_eval_md5_tag(block, desired, start_lba + i, ctx, start_lba, &tag_type, &next_tag, 0); iso_md5_compute(ctx, block, 2048); if (ret == (int) ISO_MD5_TAG_COPIED) {/* growing without emulated TOC */ ret = 2; goto ex; } if (ret == (int) ISO_MD5_AREA_CORRUPTED || ret == (int) ISO_MD5_TAG_MISMATCH) ret = ISO_SB_TREE_CORRUPTED; if (ret < 0) goto ex; if (ret == 1) break; } if (i >= 32) { ret = 2; goto ex; } if (tag_type == 4) { /* Relocated Superblock: restart checking at real session start */ if (next_tag < 32) { /* Non plausible session_start address */ ret = ISO_SB_TREE_CORRUPTED; iso_msg_submit(-1, ret, 0, NULL); goto ex; } /* Check real session */ ret = iso_src_check_sb_tree(src, next_tag, 0); goto ex; } /* Go on with tree */ for (i++; start_lba + i <= next_tag; i++) { ret = src->read_block(src, start_lba + i, (uint8_t *) block); if (ret < 0) goto ex; if (start_lba + i < next_tag) iso_md5_compute(ctx, block, 2048); } ret = iso_util_eval_md5_tag(block, (1 << 3), start_lba + i - 1, ctx, start_lba, &tag_type, &next_tag, 0); if (ret == (int) ISO_MD5_AREA_CORRUPTED || ret == (int) ISO_MD5_TAG_MISMATCH) ret = ISO_SB_TREE_CORRUPTED; if (ret < 0) goto ex; ret = 1; ex: if (ctx != NULL) iso_md5_end(&ctx, md5); LIBISO_FREE_MEM(block); return ret; } int iso_image_filesystem_new(IsoDataSource *src, struct iso_read_opts *opts, int msgid, IsoImageFilesystem **fs) { int ret, i; uint32_t block; IsoImageFilesystem *ifs; _ImageFsData *data; uint8_t *buffer = NULL; if (src == NULL || opts == NULL || fs == NULL) { ret = ISO_NULL_POINTER; goto ex; } LIBISO_ALLOC_MEM(buffer, uint8_t, BLOCK_SIZE); data = calloc(1, sizeof(_ImageFsData)); if (data == NULL) { ret = ISO_OUT_OF_MEM; goto ex; } ifs = calloc(1, sizeof(IsoImageFilesystem)); if (ifs == NULL) { free(data); {ret = ISO_OUT_OF_MEM; goto ex;} } /* get our ref to IsoDataSource */ data->src = src; iso_data_source_ref(src); data->open_count = 0; data->catcontent = NULL; /* get an id for the filesystem */ data->id = ++fs_dev_id; /* fill data from opts */ data->gid = opts->gid; data->uid = opts->uid; data->file_mode = opts->file_mode & ~S_IFMT; data->dir_mode = opts->dir_mode & ~S_IFMT; data->msgid = msgid; data->aaip_load = !opts->noaaip; if (opts->nomd5 == 0) data->md5_load = 1; else if (opts->nomd5 == 2) data->md5_load = 2; else data->md5_load = 0; data->aaip_version = -1; data->make_new_ino = opts->make_new_ino; data->num_bootimgs = 0; for (i = 0; i < Libisofs_max_boot_imageS; i++) data->bootblocks[i] = 0; data->inode_counter = 0; data->px_ino_status = 0; data->rr_err_reported = 0; data->rr_err_repeated = 0; data->joliet_ucs2_failures = 0; data->local_charset = strdup(iso_get_local_charset(0)); if (data->local_charset == NULL) { ret = ISO_OUT_OF_MEM; LIBISO_FREE_MEM(data); data = NULL; goto fs_cleanup; } strncpy(ifs->type, "iso ", 4); ifs->data = data; ifs->refcount = 1; ifs->version = 0; ifs->get_root = ifs_get_root; ifs->get_by_path = ifs_get_by_path; ifs->get_id = ifs_get_id; ifs->open = ifs_fs_open; ifs->close = ifs_fs_close; ifs->free = ifs_fs_free; /* read Volume Descriptors and ensure it is a valid image */ if (data->md5_load == 1) { /* From opts->block on : check for superblock and tree tags */; ret = iso_src_check_sb_tree(src, opts->block, 0); if (ret < 0) { iso_msgs_submit(0, "Image loading aborted due to MD5 mismatch of image tree data", 0, "FAILURE", 0); iso_msgs_submit(0, "You may override this refusal by disabling MD5 checking", 0, "HINT", 0); goto fs_cleanup; } } /* 1. first, open the filesystem */ ifs_fs_open(ifs); /* 2. read primary volume description */ ret = read_pvm(data, opts->block + 16); if (ret < 0) { goto fs_cleanup; } /* 3. read next volume descriptors */ block = opts->block + 17; do { ret = src->read_block(src, block, buffer); if (ret < 0) { /* cleanup and exit */ goto fs_cleanup; } switch (buffer[0]) { case 0: /* boot record */ { struct ecma119_boot_rec_vol_desc *vol; vol = (struct ecma119_boot_rec_vol_desc*)buffer; /* some sanity checks */ if (strncmp((char*)vol->std_identifier, "CD001", 5) || vol->vol_desc_version[0] != 1 || strncmp((char*)vol->boot_sys_id, "EL TORITO SPECIFICATION", 23)) { iso_msg_submit(data->msgid, ISO_UNSUPPORTED_EL_TORITO, 0, "Unsupported Boot Vol. Desc. Only El-Torito " "Specification, Version 1.0 Volume " "Descriptors are supported. Ignoring boot info"); } else { data->catblock = iso_read_lsb(vol->boot_catalog, 4); ret = read_el_torito_boot_catalog(data, data->catblock); if (ret < 0 && ret != (int) ISO_UNSUPPORTED_EL_TORITO && ret != (int) ISO_WRONG_EL_TORITO) { goto fs_cleanup; } } } break; case 2: /* suplementary volume descritor */ { struct ecma119_sup_vol_desc *sup; struct ecma119_dir_record *root; sup = (struct ecma119_sup_vol_desc*)buffer; if (sup->esc_sequences[0] == 0x25 && sup->esc_sequences[1] == 0x2F && (sup->esc_sequences[2] == 0x40 || sup->esc_sequences[2] == 0x43 || sup->esc_sequences[2] == 0x45) ) { /* it's a Joliet Sup. Vol. Desc. */ iso_msg_debug(data->msgid, "Found Joliet extensions"); data->joliet = 1; root = (struct ecma119_dir_record*)sup->root_dir_record; data->svd_root_block = iso_read_bb(root->block, 4, NULL) + root->len_xa[0]; /* TODO #00019 : set IsoImage attribs from Joliet SVD? */ /* TODO #00020 : handle RR info in Joliet tree */ } else if (sup->vol_desc_version[0] == 2) { /* * It is an Enhanced Volume Descriptor, image is an * ISO 9660:1999 */ iso_msg_debug(data->msgid, "Found ISO 9660:1999"); data->iso1999 = 1; root = (struct ecma119_dir_record*)sup->root_dir_record; data->evd_root_block = iso_read_bb(root->block, 4, NULL) + root->len_xa[0]; /* TODO #00021 : handle RR info in ISO 9660:1999 tree */ } else { ret = iso_msg_submit(data->msgid, ISO_UNSUPPORTED_VD, 0, "Unsupported Sup. Vol. Desc found."); if (ret < 0) { goto fs_cleanup; } } } break; case 255: /* * volume set terminator * ignore, as it's checked in loop end condition */ break; default: iso_msg_submit(data->msgid, ISO_UNSUPPORTED_VD, 0, "Ignoring Volume descriptor %x.", buffer[0]); break; } block++; } while (buffer[0] != 255); /* 4. check if RR extensions are being used */ ret = read_root_susp_entries(data, data->pvd_root_block); if (ret < 0) { goto fs_cleanup; } /* user doesn't want to read RR extensions */ if (opts->norock) { data->rr = RR_EXT_NO; } else { data->rr = data->rr_version; } /* select what tree to read */ if (data->rr) { /* RR extensions are available */ if (!opts->nojoliet && opts->preferjoliet && data->joliet) { /* if user prefers joliet, that is used */ iso_msg_debug(data->msgid, "Reading Joliet extensions."); /* Although Joliet prescribes UCS-2BE, interpret names by its superset UTF-16BE in order to avoid conversion failures. */ data->input_charset = strdup("UTF-16BE"); data->rr = RR_EXT_NO; data->iso_root_block = data->svd_root_block; } else { /* RR will be used */ iso_msg_debug(data->msgid, "Reading Rock Ridge extensions."); data->iso_root_block = data->pvd_root_block; } } else { /* RR extensions are not available */ if (!opts->nojoliet && data->joliet) { /* joliet will be used */ iso_msg_debug(data->msgid, "Reading Joliet extensions."); data->input_charset = strdup("UTF-16BE"); data->iso_root_block = data->svd_root_block; } else if (!opts->noiso1999 && data->iso1999) { /* we will read ISO 9660:1999 */ iso_msg_debug(data->msgid, "Reading ISO-9660:1999 tree."); data->iso_root_block = data->evd_root_block; } else { /* default to plain iso */ iso_msg_debug(data->msgid, "Reading plain ISO-9660 tree."); data->iso_root_block = data->pvd_root_block; data->input_charset = strdup("ASCII"); } } data->truncate_mode = opts->truncate_mode; data->truncate_length = opts->truncate_length; data->ecma119_map = opts->ecma119_map; if (data->input_charset == NULL) { if (opts->input_charset != NULL) { data->input_charset = strdup(opts->input_charset); } else { data->input_charset = strdup(data->local_charset); } } if (data->input_charset == NULL) { ret = ISO_OUT_OF_MEM; goto fs_cleanup; } data->auto_input_charset = opts->auto_input_charset; /* and finally return. Note that we keep the DataSource opened */ *fs = ifs; {ret = ISO_SUCCESS; goto ex;} fs_cleanup: ; ifs_fs_free(ifs); free(ifs); ex:; LIBISO_FREE_MEM(buffer); return ret; } /* Take over aa_string from file source to node or discard it after making the necessary change in node->mode group permissions. node->mode must already be set. */ static int src_aa_to_node(IsoFileSource *src, IsoNode *node, int flag) { int ret; unsigned char *aa_string; ImageFileSourceData *data; _ImageFsData *fsdata; char *a_text = NULL, *d_text = NULL; data = (ImageFileSourceData*)src->data; fsdata = data->fs->data; /* Obtain ownership of eventual AAIP string */ ret = iso_file_source_get_aa_string(src, &aa_string, 1); if (ret != 1 || aa_string == NULL) return 1; if (fsdata->aaip_load == 1) { /* Attach aa_string to node */ ret = iso_node_add_xinfo(node, aaip_xinfo_func, aa_string); if (ret < 0) return ret; } else { /* Look for ACL and perform S_IRWXG mapping */ iso_aa_get_acl_text(aa_string, node->mode, &a_text, &d_text, 16); if (a_text != NULL) aaip_cleanout_st_mode(a_text, &(node->mode), 4 | 16); /* Dispose ACL a_text and d_text */ iso_aa_get_acl_text(aa_string, node->mode, &a_text, &d_text, 1 << 15); /* Dispose aa_string */ aaip_xinfo_func(aa_string, 1); } return 1; } static int image_builder_create_node(IsoNodeBuilder *builder, IsoImage *image, IsoFileSource *src, char *in_name, IsoNode **node) { int ret, idx, to_copy; struct stat info; IsoNode *new = NULL; IsoBoot *bootcat; char *name = NULL; char *dest = NULL; ImageFileSourceData *data; _ImageFsData *fsdata; #ifdef Libisofs_with_zliB /* Intimate friendship with this function in filters/zisofs.c */ int ziso_add_osiz_filter(IsoFile *file, uint8_t header_size_div4, uint8_t block_size_log2, uint32_t uncompressed_size, int flag); #endif /* Libisofs_with_zliB */ if (builder == NULL || src == NULL || node == NULL || src->data == NULL) { ret = ISO_NULL_POINTER; goto ex; } data = (ImageFileSourceData*)src->data; fsdata = data->fs->data; if (in_name == NULL) { name = iso_file_source_get_name(src); } else { name = strdup(in_name); if (name == NULL) { ret = ISO_OUT_OF_MEM; goto ex; } } /* get info about source */ ret = iso_file_source_lstat(src, &info); if (ret < 0) { goto ex; } switch (info.st_mode & S_IFMT) { case S_IFREG: { /* source is a regular file */ /* El-Torito images have only one section */ if (fsdata->eltorito && data->sections[0].block == fsdata->catblock) { if (image->bootcat->node != NULL) { ret = iso_msg_submit(image->id, ISO_EL_TORITO_WARN, 0, "More than one catalog node has been found. " "We can continue, but that could lead to " "problems"); if (ret < 0) goto ex; iso_node_unref((IsoNode*)image->bootcat->node); } /* we create a placeholder for the catalog instead of * a regular file */ new = calloc(1, sizeof(IsoBoot)); if (new == NULL) { ret = ISO_OUT_OF_MEM; goto ex; } bootcat = (IsoBoot *) new; bootcat->lba = data->sections[0].block; bootcat->size = info.st_size; if (bootcat->size > 10 * BLOCK_SIZE) bootcat->size = 10 * BLOCK_SIZE; bootcat->content = NULL; if (bootcat->size > 0) { bootcat->content = calloc(1, bootcat->size); if (bootcat->content == NULL) { ret = ISO_OUT_OF_MEM; goto ex; } to_copy = bootcat->size; if (bootcat->size > fsdata->catsize) to_copy = fsdata->catsize; memcpy(bootcat->content, fsdata->catcontent, to_copy); } /* and set the image node */ image->bootcat->node = bootcat; new->type = LIBISO_BOOT; new->refcount = 1; } else { IsoStream *stream; IsoFile *file; ret = iso_file_source_stream_new(src, &stream); if (ret < 0) goto ex; /* take a ref to the src, as stream has taken our ref */ iso_file_source_ref(src); file = calloc(1, sizeof(IsoFile)); if (file == NULL) { iso_stream_unref(stream); {ret = ISO_OUT_OF_MEM; goto ex;} } /* mark file as from old session */ file->from_old_session = 1; /* * and we set the sort weight based on the block on image, to * improve performance on image modifying. * * This was too obtrusive because it occupied the highest * possible weight ranks: * file->sort_weight = INT_MAX - data->sections[0].block; * * So a try to be more nice and rely on caching with tiles * of at least 16 blocks. This occupies a range within * the interval of 1 to 2 exp 28 = 268,435,456. * (Dividing each number separately saves from integer * rollover problems.) */ file->sort_weight = fsdata->nblocks / 16 - data->sections[0].block / 16 + 1; file->stream = stream; file->node.type = LIBISO_FILE; #ifdef Libisofs_with_zliB if (data->header_size_div4 > 0) { ret = ziso_add_osiz_filter(file, data->header_size_div4, data->block_size_log2, data->uncompressed_size, 0); if (ret < 0) { iso_stream_unref(stream); goto ex; } } #endif /* Libisofs_with_zliB */ new = (IsoNode*) file; new->refcount = 0; if (data->sections[0].size > 0) { for (idx = 0; idx < fsdata->num_bootimgs; idx++) if (fsdata->eltorito && data->sections[0].block == fsdata->bootblocks[idx]) break; } else { idx = fsdata->num_bootimgs; } if (idx < fsdata->num_bootimgs) { /* it is boot image node */ if (image->bootcat->bootimages[idx]->image != NULL) { /* idx is already occupied, try to find unoccupied one which has the same block address. */ for (; idx < fsdata->num_bootimgs; idx++) if (fsdata->eltorito && data->sections[0].block == fsdata->bootblocks[idx] && image->bootcat->bootimages[idx]->image == NULL) break; } if (idx >= fsdata->num_bootimgs) { ret = iso_msg_submit(image->id, ISO_EL_TORITO_WARN, 0, "More than one ISO node has been found for the same boot image."); if (ret < 0) { iso_stream_unref(stream); goto ex; } } else { /* and set the image node */ image->bootcat->bootimages[idx]->image = file; new->refcount++; } } } } break; case S_IFDIR: { /* source is a directory */ new = calloc(1, sizeof(IsoDir)); if (new == NULL) { {ret = ISO_OUT_OF_MEM; goto ex;} } new->type = LIBISO_DIR; new->refcount = 0; } break; case S_IFLNK: { /* source is a symbolic link */ IsoSymlink *link; LIBISO_ALLOC_MEM(dest, char, LIBISOFS_NODE_PATH_MAX); ret = iso_file_source_readlink(src, dest, LIBISOFS_NODE_PATH_MAX); if (ret < 0) { goto ex; } link = calloc(1, sizeof(IsoSymlink)); if (link == NULL) { {ret = ISO_OUT_OF_MEM; goto ex;} } link->dest = strdup(dest); link->node.type = LIBISO_SYMLINK; link->fs_id = ISO_IMAGE_FS_ID; link->st_dev = info.st_dev; link->st_ino = info.st_ino; new = (IsoNode*) link; new->refcount = 0; } break; case S_IFSOCK: case S_IFBLK: case S_IFCHR: case S_IFIFO: { /* source is an special file */ IsoSpecial *special; special = calloc(1, sizeof(IsoSpecial)); if (special == NULL) { ret = ISO_OUT_OF_MEM; goto ex; } special->dev = info.st_rdev; special->node.type = LIBISO_SPECIAL; special->fs_id = ISO_IMAGE_FS_ID; special->st_dev = info.st_dev; special->st_ino = info.st_ino; new = (IsoNode*) special; new->refcount = 0; } break; default: ret = ISO_BAD_ISO_FILETYPE; goto ex; } /* fill fields */ new->refcount++; new->name = name; name = NULL; new->mode = info.st_mode; new->uid = info.st_uid; new->gid = info.st_gid; new->atime = info.st_atime; new->mtime = info.st_mtime; new->ctime = info.st_ctime; new->hidden = 0; new->parent = NULL; new->next = NULL; ret = src_aa_to_node(src, new, 0); if (ret < 0) { goto ex; } /* Attach ino as xinfo if valid and no IsoStream is involved */ if (info.st_ino != 0 && (info.st_mode & S_IFMT) != S_IFREG && !fsdata->make_new_ino) { ret = iso_node_set_ino(new, info.st_ino, 0); if (ret < 0) goto ex; } *node = new; new = NULL; {ret = ISO_SUCCESS; goto ex;} ex:; if (name != NULL) free(name); if (new != NULL) iso_node_unref(new); LIBISO_FREE_MEM(dest); return ret; } /** * Create a new builder, that is exactly a copy of an old builder, but where * create_node() function has been replaced by image_builder_create_node. */ static int iso_image_builder_new(IsoNodeBuilder *old, IsoNodeBuilder **builder) { IsoNodeBuilder *b; if (builder == NULL) { return ISO_NULL_POINTER; } b = malloc(sizeof(IsoNodeBuilder)); if (b == NULL) { return ISO_OUT_OF_MEM; } b->refcount = 1; b->create_file_data = old->create_file_data; b->create_node_data = old->create_node_data; b->create_file = old->create_file; b->create_node = image_builder_create_node; b->free = old->free; *builder = b; return ISO_SUCCESS; } /** * Create a file source to access the El-Torito boot image, when it is not * accessible from the ISO filesystem. */ static int create_boot_img_filesrc(IsoImageFilesystem *fs, IsoImage *image, int idx, IsoFileSource **src) { int ret; struct stat atts; _ImageFsData *fsdata; IsoFileSource *ifsrc = NULL; ImageFileSourceData *ifsdata = NULL; if (fs == NULL || fs->data == NULL || src == NULL) { return ISO_NULL_POINTER; } fsdata = (_ImageFsData*)fs->data; memset(&atts, 0, sizeof(struct stat)); atts.st_mode = S_IFREG; atts.st_ino = img_give_ino_number(image, 0); atts.st_nlink = 1; /* * this is the greater problem. We don't know the size. For now, we * just use a single block of data. In a future, maybe we could figure out * a better idea. Another alternative is to use several blocks, that way * is less probable that we throw out valid data. */ atts.st_size = (off_t)BLOCK_SIZE; /* Fill last entries */ atts.st_dev = fsdata->id; atts.st_blksize = BLOCK_SIZE; atts.st_blocks = DIV_UP(atts.st_size, BLOCK_SIZE); /* ok, we can now create the file source */ ifsdata = calloc(1, sizeof(ImageFileSourceData)); if (ifsdata == NULL) { ret = ISO_OUT_OF_MEM; goto boot_fs_cleanup; } ifsrc = calloc(1, sizeof(IsoFileSource)); if (ifsrc == NULL) { ret = ISO_OUT_OF_MEM; goto boot_fs_cleanup; } ifsdata->sections = malloc(sizeof(struct iso_file_section)); if (ifsdata->sections == NULL) { ret = ISO_OUT_OF_MEM; goto boot_fs_cleanup; } /* fill data */ ifsdata->fs = fs; iso_filesystem_ref(fs); ifsdata->parent = NULL; ifsdata->info = atts; ifsdata->name = NULL; ifsdata->sections[0].block = fsdata->bootblocks[idx]; ifsdata->sections[0].size = BLOCK_SIZE; ifsdata->nsections = 1; ifsrc->class = &ifs_class; ifsrc->data = ifsdata; ifsrc->refcount = 1; *src = ifsrc; return ISO_SUCCESS; boot_fs_cleanup: ; free(ifsdata); free(ifsrc); return ret; } /** ??? >>> ts B00428 : should the max size become public ? */ #define Libisofs_boot_image_max_sizE (4096*1024) /** Guess which of the loaded boot images contain boot information tables. Set boot->seems_boot_info_table accordingly. */ static int iso_image_eval_boot_info_table(IsoImage *image, struct iso_read_opts *opts, IsoDataSource *src, uint32_t iso_image_size, int flag) { int i, j, ret, section_count, todo, chunk; uint32_t img_lba, img_size, boot_pvd_found, image_pvd, alleged_size; struct iso_file_section *sections = NULL; struct el_torito_boot_image *boot; uint8_t *boot_image_buf = NULL, boot_info_found[16], *buf = NULL; IsoStream *stream = NULL; IsoFile *boot_file; uint64_t blk; if (image->bootcat == NULL) {ret = ISO_SUCCESS; goto ex;} LIBISO_ALLOC_MEM(buf, uint8_t, BLOCK_SIZE); for (i = 0; i < image->bootcat->num_bootimages; i++) { boot = image->bootcat->bootimages[i]; boot_file = boot->image; boot->seems_boot_info_table = 0; boot->seems_grub2_boot_info = 0; boot->seems_isohybrid_capable = 0; img_size = iso_file_get_size(boot_file); if (img_size > Libisofs_boot_image_max_sizE || img_size < 64) continue; img_lba = 0; sections = NULL; ret = iso_file_get_old_image_sections(boot_file, §ion_count, §ions, 0); if (ret == 1 && section_count > 0) img_lba = sections[0].block; if (sections != NULL) { free(sections); sections = NULL; } if(img_lba == 0) continue; boot_image_buf = calloc(1, img_size); if (boot_image_buf == NULL) { ret = ISO_OUT_OF_MEM; goto ex; } stream = iso_file_get_stream(boot_file); ret = iso_stream_open(stream); if (ret < 0) { stream = NULL; goto ex; } for (todo = img_size; todo > 0; ) { if (todo > BLOCK_SIZE) chunk = BLOCK_SIZE; else chunk = todo; ret = iso_stream_read(stream, boot_image_buf + (img_size - todo), chunk); if (ret != chunk) { ret = (ret < 0) ? ret : (int) ISO_FILE_READ_ERROR; goto ex; } todo -= chunk; } iso_stream_close(stream); stream = NULL; memcpy(boot_info_found, boot_image_buf + 8, 16); boot_pvd_found = iso_read_lsb(boot_info_found, 4); image_pvd = (uint32_t) (opts->block + 16); /* Accomodate to eventually relocated superblock */ if (image_pvd != boot_pvd_found && image_pvd == 16 && boot_pvd_found < iso_image_size) { /* Check whether there is a PVD at boot_pvd_found and whether it bears the same image size */ ret = read_pvd_block(src, boot_pvd_found, buf, &alleged_size); if (ret == 1 && alleged_size + boot_pvd_found == iso_image_size + image_pvd) image_pvd = boot_pvd_found; } ret = make_boot_info_table(boot_image_buf, image_pvd, img_lba, img_size); if (ret < 0) goto ex; if (memcmp(boot_image_buf + 8, boot_info_found, 16) == 0) boot->seems_boot_info_table = 1; if (img_size >= Libisofs_grub2_elto_patch_poS + 8) { blk = 0; for (j = Libisofs_grub2_elto_patch_poS + 7; j >= Libisofs_grub2_elto_patch_poS; j--) blk = (blk << 8) | boot_image_buf[j]; if (blk == img_lba * 4 + Libisofs_grub2_elto_patch_offsT) boot->seems_grub2_boot_info = 1; } if (img_size >= 68 && boot->seems_boot_info_table) if (boot_image_buf[64] == 0xfb && boot_image_buf[65] == 0xc0 && boot_image_buf[66] == 0x78 && boot_image_buf[67] == 0x70) boot->seems_isohybrid_capable = 1; free(boot_image_buf); boot_image_buf = NULL; } ret = 1; ex:; if (boot_image_buf != NULL) free(boot_image_buf); if (stream != NULL) iso_stream_close(stream); LIBISO_FREE_MEM(buf); return ret; } static void issue_collision_warning_summary(size_t failures) { if (failures > ISO_IMPORT_COLL_WARN_MAX) { iso_msg_submit(-1, ISO_IMPORT_COLLISION, 0, "More file name collisions had to be resolved"); } if (failures > 0) { iso_msg_submit(-1, ISO_IMPORT_COLLISION, 0, "Sum of resolved file name collisions: %.f", (double) failures); } } /* Mark all non-matching combinations of head_per_cyl and sectors_per_head in the matches bitmap. This is a brute force approach to find the common intersections of up to 8 hyperbolas additionally intersected with the grid of integer coordinates {1..255}x{1..63}. Given the solution space size of only 14 bits, it seems inappropriate to employ any algebra. */ static void iso_scan_hc_sh(uint32_t lba, int c, int h, int s, uint8_t *matches) { int i, j; uint32_t res; /* fprintf(stderr, "iso_scan_hc_sh :%d = %4d/%3d/%2d :\n", lba, c, h, s); */ if (lba == ((uint32_t) s) - 1 && c == 0 && h == 0) /* trivial solutions */ return; if (c == 1023 && h >= 254 && s == 63) /* Indicators for invalid CHS */ return; /* matches(i=0,j=1) == 0 indicates presence of non-trivial equations */ matches[0] &= ~1; for (i = 1; i <= 255; i++) { for (j = 1; j <= 63; j++) { res = ((c * i) + h) * j + (s - 1); if (res != lba) { matches[(i / 8) * 32 + (j - 1)] &= ~(1 << (i % 8)); /* } else { if (matches[(i / 8) * 32 + (j - 1)] & (1 << (i % 8))) fprintf(stderr, "iso_scan_hc_sh :%d = %4d/%3d/%2d : H/C= %3d S/H= %2d\n", lba, c, h, s, i, j); */ } } } } /* Pick a good remaining solution from the matches bitmap. */ static void iso_get_hc_sh(uint8_t *matches, uint32_t iso_image_size, int *hc, int *sh, int flag) { int i, j, k; static int pref[][2] = {{64, 32}, {255, 63}}, prefs = 2; *hc = *sh = 0; if (matches[0] & 1) return; /* Only trivial equations seen */ /* Look for preferred layouts */ for (k = 0; k < prefs; k++) { i = pref[k][0]; j = pref[k][1]; if ((uint32_t) (1024 / 4 * i * j) <= iso_image_size) continue; if (matches[(i / 8) * 32 + (j - 1)] & (1 << (i % 8))) { *hc = i; *sh = j; return; } } /* Look for largest possible cylinder */ for (i = 1; i <= 255; i++) { for (j = 1; j <= 63; j++) { if ((uint32_t) (1024 / 4 * i * j) <= iso_image_size) continue; if (matches[(i / 8) * 32 + (j - 1)] & (1 << (i % 8))) { if( i * j < *hc * *sh) continue; *hc = i; *sh = j; } } } } static int iso_analyze_mbr_ptable(IsoImage *image, int flag) { int i, j, ret, cyl_align_mode, part_after_image = 0; uint32_t start_h, start_s, start_c, end_h, end_s, end_c, sph = 0, hpc = 0; uint32_t start_lba, num_blocks, end_chs_lba, image_size, lba, cyl_size; uint8_t *data, pstatus, ptype, *hc_sh = NULL; struct iso_imported_sys_area *sai; /* Bitmap for finding head_per_cyl and sectors_per_head. */ LIBISO_ALLOC_MEM(hc_sh, uint8_t, 32 * 63); memset(hc_sh, 0xff, 32 * 63); sai = image->imported_sa_info; image_size = sai->image_size; for (i = 0; i < 4; i++) { data = (uint8_t *) (image->system_area_data + 446 + 16 * i); for (j = 0; j < 16; j++) if (data[j]) break; if (j == 16) continue; pstatus = data[0]; ptype = data[4]; start_c = ((data[2] & 0xc0) << 2) | data[3]; start_h = data[1]; start_s = data[2] & 63; end_c = ((data[6] & 0xc0) << 2) | data[7]; end_h = data[5]; end_s = data[6] & 63; start_lba = iso_read_lsb(data + 8, 4); num_blocks = iso_read_lsb(data + 12, 4); if (num_blocks <= 0) continue; if (sph > 0) { if (end_s != sph) sph = 0xffffffff; } else if (sph == 0) { sph = end_s; } if (hpc > 0) { if (end_h + 1 != hpc) hpc = 0xffffffff; } else if (hpc == 0) { hpc = end_h + 1; } /* Check whether start_lba + num_blocks - 1 matches chs,hpc,spc */ end_chs_lba = ((end_c * hpc) + end_h) * sph + end_s; if (hpc > 0 && hpc < 0xffffffff && sph > 0 && sph < 0xffffffff) if (end_chs_lba != start_lba + num_blocks) hpc = sph = 0xffffffff; /* In case that end CHS does not give cylinder layout */ iso_scan_hc_sh(start_lba, start_c, start_h, start_s, hc_sh); iso_scan_hc_sh(start_lba + num_blocks - 1, end_c, end_h, end_s, hc_sh); /* Register partition as iso_mbr_partition_request */ if (sai->mbr_req == NULL) { sai->mbr_req = calloc(ISO_MBR_ENTRIES_MAX, sizeof(struct iso_mbr_partition_request *)); if (sai->mbr_req == NULL) {ret = ISO_OUT_OF_MEM; goto ex;} } ret = iso_quick_mbr_entry(sai->mbr_req, &(sai->mbr_req_count), (uint64_t) start_lba, (uint64_t) num_blocks, ptype, pstatus, i + 1); if (ret < 0) goto ex; if ((start_lba + num_blocks + 3) / 4 > image_size) image_size = (start_lba + num_blocks + 3) / 4; } if (hpc > 0 && hpc < 0xffffffff && sph > 0 && sph < 0xffffffff) { sai->partition_secs_per_head = sph; sai->partition_heads_per_cyl = hpc; } else { /* Look for the best C/H/S parameters caught in scan */ iso_get_hc_sh(hc_sh, image_size, &(sai->partition_heads_per_cyl), &(sai->partition_secs_per_head), 0); } cyl_align_mode = 2; /* off */ if (sai->partition_secs_per_head >0 && sai->partition_heads_per_cyl > 0 && sai->mbr_req_count > 0) { /* Check for cylinder alignment */ for (i = 0; i < sai->mbr_req_count; i++) { cyl_size = sai->partition_secs_per_head * sai->partition_heads_per_cyl; lba = sai->mbr_req[i]->start_block + sai->mbr_req[i]->block_count; if (sai->mbr_req[i]->start_block >= sai->image_size) part_after_image = 1; end_c = lba / cyl_size; if (end_c * cyl_size != lba) break; } if (i == sai->mbr_req_count && part_after_image) cyl_align_mode = 3; /* all */ else if (i >= 1) cyl_align_mode = 1; /* on */ } sai->system_area_options &= ~(3 << 8); sai->system_area_options |= (cyl_align_mode << 8); ret = 1; ex: LIBISO_FREE_MEM(hc_sh); return ret; } /* @return 0= no hybrid detected 1= ISOLINUX isohybrid (options & 2) 2= GRUB2 MBR patching (options & (1 << 14)) */ static int iso_analyze_isohybrid(IsoImage *image, int flag) { uint8_t *sad; uint32_t eltorito_lba = 0; uint64_t mbr_lba; int i, section_count, ret; ElToritoBootImage *boot; struct iso_file_section *sections; sad = (uint8_t *) image->system_area_data; /* Learn LBA of boot image */; if (image->bootcat == NULL) return 0; if (image->bootcat->num_bootimages < 1) return 0; boot = image->bootcat->bootimages[0]; if (boot == NULL) return 0; ret = iso_file_get_old_image_sections(boot->image, §ion_count, §ions, 0); if (ret < 0) return ret; if (ret > 0 && section_count > 0) eltorito_lba = sections[0].block; free(sections); /* Check MBR whether it is ISOLINUX and learn LBA to which it points */ if (!boot->seems_isohybrid_capable) goto try_grub2_mbr; for (i= 0; i < 426; i++) if(strncmp((char *) (sad + i), "isolinux", 8) == 0) break; if (i < 426) { /* search text was found */ mbr_lba = iso_read_lsb(sad + 432, 4); mbr_lba /= 4; if (mbr_lba == eltorito_lba) return 1; goto try_grub2_mbr; } try_grub2_mbr:; /* Check for GRUB2 MBR patching */ mbr_lba = iso_read_lsb64(sad + 0x1b0); if (mbr_lba / 4 - 1 == eltorito_lba) return 2; return 0; } static int iso_analyze_partition_offset(IsoImage *image, IsoDataSource *src, uint64_t start_block, int flag) { int ret; uint8_t *buf = NULL; off_t p_offset; struct ecma119_pri_vol_desc *pvm; struct iso_imported_sys_area *sai; sai = image->imported_sa_info; /* Check for PVD at partition start with same end */ LIBISO_ALLOC_MEM(buf, uint8_t, 2048); p_offset = start_block / 4; ret = src->read_block(src, p_offset + 16, buf); if (ret > 0) { pvm = (struct ecma119_pri_vol_desc *) buf; if (strncmp((char*) pvm->std_identifier, "CD001", 5) == 0 && pvm->vol_desc_type[0] == 1 && pvm->vol_desc_version[0] == 1 && pvm->file_structure_version[0] == 1 && iso_read_lsb(pvm->vol_space_size, 4) + p_offset == sai->image_size) sai->partition_offset = p_offset; } ret = 1; ex:; LIBISO_FREE_MEM(buf); return ret; } static int iso_analyze_mbr(IsoImage *image, IsoDataSource *src, int flag) { int sub_type = 2, ret, is_isohybrid = 0, is_grub2_mbr = 0; int is_protective_label = 0; char *sad; struct iso_imported_sys_area *sai; struct iso_mbr_partition_request *part; sad = image->system_area_data; sai = image->imported_sa_info; /* Is it an MBR ? */ if (((unsigned char *) sad)[510] != 0x55 || ((unsigned char *) sad)[511] != 0xaa) {ret = 0; goto ex;} ret = iso_analyze_mbr_ptable(image, 0); if (ret <= 0) goto ex; ret = iso_analyze_isohybrid(image, 0); if (ret < 0) goto ex; if (ret == 1) { sub_type = 0; is_isohybrid = 1; } else if(ret == 2) { sub_type = 0; is_grub2_mbr = 1; } if (sai->mbr_req_count == 1 && !is_isohybrid) { part = sai->mbr_req[0]; if (part->start_block == 1 && part->block_count + 1 == ((uint64_t) sai->image_size) * 4) { /* libisofs protective msdos label for GRUB2 */ is_protective_label = 1; sub_type = 0; } else if (part->start_block == 0 && part->block_count <= ((uint64_t) sai->image_size) * 4 && part->block_count + 600 >= ((uint64_t) sai->image_size) * 4 && part->type_byte == 0x96) { /* CHRP (possibly without padding) */ sub_type = 1; } else if (sai->mbr_req[0]->start_block > 0 && (sai->mbr_req[0]->start_block % 4) == 0 && (sai->mbr_req[0]->start_block + sai->mbr_req[0]->block_count) / 4 <= sai->image_size && part->type_byte == 0x41) { /* mkisofs PReP partition */ sai->prep_part_start = sai->mbr_req[0]->start_block / 4; sai->prep_part_size = (sai->mbr_req[0]->block_count + 3) / 4; sub_type = 0; } } else if (sai->mbr_req_count == 3 && !is_isohybrid) { /* Check for libisofs PReP partitions : 0xee or 0xcd from 0 to a-1 0x41 from a to b 0x0c or 0xcd from b+1 to end */ if ((sai->mbr_req[0]->start_block == 0 && (sai->mbr_req[0]->type_byte == 0xee || sai->mbr_req[0]->type_byte == 0xcd)) && sai->mbr_req[0]->block_count == sai->mbr_req[1]->start_block && sai->mbr_req[1]->type_byte == 0x41 && (sai->mbr_req[1]->start_block % 4) == 0 && sai->mbr_req[1]->start_block + sai->mbr_req[1]->block_count == sai->mbr_req[2]->start_block && (sai->mbr_req[2]->type_byte == 0x0c || sai->mbr_req[2]->type_byte == 0xcd) && (sai->mbr_req[2]->start_block + sai->mbr_req[2]->block_count) / 4 == sai->image_size) { sai->prep_part_start = sai->mbr_req[1]->start_block / 4; sai->prep_part_size = (sai->mbr_req[1]->block_count + 3) / 4; sub_type = 0; } } /* Check for partition offset with extra set of meta data */ if (sai->mbr_req_count > 0) { part = sai->mbr_req[0]; if ((part->status_byte == 0x80 || part->status_byte == 0) && part->start_block >= 64 && part->block_count >= 72 && part->start_block <= 2048 && part->start_block % 4 == 0 && part->block_count % 4 == 0 && (part->start_block + part->block_count) / 4 == sai->image_size) { ret = iso_analyze_partition_offset(image, src, part->start_block, 0); if (ret < 0) goto ex; } } /* Set sa type 0, sub type as chosen */ sai->system_area_options = (sai->system_area_options & 0xffff8300) | is_protective_label | (is_isohybrid << 1) | (sub_type << 10) | (is_grub2_mbr << 14); ret = 1; ex:; return ret; } static int iso_seems_usable_gpt_head(uint8_t *head, int flag) { uint32_t head_size, entry_size; if (strncmp((char *) head, "EFI PART", 8) != 0) /* signature */ return 0; if (head[8] || head[9] || head[10] != 1 || head[11]) /* revision */ return 0; head_size = iso_read_lsb(head + 12, 4); if (head_size < 92) return 0; entry_size = iso_read_lsb(head + 84, 4); if (entry_size != 128) return 0; return 1; } static int iso_analyze_gpt_backup(IsoImage *image, IsoDataSource *src, int flag) { struct iso_imported_sys_area *sai; uint64_t part_start; uint32_t iso_block, found_crc, crc, entry_count, array_crc; uint8_t *head, *part_array, *b_part, *m_part; int ret, i, num_iso_blocks, l, j, entries_diff; unsigned char *buf = NULL; char *comments = NULL; sai = image->imported_sa_info; LIBISO_ALLOC_MEM(buf, unsigned char, 34 * 1024); LIBISO_ALLOC_MEM(comments, char, 4096); /* Read ISO block with backup head */ if (sai->gpt_backup_lba >= ((uint64_t) sai->image_size) * 4 && (sai->mbr_req_count < 1 || sai->mbr_req[0]->start_block + sai->mbr_req[0]->block_count > sai->gpt_backup_lba + 1)) sprintf(comments + strlen(comments), "Implausible header LBA %.f, ", (double) sai->gpt_backup_lba); iso_block = sai->gpt_backup_lba / 4; ret = src->read_block(src, iso_block, buf); if (ret < 0) { sprintf(comments + strlen(comments), "Cannot read header block at 2k LBA %.f, ", (double) iso_block); ret = 0; goto ex; } head = buf + (sai->gpt_backup_lba % 4) * 512; ret = iso_seems_usable_gpt_head(head, 0); if (ret == 0) strcat(comments, "Not a GPT 1.0 header of 92 bytes for 128 bytes per entry, "); if (ret <= 0) { ret = 0; goto ex; } /* Check head CRC */ found_crc = iso_read_lsb(head + 16, 4); memset(head + 16, 0, 4); crc = iso_crc32_gpt((unsigned char *) head, 92, 0); if (found_crc != crc) { sprintf(comments + strlen(comments), "Head CRC 0x%8x wrong. Should be 0x%8x", found_crc, crc); crc = iso_crc32_gpt((unsigned char *) head, 512, 0); if (found_crc == crc) { strcat(comments, ". Matches all 512 block bytes, "); } else { strcat(comments, ", "); ret = 0; goto ex; } } for (i = 0; i < 16; i ++) if (head[i + 56] != sai->gpt_disk_guid[i]) break; if (i < 16) { sprintf(comments + strlen(comments), "Disk GUID differs ("); iso_util_bin_to_hex(comments + strlen(comments), head + 56, 16, 0); sprintf(comments + strlen(comments), "), "); } /* Header content will possibly be overwritten now */ array_crc = iso_read_lsb(head + 88, 4); part_start = iso_read_lsb64(head + 72); entry_count = iso_read_lsb(head + 80, 4); head = NULL; /* Read backup array */ if (entry_count != sai->gpt_max_entries) { sprintf(comments + strlen(comments), "Number of array entries %u differs from main GPT %u, ", entry_count, sai->gpt_max_entries); ret = 0; goto ex; } if (part_start + (entry_count + 3) / 4 != sai->gpt_backup_lba) sprintf(comments + strlen(comments), "Implausible array LBA %.f, ", (double) part_start); iso_block = part_start / 4; num_iso_blocks = (part_start + (entry_count + 3) / 4) / 4 - iso_block + 1; for (i = 0; i < num_iso_blocks; i++) { ret = src->read_block(src, iso_block + (uint32_t) i, buf + i * 2048); if (ret < 0) { sprintf(comments + strlen(comments), "Cannot read array block at 2k LBA %.f, ", (double) iso_block); ret = 0; goto ex; } } part_array = buf + (part_start % 4) * 512; crc = iso_crc32_gpt((unsigned char *) part_array, 128 * entry_count, 0); if (crc != array_crc) sprintf(comments + strlen(comments), "Array CRC 0x%8x wrong. Should be 0x%8x, ", array_crc, crc); /* Compare entries */ entries_diff = 0; for (i = 0; i < (int) entry_count; i++) { b_part = part_array + 128 * i; m_part = ((uint8_t *) image->system_area_data) + sai->gpt_part_start * 512 + 128 * i; for (j = 0; j < 128; j++) if (b_part[j] != m_part[j]) break; if (j < 128) { if (!entries_diff) { strcat(comments, "Entries differ for partitions"); entries_diff = 1; } sprintf(comments + strlen(comments), " %d", i + 1); } } if (entries_diff) { strcat(comments, ", "); ret = 0; goto ex; } ret = 1; ex:; if (comments != NULL) { l = strlen(comments); if (l > 2) if (comments[l - 2] == ',' && comments[l - 1] == ' ') comments[l - 2] = 0; sai->gpt_backup_comments = strdup(comments); if (sai->gpt_backup_comments == NULL) ret = ISO_OUT_OF_MEM; } LIBISO_FREE_MEM(comments); LIBISO_FREE_MEM(buf); return ret; } static int iso_analyze_gpt_head(IsoImage *image, IsoDataSource *src, int flag) { struct iso_imported_sys_area *sai; uint8_t *head; uint32_t crc; uint64_t part_start; int ret; unsigned char *crc_buf = NULL; sai = image->imported_sa_info; head = ((uint8_t *) image->system_area_data) + 512; LIBISO_ALLOC_MEM(crc_buf, unsigned char, 512); /* Is this a GPT header with digestible parameters ? */ ret = iso_seems_usable_gpt_head(head, 0); if (ret <= 0) goto ex; memcpy(crc_buf, head, 512); memset(crc_buf + 16, 0, 4); /* CRC is computed when head_crc is 0 */ sai->gpt_head_crc_found = iso_read_lsb(head + 16, 4); sai->gpt_head_crc_should = iso_crc32_gpt((unsigned char *) crc_buf, 92, 0); if (sai->gpt_head_crc_found != sai->gpt_head_crc_should) { /* There was a bug during libisofs-1.2.4 to libisofs-1.2.8 (fixed in rev 1071). So accept the buggy CRC if it matches the whole GPT header block. */ crc = iso_crc32_gpt((unsigned char *) crc_buf, 512, 0); if (sai->gpt_head_crc_found != crc) {ret = 0; goto ex;} } part_start = iso_read_lsb64(head + 72); sai->gpt_max_entries = iso_read_lsb(head + 80, 4); if (part_start + (sai->gpt_max_entries + 3) / 4 > 64) {ret = 0; goto ex;} /* Fetch desired information */ memcpy(sai->gpt_disk_guid, head + 56, 16); sai->gpt_part_start = part_start; sai->gpt_backup_lba = iso_read_lsb64(head + 32); sai->gpt_first_lba = iso_read_lsb64(head + 40); sai->gpt_last_lba = iso_read_lsb64(head + 48); sai->gpt_array_crc_found = iso_read_lsb(head + 88, 4); sai->gpt_array_crc_should = iso_crc32_gpt((unsigned char *) image->system_area_data + sai->gpt_part_start * 512, sai->gpt_max_entries * 128, 0); ret = iso_analyze_gpt_backup(image, src, 0); if (ret < 0) goto ex; ret = 1; ex: LIBISO_FREE_MEM(crc_buf); return ret; } static int iso_analyze_gpt(IsoImage *image, IsoDataSource *src, int flag) { int ret, i, j; uint64_t start_block, block_count, flags, end_block, j_end, j_start; uint8_t *part; struct iso_imported_sys_area *sai; sai = image->imported_sa_info; ret = iso_analyze_gpt_head(image, src, 0); if (ret <= 0) return ret; for (i = 0; i < (int) sai->gpt_max_entries; i++) { part = ((uint8_t *) image->system_area_data) + sai->gpt_part_start * 512 + 128 * i; for (j = 0; j < 128; j++) if (part[j]) break; if (j >= 128) /* all zero, invalid entry */ continue; start_block = iso_read_lsb64(part + 32); block_count = iso_read_lsb64(part + 40); flags = iso_read_lsb64(part + 48); if ((start_block == 0 && block_count == 0) || block_count + 1 < start_block) continue; block_count = block_count + 1 - start_block; if (sai->gpt_req == NULL) { sai->gpt_req = calloc(ISO_GPT_ENTRIES_MAX, sizeof(struct iso_gpt_partition_request *)); if (sai->gpt_req == NULL) return ISO_OUT_OF_MEM; } ret = iso_quick_gpt_entry(sai->gpt_req, &(sai->gpt_req_count), start_block, block_count, part, part + 16, flags, part + 56); if (ret < 0) return ret; sai->gpt_req[sai->gpt_req_count - 1]->idx = i + 1; } /* sai->gpt_req_flags : bit0= GPT partitions may overlap >>> bit1= with bit0: neatly nested partitions without : neatly divided disk */ for (i = 0; i < (int) sai->gpt_req_count && !(sai->gpt_req_flags & 1); i++) { if (sai->gpt_req[i]->block_count == 0) continue; start_block = sai->gpt_req[i]->start_block; end_block = start_block + sai->gpt_req[i]->block_count; for (j = i + 1; j < (int) sai->gpt_req_count; j++) { if (sai->gpt_req[j]->block_count == 0) continue; j_start = sai->gpt_req[j]->start_block; j_end = j_start + sai->gpt_req[j]->block_count; if ((start_block <= j_start && j_start < end_block) || (start_block <= j_end && j_end < end_block) || (j_start <= start_block && start_block < j_end)) { sai->gpt_req_flags |= 1; break; } } } /* Check first GPT partition for ISO partition offset */ if (sai->partition_offset == 0 && sai->mbr_req_count > 0 && sai->gpt_req_count > 0) { if (sai->mbr_req[0]->type_byte == 0xee && sai->mbr_req[0]->start_block == 1) { /* protective MBR */ start_block = sai->gpt_req[0]->start_block; block_count = sai->gpt_req[0]->block_count; if (start_block >= 64 && block_count >= 72 && start_block <= 2048 && start_block % 4 == 0 && block_count % 4 == 0 && (start_block + block_count) / 4 == sai->image_size) { ret = iso_analyze_partition_offset(image, src, start_block, 0); if (ret < 0) return ret; } } } return 1; } static int iso_analyze_apm_head(IsoImage *image, IsoDataSource *src, int flag) { struct iso_imported_sys_area *sai; char *sad; uint32_t block_size; sai = image->imported_sa_info; sad = image->system_area_data; if (sad[0] != 'E' || sad[1] != 'R') return 0; block_size = iso_read_msb(((uint8_t *) sad) + 2, 2); if (block_size != 2048 && block_size != 512) return 0; sai->apm_block_size = block_size; sai->apm_req_flags |= 4 | 2; /* start_block and block_count are in block_size units, do not fill gaps */ return 1; } static int iso_analyze_apm(IsoImage *image, IsoDataSource *src, int flag) { int ret, i; uint32_t map_entries, start_block, block_count, flags; char *sad, *part, name[33], type_string[33]; struct iso_imported_sys_area *sai; sai = image->imported_sa_info; sad = image->system_area_data; ret = iso_analyze_apm_head(image, src, 0); if (ret <= 0) return ret; part = sad + sai->apm_block_size; map_entries = iso_read_msb(((uint8_t *) part) + 4, 4); for (i = 0; i < (int) map_entries; i++) { part = sad + (i + 1) * sai->apm_block_size; if (part[0] != 'P' || part[1] != 'M') break; flags = iso_read_msb(((uint8_t *) part) + 88, 4); if (!(flags & 3)) continue; memcpy(type_string, part + 48, 32); type_string[32] = 0; if(strcmp(type_string, "Apple_partition_map") == 0) continue; start_block = iso_read_msb(((uint8_t *) part) + 8, 4); block_count = iso_read_msb(((uint8_t *) part + 12), 4); memcpy(name, part + 16, 32); name[32] = 0; if (sai->apm_req == NULL) { sai->apm_req = calloc(ISO_APM_ENTRIES_MAX, sizeof(struct iso_apm_partition_request *)); if (sai->apm_req == NULL) return ISO_OUT_OF_MEM; } ret = iso_quick_apm_entry(sai->apm_req, &(sai->apm_req_count), start_block, block_count, name, type_string); if (ret <= 0) return ret; if (strncmp(name, "Gap", 3) == 0 && strcmp(type_string, "ISO9660_data") == 0) { if ('0' <= name[3] && name[3] <= '9' && (name[4] == 0 || ('0' <= name[4] && name[4] <= '9' && name[5] == 0))) { sai->apm_gap_count++; sai->apm_req_flags &= ~2; } } } return 1; } static int iso_analyze_mips(IsoImage *image, IsoDataSource *src, int flag) { int ret = 0, spt, bps, i, j, idx; uint32_t magic, chk, head_chk; char *sad; uint8_t *usad, *upart; struct iso_imported_sys_area *sai; IsoNode *node; sai = image->imported_sa_info; sad = image->system_area_data; usad = (uint8_t *) sad; magic = iso_read_msb(usad, 4); if (magic != 0x0be5a941) return 0; spt = iso_read_msb(usad + 38, 2); bps = iso_read_msb(usad + 40, 2); if (spt != 32 || bps != 512) return 0; chk = 0; for (i = 0; i < 504; i += 4) chk -= iso_read_msb(usad + i, 4); head_chk = iso_read_msb(usad + 504, 4); if (chk != head_chk) return 0; /* Verify that partitions 1 to 8 are empty */ for (j = 312; j < 408; j++) if (sad[j]) return 0; /* >>> verify that partitions 9 and 10 match the image size */; for (i = 0; i < 15; i++) { upart = usad + 72 + 16 * i; for (j = 0; j < 16; j++) if (upart[j]) break; if (j == 16) continue; if (sai->mips_vd_entries == NULL) { sai->mips_boot_file_paths = calloc(15, sizeof(char *)); sai->mips_vd_entries = calloc(15, sizeof(struct iso_mips_voldir_entry *)); if (sai->mips_vd_entries == NULL || sai->mips_boot_file_paths == NULL) return ISO_OUT_OF_MEM; sai->num_mips_boot_files = 0; for (j = 0; j < 15; j++) { sai->mips_boot_file_paths[j] = NULL; sai->mips_vd_entries[j] = NULL; } } /* Assess boot file entry */ if (sai->num_mips_boot_files >= 15) return ISO_BOOT_TOO_MANY_MIPS; idx = sai->num_mips_boot_files; sai->mips_vd_entries[idx] = calloc(1, sizeof(struct iso_mips_voldir_entry)); if (sai->mips_vd_entries[idx] == NULL) return ISO_OUT_OF_MEM; memcpy(sai->mips_vd_entries[idx]->name, upart, 8); sai->mips_vd_entries[idx]->name[8] = 0; sai->mips_vd_entries[idx]->boot_block = iso_read_msb(upart + 8, 4); sai->mips_vd_entries[idx]->boot_bytes = iso_read_msb(upart + 12, 4); ret = iso_tree_get_node_of_block(image, NULL, sai->mips_vd_entries[idx]->boot_block / 4, &node, NULL, 0); if (ret > 0) sai->mips_boot_file_paths[idx] = iso_tree_get_node_path(node); sai->num_mips_boot_files++; } if (sai->num_mips_boot_files > 0) sai->system_area_options = (1 << 2);/* MIPS Big Endian Volume Header */ return ret; } static int iso_analyze_mipsel(IsoImage *image, IsoDataSource *src, int flag) { int ret = 0, i, section_count; char *sad; uint8_t *usad; uint32_t magic; struct iso_imported_sys_area *sai; IsoNode *node; IsoFile *file; struct iso_file_section *sections = NULL; sai = image->imported_sa_info; sad = image->system_area_data; usad = (uint8_t *) sad; for (i = 0; i < 8; i++) if (sad[i]) return 0; magic = iso_read_lsb(usad + 8, 4); if (magic != 0x0002757a) return 0; sai->mipsel_p_vaddr = iso_read_lsb(usad + 16, 4); sai->mipsel_e_entry = iso_read_lsb(usad + 20, 4); sai->mipsel_p_filesz = iso_read_lsb(usad + 24, 4) * 512; sai->mipsel_seg_start = iso_read_lsb(usad + 28, 4); ret = iso_tree_get_node_of_block(image, NULL, sai->mipsel_seg_start / 4, &node, NULL, 0); if (ret > 0) { sai->mipsel_boot_file_path = iso_tree_get_node_path(node); file = (IsoFile *) node; ret = iso_file_get_old_image_sections(file, §ion_count, §ions, 0); if (ret > 0 && section_count > 0) { if (sections[0].block < (1 << 30) && sections[0].block * 4 < sai->mipsel_seg_start) sai->mipsel_p_offset = sai->mipsel_seg_start - sections[0].block * 4; free(sections); } } /* DEC Boot Block for MIPS Little Endian */ sai->system_area_options = (2 << 2); return 1; } static int iso_analyze_sun(IsoImage *image, IsoDataSource *src, int flag) { int ret = 0, i, idx; char *sad; uint8_t *usad, checksum[2]; uint16_t perms; uint64_t last_core_block; struct iso_imported_sys_area *sai; IsoNode *node; sai = image->imported_sa_info; sad = image->system_area_data; usad = (uint8_t *) sad; if (iso_read_msb(usad + 128, 4) != 1 || iso_read_msb(usad + 140, 2) != 8 || iso_read_msb(usad + 188, 4) != 0x600ddeee || iso_read_msb(usad + 430, 2) != 1 || iso_read_msb(usad + 508, 2) != 0xdabe) return 0; if (iso_read_msb(usad + 142, 2) != 4 || iso_read_msb(usad + 144, 2) != 0x10 || iso_read_msb(usad + 444, 4) != 0 || sai->image_size > 0x3fffffff || iso_read_msb(usad + 448, 4) != sai->image_size * 4) return 0; checksum[0] = checksum[1] = 0; for (i = 0; i < 510; i += 2) { checksum[0] ^= usad[i]; checksum[1] ^= usad[i + 1]; } if (checksum[0] != usad[510] || checksum[1] != usad[511]) return 0; sai->sparc_disc_label = calloc(1, 129); if (sai->sparc_disc_label == NULL) return ISO_OUT_OF_MEM; memcpy(sai->sparc_disc_label, sad, 128); sai->sparc_disc_label[128] = 0; sai->sparc_heads_per_cyl = iso_read_msb(usad + 436, 2); sai->sparc_secs_per_head = iso_read_msb(usad + 438, 2); for (i = 0; i < 8; i++) { perms = iso_read_msb(usad + 144 + 4 * i, 2); if (perms == 0) continue; if (sai->sparc_entries == NULL) { sai->sparc_entries = calloc(8, sizeof(struct iso_sun_disk_label_entry)); if (sai->sparc_entries == NULL) return ISO_OUT_OF_MEM; } idx = sai->sparc_entry_count; sai->sparc_entries[idx].idx = i + 1; sai->sparc_entries[idx].id_tag = iso_read_msb(usad + 142 + 4 * i, 2); sai->sparc_entries[idx].permissions = perms; sai->sparc_entries[idx].start_cyl = iso_read_msb(usad + 444 + 8 * i, 4); sai->sparc_entries[idx].num_blocks = iso_read_msb(usad + 448 + 8 * i, 4); sai->sparc_entry_count++; } /* GRUB2 SUN SPARC Core File Address */ sai->sparc_grub2_core_adr = iso_read_msb64(usad + 552); sai->sparc_grub2_core_size = iso_read_msb(usad + 560, 4); last_core_block = (sai->sparc_grub2_core_adr + sai->sparc_grub2_core_size + 2047) / 2048; if (last_core_block > 0) last_core_block--; if (last_core_block > 17 && last_core_block < sai->image_size) { ret = iso_tree_get_node_of_block(image, NULL, (uint32_t) last_core_block, &node, NULL, 0); if (ret > 0) { iso_node_ref(node); sai->sparc_core_node = (IsoFile *) node; } } else { sai->sparc_grub2_core_adr = 0; sai->sparc_grub2_core_size = 0; } /* SUN Disk Label for SUN SPARC */ sai->system_area_options = (3 << 2); return 1; } static int iso_analyze_hppa(IsoImage *image, IsoDataSource *src, int flag) { int ret = 0, i, cmd_adr, cmd_len; char *sad, *paths[4]; uint8_t *usad; uint16_t magic; uint32_t adrs[4]; struct iso_imported_sys_area *sai; IsoNode *node; sai = image->imported_sa_info; sad = image->system_area_data; usad = (uint8_t *) sad; magic = iso_read_msb(usad, 2); if (magic != 0x8000 || strncmp(sad + 2, "PALO", 5) != 0 || sad[7] < 4 || sad[7] > 5) return 0; sai->hppa_hdrversion = sad[7]; if (sai->hppa_hdrversion == 4) { cmd_len = 127; cmd_adr = 24; } else { cmd_len = 1023; cmd_adr = 1024; } sai->hppa_cmdline = calloc(1, cmd_len + 1); if (sai->hppa_cmdline == NULL) return ISO_OUT_OF_MEM; memcpy(sai->hppa_cmdline, sad + cmd_adr, cmd_len); sai->hppa_cmdline[cmd_len] = 0; adrs[0] = sai->hppa_kern32_adr = iso_read_msb(usad + 8, 4); sai->hppa_kern32_len = iso_read_msb(usad + 12, 4); adrs[1] = sai->hppa_kern64_adr = iso_read_msb(usad + 232, 4); sai->hppa_kern64_len = iso_read_msb(usad + 236, 4); adrs[2] = sai->hppa_ramdisk_adr = iso_read_msb(usad + 16, 4); sai->hppa_ramdisk_len = iso_read_msb(usad + 20, 4); adrs[3] = sai->hppa_bootloader_adr = iso_read_msb(usad + 240, 4); sai->hppa_bootloader_len = iso_read_msb(usad + 244, 4); for (i = 0; i < 4; i++) { paths[i] = NULL; ret = iso_tree_get_node_of_block(image, NULL, adrs[i] / 2048, &node, NULL, 0); if (ret > 0) paths[i] = iso_tree_get_node_path(node); } sai->hppa_kernel_32 = paths[0]; sai->hppa_kernel_64 = paths[1]; sai->hppa_ramdisk = paths[2]; sai->hppa_bootloader = paths[3]; if (sai->hppa_hdrversion == 5) sai->hppa_ipl_entry = iso_read_msb(usad + 248, 4); /* HP-PA PALO boot sector version 4 or 5 for HP PA-RISC */ sai->system_area_options = (sai->hppa_hdrversion << 2); return 1; } static int iso_analyze_alpha_boot(IsoImage *image, IsoDataSource *src, int flag) { int ret = 0, i, section_count; char *sad; uint8_t *usad; struct iso_imported_sys_area *sai; IsoNode *node; IsoFile *file; uint64_t checksum_found, checksum_should = 0, size; struct iso_file_section *sections = NULL; sai = image->imported_sa_info; sad = image->system_area_data; usad = (uint8_t *) sad; checksum_found = iso_read_lsb64(usad + 504); for (i = 0; i < 63; i++) checksum_should += iso_read_lsb64(usad + 8 * i); if (checksum_found != checksum_should) return 0; sai->alpha_boot_image = NULL; sai->alpha_boot_image_size = (uint64_t) iso_read_lsb64(usad + 480); sai->alpha_boot_image_adr = (uint64_t) iso_read_lsb64(usad + 488); ret = iso_tree_get_node_of_block(image, NULL, (uint32_t) (sai->alpha_boot_image_adr / 4), &node, NULL, 0); if (ret > 0) { if (iso_node_get_type(node) != LIBISO_FILE) return 0; file = (IsoFile *) node; ret = iso_file_get_old_image_sections(file, §ion_count, §ions, 0); if (ret > 0 && section_count > 0) { size = sections[0].size / 512 + !!(sections[0].size % 512); free(sections); if (size != sai->alpha_boot_image_size) return 0; } sai->alpha_boot_image = iso_tree_get_node_path(node); } else if (strncmp(sad, "Linux/Alpha aboot for ISO filesystem.", 37) != 0 || sad[37] != 0) { return 0; /* Want to see either boot file or genisoimage string */ } sai->system_area_options = (6 << 2); return 1; } struct iso_impsysa_result { char *buf; int byte_count; char **lines; int line_count; }; static int iso_impsysa_result_new(struct iso_impsysa_result **r, int flag) { int ret; LIBISO_ALLOC_MEM(*r, struct iso_impsysa_result, 1); (*r)->buf = NULL; (*r)->lines = NULL; ret = 1; ex: if (ret <= 0) { LIBISO_FREE_MEM(*r); *r = NULL; } return ret; } static void iso_impsysa_result_destroy(struct iso_impsysa_result **r, int flag) { if (*r == NULL) return; if ((*r)->buf != NULL) free((*r)->buf); if ((*r)->lines != NULL) free((*r)->lines); free(*r); *r = NULL; } static void iso_impsysa_line(struct iso_impsysa_result *target, char *msg) { if (target->buf != NULL) strcpy(target->buf + target->byte_count, msg); if (target->lines != NULL) target->lines[target->line_count] = target->buf + target->byte_count; target->byte_count += strlen(msg) + 1; target->line_count++; } static void iso_impsysa_report_text(struct iso_impsysa_result *target, char *msg, char *path, int flag) { if (strlen(msg) + strlen(path) >= ISO_MAX_SYSAREA_LINE_LENGTH) sprintf(msg + strlen(msg), "(too long to show here)"); else strcat(msg, path); iso_impsysa_line(target, msg); } static void iso_impsysa_reduce_na(uint32_t block, uint32_t *na, uint32_t claim) { if ((*na == 0 || *na > claim) && block < claim) *na = claim; } static int iso_impsysa_reduce_next_above(IsoImage *image, uint32_t block, uint32_t *next_above, int flag) { int i, section_count, ret; struct iso_imported_sys_area *sai; struct el_torito_boot_image *img; struct iso_file_section *sections = NULL; sai = image->imported_sa_info; /* PVD, path table, root directory of active and of first session */ for (i = 0; i < sai->num_meta_struct_blocks; i++) iso_impsysa_reduce_na(block, next_above, sai->meta_struct_blocks[i]); /* Partition tables */ for (i = 0; i < sai->mbr_req_count; i++) { iso_impsysa_reduce_na(block, next_above, (uint32_t) (sai->mbr_req[i]->start_block / 4)); iso_impsysa_reduce_na(block, next_above, (uint32_t) ((sai->mbr_req[i]->start_block + sai->mbr_req[i]->block_count) / 4)); } for (i = 0; i < sai->gpt_req_count; i++) { iso_impsysa_reduce_na(block, next_above, (uint32_t) (sai->gpt_req[i]->start_block / 4)); iso_impsysa_reduce_na(block, next_above, (uint32_t) ((sai->gpt_req[i]->start_block + sai->gpt_req[i]->block_count) / 4)); } for (i = 0; i < sai->apm_req_count; i++) { iso_impsysa_reduce_na(block, next_above, (uint32_t) (sai->apm_req[i]->start_block / (2048 / sai->apm_block_size))); iso_impsysa_reduce_na(block, next_above, (uint32_t) ((sai->apm_req[i]->start_block + sai->apm_req[i]->block_count) / (2048 / sai->apm_block_size))); } if (image->bootcat != NULL) { if (image->bootcat->node != NULL) iso_impsysa_reduce_na(block, next_above, image->bootcat->node->lba); for (i= 0; i < image->bootcat->num_bootimages; i++) { img = image->bootcat->bootimages[i]; ret = iso_file_get_old_image_sections(img->image, §ion_count, §ions, 0); if (ret > 0 && section_count > 0) if (block != sections[0].block) iso_impsysa_reduce_na(block, next_above, sections[0].block); if (sections != NULL) { free(sections); sections = NULL; } } } iso_impsysa_reduce_na(block, next_above, sai->image_size); return ISO_SUCCESS; } /* @param flag bit0= try to estimate the size if no path is found */ static void iso_impsysa_report_blockpath(IsoImage *image, struct iso_impsysa_result *target, char *msg, uint32_t start_block, int flag) { int ret; char *path = NULL, *cpt; IsoNode *node; uint32_t next_above = 0; uint32_t size; ret = iso_tree_get_node_of_block(image, NULL, start_block, &node, &next_above, 0); if (ret <= 0) { if (!(flag & 1)) return; /* Look for next claimed block for estimating file size. next_above already holds the best data file candidate. */ ret = iso_impsysa_reduce_next_above(image, start_block, &next_above, 0); if (ret < 0) return; if (next_above == 0) return; size = next_above - start_block; /* Replace in msg "path" by "blks", report number in bytes */ cpt = strstr(msg, "path"); if (cpt == NULL) return; path = iso_alloc_mem(strlen(msg) + 20, 1, 0); if (path == NULL) return; strcpy(path, msg); memcpy(path + (cpt - msg), "blks", 4); sprintf(path + strlen(path), "%u", (unsigned int) size); iso_impsysa_report_text(target, path, "", 0); free(path); return; } path = iso_tree_get_node_path(node); if (path != NULL) { iso_impsysa_report_text(target, msg, path, 0); free(path); } } static int iso_impsysa_report(IsoImage *image, struct iso_impsysa_result *target, int flag) { char *msg = NULL, *local_name = NULL, *path; int i, j, sa_type, sao, sa_sub, ret, idx; size_t local_len; struct iso_imported_sys_area *sai; struct iso_mbr_partition_request *part; struct iso_gpt_partition_request *gpt_entry; struct iso_apm_partition_request *apm_entry; static char *alignments[4] = {"auto", "on", "off", "all"}; IsoWriteOpts *opts = NULL; struct iso_sun_disk_label_entry *sparc_entry; sai = image->imported_sa_info; LIBISO_ALLOC_MEM(msg, char, ISO_MAX_SYSAREA_LINE_LENGTH); if (sai == NULL) {ret = 0; goto ex;} if (!sai->is_not_zero) {ret = 0; goto ex;} sao = sai->system_area_options; sprintf(msg, "System area options: 0x%-8.8x", (unsigned int) sao); iso_impsysa_line(target, msg); /* Human readable form of system_area_options */ sa_type = (sao >> 2) & 63; sa_sub = (sao >> 10) & 15; strcpy(msg, "System area summary:"); if (sa_type == 0) { if ((sao & 3) || sa_sub == 1 || sa_sub == 2) { strcat(msg, " MBR"); if (sao & 1) strcat(msg, " protective-msdos-label"); else if (sao & 2) strcat(msg, " isohybrid"); else if (sa_sub == 1) strcat(msg, " CHRP"); if ((sao & (1 << 14)) && !(sao & 2)) strcat(msg, " grub2-mbr"); sprintf(msg + strlen(msg), " cyl-align-%s", alignments[(sao >> 8) & 3]); } else if (sai->prep_part_start > 0 && sai->prep_part_size > 0) { strcat(msg, " PReP"); } else if (sai->mbr_req_count > 0) { strcat(msg, " MBR"); } else { strcat(msg, " not-recognized"); } } else if (sa_type == 1) { strcat(msg, " MIPS-Big-Endian"); } else if (sa_type == 2) { strcat(msg, " MIPS-Little-Endian"); } else if (sa_type == 3) { strcat(msg, " SUN-SPARC-Disk-Label"); } else if (sa_type == 4 || sa_type == 5) { sprintf(msg + strlen(msg), " HP-PA-PALO"); } else if (sa_type == 6) { sprintf(msg + strlen(msg), " DEC-Alpha"); } else { sprintf(msg + strlen(msg), " unkown-system-area-type-%d", sa_type); } if (sai->gpt_req_count > 0) strcat(msg, " GPT"); if (sai->apm_req_count > 0) strcat(msg, " APM"); iso_impsysa_line(target, msg); /* System area summary */ sprintf(msg, "ISO image size/512 : %.f", ((double) sai->image_size) * 4.0); iso_impsysa_line(target, msg); if (sai->mbr_req_count > 0 && sa_type == 0) { sprintf(msg, "Partition offset : %d", sai->partition_offset); iso_impsysa_line(target, msg); } if (sa_type >= 4 && sa_type <= 5) { sprintf(msg, "PALO header version: %d", sai->hppa_hdrversion); iso_impsysa_line(target, msg); sprintf(msg, "HP-PA cmdline : "); iso_impsysa_report_text(target, msg, sai->hppa_cmdline, 0); sprintf(msg, "HP-PA boot files : ByteAddr ByteSize Path"); iso_impsysa_line(target, msg); sprintf(msg, "HP-PA 32-bit kernel: %10u %10u ", sai->hppa_kern32_adr, sai->hppa_kern32_len); iso_impsysa_report_text(target, msg, sai->hppa_kernel_32 != NULL ? sai->hppa_kernel_32 : "(not found in ISO)", 0); sprintf(msg, "HP-PA 64-bit kernel: %10u %10u ", sai->hppa_kern64_adr, sai->hppa_kern64_len); iso_impsysa_report_text(target, msg, sai->hppa_kernel_64 != NULL ? sai->hppa_kernel_64 : "(not found in ISO)", 0); sprintf(msg, "HP-PA ramdisk : %10u %10u ", sai->hppa_ramdisk_adr, sai->hppa_ramdisk_len); iso_impsysa_report_text(target, msg, sai->hppa_ramdisk != NULL ? sai->hppa_ramdisk : "(not found in ISO)", 0); sprintf(msg, "HP-PA bootloader : %10u %10u ", sai->hppa_bootloader_adr, sai->hppa_bootloader_len); iso_impsysa_report_text(target, msg, sai->hppa_bootloader != NULL ? sai->hppa_bootloader : "(not found in ISO)", 0); } else if (sa_type == 6) { sprintf(msg, "DEC Alpha ldr size : %.f", (double) sai->alpha_boot_image_size); iso_impsysa_line(target, msg); sprintf(msg, "DEC Alpha ldr adr : %.f", (double) sai->alpha_boot_image_adr); iso_impsysa_line(target, msg); if (sai->alpha_boot_image != NULL) { sprintf(msg, "DEC Alpha ldr path : %s", sai->alpha_boot_image); iso_impsysa_line(target, msg); } } if (sai->mbr_req_count > 0) { sprintf(msg, "MBR heads per cyl : %d", sai->partition_heads_per_cyl); iso_impsysa_line(target, msg); sprintf(msg, "MBR secs per head : %d", sai->partition_secs_per_head); iso_impsysa_line(target, msg); sprintf(msg, "MBR partition table: N Status Type Start Blocks"); iso_impsysa_line(target, msg); } for (i = 0; i < sai->mbr_req_count; i++) { part = sai->mbr_req[i]; sprintf(msg, "MBR partition : %3d 0x%2.2x 0x%2.2x %11.f %11.f", part->desired_slot, (unsigned int) part->status_byte, (unsigned int) part->type_byte, (double) part->start_block, (double) part->block_count); iso_impsysa_line(target, msg); } for (i = 0; i < sai->mbr_req_count; i++) { part = sai->mbr_req[i]; if (part->block_count == 0) continue; sprintf(msg, "MBR partition path : %3d ", part->desired_slot); iso_impsysa_report_blockpath(image, target, msg, (uint32_t) (part->start_block / 4), 0); } if (sai->prep_part_start > 0 && sai->prep_part_size > 0) { sprintf(msg, "PReP boot partition: %u %u", sai->prep_part_start, sai->prep_part_size); iso_impsysa_line(target, msg); } if (sa_type == 1) { sprintf(msg, "MIPS-BE volume dir : N Name Block Bytes"); iso_impsysa_line(target, msg); for (i = 0; i < sai->num_mips_boot_files; i++) { sprintf(msg, "MIPS-BE boot entry : %3d %8s %10u %10u", i + 1, sai->mips_vd_entries[i]->name, sai->mips_vd_entries[i]->boot_block, sai->mips_vd_entries[i]->boot_bytes); iso_impsysa_line(target, msg); if (sai->mips_boot_file_paths[i] != NULL) { sprintf(msg, "MIPS-BE boot path : %3d ", i + 1); iso_impsysa_report_text(target, msg, sai->mips_boot_file_paths[i], 0); } } } else if (sa_type == 2) { sprintf(msg, "MIPS-LE boot map : LoadAddr ExecAddr SegmentSize SegmentStart"); iso_impsysa_line(target, msg); sprintf(msg, "MIPS-LE boot params: %10u %10u %10u %10u", sai->mipsel_p_vaddr, sai->mipsel_e_entry, sai->mipsel_p_filesz, sai->mipsel_seg_start); iso_impsysa_line(target, msg); if (sai->mipsel_boot_file_path != NULL) { sprintf(msg, "MIPS-LE boot path : "); iso_impsysa_report_text(target, msg, sai->mipsel_boot_file_path, 0); sprintf(msg, "MIPS-LE elf offset : %u", sai->mipsel_p_offset); iso_impsysa_line(target, msg); } } else if (sa_type == 3) { sprintf(msg, "SUN SPARC disklabel: %s", sai->sparc_disc_label); iso_impsysa_line(target, msg); sprintf(msg, "SUN SPARC secs/head: %d", sai->sparc_secs_per_head); iso_impsysa_line(target, msg); sprintf(msg, "SUN SPARC heads/cyl: %d", sai->sparc_heads_per_cyl); iso_impsysa_line(target, msg); sprintf(msg, "SUN SPARC partmap : N IdTag Perms StartCyl NumBlocks"); iso_impsysa_line(target, msg); for (i = 0; i < sai->sparc_entry_count; i++) { sparc_entry = sai->sparc_entries + i; sprintf(msg, "SUN SPARC partition: %3d 0x%4.4x 0x%4.4x %10u %10u", sparc_entry->idx, sparc_entry->id_tag, sparc_entry->permissions, sparc_entry->start_cyl, sparc_entry->num_blocks); iso_impsysa_line(target, msg); } if (sai->sparc_grub2_core_adr > 0) { sprintf(msg, "SPARC GRUB2 core : %.f %u", (double) sai->sparc_grub2_core_adr, sai->sparc_grub2_core_size); iso_impsysa_line(target, msg); if (sai->sparc_core_node != NULL) { path = iso_tree_get_node_path((IsoNode *) sai->sparc_core_node); if (path != NULL) { sprintf(msg, "SPARC GRUB2 path : "); iso_impsysa_report_text(target, msg, path, 0); free(path); } } } } if (sai->gpt_req_count > 0) { sprintf(msg, "GPT : N Info"); iso_impsysa_line(target, msg); if (sai->gpt_head_crc_should != sai->gpt_head_crc_found) { sprintf(msg, "GPT CRC should be : 0x%8.8x to match first 92 GPT header block bytes", sai->gpt_head_crc_should); iso_impsysa_line(target, msg); sprintf(msg, "GPT CRC found : 0x%8.8x matches all 512 bytes of GPT header block", sai->gpt_head_crc_found); iso_impsysa_line(target, msg); } if (sai->gpt_array_crc_should != sai->gpt_array_crc_found) { sprintf(msg, "GPT array CRC wrong: should be 0x%8.8x , found 0x%8.8x", sai->gpt_array_crc_should, sai->gpt_array_crc_found); iso_impsysa_line(target, msg); } if (sai->gpt_backup_comments != NULL) { if (sai->gpt_backup_comments[0]) { sprintf(msg, "GPT backup problems: "); iso_impsysa_report_text(target, msg, sai->gpt_backup_comments, 0); } } sprintf(msg, "GPT disk GUID : "); iso_util_bin_to_hex(msg + 26, sai->gpt_disk_guid, 16, 0); iso_impsysa_line(target, msg); sprintf(msg, "GPT entry array : %u %u %s", (unsigned int) sai->gpt_part_start, (unsigned int) sai->gpt_max_entries, sai->gpt_req_flags & 1 ? "overlapping" : "separated"); iso_impsysa_line(target, msg); sprintf(msg, "GPT lba range : %.f %.f %.f", (double) sai->gpt_first_lba, (double) sai->gpt_last_lba, (double) sai->gpt_backup_lba); iso_impsysa_line(target, msg); ret = iso_write_opts_new(&opts, 0); if (ret < 0) goto ex; ret = iso_write_opts_set_output_charset(opts, "UTF-16LE"); if (ret < 0) goto ex; } for (i = 0; i < sai->gpt_req_count; i++) { gpt_entry = sai->gpt_req[i]; idx = gpt_entry->idx; sprintf(msg, "GPT partition name : %3d ", idx); for (j = 72; j >= 2; j -= 2) if (gpt_entry->name[j - 2] || gpt_entry->name[j - 1]) break; iso_util_bin_to_hex(msg + 26, gpt_entry->name, j, 0); iso_impsysa_line(target, msg); if (j > 0) ret = iso_conv_name_chars(opts, (char *) gpt_entry->name, j, &local_name, &local_len, 0 | 512 | (1 << 15)); else ret = 0; if (ret == 1 && local_len <= 228) { sprintf(msg, "GPT partname local : %3d ", idx); memcpy(msg + 26, local_name, local_len); LIBISO_FREE_MEM(local_name); local_name = NULL; msg[26 + local_len] = 0; iso_impsysa_line(target, msg); } sprintf(msg, "GPT partition GUID : %3d ", idx); iso_util_bin_to_hex(msg + 26, gpt_entry->partition_guid, 16, 0); iso_impsysa_line(target, msg); sprintf(msg, "GPT type GUID : %3d ", idx); iso_util_bin_to_hex(msg + 26, gpt_entry->type_guid, 16, 0); iso_impsysa_line(target, msg); sprintf(msg, "GPT partition flags: %3d 0x%8.8x%8.8x", idx, (unsigned int) ((gpt_entry->flags >> 32) & 0xffffffff), (unsigned int) (gpt_entry->flags & 0xffffffff)); iso_impsysa_line(target, msg); sprintf(msg, "GPT start and size : %3d %.f %.f", idx, (double) gpt_entry->start_block, (double) gpt_entry->block_count); iso_impsysa_line(target, msg); if (gpt_entry->block_count == 0) continue; sprintf(msg, "GPT partition path : %3d ", idx); iso_impsysa_report_blockpath(image, target, msg, (uint32_t) (gpt_entry->start_block / 4), 0); } if (sai->apm_req_count > 0) { sprintf(msg, "APM : N Info"); iso_impsysa_line(target, msg); sprintf(msg, "APM block size : %u", sai->apm_block_size); iso_impsysa_line(target, msg); sprintf(msg, "APM gap fillers : %d", sai->apm_gap_count); iso_impsysa_line(target, msg); } for (i = 0; i < sai->apm_req_count; i++) { apm_entry = sai->apm_req[i]; idx = i + 1; sprintf(msg, "APM partition name : %3d %s", idx, apm_entry->name); iso_impsysa_line(target, msg); sprintf(msg, "APM partition type : %3d %s", idx, apm_entry->type); iso_impsysa_line(target, msg); sprintf(msg, "APM start and size : %3d %.f %.f", idx, (double) apm_entry->start_block, (double) apm_entry->block_count); iso_impsysa_line(target, msg); if (apm_entry->block_count == 0) continue; sprintf(msg, "APM partition path : %3d ", idx); iso_impsysa_report_blockpath(image, target, msg, (uint32_t) (apm_entry->start_block / (2048 / sai->apm_block_size)), 0); } ret = 1; ex: LIBISO_FREE_MEM(local_name); if (opts != NULL) iso_write_opts_free(opts); LIBISO_FREE_MEM(msg); return ret; } static int iso_report_result_destroy(char ***result, int flag) { if (*result == NULL) return ISO_SUCCESS; if ((*result)[0] != NULL) /* points to the whole multi-line buffer */ free((*result)[0]); free(*result); *result = NULL; return ISO_SUCCESS; } static int iso_report_help(char **doc, char ***result, int *line_count, int flag) { int i, count = 0; char *buf = NULL; *line_count = 0; for (i = 0; strcmp(doc[i], "@END_OF_DOC@") != 0; i++) count += strlen(doc[i]) + 1; if (i == 0) return ISO_SUCCESS; *result = calloc(i, sizeof(char *)); if (*result == NULL) return ISO_OUT_OF_MEM; buf = calloc(1, count); if (buf == NULL) { free(*result); *result = NULL; return ISO_OUT_OF_MEM; } *line_count = i; count = 0; for (i = 0; strcmp(doc[i], "@END_OF_DOC@") != 0; i++) { strcpy(buf + count, doc[i]); (*result)[i] = buf + count; count += strlen(doc[i]) + 1; } return ISO_SUCCESS; } static int iso_eltorito_report(IsoImage *image, struct iso_impsysa_result *target, int flag) { char *msg = NULL, emul_code[6], pltf[5], *path; int i, j, ret, section_count; uint32_t lba, *lba_mem = NULL; struct el_torito_boot_catalog *bootcat; IsoBoot *bootnode; struct el_torito_boot_image *img; struct iso_file_section *sections = NULL; static char emul_names[5][6] = {"none", "fd1.2", "fd1.4", "fd2.8", "hd"}; static char pltf_names[3][5] = {"BIOS", "PPC", "Mac"}; static int num_emuls = 5, num_pltf = 3; bootcat = image->bootcat; LIBISO_ALLOC_MEM(msg, char, ISO_MAX_SYSAREA_LINE_LENGTH); if (bootcat == NULL) {ret= 0; goto ex;} bootnode = image->bootcat->node; if (bootnode == NULL) {ret= 0; goto ex;} sprintf(msg, "El Torito catalog : %u %u", (unsigned int) bootnode->lba, (unsigned int) (bootnode->size + 2047) / 2048); iso_impsysa_line(target, msg); path = iso_tree_get_node_path((IsoNode *) bootnode); if (path != NULL) { sprintf(msg, "El Torito cat path : "); iso_impsysa_report_text(target, msg, path, 0); free(path); } if (bootcat->num_bootimages > 0) { sprintf(msg, "El Torito images : N Pltf B Emul Ld_seg Hdpt Ldsiz LBA"); iso_impsysa_line(target, msg); LIBISO_ALLOC_MEM(lba_mem, uint32_t, bootcat->num_bootimages); } for (i= 0; i < bootcat->num_bootimages; i++) { img = bootcat->bootimages[i]; if (img->type < num_emuls) strcpy(emul_code, emul_names[img->type]); else sprintf(emul_code, "0x%2.2x", (unsigned int) img->type); if (img->platform_id < num_pltf) strcpy(pltf, pltf_names[img->platform_id]); else if(img->platform_id == 0xef) strcpy(pltf, "UEFI"); else sprintf(pltf, "0x%2.2x", (unsigned int) img->platform_id); lba = 0xffffffff; ret = iso_file_get_old_image_sections(img->image, §ion_count, §ions, 0); if (ret > 0 && section_count > 0) lba = sections[0].block; lba_mem[i]= lba; if (sections != NULL) { free(sections); sections = NULL; } sprintf(msg, "El Torito boot img : %3d %4s %c %5s 0x%4.4x 0x%2.2x %5u %10u", i + 1, pltf, img->bootable ? 'y' : 'n', emul_code, (unsigned int) img->load_seg, (unsigned int) img->partition_type, (unsigned int) img->load_size, (unsigned int) lba); iso_impsysa_line(target, msg); } for (i= 0; i < bootcat->num_bootimages; i++) { img = bootcat->bootimages[i]; if (lba_mem[i] != 0xffffffff) { sprintf(msg, "El Torito img path : %3d ", i + 1); iso_impsysa_report_blockpath(image, target, msg, lba_mem[i], 1); } sprintf(msg, "El Torito img opts : %3d ", i + 1); if (img->seems_boot_info_table) strcat(msg, "boot-info-table "); if (img->seems_isohybrid_capable) strcat(msg, "isohybrid-suitable "); if (img->seems_grub2_boot_info) strcat(msg, "grub2-boot-info "); if (strlen(msg) > 27) { msg[strlen(msg) - 1] = 0; iso_impsysa_line(target, msg); } for (j = 0; j < (int) sizeof(img->id_string); j++) if (img->id_string[j]) break; if (j < (int) sizeof(img->id_string)) { sprintf(msg, "El Torito id string: %3d ", i + 1); iso_util_bin_to_hex(msg + strlen(msg), img->id_string, 24 + 4 * (i > 0), 0); } for (j = 0; j < (int) sizeof(img->selection_crit); j++) if (img->selection_crit[j]) break; if (j < (int) sizeof(img->selection_crit) && i > 0) { sprintf(msg, "El Torito sel crit : %3d ", i + 1); iso_util_bin_to_hex(msg + strlen(msg), img->selection_crit, 20, 0); } } ret = ISO_SUCCESS; ex:; LIBISO_FREE_MEM(msg); LIBISO_FREE_MEM(lba_mem); return ret; } /* API */ /* @param flag bit1= do not report system area but rather reply help text bit15= dispose result from previous call */ static int iso_image_report_boot_eqp(IsoImage *image, int what, char ***result, int *line_count, int flag) { int ret; char **doc; struct iso_impsysa_result *target = NULL; static char *sysarea_doc[] = { ISO_SYSAREA_REPORT_DOC , ISO_SYSAREA_REPORT_DOC_MBR , ISO_SYSAREA_REPORT_DOC_GPT1 , ISO_SYSAREA_REPORT_DOC_GPT2 , ISO_SYSAREA_REPORT_DOC_APM , ISO_SYSAREA_REPORT_DOC_MIPS , ISO_SYSAREA_REPORT_DOC_SUN , ISO_SYSAREA_REPORT_DOC_HPPA , ISO_SYSAREA_REPORT_DOC_ALPHA , "@END_OF_DOC@" }; static char *eltorito_doc[] = { ISO_ELTORITO_REPORT_DOC , "@END_OF_DOC@" }; if (flag & (1 << 15)) return iso_report_result_destroy(result, 0); if (flag & 1) { if (what == 0) doc = sysarea_doc; else doc = eltorito_doc; return iso_report_help(doc, result, line_count, 0); } *result = NULL; *line_count = 0; ret = iso_impsysa_result_new(&target, 0); if (ret < 0) goto ex; if (what == 0) ret = iso_impsysa_report(image, target, 0); else ret = iso_eltorito_report(image, target, 0); if (ret <= 0) goto ex; target->buf = calloc(1, target->byte_count + 1); target->lines = calloc(target->line_count + 1, sizeof(char *)); if (target->buf == NULL || target->lines == NULL) {ret = ISO_OUT_OF_MEM; goto ex;} target->lines[0] = target->buf; /* even if no lines get reported */ target->byte_count = 0; target->line_count = 0; if (what == 0) ret = iso_impsysa_report(image, target, 0); else ret = iso_eltorito_report(image, target, 0); if (ret <= 0) goto ex; /* target to result */ *result = target->lines; target->lines = NULL; target->buf = NULL; *line_count = target->line_count; ret = ISO_SUCCESS; ex: iso_impsysa_result_destroy(&target, 0); return ret; } /* API */ /* @param flag bit1= do not report system area but rather reply help text bit15= dispose result from previous call */ int iso_image_report_system_area(IsoImage *image, char ***result, int *line_count, int flag) { return iso_image_report_boot_eqp(image, 0, result, line_count, flag); } static int iso_record_pvd_blocks(IsoImage *image, IsoDataSource *src, uint32_t block, int flag) { int ret; uint8_t *buffer = NULL; struct iso_imported_sys_area *sai; LIBISO_ALLOC_MEM(buffer, uint8_t, 2048); sai = image->imported_sa_info; sai->meta_struct_blocks[sai->num_meta_struct_blocks++] = block; ret = src->read_block(src, block, buffer); if (ret < 0) goto ex; /* Verify that it is a PVD of a volume not larger than sai->image_size */ if (buffer[0] != 1 || strncmp((char *) buffer + 1, "CD001", 5) != 0) {ret = 0; goto ex;} if (iso_read_lsb(buffer + 80, 4) > sai->image_size) {ret = 0; goto ex;} /* L pathtable, Opt L, M pathtable , Opt M, Root directory extent*/ sai->meta_struct_blocks[sai->num_meta_struct_blocks++] = iso_read_lsb(buffer + 140, 4); sai->meta_struct_blocks[sai->num_meta_struct_blocks++] = iso_read_lsb(buffer + 144, 4); sai->meta_struct_blocks[sai->num_meta_struct_blocks++] = iso_read_lsb(buffer + 148, 4); sai->meta_struct_blocks[sai->num_meta_struct_blocks++] = iso_read_lsb(buffer + 152, 4); sai->meta_struct_blocks[sai->num_meta_struct_blocks++] = iso_read_lsb(buffer + 158, 4); ret = ISO_SUCCESS; ex:; LIBISO_FREE_MEM(buffer); return ret; } static int iso_record_meta_struct_blocks(IsoImage *image, IsoDataSource *src, int flag) { int ret; struct iso_imported_sys_area *sai; sai = image->imported_sa_info; ret = iso_record_pvd_blocks(image, src, sai->pvd_block, 0); if (ret < 0) goto ex; /* Try block 32 as first session PVD */ ret = iso_record_pvd_blocks(image, src, 16, 0); if (ret < 0) goto ex; if (ret == 0 && sai->pvd_block > 16) { /* No emulated multi-session: Try block 16 as first session PVD */ ret = iso_record_pvd_blocks(image, src, 16, 0); if (ret < 0) goto ex; } ret = ISO_SUCCESS; ex: return ret; } static int iso_analyze_system_area(IsoImage *image, IsoDataSource *src, struct iso_read_opts *opts, uint32_t image_size, int flag) { int ret, i, sao, sa_type, sa_sub; iso_imported_sa_unref(&(image->imported_sa_info), 0); ret = iso_imported_sa_new(&(image->imported_sa_info), 0); if (ret < 0) goto ex; for (i = 0; i < 32768; i++) if (image->system_area_data[i] != 0) break; if (i < 32768) image->imported_sa_info->is_not_zero = 1; image->imported_sa_info->image_size = image_size; image->imported_sa_info->pvd_block = opts->block + 16; ret = iso_analyze_mbr(image, src, 0); if (ret < 0) goto ex; ret = iso_analyze_gpt(image, src, 0); if (ret < 0) goto ex; ret = iso_analyze_apm(image, src, 0); if (ret < 0) goto ex; sao = image->imported_sa_info->system_area_options; sa_type = (sao >> 2) & 0x3f; sa_sub = (sao >> 10) & 0xf; if (sa_type == 0 && !((sao & 3) || sa_sub == 1 || sa_sub == 2)) { ret = iso_analyze_mips(image, src, 0); if (ret < 0) goto ex; if (ret == 0) { ret = iso_analyze_mipsel(image, src, 0); if (ret < 0) goto ex; } if (ret == 0) { ret = iso_analyze_sun(image, src, 0); if (ret < 0) goto ex; } } if (sa_type == 0 && !((sao & 3) || sa_sub == 1)) { /* HP-PA PALO v5 can look like generic MBR */ ret = iso_analyze_hppa(image, src, 0); if (ret < 0) goto ex; /* DEC Alpha has checksum bytes where MBR has its magic number */ if (ret == 0) { ret = iso_analyze_alpha_boot(image, src, 0); if (ret < 0) goto ex; } } ret = iso_record_meta_struct_blocks(image, src, 0); if (ret < 0) goto ex; ret = ISO_SUCCESS; ex:; image->imported_sa_info->overall_return = ret; return ret; } /* API */ /* @param flag bit1= do not report system area but rather reply help text bit15= dispose result from previous call */ int iso_image_report_el_torito(IsoImage *image, char ***reply, int *line_count, int flag) { return iso_image_report_boot_eqp(image, 1, reply, line_count, flag); } int iso_image_import(IsoImage *image, IsoDataSource *src, struct iso_read_opts *opts, IsoReadImageFeatures **features) { int ret, hflag, i, idx; IsoImageFilesystem *fs; IsoFilesystem *fsback; IsoNodeBuilder *blback; IsoDir *oldroot; IsoFileSource *newroot; _ImageFsData *data; struct el_torito_boot_catalog *oldbootcat; uint8_t *rpt; IsoFileSource *boot_src; IsoNode *node; char *old_checksum_array = NULL; char checksum_type[81]; uint32_t checksum_size, truncate_mode, truncate_length; size_t size, attr_value_length; char *attr_value; unsigned char *aa_string = NULL; void *ctx = NULL; char md5[16]; struct el_torito_boot_catalog *catalog = NULL; ElToritoBootImage *boot_image = NULL; if (image == NULL || src == NULL || opts == NULL) { return ISO_NULL_POINTER; } opts->truncate_mode = image->truncate_mode; opts->truncate_length = image->truncate_length; ret = iso_image_filesystem_new(src, opts, image->id, &fs); if (ret < 0) { return ret; } data = fs->data; if (opts->keep_import_src) { iso_data_source_ref(src); image->import_src = src; } if (opts->load_system_area) { if (image->system_area_data != NULL) free(image->system_area_data); image->system_area_data = calloc(32768, 1); if (image->system_area_data == NULL) { iso_filesystem_unref(fs); return ISO_OUT_OF_MEM; } image->system_area_options = 0; /* Read 32768 bytes */ for (i = 0; i < 16; i++) { rpt = (uint8_t *) (image->system_area_data + i * 2048); ret = src->read_block(src, opts->block + i, rpt); if (ret < 0) { iso_filesystem_unref(fs); return ret; } } } /* get root from filesystem */ ret = fs->get_root(fs, &newroot); if (ret < 0) { iso_filesystem_unref(fs); return ret; } /* Lookup character set even if no AAIP loading is enabled */ ret = iso_file_source_get_aa_string(newroot, &aa_string, 2); if (ret == 1 && aa_string != NULL) { ret = iso_aa_lookup_attr(aa_string, "isofs.cs", &attr_value_length, &attr_value, 0); free(aa_string); } else { ret = 0; } if (ret == 1) { if (data->auto_input_charset & 1) { if (data->input_charset != NULL) free(data->input_charset); data->input_charset = attr_value; iso_msg_submit(image->id, ISO_GENERAL_NOTE, 0, "Learned from ISO image: input character set '%.80s'", attr_value); } else { iso_msg_submit(image->id, ISO_GENERAL_NOTE, 0, "Ignored character set name recorded in ISO image: '%.80s'", attr_value); free(attr_value); } attr_value = NULL; } /* backup image filesystem, builder and root */ fsback = image->fs; blback = image->builder; oldroot = image->root; oldbootcat = image->bootcat; /* could be NULL */ image->bootcat = NULL; old_checksum_array = image->checksum_array; image->checksum_array = NULL; /* create new builder */ ret = iso_image_builder_new(blback, &image->builder); if (ret < 0) { goto import_revert; } image->fs = fs; /* create new root, and set root attributes from source */ ret = iso_node_new_root(&image->root); if (ret < 0) { goto import_revert; } { struct stat info; /* I know this will not fail */ iso_file_source_lstat(newroot, &info); image->root->node.mode = info.st_mode; image->root->node.uid = info.st_uid; image->root->node.gid = info.st_gid; image->root->node.atime = info.st_atime; image->root->node.mtime = info.st_mtime; image->root->node.ctime = info.st_ctime; /* This might fail in iso_node_add_xinfo() */ ret = src_aa_to_node(newroot, &(image->root->node), 0); if (ret < 0) goto import_revert; /* Attach ino as xinfo if valid */ if (info.st_ino != 0 && !data->make_new_ino) { ret = iso_node_set_ino(&(image->root->node), info.st_ino, 0); if (ret < 0) goto import_revert; } } ret = iso_root_get_isofsnt(&(image->root->node), &truncate_mode, &truncate_length, 0); if (ret == 1 && (int) truncate_mode == image->truncate_mode && image->truncate_mode == 1 && truncate_length >= 64 && truncate_length <= 255 && (int) truncate_length != image->truncate_length) { data->truncate_mode = opts->truncate_mode = image->truncate_mode = truncate_mode; data->truncate_length = opts->truncate_length = image->truncate_length = truncate_length; iso_msg_submit(image->id, ISO_TRUNCATE_ISOFSNT, 0, "File name truncation length changed by loaded image info: %d", (int) truncate_length); } /* if old image has el-torito, add a new catalog */ if (data->eltorito) { catalog = calloc(1, sizeof(struct el_torito_boot_catalog)); if (catalog == NULL) { ret = ISO_OUT_OF_MEM; goto import_revert; } catalog->num_bootimages = 0; for (idx = 0; idx < data->num_bootimgs; idx++) { boot_image = calloc(1, sizeof(ElToritoBootImage)); if (boot_image == NULL) { ret = ISO_OUT_OF_MEM; goto import_revert; } boot_image->image = NULL; boot_image->bootable = data->boot_flags[idx] & 1; boot_image->type = data->media_types[idx]; boot_image->partition_type = data->partition_types[idx]; boot_image->load_seg = data->load_segs[idx]; boot_image->load_size = data->load_sizes[idx]; boot_image->platform_id = data->platform_ids[idx]; memcpy(boot_image->id_string, data->id_strings[idx], 28); memcpy(boot_image->selection_crit, data->selection_crits, 20); catalog->bootimages[catalog->num_bootimages] = boot_image; boot_image = NULL; catalog->num_bootimages++; } for ( ; idx < Libisofs_max_boot_imageS; idx++) catalog->bootimages[idx] = NULL; image->bootcat = catalog; catalog = NULL; /* So it does not get freed */ } /* recursively add image */ ret = iso_add_dir_src_rec(image, image->root, newroot); if (ret < 0) { /* error during recursive image addition */ iso_node_builder_unref(image->builder); goto import_revert; } issue_ucs2_warning_summary(data->joliet_ucs2_failures); issue_collision_warning_summary(image->collision_warnings); /* Take over inode management from IsoImageFilesystem. data->inode_counter is supposed to hold the maximum PX inode number. */ image->inode_counter = data->inode_counter; if ((data->px_ino_status & (2 | 4 | 8)) || opts->make_new_ino) { /* Attach new inode numbers to any node which does not have one, resp. to all nodes in case of opts->make_new_ino */ if (opts->make_new_ino) hflag = 1; /* Equip all data files with new unique inos */ else hflag = 2 | 4 | 8; /* Equip any file type if it has ino == 0 */ ret = img_make_inos(image, image->root, hflag); if (ret < 0) { iso_node_builder_unref(image->builder); goto import_revert; } } if (data->eltorito) { /* if catalog and boot image nodes were not filled, we create them here */ for (idx = 0; idx < image->bootcat->num_bootimages; idx++) { if (image->bootcat->bootimages[idx]->image != NULL) continue; ret = create_boot_img_filesrc(fs, image, idx, &boot_src); if (ret < 0) { iso_node_builder_unref(image->builder); goto import_revert; } ret = image_builder_create_node(image->builder, image, boot_src, NULL, &node); iso_file_source_unref(boot_src); /* Now owned by node */ if (ret < 0) { iso_node_builder_unref(image->builder); goto import_revert; } if (image->bootcat->bootimages[idx]->image != NULL) { /* Already added to bootimages in image_builder_create_node(). * Now it has one refcount for tree and one for bootimages. * But it will not go to tree. So unref. */ iso_node_unref(node); } else { image->bootcat->bootimages[idx]->image = (IsoFile*)node; } /* warn about hidden images */ iso_msg_submit(image->id, ISO_EL_TORITO_HIDDEN, 0, "Found hidden El-Torito image. Its size could not " "be figured out, so image modify or boot image " "patching may lead to bad results."); } if (image->bootcat->node == NULL) { IsoNode *node; IsoBoot *bootcat; node = calloc(1, sizeof(IsoBoot)); if (node == NULL) { ret = ISO_OUT_OF_MEM; goto import_revert; } bootcat = (IsoBoot *) node; bootcat->lba = data->catblock; bootcat->size = data->catsize; bootcat->content = NULL; if (bootcat->size > 0) { bootcat->content = calloc(1, bootcat->size); if (bootcat->content == NULL) { free(node); ret = ISO_OUT_OF_MEM; goto import_revert; } memcpy(bootcat->content, data->catcontent, bootcat->size); } node->type = LIBISO_BOOT; node->mode = S_IFREG; node->refcount = 1; image->bootcat->node = (IsoBoot*)node; } } iso_node_builder_unref(image->builder); /* set volume attributes */ iso_image_set_volset_id(image, data->volset_id); iso_image_set_volume_id(image, data->volume_id); iso_image_set_publisher_id(image, data->publisher_id); iso_image_set_data_preparer_id(image, data->data_preparer_id); iso_image_set_system_id(image, data->system_id); iso_image_set_application_id(image, data->application_id); iso_image_set_copyright_file_id(image, data->copyright_file_id); iso_image_set_abstract_file_id(image, data->abstract_file_id); iso_image_set_biblio_file_id(image, data->biblio_file_id); iso_image_set_pvd_times(image, data->creation_time, data->modification_time, data->expiration_time, data->effective_time); if (features != NULL) { *features = malloc(sizeof(IsoReadImageFeatures)); if (*features == NULL) { ret = ISO_OUT_OF_MEM; goto import_revert; } (*features)->hasJoliet = data->joliet; (*features)->hasRR = data->rr_version != 0; (*features)->hasIso1999 = data->iso1999; (*features)->hasElTorito = data->eltorito; (*features)->size = data->nblocks; } if (data->md5_load) { /* Read checksum array */ ret = iso_root_get_isofsca((IsoNode *) image->root, &(image->checksum_start_lba), &(image->checksum_end_lba), &(image->checksum_idx_count), &checksum_size, checksum_type, 0); if (ret > 0) if (checksum_size != 16 || strcmp(checksum_type, "MD5") != 0) ret = 0; if (ret > 0 && image->checksum_idx_count > 1) { size = image->checksum_idx_count / 128; if (size * 128 < image->checksum_idx_count) size++; image->checksum_array = calloc(size, 2048); if (image->checksum_array == NULL) { ret = ISO_OUT_OF_MEM; goto import_revert; } /* Load from image->checksum_end_lba */; for (i = 0; i < (int) size; i++) { rpt = (uint8_t *) (image->checksum_array + i * 2048); ret = src->read_block(src, image->checksum_end_lba + i, rpt); if (ret <= 0) goto import_cleanup; } /* Compute MD5 and compare with recorded MD5 */ ret = iso_md5_start(&ctx); if (ret < 0) { ret = ISO_OUT_OF_MEM; goto import_revert; } for (i = 0; i < (int) image->checksum_idx_count - 1; i++) iso_md5_compute(ctx, image->checksum_array + i * 16, 16); iso_md5_end(&ctx, md5); for (i = 0; i < 16; i++) if (md5[i] != image->checksum_array[ (image->checksum_idx_count - 1) * 16 + i] ) break; if (i < 16) { iso_msg_submit(image->id, ISO_MD5_AREA_CORRUPTED, 0, "MD5 checksum array appears damaged and not trustworthy for verifications."); free(image->checksum_array); image->checksum_array = NULL; image->checksum_idx_count = 0; } } } ret = iso_image_eval_boot_info_table(image, opts, src, data->nblocks, 0); if (ret < 0) goto import_revert; if (opts->load_system_area && image->system_area_data != NULL) { ret = iso_analyze_system_area(image, src, opts, data->nblocks, 0); if (ret < 0) { iso_msg_submit(-1, ISO_SYSAREA_PROBLEMS, 0, "Problem encountered during inspection of System Area:"); iso_msg_submit(-1, ISO_SYSAREA_PROBLEMS, 0, iso_error_to_msg(ret)); } } ret = ISO_SUCCESS; goto import_cleanup; import_revert:; iso_node_unref((IsoNode*)image->root); el_torito_boot_catalog_free(image->bootcat); image->root = oldroot; oldroot = NULL; image->bootcat = oldbootcat; oldbootcat = NULL; image->checksum_array = old_checksum_array; old_checksum_array = NULL; import_cleanup:; /* recover backed fs and builder */ image->fs = fsback; image->builder = blback; /* free old root */ if (oldroot != NULL) iso_node_unref((IsoNode*)oldroot); /* free old boot catalog */ if (oldbootcat != NULL) el_torito_boot_catalog_free(oldbootcat); if (catalog != NULL) el_torito_boot_catalog_free(catalog); if (boot_image != NULL) free((char *) boot_image); iso_file_source_unref(newroot); fs->close(fs); iso_filesystem_unref(fs); if (old_checksum_array != NULL) free(old_checksum_array); if (ctx != NULL) iso_md5_end(&ctx, md5); return ret; } const char *iso_image_fs_get_volset_id(IsoImageFilesystem *fs) { _ImageFsData *data = (_ImageFsData*) fs->data; return data->volset_id; } const char *iso_image_fs_get_volume_id(IsoImageFilesystem *fs) { _ImageFsData *data = (_ImageFsData*) fs->data; return data->volume_id; } const char *iso_image_fs_get_publisher_id(IsoImageFilesystem *fs) { _ImageFsData *data = (_ImageFsData*) fs->data; return data->publisher_id; } const char *iso_image_fs_get_data_preparer_id(IsoImageFilesystem *fs) { _ImageFsData *data = (_ImageFsData*) fs->data; return data->data_preparer_id; } const char *iso_image_fs_get_system_id(IsoImageFilesystem *fs) { _ImageFsData *data = (_ImageFsData*) fs->data; return data->system_id; } const char *iso_image_fs_get_application_id(IsoImageFilesystem *fs) { _ImageFsData *data = (_ImageFsData*) fs->data; return data->application_id; } const char *iso_image_fs_get_copyright_file_id(IsoImageFilesystem *fs) { _ImageFsData *data = (_ImageFsData*) fs->data; return data->copyright_file_id; } const char *iso_image_fs_get_abstract_file_id(IsoImageFilesystem *fs) { _ImageFsData *data; data = (_ImageFsData*) fs->data; return data->abstract_file_id; } const char *iso_image_fs_get_biblio_file_id(IsoImageFilesystem *fs) { _ImageFsData *data = (_ImageFsData*) fs->data; return data->biblio_file_id; } int iso_read_opts_new(IsoReadOpts **opts, int profile) { IsoReadOpts *ropts; if (opts == NULL) { return ISO_NULL_POINTER; } if (profile != 0) { return ISO_WRONG_ARG_VALUE; } ropts = calloc(1, sizeof(IsoReadOpts)); if (ropts == NULL) { return ISO_OUT_OF_MEM; } ropts->file_mode = 0444; ropts->dir_mode = 0555; ropts->noaaip = 1; ropts->ecma119_map = 1; ropts->nomd5 = 1; ropts->load_system_area = 0; ropts->keep_import_src = 0; ropts->truncate_mode = 1; ropts->truncate_length = LIBISOFS_NODE_NAME_MAX; *opts = ropts; return ISO_SUCCESS; } void iso_read_opts_free(IsoReadOpts *opts) { if (opts == NULL) { return; } free(opts->input_charset); free(opts); } int iso_read_opts_set_start_block(IsoReadOpts *opts, uint32_t block) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->block = block; return ISO_SUCCESS; } int iso_read_opts_set_no_rockridge(IsoReadOpts *opts, int norr) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->norock = norr ? 1 :0; return ISO_SUCCESS; } int iso_read_opts_set_no_joliet(IsoReadOpts *opts, int nojoliet) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->nojoliet = nojoliet ? 1 :0; return ISO_SUCCESS; } int iso_read_opts_set_no_iso1999(IsoReadOpts *opts, int noiso1999) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->noiso1999 = noiso1999 ? 1 :0; return ISO_SUCCESS; } int iso_read_opts_set_no_aaip(IsoReadOpts *opts, int noaaip) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->noaaip = noaaip ? 1 : 0; return ISO_SUCCESS; } int iso_read_opts_set_no_md5(IsoReadOpts *opts, int no_md5) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->nomd5 = no_md5 == 2 ? 2 : no_md5 == 1 ? 1 : 0; return ISO_SUCCESS; } int iso_read_opts_set_new_inos(IsoReadOpts *opts, int new_inos) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->make_new_ino = new_inos ? 1 : 0; return ISO_SUCCESS; } int iso_read_opts_set_preferjoliet(IsoReadOpts *opts, int preferjoliet) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->preferjoliet = preferjoliet ? 1 :0; return ISO_SUCCESS; } int iso_read_opts_set_ecma119_map(IsoReadOpts *opts, int ecma119_map) { if (opts == NULL) { return ISO_NULL_POINTER; } if (ecma119_map < 0 || ecma119_map > 3) return 0; opts->ecma119_map = ecma119_map; return ISO_SUCCESS; } int iso_read_opts_set_default_uid(IsoReadOpts *opts, uid_t uid) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->uid = uid; return ISO_SUCCESS; } int iso_read_opts_set_default_gid(IsoReadOpts *opts, gid_t gid) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->gid = gid; return ISO_SUCCESS; } int iso_read_opts_set_default_permissions(IsoReadOpts *opts, mode_t file_perm, mode_t dir_perm) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->file_mode = file_perm; opts->dir_mode = dir_perm; return ISO_SUCCESS; } int iso_read_opts_set_input_charset(IsoReadOpts *opts, const char *charset) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->input_charset = charset ? strdup(charset) : NULL; return ISO_SUCCESS; } int iso_read_opts_auto_input_charset(IsoReadOpts *opts, int mode) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->auto_input_charset = mode; return ISO_SUCCESS; } int iso_read_opts_load_system_area(IsoReadOpts *opts, int mode) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->load_system_area = mode & 1; return ISO_SUCCESS; } int iso_read_opts_keep_import_src(IsoReadOpts *opts, int mode) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->keep_import_src = mode & 1; return ISO_SUCCESS; } /** * Destroy an IsoReadImageFeatures object obtained with iso_image_import. */ void iso_read_image_features_destroy(IsoReadImageFeatures *f) { if (f) { free(f); } } /** * Get the size (in 2048 byte block) of the image, as reported in the PVM. */ uint32_t iso_read_image_features_get_size(IsoReadImageFeatures *f) { return f->size; } /** * Whether RockRidge extensions are present in the image imported. */ int iso_read_image_features_has_rockridge(IsoReadImageFeatures *f) { return f->hasRR; } /** * Whether Joliet extensions are present in the image imported. */ int iso_read_image_features_has_joliet(IsoReadImageFeatures *f) { return f->hasJoliet; } /** * Whether the image is recorded according to ISO 9660:1999, i.e. it has * a version 2 Enhanced Volume Descriptor. */ int iso_read_image_features_has_iso1999(IsoReadImageFeatures *f) { return f->hasIso1999; } /** * Whether El-Torito boot record is present present in the image imported. */ int iso_read_image_features_has_eltorito(IsoReadImageFeatures *f) { return f->hasElTorito; } /** * Get the start addresses and the sizes of the data extents of a file node * if it was imported from an old image. * * @param file * The file * @param section_count * Returns the number of extent entries in sections arrays * @param sections * Returns the array of file sections. Apply free() to dispose it. * @param flag * Reserved for future usage, submit 0 * @return * 1 if there are valid extents (file comes from old image), * 0 if file was newly added, i.e. it does not come from an old image, * < 0 error */ int iso_file_get_old_image_sections(IsoFile *file, int *section_count, struct iso_file_section **sections, int flag) { if (file == NULL || section_count == NULL || sections == NULL) { return ISO_NULL_POINTER; } if (flag != 0) { return ISO_WRONG_ARG_VALUE; } *section_count = 0; *sections = NULL; if (file->from_old_session != 0) { /* * When file is from old session, we retrieve the original IsoFileSource * to get the sections. This break encapsultation, but safes memory as * we don't need to store the sections in the IsoFile node. */ IsoStream *stream = file->stream, *input_stream; FSrcStreamData *data; ImageFileSourceData *ifsdata; /* Get the most original stream */ while (1) { input_stream = iso_stream_get_input_stream(stream, 0); if (input_stream == NULL || input_stream == stream) break; stream = input_stream; } /* From here on it must be a stream with FSrcStreamData. */ /* ??? Shall one rather check : stream->class == extern IsoStreamIface fsrc_stream_class (its storage location is global in stream.c) */ if (stream->class->type[0] != 'f' || stream->class->type[1] != 's' || stream->class->type[2] != 'r' || stream->class->type[3] != 'c') return 0; data = stream->data; ifsdata = data->src->data; *section_count = ifsdata->nsections; if (*section_count <= 0) return 1; *sections = malloc(ifsdata->nsections * sizeof(struct iso_file_section)); if (*sections == NULL) { return ISO_OUT_OF_MEM; } memcpy(*sections, ifsdata->sections, ifsdata->nsections * sizeof(struct iso_file_section)); return 1; } return 0; } /* Rank two IsoFileSource by their eventual old image LBAs if still non-zero. Other IsoFileSource classes and zeroized LBAs will be ranked only roughly. flag bit0 preserves transitivity of the caller by evaluating ifs_class with non-zero block address as smaller than anything else. flag bit1 could harm reproducibility of ISO image output. @param flag bit0= if s1 exor s2 is of applicable class, then enforce a valid test result by comparing classes bit1= if both are applicable but also have sections[].block == 0 then enforce a valid test result by comparing object addresses. */ int iso_ifs_sections_cmp(IsoFileSource *s1, IsoFileSource *s2, int *cmp_ret, int flag) { int i; ImageFileSourceData *d1 = NULL, *d2 = NULL; IsoFileSourceIface *class1 = NULL, *class2 = NULL; /* Newly created IsoFileSrc from imported IsoFile (e.g. boot image) is not an applicable source. It must be kept from causing a decision with other non-applicables. */ if (s1 != NULL) { class1 = (IsoFileSourceIface *) s1->class; if (class1 == &ifs_class) { d1 = (ImageFileSourceData *) s1->data; if (d1->nsections > 0) if (d1->sections[0].block == 0) class1 = NULL; } } if (s2 != NULL) { class2 = (IsoFileSourceIface *) s2->class; if (class2 == &ifs_class) { d2 = (ImageFileSourceData *) s2->data; if (d2->nsections > 0) if (d2->sections[0].block == 0) class2 = NULL; } } if (class1 != &ifs_class && class2 != &ifs_class) { *cmp_ret = 0; return 0; } if (class1 != class2) { *cmp_ret = (class1 == &ifs_class ? -1 : 1); if (flag & 1) return 1; return 0; } if (d1->nsections != d2->nsections) { *cmp_ret = d1->nsections < d2->nsections ? -1 : 1; return 1; } if (d1->nsections == 0) { *cmp_ret = 0; return 1; } if (d1->sections[0].size < 1 || d2->sections[0].size < 1) { if (d1->sections[0].size > d2->sections[0].size) *cmp_ret = 1; else if (d1->sections[0].size < d2->sections[0].size) *cmp_ret = -1; else *cmp_ret = 0; return 1; } for (i = 0; i < d1->nsections; i++) { if (d1->sections[i].block != d2->sections[i].block) { *cmp_ret = (d1->sections[i].block < d2->sections[i].block ? -1 : 1); return 1; } if (d1->sections[i].size != d2->sections[i].size) { *cmp_ret = (d1->sections[i].size < d2->sections[i].size ? -1 : 1); return 1; } } *cmp_ret = 0; return 1; } libisofs-1.4.2/libisofs/hfsplus.c0000644000175700017510000016500512606205053013731 00000000000000/* * Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2007 Mario Danic * Copyright (c) 2011-2012 Thomas Schmitt * Copyright (c) 2012 Vladimir Serbinenko * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ /* Some extra debugging messages for Vladimir Serbinenko #define Libisofs_hfsplus_verbose_debuG yes */ /* Some extra debugging messages for Thomas Schmitt */ #define Libisofs_ts_debuG yes #ifdef HAVE_CONFIG_H #include "../config.h" #endif #include "hfsplus.h" #include "messages.h" #include "writer.h" #include "image.h" #include "filesrc.h" #include "eltorito.h" #include "libisofs.h" #include "util.h" #include "ecma119.h" #include "system_area.h" #include #include #include /* To be used if Ecma119.hfsplus_block_size == 0 in hfsplus_writer_create(). It cannot be larger than 2048 because filesrc_writer aligns data file content start to 2048. */ #define HFSPLUS_DEFAULT_BLOCK_SIZE 2048 /* To be used with storage allocation. */ #define HFSPLUS_MAX_BLOCK_SIZE 2048 /* In libisofs/hfsplus_case.c */ extern uint16_t iso_hfsplus_cichar(uint16_t x); /* ts B20623: pad up output block to full 2048 bytes */ static int pad_up_block(Ecma119Image *t) { int ret; static char buffer[2048], buf_zeroed = 0; if (!buf_zeroed) { memset(buffer, 0, 2048); buf_zeroed = 1; } if (t->bytes_written % 2048) { ret = iso_write(t, buffer, 2048 - (t->bytes_written % 2048)); if (ret < 0) return ret; } return 1; } static int filesrc_block_and_size(Ecma119Image *t, IsoFileSrc *src, uint32_t *start_block, uint64_t *total_size) { int i; uint32_t pos; *start_block = 0; *total_size = 0; if (src->nsections <= 0) return 0; pos = *start_block = src->sections[0].block; for (i = 0; i < src->nsections; i++) { *total_size += src->sections[i].size; if (pos != src->sections[i].block) { iso_msg_submit(t->image->id, ISO_SECT_SCATTERED, 0, "File sections do not form consequtive array of blocks"); return ISO_SECT_SCATTERED; } /* If .size is not aligned to blocks then there is a byte gap. No need to trace the exact byte address. */ pos = src->sections[i].block + src->sections[i].size / 2048; } return 1; } static uint8_t get_class (uint16_t v) { uint16_t s; uint8_t high, low; s = iso_ntohs (v); high = s >> 8; low = v & 0xff; if (!hfsplus_class_pages[high]) return 0; return hfsplus_class_pages[high][low]; } int iso_get_hfsplus_name(char *input_charset, int imgid, char *name, uint16_t **result, uint32_t *result_len, uint16_t **cmp_name) { int ret; uint16_t *ucs_name, *iptr, *optr; uint32_t curlen; int done; if (name == NULL) { /* it is not necessarily an error, it can be the root */ return ISO_SUCCESS; } ret = str2utf16be(input_charset, name, &ucs_name); if (ret < 0) { iso_msg_debug(imgid, "Cannot convert '%s'", name); return ret; } curlen = ucslen (ucs_name); *result = calloc ((curlen * HFSPLUS_MAX_DECOMPOSE_LEN + 1), sizeof (uint16_t)); if (*result == NULL) { free(ucs_name); return ISO_OUT_OF_MEM; } for (iptr = ucs_name, optr = *result; *iptr; iptr++) { const uint16_t *dptr; uint16_t val = iso_ntohs (*iptr); uint8_t high = val >> 8; uint8_t low = val & 0xff; if (val == ':') { *optr++ = iso_htons ('/'); continue; } if (val >= 0xac00 && val <= 0xd7a3) { uint16_t s, l, v, t; s = val - 0xac00; l = s / (21 * 28); v = (s % (21 * 28)) / 28; t = s % 28; *optr++ = iso_htons (l + 0x1100); *optr++ = iso_htons (v + 0x1161); if (t) *optr++ = iso_htons (t + 0x11a7); continue; } if (!hfsplus_decompose_pages[high]) { *optr++ = *iptr; continue; } dptr = hfsplus_decompose_pages[high][low]; if (!dptr[0]) { *optr++ = *iptr; continue; } for (; *dptr; dptr++) *optr++ = iso_htons (*dptr); } *optr = 0; do { uint8_t last_class; done = 0; if (!ucs_name[0]) break; last_class = get_class (ucs_name[0]); for (optr = *result + 1; *optr; optr++) { uint8_t new_class = get_class (*optr); if (last_class == 0 || new_class == 0 || last_class <= new_class) last_class = new_class; else { uint16_t t; t = *(optr - 1); *(optr - 1) = *optr; *optr = t; } } } while (done); *cmp_name = calloc ((ucslen (*result) + 1), sizeof (uint16_t)); if (*cmp_name == NULL) { free(ucs_name); free(*result); *result = NULL; return ISO_OUT_OF_MEM; } for (iptr = *result, optr = *cmp_name; *iptr; iptr++) { *optr = iso_hfsplus_cichar(*iptr); if (*optr != 0) optr++; } *optr = 0; free (ucs_name); *result_len = ucslen (*result); return ISO_SUCCESS; } static int set_hfsplus_name(Ecma119Image *t, char *name, HFSPlusNode *node) { int ret; ret = iso_get_hfsplus_name(t->input_charset, t->image->id, name, &(node->name), &(node->strlen), &(node->cmp_name)); return ret; } /* >>> ts B20617 This should be HFSPlusNode rather than IsoNode in order to have access to IsoFileSrc.no_write which indicates that the file content will not be in written the range of filesrc_writer. */ static int hfsplus_count_tree(Ecma119Image *t, IsoNode *iso) { if (t == NULL || iso == NULL) { return ISO_NULL_POINTER; } if (iso->hidden & LIBISO_HIDE_ON_HFSPLUS) { /* file will be ignored */ return 0; } switch (iso->type) { case LIBISO_SYMLINK: case LIBISO_SPECIAL: case LIBISO_FILE: t->hfsp_nfiles++; return ISO_SUCCESS; case LIBISO_DIR: t->hfsp_ndirs++; { IsoNode *pos; IsoDir *dir = (IsoDir*)iso; pos = dir->children; while (pos) { int cret; cret = hfsplus_count_tree(t, pos); if (cret < 0) { /* error */ return cret; } pos = pos->next; } } return ISO_SUCCESS; case LIBISO_BOOT: return ISO_SUCCESS; default: /* should never happen */ return ISO_ASSERT_FAILURE; } } /** * Create the low level Hfsplus tree from the high level ISO tree. * * @return * 1 success, 0 file ignored, < 0 error */ static int create_tree(Ecma119Image *t, IsoNode *iso, uint32_t parent_id) { int ret; uint32_t cat_id, cleaf; int i; if (t == NULL || iso == NULL) { return ISO_NULL_POINTER; } if (iso->hidden & LIBISO_HIDE_ON_HFSPLUS) { /* file will be ignored */ return 0; } if (iso->type != LIBISO_FILE && iso->type != LIBISO_DIR && iso->type != LIBISO_SYMLINK && iso->type != LIBISO_SPECIAL) return 0; cat_id = t->hfsp_cat_id++; for (i = 0; i < ISO_HFSPLUS_BLESS_MAX; i++) if (t->hfsplus_blessed[i] == iso) { #ifdef Libisofs_ts_debuG iso_msg_debug(t->image->id, "hfsplus bless %d to cat_id %u ('%s')", i, cat_id, iso->name); #endif /* Libisofs_ts_debuG */ t->hfsp_bless_id[i] = cat_id; } t->hfsp_leafs[t->hfsp_curleaf].node = iso; t->hfsp_leafs[t->hfsp_curleaf].parent_id = parent_id; ret = set_hfsplus_name (t, iso->name, &t->hfsp_leafs[t->hfsp_curleaf]); if (ret < 0) return ret; t->hfsp_leafs[t->hfsp_curleaf].cat_id = cat_id; t->hfsp_leafs[t->hfsp_curleaf].unix_type = UNIX_NONE; t->hfsp_leafs[t->hfsp_curleaf].symlink_dest = NULL; switch (iso->type) { case LIBISO_SYMLINK: { IsoSymlink *sym = (IsoSymlink*) iso; t->hfsp_leafs[t->hfsp_curleaf].type = HFSPLUS_FILE; t->hfsp_leafs[t->hfsp_curleaf].symlink_dest = strdup(sym->dest); if (t->hfsp_leafs[t->hfsp_curleaf].symlink_dest == NULL) return ISO_OUT_OF_MEM; t->hfsp_leafs[t->hfsp_curleaf].unix_type = UNIX_SYMLINK; t->hfsp_leafs[t->hfsp_curleaf].used_size = t->hfsp_leafs[t->hfsp_curleaf].strlen * 2 + 8 + 2 + sizeof (struct hfsplus_catfile_common) + 2 * sizeof (struct hfsplus_forkdata); break; } case LIBISO_SPECIAL: t->hfsp_leafs[t->hfsp_curleaf].unix_type = UNIX_SPECIAL; t->hfsp_leafs[t->hfsp_curleaf].type = HFSPLUS_FILE; t->hfsp_leafs[t->hfsp_curleaf].used_size = t->hfsp_leafs[t->hfsp_curleaf].strlen * 2 + 8 + 2 + sizeof (struct hfsplus_catfile_common) + 2 * sizeof (struct hfsplus_forkdata); break; case LIBISO_FILE: { IsoFile *file = (IsoFile*) iso; t->hfsp_leafs[t->hfsp_curleaf].type = HFSPLUS_FILE; ret = iso_file_src_create(t, file, &t->hfsp_leafs[t->hfsp_curleaf].file); if (ret < 0) { return ret; } t->hfsp_leafs[t->hfsp_curleaf].used_size = t->hfsp_leafs[t->hfsp_curleaf].strlen * 2 + 8 + 2 + sizeof (struct hfsplus_catfile_common) + 2 * sizeof (struct hfsplus_forkdata); } break; case LIBISO_DIR: { t->hfsp_leafs[t->hfsp_curleaf].type = HFSPLUS_DIR; t->hfsp_leafs[t->hfsp_curleaf].used_size = t->hfsp_leafs[t->hfsp_curleaf].strlen * 2 + 8 + 2 + sizeof (struct hfsplus_catfile_common); break; } default: return ISO_ASSERT_FAILURE; } cleaf = t->hfsp_curleaf; t->hfsp_leafs[t->hfsp_curleaf].nchildren = 0; t->hfsp_curleaf++; t->hfsp_leafs[t->hfsp_curleaf].name = t->hfsp_leafs[t->hfsp_curleaf - 1].name; t->hfsp_leafs[t->hfsp_curleaf].cmp_name = NULL; t->hfsp_leafs[t->hfsp_curleaf].strlen = t->hfsp_leafs[t->hfsp_curleaf - 1].strlen; t->hfsp_leafs[t->hfsp_curleaf].used_size = t->hfsp_leafs[t->hfsp_curleaf].strlen * 2 + 8 + 2 + sizeof (struct hfsplus_catfile_thread); t->hfsp_leafs[t->hfsp_curleaf].node = iso; t->hfsp_leafs[t->hfsp_curleaf].type = (iso->type == LIBISO_DIR) ? HFSPLUS_DIR_THREAD : HFSPLUS_FILE_THREAD; t->hfsp_leafs[t->hfsp_curleaf].file = 0; t->hfsp_leafs[t->hfsp_curleaf].cat_id = parent_id; t->hfsp_leafs[t->hfsp_curleaf].parent_id = cat_id; t->hfsp_leafs[t->hfsp_curleaf].unix_type = UNIX_NONE; t->hfsp_curleaf++; if (iso->type == LIBISO_DIR) { IsoNode *pos; IsoDir *dir = (IsoDir*)iso; pos = dir->children; while (pos) { int cret; cret = create_tree(t, pos, cat_id); if (cret < 0) return cret; pos = pos->next; t->hfsp_leafs[cleaf].nchildren++; } } return ISO_SUCCESS; } static int cmp_node(const void *f1, const void *f2) { HFSPlusNode *f = (HFSPlusNode*) f1; HFSPlusNode *g = (HFSPlusNode*) f2; const uint16_t empty[1] = {0}; const uint16_t *a, *b; if (f->parent_id > g->parent_id) return +1; if (f->parent_id < g->parent_id) return -1; a = f->cmp_name; b = g->cmp_name; if (!a) a = empty; if (!b) b = empty; return ucscmp(a, b); } static int hfsplus_tail_writer_compute_data_blocks(IsoImageWriter *writer) { Ecma119Image *t; uint32_t hfsp_size, hfsp_curblock, block_fac, block_size; if (writer == NULL) { return ISO_OUT_OF_MEM; } t = writer->target; block_size = t->opts->hfsp_block_size; block_fac = t->hfsp_iso_block_fac; #ifdef Libisofs_ts_debuG iso_msg_debug(t->image->id, "hfsplus tail writer start = %.f", ((double) t->curblock) * 2048.0); #endif hfsp_curblock = t->curblock * block_fac; hfsp_size = hfsp_curblock - t->hfsp_part_start + 1; /* We need one bit for every block. */ /* So if we allocate x blocks we have to satisfy: 8 * block_size * x >= total_size + x (8 * block_size - 1) * x >= total_size */ t->hfsp_allocation_blocks = hfsp_size / (8 * block_size - 1) + 1; t->hfsp_allocation_file_start = hfsp_curblock; hfsp_curblock += t->hfsp_allocation_blocks; /* write_data() will need to pad up ISO block before superblock copy */ t->curblock = hfsp_curblock / block_fac; if (hfsp_curblock % block_fac) t->curblock++; hfsp_curblock = t->curblock * block_fac; /* Superblock always occupies 2K */ hfsp_curblock += block_fac; t->curblock++; #ifdef Libisofs_ts_debuG iso_msg_debug(t->image->id, "hfsplus tail writer end = %.f", ((double) hfsp_curblock) * block_size); #endif t->hfsp_total_blocks = hfsp_curblock - t->hfsp_part_start; return iso_quick_apm_entry(t->apm_req, &(t->apm_req_count), t->hfsp_part_start / block_fac, t->hfsp_total_blocks / block_fac + !!(t->hfsp_total_blocks % block_fac), "HFSPLUS_Hybrid", "Apple_HFS"); } static int hfsplus_writer_compute_data_blocks(IsoImageWriter *writer) { Ecma119Image *t; uint32_t i, hfsp_curblock; uint32_t block_fac, block_size; if (writer == NULL) { return ISO_OUT_OF_MEM; } t = writer->target; block_size = t->opts->hfsp_block_size; block_fac = t->hfsp_iso_block_fac; iso_msg_debug(t->image->id, "(b) curblock=%d, nodes =%d", t->curblock, t->hfsp_nnodes); t->hfsp_part_start = t->curblock * block_fac; hfsp_curblock = t->curblock * block_fac; /* Superblock always occupies 2K */ hfsp_curblock += block_fac; t->hfsp_catalog_file_start = hfsp_curblock; /* hfsp_curblock += (t->hfsp_nnodes * t->hfsp_cat_node_size + block_size - 1) / block_size; */ hfsp_curblock += 2 * t->hfsp_nnodes; t->hfsp_extent_file_start = hfsp_curblock; hfsp_curblock++; iso_msg_debug(t->image->id, "(d) hfsp_curblock=%d, nodes =%d", hfsp_curblock, t->hfsp_nnodes); for (i = 0; i < t->hfsp_nleafs; i++) if (t->hfsp_leafs[i].unix_type == UNIX_SYMLINK) { t->hfsp_leafs[i].symlink_block = hfsp_curblock; hfsp_curblock += (strlen(t->hfsp_leafs[i].symlink_dest) + block_size - 1) / block_size; } t->curblock = hfsp_curblock / block_fac; if (hfsp_curblock % block_fac) t->curblock++; iso_msg_debug(t->image->id, "(a) curblock=%d, nodes =%d", t->curblock, t->hfsp_nnodes); return ISO_SUCCESS; } static void set_time (uint32_t *tm, uint32_t t) { iso_msb ((uint8_t *) tm, t + 2082844800, 4); } int nop_writer_write_vol_desc(IsoImageWriter *writer) { return ISO_SUCCESS; } static uid_t px_get_uid(Ecma119Image *t, IsoNode *n) { if (t->replace_uid) { return t->uid; } else { return n->uid; } } static uid_t px_get_gid(Ecma119Image *t, IsoNode *n) { if (t->replace_gid) { return t->gid; } else { return n->gid; } } static mode_t px_get_mode(Ecma119Image *t, IsoNode *n, int isdir) { if (isdir) { if (t->replace_dir_mode) { return (n->mode & S_IFMT) | t->dir_mode; } } else { if (t->replace_file_mode) { return (n->mode & S_IFMT) | t->file_mode; } } return n->mode; } int write_sb (Ecma119Image *t) { struct hfsplus_volheader sb; static char buffer[1024]; int ret; int i; uint32_t block_size; iso_msg_debug(t->image->id, "Write HFS+ superblock"); block_size = t->opts->hfsp_block_size; memset (buffer, 0, sizeof (buffer)); ret = iso_write(t, buffer, 1024); if (ret < 0) return ret; memset (&sb, 0, sizeof (sb)); t->hfsp_allocation_size = (t->hfsp_total_blocks + 7) >> 3; iso_msb ((uint8_t *) &sb.magic, 0x482b, 2); iso_msb ((uint8_t *) &sb.version, 4, 2); /* Cleanly unmounted, software locked. */ iso_msb ((uint8_t *) &sb.attributes, (1 << 8) | (1 << 15), 4); iso_msb ((uint8_t *) &sb.last_mounted_version, 0x6c69736f, 4); set_time (&sb.ctime, t->now); set_time (&sb.utime, t->now); set_time (&sb.fsck_time, t->now); iso_msb ((uint8_t *) &sb.file_count, t->hfsp_nfiles, 4); iso_msb ((uint8_t *) &sb.folder_count, t->hfsp_ndirs - 1, 4); iso_msb ((uint8_t *) &sb.blksize, block_size, 4); iso_msb ((uint8_t *) &sb.catalog_node_id, t->hfsp_cat_id, 4); iso_msb ((uint8_t *) &sb.rsrc_clumpsize, block_size, 4); iso_msb ((uint8_t *) &sb.data_clumpsize, block_size, 4); iso_msb ((uint8_t *) &sb.total_blocks, t->hfsp_total_blocks, 4); iso_msb ((uint8_t *) &sb.encodings_bitmap + 4, 1, 4); iso_msb ((uint8_t *) &sb.allocations_file.size + 4, t->hfsp_allocation_size, 4); iso_msb ((uint8_t *) &sb.allocations_file.clumpsize, block_size, 4); iso_msb ((uint8_t *) &sb.allocations_file.blocks, (t->hfsp_allocation_size + block_size - 1) / block_size, 4); iso_msb ((uint8_t *) &sb.allocations_file.extents[0].start, t->hfsp_allocation_file_start - t->hfsp_part_start, 4); iso_msb ((uint8_t *) &sb.allocations_file.extents[0].count, (t->hfsp_allocation_size + block_size - 1) / block_size, 4); iso_msb ((uint8_t *) &sb.extents_file.size + 4, block_size, 4); iso_msb ((uint8_t *) &sb.extents_file.clumpsize, block_size, 4); iso_msb ((uint8_t *) &sb.extents_file.blocks, 1, 4); iso_msb ((uint8_t *) &sb.extents_file.extents[0].start, t->hfsp_extent_file_start - t->hfsp_part_start, 4); iso_msb ((uint8_t *) &sb.extents_file.extents[0].count, 1, 4); iso_msg_debug(t->image->id, "extent_file_start = %d\n", (int)t->hfsp_extent_file_start); iso_msb ((uint8_t *) &sb.catalog_file.size + 4, block_size * 2 * t->hfsp_nnodes, 4); iso_msb ((uint8_t *) &sb.catalog_file.clumpsize, block_size * 2, 4); iso_msb ((uint8_t *) &sb.catalog_file.blocks, 2 * t->hfsp_nnodes, 4); iso_msb ((uint8_t *) &sb.catalog_file.extents[0].start, t->hfsp_catalog_file_start - t->hfsp_part_start, 4); iso_msb ((uint8_t *) &sb.catalog_file.extents[0].count, 2 * t->hfsp_nnodes, 4); iso_msg_debug(t->image->id, "catalog_file_start = %d\n", (int)t->hfsp_catalog_file_start); for (i = 0; i < ISO_HFSPLUS_BLESS_MAX; i++) { iso_msb ((uint8_t *) (&sb.ppc_bootdir + i + (i == ISO_HFSPLUS_BLESS_OSX_FOLDER)), t->hfsp_bless_id[i], 4); #ifdef Libisofs_ts_debuG iso_msg_debug(t->image->id, "hfsplus bless %d written for cat_id %u", i, t->hfsp_bless_id[i]); #endif /* Libisofs_ts_debuG */ } memcpy (&sb.num_serial, &t->opts->hfsp_serial_number, 8); ret = iso_write(t, &sb, sizeof (sb)); if (ret < 0) return ret; return iso_write(t, buffer, 512); } static int hfsplus_writer_write_data(IsoImageWriter *writer) { int ret; static char buffer[2 * HFSPLUS_MAX_BLOCK_SIZE]; Ecma119Image *t; struct hfsplus_btnode *node_head; struct hfsplus_btheader *tree_head; int level; uint32_t curpos = 1, i, block_fac, cat_node_size, block_size; if (writer == NULL) { return ISO_NULL_POINTER; } t = writer->target; block_size = t->opts->hfsp_block_size; block_fac = t->hfsp_iso_block_fac; cat_node_size = t->hfsp_cat_node_size; iso_msg_debug(t->image->id, "(b) %d written", (int) t->bytes_written / 0x800); ret = write_sb (t); if (ret < 0) return ret; iso_msg_debug(t->image->id, "(c) %d written", (int) t->bytes_written / 0x800); iso_msg_debug(t->image->id, "real catalog_file_start = %d\n", (int)t->bytes_written / 2048); memset (buffer, 0, sizeof (buffer)); node_head = (struct hfsplus_btnode *) buffer; node_head->type = 1; iso_msb ((uint8_t *) &node_head->count, 3, 2); tree_head = (struct hfsplus_btheader *) (node_head + 1); iso_msb ((uint8_t *) &tree_head->depth, t->hfsp_nlevels, 2); iso_msb ((uint8_t *) &tree_head->root, 1, 4); iso_msb ((uint8_t *) &tree_head->leaf_records, t->hfsp_nleafs, 4); iso_msb ((uint8_t *) &tree_head->first_leaf_node, t->hfsp_nnodes - t->hfsp_levels[0].level_size, 4); iso_msb ((uint8_t *) &tree_head->last_leaf_node, t->hfsp_nnodes - 1, 4); iso_msb ((uint8_t *) &tree_head->nodesize, cat_node_size, 2); iso_msb ((uint8_t *) &tree_head->keysize, 6 + 2 * LIBISO_HFSPLUS_NAME_MAX, 2); iso_msb ((uint8_t *) &tree_head->total_nodes, t->hfsp_nnodes, 4); iso_msb ((uint8_t *) &tree_head->free_nodes, 0, 4); iso_msb ((uint8_t *) &tree_head->clump_size, cat_node_size, 4); tree_head->key_compare = 0xcf; iso_msb ((uint8_t *) &tree_head->attributes, 2 | 4, 4); memset (buffer + 0xf8, -1, t->hfsp_nnodes / 8); buffer[0xf8 + (t->hfsp_nnodes / 8)] = 0xff00 >> (t->hfsp_nnodes % 8); buffer[cat_node_size - 1] = sizeof (*node_head); buffer[cat_node_size - 3] = sizeof (*node_head) + sizeof (*tree_head); buffer[cat_node_size - 5] = (char) 0xf8; buffer[cat_node_size - 7] = (char) ((cat_node_size - 8) & 0xff); buffer[cat_node_size - 8] = (cat_node_size - 8) >> 8; #ifdef Libisofs_hfsplus_verbose_debuG iso_msg_debug(t->image->id, "Write\n"); #endif ret = iso_write(t, buffer, cat_node_size); if (ret < 0) return ret; for (level = t->hfsp_nlevels - 1; level > 0; level--) { uint32_t i; uint32_t next_lev = curpos + t->hfsp_levels[level].level_size; for (i = 0; i < t->hfsp_levels[level].level_size; i++) { uint32_t curoff; uint32_t j; uint32_t curnode = t->hfsp_levels[level].nodes[i].start; memset (buffer, 0, sizeof (buffer)); node_head = (struct hfsplus_btnode *) buffer; if (i != t->hfsp_levels[level].level_size - 1) iso_msb ((uint8_t *) &node_head->next, curpos + i + 1, 4); if (i != 0) iso_msb ((uint8_t *) &node_head->prev, curpos + i - 1, 4); node_head->type = 0; node_head->height = level + 1; iso_msb ((uint8_t *) &node_head->count, t->hfsp_levels[level].nodes[i].cnt, 2); curoff = sizeof (struct hfsplus_btnode); for (j = 0; j < t->hfsp_levels[level].nodes[i].cnt; j++) { iso_msb ((uint8_t *) buffer + cat_node_size - j * 2 - 2, curoff, 2); iso_msb ((uint8_t *) buffer + curoff, 2 * t->hfsp_levels[level - 1].nodes[curnode].strlen + 6, 2); iso_msb ((uint8_t *) buffer + curoff + 2, t->hfsp_levels[level - 1].nodes[curnode].parent_id, 4); iso_msb ((uint8_t *) buffer + curoff + 6, t->hfsp_levels[level - 1].nodes[curnode].strlen, 2); curoff += 8; memcpy ((uint8_t *) buffer + curoff, t->hfsp_levels[level - 1].nodes[curnode].str, 2 * t->hfsp_levels[level - 1].nodes[curnode].strlen); curoff += 2 * t->hfsp_levels[level - 1].nodes[curnode].strlen; iso_msb ((uint8_t *) buffer + curoff, next_lev + curnode, 4); curoff += 4; curnode++; } iso_msb ((uint8_t *) buffer + cat_node_size - j * 2 - 2, curoff, 2); #ifdef Libisofs_hfsplus_verbose_debuG iso_msg_debug(t->image->id, "Write\n"); #endif ret = iso_write(t, buffer, cat_node_size); if (ret < 0) return ret; } curpos = next_lev; } { uint32_t i; uint32_t next_lev = curpos + t->hfsp_levels[level].level_size; for (i = 0; i < t->hfsp_levels[level].level_size; i++) { uint32_t curoff; uint32_t j; uint32_t curnode = t->hfsp_levels[level].nodes[i].start; memset (buffer, 0, sizeof (buffer)); node_head = (struct hfsplus_btnode *) buffer; if (i != t->hfsp_levels[level].level_size - 1) iso_msb ((uint8_t *) &node_head->next, curpos + i + 1, 4); if (i != 0) iso_msb ((uint8_t *) &node_head->prev, curpos + i - 1, 4); node_head->type = -1; node_head->height = level + 1; iso_msb ((uint8_t *) &node_head->count, t->hfsp_levels[level].nodes[i].cnt, 2); curoff = sizeof (struct hfsplus_btnode); for (j = 0; j < t->hfsp_levels[level].nodes[i].cnt; j++) { iso_msb ((uint8_t *) buffer + cat_node_size - j * 2 - 2, curoff, 2); #ifdef Libisofs_hfsplus_verbose_debuG if (t->hfsp_leafs[curnode].node->name == NULL) { iso_msg_debug(t->image->id, "%d out of %d", (int) curnode, t->hfsp_nleafs); } else { iso_msg_debug(t->image->id, "%d out of %d, %s", (int) curnode, t->hfsp_nleafs, t->hfsp_leafs[curnode].node->name); } #endif /* Libisofs_hfsplus_verbose_debuG */ switch (t->hfsp_leafs[curnode].type) { case HFSPLUS_FILE_THREAD: case HFSPLUS_DIR_THREAD: { struct hfsplus_catfile_thread *thread; iso_msb ((uint8_t *) buffer + curoff, 6, 2); iso_msb ((uint8_t *) buffer + curoff + 2, t->hfsp_leafs[curnode].parent_id, 4); iso_msb ((uint8_t *) buffer + curoff + 6, 0, 2); curoff += 8; thread = (struct hfsplus_catfile_thread *) (buffer + curoff); ((uint8_t *) &thread->type)[1] = t->hfsp_leafs[curnode].type; iso_msb ((uint8_t *) &thread->parentid, t->hfsp_leafs[curnode].cat_id, 4); iso_msb ((uint8_t *) &thread->namelen, t->hfsp_leafs[curnode].strlen, 2); curoff += sizeof (*thread); memcpy (buffer + curoff, t->hfsp_leafs[curnode].name, t->hfsp_leafs[curnode].strlen * 2); curoff += t->hfsp_leafs[curnode].strlen * 2; break; } case HFSPLUS_FILE: case HFSPLUS_DIR: { struct hfsplus_catfile_common *common; struct hfsplus_forkdata *data_fork; iso_msb ((uint8_t *) buffer + curoff, 6 + 2 * t->hfsp_leafs[curnode].strlen, 2); iso_msb ((uint8_t *) buffer + curoff + 2, t->hfsp_leafs[curnode].parent_id, 4); iso_msb ((uint8_t *) buffer + curoff + 6, t->hfsp_leafs[curnode].strlen, 2); curoff += 8; memcpy (buffer + curoff, t->hfsp_leafs[curnode].name, t->hfsp_leafs[curnode].strlen * 2); curoff += t->hfsp_leafs[curnode].strlen * 2; common = (struct hfsplus_catfile_common *) (buffer + curoff); ((uint8_t *) &common->type)[1] = t->hfsp_leafs[curnode].type; iso_msb ((uint8_t *) &common->valence, t->hfsp_leafs[curnode].nchildren, 4); iso_msb ((uint8_t *) &common->fileid, t->hfsp_leafs[curnode].cat_id, 4); set_time (&common->ctime, t->hfsp_leafs[curnode].node->ctime); set_time (&common->mtime, t->hfsp_leafs[curnode].node->mtime); /* FIXME: distinguish attr_mtime and mtime. */ set_time (&common->attr_mtime, t->hfsp_leafs[curnode].node->mtime); set_time (&common->atime, t->hfsp_leafs[curnode].node->atime); iso_msb ((uint8_t *) &common->uid, px_get_uid (t, t->hfsp_leafs[curnode].node), 4); iso_msb ((uint8_t *) &common->gid, px_get_gid (t, t->hfsp_leafs[curnode].node), 4); iso_msb ((uint8_t *) &common->mode, px_get_mode (t, t->hfsp_leafs[curnode].node, (t->hfsp_leafs[curnode].type == HFSPLUS_DIR)), 2); /* FIXME: uint8_t user_flags; uint8_t group_flags; finder info */ if (t->hfsp_leafs[curnode].type == HFSPLUS_FILE) { if (t->hfsp_leafs[curnode].unix_type == UNIX_SYMLINK) { memcpy (common->file_type, "slnk", 4); memcpy (common->file_creator, "rhap", 4); } else { struct iso_hfsplus_xinfo_data *xinfo; ret = iso_node_get_xinfo(t->hfsp_leafs[curnode].node, iso_hfsplus_xinfo_func, (void *) &xinfo); if (ret > 0) { memcpy (common->file_type, xinfo->type_code, 4); memcpy (common->file_creator, xinfo->creator_code, 4); #ifdef Libisofs_ts_debuG { char crtp[14]; crtp[0] = '\''; memcpy(crtp+1, xinfo->creator_code, 4); strcpy(crtp + 5, "','"); memcpy(crtp + 8, xinfo->type_code, 4); crtp[12] = '\''; crtp[13]= 0; iso_msg_debug(t->image->id, "hfsplus creator,type %s to '%s/%s'", crtp, ((IsoNode *) t->hfsp_leafs[curnode].node->parent)->name, t->hfsp_leafs[curnode].node->name); } #endif /* Libisofs_ts_debuG */ } else if (ret < 0) return ret; else { memcpy (common->file_type, "????", 4); memcpy (common->file_creator, "????", 4); } } if (t->hfsp_leafs[curnode].unix_type == UNIX_SPECIAL && (S_ISBLK(t->hfsp_leafs[curnode].node->mode) || S_ISCHR(t->hfsp_leafs[curnode].node->mode))) iso_msb ((uint8_t *) &common->special, (((IsoSpecial*) t->hfsp_leafs[curnode].node)->dev & 0xffffffff), 4); iso_msb ((uint8_t *) &common->flags, 2, 2); } else if (t->hfsp_leafs[curnode].type == HFSPLUS_DIR) { iso_msb ((uint8_t *) &common->flags, 0, 2); } curoff += sizeof (*common); if (t->hfsp_leafs[curnode].type == HFSPLUS_FILE) { uint64_t sz; uint32_t blk; data_fork = (struct hfsplus_forkdata *) (buffer + curoff); if (t->hfsp_leafs[curnode].unix_type == UNIX_SYMLINK) { blk = t->hfsp_leafs[curnode].symlink_block; sz = strlen(t->hfsp_leafs[curnode].symlink_dest); } else if (t->hfsp_leafs[curnode].unix_type == UNIX_SPECIAL) { blk = 0; sz = 0; } else { ret = filesrc_block_and_size(t, t->hfsp_leafs[curnode].file, &blk, &sz); if (ret <= 0) return ret; blk *= block_fac; } if (sz == 0) blk = t->hfsp_part_start; iso_msb ((uint8_t *) &data_fork->size, sz >> 32, 4); iso_msb ((uint8_t *) &data_fork->size + 4, sz, 4); iso_msb ((uint8_t *) &data_fork->clumpsize, block_size, 4); iso_msb ((uint8_t *) &data_fork->blocks, (sz + block_size - 1) / block_size, 4); iso_msb ((uint8_t *) &data_fork->extents[0].start, blk - t->hfsp_part_start, 4); iso_msb ((uint8_t *) &data_fork->extents[0].count, (sz + block_size - 1) / block_size, 4); curoff += sizeof (*data_fork) * 2; /* FIXME: resource fork */ } break; } } curnode++; } iso_msb ((uint8_t *) buffer + cat_node_size - j * 2 - 2, curoff, 2); #ifdef Libisofs_hfsplus_verbose_debuG iso_msg_debug(t->image->id, "Write\n"); #endif ret = iso_write(t, buffer, cat_node_size); if (ret < 0) return ret; } curpos = next_lev; } memset (buffer, 0, sizeof (buffer)); iso_msg_debug(t->image->id, "real extent_file_start = %d\n", (int)t->bytes_written / 2048); node_head = (struct hfsplus_btnode *) buffer; node_head->type = 1; iso_msb ((uint8_t *) &node_head->count, 3, 2); tree_head = (struct hfsplus_btheader *) (node_head + 1); iso_msb ((uint8_t *) &tree_head->nodesize, block_size, 2); iso_msb ((uint8_t *) &tree_head->keysize, 10, 2); iso_msb ((uint8_t *) &tree_head->total_nodes, 1, 4); iso_msb ((uint8_t *) &tree_head->free_nodes, 0, 4); iso_msb ((uint8_t *) &tree_head->clump_size, block_size, 4); iso_msb ((uint8_t *) &tree_head->attributes, 2, 4); buffer[0xf8] = (char) 0x80; buffer[block_size - 1] = sizeof (*node_head); buffer[block_size - 3] = sizeof (*node_head) + sizeof (*tree_head); buffer[block_size - 5] = (char) 0xf8; buffer[block_size - 7] = (char) ((block_size - 8) & 0xff); buffer[block_size - 8] = (block_size - 8) >> 8; ret = iso_write(t, buffer, block_size); if (ret < 0) return ret; iso_msg_debug(t->image->id, "(d) %d written", (int) t->bytes_written / 0x800); memset (buffer, 0, sizeof (buffer)); for (i = 0; i < t->hfsp_nleafs; i++) if (t->hfsp_leafs[i].unix_type == UNIX_SYMLINK) { int overhead; ret = iso_write(t, t->hfsp_leafs[i].symlink_dest, strlen(t->hfsp_leafs[i].symlink_dest)); if (ret < 0) return ret; overhead = strlen(t->hfsp_leafs[i].symlink_dest) % block_size; if (overhead) overhead = block_size - overhead; ret = iso_write(t, buffer, overhead); if (ret < 0) return ret; } /* Need to align for start of next writer */ ret = pad_up_block(t); if (ret < 0) return ret; iso_msg_debug(t->image->id, "(a) %d written", (int) t->bytes_written / 0x800); return ISO_SUCCESS; } static int hfsplus_tail_writer_write_data(IsoImageWriter *writer) { int ret; static char buffer[2 * HFSPLUS_MAX_BLOCK_SIZE]; uint32_t complete_blocks, remaining_blocks, block_size; int over; Ecma119Image *t; if (writer == NULL) { return ISO_NULL_POINTER; } t = writer->target; block_size = t->opts->hfsp_block_size; #ifdef Libisofs_ts_debuG iso_msg_debug(t->image->id, "hfsplus tail writer writes at = %.f", (double) t->bytes_written); #endif memset (buffer, -1, sizeof (buffer)); complete_blocks = (t->hfsp_allocation_size - 1) / block_size; remaining_blocks = t->hfsp_allocation_blocks - complete_blocks; while (complete_blocks--) { ret = iso_write(t, buffer, block_size); if (ret < 0) return ret; } over = (t->hfsp_allocation_size - 1) % block_size; if (over) { memset (buffer + over, 0, sizeof (buffer) - over); buffer[over] = 0xff00 >> (t->hfsp_total_blocks % 8); ret = iso_write(t, buffer, block_size); if (ret < 0) return ret; remaining_blocks--; } memset (buffer, 0, sizeof (buffer)); /* When we have both FAT and HFS+ we may to overestimate needed blocks a bit. */ while (remaining_blocks--) { ret = iso_write(t, buffer, block_size); if (ret < 0) return ret; } ret = pad_up_block(t); if (ret < 0) return ret; iso_msg_debug(t->image->id, "%d written", (int) t->bytes_written); ret = write_sb (t); #ifdef Libisofs_ts_debuG iso_msg_debug(t->image->id, "hfsplus tail writer ends at = %.f", (double) t->bytes_written); #endif return ret; } static int hfsplus_writer_free_data(IsoImageWriter *writer) { /* free the Hfsplus tree */ Ecma119Image *t = writer->target; uint32_t i; for (i = 0; i < t->hfsp_curleaf; i++) if (t->hfsp_leafs[i].type != HFSPLUS_FILE_THREAD && t->hfsp_leafs[i].type != HFSPLUS_DIR_THREAD) { free (t->hfsp_leafs[i].name); free (t->hfsp_leafs[i].cmp_name); if (t->hfsp_leafs[i].symlink_dest != NULL) free (t->hfsp_leafs[i].symlink_dest); } free(t->hfsp_leafs); for (i = 0; i < t->hfsp_nlevels; i++) free (t->hfsp_levels[i].nodes); free(t->hfsp_levels); return ISO_SUCCESS; } static int nop_writer_free_data(IsoImageWriter *writer) { return ISO_SUCCESS; } /* ??? : Change this to binary search ? Expected advantage is low except with prefix "MANGLED". @param flag bit0= array is unsorted, do not abort on first larger element @return 0 = collision (collider in *new_idx), 1 = insert at *new_idx */ static int search_mangled_pos(Ecma119Image *target, uint32_t idx, uint32_t *new_idx, uint32_t search_start, uint32_t search_end, int flag) { uint32_t i; int rel; for (i = search_start; i < search_end; i++) { if (target->hfsp_leafs[i].type == HFSPLUS_DIR_THREAD || target->hfsp_leafs[i].type == HFSPLUS_FILE_THREAD) continue; rel = cmp_node(&(target->hfsp_leafs[idx]), &(target->hfsp_leafs[i])); if (rel == 0 && idx != i) { *new_idx = i; return 0; /* Collision */ } if (rel < 0 && !(flag & 1)) { if (i <= idx) *new_idx = i; else *new_idx = i - 1; return 1; } } *new_idx = search_end - 1; return 1; } static void rotate_hfs_list(Ecma119Image *target, uint32_t old_idx, uint32_t new_idx, int flag) { uint32_t i, sz; HFSPlusNode tr; if (old_idx == new_idx) return; sz = sizeof(HFSPlusNode); memcpy(&tr, &target->hfsp_leafs[old_idx], sz); if (old_idx > new_idx) { for (i = old_idx; i > new_idx; i--) memcpy(&target->hfsp_leafs[i], &target->hfsp_leafs[i - 1], sz); } else { for (i = old_idx; i < new_idx; i++) memcpy(&target->hfsp_leafs[i], &target->hfsp_leafs[i + 1], sz); } memcpy(&target->hfsp_leafs[new_idx], &tr, sz); } static int subst_symlink_dest_comp(Ecma119Image *target, uint32_t idx, char **dest, unsigned int *dest_len, char **comp_start, char **comp_end, char *new_name, int flag) { int new_len; unsigned int new_dest_len; char *new_dest, *wpt; new_len = strlen(new_name); new_dest_len = *comp_start - *dest + new_len + *dest_len - (*comp_end - *dest); new_dest = calloc(1, new_dest_len + 1); if (new_dest == NULL) return ISO_OUT_OF_MEM; wpt = new_dest; if (*comp_start - *dest > 0) memcpy(wpt, *dest, *comp_start - *dest); wpt += *comp_start - *dest; memcpy(wpt, new_name, new_len); wpt += new_len; if ((unsigned int) (*comp_end - *dest) < *dest_len) memcpy(wpt, *comp_end, *dest_len - (*comp_end - *dest)); wpt += *dest_len - (*comp_end - *dest); *wpt = 0; *comp_start = new_dest + (*comp_start - *dest); *comp_end = *comp_start + new_len; target->hfsp_leafs[idx].symlink_dest = new_dest; *dest_len = new_dest_len; free(*dest); *dest = new_dest; return ISO_SUCCESS; } /* A specialized version of API call iso_tree_resolve_symlink(). It updates symlink destination components which lead to the HFS+ node [changed_idx] in sync with resolution of the IsoImage destination path. It seems too much prone to weird link loopings if one would let a function underneath iso_tree_resolve_symlink() watch out for the IsoNode in question. Multiple passes through that node are possible. So this function exchanges components when encountered. */ static int update_symlink(Ecma119Image *target, uint32_t changed_idx, char *new_name, uint32_t link_idx, int *depth, int flag) { IsoSymlink *sym; IsoDir *cur_dir = NULL; IsoNode *n, *resolved_node; char *orig_dest, *orig_start, *orig_end; char *hfsp_dest, *hfsp_start, *hfsp_end; int ret = 0; unsigned int comp_len, orig_len, hfsp_len; if (target->hfsp_leafs[link_idx].node->type != LIBISO_SYMLINK) return ISO_SUCCESS; sym = (IsoSymlink *) target->hfsp_leafs[link_idx].node; orig_dest = sym->dest; orig_len = strlen(orig_dest); hfsp_dest = target->hfsp_leafs[link_idx].symlink_dest; hfsp_len = strlen(hfsp_dest); if (orig_dest[0] == '/') { /* >>> ??? How to salvage absolute links without knowing the path of the future mount point ? ??? Would it be better to leave them as is ? I can only assume that it gets mounted at / during some stage of booting. */; cur_dir = target->image->root; orig_end = orig_dest; } else { cur_dir = sym->node.parent; if (cur_dir == NULL) cur_dir = target->image->root; orig_end = orig_dest - 1; } if (hfsp_dest[0] == '/') hfsp_end = hfsp_dest; else hfsp_end = hfsp_dest - 1; while (orig_end < orig_dest + orig_len) { orig_start = orig_end + 1; hfsp_start = hfsp_end + 1; orig_end = strchr(orig_start, '/'); if (orig_end == NULL) orig_end = orig_start + strlen(orig_start); comp_len = orig_end - orig_start; hfsp_end = strchr(hfsp_start, '/'); if (hfsp_end == NULL) hfsp_end = hfsp_start + strlen(hfsp_start); if (comp_len == 0 || (comp_len == 1 && orig_start[0] == '.')) continue; if (comp_len == 2 && orig_start[0] == '.' && orig_start[1] == '.') { cur_dir = cur_dir->node.parent; if (cur_dir == NULL) /* link shoots over root */ return ISO_SUCCESS; continue; } /* Search node in cur_dir */ for (n = cur_dir->children; n != NULL; n = n->next) if (strncmp(orig_start, n->name, comp_len) == 0 && strlen(n->name) == comp_len) break; if (n == NULL) /* dead link */ return ISO_SUCCESS; if (n == target->hfsp_leafs[changed_idx].node) { iso_msg_debug(target->image->id, " link path '%s' touches RR '%s', HFS+ '%s'", orig_dest, (n->name != NULL ? n->name : ""), new_name); /* Exchange HFS+ component by new_name */ ret = subst_symlink_dest_comp(target, link_idx, &hfsp_dest, &hfsp_len, &hfsp_start, &hfsp_end, new_name, 0); if (ret < 0) return ret; } if (n->type == LIBISO_DIR) { cur_dir = (IsoDir *) n; } else if (n->type == LIBISO_SYMLINK) { /* Resolve link and check whether it is a directory */ if (*depth >= LIBISO_MAX_LINK_DEPTH) return ISO_SUCCESS; (*depth)++; ret = iso_tree_resolve_symlink(target->image, (IsoSymlink *) n, &resolved_node, depth, 0); if (ret == (int) ISO_DEAD_SYMLINK || ret == (int) ISO_DEEP_SYMLINK) return ISO_SUCCESS; if (ret < 0) return ret; if (resolved_node->type != LIBISO_DIR) return ISO_SUCCESS; cur_dir = (IsoDir *) resolved_node; } else { break; } } return ISO_SUCCESS; } /* Find the other nodes with old_name and switch to new .name One could make assumptions where name-followers are. But then there are still the symbolic links. They can be located anywhere. */ static int update_name_followers(Ecma119Image *target, uint32_t idx, char *new_name, uint16_t *old_name, uint16_t *old_cmp_name, uint32_t old_strlen) { uint32_t i; int ret, link_depth; for (i = 0; i < target->hfsp_nleafs; i++) { if (target->hfsp_leafs[i].unix_type == UNIX_SYMLINK) { link_depth = 0; ret = update_symlink(target, idx, new_name, i, &link_depth, 0); if (ret < 0) return ret; } if (target->hfsp_leafs[i].name != old_name) continue; target->hfsp_leafs[i].name = target->hfsp_leafs[idx].name; target->hfsp_leafs[i].strlen = target->hfsp_leafs[idx].strlen; if (target->hfsp_leafs[i].cmp_name == old_cmp_name) target->hfsp_leafs[i].cmp_name = target->hfsp_leafs[idx].cmp_name; if (target->hfsp_leafs[i].strlen > old_strlen) target->hfsp_leafs[i].used_size += (target->hfsp_leafs[i].strlen - old_strlen) * 2; else target->hfsp_leafs[i].used_size -= 2 * (old_strlen - target->hfsp_leafs[i].strlen); } return 1; } /* @param flag bit0= node is new: do not rotate, do not update followers */ static int try_mangle(Ecma119Image *target, uint32_t idx, uint32_t prev_idx, uint32_t search_start, uint32_t search_end, uint32_t *new_idx, char *prefix, int flag) { int i, ret = 0; char new_name[LIBISO_HFSPLUS_NAME_MAX + 1], number[9]; uint16_t *old_name, *old_cmp_name; uint32_t old_strlen; old_name = target->hfsp_leafs[idx].name; old_cmp_name = target->hfsp_leafs[idx].cmp_name; old_strlen = target->hfsp_leafs[idx].strlen; for (i = -1; i < 0x7fffffff; i++) { if (i == -1) number[0] = 0; else sprintf(number, "%X", (unsigned int) i); if (strlen(prefix) + 1 + strlen(number) > LIBISO_HFSPLUS_NAME_MAX) { ret = 0; goto no_success; } /* "-" would sort lower than capital letters , traditional "_" causes longer rotations */ sprintf(new_name, "%s_%s", prefix, number); /* The original name is kept until the end of the try */ if (target->hfsp_leafs[idx].name != old_name) free(target->hfsp_leafs[idx].name); if (target->hfsp_leafs[idx].cmp_name != old_cmp_name) free(target->hfsp_leafs[idx].cmp_name); ret = set_hfsplus_name(target, new_name, &(target->hfsp_leafs[idx])); if (ret < 0) goto no_success; ret = search_mangled_pos(target, idx, new_idx, search_start, search_end, (flag & 1)); if (ret < 0) goto no_success; if (ret == 0) continue; /* collision */ if (flag & 1) *new_idx = idx; else rotate_hfs_list(target, idx, *new_idx, 0); /* >>> Get full ISO-RR paths of colliding nodes */; /* >>> iso_tree_get_node_path(node); */ iso_msg_debug(target->image->id, "HFS+ name collision with \"%s\" : \"%s\" renamed to \"%s\"", target->hfsp_leafs[prev_idx].node->name, target->hfsp_leafs[*new_idx].node->name, new_name); break; } target->hfsp_leafs[*new_idx].used_size += (target->hfsp_leafs[*new_idx].strlen - old_strlen) * 2; if (!(flag & 1)) { ret = update_name_followers(target, *new_idx, new_name, old_name, old_cmp_name, old_strlen); if (ret < 0) goto no_success; } free(old_name); free(old_cmp_name); return 1; no_success:; target->hfsp_leafs[idx].name = old_name; target->hfsp_leafs[idx].cmp_name = old_cmp_name; target->hfsp_leafs[idx].strlen = old_strlen; return ret; } static int mangle_leafs(Ecma119Image *target, int flag) { int ret; uint32_t i, new_idx, prev, first_prev; iso_msg_debug(target->image->id, "%s", "HFS+ mangling started ..."); /* Look for the first owner of a name */ for (prev = 0; prev < target->hfsp_nleafs; prev++) { if (target->hfsp_leafs[prev].type == HFSPLUS_DIR_THREAD || target->hfsp_leafs[prev].type == HFSPLUS_FILE_THREAD || target->hfsp_leafs[prev].node == NULL || target->hfsp_leafs[prev].name == NULL || target->hfsp_leafs[prev].cmp_name == NULL) continue; if (target->hfsp_leafs[prev].node->name == NULL) continue; break; } first_prev = prev; for (i = prev + 1; i < target->hfsp_nleafs; i++) { if (target->hfsp_leafs[i].type == HFSPLUS_DIR_THREAD || target->hfsp_leafs[i].type == HFSPLUS_FILE_THREAD || target->hfsp_leafs[i].node == NULL || target->hfsp_leafs[i].name == NULL || target->hfsp_leafs[i].cmp_name == NULL) continue; if (target->hfsp_leafs[i].node->name == NULL) continue; if (cmp_node(&(target->hfsp_leafs[prev]), &(target->hfsp_leafs[i])) != 0) { prev = i; continue; } target->hfsp_collision_count++; #ifdef Libisofs_with_mangle_masK /* >>> Development sketch: */ /* >>> define in libisofs.h : enum with LIBISO_NOMANGLE_xyz xinfo function for uint32_t */ /* >>> inquire xinfo for mangle protection : uint32_t mangle_mask */ if (mangle_mask & (1 << LIBISO_NOMANGLE_HFSPLUS)) { /* >>> Get full ISO-RR paths of colliding nodes and print error message */; return ISO_HFSP_NO_MANGLE; } else { #else /* Libisofs_with_mangle_masK */ { #endif /* ! Libisofs_with_mangle_masK */ ret= try_mangle(target, i, prev, i + 1, target->hfsp_nleafs, &new_idx, target->hfsp_leafs[i].node->name, 0); if (ret == 0) ret= try_mangle(target, i, prev, 0, target->hfsp_nleafs, &new_idx, "MANGLED", 0); if (ret < 0) return(ret); if (new_idx > i) { i--; /* an unprocessed candidate has been rotated to i */ } else { prev = i; /* advance */ } } } if (target->hfsp_collision_count > 0) { /* Mangling cannot be properly performed if the name owners do not stay in sorting order. */ prev = first_prev; for (i = prev + 1; i < target->hfsp_nleafs; i++) { if (target->hfsp_leafs[i].type == HFSPLUS_DIR_THREAD || target->hfsp_leafs[i].type == HFSPLUS_FILE_THREAD || target->hfsp_leafs[i].node == NULL || target->hfsp_leafs[i].name == NULL || target->hfsp_leafs[i].cmp_name == NULL) continue; if (target->hfsp_leafs[i].node->name == NULL) continue; if (cmp_node(&(target->hfsp_leafs[prev]), &(target->hfsp_leafs[i])) > 0) { iso_msg_debug(target->image->id, "*********** Mangling messed up sorting *************\n"); break; } prev = i; } /* Only the owners of names were considered during mangling. The HFSPLUS_*_THREAD types must get in line by sorting again. */ qsort(target->hfsp_leafs, target->hfsp_nleafs, sizeof(*target->hfsp_leafs), cmp_node); } iso_msg_debug(target->image->id, "HFS+ mangling done. Resolved Collisions: %lu", (unsigned long) target->hfsp_collision_count); return ISO_SUCCESS; } int hfsplus_writer_create(Ecma119Image *target) { int ret; IsoImageWriter *writer = NULL; int max_levels; int level = 0; IsoNode *pos; IsoDir *dir; int i; uint32_t cat_node_size; writer = calloc(1, sizeof(IsoImageWriter)); if (writer == NULL) { ret = ISO_OUT_OF_MEM; goto ex; } make_hfsplus_decompose_pages(); make_hfsplus_class_pages(); if (target->opts->hfsp_block_size == 0) target->opts->hfsp_block_size = HFSPLUS_DEFAULT_BLOCK_SIZE; target->hfsp_cat_node_size = 2 * target->opts->hfsp_block_size; target->hfsp_iso_block_fac = 2048 / target->opts->hfsp_block_size; cat_node_size = target->hfsp_cat_node_size; writer->compute_data_blocks = hfsplus_writer_compute_data_blocks; writer->write_vol_desc = nop_writer_write_vol_desc; writer->write_data = hfsplus_writer_write_data; writer->free_data = hfsplus_writer_free_data; writer->data = NULL; writer->target = target; iso_msg_debug(target->image->id, "Creating HFS+ tree..."); target->hfsp_nfiles = 0; target->hfsp_ndirs = 0; target->hfsp_cat_id = 16; ret = hfsplus_count_tree(target, (IsoNode*)target->image->root); if (ret < 0) goto ex; for (i = 0; i < ISO_HFSPLUS_BLESS_MAX; i++) target->hfsp_bless_id[i] = 0; target->hfsp_nleafs = 2 * (target->hfsp_nfiles + target->hfsp_ndirs); target->hfsp_curleaf = 0; target->hfsp_leafs = calloc (target->hfsp_nleafs, sizeof (target->hfsp_leafs[0])); if (target->hfsp_leafs == NULL) { ret = ISO_OUT_OF_MEM; goto ex; } ret = set_hfsplus_name (target, target->image->volume_id, &target->hfsp_leafs[target->hfsp_curleaf]); if (ret < 0) goto ex; target->hfsp_leafs[target->hfsp_curleaf].node = (IsoNode *) target->image->root; target->hfsp_leafs[target->hfsp_curleaf].used_size = target->hfsp_leafs[target->hfsp_curleaf].strlen * 2 + 8 + 2 + sizeof (struct hfsplus_catfile_common); target->hfsp_leafs[target->hfsp_curleaf].type = HFSPLUS_DIR; target->hfsp_leafs[target->hfsp_curleaf].file = 0; target->hfsp_leafs[target->hfsp_curleaf].cat_id = 2; target->hfsp_leafs[target->hfsp_curleaf].parent_id = 1; target->hfsp_leafs[target->hfsp_curleaf].nchildren = 0; target->hfsp_leafs[target->hfsp_curleaf].unix_type = UNIX_NONE; target->hfsp_curleaf++; target->hfsp_leafs[target->hfsp_curleaf].name = target->hfsp_leafs[target->hfsp_curleaf - 1].name; target->hfsp_leafs[target->hfsp_curleaf].cmp_name = 0; target->hfsp_leafs[target->hfsp_curleaf].strlen = target->hfsp_leafs[target->hfsp_curleaf - 1].strlen; target->hfsp_leafs[target->hfsp_curleaf].used_size = target->hfsp_leafs[target->hfsp_curleaf].strlen * 2 + 8 + 2 + sizeof (struct hfsplus_catfile_thread); target->hfsp_leafs[target->hfsp_curleaf].node = (IsoNode *) target->image->root; target->hfsp_leafs[target->hfsp_curleaf].type = HFSPLUS_DIR_THREAD; target->hfsp_leafs[target->hfsp_curleaf].file = 0; target->hfsp_leafs[target->hfsp_curleaf].cat_id = 1; target->hfsp_leafs[target->hfsp_curleaf].parent_id = 2; target->hfsp_leafs[target->hfsp_curleaf].unix_type = UNIX_NONE; target->hfsp_curleaf++; dir = (IsoDir*)target->image->root; pos = dir->children; while (pos) { int cret; cret = create_tree(target, pos, 2); if (cret < 0) { ret = cret; goto ex; } pos = pos->next; target->hfsp_leafs[0].nchildren++; } qsort(target->hfsp_leafs, target->hfsp_nleafs, sizeof(*target->hfsp_leafs), cmp_node); ret = mangle_leafs(target, 0); if (ret < 0) goto ex; for (max_levels = 0; target->hfsp_nleafs >> max_levels; max_levels++); max_levels += 2; target->hfsp_levels = calloc (max_levels, sizeof (target->hfsp_levels[0])); if (target->hfsp_levels == NULL) { ret = ISO_OUT_OF_MEM; goto ex; } target->hfsp_nnodes = 1; { uint32_t last_start = 0; uint32_t i; unsigned bytes_rem = cat_node_size - sizeof (struct hfsplus_btnode) - 2; target->hfsp_levels[level].nodes = calloc ((target->hfsp_nleafs + 1), sizeof (target->hfsp_levels[level].nodes[0])); if (!target->hfsp_levels[level].nodes) { ret = ISO_OUT_OF_MEM; goto ex; } target->hfsp_levels[level].level_size = 0; for (i = 0; i < target->hfsp_nleafs; i++) { if (bytes_rem < target->hfsp_leafs[i].used_size) { target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].start = last_start; target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].cnt = i - last_start; if (target->hfsp_leafs[last_start].cmp_name) { target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].strlen = target->hfsp_leafs[last_start].strlen; target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].str = target->hfsp_leafs[last_start].name; } else { target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].strlen = 0; target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].str = NULL; } target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].parent_id = target->hfsp_leafs[last_start].parent_id; target->hfsp_levels[level].level_size++; last_start = i; bytes_rem = cat_node_size - sizeof (struct hfsplus_btnode) - 2; } bytes_rem -= target->hfsp_leafs[i].used_size; } target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].start = last_start; target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].cnt = i - last_start; if (target->hfsp_leafs[last_start].cmp_name) { target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].strlen = target->hfsp_leafs[last_start].strlen; target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].str = target->hfsp_leafs[last_start].name; } else { target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].strlen = 0; target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].str = NULL; } target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].parent_id = target->hfsp_leafs[last_start].parent_id; target->hfsp_levels[level].level_size++; target->hfsp_nnodes += target->hfsp_levels[level].level_size; } while (target->hfsp_levels[level].level_size > 1) { uint32_t last_start = 0; uint32_t i; uint32_t last_size; unsigned bytes_rem = cat_node_size - sizeof (struct hfsplus_btnode) - 2; last_size = target->hfsp_levels[level].level_size; level++; target->hfsp_levels[level].nodes = calloc (((last_size + 1) / 2), sizeof (target->hfsp_levels[level].nodes[0])); if (!target->hfsp_levels[level].nodes) { ret = ISO_OUT_OF_MEM; goto ex; } target->hfsp_levels[level].level_size = 0; for (i = 0; i < last_size; i++) { uint32_t used_size; used_size = target->hfsp_levels[level - 1].nodes[i].strlen * 2 + 14; if (bytes_rem < used_size) { target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].start = last_start; target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].cnt = i - last_start; target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].strlen = target->hfsp_levels[level - 1].nodes[last_start].strlen; target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].str = target->hfsp_levels[level - 1].nodes[last_start].str; target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].parent_id = target->hfsp_levels[level - 1].nodes[last_start].parent_id; target->hfsp_levels[level].level_size++; last_start = i; bytes_rem = cat_node_size - sizeof (struct hfsplus_btnode) - 2; } bytes_rem -= used_size; } target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].start = last_start; target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].cnt = i - last_start; target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].strlen = target->hfsp_levels[level - 1].nodes[last_start].strlen; target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].str = target->hfsp_levels[level - 1].nodes[last_start].str; target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].parent_id = target->hfsp_levels[level - 1].nodes[last_start].parent_id; target->hfsp_levels[level].level_size++; target->hfsp_nnodes += target->hfsp_levels[level].level_size; } target->hfsp_nlevels = level + 1; if (target->hfsp_nnodes > (cat_node_size - 0x100) * 8) { iso_msg_submit(target->image->id, ISO_MANGLE_TOO_MUCH_FILES, 0, "HFS+ map nodes aren't implemented"); ret = ISO_MANGLE_TOO_MUCH_FILES; goto ex; } /* add this writer to image */ target->writers[target->nwriters++] = writer; writer = NULL; ret = ISO_SUCCESS; ex:; if (writer != NULL) free(writer); return ret; } int hfsplus_tail_writer_create(Ecma119Image *target) { IsoImageWriter *writer; writer = calloc(1, sizeof(IsoImageWriter)); if (writer == NULL) { return ISO_OUT_OF_MEM; } writer->compute_data_blocks = hfsplus_tail_writer_compute_data_blocks; writer->write_vol_desc = nop_writer_write_vol_desc; writer->write_data = hfsplus_tail_writer_write_data; writer->free_data = nop_writer_free_data; writer->data = NULL; writer->target = target; /* add this writer to image */ target->writers[target->nwriters++] = writer; return ISO_SUCCESS; } /* API */ int iso_hfsplus_xinfo_func(void *data, int flag) { if (flag == 1 && data != NULL) free(data); return 1; } /* API */ struct iso_hfsplus_xinfo_data *iso_hfsplus_xinfo_new(int flag) { struct iso_hfsplus_xinfo_data *o; o = calloc(1, sizeof(struct iso_hfsplus_xinfo_data)); if (o == NULL) return NULL; o->version = 0; return o; } /* The iso_node_xinfo_cloner function which gets associated to * iso_hfsplus_xinfo_func by iso_init() or iso_init_with_flag() via * iso_node_xinfo_make_clonable() */ int iso_hfsplus_xinfo_cloner(void *old_data, void **new_data, int flag) { *new_data = NULL; if (flag) return ISO_XINFO_NO_CLONE; if (old_data == NULL) return 0; *new_data = iso_hfsplus_xinfo_new(0); if(*new_data == NULL) return ISO_OUT_OF_MEM; memcpy(*new_data, old_data, sizeof(struct iso_hfsplus_xinfo_data)); return ISO_SUCCESS; } libisofs-1.4.2/libisofs/eltorito.c0000644000175700017510000011337112605742276014121 00000000000000/* * Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2010 - 2014 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif #include "libisofs.h" #include "eltorito.h" #include "fsource.h" #include "filesrc.h" #include "image.h" #include "messages.h" #include "writer.h" #include #include #include /** * This table should be written with the actual values at offset * 8 of boot image, when used ISOLINUX boot loader */ struct boot_info_table { uint8_t bi_pvd BP(1, 4); /* LBA of primary volume descriptor */ uint8_t bi_file BP(5, 8); /* LBA of boot file */ uint8_t bi_length BP(9, 12); /* Length of boot file */ uint8_t bi_csum BP(13, 16); /* Checksum of boot file */ uint8_t bi_reserved BP(17, 56); /* Reserved */ }; /** * Structure for each one of the four entries in a partition table on a * hard disk image. */ struct partition_desc { uint8_t boot_ind; uint8_t begin_chs[3]; uint8_t type; uint8_t end_chs[3]; uint8_t start[4]; uint8_t size[4]; }; /** * Structures for a Master Boot Record of a hard disk image. */ struct hard_disc_mbr { uint8_t code_area[440]; uint8_t opt_disk_sg[4]; uint8_t pad[2]; struct partition_desc partition[4]; uint8_t sign1; uint8_t sign2; }; /* API */ int el_torito_set_boot_platform_id(ElToritoBootImage *bootimg, uint8_t id) { bootimg->platform_id = id; return 1; } /* API */ int el_torito_get_boot_platform_id(ElToritoBootImage *bootimg) { return bootimg->platform_id; } /** * Sets the load segment for the initial boot image. This is only for * no emulation boot images, and is a NOP for other image types. */ void el_torito_set_load_seg(ElToritoBootImage *bootimg, short segment) { if (bootimg->type != 0) return; if (segment < 0) bootimg->load_seg = 0x1000 + segment; else bootimg->load_seg = segment; } /* API */ int el_torito_get_load_seg(ElToritoBootImage *bootimg) { return (int) bootimg->load_seg; } /** * Sets the number of sectors (512b) to be load at load segment during * the initial boot procedure. This is only for no emulation boot images, * and is a NOP for other image types. */ void el_torito_set_load_size(ElToritoBootImage *bootimg, short sectors) { if (bootimg->type != 0) return; if (sectors < 0) bootimg->load_size = 0x10000 + sectors; else bootimg->load_size = sectors; } /* API */ int el_torito_get_load_size(ElToritoBootImage *bootimg) { return (int) bootimg->load_size; } /** * Marks the specified boot image as not bootable */ void el_torito_set_no_bootable(ElToritoBootImage *bootimg) { bootimg->bootable = 0; } /* API */ int el_torito_get_bootable(ElToritoBootImage *bootimg) { return !!bootimg->bootable; } /* API */ int el_torito_set_id_string(ElToritoBootImage *bootimg, uint8_t id_string[28]) { memcpy(bootimg->id_string, id_string, 28); return 1; } /* API */ int el_torito_get_id_string(ElToritoBootImage *bootimg, uint8_t id_string[28]) { memcpy(id_string, bootimg->id_string, 28); return 1; } /* API */ int el_torito_set_selection_crit(ElToritoBootImage *bootimg, uint8_t crit[20]) { memcpy(bootimg->selection_crit, crit, 20); return 1; } /* API */ int el_torito_get_selection_crit(ElToritoBootImage *bootimg, uint8_t crit[20]) { memcpy(crit, bootimg->selection_crit, 20); return 1; } /* API */ int el_torito_seems_boot_info_table(ElToritoBootImage *bootimg, int flag) { switch (flag & 15) { case 0: return bootimg->seems_boot_info_table; case 1: return bootimg->seems_grub2_boot_info; } return 0; } /** * Specifies that this image needs to be patched. This involves the writing * of a 56 bytes boot information table at offset 8 of the boot image file. * The original boot image file won't be modified. * This is needed for isolinux boot images. */ void el_torito_patch_isolinux_image(ElToritoBootImage *bootimg) { bootimg->isolinux_options |= 0x01; } /** * Specifies options for IsoLinux boot images. This should only be used with * isolinux boot images. * * @param options * bitmask style flag. The following values are defined: * * bit 0 -> 1 to path the image, 0 to not * Patching the image involves the writing of a 56 bytes * boot information table at offset 8 of the boot image file. * The original boot image file won't be modified. This is needed * to allow isolinux images to be bootable. * bit 1 -> 1 to generate an hybrid image, 0 to not * An hybrid image is a boot image that boots from either CD/DVD * media or from USB sticks. For that, you should use an isolinux * image that supports hybrid mode. Recent images support this. * @return * 1 if success, < 0 on error * @since 0.6.12 */ int el_torito_set_isolinux_options(ElToritoBootImage *bootimg, int options, int flag) { bootimg->isolinux_options = (options & 0x03ff); bootimg->seems_boot_info_table = !!(options & 1); bootimg->seems_grub2_boot_info = !!(options & (1 << 9)); return ISO_SUCCESS; } /* API */ int el_torito_get_isolinux_options(ElToritoBootImage *bootimg, int flag) { return bootimg->isolinux_options & 0x03ff; } /* API */ int el_torito_get_boot_media_type(ElToritoBootImage *bootimg, enum eltorito_boot_media_type *media_type) { if (bootimg) { switch (bootimg->type) { case 1: case 2: case 3: *media_type = ELTORITO_FLOPPY_EMUL; return 1; case 4: *media_type = ELTORITO_HARD_DISC_EMUL; return 1; case 0: *media_type = ELTORITO_NO_EMUL; return 1; default: /* should never happen */ return ISO_ASSERT_FAILURE; break; } } return ISO_WRONG_ARG_VALUE; } static int iso_tree_add_boot_node(IsoDir *parent, const char *name, IsoBoot **boot) { IsoBoot *node; IsoNode **pos; time_t now; int ret; if (parent == NULL || name == NULL || boot == NULL) { return ISO_NULL_POINTER; } if (boot) { *boot = NULL; } /* check if the name is valid */ ret = iso_node_is_valid_name(name); if (ret < 0) return ret; /* find place where to insert */ pos = &(parent->children); while (*pos != NULL && strcmp((*pos)->name, name) < 0) { pos = &((*pos)->next); } if (*pos != NULL && !strcmp((*pos)->name, name)) { /* a node with same name already exists */ return ISO_NODE_NAME_NOT_UNIQUE; } node = calloc(1, sizeof(IsoBoot)); if (node == NULL) { return ISO_OUT_OF_MEM; } node->node.refcount = 1; node->node.type = LIBISO_BOOT; node->node.name = strdup(name); if (node->node.name == NULL) { free(node); return ISO_OUT_OF_MEM; } node->lba = 0; node->size = 0; node->content = NULL; /* atributes from parent */ node->node.mode = S_IFREG | (parent->node.mode & 0444); node->node.uid = parent->node.uid; node->node.gid = parent->node.gid; node->node.hidden = parent->node.hidden; /* current time */ now = time(NULL); node->node.atime = now; node->node.ctime = now; node->node.mtime = now; /* add to dir */ node->node.parent = parent; node->node.next = *pos; *pos = (IsoNode*)node; if (boot) { *boot = node; } return ++parent->nchildren; } static int create_image(IsoImage *image, const char *image_path, enum eltorito_boot_media_type type, struct el_torito_boot_image **bootimg, IsoFile **bootnode) { int ret; struct el_torito_boot_image *boot; int boot_media_type = 0; int load_sectors = 0; /* number of sector to load */ unsigned char partition_type = 0; off_t size; IsoNode *imgfile; IsoStream *stream; *bootnode = NULL; ret = iso_tree_path_to_node(image, image_path, &imgfile); if (ret < 0) { return ret; } if (ret == 0) { iso_msg_submit(image->id, ISO_NODE_DOESNT_EXIST, 0, "El Torito boot image file missing in ISO image: '%s'", image_path); return ISO_NODE_DOESNT_EXIST; } if (imgfile->type != LIBISO_FILE) { return ISO_BOOT_IMAGE_NOT_VALID; } *bootnode = (IsoFile *) imgfile; stream = ((IsoFile*)imgfile)->stream; /* we need to read the image at least two times */ if (!iso_stream_is_repeatable(stream)) { return ISO_BOOT_IMAGE_NOT_VALID; } size = iso_stream_get_size(stream); if (size <= 0) { iso_msg_submit(image->id, ISO_BOOT_IMAGE_NOT_VALID, 0, "Boot image file is empty"); return ISO_BOOT_IMAGE_NOT_VALID; } switch (type) { case ELTORITO_FLOPPY_EMUL: switch (size) { case 1200 * 1024: boot_media_type = 1; /* 1.2 meg diskette */ break; case 1440 * 1024: boot_media_type = 2; /* 1.44 meg diskette */ break; case 2880 * 1024: boot_media_type = 3; /* 2.88 meg diskette */ break; default: iso_msg_submit(image->id, ISO_BOOT_IMAGE_NOT_VALID, 0, "Invalid image size %d Kb. Must be one of 1.2, 1.44" "or 2.88 Mb", iso_stream_get_size(stream) / 1024); return ISO_BOOT_IMAGE_NOT_VALID; break; } /* it seems that for floppy emulation we need to load * a single sector (512b) */ load_sectors = 1; break; case ELTORITO_HARD_DISC_EMUL: { size_t i; struct hard_disc_mbr mbr; int used_partition; /* read the MBR on disc and get the type of the partition */ ret = iso_stream_open(stream); if (ret < 0) { iso_msg_submit(image->id, ISO_BOOT_IMAGE_NOT_VALID, ret, "Can't open image file."); return ret; } ret = iso_stream_read(stream, &mbr, sizeof(mbr)); iso_stream_close(stream); if (ret != sizeof(mbr)) { iso_msg_submit(image->id, ISO_BOOT_IMAGE_NOT_VALID, 0, "Can't read MBR from image file."); return ret < 0 ? ret : (int) ISO_FILE_READ_ERROR; } /* check valid MBR signature */ if ( mbr.sign1 != 0x55 || mbr.sign2 != 0xAA ) { iso_msg_submit(image->id, ISO_BOOT_IMAGE_NOT_VALID, 0, "Invalid MBR. Wrong signature."); return (int) ISO_BOOT_IMAGE_NOT_VALID; } /* ensure single partition */ used_partition = -1; for (i = 0; i < 4; ++i) { if (mbr.partition[i].type != 0) { /* it's an used partition */ if (used_partition != -1) { iso_msg_submit(image->id, ISO_BOOT_IMAGE_NOT_VALID, 0, "Invalid MBR. At least 2 partitions: %d and " "%d, are being used\n", used_partition, i); return ISO_BOOT_IMAGE_NOT_VALID; } else used_partition = i; } } partition_type = mbr.partition[used_partition].type; } boot_media_type = 4; /* only load the MBR */ load_sectors = 1; break; case ELTORITO_NO_EMUL: boot_media_type = 0; break; } boot = calloc(1, sizeof(struct el_torito_boot_image)); if (boot == NULL) { return ISO_OUT_OF_MEM; } boot->image = (IsoFile*)imgfile; iso_node_ref(imgfile); /* get our ref */ boot->bootable = 1; boot->seems_boot_info_table = 0; boot->seems_grub2_boot_info = 0; boot->seems_isohybrid_capable = 0; boot->isolinux_options = 0; boot->type = boot_media_type; boot->partition_type = partition_type; boot->load_seg = 0; boot->load_size = load_sectors; boot->platform_id = 0; /* 80x86 */ memset(boot->id_string, 0, sizeof(boot->id_string)); memset(boot->selection_crit, 0, sizeof(boot->selection_crit)); *bootimg = boot; return ISO_SUCCESS; } int iso_image_set_boot_image(IsoImage *image, const char *image_path, enum eltorito_boot_media_type type, const char *catalog_path, ElToritoBootImage **boot) { int ret, i; struct el_torito_boot_catalog *catalog; ElToritoBootImage *boot_image= NULL; IsoBoot *cat_node= NULL; IsoFile *boot_node; if (image == NULL || image_path == NULL || catalog_path == NULL) { return ISO_NULL_POINTER; } if (image->bootcat != NULL) { return ISO_IMAGE_ALREADY_BOOTABLE; } /* create the node for the catalog */ { IsoDir *parent; char *catdir = NULL, *catname = NULL; catdir = strdup(catalog_path); if (catdir == NULL) { return ISO_OUT_OF_MEM; } /* get both the dir and the name */ catname = strrchr(catdir, '/'); if (catname == NULL) { free(catdir); return ISO_WRONG_ARG_VALUE; } if (catname == catdir) { /* we are apending catalog to root node */ parent = image->root; } else { IsoNode *p; catname[0] = '\0'; ret = iso_tree_path_to_node(image, catdir, &p); if (ret <= 0) { iso_msg_submit(image->id, ISO_NODE_DOESNT_EXIST, 0, "Cannot find directory for El Torito boot catalog in ISO image: '%s'", catdir); free(catdir); return ret < 0 ? ret : (int) ISO_NODE_DOESNT_EXIST; } if (p->type != LIBISO_DIR) { free(catdir); return ISO_WRONG_ARG_VALUE; } parent = (IsoDir*)p; } catname++; ret = iso_tree_add_boot_node(parent, catname, &cat_node); free(catdir); if (ret < 0) { return ret; } } /* create the boot image */ ret = create_image(image, image_path, type, &boot_image, &boot_node); if (ret < 0) { goto boot_image_cleanup; } /* creates the catalog with the given image */ catalog = calloc(1, sizeof(struct el_torito_boot_catalog)); if (catalog == NULL) { ret = ISO_OUT_OF_MEM; goto boot_image_cleanup; } catalog->num_bootimages = 1; catalog->bootimages[0] = boot_image; for (i = 1; i < Libisofs_max_boot_imageS; i++) catalog->bootimages[i] = NULL; catalog->node = cat_node; catalog->sort_weight = 1000000000; /* very high */ if (!(boot_node->explicit_weight || boot_node->from_old_session)) boot_node->sort_weight = 2; iso_node_ref((IsoNode*)cat_node); image->bootcat = catalog; if (boot) { *boot = boot_image; } return ISO_SUCCESS; boot_image_cleanup:; if (cat_node) { iso_node_take((IsoNode*)cat_node); iso_node_unref((IsoNode*)cat_node); } if (boot_image) { iso_node_unref((IsoNode*)boot_image->image); free(boot_image); } return ret; } /** * Get the boot catalog and the El-Torito default boot image of an ISO image. * * This can be useful, for example, to check if a volume read from a previous * session or an existing image is bootable. It can also be useful to get * the image and catalog tree nodes. An application would want those, for * example, to prevent the user removing it. * * Both nodes are owned by libisofs and should not be freed. You can get your * own ref with iso_node_ref(). You can can also check if the node is already * on the tree by getting its parent (note that when reading El-Torito info * from a previous image, the nodes might not be on the tree even if you haven't * removed them). Remember that you'll need to get a new ref * (with iso_node_ref()) before inserting them again to the tree, and probably * you will also need to set the name or permissions. * * @param image * The image from which to get the boot image. * @param boot * If not NULL, it will be filled with a pointer to the boot image, if * any. That object is owned by the IsoImage and should not be freed by * the user, nor dereferenced once the last reference to the IsoImage was * disposed via iso_image_unref(). * @param imgnode * When not NULL, it will be filled with the image tree node. No extra ref * is added, you can use iso_node_ref() to get one if you need it. * @param catnode * When not NULL, it will be filled with the catnode tree node. No extra * ref is added, you can use iso_node_ref() to get one if you need it. * @return * 1 on success, 0 is the image is not bootable (i.e., it has no El-Torito * image), < 0 error. */ int iso_image_get_boot_image(IsoImage *image, ElToritoBootImage **boot, IsoFile **imgnode, IsoBoot **catnode) { if (image == NULL) { return ISO_NULL_POINTER; } if (image->bootcat == NULL) { return 0; } /* ok, image is bootable */ if (boot) { *boot = image->bootcat->bootimages[0]; } if (imgnode) { *imgnode = image->bootcat->bootimages[0]->image; } if (catnode) { *catnode = image->bootcat->node; } return ISO_SUCCESS; } int iso_image_get_bootcat(IsoImage *image, IsoBoot **catnode, uint32_t *lba, char **content, off_t *size) { IsoBoot *bootcat; *catnode = NULL; *lba = 0; *content = NULL; *size = 0; bootcat = image->bootcat->node; if (bootcat == NULL) return 0; *catnode = bootcat; *lba = bootcat->lba; *size = bootcat->size; if (bootcat->size > 0 && bootcat->content != NULL) { *content = calloc(1, bootcat->size); if (*content == NULL) return ISO_OUT_OF_MEM; memcpy(*content, bootcat->content, bootcat->size); } return 1; } int iso_image_get_all_boot_imgs(IsoImage *image, int *num_boots, ElToritoBootImage ***boots, IsoFile ***bootnodes, int flag) { int i; struct el_torito_boot_catalog *cat; if (image == NULL) return ISO_NULL_POINTER; if (image->bootcat == NULL) return 0; cat = image->bootcat; *num_boots = cat->num_bootimages; *boots = NULL; *bootnodes = NULL; if (*num_boots <= 0) return 0; *boots = calloc(*num_boots, sizeof(ElToritoBootImage *)); *bootnodes = calloc(*num_boots, sizeof(IsoFile *)); if(*boots == NULL || *bootnodes == NULL) { if (*boots != NULL) free(*boots); if (*bootnodes != NULL) free(*bootnodes); *boots = NULL; *bootnodes = NULL; return ISO_OUT_OF_MEM; } for (i = 0; i < *num_boots; i++) { (*boots)[i] = cat->bootimages[i]; (*bootnodes)[i] = image->bootcat->bootimages[i]->image; } return 1; } /** * Removes the El-Torito bootable image. * * The IsoBoot node that acts as placeholder for the catalog is also removed * for the image tree, if there. * If the image is not bootable (don't have el-torito boot image) this function * just returns. */ void iso_image_remove_boot_image(IsoImage *image) { if (image == NULL || image->bootcat == NULL) return; /* * remove catalog node from its parent and dispose it * (another reference is with the catalog) */ if (iso_node_get_parent((IsoNode*) image->bootcat->node) != NULL) { iso_node_take((IsoNode*) image->bootcat->node); iso_node_unref((IsoNode*) image->bootcat->node); } /* free boot catalog and image, including references to nodes */ el_torito_boot_catalog_free(image->bootcat); image->bootcat = NULL; } /* API */ int iso_image_add_boot_image(IsoImage *image, const char *image_path, enum eltorito_boot_media_type type, int flag, ElToritoBootImage **boot) { int ret; struct el_torito_boot_catalog *catalog = image->bootcat; ElToritoBootImage *boot_img; IsoFile *boot_node; if(catalog == NULL) return ISO_BOOT_NO_CATALOG; if (catalog->num_bootimages >= Libisofs_max_boot_imageS) return ISO_BOOT_IMAGE_OVERFLOW; ret = create_image(image, image_path, type, &boot_img, &boot_node); if (ret < 0) return ret; if (!(boot_node->explicit_weight || boot_node->from_old_session)) boot_node->sort_weight = 2; catalog->bootimages[catalog->num_bootimages] = boot_img; catalog->num_bootimages++; if (boot != NULL) *boot = boot_img; return 1; } /* API */ int iso_image_set_boot_catalog_weight(IsoImage *image, int sort_weight) { if (image->bootcat == NULL) return 0; image->bootcat->sort_weight = sort_weight; return 1; } /* API */ int iso_image_set_boot_catalog_hidden(IsoImage *image, int hide_attrs) { if (image->bootcat == NULL) return 0; if (image->bootcat->node == NULL) return 0; iso_node_set_hidden((IsoNode *) image->bootcat->node, hide_attrs); return 1; } void el_torito_boot_catalog_free(struct el_torito_boot_catalog *cat) { struct el_torito_boot_image *image; int i; if (cat == NULL) { return; } for (i = 0; i < Libisofs_max_boot_imageS; i++) { image = cat->bootimages[i]; if (image == NULL) continue; if ((IsoNode*)image->image != NULL) iso_node_unref((IsoNode*)image->image); free(image); } if ((IsoNode*)cat->node != NULL) iso_node_unref((IsoNode*)cat->node); free(cat); } /** * Stream that generates the contents of a El-Torito catalog. */ struct catalog_stream { Ecma119Image *target; uint8_t buffer[BLOCK_SIZE]; int offset; /* -1 if stream is not opened */ }; static void write_validation_entry(uint8_t *buf, uint8_t platform_id, uint8_t id_string[24]) { size_t i; int checksum; struct el_torito_validation_entry *ve = (struct el_torito_validation_entry*)buf; ve->header_id[0] = 1; ve->platform_id[0] = platform_id; memcpy(ve->id_string, id_string, sizeof(ve->id_string)); ve->key_byte1[0] = 0x55; ve->key_byte2[0] = 0xAA; /* calculate the checksum, to ensure sum of all words is 0 */ checksum = 0; for (i = 0; i < sizeof(struct el_torito_validation_entry); i += 2) { checksum -= (int16_t) ((buf[i+1] << 8) | buf[i]); } iso_lsb(ve->checksum, checksum, 2); } static void write_section_header(uint8_t *buf, Ecma119Image *t, int idx, int num_entries) { char *id_string; struct el_torito_section_header *e = (struct el_torito_section_header *) buf; /* 0x90 = more section headers follow , 0x91 = final section */ e->header_indicator[0] = 0x90 + (idx == t->catalog->num_bootimages - num_entries); e->platform_id[0] = t->catalog->bootimages[idx]->platform_id; e->num_entries[0] = num_entries & 0xff; e->num_entries[1] = (num_entries >> 8) & 0xff;; id_string = (char *) e->id_string; memcpy(id_string, t->catalog->bootimages[idx]->id_string, sizeof(e->id_string)); } /** * Write one section entry. * Usable for the Default Entry * and for Section Entries with Selection criteria type == 0 */ static void write_section_entry(uint8_t *buf, Ecma119Image *t, int idx) { struct el_torito_boot_image *img; struct el_torito_section_entry *se = (struct el_torito_section_entry*)buf; img = t->catalog->bootimages[idx]; se->boot_indicator[0] = img->bootable ? 0x88 : 0x00; se->boot_media_type[0] = img->type; iso_lsb(se->load_seg, img->load_seg, 2); se->system_type[0] = img->partition_type; iso_lsb(se->sec_count, img->load_size, 2); iso_lsb(se->block, t->bootsrc[idx]->sections[0].block, 4); se->selec_criteria[0] = img->selection_crit[0]; memcpy(se->vendor_sc, img->selection_crit + 1, 19); } static int catalog_open(IsoStream *stream) { int i, j, k, num_entries; struct catalog_stream *data; uint8_t *wpt; struct el_torito_boot_catalog *cat; struct el_torito_boot_image **boots; if (stream == NULL) { return ISO_NULL_POINTER; } data = stream->data; cat = data->target->catalog; boots = cat->bootimages; if (data->offset != -1) { return ISO_FILE_ALREADY_OPENED; } memset(data->buffer, 0, BLOCK_SIZE); /* fill the buffer with the catalog contents */ write_validation_entry(data->buffer, boots[0]->platform_id, boots[0]->id_string); /* write default entry = first boot image */ write_section_entry(data->buffer + 32, data->target, 0); /* IMPORTANT: The maximum number of boot images must fit into BLOCK_SIZE */ wpt = data->buffer + 64; for (i = 1; i < cat->num_bootimages; ) { /* Look ahead and put images of same platform_id and id_string into the same section */ for (j = i + 1; j < cat->num_bootimages; j++) { if (boots[i]->platform_id != boots[j]->platform_id) break; for (k = 0; k < (int) sizeof(boots[i]->id_string); k++) if (boots[i]->id_string[k] != boots[j]->id_string[k]) break; if (k < (int) sizeof(boots[i]->id_string)) break; } num_entries = j - i; write_section_header(wpt, data->target, i, num_entries); wpt += 32; for (j = 0; j < num_entries; j++) { write_section_entry(wpt, data->target, i); wpt += 32; i++; } } data->offset = 0; return ISO_SUCCESS; } static int catalog_close(IsoStream *stream) { struct catalog_stream *data; if (stream == NULL) { return ISO_NULL_POINTER; } data = stream->data; if (data->offset == -1) { return ISO_FILE_NOT_OPENED; } data->offset = -1; return ISO_SUCCESS; } static off_t catalog_get_size(IsoStream *stream) { return BLOCK_SIZE; } static int catalog_read(IsoStream *stream, void *buf, size_t count) { size_t len; struct catalog_stream *data; if (stream == NULL || buf == NULL) { return ISO_NULL_POINTER; } if (count == 0) { return ISO_WRONG_ARG_VALUE; } data = stream->data; if (data->offset == -1) { return ISO_FILE_NOT_OPENED; } len = MIN(count, (size_t) (BLOCK_SIZE - data->offset)); memcpy(buf, data->buffer + data->offset, len); return len; } static int catalog_is_repeatable(IsoStream *stream) { return 1; } /** * fs_id will be the id reserved for El-Torito * dev_id will be 0 for catalog, 1 for boot image (if needed) * ino_id 0 is supposed to be unique. At write time it will get assigned * an automatic file serial number in the ISO, if needed. */ static void catalog_get_id(IsoStream *stream, unsigned int *fs_id, dev_t *dev_id, ino_t *ino_id) { *fs_id = ISO_ELTORITO_FS_ID; *dev_id = 0; *ino_id = 0; } static void catalog_free(IsoStream *stream) { free(stream->data); } IsoStreamIface catalog_stream_class = { 0, "boot", catalog_open, catalog_close, catalog_get_size, catalog_read, catalog_is_repeatable, catalog_get_id, catalog_free, NULL, NULL, NULL, NULL }; /** * Create an IsoStream for writing El-Torito catalog for a given target. */ static int catalog_stream_new(Ecma119Image *target, IsoStream **stream) { IsoStream *str; struct catalog_stream *data; if (target == NULL || stream == NULL || target->catalog == NULL) { return ISO_NULL_POINTER; } str = calloc(1, sizeof(IsoStream)); if (str == NULL) { return ISO_OUT_OF_MEM; } data = calloc(1, sizeof(struct catalog_stream)); if (data == NULL) { free(str); return ISO_OUT_OF_MEM; } /* fill data */ data->target = target; data->offset = -1; str->refcount = 1; str->data = data; str->class = &catalog_stream_class; *stream = str; return ISO_SUCCESS; } int el_torito_catalog_file_src_create(Ecma119Image *target, IsoFileSrc **src) { int ret; IsoFileSrc *file; IsoStream *stream; if (target == NULL || src == NULL || target->catalog == NULL) { return ISO_OUT_OF_MEM; } if (target->cat != NULL) { /* catalog file src already created */ *src = target->cat; return ISO_SUCCESS; } file = calloc(1, sizeof(IsoFileSrc)); if (file == NULL) { return ISO_OUT_OF_MEM; } ret = catalog_stream_new(target, &stream); if (ret < 0) { free(file); return ret; } /* fill fields */ file->no_write = 0; /* TODO allow copy of old img catalog???? */ file->checksum_index = 0; file->nsections = 1; file->sections = calloc(1, sizeof(struct iso_file_section)); file->sort_weight = target->catalog->sort_weight; file->stream = stream; ret = iso_file_src_add(target, file, src); if (ret <= 0) { iso_stream_unref(stream); free(file); } else { target->cat = *src; } return ret; } /******************* EL-TORITO WRITER *******************************/ /** * Insert boot info table content into buf. * * @return * 1 on success, 0 error (but continue), < 0 error */ int make_boot_info_table(uint8_t *buf, uint32_t pvd_lba, uint32_t boot_lba, uint32_t imgsize) { struct boot_info_table *info; uint32_t checksum; uint32_t offset; info = (struct boot_info_table *) (buf + 8); if (imgsize < 64) return ISO_ISOLINUX_CANT_PATCH; /* compute checksum, as the the sum of all 32 bit words in boot image * from offset 64 */ checksum = 0; offset = 64; while (offset <= imgsize - 4) { checksum += iso_read_lsb(buf + offset, 4); offset += 4; } if (offset != imgsize) { /* * file length not multiple of 4 * empty space in isofs is padded with zero; * assume same for last dword */ checksum += iso_read_lsb(buf + offset, imgsize - offset); } /*memset(info, 0, sizeof(struct boot_info_table));*/ iso_lsb(info->bi_pvd, pvd_lba, 4); iso_lsb(info->bi_file, boot_lba, 4); iso_lsb(info->bi_length, imgsize, 4); iso_lsb(info->bi_csum, checksum, 4); memset(buf + 24, 0, 40); return ISO_SUCCESS; } /** * Patch an El Torito boot image by a boot info table. * * @return * 1 on success, 0 error (but continue), < 0 error */ static int patch_boot_info_table(uint8_t *buf, Ecma119Image *t, size_t imgsize, int idx) { int ret; if (imgsize < 64) { return iso_msg_submit(t->image->id, ISO_ISOLINUX_CANT_PATCH, 0, "Isolinux image too small. We won't patch it."); } ret = make_boot_info_table(buf, t->opts->ms_block + (uint32_t) 16, t->bootsrc[idx]->sections[0].block, (uint32_t) imgsize); return ret; } /** * Patch a GRUB2 El Torito boot image. */ static int patch_grub2_boot_image(uint8_t *buf, Ecma119Image *t, size_t imgsize, int idx, size_t pos, int offst) { uint64_t blk; if (imgsize < pos + 8) return iso_msg_submit(t->image->id, ISO_ISOLINUX_CANT_PATCH, 0, "Isolinux image too small for GRUB2. Will not patch it."); blk = ((uint64_t) t->bootsrc[idx]->sections[0].block) * 4 + offst; iso_lsb((buf + pos), blk & 0xffffffff, 4); iso_lsb((buf + pos + 4), blk >> 32, 4); return ISO_SUCCESS; } /* Patch the boot images if indicated */ int iso_patch_eltoritos(Ecma119Image *t) { int ret, idx; size_t size; uint8_t *buf; IsoStream *new = NULL; IsoStream *original = NULL; if (t->catalog == NULL) return ISO_SUCCESS; for (idx = 0; idx < t->catalog->num_bootimages; idx++) { if (!(t->catalog->bootimages[idx]->isolinux_options & 0x201)) continue; original = t->bootsrc[idx]->stream; size = (size_t) iso_stream_get_size(original); if (size > Libisofs_elto_max_patchablE) return ISO_PATCH_OVERSIZED_BOOT; if (iso_stream_get_input_stream(original, 0) != NULL) return ISO_PATCH_FILTERED_BOOT; buf = calloc(1, size); if (buf == NULL) { return ISO_OUT_OF_MEM; } ret = iso_stream_open(original); if (ret < 0) { free(buf); return ret; } ret = iso_stream_read(original, buf, size); iso_stream_close(original); if (ret != (int) size) { if (ret >= 0) iso_msg_submit(t->image->id, ISO_FILE_READ_ERROR, 0, "Cannot read all bytes from El Torito boot image for boot info table"); return (ret < 0) ? ret : (int) ISO_FILE_READ_ERROR; } /* ok, patch the read buffer */ if (t->catalog->bootimages[idx]->isolinux_options & 0x200) { /* GRUB2 boot provisions */ ret = patch_grub2_boot_image(buf, t, size, idx, Libisofs_grub2_elto_patch_poS, Libisofs_grub2_elto_patch_offsT); if (ret < 0) return ret; } /* Must be done as last patching */ if (t->catalog->bootimages[idx]->isolinux_options & 0x01) { /* Boot Info Table */ ret = patch_boot_info_table(buf, t, size, idx); if (ret < 0) return ret; } /* replace the original stream with a memory stream that reads from * the patched buffer */ ret = iso_memory_stream_new(buf, size, &new); if (ret < 0) { return ret; } t->bootsrc[idx]->stream = new; iso_stream_unref(original); } return ISO_SUCCESS; } static int eltorito_writer_compute_data_blocks(IsoImageWriter *writer) { /* * We have nothing to write. */ return ISO_SUCCESS; } /** * Write the Boot Record Volume Descriptor (ECMA-119, 8.2) */ static int eltorito_writer_write_vol_desc(IsoImageWriter *writer) { Ecma119Image *t; struct ecma119_boot_rec_vol_desc vol; if (writer == NULL) { return ISO_NULL_POINTER; } t = writer->target; iso_msg_debug(t->image->id, "Write El-Torito boot record"); memset(&vol, 0, sizeof(struct ecma119_boot_rec_vol_desc)); vol.vol_desc_type[0] = 0; memcpy(vol.std_identifier, "CD001", 5); vol.vol_desc_version[0] = 1; memcpy(vol.boot_sys_id, "EL TORITO SPECIFICATION", 23); iso_lsb(vol.boot_catalog, t->cat->sections[0].block - t->eff_partition_offset, 4); return iso_write(t, &vol, sizeof(struct ecma119_boot_rec_vol_desc)); } static int eltorito_writer_write_data(IsoImageWriter *writer) { /* nothing to do, the files are written by the file writer */ return ISO_SUCCESS; } static int eltorito_writer_free_data(IsoImageWriter *writer) { /* nothing to do */ return ISO_SUCCESS; } int eltorito_writer_create(Ecma119Image *target) { int ret, idx, outsource_efi = 0; IsoImageWriter *writer; IsoFile *bootimg; IsoFileSrc *src; writer = calloc(1, sizeof(IsoImageWriter)); if (writer == NULL) { return ISO_OUT_OF_MEM; } writer->compute_data_blocks = eltorito_writer_compute_data_blocks; writer->write_vol_desc = eltorito_writer_write_vol_desc; writer->write_data = eltorito_writer_write_data; writer->free_data = eltorito_writer_free_data; writer->data = NULL; writer->target = target; /* add this writer to image */ target->writers[target->nwriters++] = writer; /* * get catalog and image file sources. * Note that the catalog may be already added, when creating the low * level ECMA-119 tree. */ if (target->cat == NULL) { ret = el_torito_catalog_file_src_create(target, &src); if (ret < 0) { return ret; } } if (target->opts->efi_boot_partition != NULL) if (strcmp(target->opts->efi_boot_partition, "--efi-boot-image") == 0) outsource_efi = 1; for (idx = 0; idx < target->catalog->num_bootimages; idx++) { bootimg = target->catalog->bootimages[idx]->image; ret = iso_file_src_create(target, bootimg, &src); if (ret < 0) { return ret; } target->bootsrc[idx] = src; /* For patching an image, it needs to be copied always */ if (target->catalog->bootimages[idx]->isolinux_options & 0x01) { src->no_write = 0; } /* If desired: Recognize first EFI boot image that will be newly written, and mark it as claimed for being a partition. */ if (outsource_efi && target->catalog->bootimages[idx]->platform_id == 0xef && src->no_write == 0) { target->efi_boot_part_filesrc = src; src->sections[0].block = 0xfffffffe; ((IsoNode *) bootimg)->hidden |= LIBISO_HIDE_ON_HFSPLUS | LIBISO_HIDE_ON_FAT; outsource_efi = 0; } } /* we need the bootable volume descriptor */ target->curblock++; if (outsource_efi) { /* Disable EFI Boot partition and complain */ free(target->opts->efi_boot_partition); target->opts->efi_boot_partition = NULL; iso_msg_submit(target->image->id, ISO_BOOT_NO_EFI_ELTO, 0, "No newly added El Torito EFI boot image found for exposure as GPT partition"); return ISO_BOOT_NO_EFI_ELTO; } return ISO_SUCCESS; } libisofs-1.4.2/libisofs/md5.c0000644000175700017510000006704612321161425012736 00000000000000/* * Copyright (c) 2009 - 2013 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif #ifdef HAVE_STDINT_H #include #else #ifdef HAVE_INTTYPES_H #include #endif #endif #include #include #include #include "writer.h" #include "messages.h" #include "ecma119.h" #include "image.h" #include "util.h" #include "md5.h" /* This code is derived from RFC 1321 and implements computation of the "RSA Data Security, Inc. MD5 Message-Digest Algorithm" */ #define Libisofs_md5_S11 7 #define Libisofs_md5_S12 12 #define Libisofs_md5_S13 17 #define Libisofs_md5_S14 22 #define Libisofs_md5_S21 5 #define Libisofs_md5_S22 9 #define Libisofs_md5_S23 14 #define Libisofs_md5_S24 20 #define Libisofs_md5_S31 4 #define Libisofs_md5_S32 11 #define Libisofs_md5_S33 16 #define Libisofs_md5_S34 23 #define Libisofs_md5_S41 6 #define Libisofs_md5_S42 10 #define Libisofs_md5_S43 15 #define Libisofs_md5_S44 21 /* F, G, H and I are basic MD5 functions. */ #define Libisofs_md5_F(x, y, z) (((x) & (y)) | ((~x) & (z))) #define Libisofs_md5_G(x, y, z) (((x) & (z)) | ((y) & (~z))) #define Libisofs_md5_H(x, y, z) ((x) ^ (y) ^ (z)) #define Libisofs_md5_I(x, y, z) ((y) ^ ((x) | (~z))) /* ROTATE_LEFT rotates x left n bits. */ #define Libisofs_md5_ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. Rotation is separate from addition to prevent recomputation. */ #define Libisofs_md5_FF(a, b, c, d, x, s, ac) { \ (a) += Libisofs_md5_F ((b), (c), (d)) + (x) + (uint32_t)(ac); \ (a) = Libisofs_md5_ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #define Libisofs_md5_GG(a, b, c, d, x, s, ac) { \ (a) += Libisofs_md5_G ((b), (c), (d)) + (x) + (uint32_t)(ac); \ (a) = Libisofs_md5_ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #define Libisofs_md5_HH(a, b, c, d, x, s, ac) { \ (a) += Libisofs_md5_H ((b), (c), (d)) + (x) + (uint32_t)(ac); \ (a) = Libisofs_md5_ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #define Libisofs_md5_II(a, b, c, d, x, s, ac) { \ (a) += Libisofs_md5_I ((b), (c), (d)) + (x) + (uint32_t)(ac); \ (a) = Libisofs_md5_ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } /* MD5 context. */ struct _libisofs_md5_ctx { uint32_t state[4]; /* state (ABCD) */ uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */ unsigned char buffer[64]; /* input buffer */ }; typedef struct _libisofs_md5_ctx libisofs_md5_ctx; /* MD5 basic transformation. Transforms state based on block. */ static int md5__transform (uint32_t state[4], unsigned char block[64]) { uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16]; unsigned int i, j; for (i = 0, j = 0; j < 64; i++, j += 4) x[i] = ((uint32_t)block[j]) | (((uint32_t)block[j+1]) << 8) | (((uint32_t)block[j+2]) << 16) | (((uint32_t)block[j+3]) << 24); /* Round 1 */ Libisofs_md5_FF (a, b, c, d, x[ 0], Libisofs_md5_S11, 0xd76aa478); /* 1 */ Libisofs_md5_FF (d, a, b, c, x[ 1], Libisofs_md5_S12, 0xe8c7b756); /* 2 */ Libisofs_md5_FF (c, d, a, b, x[ 2], Libisofs_md5_S13, 0x242070db); /* 3 */ Libisofs_md5_FF (b, c, d, a, x[ 3], Libisofs_md5_S14, 0xc1bdceee); /* 4 */ Libisofs_md5_FF (a, b, c, d, x[ 4], Libisofs_md5_S11, 0xf57c0faf); /* 5 */ Libisofs_md5_FF (d, a, b, c, x[ 5], Libisofs_md5_S12, 0x4787c62a); /* 6 */ Libisofs_md5_FF (c, d, a, b, x[ 6], Libisofs_md5_S13, 0xa8304613); /* 7 */ Libisofs_md5_FF (b, c, d, a, x[ 7], Libisofs_md5_S14, 0xfd469501); /* 8 */ Libisofs_md5_FF (a, b, c, d, x[ 8], Libisofs_md5_S11, 0x698098d8); /* 9 */ Libisofs_md5_FF (d, a, b, c, x[ 9], Libisofs_md5_S12, 0x8b44f7af); /* 10 */ Libisofs_md5_FF (c, d, a, b, x[10], Libisofs_md5_S13, 0xffff5bb1); /* 11 */ Libisofs_md5_FF (b, c, d, a, x[11], Libisofs_md5_S14, 0x895cd7be); /* 12 */ Libisofs_md5_FF (a, b, c, d, x[12], Libisofs_md5_S11, 0x6b901122); /* 13 */ Libisofs_md5_FF (d, a, b, c, x[13], Libisofs_md5_S12, 0xfd987193); /* 14 */ Libisofs_md5_FF (c, d, a, b, x[14], Libisofs_md5_S13, 0xa679438e); /* 15 */ Libisofs_md5_FF (b, c, d, a, x[15], Libisofs_md5_S14, 0x49b40821); /* 16 */ /* Round 2 */ Libisofs_md5_GG (a, b, c, d, x[ 1], Libisofs_md5_S21, 0xf61e2562); /* 17 */ Libisofs_md5_GG (d, a, b, c, x[ 6], Libisofs_md5_S22, 0xc040b340); /* 18 */ Libisofs_md5_GG (c, d, a, b, x[11], Libisofs_md5_S23, 0x265e5a51); /* 19 */ Libisofs_md5_GG (b, c, d, a, x[ 0], Libisofs_md5_S24, 0xe9b6c7aa); /* 20 */ Libisofs_md5_GG (a, b, c, d, x[ 5], Libisofs_md5_S21, 0xd62f105d); /* 21 */ Libisofs_md5_GG (d, a, b, c, x[10], Libisofs_md5_S22, 0x2441453); /* 22 */ Libisofs_md5_GG (c, d, a, b, x[15], Libisofs_md5_S23, 0xd8a1e681); /* 23 */ Libisofs_md5_GG (b, c, d, a, x[ 4], Libisofs_md5_S24, 0xe7d3fbc8); /* 24 */ Libisofs_md5_GG (a, b, c, d, x[ 9], Libisofs_md5_S21, 0x21e1cde6); /* 25 */ Libisofs_md5_GG (d, a, b, c, x[14], Libisofs_md5_S22, 0xc33707d6); /* 26 */ Libisofs_md5_GG (c, d, a, b, x[ 3], Libisofs_md5_S23, 0xf4d50d87); /* 27 */ Libisofs_md5_GG (b, c, d, a, x[ 8], Libisofs_md5_S24, 0x455a14ed); /* 28 */ Libisofs_md5_GG (a, b, c, d, x[13], Libisofs_md5_S21, 0xa9e3e905); /* 29 */ Libisofs_md5_GG (d, a, b, c, x[ 2], Libisofs_md5_S22, 0xfcefa3f8); /* 30 */ Libisofs_md5_GG (c, d, a, b, x[ 7], Libisofs_md5_S23, 0x676f02d9); /* 31 */ Libisofs_md5_GG (b, c, d, a, x[12], Libisofs_md5_S24, 0x8d2a4c8a); /* 32 */ /* Round 3 */ Libisofs_md5_HH (a, b, c, d, x[ 5], Libisofs_md5_S31, 0xfffa3942); /* 33 */ Libisofs_md5_HH (d, a, b, c, x[ 8], Libisofs_md5_S32, 0x8771f681); /* 34 */ Libisofs_md5_HH (c, d, a, b, x[11], Libisofs_md5_S33, 0x6d9d6122); /* 35 */ Libisofs_md5_HH (b, c, d, a, x[14], Libisofs_md5_S34, 0xfde5380c); /* 36 */ Libisofs_md5_HH (a, b, c, d, x[ 1], Libisofs_md5_S31, 0xa4beea44); /* 37 */ Libisofs_md5_HH (d, a, b, c, x[ 4], Libisofs_md5_S32, 0x4bdecfa9); /* 38 */ Libisofs_md5_HH (c, d, a, b, x[ 7], Libisofs_md5_S33, 0xf6bb4b60); /* 39 */ Libisofs_md5_HH (b, c, d, a, x[10], Libisofs_md5_S34, 0xbebfbc70); /* 40 */ Libisofs_md5_HH (a, b, c, d, x[13], Libisofs_md5_S31, 0x289b7ec6); /* 41 */ Libisofs_md5_HH (d, a, b, c, x[ 0], Libisofs_md5_S32, 0xeaa127fa); /* 42 */ Libisofs_md5_HH (c, d, a, b, x[ 3], Libisofs_md5_S33, 0xd4ef3085); /* 43 */ Libisofs_md5_HH (b, c, d, a, x[ 6], Libisofs_md5_S34, 0x4881d05); /* 44 */ Libisofs_md5_HH (a, b, c, d, x[ 9], Libisofs_md5_S31, 0xd9d4d039); /* 45 */ Libisofs_md5_HH (d, a, b, c, x[12], Libisofs_md5_S32, 0xe6db99e5); /* 46 */ Libisofs_md5_HH (c, d, a, b, x[15], Libisofs_md5_S33, 0x1fa27cf8); /* 47 */ Libisofs_md5_HH (b, c, d, a, x[ 2], Libisofs_md5_S34, 0xc4ac5665); /* 48 */ /* Round 4 */ Libisofs_md5_II (a, b, c, d, x[ 0], Libisofs_md5_S41, 0xf4292244); /* 49 */ Libisofs_md5_II (d, a, b, c, x[ 7], Libisofs_md5_S42, 0x432aff97); /* 50 */ Libisofs_md5_II (c, d, a, b, x[14], Libisofs_md5_S43, 0xab9423a7); /* 51 */ Libisofs_md5_II (b, c, d, a, x[ 5], Libisofs_md5_S44, 0xfc93a039); /* 52 */ Libisofs_md5_II (a, b, c, d, x[12], Libisofs_md5_S41, 0x655b59c3); /* 53 */ Libisofs_md5_II (d, a, b, c, x[ 3], Libisofs_md5_S42, 0x8f0ccc92); /* 54 */ Libisofs_md5_II (c, d, a, b, x[10], Libisofs_md5_S43, 0xffeff47d); /* 55 */ Libisofs_md5_II (b, c, d, a, x[ 1], Libisofs_md5_S44, 0x85845dd1); /* 56 */ Libisofs_md5_II (a, b, c, d, x[ 8], Libisofs_md5_S41, 0x6fa87e4f); /* 57 */ Libisofs_md5_II (d, a, b, c, x[15], Libisofs_md5_S42, 0xfe2ce6e0); /* 58 */ Libisofs_md5_II (c, d, a, b, x[ 6], Libisofs_md5_S43, 0xa3014314); /* 59 */ Libisofs_md5_II (b, c, d, a, x[13], Libisofs_md5_S44, 0x4e0811a1); /* 60 */ Libisofs_md5_II (a, b, c, d, x[ 4], Libisofs_md5_S41, 0xf7537e82); /* 61 */ Libisofs_md5_II (d, a, b, c, x[11], Libisofs_md5_S42, 0xbd3af235); /* 62 */ Libisofs_md5_II (c, d, a, b, x[ 2], Libisofs_md5_S43, 0x2ad7d2bb); /* 63 */ Libisofs_md5_II (b, c, d, a, x[ 9], Libisofs_md5_S44, 0xeb86d391); /* 64 */ state[0] += a; state[1] += b; state[2] += c; state[3] += d; /* Zeroize sensitive information. */ memset ((char *) x, 0, sizeof (x)); return(1); } static int md5__encode(unsigned char *output, uint32_t *input, unsigned int len) { unsigned int i, j; for (i = 0, j = 0; j < len; i++, j += 4) { output[j] = (unsigned char)(input[i] & 0xff); output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); } return(1); } static int md5_init(libisofs_md5_ctx *ctx, int flag) { ctx->count[0] = ctx->count[1] = 0; /* Load magic initialization constants. */ ctx->state[0] = 0x67452301; ctx->state[1] = 0xefcdab89; ctx->state[2] = 0x98badcfe; ctx->state[3] = 0x10325476; return(1); } /* MD5 block update operation. Continues an MD5 message-digest operation, processing another message block, and updating the context. */ static int md5_update(libisofs_md5_ctx *ctx, unsigned char *data, int datalen, int flag) { int i, index, partlen; /* Compute number of bytes mod 64 */ index = ((ctx->count[0] >> 3) & 0x3F); /* Update number of bits */ if ((ctx->count[0] += ((uint32_t) datalen << 3)) < ((uint32_t) datalen << 3)) ctx->count[1]++; ctx->count[1] += ((uint32_t) datalen >> 29); partlen = 64 - index; /* Transform as many times as possible. */ if (datalen >= partlen) { memcpy((char *) &ctx->buffer[index], (char *) data, partlen); md5__transform(ctx->state, ctx->buffer); for (i = partlen; i + 63 < datalen; i += 64) md5__transform(ctx->state, &data[i]); index = 0; } else i = 0; /* Buffer remaining data */ memcpy((char *) &ctx->buffer[index], (char *) &data[i],datalen-i); return(1); } static int md5_final(libisofs_md5_ctx *ctx, char result[16], int flag) { unsigned char bits[8], *respt; unsigned int index, padlen; static unsigned char PADDING[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* Save number of bits */ md5__encode(bits, ctx->count, 8); /* Pad out to 56 mod 64. */ index = (unsigned int)((ctx->count[0] >> 3) & 0x3f); padlen = (index < 56) ? (56 - index) : (120 - index); md5_update(ctx, PADDING, padlen,0); /* Append length (before padding) */ md5_update(ctx, bits, 8,0); /* Store state in result */ respt= (unsigned char *) result; md5__encode(respt, ctx->state, 16); /* Zeroize sensitive information. */ memset ((char *) ctx, 0, sizeof (*ctx)); return(1); } /** Compute a MD5 checksum from one or more calls of this function. The first call has to be made with flag bit0 == 1. It may already submit processing payload in data and datalen. The last call has to be made with bit15 set. Normally bit1 will be set too in order to receive the checksum before it gets disposed. bit1 may only be set in the last call or together with bit2. The combination of bit1 and bit2 may be used to get an intermediate result without hampering an ongoing checksum computation. @param ctx the checksum context which stores the state between calls. It gets created with flag bit0 and disposed with bit15. With flag bit0, *ctx has to be NULL or point to freeable memory. @param data the bytes to be checksummed @param datalen the number of bytes in data @param result returns the 16 bytes of checksum if called with bit1 set @param flag bit0= allocate and init *ctx bit1= transfer ctx to result bit2= with bit 0 : clone new *ctx from data bit15= free *ctx */ static int libisofs_md5(void **ctx_in, char *data, int datalen, char result[16], int flag) /* *ctx has to be NULL or point to freeable memory */ /* bit0= allocate and init *ctx bit1= transfer ctx to result bit2= with bit 0 : clone new *ctx from data bit15= free *ctx */ { unsigned char *datapt; libisofs_md5_ctx **ctx; ctx= (libisofs_md5_ctx **) ctx_in; if(flag&1) { if(*ctx!=NULL) free((char *) *ctx); *ctx= calloc(1, sizeof(libisofs_md5_ctx)); if(*ctx==NULL) return(-1); md5_init(*ctx,0); if(flag&4) memcpy((char *) *ctx,data,sizeof(libisofs_md5_ctx)); } if(*ctx==NULL) return(0); if(datalen>0) { datapt= (unsigned char *) data; md5_update(*ctx, datapt, datalen, 0); } if(flag&2) md5_final(*ctx, result, 0); if(flag&(1<<15)) { free((char *) *ctx); *ctx= NULL; } return(1); } /* ----------------------------------------------------------------------- */ /* Public MD5 computing facility */ /* API */ int iso_md5_start(void **md5_context) { int ret; ret = libisofs_md5(md5_context, NULL, 0, NULL, 1); if (ret <= 0) return ISO_OUT_OF_MEM; return 1; } /* API */ int iso_md5_compute(void *md5_context, char *data, int datalen) { int ret; ret = libisofs_md5(&md5_context, data, datalen, NULL, 0); if (ret <= 0) return ISO_NULL_POINTER; return 1; } /* API */ int iso_md5_clone(void *old_md5_context, void **new_md5_context) { int ret; ret = libisofs_md5(new_md5_context, old_md5_context, 0, NULL, 1 | 4); if (ret < 0) return ISO_OUT_OF_MEM; if (ret == 0) return ISO_NULL_POINTER; return 1; } /* API */ int iso_md5_end(void **md5_context, char result[16]) { int ret; ret = libisofs_md5(md5_context, NULL, 0, result, 2 | (1 << 15)); if (ret <= 0) return ISO_NULL_POINTER; return 1; } /* API */ int iso_md5_match(char first_md5[16], char second_md5[16]) { int i; for (i= 0; i < 16; i++) if (first_md5[i] != second_md5[i]) return 0; return 1; } /* ----------------------------------------------------------------------- */ /* Function to identify and manage md5sum indice of the old image. * data is supposed to be a 4 byte integer, bit 31 shall be 0, * value 0 of this integer means that it is not a valid index. */ int checksum_cx_xinfo_func(void *data, int flag) { /* data is an int disguised as pointer. It does not point to memory. */ return 1; } /* The iso_node_xinfo_cloner function which gets associated to * checksum_cx_xinfo_func by iso_init() resp. iso_init_with_flag() via * iso_node_xinfo_make_clonable() */ int checksum_cx_xinfo_cloner(void *old_data, void **new_data, int flag) { *new_data = NULL; if (flag) return ISO_XINFO_NO_CLONE; if (old_data == NULL) return 0; /* data is an int disguised as pointer. It does not point to memory. */ *new_data = old_data; return 0; } /* Function to identify and manage md5 sums of unspecified providence stored * directly in this xinfo. */ int checksum_md5_xinfo_func(void *data, int flag) { if (data == NULL) return 1; free(data); return 1; } /* The iso_node_xinfo_cloner function which gets associated to * checksum_md5_xinfo_func by iso_init() resp. iso_init_with_flag() via * iso_node_xinfo_make_clonable() */ int checksum_md5_xinfo_cloner(void *old_data, void **new_data, int flag) { *new_data = NULL; if (flag) return ISO_XINFO_NO_CLONE; if (old_data == NULL) return 0; *new_data = calloc(1, 16); if (*new_data == NULL) return ISO_OUT_OF_MEM; memcpy(*new_data, old_data, 16); return 16; } /* ----------------------------------------------------------------------- */ /* MD5 checksum image writer */ /* @flag bit0= recursion bit1= session will be appended to an existing image */ static int checksum_copy_old_nodes(Ecma119Image *target, IsoNode *node, int flag) { IsoNode *pos; IsoFile *file; IsoImage *img; int ret, i; size_t value_length; unsigned int idx = 0, old_idx = 0; char *value = NULL, *md5_pt = NULL; void *xipt; img = target->image; if (target->checksum_buffer == NULL) return 0; if (node->type == LIBISO_FILE) { file = (IsoFile *) node; if (file->from_old_session && target->opts->appendable) { /* Look for checksums at various places */ /* Try checksum directly stored with node */ if (md5_pt == NULL) { ret = iso_node_get_xinfo(node, checksum_md5_xinfo_func, &xipt); if (ret < 0) return ret; if (ret == 1) md5_pt = (char *) xipt; } /* Try checksum index to image checksum buffer */ if (md5_pt == NULL && img->checksum_array != NULL) { ret = iso_node_get_xinfo(node, checksum_cx_xinfo_func, &xipt); if (ret <= 0) return ret; /* xipt is an int disguised as void pointer */ old_idx = 0; for (i = 0; i < 4; i++) old_idx = (old_idx << 8) | ((unsigned char *) &xipt)[i]; if (old_idx == 0 || old_idx > img->checksum_idx_count - 1) return 0; md5_pt = img->checksum_array + 16 * old_idx; } if (md5_pt == NULL) return 0; if (!target->opts->will_cancel) { ret = iso_node_lookup_attr(node, "isofs.cx", &value_length, &value, 0); if (ret == 1 && value_length == 4) { for (i = 0; i < 4; i++) idx = (idx << 8) | ((unsigned char *) value)[i]; if (idx > 0 && idx <= target->checksum_idx_counter) { memcpy(target->checksum_buffer + 16 * idx, md5_pt, 16); } } if (value != NULL) free(value); /* >>> ts B30114 : It is unclear why these are removed here. At least with the opts->will_cancel runs, this is not appropriate. */ iso_node_remove_xinfo(node, checksum_md5_xinfo_func); } } } else if (node->type == LIBISO_DIR) { for (pos = ((IsoDir *) node)->children; pos != NULL; pos = pos->next) { ret = checksum_copy_old_nodes(target, pos, 1); if (ret < 0) return ret; } } return ISO_SUCCESS; } static int checksum_writer_compute_data_blocks(IsoImageWriter *writer) { size_t size; Ecma119Image *t; int ret; if (writer == NULL) { return ISO_ASSERT_FAILURE; } t = writer->target; t->checksum_array_pos = t->curblock; /* (t->curblock already contains t->opts->ms_block) */ t->checksum_range_start = t->opts->ms_block; size = (t->checksum_idx_counter + 2) / 128; if (size * 128 < t->checksum_idx_counter + 2) size++; t->curblock += size; t->checksum_range_size = t->checksum_array_pos + size - t->checksum_range_start; /* Extra block for stream detectable checksum tag */ t->checksum_tag_pos = t->curblock; t->curblock++; /* Allocate array of MD5 sums */ t->checksum_buffer = calloc(size, 2048); if (t->checksum_buffer == NULL) return ISO_OUT_OF_MEM; /* Copy MD5 from nodes of old image into writer->data */ ret = checksum_copy_old_nodes(t, (IsoNode *) t->image->root, 0); if (ret < 0) return ret; /* Record lba,count,size,cecksum_type in "isofs.ca" of root node */ ret = iso_root_set_isofsca((IsoNode *) t->image->root, t->checksum_range_start, t->checksum_array_pos, t->checksum_idx_counter + 2, 16, "MD5", 0); if (ret < 0) return ret; return ISO_SUCCESS; } static int checksum_writer_write_vol_desc(IsoImageWriter *writer) { /* The superblock checksum tag has to be written after the Volume Descriptor Set Terminator and thus may not be written by this function. (It would have been neat, though). */ return ISO_SUCCESS; } static int checksum_writer_write_data(IsoImageWriter *writer) { int wres, res; size_t i, size; Ecma119Image *t; void *ctx = NULL; char md5[16]; if (writer == NULL) { return ISO_ASSERT_FAILURE; } t = writer->target; iso_msg_debug(t->image->id, "Writing Checksums..."); /* Write image checksum to index 0 */ if (t->checksum_ctx != NULL) { res = iso_md5_clone(t->checksum_ctx, &ctx); if (res > 0) { res = iso_md5_end(&ctx, t->image_md5); if (res > 0) memcpy(t->checksum_buffer + 0 * 16, t->image_md5, 16); } } size = (t->checksum_idx_counter + 2) / 128; if (size * 128 < t->checksum_idx_counter + 2) size++; /* Write checksum of checksum array as index t->checksum_idx_counter + 1 */ res = iso_md5_start(&ctx); if (res > 0) { for (i = 0; i < t->checksum_idx_counter + 1; i++) iso_md5_compute(ctx, t->checksum_buffer + ((size_t) i) * (size_t) 16, 16); res = iso_md5_end(&ctx, md5); if (res > 0) memcpy(t->checksum_buffer + (t->checksum_idx_counter + 1) * 16, md5, 16); } for (i = 0; i < size; i++) { wres = iso_write(t, t->checksum_buffer + ((size_t) 2048) * i, 2048); if (wres < 0) { res = wres; goto ex; } } if (t->checksum_ctx == NULL) { res = ISO_SUCCESS; goto ex; } /* Write stream detectable checksum tag to extra block */; res = iso_md5_write_tag(t, 1); if (res < 0) goto ex; res = ISO_SUCCESS; ex:; if (ctx != NULL) iso_md5_end(&ctx, md5); return(res); } static int checksum_writer_free_data(IsoImageWriter *writer) { /* nothing was allocated at writer->data */ return ISO_SUCCESS; } int checksum_writer_create(Ecma119Image *target) { IsoImageWriter *writer; writer = malloc(sizeof(IsoImageWriter)); if (writer == NULL) { return ISO_OUT_OF_MEM; } writer->compute_data_blocks = checksum_writer_compute_data_blocks; writer->write_vol_desc = checksum_writer_write_vol_desc; writer->write_data = checksum_writer_write_data; writer->free_data = checksum_writer_free_data; writer->data = NULL; writer->target = target; /* add this writer to image */ target->writers[target->nwriters++] = writer; /* Account for superblock checksum tag */ if (target->opts->md5_session_checksum) { target->checksum_sb_tag_pos = target->curblock; target->curblock++; } return ISO_SUCCESS; } static int iso_md5_write_scdbackup_tag(Ecma119Image *t, char *tag_block, int flag) { void *ctx = NULL; off_t pos = 0, line_start; int record_len, block_len, ret, i; char postext[40], md5[16], *record = NULL; LIBISO_ALLOC_MEM(record, char, 160); line_start = strlen(tag_block); iso_md5_compute(t->checksum_ctx, tag_block, line_start); ret = iso_md5_clone(t->checksum_ctx, &ctx); if (ret < 0) goto ex; ret = iso_md5_end(&ctx, md5); pos = (off_t) t->checksum_tag_pos * (off_t) 2048 + line_start; if(pos >= 1000000000) sprintf(postext, "%u%9.9u", (unsigned int) (pos / 1000000000), (unsigned int) (pos % 1000000000)); else sprintf(postext, "%u", (unsigned int) pos); sprintf(record, "%s %s ", t->opts->scdbackup_tag_parm, postext); record_len = strlen(record); for (i = 0; i < 16; i++) sprintf(record + record_len + 2 * i, "%2.2x", ((unsigned char *) md5)[i]); record_len += 32; ret = iso_md5_start(&ctx); if (ret < 0) goto ex; iso_md5_compute(ctx, record, record_len); iso_md5_end(&ctx, md5); sprintf(tag_block + line_start, "scdbackup_checksum_tag_v0.1 %s %d %s ", postext, record_len, record); block_len = strlen(tag_block); for (i = 0; i < 16; i++) sprintf(tag_block + block_len + 2 * i, "%2.2x", ((unsigned char *) md5)[i]); block_len+= 32; tag_block[block_len++]= '\n'; if (t->opts->scdbackup_tag_written != NULL) strncpy(t->opts->scdbackup_tag_written, tag_block + line_start, block_len - line_start); ret = ISO_SUCCESS; ex:; if (ctx != NULL) iso_md5_end(&ctx, md5); LIBISO_FREE_MEM(record); return ret; } /* Write stream detectable checksum tag to extra block. * @flag bit0-7= tag type * 1= session tag (End checksumming.) * 2= superblock tag (System Area and Volume Descriptors) * 3= tree tag (ECMA-119 and Rock Ridge tree) * 4= relocated superblock tag (at LBA 0 of overwriteable media) * Write to target->opts_overwrite rather than to iso_write(). */ int iso_md5_write_tag(Ecma119Image *t, int flag) { int ret, mode, l, i, wres, tag_id_len; void *ctx = NULL; char md5[16], *tag_block = NULL, *tag_id; uint32_t size = 0, pos = 0, start; LIBISO_ALLOC_MEM(tag_block, char, 2048); start = t->checksum_range_start; mode = flag & 255; if (mode < 1 || mode > 4) {ret = ISO_WRONG_ARG_VALUE; goto ex;} ret = iso_md5_clone(t->checksum_ctx, &ctx); if (ret < 0) goto ex; ret = iso_md5_end(&ctx, md5); if (mode == 1) { size = t->checksum_range_size; pos = t->checksum_tag_pos; } else { if (mode == 2) { pos = t->checksum_sb_tag_pos; } else if (mode == 3) { pos = t->checksum_tree_tag_pos; } else if (mode == 4) { pos = t->checksum_rlsb_tag_pos; start = pos - (pos % 32); } size = pos - start; } if (ret < 0) goto ex; iso_util_tag_magic(mode, &tag_id, &tag_id_len, 0); sprintf(tag_block, "%s pos=%u range_start=%u range_size=%u", tag_id, pos, start, size); l = strlen(tag_block); if (mode == 2) { sprintf(tag_block + l, " next=%u", t->checksum_tree_tag_pos); } else if (mode == 3) { sprintf(tag_block + l, " next=%u", t->checksum_tag_pos); } else if (mode == 4) { sprintf(tag_block + l, " session_start=%u", t->opts->ms_block); } strcat(tag_block + l, " md5="); l = strlen(tag_block); for (i = 0; i < 16; i++) sprintf(tag_block + l + 2 * i, "%2.2x", ((unsigned char *) md5)[i]); l+= 32; ret = iso_md5_start(&ctx); if (ret > 0) { iso_md5_compute(ctx, tag_block, l); iso_md5_end(&ctx, md5); strcpy(tag_block + l, " self="); l += 6; for (i = 0; i < 16; i++) sprintf(tag_block + l + 2 * i, "%2.2x", ((unsigned char *) md5)[i]); } tag_block[l + 32] = '\n'; if (mode == 1 && t->opts->scdbackup_tag_parm[0]) { if (t->opts->ms_block > 0) { iso_msg_submit(t->image->id, ISO_SCDBACKUP_TAG_NOT_0, 0, NULL); } else { ret = iso_md5_write_scdbackup_tag(t, tag_block, 0); if (ret < 0) goto ex; } } if (mode == 4) { if (t->opts_overwrite != NULL) memcpy(t->opts_overwrite + pos * 2048, tag_block, 2048); } else { wres = iso_write(t, tag_block, 2048); if (wres < 0) { ret = wres; goto ex; } } ret = ISO_SUCCESS; ex:; if (ctx != NULL) iso_md5_end(&ctx, md5); LIBISO_FREE_MEM(tag_block); return ret; } libisofs-1.4.2/libisofs/libisofs.h0000644000175700017510000115267612626304715014106 00000000000000 #ifndef LIBISO_LIBISOFS_H_ #define LIBISO_LIBISOFS_H_ /* * Copyright (c) 2007-2008 Vreixo Formoso, Mario Danic * Copyright (c) 2009-2015 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ /* Important: If you add a public API function then add its name to file libisofs/libisofs.ver */ /* * * Applications must use 64 bit off_t. * E.g. on 32-bit GNU/Linux by defining * #define _LARGEFILE_SOURCE * #define _FILE_OFFSET_BITS 64 * The minimum requirement is to interface with the library by 64 bit signed * integers where libisofs.h or libisoburn.h prescribe off_t. * Failure to do so may result in surprising malfunction or memory faults. * * Application files which include libisofs/libisofs.h must provide * definitions for uint32_t and uint8_t. * This can be achieved either: * - by using autotools which will define HAVE_STDINT_H or HAVE_INTTYPES_H * according to its ./configure tests, * - or by defining the macros HAVE_STDINT_H or HAVE_INTTYPES_H according * to the local situation, * - or by appropriately defining uint32_t and uint8_t by other means, * e.g. by including inttypes.h before including libisofs.h */ #ifdef HAVE_STDINT_H #include #else #ifdef HAVE_INTTYPES_H #include #endif #endif /* * Normally this API is operated via public functions and opaque object * handles. But it also exposes several C structures which may be used to * provide custom functionality for the objects of the API. The same * structures are used for internal objects of libisofs, too. * You are not supposed to manipulate the entrails of such objects if they * are not your own custom extensions. * * See for an example IsoStream = struct iso_stream below. */ #include #include /* Because AIX defines "open" as "open64". There are struct members named "open" in libisofs.h which get affected. So all includers of libisofs.h must get included fcntl.h to see the same. */ #include /** * The following two functions and three macros are utilities to help ensuring * version match of application, compile time header, and runtime library. */ /** * These three release version numbers tell the revision of this header file * and of the API it describes. They are memorized by applications at * compile time. * They must show the same values as these symbols in ./configure.ac * LIBISOFS_MAJOR_VERSION=... * LIBISOFS_MINOR_VERSION=... * LIBISOFS_MICRO_VERSION=... * Note to anybody who does own work inside libisofs: * Any change of configure.ac or libisofs.h has to keep up this equality ! * * Before usage of these macros on your code, please read the usage discussion * below. * * @since 0.6.2 */ #define iso_lib_header_version_major 1 #define iso_lib_header_version_minor 4 #define iso_lib_header_version_micro 2 /** * Get version of the libisofs library at runtime. * NOTE: This function may be called before iso_init(). * * @since 0.6.2 */ void iso_lib_version(int *major, int *minor, int *micro); /** * Check at runtime if the library is ABI compatible with the given version. * NOTE: This function may be called before iso_init(). * * @return * 1 lib is compatible, 0 is not. * * @since 0.6.2 */ int iso_lib_is_compatible(int major, int minor, int micro); /** * Usage discussion: * * Some developers of the libburnia project have differing opinions how to * ensure the compatibility of libaries and applications. * * It is about whether to use at compile time and at runtime the version * numbers provided here. Thomas Schmitt advises to use them. Vreixo Formoso * advises to use other means. * * At compile time: * * Vreixo Formoso advises to leave proper version matching to properly * programmed checks in the the application's build system, which will * eventually refuse compilation. * * Thomas Schmitt advises to use the macros defined here for comparison with * the application's requirements of library revisions and to eventually * break compilation. * * Both advises are combinable. I.e. be master of your build system and have * #if checks in the source code of your application, nevertheless. * * At runtime (via iso_lib_is_compatible()): * * Vreixo Formoso advises to compare the application's requirements of * library revisions with the runtime library. This is to allow runtime * libraries which are young enough for the application but too old for * the lib*.h files seen at compile time. * * Thomas Schmitt advises to compare the header revisions defined here with * the runtime library. This is to enforce a strictly monotonous chain of * revisions from app to header to library, at the cost of excluding some older * libraries. * * These two advises are mutually exclusive. */ struct burn_source; /** * Context for image creation. It holds the files that will be added to image, * and several options to control libisofs behavior. * * @since 0.6.2 */ typedef struct Iso_Image IsoImage; /* * A node in the iso tree, i.e. a file that will be written to image. * * It can represent any kind of files. When needed, you can get the type with * iso_node_get_type() and cast it to the appropiate subtype. Useful macros * are provided, see below. * * @since 0.6.2 */ typedef struct Iso_Node IsoNode; /** * A directory in the iso tree. It is an special type of IsoNode and can be * casted to it in any case. * * @since 0.6.2 */ typedef struct Iso_Dir IsoDir; /** * A symbolic link in the iso tree. It is an special type of IsoNode and can be * casted to it in any case. * * @since 0.6.2 */ typedef struct Iso_Symlink IsoSymlink; /** * A regular file in the iso tree. It is an special type of IsoNode and can be * casted to it in any case. * * @since 0.6.2 */ typedef struct Iso_File IsoFile; /** * An special file in the iso tree. This is used to represent any POSIX file * other that regular files, directories or symlinks, i.e.: socket, block and * character devices, and fifos. * It is an special type of IsoNode and can be casted to it in any case. * * @since 0.6.2 */ typedef struct Iso_Special IsoSpecial; /** * The type of an IsoNode. * * When an user gets an IsoNode from an image, (s)he can use * iso_node_get_type() to get the current type of the node, and then * cast to the appropriate subtype. For example: * * ... * IsoNode *node; * res = iso_dir_iter_next(iter, &node); * if (res == 1 && iso_node_get_type(node) == LIBISO_DIR) { * IsoDir *dir = (IsoDir *)node; * ... * } * * @since 0.6.2 */ enum IsoNodeType { LIBISO_DIR, LIBISO_FILE, LIBISO_SYMLINK, LIBISO_SPECIAL, LIBISO_BOOT }; /* macros to check node type */ #define ISO_NODE_IS_DIR(n) (iso_node_get_type(n) == LIBISO_DIR) #define ISO_NODE_IS_FILE(n) (iso_node_get_type(n) == LIBISO_FILE) #define ISO_NODE_IS_SYMLINK(n) (iso_node_get_type(n) == LIBISO_SYMLINK) #define ISO_NODE_IS_SPECIAL(n) (iso_node_get_type(n) == LIBISO_SPECIAL) #define ISO_NODE_IS_BOOTCAT(n) (iso_node_get_type(n) == LIBISO_BOOT) /* macros for safe downcasting */ #define ISO_DIR(n) ((IsoDir*)(ISO_NODE_IS_DIR(n) ? n : NULL)) #define ISO_FILE(n) ((IsoFile*)(ISO_NODE_IS_FILE(n) ? n : NULL)) #define ISO_SYMLINK(n) ((IsoSymlink*)(ISO_NODE_IS_SYMLINK(n) ? n : NULL)) #define ISO_SPECIAL(n) ((IsoSpecial*)(ISO_NODE_IS_SPECIAL(n) ? n : NULL)) #define ISO_NODE(n) ((IsoNode*)n) /** * File section in an old image. * * @since 0.6.8 */ struct iso_file_section { uint32_t block; uint32_t size; }; /* If you get here because of a compilation error like /usr/include/libisofs/libisofs.h:166: error: expected specifier-qualifier-list before 'uint32_t' then see the paragraph above about the definition of uint32_t. */ /** * Context for iterate on directory children. * @see iso_dir_get_children() * * @since 0.6.2 */ typedef struct Iso_Dir_Iter IsoDirIter; /** * It represents an El-Torito boot image. * * @since 0.6.2 */ typedef struct el_torito_boot_image ElToritoBootImage; /** * An special type of IsoNode that acts as a placeholder for an El-Torito * boot catalog. Once written, it will appear as a regular file. * * @since 0.6.2 */ typedef struct Iso_Boot IsoBoot; /** * Flag used to hide a file in the RR/ISO or Joliet tree. * * @see iso_node_set_hidden * @since 0.6.2 */ enum IsoHideNodeFlag { /** Hide the node in the ECMA-119 / RR tree */ LIBISO_HIDE_ON_RR = 1 << 0, /** Hide the node in the Joliet tree, if Joliet extension are enabled */ LIBISO_HIDE_ON_JOLIET = 1 << 1, /** Hide the node in the ISO-9660:1999 tree, if that format is enabled */ LIBISO_HIDE_ON_1999 = 1 << 2, /** Hide the node in the HFS+ tree, if that format is enabled. @since 1.2.4 */ LIBISO_HIDE_ON_HFSPLUS = 1 << 4, /** Hide the node in the FAT tree, if that format is enabled. @since 1.2.4 */ LIBISO_HIDE_ON_FAT = 1 << 5, /** With IsoNode and IsoBoot: Write data content even if the node is * not visible in any tree. * With directory nodes : Write data content of IsoNode and IsoBoot * in the directory's tree unless they are * explicitely marked LIBISO_HIDE_ON_RR * without LIBISO_HIDE_BUT_WRITE. * @since 0.6.34 */ LIBISO_HIDE_BUT_WRITE = 1 << 3 }; /** * El-Torito bootable image type. * * @since 0.6.2 */ enum eltorito_boot_media_type { ELTORITO_FLOPPY_EMUL, ELTORITO_HARD_DISC_EMUL, ELTORITO_NO_EMUL }; /** * Replace mode used when addding a node to a directory. * This controls how libisofs will act when you tried to add to a dir a file * with the same name that an existing file. * * @since 0.6.2 */ enum iso_replace_mode { /** * Never replace an existing node, and instead fail with * ISO_NODE_NAME_NOT_UNIQUE. */ ISO_REPLACE_NEVER, /** * Always replace the old node with the new. */ ISO_REPLACE_ALWAYS, /** * Replace with the new node if it is the same file type */ ISO_REPLACE_IF_SAME_TYPE, /** * Replace with the new node if it is the same file type and its ctime * is newer than the old one. */ ISO_REPLACE_IF_SAME_TYPE_AND_NEWER, /** * Replace with the new node if its ctime is newer than the old one. */ ISO_REPLACE_IF_NEWER /* * TODO #00006 define more values * -if both are dirs, add contents (and what to do with conflicts?) */ }; /** * Options for image written. * @see iso_write_opts_new() * @since 0.6.2 */ typedef struct iso_write_opts IsoWriteOpts; /** * Options for image reading or import. * @see iso_read_opts_new() * @since 0.6.2 */ typedef struct iso_read_opts IsoReadOpts; /** * Source for image reading. * * @see struct iso_data_source * @since 0.6.2 */ typedef struct iso_data_source IsoDataSource; /** * Data source used by libisofs for reading an existing image. * * It offers homogeneous read access to arbitrary blocks to different sources * for images, such as .iso files, CD/DVD drives, etc... * * To create a multisession image, libisofs needs a IsoDataSource, that the * user must provide. The function iso_data_source_new_from_file() constructs * an IsoDataSource that uses POSIX I/O functions to access data. You can use * it with regular .iso images, and also with block devices that represent a * drive. * * @since 0.6.2 */ struct iso_data_source { /* reserved for future usage, set to 0 */ int version; /** * Reference count for the data source. Should be 1 when a new source * is created. Don't access it directly, but with iso_data_source_ref() * and iso_data_source_unref() functions. */ unsigned int refcount; /** * Opens the given source. You must open() the source before any attempt * to read data from it. The open is the right place for grabbing the * underlying resources. * * @return * 1 if success, < 0 on error (has to be a valid libisofs error code) */ int (*open)(IsoDataSource *src); /** * Close a given source, freeing all system resources previously grabbed in * open(). * * @return * 1 if success, < 0 on error (has to be a valid libisofs error code) */ int (*close)(IsoDataSource *src); /** * Read an arbitrary block (2048 bytes) of data from the source. * * @param lba * Block to be read. * @param buffer * Buffer where the data will be written. It should have at least * 2048 bytes. * @return * 1 if success, * < 0 if error. This function has to emit a valid libisofs error code. * Predifined (but not mandatory) for this purpose are: * ISO_DATA_SOURCE_SORRY , ISO_DATA_SOURCE_MISHAP, * ISO_DATA_SOURCE_FAILURE , ISO_DATA_SOURCE_FATAL */ int (*read_block)(IsoDataSource *src, uint32_t lba, uint8_t *buffer); /** * Clean up the source specific data. Never call this directly, it is * automatically called by iso_data_source_unref() when refcount reach * 0. */ void (*free_data)(IsoDataSource *src); /** Source specific data */ void *data; }; /** * Return information for image. This is optionally allocated by libisofs, * as a way to inform user about the features of an existing image, such as * extensions present, size, ... * * @see iso_image_import() * @since 0.6.2 */ typedef struct iso_read_image_features IsoReadImageFeatures; /** * POSIX abstraction for source files. * * @see struct iso_file_source * @since 0.6.2 */ typedef struct iso_file_source IsoFileSource; /** * Abstract for source filesystems. * * @see struct iso_filesystem * @since 0.6.2 */ typedef struct iso_filesystem IsoFilesystem; /** * Interface that defines the operations (methods) available for an * IsoFileSource. * * @see struct IsoFileSource_Iface * @since 0.6.2 */ typedef struct IsoFileSource_Iface IsoFileSourceIface; /** * IsoFilesystem implementation to deal with ISO images, and to offer a way to * access specific information of the image, such as several volume attributes, * extensions being used, El-Torito artifacts... * * @since 0.6.2 */ typedef IsoFilesystem IsoImageFilesystem; /** * See IsoFilesystem->get_id() for info about this. * @since 0.6.2 */ extern unsigned int iso_fs_global_id; /** * An IsoFilesystem is a handler for a source of files, or a "filesystem". * That is defined as a set of files that are organized in a hierarchical * structure. * * A filesystem allows libisofs to access files from several sources in * an homogeneous way, thus abstracting the underlying operations needed to * access and read file contents. Note that this doesn't need to be tied * to the disc filesystem used in the partition being accessed. For example, * we have an IsoFilesystem implementation to access any mounted filesystem, * using standard POSIX functions. It is also legal, of course, to implement * an IsoFilesystem to deal with a specific filesystem over raw partitions. * That is what we do, for example, to access an ISO Image. * * Each file inside an IsoFilesystem is represented as an IsoFileSource object, * that defines POSIX-like interface for accessing files. * * @since 0.6.2 */ struct iso_filesystem { /** * Type of filesystem. * "file" -> local filesystem * "iso " -> iso image filesystem */ char type[4]; /* reserved for future usage, set to 0 */ int version; /** * Get the root of a filesystem. * * @return * 1 on success, < 0 on error (has to be a valid libisofs error code) */ int (*get_root)(IsoFilesystem *fs, IsoFileSource **root); /** * Retrieve a file from its absolute path inside the filesystem. * @param file * Returns a pointer to a IsoFileSource object representing the * file. It has to be disposed by iso_file_source_unref() when * no longer needed. * @return * 1 success, < 0 error (has to be a valid libisofs error code) * Error codes: * ISO_FILE_ACCESS_DENIED * ISO_FILE_BAD_PATH * ISO_FILE_DOESNT_EXIST * ISO_OUT_OF_MEM * ISO_FILE_ERROR * ISO_NULL_POINTER */ int (*get_by_path)(IsoFilesystem *fs, const char *path, IsoFileSource **file); /** * Get filesystem identifier. * * If the filesystem is able to generate correct values of the st_dev * and st_ino fields for the struct stat of each file, this should * return an unique number, greater than 0. * * To get a identifier for your filesystem implementation you should * use iso_fs_global_id, incrementing it by one each time. * * Otherwise, if you can't ensure values in the struct stat are valid, * this should return 0. */ unsigned int (*get_id)(IsoFilesystem *fs); /** * Opens the filesystem for several read operations. Calling this funcion * is not needed at all, each time that the underlying system resource * needs to be accessed, it is openned propertly. * However, if you plan to execute several operations on the filesystem, * it is a good idea to open it previously, to prevent several open/close * operations to occur. * * @return 1 on success, < 0 on error (has to be a valid libisofs error code) */ int (*open)(IsoFilesystem *fs); /** * Close the filesystem, thus freeing all system resources. You should * call this function if you have previously open() it. * Note that you can open()/close() a filesystem several times. * * @return 1 on success, < 0 on error (has to be a valid libisofs error code) */ int (*close)(IsoFilesystem *fs); /** * Free implementation specific data. Should never be called by user. * Use iso_filesystem_unref() instead. */ void (*free)(IsoFilesystem *fs); /* internal usage, do never access them directly */ unsigned int refcount; void *data; }; /** * Interface definition for an IsoFileSource. Defines the POSIX-like function * to access files and abstract underlying source. * * @since 0.6.2 */ struct IsoFileSource_Iface { /** * Tells the version of the interface: * Version 0 provides functions up to (*lseek)(). * @since 0.6.2 * Version 1 additionally provides function *(get_aa_string)(). * @since 0.6.14 * Version 2 additionally provides function *(clone_src)(). * @since 1.0.2 */ int version; /** * Get the absolute path in the filesystem this file source belongs to. * * @return * the path of the FileSource inside the filesystem, it should be * freed when no more needed. */ char* (*get_path)(IsoFileSource *src); /** * Get the name of the file, with the dir component of the path. * * @return * the name of the file, it should be freed when no more needed. */ char* (*get_name)(IsoFileSource *src); /** * Get information about the file. It is equivalent to lstat(2). * * @return * 1 success, < 0 error (has to be a valid libisofs error code) * Error codes: * ISO_FILE_ACCESS_DENIED * ISO_FILE_BAD_PATH * ISO_FILE_DOESNT_EXIST * ISO_OUT_OF_MEM * ISO_FILE_ERROR * ISO_NULL_POINTER */ int (*lstat)(IsoFileSource *src, struct stat *info); /** * Get information about the file. If the file is a symlink, the info * returned refers to the destination. It is equivalent to stat(2). * * @return * 1 success, < 0 error * Error codes: * ISO_FILE_ACCESS_DENIED * ISO_FILE_BAD_PATH * ISO_FILE_DOESNT_EXIST * ISO_OUT_OF_MEM * ISO_FILE_ERROR * ISO_NULL_POINTER */ int (*stat)(IsoFileSource *src, struct stat *info); /** * Check if the process has access to read file contents. Note that this * is not necessarily related with (l)stat functions. For example, in a * filesystem implementation to deal with an ISO image, if the user has * read access to the image it will be able to read all files inside it, * despite of the particular permission of each file in the RR tree, that * are what the above functions return. * * @return * 1 if process has read access, < 0 on error (has to be a valid * libisofs error code) * Error codes: * ISO_FILE_ACCESS_DENIED * ISO_FILE_BAD_PATH * ISO_FILE_DOESNT_EXIST * ISO_OUT_OF_MEM * ISO_FILE_ERROR * ISO_NULL_POINTER */ int (*access)(IsoFileSource *src); /** * Opens the source. * @return 1 on success, < 0 on error (has to be a valid libisofs error code) * Error codes: * ISO_FILE_ALREADY_OPENED * ISO_FILE_ACCESS_DENIED * ISO_FILE_BAD_PATH * ISO_FILE_DOESNT_EXIST * ISO_OUT_OF_MEM * ISO_FILE_ERROR * ISO_NULL_POINTER */ int (*open)(IsoFileSource *src); /** * Close a previuously openned file * @return 1 on success, < 0 on error * Error codes: * ISO_FILE_ERROR * ISO_NULL_POINTER * ISO_FILE_NOT_OPENED */ int (*close)(IsoFileSource *src); /** * Attempts to read up to count bytes from the given source into * the buffer starting at buf. * * The file src must be open() before calling this, and close() when no * more needed. Not valid for dirs. On symlinks it reads the destination * file. * * @return * number of bytes read, 0 if EOF, < 0 on error (has to be a valid * libisofs error code) * Error codes: * ISO_FILE_ERROR * ISO_NULL_POINTER * ISO_FILE_NOT_OPENED * ISO_WRONG_ARG_VALUE -> if count == 0 * ISO_FILE_IS_DIR * ISO_OUT_OF_MEM * ISO_INTERRUPTED */ int (*read)(IsoFileSource *src, void *buf, size_t count); /** * Read a directory. * * Each call to this function will return a new children, until we reach * the end of file (i.e, no more children), in that case it returns 0. * * The dir must be open() before calling this, and close() when no more * needed. Only valid for dirs. * * Note that "." and ".." children MUST NOT BE returned. * * @param child * pointer to be filled with the given child. Undefined on error or OEF * @return * 1 on success, 0 if EOF (no more children), < 0 on error (has to be * a valid libisofs error code) * Error codes: * ISO_FILE_ERROR * ISO_NULL_POINTER * ISO_FILE_NOT_OPENED * ISO_FILE_IS_NOT_DIR * ISO_OUT_OF_MEM */ int (*readdir)(IsoFileSource *src, IsoFileSource **child); /** * Read the destination of a symlink. You don't need to open the file * to call this. * * @param buf * allocated buffer of at least bufsiz bytes. * The dest. will be copied there, and it will be NULL-terminated * @param bufsiz * characters to be copied. Destination link will be truncated if * it is larger than given size. This include the 0x0 character. * @return * 1 on success, < 0 on error (has to be a valid libisofs error code) * Error codes: * ISO_FILE_ERROR * ISO_NULL_POINTER * ISO_WRONG_ARG_VALUE -> if bufsiz <= 0 * ISO_FILE_IS_NOT_SYMLINK * ISO_OUT_OF_MEM * ISO_FILE_BAD_PATH * ISO_FILE_DOESNT_EXIST * */ int (*readlink)(IsoFileSource *src, char *buf, size_t bufsiz); /** * Get the filesystem for this source. No extra ref is added, so you * musn't unref the IsoFilesystem. * * @return * The filesystem, NULL on error */ IsoFilesystem* (*get_filesystem)(IsoFileSource *src); /** * Free implementation specific data. Should never be called by user. * Use iso_file_source_unref() instead. */ void (*free)(IsoFileSource *src); /** * Repositions the offset of the IsoFileSource (must be opened) to the * given offset according to the value of flag. * * @param offset * in bytes * @param flag * 0 The offset is set to offset bytes (SEEK_SET) * 1 The offset is set to its current location plus offset bytes * (SEEK_CUR) * 2 The offset is set to the size of the file plus offset bytes * (SEEK_END). * @return * Absolute offset position of the file, or < 0 on error. Cast the * returning value to int to get a valid libisofs error. * * @since 0.6.4 */ off_t (*lseek)(IsoFileSource *src, off_t offset, int flag); /* Add-ons of .version 1 begin here */ /** * Valid only if .version is > 0. See above. * Get the AAIP string with encoded ACL and xattr. * (Not to be confused with ECMA-119 Extended Attributes). * * bit1 and bit2 of flag should be implemented so that freshly fetched * info does not include the undesired ACL or xattr. Nevertheless if the * aa_string is cached, then it is permissible that ACL and xattr are still * delivered. * * @param flag Bitfield for control purposes * bit0= Transfer ownership of AAIP string data. * src will free the eventual cached data and might * not be able to produce it again. * bit1= No need to get ACL (no guarantee of exclusion) * bit2= No need to get xattr (no guarantee of exclusion) * @param aa_string Returns a pointer to the AAIP string data. If no AAIP * string is available, *aa_string becomes NULL. * (See doc/susp_aaip_*_*.txt for the meaning of AAIP and * libisofs/aaip_0_2.h for encoding and decoding.) * The caller is responsible for finally calling free() * on non-NULL results. * @return 1 means success (*aa_string == NULL is possible) * <0 means failure and must b a valid libisofs error code * (e.g. ISO_FILE_ERROR if no better one can be found). * @since 0.6.14 */ int (*get_aa_string)(IsoFileSource *src, unsigned char **aa_string, int flag); /** * Produce a copy of a source. It must be possible to operate both source * objects concurrently. * * @param old_src * The existing source object to be copied * @param new_stream * Will return a pointer to the copy * @param flag * Bitfield for control purposes. Submit 0 for now. * The function shall return ISO_STREAM_NO_CLONE on unknown flag bits. * * @since 1.0.2 * Present if .version is 2 or higher. */ int (*clone_src)(IsoFileSource *old_src, IsoFileSource **new_src, int flag); /* * TODO #00004 Add a get_mime_type() function. * This can be useful for GUI apps, to choose the icon of the file */ }; #ifndef __cplusplus #ifndef Libisofs_h_as_cpluspluS /** * An IsoFile Source is a POSIX abstraction of a file. * * @since 0.6.2 */ struct iso_file_source { const IsoFileSourceIface *class; int refcount; void *data; }; #endif /* ! Libisofs_h_as_cpluspluS */ #endif /* ! __cplusplus */ /* A class of IsoStream is implemented by a class description * IsoStreamIface = struct IsoStream_Iface * and a structure of data storage for each instance of IsoStream. * This structure shall be known to the functions of the IsoStreamIface. * To create a custom IsoStream class: * - Define the structure of the custom instance data. * - Implement the methods which are described by the definition of * struct IsoStream_Iface (see below), * - Create a static instance of IsoStreamIface which lists the methods as * C function pointers. (Example in libisofs/stream.c : fsrc_stream_class) * To create an instance of that class: * - Allocate sizeof(IsoStream) bytes of memory and initialize it as * struct iso_stream : * - Point to the custom IsoStreamIface by member .class . * - Set member .refcount to 1. * - Let member .data point to the custom instance data. * * Regrettably the choice of the structure member name "class" makes it * impossible to implement this generic interface in C++ language directly. * If C++ is absolutely necessary then you will have to make own copies * of the public API structures. Use other names but take care to maintain * the same memory layout. */ /** * Representation of file contents. It is an stream of bytes, functionally * like a pipe. * * @since 0.6.4 */ typedef struct iso_stream IsoStream; /** * Interface that defines the operations (methods) available for an * IsoStream. * * @see struct IsoStream_Iface * @since 0.6.4 */ typedef struct IsoStream_Iface IsoStreamIface; /** * Serial number to be used when you can't get a valid id for a Stream by other * means. If you use this, both fs_id and dev_id should be set to 0. * This must be incremented each time you get a reference to it. * * @see IsoStreamIface->get_id() * @since 0.6.4 */ extern ino_t serial_id; /** * Interface definition for IsoStream methods. It is public to allow * implementation of own stream types. * The methods defined here typically make use of stream.data which points * to the individual state data of stream instances. * * @since 0.6.4 */ struct IsoStream_Iface { /* * Current version of the interface. * Version 0 (since 0.6.4) * deprecated but still valid. * Version 1 (since 0.6.8) * update_size() added. * Version 2 (since 0.6.18) * get_input_stream() added. * A filter stream must have version 2 at least. * Version 3 (since 0.6.20) * cmp_ino() added. * A filter stream should have version 3 at least. * Version 4 (since 1.0.2) * clone_stream() added. */ int version; /** * Type of Stream. * "fsrc" -> Read from file source * "cout" -> Cut out interval from disk file * "mem " -> Read from memory * "boot" -> Boot catalog * "extf" -> External filter program * "ziso" -> zisofs compression * "osiz" -> zisofs uncompression * "gzip" -> gzip compression * "pizg" -> gzip uncompression (gunzip) * "user" -> User supplied stream */ char type[4]; /** * Opens the stream. * * @return * 1 on success, 2 file greater than expected, 3 file smaller than * expected, < 0 on error (has to be a valid libisofs error code) */ int (*open)(IsoStream *stream); /** * Close the Stream. * @return * 1 on success, < 0 on error (has to be a valid libisofs error code) */ int (*close)(IsoStream *stream); /** * Get the size (in bytes) of the stream. This function should always * return the same size, even if the underlying source size changes, * unless you call update_size() method. */ off_t (*get_size)(IsoStream *stream); /** * Attempt to read up to count bytes from the given stream into * the buffer starting at buf. The implementation has to make sure that * either the full desired count of bytes is delivered or that the * next call to this function will return EOF or error. * I.e. only the last read block may be shorter than parameter count. * * The stream must be open() before calling this, and close() when no * more needed. * * @return * number of bytes read, 0 if EOF, < 0 on error (has to be a valid * libisofs error code) */ int (*read)(IsoStream *stream, void *buf, size_t count); /** * Tell whether this IsoStream can be read several times, with the same * results. For example, a regular file is repeatable, you can read it * as many times as you want. However, a pipe is not. * * @return * 1 if stream is repeatable, 0 if not, * < 0 on error (has to be a valid libisofs error code) */ int (*is_repeatable)(IsoStream *stream); /** * Get an unique identifier for the IsoStream. */ void (*get_id)(IsoStream *stream, unsigned int *fs_id, dev_t *dev_id, ino_t *ino_id); /** * Free implementation specific data. Should never be called by user. * Use iso_stream_unref() instead. */ void (*free)(IsoStream *stream); /** * Update the size of the IsoStream with the current size of the underlying * source, if the source is prone to size changes. After calling this, * get_size() shall eventually return the new size. * This will never be called after iso_image_create_burn_source() was * called and before the image was completely written. * (The API call to update the size of all files in the image is * iso_image_update_sizes()). * * @return * 1 if ok, < 0 on error (has to be a valid libisofs error code) * * @since 0.6.8 * Present if .version is 1 or higher. */ int (*update_size)(IsoStream *stream); /** * Retrieve the eventual input stream of a filter stream. * * @param stream * The eventual filter stream to be inquired. * @param flag * Bitfield for control purposes. 0 means normal behavior. * @return * The input stream, if one exists. Elsewise NULL. * No extra reference to the stream shall be taken by this call. * * @since 0.6.18 * Present if .version is 2 or higher. */ IsoStream *(*get_input_stream)(IsoStream *stream, int flag); /** * Compare two streams whether they are based on the same input and will * produce the same output. If in any doubt, then this comparison should * indicate no match. A match might allow hardlinking of IsoFile objects. * * A pointer value of NULL is permissible. In this case, function * iso_stream_cmp_ino() will decide on its own. * * If not NULL, this function .cmp_ino() will be called by * iso_stream_cmp_ino() if both compared streams point to it, and if not * flag bit0 of iso_stream_cmp_ino() prevents it. * So a .cmp_ino() function must be able to compare any pair of streams * which name it as their .cmp_ino(). A fallback to iso_stream_cmp_ino(,,1) * would endanger transitivity of iso_stream_cmp_ino(,,0). * * With filter streams, the decision whether the underlying chains of * streams match, should be delegated to * iso_stream_cmp_ino(iso_stream_get_input_stream(s1, 0), * iso_stream_get_input_stream(s2, 0), 0); * * The stream.cmp_ino() function has to establish an equivalence and order * relation: * cmp_ino(A,A) == 0 * cmp_ino(A,B) == -cmp_ino(B,A) * if cmp_ino(A,B) == 0 && cmp_ino(B,C) == 0 then cmp_ino(A,C) == 0 * Most tricky is the demand for transitivity: * if cmp_ino(A,B) < 0 && cmp_ino(B,C) < 0 then cmp_ino(A,C) < 0 * * @param s1 * The first stream to compare. Expect foreign stream types. * @param s2 * The second stream to compare. Expect foreign stream types. * @return * -1 if s1 is smaller s2 , 0 if s1 matches s2 , 1 if s1 is larger s2 * * @since 0.6.20 * Present if .version is 3 or higher. */ int (*cmp_ino)(IsoStream *s1, IsoStream *s2); /** * Produce a copy of a stream. It must be possible to operate both stream * objects concurrently. * * @param old_stream * The existing stream object to be copied * @param new_stream * Will return a pointer to the copy * @param flag * Bitfield for control purposes. 0 means normal behavior. * The function shall return ISO_STREAM_NO_CLONE on unknown flag bits. * @return * 1 in case of success, or an error code < 0 * * @since 1.0.2 * Present if .version is 4 or higher. */ int (*clone_stream)(IsoStream *old_stream, IsoStream **new_stream, int flag); }; #ifndef __cplusplus #ifndef Libisofs_h_as_cpluspluS /** * Representation of file contents as a stream of bytes. * * @since 0.6.4 */ struct iso_stream { IsoStreamIface *class; int refcount; void *data; }; #endif /* ! Libisofs_h_as_cpluspluS */ #endif /* ! __cplusplus */ /** * Initialize libisofs. Before any usage of the library you must either call * this function or iso_init_with_flag(). * Only exception from this rule: iso_lib_version(), iso_lib_is_compatible(). * @return 1 on success, < 0 on error * * @since 0.6.2 */ int iso_init(); /** * Initialize libisofs. Before any usage of the library you must either call * this function or iso_init() which is equivalent to iso_init_with_flag(0). * Only exception from this rule: iso_lib_version(), iso_lib_is_compatible(). * @param flag * Bitfield for control purposes * bit0= do not set up locale by LC_* environment variables * @return 1 on success, < 0 on error * * @since 0.6.18 */ int iso_init_with_flag(int flag); /** * Finalize libisofs. * * @since 0.6.2 */ void iso_finish(); /** * Override the reply of libc function nl_langinfo(CODESET) which may or may * not give the name of the character set which is in effect for your * environment. So this call can compensate for inconsistent terminal setups. * Another use case is to choose UTF-8 as intermediate character set for a * conversion from an exotic input character set to an exotic output set. * * @param name * Name of the character set to be assumed as "local" one. * @param flag * Unused yet. Submit 0. * @return * 1 indicates success, <=0 failure * * @since 0.6.12 */ int iso_set_local_charset(char *name, int flag); /** * Obtain the local charset as currently assumed by libisofs. * The result points to internal memory. It is volatile and must not be * altered. * * @param flag * Unused yet. Submit 0. * * @since 0.6.12 */ char *iso_get_local_charset(int flag); /** * Create a new image, empty. * * The image will be owned by you and should be unref() when no more needed. * * @param name * Name of the image. This will be used as volset_id and volume_id. * @param image * Location where the image pointer will be stored. * @return * 1 sucess, < 0 error * * @since 0.6.2 */ int iso_image_new(const char *name, IsoImage **image); /** * Control whether ACL and xattr will be imported from external filesystems * (typically the local POSIX filesystem) when new nodes get inserted. If * enabled by iso_write_opts_set_aaip() they will later be written into the * image as AAIP extension fields. * * A change of this setting does neither affect existing IsoNode objects * nor the way how ACL and xattr are handled when loading an ISO image. * The latter is controlled by iso_read_opts_set_no_aaip(). * * @param image * The image of which the behavior is to be controlled * @param what * A bit field which sets the behavior: * bit0= ignore ACLs if the external file object bears some * bit1= ignore xattr if the external file object bears some * all other bits are reserved * * @since 0.6.14 */ void iso_image_set_ignore_aclea(IsoImage *image, int what); /** * Creates an IsoWriteOpts for writing an image. You should set the options * desired with the correspondent setters. * * Options by default are determined by the selected profile. Fifo size is set * by default to 2 MB. * * @param opts * Pointer to the location where the newly created IsoWriteOpts will be * stored. You should free it with iso_write_opts_free() when no more * needed. * @param profile * Default profile for image creation. For now the following values are * defined: * ---> 0 [BASIC] * No extensions are enabled, and ISO level is set to 1. Only suitable * for usage for very old and limited systems (like MS-DOS), or by a * start point from which to set your custom options. * ---> 1 [BACKUP] * POSIX compatibility for backup. Simple settings, ISO level is set to * 3 and RR extensions are enabled. Useful for backup purposes. * Note that ACL and xattr are not enabled by default. * If you enable them, expect them not to show up in the mounted image. * They will have to be retrieved by libisofs applications like xorriso. * ---> 2 [DISTRIBUTION] * Setting for information distribution. Both RR and Joliet are enabled * to maximize compatibility with most systems. Permissions are set to * default values, and timestamps to the time of recording. * @return * 1 success, < 0 error * * @since 0.6.2 */ int iso_write_opts_new(IsoWriteOpts **opts, int profile); /** * Free an IsoWriteOpts previously allocated with iso_write_opts_new(). * * @since 0.6.2 */ void iso_write_opts_free(IsoWriteOpts *opts); /** * Announce that only the image size is desired, that the struct burn_source * which is set to consume the image output stream will stay inactive, * and that the write thread will be cancelled anyway by the .cancel() method * of the struct burn_source. * This avoids to create a write thread which would begin production of the * image stream and would generate a MISHAP event when burn_source.cancel() * gets into effect. * * @param opts * The option set to be manipulated. * @param will_cancel * 0= normal image generation * 1= prepare for being canceled before image stream output is completed * @return * 1 success, < 0 error * * @since 0.6.40 */ int iso_write_opts_set_will_cancel(IsoWriteOpts *opts, int will_cancel); /** * Set the ISO-9960 level to write at. * * @param opts * The option set to be manipulated. * @param level * -> 1 for higher compatibility with old systems. With this level * filenames are restricted to 8.3 characters. * -> 2 to allow up to 31 filename characters. * -> 3 to allow files greater than 4GB * @return * 1 success, < 0 error * * @since 0.6.2 */ int iso_write_opts_set_iso_level(IsoWriteOpts *opts, int level); /** * Whether to use or not Rock Ridge extensions. * * This are standard extensions to ECMA-119, intended to add POSIX filesystem * features to ECMA-119 images. Thus, usage of this flag is highly recommended * for images used on GNU/Linux systems. With the usage of RR extension, the * resulting image will have long filenames (up to 255 characters), deeper * directory structure, POSIX permissions and owner info on files and * directories, support for symbolic links or special files... All that * attributes can be modified/setted with the appropiate function. * * @param opts * The option set to be manipulated. * @param enable * 1 to enable RR extension, 0 to not add them * @return * 1 success, < 0 error * * @since 0.6.2 */ int iso_write_opts_set_rockridge(IsoWriteOpts *opts, int enable); /** * Whether to add the non-standard Joliet extension to the image. * * This extensions are heavily used in Microsoft Windows systems, so if you * plan to use your disc on such a system you should add this extension. * Usage of Joliet supplies longer filesystem length (up to 64 unicode * characters), and deeper directory structure. * * @param opts * The option set to be manipulated. * @param enable * 1 to enable Joliet extension, 0 to not add them * @return * 1 success, < 0 error * * @since 0.6.2 */ int iso_write_opts_set_joliet(IsoWriteOpts *opts, int enable); /** * Whether to add a HFS+ filesystem to the image which points to the same * file content as the other directory trees. * It will get marked by an Apple Partition Map in the System Area of the ISO * image. This may collide with data submitted by * iso_write_opts_set_system_area() * and with settings made by * el_torito_set_isolinux_options() * The first 8 bytes of the System Area get overwritten by * {0x45, 0x52, 0x08 0x00, 0xeb, 0x02, 0xff, 0xff} * which can be executed as x86 machine code without negative effects. * So if an MBR gets combined with this feature, then its first 8 bytes * should contain no essential commands. * The next blocks of 2 KiB in the System Area will be occupied by APM entries. * The first one covers the part of the ISO image before the HFS+ filesystem * metadata. The second one marks the range from HFS+ metadata to the end * of file content data. If more ISO image data follow, then a third partition * entry gets produced. Other features of libisofs might cause the need for * more APM entries. * * @param opts * The option set to be manipulated. * @param enable * 1 to enable HFS+ extension, 0 to not add HFS+ metadata and APM * @return * 1 success, < 0 error * * @since 1.2.4 */ int iso_write_opts_set_hfsplus(IsoWriteOpts *opts, int enable); /** * >>> Production of FAT32 is not implemented yet. * >>> This call exists only as preparation for implementation. * * Whether to add a FAT32 filesystem to the image which points to the same * file content as the other directory trees. * * >>> FAT32 is planned to get implemented in co-existence with HFS+ * >>> Describe impact on MBR * * @param opts * The option set to be manipulated. * @param enable * 1 to enable FAT32 extension, 0 to not add FAT metadata * @return * 1 success, < 0 error * * @since 1.2.4 */ int iso_write_opts_set_fat(IsoWriteOpts *opts, int enable); /** * Supply a serial number for the HFS+ extension of the emerging image. * * @param opts * The option set to be manipulated. * @param serial_number * 8 bytes which should be unique to the image. * If all bytes are 0, then the serial number will be generated as * random number by libisofs. This is the default setting. * @return * 1 success, < 0 error * * @since 1.2.4 */ int iso_write_opts_set_hfsp_serial_number(IsoWriteOpts *opts, uint8_t serial_number[8]); /** * Set the block size for Apple Partition Map and for HFS+. * * @param opts * The option set to be manipulated. * @param hfsp_block_size * The allocation block size to be used by the HFS+ fileystem. * 0, 512, or 2048 * @param hfsp_block_size * The block size to be used for and within the Apple Partition Map. * 0, 512, or 2048. * Size 512 is not compatible with options which produce GPT. * @return * 1 success, < 0 error * * @since 1.2.4 */ int iso_write_opts_set_hfsp_block_size(IsoWriteOpts *opts, int hfsp_block_size, int apm_block_size); /** * Whether to use newer ISO-9660:1999 version. * * This is the second version of ISO-9660. It allows longer filenames and has * less restrictions than old ISO-9660. However, nobody is using it so there * are no much reasons to enable this. * * @since 0.6.2 */ int iso_write_opts_set_iso1999(IsoWriteOpts *opts, int enable); /** * Control generation of non-unique inode numbers for the emerging image. * Inode numbers get written as "file serial number" with PX entries as of * RRIP-1.12. They may mark families of hardlinks. * RRIP-1.10 prescribes a PX entry without file serial number. If not overriden * by iso_write_opts_set_rrip_1_10_px_ino() there will be no file serial number * written into RRIP-1.10 images. * * Inode number generation does not affect IsoNode objects which imported their * inode numbers from the old ISO image (see iso_read_opts_set_new_inos()) * and which have not been altered since import. It rather applies to IsoNode * objects which were newly added to the image, or to IsoNode which brought no * inode number from the old image, or to IsoNode where certain properties * have been altered since image import. * * If two IsoNode are found with same imported inode number but differing * properties, then one of them will get assigned a new unique inode number. * I.e. the hardlink relation between both IsoNode objects ends. * * @param opts * The option set to be manipulated. * @param enable * 1 = Collect IsoNode objects which have identical data sources and * properties. * 0 = Generate unique inode numbers for all IsoNode objects which do not * have a valid inode number from an imported ISO image. * All other values are reserved. * * @since 0.6.20 */ int iso_write_opts_set_hardlinks(IsoWriteOpts *opts, int enable); /** * Control writing of AAIP informations for ACL and xattr. * For importing ACL and xattr when inserting nodes from external filesystems * (e.g. the local POSIX filesystem) see iso_image_set_ignore_aclea(). * For loading of this information from images see iso_read_opts_set_no_aaip(). * * @param opts * The option set to be manipulated. * @param enable * 1 = write AAIP information from nodes into the image * 0 = do not write AAIP information into the image * All other values are reserved. * * @since 0.6.14 */ int iso_write_opts_set_aaip(IsoWriteOpts *opts, int enable); /** * Use this only if you need to reproduce a suboptimal behavior of older * versions of libisofs. They used address 0 for links and device files, * and the address of the Volume Descriptor Set Terminator for empty data * files. * New versions let symbolic links, device files, and empty data files point * to a dedicated block of zero-bytes after the end of the directory trees. * (Single-pass reader libarchive needs to see all directory info before * processing any data files.) * * @param opts * The option set to be manipulated. * @param enable * 1 = use the suboptimal block addresses in the range of 0 to 115. * 0 = use the address of a block after the directory tree. (Default) * * @since 1.0.2 */ int iso_write_opts_set_old_empty(IsoWriteOpts *opts, int enable); /** * Caution: This option breaks any assumptions about names that * are supported by ECMA-119 specifications. * Try to omit any translation which would make a file name compliant to the * ECMA-119 rules. This includes and exceeds omit_version_numbers, * max_37_char_filenames, no_force_dots bit0, allow_full_ascii. Further it * prevents the conversion from local character set to ASCII. * The maximum name length is given by this call. If a filename exceeds * this length or cannot be recorded untranslated for other reasons, then * image production is aborted with ISO_NAME_NEEDS_TRANSL. * Currently the length limit is 96 characters, because an ECMA-119 directory * record may at most have 254 bytes and up to 158 other bytes must fit into * the record. Probably 96 more bytes can be made free for the name in future. * @param opts * The option set to be manipulated. * @param len * 0 = disable this feature and perform name translation according to * other settings. * >0 = Omit any translation. Eventually abort image production * if a name is longer than the given value. * -1 = Like >0. Allow maximum possible length (currently 96) * @return >=0 success, <0 failure * In case of >=0 the return value tells the effectively set len. * E.g. 96 after using len == -1. * @since 1.0.0 */ int iso_write_opts_set_untranslated_name_len(IsoWriteOpts *opts, int len); /** * Convert directory names for ECMA-119 similar to other file names, but do * not force a dot or add a version number. * This violates ECMA-119 by allowing one "." and especially ISO level 1 * by allowing DOS style 8.3 names rather than only 8 characters. * (mkisofs and its clones seem to do this violation.) * @param opts * The option set to be manipulated. * @param allow * 1= allow dots , 0= disallow dots and convert them * @return * 1 success, < 0 error * @since 1.0.0 */ int iso_write_opts_set_allow_dir_id_ext(IsoWriteOpts *opts, int allow); /** * Omit the version number (";1") at the end of the ISO-9660 identifiers. * This breaks ECMA-119 specification, but version numbers are usually not * used, so it should work on most systems. Use with caution. * @param opts * The option set to be manipulated. * @param omit * bit0= omit version number with ECMA-119 and Joliet * bit1= omit version number with Joliet alone (@since 0.6.30) * @since 0.6.2 */ int iso_write_opts_set_omit_version_numbers(IsoWriteOpts *opts, int omit); /** * Allow ISO-9660 directory hierarchy to be deeper than 8 levels. * This breaks ECMA-119 specification. Use with caution. * * @since 0.6.2 */ int iso_write_opts_set_allow_deep_paths(IsoWriteOpts *opts, int allow); /** * This call describes the directory where to store Rock Ridge relocated * directories. * If not iso_write_opts_set_allow_deep_paths(,1) is in effect, then it may * become necessary to relocate directories so that no ECMA-119 file path * has more than 8 components. These directories are grafted into either * the root directory of the ISO image or into a dedicated relocation * directory. * For Rock Ridge, the relocated directories are linked forth and back to * placeholders at their original positions in path level 8. Directories * marked by Rock Ridge entry RE are to be considered artefacts of relocation * and shall not be read into a Rock Ridge tree. Instead they are to be read * via their placeholders and their links. * For plain ECMA-119, the relocation directory and the relocated directories * are just normal directories which contain normal files and directories. * @param opts * The option set to be manipulated. * @param name * The name of the relocation directory in the root directory. Do not * prepend "/". An empty name or NULL will direct relocated directories * into the root directory. This is the default. * If the given name does not exist in the root directory when * iso_image_create_burn_source() is called, and if there are directories * at path level 8, then directory /name will be created automatically. * The name given by this call will be compared with iso_node_get_name() * of the directories in the root directory, not with the final ECMA-119 * names of those directories. * @parm flags * Bitfield for control purposes. * bit0= Mark the relocation directory by a Rock Ridge RE entry, if it * gets created during iso_image_create_burn_source(). This will * make it invisible for most Rock Ridge readers. * bit1= not settable via API (used internally) * @return * 1 success, < 0 error * @since 1.2.2 */ int iso_write_opts_set_rr_reloc(IsoWriteOpts *opts, char *name, int flags); /** * Allow path in the ISO-9660 tree to have more than 255 characters. * This breaks ECMA-119 specification. Use with caution. * * @since 0.6.2 */ int iso_write_opts_set_allow_longer_paths(IsoWriteOpts *opts, int allow); /** * Allow a single file or directory identifier to have up to 37 characters. * This is larger than the 31 characters allowed by ISO level 2, and the * extra space is taken from the version number, so this also forces * omit_version_numbers. * This breaks ECMA-119 specification and could lead to buffer overflow * problems on old systems. Use with caution. * * @since 0.6.2 */ int iso_write_opts_set_max_37_char_filenames(IsoWriteOpts *opts, int allow); /** * ISO-9660 forces filenames to have a ".", that separates file name from * extension. libisofs adds it if original filename doesn't has one. Set * this to 1 to prevent this behavior. * This breaks ECMA-119 specification. Use with caution. * * @param opts * The option set to be manipulated. * @param no * bit0= no forced dot with ECMA-119 * bit1= no forced dot with Joliet (@since 0.6.30) * * @since 0.6.2 */ int iso_write_opts_set_no_force_dots(IsoWriteOpts *opts, int no); /** * Allow lowercase characters in ISO-9660 filenames. By default, only * uppercase characters, numbers and a few other characters are allowed. * This breaks ECMA-119 specification. Use with caution. * If lowercase is not allowed then those letters get mapped to uppercase * letters. * * @since 0.6.2 */ int iso_write_opts_set_allow_lowercase(IsoWriteOpts *opts, int allow); /** * Allow all 8-bit characters to appear on an ISO-9660 filename. Note * that "/" and 0x0 characters are never allowed, even in RR names. * This breaks ECMA-119 specification. Use with caution. * * @since 0.6.2 */ int iso_write_opts_set_allow_full_ascii(IsoWriteOpts *opts, int allow); /** * If not iso_write_opts_set_allow_full_ascii() is set to 1: * Allow all 7-bit characters that would be allowed by allow_full_ascii, but * map lowercase to uppercase if iso_write_opts_set_allow_lowercase() * is not set to 1. * @param opts * The option set to be manipulated. * @param allow * If not zero, then allow what is described above. * * @since 1.2.2 */ int iso_write_opts_set_allow_7bit_ascii(IsoWriteOpts *opts, int allow); /** * Allow all characters to be part of Volume and Volset identifiers on * the Primary Volume Descriptor. This breaks ISO-9660 contraints, but * should work on modern systems. * * @since 0.6.2 */ int iso_write_opts_set_relaxed_vol_atts(IsoWriteOpts *opts, int allow); /** * Allow paths in the Joliet tree to have more than 240 characters. * This breaks Joliet specification. Use with caution. * * @since 0.6.2 */ int iso_write_opts_set_joliet_longer_paths(IsoWriteOpts *opts, int allow); /** * Allow leaf names in the Joliet tree to have up to 103 characters. * Normal limit is 64. * This breaks Joliet specification. Use with caution. * * @since 1.0.6 */ int iso_write_opts_set_joliet_long_names(IsoWriteOpts *opts, int allow); /** * Use character set UTF-16BE with Joliet, which is a superset of the * actually prescribed character set UCS-2. * This breaks Joliet specification with exotic characters which would * elsewise be mapped to underscore '_'. Use with caution. * * @since 1.3.6 */ int iso_write_opts_set_joliet_utf16(IsoWriteOpts *opts, int allow); /** * Write Rock Ridge info as of specification RRIP-1.10 rather than RRIP-1.12: * signature "RRIP_1991A" rather than "IEEE_1282", field PX without file * serial number. * * @since 0.6.12 */ int iso_write_opts_set_rrip_version_1_10(IsoWriteOpts *opts, int oldvers); /** * Write field PX with file serial number (i.e. inode number) even if * iso_write_opts_set_rrip_version_1_10(,1) is in effect. * This clearly violates the RRIP-1.10 specs. But it is done by mkisofs since * a while and no widespread protest is visible in the web. * If this option is not enabled, then iso_write_opts_set_hardlinks() will * only have an effect with iso_write_opts_set_rrip_version_1_10(,0). * * @since 0.6.20 */ int iso_write_opts_set_rrip_1_10_px_ino(IsoWriteOpts *opts, int enable); /** * Write AAIP as extension according to SUSP 1.10 rather than SUSP 1.12. * I.e. without announcing it by an ER field and thus without the need * to preceed the RRIP fields and the AAIP field by ES fields. * This saves 5 to 10 bytes per file and might avoid problems with readers * which dislike ER fields other than the ones for RRIP. * On the other hand, SUSP 1.12 frowns on such unannounced extensions * and prescribes ER and ES. It does this since the year 1994. * * In effect only if above iso_write_opts_set_aaip() enables writing of AAIP. * * @since 0.6.14 */ int iso_write_opts_set_aaip_susp_1_10(IsoWriteOpts *opts, int oldvers); /** * Store as ECMA-119 Directory Record timestamp the mtime of the source node * rather than the image creation time. * If storing of mtime is enabled, then the settings of * iso_write_opts_set_replace_timestamps() apply. (replace==1 will revoke, * replace==2 will override mtime by iso_write_opts_set_default_timestamp(). * * Since version 1.2.0 this may apply also to Joliet and ISO 9660:1999. To * reduce the probability of unwanted behavior changes between pre-1.2.0 and * post-1.2.0, the bits for Joliet and ISO 9660:1999 also enable ECMA-119. * The hopefully unlikely bit14 may then be used to disable mtime for ECMA-119. * * To enable mtime for all three directory trees, submit 7. * To disable this feature completely, submit 0. * * @param opts * The option set to be manipulated. * @param allow * If this parameter is negative, then mtime is enabled only for ECMA-119. * With positive numbers, the parameter is interpreted as bit field : * bit0= enable mtime for ECMA-119 * bit1= enable mtime for Joliet and ECMA-119 * bit2= enable mtime for ISO 9660:1999 and ECMA-119 * bit14= disable mtime for ECMA-119 although some of the other bits * would enable it * @since 1.2.0 * Before version 1.2.0 this applied only to ECMA-119 : * 0 stored image creation time in ECMA-119 tree. * Any other value caused storing of mtime. * Joliet and ISO 9660:1999 always stored the image creation time. * @since 0.6.12 */ int iso_write_opts_set_dir_rec_mtime(IsoWriteOpts *opts, int allow); /** * Whether to sort files based on their weight. * * @see iso_node_set_sort_weight * @since 0.6.2 */ int iso_write_opts_set_sort_files(IsoWriteOpts *opts, int sort); /** * Whether to compute and record MD5 checksums for the whole session and/or * for each single IsoFile object. The checksums represent the data as they * were written into the image output stream, not necessarily as they were * on hard disk at any point of time. * See also calls iso_image_get_session_md5() and iso_file_get_md5(). * @param opts * The option set to be manipulated. * @param session * If bit0 set: Compute session checksum * @param files * If bit0 set: Compute a checksum for each single IsoFile object which * gets its data content written into the session. Copy * checksums from files which keep their data in older * sessions. * If bit1 set: Check content stability (only with bit0). I.e. before * writing the file content into to image stream, read it * once and compute a MD5. Do a second reading for writing * into the image stream. Afterwards compare both MD5 and * issue a MISHAP event ISO_MD5_STREAM_CHANGE if they do not * match. * Such a mismatch indicates content changes between the * time point when the first MD5 reading started and the * time point when the last block was read for writing. * So there is high risk that the image stream was fed from * changing and possibly inconsistent file content. * * @since 0.6.22 */ int iso_write_opts_set_record_md5(IsoWriteOpts *opts, int session, int files); /** * Set the parameters "name" and "timestamp" for a scdbackup checksum tag. * It will be appended to the libisofs session tag if the image starts at * LBA 0 (see iso_write_opts_set_ms_block()). The scdbackup tag can be used * to verify the image by command scdbackup_verify device -auto_end. * See scdbackup/README appendix VERIFY for its inner details. * * @param opts * The option set to be manipulated. * @param name * A word of up to 80 characters. Typically volno_totalno telling * that this is volume volno of a total of totalno volumes. * @param timestamp * A string of 13 characters YYMMDD.hhmmss (e.g. A90831.190324). * A9 = 2009, B0 = 2010, B1 = 2011, ... C0 = 2020, ... * @param tag_written * Either NULL or the address of an array with at least 512 characters. * In the latter case the eventually produced scdbackup tag will be * copied to this array when the image gets written. This call sets * scdbackup_tag_written[0] = 0 to mark its preliminary invalidity. * @return * 1 indicates success, <0 is error * * @since 0.6.24 */ int iso_write_opts_set_scdbackup_tag(IsoWriteOpts *opts, char *name, char *timestamp, char *tag_written); /** * Whether to set default values for files and directory permissions, gid and * uid. All these take one of three values: 0, 1 or 2. * * If 0, the corresponding attribute will be kept as set in the IsoNode. * Unless you have changed it, it corresponds to the value on disc, so it * is suitable for backup purposes. If set to 1, the corresponding attrib. * will be changed by a default suitable value. Finally, if you set it to * 2, the attrib. will be changed with the value specified by the functioins * below. Note that for mode attributes, only the permissions are set, the * file type remains unchanged. * * @see iso_write_opts_set_default_dir_mode * @see iso_write_opts_set_default_file_mode * @see iso_write_opts_set_default_uid * @see iso_write_opts_set_default_gid * @since 0.6.2 */ int iso_write_opts_set_replace_mode(IsoWriteOpts *opts, int dir_mode, int file_mode, int uid, int gid); /** * Set the mode to use on dirs when you set the replace_mode of dirs to 2. * * @see iso_write_opts_set_replace_mode * @since 0.6.2 */ int iso_write_opts_set_default_dir_mode(IsoWriteOpts *opts, mode_t dir_mode); /** * Set the mode to use on files when you set the replace_mode of files to 2. * * @see iso_write_opts_set_replace_mode * @since 0.6.2 */ int iso_write_opts_set_default_file_mode(IsoWriteOpts *opts, mode_t file_mode); /** * Set the uid to use when you set the replace_uid to 2. * * @see iso_write_opts_set_replace_mode * @since 0.6.2 */ int iso_write_opts_set_default_uid(IsoWriteOpts *opts, uid_t uid); /** * Set the gid to use when you set the replace_gid to 2. * * @see iso_write_opts_set_replace_mode * @since 0.6.2 */ int iso_write_opts_set_default_gid(IsoWriteOpts *opts, gid_t gid); /** * 0 to use IsoNode timestamps, 1 to use recording time, 2 to use * values from timestamp field. This applies to the timestamps of Rock Ridge * and if the use of mtime is enabled by iso_write_opts_set_dir_rec_mtime(). * In the latter case, value 1 will revoke the recording of mtime, value * 2 will override mtime by iso_write_opts_set_default_timestamp(). * * @see iso_write_opts_set_default_timestamp * @since 0.6.2 */ int iso_write_opts_set_replace_timestamps(IsoWriteOpts *opts, int replace); /** * Set the timestamp to use when you set the replace_timestamps to 2. * * @see iso_write_opts_set_replace_timestamps * @since 0.6.2 */ int iso_write_opts_set_default_timestamp(IsoWriteOpts *opts, time_t timestamp); /** * Whether to always record timestamps in GMT. * * By default, libisofs stores local time information on image. You can set * this to always store timestamps converted to GMT. This prevents any * discrimination of the timezone of the image preparer by the image reader. * * It is useful if you want to hide your timezone, or you live in a timezone * that can't be represented in ECMA-119. These are timezones with an offset * from GMT greater than +13 hours, lower than -12 hours, or not a multiple * of 15 minutes. * Negative timezones (west of GMT) can trigger bugs in some operating systems * which typically appear in mounted ISO images as if the timezone shift from * GMT was applied twice (e.g. in New York 22:36 becomes 17:36). * * @since 0.6.2 */ int iso_write_opts_set_always_gmt(IsoWriteOpts *opts, int gmt); /** * Set the charset to use for the RR names of the files that will be created * on the image. * NULL to use default charset, that is the locale charset. * You can obtain the list of charsets supported on your system executing * "iconv -l" in a shell. * * @since 0.6.2 */ int iso_write_opts_set_output_charset(IsoWriteOpts *opts, const char *charset); /** * Set the type of image creation in case there was already an existing * image imported. Libisofs supports two types of creation: * stand-alone and appended. * * A stand-alone image is an image that does not need the old image any more * for being mounted by the operating system or imported by libisofs. It may * be written beginning with byte 0 of optical media or disk file objects. * There will be no distinction between files from the old image and those * which have been added by the new image generation. * * On the other side, an appended image is not self contained. It may refer * to files that stay stored in the imported existing image. * This usage model is inspired by CD multi-session. It demands that the * appended image is finally written to the same media or disk file * as the imported image at an address behind the end of that imported image. * The exact address may depend on media peculiarities and thus has to be * announced by the application via iso_write_opts_set_ms_block(). * The real address where the data will be written is under control of the * consumer of the struct burn_source which takes the output of libisofs * image generation. It may be the one announced to libisofs or an intermediate * one. Nevertheless, the image will be readable only at the announced address. * * If you have not imported a previous image by iso_image_import(), then the * image will always be a stand-alone image, as there is no previous data to * refer to. * * @param opts * The option set to be manipulated. * @param append * 1 to create an appended image, 0 for an stand-alone one. * * @since 0.6.2 */ int iso_write_opts_set_appendable(IsoWriteOpts *opts, int append); /** * Set the start block of the image. It is supposed to be the lba where the * first block of the image will be written on disc. All references inside the * ISO image will take this into account, thus providing a mountable image. * * For appendable images, that are written to a new session, you should * pass here the lba of the next writable address on disc. * * In stand alone images this is usually 0. However, you may want to * provide a different ms_block if you don't plan to burn the image in the * first session on disc, such as in some CD-Extra disc whether the data * image is written in a new session after some audio tracks. * * @since 0.6.2 */ int iso_write_opts_set_ms_block(IsoWriteOpts *opts, uint32_t ms_block); /** * Sets the buffer where to store the descriptors which shall be written * at the beginning of an overwriteable media to point to the newly written * image. * This is needed if the write start address of the image is not 0. * In this case the first 64 KiB of the media have to be overwritten * by the buffer content after the session was written and the buffer * was updated by libisofs. Otherwise the new session would not be * found by operating system function mount() or by libisoburn. * (One could still mount that session if its start address is known.) * * If you do not need this information, for example because you are creating a * new image for LBA 0 or because you will create an image for a true * multisession media, just do not use this call or set buffer to NULL. * * Use cases: * * - Together with iso_write_opts_set_appendable(opts, 1) the buffer serves * for the growing of an image as done in growisofs by Andy Polyakov. * This allows appending of a new session to non-multisession media, such * as DVD+RW. The new session will refer to the data of previous sessions * on the same media. * libisoburn emulates multisession appendability on overwriteable media * and disk files by performing this use case. * * - Together with iso_write_opts_set_appendable(opts, 0) the buffer allows * to write the first session on overwriteable media to start addresses * other than 0. * This address must not be smaller than 32 blocks plus the eventual * partition offset as defined by iso_write_opts_set_part_offset(). * libisoburn in most cases writes the first session on overwriteable media * and disk files to LBA (32 + partition_offset) in order to preserve its * descriptors from the subsequent overwriting by the descriptor buffer of * later sessions. * * @param opts * The option set to be manipulated. * @param overwrite * When not NULL, it should point to at least 64KiB of memory, where * libisofs will install the contents that shall be written at the * beginning of overwriteable media. * You should initialize the buffer either with 0s, or with the contents * of the first 32 blocks of the image you are growing. In most cases, * 0 is good enought. * IMPORTANT: If you use iso_write_opts_set_part_offset() then the * overwrite buffer must be larger by the offset defined there. * * @since 0.6.2 */ int iso_write_opts_set_overwrite_buf(IsoWriteOpts *opts, uint8_t *overwrite); /** * Set the size, in number of blocks, of the ring buffer used between the * writer thread and the burn_source. You have to provide at least a 32 * blocks buffer. Default value is set to 2MB, if that is ok for you, you * don't need to call this function. * * @since 0.6.2 */ int iso_write_opts_set_fifo_size(IsoWriteOpts *opts, size_t fifo_size); /* * Attach 32 kB of binary data which shall get written to the first 32 kB * of the ISO image, the ECMA-119 System Area. This space is intended for * system dependent boot software, e.g. a Master Boot Record which allows to * boot from USB sticks or hard disks. ECMA-119 makes no own assumptions or * prescriptions about the byte content. * * If system area data are given or options bit0 is set, then bit1 of * el_torito_set_isolinux_options() is automatically disabled. * * @param opts * The option set to be manipulated. * @param data * Either NULL or 32 kB of data. Do not submit less bytes ! * @param options * Can cause manipulations of submitted data before they get written: * bit0= Only with System area type 0 = MBR * Apply a --protective-msdos-label as of grub-mkisofs. * This means to patch bytes 446 to 512 of the system area so * that one partition is defined which begins at the second * 512-byte block of the image and ends where the image ends. * This works with and without system_area_data. * Modern GRUB2 system areas get also treated by bit14. See below. * bit1= Only with System area type 0 = MBR * Apply isohybrid MBR patching to the system area. * This works only with system area data from SYSLINUX plus an * ISOLINUX boot image as first submitted boot image * (see iso_image_set_boot_image()) and only if not bit0 is set. * bit2-7= System area type * 0= with bit0 or bit1: MBR * else: type depends on bits bit10-13: System area sub type * 1= MIPS Big Endian Volume Header * @since 0.6.38 * Submit up to 15 MIPS Big Endian boot files by * iso_image_add_mips_boot_file(). * This will overwrite the first 512 bytes of the submitted * data. * 2= DEC Boot Block for MIPS Little Endian * @since 0.6.38 * The first boot file submitted by * iso_image_add_mips_boot_file() will be activated. * This will overwrite the first 512 bytes of the submitted * data. * 3= SUN Disk Label for SUN SPARC * @since 0.6.40 * Submit up to 7 SPARC boot images by * iso_write_opts_set_partition_img() for partition numbers 2 * to 8. * This will overwrite the first 512 bytes of the submitted * data. * 4= HP-PA PALO boot sector version 4 for HP PA-RISC * @since 1.3.8 * Suitable for older PALO of e.g. Debian 4 and 5. * Submit all five parameters of iso_image_set_hppa_palo(): * cmdline, bootloader, kernel_32, kernel_64, ramdisk * 5= HP-PA PALO boot sector version 5 for HP PA-RISC * @since 1.3.8 * Suitable for newer PALO, where PALOHDRVERSION in * lib/common.h is defined as 5. * Submit all five parameters of iso_image_set_hppa_palo(): * cmdline, bootloader, kernel_32, kernel_64, ramdisk * 6= DEC Alpha SRM boot sector * @since 1.4.0 * Submit bootloader path in ISO by iso_image_set_alpha_boot(). * bit8-9= Only with System area type 0 = MBR * @since 1.0.4 * Cylinder alignment mode eventually pads the image to make it * end at a cylinder boundary. * 0 = auto (align if bit1) * 1 = always align to cylinder boundary * 2 = never align to cylinder boundary * 3 = always align, additionally pad up and align partitions * which were appended by iso_write_opts_set_partition_img() * @since 1.2.6 * bit10-13= System area sub type * @since 1.2.4 * With type 0 = MBR: * Gets overridden by bit0 and bit1. * 0 = no particular sub type, use unaltered * 1 = CHRP: A single MBR partition of type 0x96 covers the * ISO image. Not compatible with any other feature * which needs to have own MBR partition entries. * 2 = generic MBR @since 1.3.8 * bit14= Only with System area type 0 = MBR * GRUB2 boot provisions: * @since 1.3.0 * Patch system area at byte 0x1b0 to 0x1b7 with * (512-block address + 4) of the first boot image file. * Little-endian 8-byte. * Should be combined with options bit0. * Will not be in effect if options bit1 is set. * @param flag * bit0 = invalidate any attached system area data. Same as data == NULL * (This re-activates eventually loaded image System Area data. * To erase those, submit 32 kB of zeros without flag bit0.) * bit1 = keep data unaltered * bit2 = keep options unaltered * @return * ISO_SUCCESS or error * @since 0.6.30 */ int iso_write_opts_set_system_area(IsoWriteOpts *opts, char data[32768], int options, int flag); /** * Set a name for the system area. This setting is ignored unless system area * type 3 "SUN Disk Label" is in effect by iso_write_opts_set_system_area(). * In this case it will replace the default text at the start of the image: * "CD-ROM Disc with Sun sparc boot created by libisofs" * * @param opts * The option set to be manipulated. * @param label * A text of up to 128 characters. * @return * ISO_SUCCESS or error * @since 0.6.40 */ int iso_write_opts_set_disc_label(IsoWriteOpts *opts, char *label); /** * Explicitely set the four timestamps of the emerging Primary Volume * Descriptor and in the volume descriptors of Joliet and ISO 9660:1999, * if those are to be generated. * Default with all parameters is 0. * * ECMA-119 defines them as: * @param opts * The option set to be manipulated. * @param vol_creation_time * When "the information in the volume was created." * A value of 0 means that the timepoint of write start is to be used. * @param vol_modification_time * When "the information in the volume was last modified." * A value of 0 means that the timepoint of write start is to be used. * @param vol_expiration_time * When "the information in the volume may be regarded as obsolete." * A value of 0 means that the information never shall expire. * @param vol_effective_time * When "the information in the volume may be used." * A value of 0 means that not such retention is intended. * @param vol_uuid * If this text is not empty, then it overrides vol_creation_time and * vol_modification_time by copying the first 16 decimal digits from * uuid, eventually padding up with decimal '1', and writing a NUL-byte * as timezone. * Other than with vol_*_time the resulting string in the ISO image * is fully predictable and free of timezone pitfalls. * It should express a reasonable time in form YYYYMMDDhhmmsscc. * The timezone will always be recorded as GMT. * E.g.: "2010040711405800" = 7 Apr 2010 11:40:58 (+0 centiseconds) * @return * ISO_SUCCESS or error * * @since 0.6.30 */ int iso_write_opts_set_pvd_times(IsoWriteOpts *opts, time_t vol_creation_time, time_t vol_modification_time, time_t vol_expiration_time, time_t vol_effective_time, char *vol_uuid); /* * Control production of a second set of volume descriptors (superblock) * and directory trees, together with a partition table in the MBR where the * first partition has non-zero start address and the others are zeroed. * The first partition stretches to the end of the whole ISO image. * The additional volume descriptor set and trees will allow to mount the * ISO image at the start of the first partition, while it is still possible * to mount it via the normal first volume descriptor set and tree at the * start of the image or storage device. * This makes few sense on optical media. But on USB sticks it creates a * conventional partition table which makes it mountable on e.g. Linux via * /dev/sdb and /dev/sdb1 alike. * IMPORTANT: When submitting memory by iso_write_opts_set_overwrite_buf() * then its size must be at least 64 KiB + partition offset. * * @param opts * The option set to be manipulated. * @param block_offset_2k * The offset of the partition start relative to device start. * This is counted in 2 kB blocks. The partition table will show the * according number of 512 byte sectors. * Default is 0 which causes no special partition table preparations. * If it is not 0 then it must not be smaller than 16. * @param secs_512_per_head * Number of 512 byte sectors per head. 1 to 63. 0=automatic. * @param heads_per_cyl * Number of heads per cylinder. 1 to 255. 0=automatic. * @return * ISO_SUCCESS or error * * @since 0.6.36 */ int iso_write_opts_set_part_offset(IsoWriteOpts *opts, uint32_t block_offset_2k, int secs_512_per_head, int heads_per_cyl); /** The minimum version of libjte to be used with this version of libisofs at compile time. The use of libjte is optional and depends on configure tests. It can be prevented by ./configure option --disable-libjte . @since 0.6.38 */ #define iso_libjte_req_major 1 #define iso_libjte_req_minor 0 #define iso_libjte_req_micro 0 /** * Associate a libjte environment object to the upcomming write run. * libjte implements Jigdo Template Extraction as of Steve McIntyre and * Richard Atterer. * The call will fail if no libjte support was enabled at compile time. * @param opts * The option set to be manipulated. * @param libjte_handle * Pointer to a struct libjte_env e.g. created by libjte_new(). * It must stay existent from the start of image generation by * iso_image_create_burn_source() until the write thread has ended. * This can be inquired by iso_image_generator_is_running(). * In order to keep the libisofs API identical with and without * libjte support the parameter type is (void *). * @return * ISO_SUCCESS or error * * @since 0.6.38 */ int iso_write_opts_attach_jte(IsoWriteOpts *opts, void *libjte_handle); /** * Remove eventual association to a libjte environment handle. * The call will fail if no libjte support was enabled at compile time. * @param opts * The option set to be manipulated. * @param libjte_handle * If not submitted as NULL, this will return the previously set * libjte handle. * @return * ISO_SUCCESS or error * * @since 0.6.38 */ int iso_write_opts_detach_jte(IsoWriteOpts *opts, void **libjte_handle); /** * Cause a number of blocks with zero bytes to be written after the payload * data, but before the eventual checksum data. Unlike libburn tail padding, * these blocks are counted as part of the image and covered by eventual * image checksums. * A reason for such padding can be the wish to prevent the Linux read-ahead * bug by sacrificial data which still belong to image and Jigdo template. * Normally such padding would be the job of the burn program which should know * that it is needed with CD write type TAO if Linux read(2) shall be able * to read all payload blocks. * 150 blocks = 300 kB is the traditional sacrifice to the Linux kernel. * @param opts * The option set to be manipulated. * @param num_blocks * Number of extra 2 kB blocks to be written. * @return * ISO_SUCCESS or error * * @since 0.6.38 */ int iso_write_opts_set_tail_blocks(IsoWriteOpts *opts, uint32_t num_blocks); /** * The libisofs interval reader is used internally and offered by libisofs API: * @since 1.4.0 * The functions iso_write_opts_set_prep_img(), iso_write_opts_set_efi_bootp(), * and iso_write_opts_set_partition_img() accept with their flag bit0 an * interval reader description string instead of a disk path. * The API calls are iso_interval_reader_new(), iso_interval_reader_read(), * and iso_interval_reader_destroy(). * The data may be cut out and optionally partly zeroized. * * An interval reader description string has the form: * $flags:$interval:$zeroizers:$source * The component $flags modifies the further interpretation: * "local_fs" ....... demands to read from a file depicted by the path in * $source. * "imported_iso" ... demands to read from the IsoDataSource object that was * used with iso_image_import() when * iso_read_opts_keep_import_src() was enabled. * The text in $source is ignored. * The application has to ensure that reading from the * import source does not disturb production of the new * ISO session. Especially this would be the case if the * import source is the same libburn drive with a * sequential optical medium to which the new session shall * get burned. * The component $interval consists of two byte address numbers separated * by a "-" character. E.g. "0-429" means to read bytes 0 to 429. * The component $zeroizers consists of zero or more comma separated strings. * They define which part of the read data to zeroize. Byte number 0 means * the byte read from the $interval start address. * Each string may be either * "zero_mbrpt" ..... demands to zeroize bytes 446 to 509 of the read data if * bytes 510 and 511 bear the MBR signature 0x55 0xaa. * "zero_gpt" ....... demands to check for a GPT header in bytes 512 to 1023, * to zeroize it and its partition table blocks. * "zero_apm" ....... demands to check for an APM block 0 and to zeroize * its partition table blocks. But not the block 0 itself, * because it could be actually MBR x86 machine code. * $zero_start"-"$zero_end ... demands to zeroize the read-in bytes beginning * with number $zero_start and ending after $zero_end. * The component $source is the file path with "local_fs", and ignored with * "imported_iso". * Byte numbers may be scaled by a suffix out of {k,m,g,t,s,d} meaning * multiplication by {1024, 1024k, 1024m, 1024g, 2048, 512}. A scaled value * as end number depicts the last byte of the scaled range. * E.g. "0d-0d" is "0-511". * Examples: * "local_fs:0-32767:zero_mbrpt,zero_gpt,440-443:/tmp/template.iso" * "imported_iso:45056d-47103d::" */ struct iso_interval_reader; /** * Create an interval reader object. * * @param img * The IsoImage object which can provide the "imported_iso" data source. * @param path * The interval reader description string. See above. * @param ivr * Returns in case of success a pointer to the created object. * Dispose it by iso_interval_reader_destroy() when no longer needed. * @param byte_count * Returns in case of success the number of bytes in the interval. * @param flag * bit0= tolerate (src == NULL) with "imported_iso". * (Will immediately cause eof of interval input.) * @return * ISO_SUCCESS or error (which is < 0) * * @since 1.4.0 */ int iso_interval_reader_new(IsoImage *img, char *path, struct iso_interval_reader **ivr, off_t *byte_count, int flag); /** * Dispose an interval reader object. * * @param ivr * The reader object to be disposed. *ivr will be set to NULL. * @return * ISO_SUCCESS or error (which is < 0) * * @since 1.4.0 */ int iso_interval_reader_destroy(struct iso_interval_reader **ivr, int flag); /** * Read the next block of 2048 bytes from an interval reader object. * If end-of-input happens, the interval will get filled up with 0 bytes. * * @param ivr * The object to read from. * @param buf * Pointer to memory for filling in at least 2048 bytes. * @param buf_fill * Will in case of success return the number of valid bytes. * If this is smaller than 2048, then end-of-interval has occured. * @param flag * Unused yet. Submit 0. * @return * ISO_SUCCESS if data were read, 0 if not, < 0 if error * * @since 1.4.0 */ int iso_interval_reader_read(struct iso_interval_reader *ivr, uint8_t *buf, int *buf_fill, int flag); /** * Copy a data file from the local filesystem into the emerging ISO image. * Mark it by an MBR partition entry as PreP partition and also cause * protective MBR partition entries before and after this partition. * Vladimir Serbinenko stated aboy PreP = PowerPC Reference Platform : * "PreP [...] refers mainly to IBM hardware. PreP boot is a partition * containing only raw ELF and having type 0x41." * * This feature is only combinable with system area type 0 * and currently not combinable with ISOLINUX isohybrid production. * It overrides --protective-msdos-label. See iso_write_opts_set_system_area(). * Only partition 4 stays available for iso_write_opts_set_partition_img(). * It is compatible with HFS+/FAT production by storing the PreP partition * before the start of the HFS+/FAT partition. * * @param opts * The option set to be manipulated. * @param image_path * File address in the local file system or instructions for interval * reader. See flag bit0. * NULL revokes production of the PreP partition. * @param flag * bit0= The path contains instructions for the interval reader. * See above. * @since 1.4.0 * All other bits are reserved for future usage. Set them to 0. * @return * ISO_SUCCESS or error * * @since 1.2.4 */ int iso_write_opts_set_prep_img(IsoWriteOpts *opts, char *image_path, int flag); /** * Copy a data file from the local filesystem into the emerging ISO image. * Mark it by an GPT partition entry as EFI System partition, and also cause * protective GPT partition entries before and after the partition. * GPT = Globally Unique Identifier Partition Table * * This feature may collide with data submitted by * iso_write_opts_set_system_area() * and with settings made by * el_torito_set_isolinux_options() * It is compatible with HFS+/FAT production by storing the EFI partition * before the start of the HFS+/FAT partition. * The GPT overwrites byte 0x0200 to 0x03ff of the system area and all * further bytes above 0x0800 which are not used by an Apple Partition Map. * * @param opts * The option set to be manipulated. * @param image_path * File address in the local file system or instructions for interval * reader. See flag bit0. * NULL revokes production of the EFI boot partition. * @param flag * bit0= The path contains instructions for the interval reader * See above. * @since 1.4.0 * All other bits are reserved for future usage. Set them to 0. * @return * ISO_SUCCESS or error * * @since 1.2.4 */ int iso_write_opts_set_efi_bootp(IsoWriteOpts *opts, char *image_path, int flag); /** * Cause an arbitrary data file to be appended to the ISO image and to be * described by a partition table entry in an MBR or SUN Disk Label at the * start of the ISO image. * The partition entry will bear the size of the image file rounded up to * the next multiple of 2048 bytes. * MBR or SUN Disk Label are selected by iso_write_opts_set_system_area() * system area type: 0 selects MBR partition table. 3 selects a SUN partition * table with 320 kB start alignment. * * @param opts * The option set to be manipulated. * @param partition_number * Depicts the partition table entry which shall describe the * appended image. * Range with MBR: 1 to 4. 1 will cause the whole ISO image to be * unclaimable space before partition 1. * Range with SUN Disk Label: 2 to 8. * @param image_path * File address in the local file system or instructions for interval * reader. See flag bit0. * With SUN Disk Label: an empty name causes the partition to become * a copy of the next lower partition. * @param image_type * The MBR partition type. E.g. FAT12 = 0x01 , FAT16 = 0x06, * Linux Native Partition = 0x83. See fdisk command L. * This parameter is ignored with SUN Disk Label. * @param flag * bit0= The path contains instructions for the interval reader * See above. * @since 1.4.0 * All other bits are reserved for future usage. Set them to 0. * @return * ISO_SUCCESS or error * * @since 0.6.38 */ int iso_write_opts_set_partition_img(IsoWriteOpts *opts, int partition_number, uint8_t partition_type, char *image_path, int flag); /** * Control whether partitions created by iso_write_opts_set_partition_img() * are to be represented in MBR or as GPT partitions. * * @param opts * The option set to be manipulated. * @param gpt * 0= represent as MBR partition; as GPT only if other GPT partitions * are present * 1= represent as GPT partition and cause protective MBR with a single * partition which covers the whole output data. * This may fail if other settings demand MBR partitions. * @return * ISO_SUCCESS or error * * @since 1.4.0 */ int iso_write_opts_set_appended_as_gpt(IsoWriteOpts *opts, int gpt); /** * Inquire the start address of the file data blocks after having used * IsoWriteOpts with iso_image_create_burn_source(). * @param opts * The option set that was used when starting image creation * @param data_start * Returns the logical block address if it is already valid * @param flag * Reserved for future usage, set to 0. * @return * 1 indicates valid data_start, <0 indicates invalid data_start * * @since 0.6.16 */ int iso_write_opts_get_data_start(IsoWriteOpts *opts, uint32_t *data_start, int flag); /** * Update the sizes of all files added to image. * * This may be called just before iso_image_create_burn_source() to force * libisofs to check the file sizes again (they're already checked when added * to IsoImage). It is useful if you have changed some files after adding then * to the image. * * @return * 1 on success, < 0 on error * @since 0.6.8 */ int iso_image_update_sizes(IsoImage *image); /** * Create a burn_source and a thread which immediately begins to generate * the image. That burn_source can be used with libburn as a data source * for a track. A copy of its public declaration in libburn.h can be found * further below in this text. * * If image generation shall be aborted by the application program, then * the .cancel() method of the burn_source must be called to end the * generation thread: burn_src->cancel(burn_src); * * @param image * The image to write. * @param opts * The options for image generation. All needed data will be copied, so * you can free the given struct once this function returns. * @param burn_src * Location where the pointer to the burn_source will be stored * @return * 1 on success, < 0 on error * * @since 0.6.2 */ int iso_image_create_burn_source(IsoImage *image, IsoWriteOpts *opts, struct burn_source **burn_src); /** * Inquire whether the image generator thread is still at work. As soon as the * reply is 0, the caller of iso_image_create_burn_source() may assume that * the image generation has ended. * Nevertheless there may still be readily formatted output data pending in * the burn_source or its consumers. So the final delivery of the image has * also to be checked at the data consumer side,e.g. by burn_drive_get_status() * in case of libburn as consumer. * @param image * The image to inquire. * @return * 1 generating of image stream is still in progress * 0 generating of image stream has ended meanwhile * * @since 0.6.38 */ int iso_image_generator_is_running(IsoImage *image); /** * Creates an IsoReadOpts for reading an existent image. You should set the * options desired with the correspondent setters. Note that you may want to * set the start block value. * * Options by default are determined by the selected profile. * * @param opts * Pointer to the location where the newly created IsoReadOpts will be * stored. You should free it with iso_read_opts_free() when no more * needed. * @param profile * Default profile for image reading. For now the following values are * defined: * ---> 0 [STANDARD] * Suitable for most situations. Most extension are read. When both * Joliet and RR extension are present, RR is used. * AAIP for ACL and xattr is not enabled by default. * @return * 1 success, < 0 error * * @since 0.6.2 */ int iso_read_opts_new(IsoReadOpts **opts, int profile); /** * Free an IsoReadOpts previously allocated with iso_read_opts_new(). * * @since 0.6.2 */ void iso_read_opts_free(IsoReadOpts *opts); /** * Set the block where the image begins. It is usually 0, but may be different * on a multisession disc. * * @since 0.6.2 */ int iso_read_opts_set_start_block(IsoReadOpts *opts, uint32_t block); /** * Do not read Rock Ridge extensions. * In most cases you don't want to use this. It could be useful if RR info * is damaged, or if you want to use the Joliet tree. * * @since 0.6.2 */ int iso_read_opts_set_no_rockridge(IsoReadOpts *opts, int norr); /** * Do not read Joliet extensions. * * @since 0.6.2 */ int iso_read_opts_set_no_joliet(IsoReadOpts *opts, int nojoliet); /** * Do not read ISO 9660:1999 enhanced tree * * @since 0.6.2 */ int iso_read_opts_set_no_iso1999(IsoReadOpts *opts, int noiso1999); /** * Control reading of AAIP informations about ACL and xattr when loading * existing images. * For importing ACL and xattr when inserting nodes from external filesystems * (e.g. the local POSIX filesystem) see iso_image_set_ignore_aclea(). * For eventual writing of this information see iso_write_opts_set_aaip(). * * @param opts * The option set to be manipulated * @param noaaip * 1 = Do not read AAIP information * 0 = Read AAIP information if available * All other values are reserved. * @since 0.6.14 */ int iso_read_opts_set_no_aaip(IsoReadOpts *opts, int noaaip); /** * Control reading of an array of MD5 checksums which is eventually stored * at the end of a session. See also iso_write_opts_set_record_md5(). * Important: Loading of the MD5 array will only work if AAIP is enabled * because its position and layout is recorded in xattr "isofs.ca". * * @param opts * The option set to be manipulated * @param no_md5 * 0 = Read MD5 array if available, refuse on non-matching MD5 tags * 1 = Do not read MD5 checksum array * 2 = Read MD5 array, but do not check MD5 tags * @since 1.0.4 * All other values are reserved. * * @since 0.6.22 */ int iso_read_opts_set_no_md5(IsoReadOpts *opts, int no_md5); /** * Control discarding of eventual inode numbers from existing images. * Such numbers may come from RRIP 1.12 entries PX. If not discarded they * get written unchanged when the file object gets written into an ISO image. * If this inode number is missing with a file in the imported image, * or if it has been discarded during image reading, then a unique inode number * will be generated at some time before the file gets written into an ISO * image. * Two image nodes which have the same inode number represent two hardlinks * of the same file object. So discarding the numbers splits hardlinks. * * @param opts * The option set to be manipulated * @param new_inos * 1 = Discard imported inode numbers and finally hand out a unique new * one to each single file before it gets written into an ISO image. * 0 = Keep eventual inode numbers from PX entries. * All other values are reserved. * @since 0.6.20 */ int iso_read_opts_set_new_inos(IsoReadOpts *opts, int new_inos); /** * Whether to prefer Joliet over RR. libisofs usually prefers RR over * Joliet, as it give us much more info about files. So, if both extensions * are present, RR is used. You can set this if you prefer Joliet, but * note that this is not very recommended. This doesn't mean than RR * extensions are not read: if no Joliet is present, libisofs will read * RR tree. * * @since 0.6.2 */ int iso_read_opts_set_preferjoliet(IsoReadOpts *opts, int preferjoliet); /** * How to convert file names if neither Rock Ridge nor Joliet names * are present and acceptable. * * @param opts * The option set to be manipulated * @param ecma119_map * The conversion mode to apply: * 0 = unmapped: Take name as recorded in ECMA-119 directory record * (not suitable for writing them to a new ISO filesystem) * 1 = stripped: Like unmapped, but strip off trailing ";1" or ".;1" * 2 = uppercase: Like stripped, but map {a-z} to {A-Z} * 3 = lowercase: Like stripped, but map {A-Z} to {a-z} * @return * ISO_SUCCESS if ecma119_map was accepted * 0 if the value was out of range * < 0 if other error * * @since 1.4.2 */ int iso_read_opts_set_ecma119_map(IsoReadOpts *opts, int ecma119_map); /** * Set default uid for files when RR extensions are not present. * * @since 0.6.2 */ int iso_read_opts_set_default_uid(IsoReadOpts *opts, uid_t uid); /** * Set default gid for files when RR extensions are not present. * * @since 0.6.2 */ int iso_read_opts_set_default_gid(IsoReadOpts *opts, gid_t gid); /** * Set default permissions for files when RR extensions are not present. * * @param opts * The option set to be manipulated * @param file_perm * Permissions for files. * @param dir_perm * Permissions for directories. * * @since 0.6.2 */ int iso_read_opts_set_default_permissions(IsoReadOpts *opts, mode_t file_perm, mode_t dir_perm); /** * Set the input charset of the file names on the image. NULL to use locale * charset. You have to specify a charset if the image filenames are encoded * in a charset different that the local one. This could happen, for example, * if the image was created on a system with different charset. * * @param opts * The option set to be manipulated * @param charset * The charset to use as input charset. You can obtain the list of * charsets supported on your system executing "iconv -l" in a shell. * * @since 0.6.2 */ int iso_read_opts_set_input_charset(IsoReadOpts *opts, const char *charset); /** * Enable or disable methods to automatically choose an input charset. * This eventually overrides the name set via iso_read_opts_set_input_charset() * * @param opts * The option set to be manipulated * @param mode * Bitfield for control purposes: * bit0= Allow to use the input character set name which is eventually * stored in attribute "isofs.cs" of the root directory. * Applications may attach this xattr by iso_node_set_attrs() to * the root node, call iso_write_opts_set_output_charset() with the * same name and enable iso_write_opts_set_aaip() when writing * an image. * Submit any other bits with value 0. * * @since 0.6.18 * */ int iso_read_opts_auto_input_charset(IsoReadOpts *opts, int mode); /** * Enable or disable loading of the first 32768 bytes of the session. * * @param opts * The option set to be manipulated * @param mode * Bitfield for control purposes: * bit0= Load System Area data and attach them to the image so that they * get written by the next session, if not overridden by * iso_write_opts_set_system_area(). * Submit any other bits with value 0. * * @since 0.6.30 * */ int iso_read_opts_load_system_area(IsoReadOpts *opts, int mode); /** * Control whether to keep a reference to the IsoDataSource object which * allows access to the blocks of the imported ISO 9660 filesystem. * This is needed if the interval reader shall read from "imported_iso". * * @param opts * The option set to be manipulated * @param mode * Bitfield for control purposes: * bit0= Keep a reference to the IsoDataSource until the IsoImage object * gets disposed by its final iso_image_unref(). * Submit any other bits with value 0. * * @since 1.4.0 * */ int iso_read_opts_keep_import_src(IsoReadOpts *opts, int mode); /** * Import a previous session or image, for growing or modify. * * @param image * The image context to which old image will be imported. Note that all * files added to image, and image attributes, will be replaced with the * contents of the old image. * TODO #00025 support for merging old image files * @param src * Data Source from which old image will be read. A extra reference is * added, so you still need to iso_data_source_unref() yours. * @param opts * Options for image import. All needed data will be copied, so you * can free the given struct once this function returns. * @param features * If not NULL, a new IsoReadImageFeatures will be allocated and filled * with the features of the old image. It should be freed with * iso_read_image_features_destroy() when no more needed. You can pass * NULL if you're not interested on them. * @return * 1 on success, < 0 on error * * @since 0.6.2 */ int iso_image_import(IsoImage *image, IsoDataSource *src, IsoReadOpts *opts, IsoReadImageFeatures **features); /** * Destroy an IsoReadImageFeatures object obtained with iso_image_import. * * @since 0.6.2 */ void iso_read_image_features_destroy(IsoReadImageFeatures *f); /** * Get the size (in 2048 byte block) of the image, as reported in the PVM. * * @since 0.6.2 */ uint32_t iso_read_image_features_get_size(IsoReadImageFeatures *f); /** * Whether RockRidge extensions are present in the image imported. * * @since 0.6.2 */ int iso_read_image_features_has_rockridge(IsoReadImageFeatures *f); /** * Whether Joliet extensions are present in the image imported. * * @since 0.6.2 */ int iso_read_image_features_has_joliet(IsoReadImageFeatures *f); /** * Whether the image is recorded according to ISO 9660:1999, i.e. it has * a version 2 Enhanced Volume Descriptor. * * @since 0.6.2 */ int iso_read_image_features_has_iso1999(IsoReadImageFeatures *f); /** * Whether El-Torito boot record is present present in the image imported. * * @since 0.6.2 */ int iso_read_image_features_has_eltorito(IsoReadImageFeatures *f); /** * Increments the reference counting of the given image. * * @since 0.6.2 */ void iso_image_ref(IsoImage *image); /** * Decrements the reference couting of the given image. * If it reaches 0, the image is free, together with its tree nodes (whether * their refcount reach 0 too, of course). * * @since 0.6.2 */ void iso_image_unref(IsoImage *image); /** * Attach user defined data to the image. Use this if your application needs * to store addition info together with the IsoImage. If the image already * has data attached, the old data will be freed. * * @param image * The image to which data shall be attached. * @param data * Pointer to application defined data that will be attached to the * image. You can pass NULL to remove any already attached data. * @param give_up * Function that will be called when the image does not need the data * any more. It receives the data pointer as an argumente, and eventually * causes data to be freed. It can be NULL if you don't need it. * @return * 1 on succes, < 0 on error * * @since 0.6.2 */ int iso_image_attach_data(IsoImage *image, void *data, void (*give_up)(void*)); /** * The the data previously attached with iso_image_attach_data() * * @since 0.6.2 */ void *iso_image_get_attached_data(IsoImage *image); /** * Set the name truncation mode and the maximum name length for nodes from * image importing, creation of new IsoNode objects, and name changing image * manipulations. * * Truncated names are supposed to be nearly unique because they end by the MD5 * of the first 4095 characters of the untruncated name. One should treat them * as if they were the untruncated original names. * * For proper processing of truncated names it is necessary to use * iso_image_set_node_name() instead of iso_node_set_name() * iso_image_add_new_dir() iso_tree_add_new_dir() * iso_image_add_new_file() iso_tree_add_new_file() * iso_image_add_new_special() iso_tree_add_new_special() * iso_image_add_new_symlink() iso_tree_add_new_symlink() * iso_image_tree_clone() iso_tree_clone() * iso_image_dir_get_node() iso_dir_get_node() * iso_image_path_to_node() iso_tree_path_to_node() * * Beware of ambiguities if both, the full name and the truncated name, * exist in the same directory. Best is to only set truncation parameters * once with an ISO filesystem and to never change them later. * * If writing of AAIP is enabled, then the mode and length are recorded in * xattr "isofs.nt" of the root node. * If reading of AAIP is enabled and "isofs.nt" is found, then it gets into * effect if both, the truncate mode value from "isofs.nt" and the current * truncate mode of the IsoImage are 1, and the length is between 64 and 255. * * @param image * The image which shall be manipulated. * @param mode * 0= Do not truncate but throw error ISO_RR_NAME_TOO_LONG if a file name * is longer than parameter length. * 1= Truncate to length and overwrite the last 33 bytes of that length * by a colon ':' and the hex representation of the MD5 of the first * 4095 bytes of the whole oversized name. * Potential incomplete UTF-8 characters will get their leading bytes * replaced by '_'. * Mode 1 is the default. * @param length * Maximum byte count of a file name. Permissible values are 64 to 255. * Default is 255. * @return * ISO_SUCCESS or ISO_WRONG_ARG_VALUE * * @since 1.4.2 */ int iso_image_set_truncate_mode(IsoImage *img, int mode, int length); /** * Inquire the current setting of iso_image_set_truncate_mode(). * * @param image * The image which shall be inquired. * @param mode * Returns the mode value. * @param length * Returns the length value. * @return * ISO_SUCCESS or <0 = error * * @since 1.4.2 */ int iso_image_get_truncate_mode(IsoImage *img, int *mode, int *length); /** * Immediately apply the given truncate mode and length to the given string. * * @param mode * See iso_image_set_truncate_mode() * @param length * See iso_image_set_truncate_mode() * @param name * The string to be inspected and truncated if mode says so. * @param flag * Bitfield for control purposes. Unused yet. Submit 0. * @return * ISO_SUCCESS, ISO_WRONG_ARG_VALUE, ISO_RR_NAME_TOO_LONG * * @since 1.4.2 */ int iso_truncate_leaf_name(int mode, int length, char *name, int flag); /** * Get the root directory of the image. * No extra ref is added to it, so you must not unref it. Use iso_node_ref() * if you want to get your own reference. * * @since 0.6.2 */ IsoDir *iso_image_get_root(const IsoImage *image); /** * Fill in the volset identifier for a image. * * @since 0.6.2 */ void iso_image_set_volset_id(IsoImage *image, const char *volset_id); /** * Get the volset identifier. * The returned string is owned by the image and must not be freed nor * changed. * * @since 0.6.2 */ const char *iso_image_get_volset_id(const IsoImage *image); /** * Fill in the volume identifier for a image. * * @since 0.6.2 */ void iso_image_set_volume_id(IsoImage *image, const char *volume_id); /** * Get the volume identifier. * The returned string is owned by the image and must not be freed nor * changed. * * @since 0.6.2 */ const char *iso_image_get_volume_id(const IsoImage *image); /** * Fill in the publisher for a image. * * @since 0.6.2 */ void iso_image_set_publisher_id(IsoImage *image, const char *publisher_id); /** * Get the publisher of a image. * The returned string is owned by the image and must not be freed nor * changed. * * @since 0.6.2 */ const char *iso_image_get_publisher_id(const IsoImage *image); /** * Fill in the data preparer for a image. * * @since 0.6.2 */ void iso_image_set_data_preparer_id(IsoImage *image, const char *data_preparer_id); /** * Get the data preparer of a image. * The returned string is owned by the image and must not be freed nor * changed. * * @since 0.6.2 */ const char *iso_image_get_data_preparer_id(const IsoImage *image); /** * Fill in the system id for a image. Up to 32 characters. * * @since 0.6.2 */ void iso_image_set_system_id(IsoImage *image, const char *system_id); /** * Get the system id of a image. * The returned string is owned by the image and must not be freed nor * changed. * * @since 0.6.2 */ const char *iso_image_get_system_id(const IsoImage *image); /** * Fill in the application id for a image. Up to 128 chars. * * @since 0.6.2 */ void iso_image_set_application_id(IsoImage *image, const char *application_id); /** * Get the application id of a image. * The returned string is owned by the image and must not be freed nor * changed. * * @since 0.6.2 */ const char *iso_image_get_application_id(const IsoImage *image); /** * Fill copyright information for the image. Usually this refers * to a file on disc. Up to 37 characters. * * @since 0.6.2 */ void iso_image_set_copyright_file_id(IsoImage *image, const char *copyright_file_id); /** * Get the copyright information of a image. * The returned string is owned by the image and must not be freed nor * changed. * * @since 0.6.2 */ const char *iso_image_get_copyright_file_id(const IsoImage *image); /** * Fill abstract information for the image. Usually this refers * to a file on disc. Up to 37 characters. * * @since 0.6.2 */ void iso_image_set_abstract_file_id(IsoImage *image, const char *abstract_file_id); /** * Get the abstract information of a image. * The returned string is owned by the image and must not be freed nor * changed. * * @since 0.6.2 */ const char *iso_image_get_abstract_file_id(const IsoImage *image); /** * Fill biblio information for the image. Usually this refers * to a file on disc. Up to 37 characters. * * @since 0.6.2 */ void iso_image_set_biblio_file_id(IsoImage *image, const char *biblio_file_id); /** * Get the biblio information of a image. * The returned string is owned by the image and must not be freed or changed. * * @since 0.6.2 */ const char *iso_image_get_biblio_file_id(const IsoImage *image); /** * Fill Application Use field of the Primary Volume Descriptor. * ECMA-119 8.4.32 Application Use (BP 884 to 1395) * "This field shall be reserved for application use. Its content * is not specified by this Standard." * * @param image * The image to manipulate. * @param app_use_data * Up to 512 bytes of data. * @param count * The number of bytes in app_use_data. If the number is smaller than 512, * then the remaining bytes will be set to 0. * @since 1.3.2 */ void iso_image_set_app_use(IsoImage *image, const char *app_use_data, int count); /** * Get the current setting for the Application Use field of the Primary Volume * Descriptor. * The returned char array of 512 bytes is owned by the image and must not * be freed or changed. * * @param image * The image to inquire * @since 1.3.2 */ const char *iso_image_get_app_use(IsoImage *image); /** * Get the four timestamps from the Primary Volume Descriptor of the imported * ISO image. The timestamps are strings which are either empty or consist * of 16 digits of the form YYYYMMDDhhmmsscc, plus a signed byte in the range * of -48 to +52, which gives the timezone offset in steps of 15 minutes. * None of the returned string pointers shall be used for altering or freeing * data. They are just for reading. * * @param image * The image to be inquired. * @param vol_creation_time * Returns a pointer to the Volume Creation time: * When "the information in the volume was created." * @param vol_modification_time * Returns a pointer to Volume Modification time: * When "the information in the volume was last modified." * @param vol_expiration_time * Returns a pointer to Volume Expiration time: * When "the information in the volume may be regarded as obsolete." * @param vol_effective_time * Returns a pointer to Volume Expiration time: * When "the information in the volume may be used." * @return * ISO_SUCCESS or error * * @since 1.2.8 */ int iso_image_get_pvd_times(IsoImage *image, char **creation_time, char **modification_time, char **expiration_time, char **effective_time); /** * Create a new set of El-Torito bootable images by adding a boot catalog * and the default boot image. * Further boot images may then be added by iso_image_add_boot_image(). * * @param image * The image to make bootable. If it was already bootable this function * returns an error and the image remains unmodified. * @param image_path * The absolute path of a IsoFile to be used as default boot image. * @param type * The boot media type. This can be one of 3 types: * - Floppy emulation: Boot image file must be exactly * 1200 kB, 1440 kB or 2880 kB. * - Hard disc emulation: The image must begin with a master * boot record with a single image. * - No emulation. You should specify load segment and load size * of image. * @param catalog_path * The absolute path in the image tree where the catalog will be stored. * The directory component of this path must be a directory existent on * the image tree, and the filename component must be unique among all * children of that directory on image. Otherwise a correspodent error * code will be returned. This function will add an IsoBoot node that acts * as a placeholder for the real catalog, that will be generated at image * creation time. * @param boot * Location where a pointer to the added boot image will be stored. That * object is owned by the IsoImage and must not be freed by the user, * nor dereferenced once the last reference to the IsoImage was disposed * via iso_image_unref(). A NULL value is allowed if you don't need a * reference to the boot image. * @return * 1 on success, < 0 on error * * @since 0.6.2 */ int iso_image_set_boot_image(IsoImage *image, const char *image_path, enum eltorito_boot_media_type type, const char *catalog_path, ElToritoBootImage **boot); /** * Add a further boot image to the set of El-Torito bootable images. * This set has already to be created by iso_image_set_boot_image(). * Up to 31 further boot images may be added. * * @param image * The image to which the boot image shall be added. * returns an error and the image remains unmodified. * @param image_path * The absolute path of a IsoFile to be used as default boot image. * @param type * The boot media type. See iso_image_set_boot_image * @param flag * Bitfield for control purposes. Unused yet. Submit 0. * @param boot * Location where a pointer to the added boot image will be stored. * See iso_image_set_boot_image * @return * 1 on success, < 0 on error * ISO_BOOT_NO_CATALOG means iso_image_set_boot_image() * was not called first. * * @since 0.6.32 */ int iso_image_add_boot_image(IsoImage *image, const char *image_path, enum eltorito_boot_media_type type, int flag, ElToritoBootImage **boot); /** * Get the El-Torito boot catalog and the default boot image of an ISO image. * * This can be useful, for example, to check if a volume read from a previous * session or an existing image is bootable. It can also be useful to get * the image and catalog tree nodes. An application would want those, for * example, to prevent the user removing it. * * Both nodes are owned by libisofs and must not be freed. You can get your * own ref with iso_node_ref(). You can also check if the node is already * on the tree by getting its parent (note that when reading El-Torito info * from a previous image, the nodes might not be on the tree even if you haven't * removed them). Remember that you'll need to get a new ref * (with iso_node_ref()) before inserting them again to the tree, and probably * you will also need to set the name or permissions. * * @param image * The image from which to get the boot image. * @param boot * If not NULL, it will be filled with a pointer to the boot image, if * any. That object is owned by the IsoImage and must not be freed by * the user, nor dereferenced once the last reference to the IsoImage was * disposed via iso_image_unref(). * @param imgnode * When not NULL, it will be filled with the image tree node. No extra ref * is added, you can use iso_node_ref() to get one if you need it. * @param catnode * When not NULL, it will be filled with the catnode tree node. No extra * ref is added, you can use iso_node_ref() to get one if you need it. * @return * 1 on success, 0 is the image is not bootable (i.e., it has no El-Torito * image), < 0 error. * * @since 0.6.2 */ int iso_image_get_boot_image(IsoImage *image, ElToritoBootImage **boot, IsoFile **imgnode, IsoBoot **catnode); /** * Get detailed information about the boot catalog that was loaded from * an ISO image. * The boot catalog links the El Torito boot record at LBA 17 with the * boot images which are IsoFile objects in the image. The boot catalog * itself is not a regular file and thus will not deliver an IsoStream. * Its content is usually quite short and can be obtained by this call. * * @param image * The image to inquire. * @param catnode * Will return the boot catalog tree node. No extra ref is taken. * @param lba * Will return the block address of the boot catalog in the image. * @param content * Will return either NULL or an allocated memory buffer with the * content bytes of the boot catalog. * Dispose it by free() when no longer needed. * @param size * Will return the number of bytes in content. * @return * 1 if reply is valid, 0 if not boot catalog was loaded, < 0 on error. * * @since 1.1.2 */ int iso_image_get_bootcat(IsoImage *image, IsoBoot **catnode, uint32_t *lba, char **content, off_t *size); /** * Get all El-Torito boot images of an ISO image. * * The first of these boot images is the same as returned by * iso_image_get_boot_image(). The others are alternative boot images. * * @param image * The image from which to get the boot images. * @param num_boots * The number of available array elements in boots and bootnodes. * @param boots * Returns NULL or an allocated array of pointers to boot images. * Apply system call free(boots) to dispose it. * @param bootnodes * Returns NULL or an allocated array of pointers to the IsoFile nodes * which bear the content of the boot images in boots. * @param flag * Bitfield for control purposes. Unused yet. Submit 0. * @return * 1 on success, 0 no El-Torito catalog and boot image attached, * < 0 error. * * @since 0.6.32 */ int iso_image_get_all_boot_imgs(IsoImage *image, int *num_boots, ElToritoBootImage ***boots, IsoFile ***bootnodes, int flag); /** * Removes all El-Torito boot images from the ISO image. * * The IsoBoot node that acts as placeholder for the catalog is also removed * for the image tree, if there. * If the image is not bootable (don't have el-torito boot image) this function * just returns. * * @since 0.6.2 */ void iso_image_remove_boot_image(IsoImage *image); /** * Sets the sort weight of the boot catalog that is attached to an IsoImage. * * For the meaning of sort weights see iso_node_set_sort_weight(). * That function cannot be applied to the emerging boot catalog because * it is not represented by an IsoFile. * * @param image * The image to manipulate. * @param sort_weight * The larger this value, the lower will be the block address of the * boot catalog record. * @return * 0= no boot catalog attached , 1= ok , <0 = error * * @since 0.6.32 */ int iso_image_set_boot_catalog_weight(IsoImage *image, int sort_weight); /** * Hides the boot catalog file from directory trees. * * For the meaning of hiding files see iso_node_set_hidden(). * * * @param image * The image to manipulate. * @param hide_attrs * Or-combination of values from enum IsoHideNodeFlag to set the trees * in which the record. * @return * 0= no boot catalog attached , 1= ok , <0 = error * * @since 0.6.34 */ int iso_image_set_boot_catalog_hidden(IsoImage *image, int hide_attrs); /** * Get the boot media type as of parameter "type" of iso_image_set_boot_image() * or iso_image_add_boot_image(). * * @param bootimg * The image to inquire * @param media_type * Returns the media type * @return * 1 = ok , < 0 = error * * @since 0.6.32 */ int el_torito_get_boot_media_type(ElToritoBootImage *bootimg, enum eltorito_boot_media_type *media_type); /** * Sets the platform ID of the boot image. * * The Platform ID gets written into the boot catalog at byte 1 of the * Validation Entry, or at byte 1 of a Section Header Entry. * If Platform ID and ID String of two consequtive bootimages are the same * * @param bootimg * The image to manipulate. * @param id * A Platform ID as of * El Torito 1.0 : 0x00= 80x86, 0x01= PowerPC, 0x02= Mac * Others : 0xef= EFI * @return * 1 ok , <=0 error * * @since 0.6.32 */ int el_torito_set_boot_platform_id(ElToritoBootImage *bootimg, uint8_t id); /** * Get the platform ID value. See el_torito_set_boot_platform_id(). * * @param bootimg * The image to inquire * @return * 0 - 255 : The platform ID * < 0 : error * * @since 0.6.32 */ int el_torito_get_boot_platform_id(ElToritoBootImage *bootimg); /** * Sets the load segment for the initial boot image. This is only for * no emulation boot images, and is a NOP for other image types. * * @param bootimg * The image to to manipulate * @param segment * Load segment address. * The data type of this parameter is not fully suitable. You may submit * negative numbers in the range ((short) 0x8000) to ((short) 0xffff) * in order to express the non-negative numbers 0x8000 to 0xffff. * * @since 0.6.2 */ void el_torito_set_load_seg(ElToritoBootImage *bootimg, short segment); /** * Get the load segment value. See el_torito_set_load_seg(). * * @param bootimg * The image to inquire * @return * 0 - 65535 : The load segment value * < 0 : error * * @since 0.6.32 */ int el_torito_get_load_seg(ElToritoBootImage *bootimg); /** * Sets the number of sectors (512b) to be load at load segment during * the initial boot procedure. This is only for * no emulation boot images, and is a NOP for other image types. * * @param bootimg * The image to to manipulate * @param sectors * Number of 512-byte blocks to be loaded by the BIOS. * The data type of this parameter is not fully suitable. You may submit * negative numbers in the range ((short) 0x8000) to ((short) 0xffff) * in order to express the non-negative numbers 0x8000 to 0xffff. * * @since 0.6.2 */ void el_torito_set_load_size(ElToritoBootImage *bootimg, short sectors); /** * Get the load size. See el_torito_set_load_size(). * * @param bootimg * The image to inquire * @return * 0 - 65535 : The load size value * < 0 : error * * @since 0.6.32 */ int el_torito_get_load_size(ElToritoBootImage *bootimg); /** * Marks the specified boot image as not bootable * * @since 0.6.2 */ void el_torito_set_no_bootable(ElToritoBootImage *bootimg); /** * Get the bootability flag. See el_torito_set_no_bootable(). * * @param bootimg * The image to inquire * @return * 0 = not bootable, 1 = bootable , <0 = error * * @since 0.6.32 */ int el_torito_get_bootable(ElToritoBootImage *bootimg); /** * Set the id_string of the Validation Entry or Sector Header Entry which * will govern the boot image Section Entry in the El Torito Catalog. * * @param bootimg * The image to manipulate. * @param id_string * The first boot image puts 24 bytes of ID string into the Validation * Entry, where they shall "identify the manufacturer/developer of * the CD-ROM". * Further boot images put 28 bytes into their Section Header. * El Torito 1.0 states that "If the BIOS understands the ID string, it * may choose to boot the system using one of these entries in place * of the INITIAL/DEFAULT entry." (The INITIAL/DEFAULT entry points to the * first boot image.) * @return * 1 = ok , <0 = error * * @since 0.6.32 */ int el_torito_set_id_string(ElToritoBootImage *bootimg, uint8_t id_string[28]); /** * Get the id_string as of el_torito_set_id_string(). * * @param bootimg * The image to inquire * @param id_string * Returns 28 bytes of id string * @return * 1 = ok , <0 = error * * @since 0.6.32 */ int el_torito_get_id_string(ElToritoBootImage *bootimg, uint8_t id_string[28]); /** * Set the Selection Criteria of a boot image. * * @param bootimg * The image to manipulate. * @param crit * The first boot image has no selection criteria. They will be ignored. * Further boot images put 1 byte of Selection Criteria Type and 19 * bytes of data into their Section Entry. * El Torito 1.0 states that "The format of the selection criteria is * a function of the BIOS vendor. In the case of a foreign language * BIOS three bytes would be used to identify the language". * Type byte == 0 means "no criteria", * type byte == 1 means "Language and Version Information (IBM)". * @return * 1 = ok , <0 = error * * @since 0.6.32 */ int el_torito_set_selection_crit(ElToritoBootImage *bootimg, uint8_t crit[20]); /** * Get the Selection Criteria bytes as of el_torito_set_selection_crit(). * * @param bootimg * The image to inquire * @param id_string * Returns 20 bytes of type and data * @return * 1 = ok , <0 = error * * @since 0.6.32 */ int el_torito_get_selection_crit(ElToritoBootImage *bootimg, uint8_t crit[20]); /** * Makes a guess whether the boot image was patched by a boot information * table. It is advisable to patch such boot images if their content gets * copied to a new location. See el_torito_set_isolinux_options(). * Note: The reply can be positive only if the boot image was imported * from an existing ISO image. * * @param bootimg * The image to inquire * @param flag * Bitfield for control purposes: * bit0 - bit3= mode * 0 = inquire for classic boot info table as described in man mkisofs * @since 0.6.32 * 1 = inquire for GRUB2 boot info as of bit9 of options of * el_torito_set_isolinux_options() * @since 1.3.0 * @return * 1 = seems to contain the inquired boot info, 0 = quite surely not * @since 0.6.32 */ int el_torito_seems_boot_info_table(ElToritoBootImage *bootimg, int flag); /** * Specifies options for ISOLINUX or GRUB boot images. This should only be used * if the type of boot image is known. * * @param bootimg * The image to set options on * @param options * bitmask style flag. The following values are defined: * * bit0= Patch the boot info table of the boot image. * This does the same as mkisofs option -boot-info-table. * Needed for ISOLINUX or GRUB boot images with platform ID 0. * The table is located at byte 8 of the boot image file. * Its size is 56 bytes. * The original boot image file on disk will not be modified. * * One may use el_torito_seems_boot_info_table() for a * qualified guess whether a boot info table is present in * the boot image. If the result is 1 then it should get bit0 * set if its content gets copied to a new LBA. * * bit1= Generate a ISOLINUX isohybrid image with MBR. * ---------------------------------------------------------- * @deprecated since 31 Mar 2010: * The author of syslinux, H. Peter Anvin requested that this * feature shall not be used any more. He intends to cease * support for the MBR template that is included in libisofs. * ---------------------------------------------------------- * A hybrid image is a boot image that boots from either * CD/DVD media or from disk-like media, e.g. USB stick. * For that you need isolinux.bin from SYSLINUX 3.72 or later. * IMPORTANT: The application has to take care that the image * on media gets padded up to the next full MB. * Under seiveral circumstances it might get aligned * automatically. But there is no warranty. * bit2-7= Mentioning in isohybrid GPT * 0= Do not mention in GPT * 1= Mention as Basic Data partition. * This cannot be combined with GPT partitions as of * iso_write_opts_set_efi_bootp() * @since 1.2.4 * 2= Mention as HFS+ partition. * This cannot be combined with HFS+ production by * iso_write_opts_set_hfsplus(). * @since 1.2.4 * Primary GPT and backup GPT get written if at least one * ElToritoBootImage shall be mentioned. * The first three mentioned GPT partitions get mirrored in the * the partition table of the isohybrid MBR. They get type 0xfe. * The MBR partition entry for PC-BIOS gets type 0x00 rather * than 0x17. * Often it is one of the further MBR partitions which actually * gets used by EFI. * @since 1.2.4 * bit8= Mention in isohybrid Apple partition map * APM get written if at least one ElToritoBootImage shall be * mentioned. The ISOLINUX MBR must look suitable or else an error * event will happen at image generation time. * @since 1.2.4 * bit9= GRUB2 boot info * Patch the boot image file at byte 1012 with the 512-block * address + 2. Two little endian 32-bit words. Low word first. * This is combinable with bit0. * @since 1.3.0 * @param flag * Reserved for future usage, set to 0. * @return * 1 success, < 0 on error * @since 0.6.12 */ int el_torito_set_isolinux_options(ElToritoBootImage *bootimg, int options, int flag); /** * Get the options as of el_torito_set_isolinux_options(). * * @param bootimg * The image to inquire * @param flag * Reserved for future usage, set to 0. * @return * >= 0 returned option bits , <0 = error * * @since 0.6.32 */ int el_torito_get_isolinux_options(ElToritoBootImage *bootimg, int flag); /** Deprecated: * Specifies that this image needs to be patched. This involves the writing * of a 16 bytes boot information table at offset 8 of the boot image file. * The original boot image file won't be modified. * This is needed for isolinux boot images. * * @since 0.6.2 * @deprecated Use el_torito_set_isolinux_options() instead */ void el_torito_patch_isolinux_image(ElToritoBootImage *bootimg); /** * Obtain a copy of the eventually loaded first 32768 bytes of the imported * session, the System Area. * It will be written to the start of the next session unless it gets * overwritten by iso_write_opts_set_system_area(). * * @param img * The image to be inquired. * @param data * A byte array of at least 32768 bytes to take the loaded bytes. * @param options * The option bits which will be applied if not overridden by * iso_write_opts_set_system_area(). See there. * @param flag * Bitfield for control purposes, unused yet, submit 0 * @return * 1 on success, 0 if no System Area was loaded, < 0 error. * @since 0.6.30 */ int iso_image_get_system_area(IsoImage *img, char data[32768], int *options, int flag); /** * The maximum length of a single line in the output of function * iso_image_report_system_area() and iso_image_report_el_torito(). * This number includes the trailing 0. * @since 1.3.8 */ #define ISO_MAX_SYSAREA_LINE_LENGTH 4096 /** * Texts which describe the output format of iso_image_report_system_area(). * They are publicly defined here only as part of the API description. * Do not use these macros in your application but rather call * iso_image_report_system_area() with flag bit0. */ #define ISO_SYSAREA_REPORT_DOC \ \ "Report format for recognized System Area data.", \ "", \ "No text will be reported if no System Area was loaded or if it was", \ "entirely filled with 0-bytes.", \ "Else there will be at least these three lines:", \ " System area options: hex", \ " see libisofs.h, parameter of iso_write_opts_set_system_area().", \ " System area summary: word ... word", \ " human readable interpretation of system area options and other info", \ " The words are from the set:", \ " { MBR, CHRP, PReP, GPT, APM, MIPS-Big-Endian, MIPS-Little-Endian,", \ " SUN-SPARC-Disk-Label, HP-PA-PALO, DEC-Alpha, ", \ " protective-msdos-label, isohybrid, grub2-mbr,", \ " cyl-align-{auto,on,off,all}, not-recognized, }", \ " The acronyms indicate boot data for particular hardware/firmware.", \ " protective-msdos-label is an MBR conformant to specs of GPT.", \ " isohybrid is an MBR implementing ISOLINUX isohybrid functionality.", \ " grub2-mbr is an MBR with GRUB2 64 bit address patching.", \ " cyl-align-on indicates that the ISO image MBR partition ends at a", \ " cylinder boundary. cyl-align-all means that more MBR partitions", \ " exist and all end at a cylinder boundary.", \ " not-recognized tells about unrecognized non-zero system area data.", \ " ISO image size/512 : decimal", \ " size of ISO image in block units of 512 bytes.", \ "" #define ISO_SYSAREA_REPORT_DOC_MBR \ \ "If an MBR is detected, with at least one partition entry of non-zero size,", \ "then there may be:", \ " Partition offset : decimal", \ " if not 0 then a second ISO 9660 superblock was found to which", \ " MBR partition 1 or GPT partition 1 is pointing.", \ " MBR heads per cyl : decimal", \ " conversion factor between MBR C/H/S address and LBA. 0=inconsistent.", \ " MBR secs per head : decimal", \ " conversion factor between MBR C/H/S address and LBA. 0=inconsistent.", \ " MBR partition table: N Status Type Start Blocks", \ " headline for MBR partition table.", \ " MBR partition : X hex hex decimal decimal", \ " gives partition number, status byte, type byte, start block,", \ " and number of blocks. 512 bytes per block.", \ " MBR partition path : X path", \ " the path of a file in the ISO image which begins at the partition", \ " start block of partition X.", \ " PReP boot partition: decimal decimal", \ " gives start block and size of a PReP boot partition in ISO 9660", \ " block units of 2048 bytes.", \ "" #define ISO_SYSAREA_REPORT_DOC_GPT1 \ \ "GUID Partition Table can coexist with MBR:", \ " GPT : N Info", \ " headline for GPT partition table. The fields are too wide for a", \ " neat table. So they are listed with a partition number and a text.", \ " GPT CRC should be : to match first 92 GPT header block bytes", \ " GPT CRC found : matches all 512 bytes of GPT header block", \ " libisofs-1.2.4 to 1.2.8 had a bug with the GPT header CRC. So", \ " libisofs is willing to recognize GPT with the buggy CRC. These", \ " two lines inform that most partition editors will not accept it.", \ " GPT array CRC wrong: should be , found ", \ " GPT entry arrays are accepted even if their CRC does not match.", \ " In this case, both CRCs are reported by this line.", \ " GPT backup problems: text", \ " reports about inconsistencies between main GPT and backup GPT.", \ " The statements are comma separated:", \ " Implausible header LBA ", \ " Cannot read header block at 2k LBA ", \ " Not a GPT 1.0 header of 92 bytes for 128 bytes per entry", \ " Head CRC wrong. Should be ", \ " Head CRC wrong. Should be . Matches all 512 block bytes", \ " Disk GUID differs ()", \ " Cannot read array block at 2k LBA ", \ " Array CRC wrong. Should be ", \ " Entries differ for partitions [... ]", \ " GPT disk GUID : hex_digits", \ " 32 hex digits giving the byte string of the disk's GUID", \ " GPT entry array : decimal decimal word", \ " start block of partition entry array and number of entries. 512 bytes", \ " per block. The word may be \"separated\" if partitions are disjoint,", \ " \"overlapping\" if they are not. In future there may be \"nested\"", \ " as special case where all overlapping partitions are superset and", \ " subset, and \"covering\" as special case of disjoint partitions", \ " covering the whole GPT block range for partitions.", \ " GPT lba range : decimal decimal decimal", \ " addresses of first payload block, last payload block, and of the", \ " GPT backup header block. 512 bytes per block." \ #define ISO_SYSAREA_REPORT_DOC_GPT2 \ \ " GPT partition name : X hex_digits", \ " up to 144 hex digits giving the UTF-16LE name byte string of", \ " partition X. Trailing 16 bit 0-characters are omitted.", \ " GPT partname local : X text", \ " the name of partition X converted to the local character set.", \ " This line may be missing if the name cannot be converted, or is", \ " empty.", \ " GPT partition GUID : X hex_digits", \ " 32 hex digits giving the byte string of the GUID of partition X.", \ " GPT type GUID : X hex_digits", \ " 32 hex digits giving the byte string of the type GUID of partition X.", \ " GPT partition flags: X hex", \ " 64 flag bits of partition X in hex representation.", \ " Known bit meanings are:", \ " bit0 = \"System Partition\" Do not alter.", \ " bit2 = Legacy BIOS bootable (MBR partition type 0x80)", \ " bit60= read-only", \ " GPT start and size : X decimal decimal", \ " start block and number of blocks of partition X. 512 bytes per block.", \ " GPT partition path : X path", \ " the path of a file in the ISO image which begins at the partition", \ " start block of partition X.", \ "" #define ISO_SYSAREA_REPORT_DOC_APM \ \ "Apple partition map can coexist with MBR and GPT:", \ " APM : N Info", \ " headline for human readers.", \ " APM block size : decimal", \ " block size of Apple Partition Map. 512 or 2048. This applies to", \ " start address and size of all partitions in the APM.", \ " APM gap fillers : decimal", \ " tells the number of partitions with name \"Gap[0-9[0-9]]\" and type", \ " \"ISO9660_data\".", \ " APM partition name : X text", \ " the name of partition X. Up to 32 characters.", \ " APM partition type : X text", \ " the type string of partition X. Up to 32 characters.", \ " APM start and size : X decimal decimal", \ " start block and number of blocks of partition X.", \ " APM partition path : X path", \ " the path of a file in the ISO image which begins at the partition", \ " start block of partition X.", \ "" #define ISO_SYSAREA_REPORT_DOC_MIPS \ \ "If a MIPS Big Endian Volume Header is detected, there may be:", \ " MIPS-BE volume dir : N Name Block Bytes", \ " headline for human readers.", \ " MIPS-BE boot entry : X upto8chr decimal decimal", \ " tells name, 512-byte block address, and byte count of boot entry X.", \ " MIPS-BE boot path : X path", \ " tells the path to the boot image file in the ISO image which belongs", \ " to the block address given by boot entry X.", \ "", \ "If a DEC Boot Block for MIPS Little Endian is detected, there may be:", \ " MIPS-LE boot map : LoadAddr ExecAddr SegmentSize SegmentStart", \ " headline for human readers.", \ " MIPS-LE boot params: decimal decimal decimal decimal", \ " tells four numbers which are originally derived from the ELF header", \ " of the boot file. The first two are counted in bytes, the other two", \ " are counted in blocks of 512 bytes.", \ " MIPS-LE boot path : path", \ " tells the path to the boot file in the ISO image which belongs to the", \ " address given by SegmentStart.", \ " MIPS-LE elf offset : decimal", \ " tells the relative 512-byte block offset inside the boot file:", \ " SegmentStart - FileStartBlock", \ "" #define ISO_SYSAREA_REPORT_DOC_SUN \ \ "If a SUN SPARC Disk Label is present:", \ " SUN SPARC disklabel: text", \ " tells the disk label text.", \ " SUN SPARC secs/head: decimal", \ " tells the number of sectors per head.", \ " SUN SPARC heads/cyl: decimal", \ " tells the number of heads per cylinder.", \ " SUN SPARC partmap : N IdTag Perms StartCyl NumBlock", \ " headline for human readers.", \ " SUN SPARC partition: X hex hex decimal decimal", \ " gives partition number, type word, permission word, start cylinder,", \ " and number of of blocks. 512 bytes per block. Type word may be: ", \ " 0=unused, 2=root partition with boot, 4=user partition.", \ " Permission word is 0x10 = read-only.", \ " SPARC GRUB2 core : decimal decimal", \ " tells byte address and byte count of the GRUB2 SPARC core file.", \ " SPARC GRUB2 path : path", \ " tells the path to the data file in the ISO image which belongs to the", \ " address given by core.", \ "" #define ISO_SYSAREA_REPORT_DOC_HPPA \ \ "If a HP-PA PALO boot sector version 4 or 5 is present:", \ " PALO header version: decimal", \ " tells the PALO header version: 4 or 5.", \ " HP-PA cmdline : text", \ " tells the command line for the kernels.", \ " HP-PA boot files : ByteAddr ByteSize Path", \ " headline for human readers.", \ " HP-PA 32-bit kernel: decimal decimal path", \ " tells start byte, byte count, and file path of the 32-bit kernel.", \ " HP-PA 64-bit kernel: decimal decimal path", \ " tells the same for the 64-bit kernel.", \ " HP-PA ramdisk : decimal decimal path", \ " tells the same for the ramdisk file.", \ " HP-PA bootloader : decimal decimal path", \ " tells the same for the bootloader file.", \ "" #define ISO_SYSAREA_REPORT_DOC_ALPHA \ "If a DEC Alpha SRM boot sector is present:", \ " DEC Alpha ldr size : decimal", \ " tells the number of 512-byte blocks in DEC Alpha Secondary Bootstrap" \ " Loader file.", \ " DEC Alpha ldr adr : decimal", \ " tells the start of the loader file in units of 512-byte blocks.", \ " DEC Alpha ldr path : path", \ " tells the path of a file in the ISO image which starts at the loader", \ " start address." /** * Obtain an array of texts describing the detected properties of the * eventually loaded System Area. * The array will be NULL if no System Area was loaded. It will be non-NULL * with zero line count if the System Area was loaded and contains only * 0-bytes. * Else it will consist of lines as described in ISO_SYSAREA_REPORT_DOC above. * * File paths and other long texts are reported as "(too long to show here)" * if their length plus preceeding text plus trailing 0-byte exceeds the * line length limit of ISO_MAX_SYSAREA_LINE_LENGTH bytes. * Texts which may contain whitespace or unprintable characters will start * at fixed positions and extend to the end of the line. * Note that newline characters may well appearing in the middle of a "line". * * @param image * The image to be inquired. * @param reply * Will return an array of pointers to the result text lines or NULL. * Dispose a non-NULL reply by a call to iso_image_report_system_area() * with flag bit15, when no longer needed. * Be prepared for a long text with up to ISO_MAX_SYSAREA_LINE_LENGTH * characters per line. * @param line_count * Will return the number of valid pointers in reply. * @param flag * Bitfield for control purposes * bit0= do not report system area but rather reply a copy of * above text line arrays ISO_SYSAREA_REPORT_DOC*. * With this bit it is permissible to submit image as NULL. * bit15= dispose result from previous call. * @return * 1 on success, 0 if no System Area was loaded, < 0 error. * @since 1.3.8 */ int iso_image_report_system_area(IsoImage *image, char ***reply, int *line_count, int flag); /** * Text which describes the output format of iso_image_report_el_torito(). * It is publicly defined here only as part of the API description. * Do not use it as macro in your application but rather call * iso_image_report_el_torito() with flag bit0. */ #define ISO_ELTORITO_REPORT_DOC \ "Report format for recognized El Torito boot information.", \ "", \ "No text will be reported if no El Torito information was found.", \ "Else there will be at least these three lines", \ " El Torito catalog : decimal decimal", \ " tells the block address and number of 2048-blocks of the boot catalog.", \ " El Torito images : N Pltf B Emul Ld_seg Hdpt Ldsiz LBA", \ " is the headline of the boot image list.", \ " El Torito boot img : X word char word hex hex decimal decimal", \ " tells about boot image number X:", \ " - Platform Id: \"BIOS\", \"PPC\", \"Mac\", \"UEFI\" or a hex number.", \ " - Bootability: either \"y\" or \"n\".", \ " - Emulation: \"none\", \"fd1.2\", \"fd1.4\", \"fd2.8\", \"hd\"", \ " for no emulation, three floppy MB sizes, hard disk.", \ " - Load Segment: start offset in boot image. 0x0000 means 0x07c0.", \ " - Hard disk emulation partition type: MBR partition type code.", \ " - Load size: number of 512-blocks to load with emulation mode \"none\".", \ " - LBA: start block number in ISO filesystem (2048-block).", \ "", \ "The following lines appear conditionally:", \ " El Torito cat path : iso_rr_path", \ " tells the path to the data file in the ISO image which belongs to", \ " the block address where the boot catalog starts.", \ " (This line is not reported if no path points to that block.)", \ " El Torito img path : X iso_rr_path", \ " tells the path to the data file in the ISO image which belongs to", \ " the block address given by LBA of boot image X.", \ " (This line is not reported if no path points to that block.)", \ " El Torito img opts : X word ... word", \ " tells the presence of extra features:", \ " \"boot-info-table\" image got boot info table patching.", \ " \"isohybrid-suitable\" image is suitable for ISOLINUX isohybrid MBR.", \ " \"grub2-boot-info\" image got GRUB2 boot info patching.", \ " (This line is not reported if no such options were detected.)", \ " El Torito id string: X hex_digits", \ " tells the id string of the catalog section which hosts boot image X.", \ " (This line is not reported if the id string is all zero.)", \ " El Torito sel crit : X hex_digits", \ " tells the selection criterion of boot image X.", \ " (This line is not reported if the criterion is all zero.)", \ " El Torito img blks : X decimal", \ " gives an upper limit of the number of 2048-blocks in the boot image", \ " if it is not accessible via a path in the ISO directory tree.", \ " The boot image is supposed to end before the start block of any", \ " other entity of the ISO filesystem.", \ " (This line is not reported if no limiting entity is found.)", \ "" /** * Obtain an array of texts describing the detected properties of the * eventually loaded El Torito boot information. * The array will be NULL if no El Torito info was loaded. * Else it will consist of lines as described in ISO_ELTORITO_REPORT_DOC above. * * The lines have the same length restrictions and whitespace rules as the ones * returned by iso_image_report_system_area(). * * @param image * The image to be inquired. * @param reply * Will return an array of pointers to the result text lines or NULL. * Dispose a non-NULL reply by a call to iso_image_report_el_torito() * with flag bit15, when no longer needed. * Be prepared for a long text with up to ISO_MAX_SYSAREA_LINE_LENGTH * characters per line. * @param line_count * Will return the number of valid pointers in reply. * @param flag * Bitfield for control purposes * bit0= do not report system area but rather reply a copy of * above text line array ISO_ELTORITO_REPORT_DOC. * With this bit it is permissible to submit image as NULL. * bit15= dispose result from previous call. * @return * 1 on success, 0 if no El Torito information was loaded, < 0 error. * @since 1.3.8 */ int iso_image_report_el_torito(IsoImage *image, char ***reply, int *line_count, int flag); /** * Compute a CRC number as expected in the GPT main and backup header blocks. * * The CRC at byte offset 88 is supposed to cover the array of partition * entries. * The CRC at byte offset 16 is supposed to cover the readily produced * first 92 bytes of the header block while its bytes 16 to 19 are still * set to 0. * Block size is 512 bytes. Numbers are stored little-endian. * See doc/boot_sectors.txt for the byte layout of GPT. * * This might be helpful for applications which want to manipulate GPT * directly. The function is in libisofs/system_area.c and self-contained. * So if you want to copy+paste it under the license of that file: Be invited. * Be warned that this implementation works bit-wise and thus is much slower * than table-driven ones. For less than 32 KiB, it fully suffices, though. * * @param data * The memory buffer with the data to sum up. * @param count * Number of bytes in data. * @param flag * Bitfield for control purposes. Submit 0. * @return * The CRC of data. * @since 1.3.8 */ uint32_t iso_crc32_gpt(unsigned char *data, int count, int flag); /** * Add a MIPS boot file path to the image. * Up to 15 such files can be written into a MIPS Big Endian Volume Header * if this is enabled by value 1 in iso_write_opts_set_system_area() option * bits 2 to 7. * A single file can be written into a DEC Boot Block if this is enabled by * value 2 in iso_write_opts_set_system_area() option bits 2 to 7. So only * the first added file gets into effect with this system area type. * The data files which shall serve as MIPS boot files have to be brought into * the image by the normal means. * @param img * The image to be manipulated. * @param path * Absolute path of the boot file in the ISO 9660 Rock Ridge tree. * @param flag * Bitfield for control purposes, unused yet, submit 0 * @return * 1 on success, < 0 error * @since 0.6.38 */ int iso_image_add_mips_boot_file(IsoImage *image, char *path, int flag); /** * Obtain the number of added MIPS Big Endian boot files and pointers to * their paths in the ISO 9660 Rock Ridge tree. * @param img * The image to be inquired. * @param paths * An array of pointers to be set to the registered boot file paths. * This are just pointers to data inside IsoImage. Do not free() them. * Eventually make own copies of the data before manipulating the image. * @param flag * Bitfield for control purposes, unused yet, submit 0 * @return * >= 0 is the number of valid path pointers , <0 means error * @since 0.6.38 */ int iso_image_get_mips_boot_files(IsoImage *image, char *paths[15], int flag); /** * Clear the list of MIPS Big Endian boot file paths. * @param img * The image to be manipulated. * @param flag * Bitfield for control purposes, unused yet, submit 0 * @return * 1 is success , <0 means error * @since 0.6.38 */ int iso_image_give_up_mips_boot(IsoImage *image, int flag); /** * Designate a data file in the ISO image of which the position and size * shall be written after the SUN Disk Label. The position is written as * 64-bit big-endian number to byte position 0x228. The size is written * as 32-bit big-endian to 0x230. * This setting has an effect only if system area type is set to 3 * with iso_write_opts_set_system_area(). * * @param img * The image to be manipulated. * @param sparc_core * The IsoFile which shall be mentioned after the SUN Disk label. * NULL is a permissible value. It disables this feature. * @param flag * Bitfield for control purposes, unused yet, submit 0 * @return * 1 is success , <0 means error * @since 1.3.0 */ int iso_image_set_sparc_core(IsoImage *img, IsoFile *sparc_core, int flag); /** * Obtain the current setting of iso_image_set_sparc_core(). * * @param img * The image to be inquired. * @param sparc_core * Will return a pointer to the IsoFile (or NULL, which is not an error) * @param flag * Bitfield for control purposes, unused yet, submit 0 * @return * 1 is success , <0 means error * @since 1.3.0 */ int iso_image_get_sparc_core(IsoImage *img, IsoFile **sparc_core, int flag); /** * Define a command line and submit the paths of four mandatory files for * production of a HP-PA PALO boot sector for PA-RISC machines. * The paths must lead to already existing data files in the ISO image * which stay with these paths until image production. * * @param img * The image to be manipulated. * @param cmdline * Up to 127 characters of command line. * @param bootloader * Absolute path of a data file in the ISO image. * @param kernel_32 * Absolute path of a data file in the ISO image which serves as * 32 bit kernel. * @param kernel_64 * Absolute path of a data file in the ISO image which serves as * 64 bit kernel. * @param ramdisk * Absolute path of a data file in the ISO image. * @param flag * Bitfield for control purposes * bit0= Let NULL parameters free the corresponding image properties. * Else only the non-NULL parameters of this call have an effect * @return * 1 is success , <0 means error * @since 1.3.8 */ int iso_image_set_hppa_palo(IsoImage *img, char *cmdline, char *bootloader, char *kernel_32, char *kernel_64, char *ramdisk, int flag); /** * Inquire the current settings of iso_image_set_hppa_palo(). * Do not free() the returned pointers. * * @param img * The image to be inquired. * @param cmdline * Will return the command line. * @param bootloader * Will return the absolute path of the bootloader file. * @param kernel_32 * Will return the absolute path of the 32 bit kernel file. * @param kernel_64 * Will return the absolute path of the 64 bit kernel file. * @param ramdisk * Will return the absolute path of the RAM disk file. * @return * 1 is success , <0 means error * @since 1.3.8 */ int iso_image_get_hppa_palo(IsoImage *img, char **cmdline, char **bootloader, char **kernel_32, char **kernel_64, char **ramdisk); /** * Submit the path of the DEC Alpha Secondary Bootstrap Loader file. * The path must lead to an already existing data file in the ISO image * which stays with this path until image production. * This setting has an effect only if system area type is set to 6 * with iso_write_opts_set_system_area(). * * @param img * The image to be manipulated. * @param boot_loader_path * Absolute path of a data file in the ISO image. * Submit NULL to free this image property. * @param flag * Bitfield for control purposes. Unused yet. Submit 0. * @return * 1 is success , <0 means error * @since 1.4.0 */ int iso_image_set_alpha_boot(IsoImage *img, char *boot_loader_path, int flag); /** * Inquire the path submitted by iso_image_set_alpha_boot() * Do not free() the returned pointer. * * @param img * The image to be inquired. * @param cmdline * Will return the path. NULL if none is currently submitted. * @return * 1 is success , <0 means error * @since 1.4.0 */ int iso_image_get_alpha_boot(IsoImage *img, char **boot_loader_path); /** * Increments the reference counting of the given node. * * @since 0.6.2 */ void iso_node_ref(IsoNode *node); /** * Decrements the reference couting of the given node. * If it reach 0, the node is free, and, if the node is a directory, * its children will be unref() too. * * @since 0.6.2 */ void iso_node_unref(IsoNode *node); /** * Get the type of an IsoNode. * * @since 0.6.2 */ enum IsoNodeType iso_node_get_type(IsoNode *node); /** * Class of functions to handle particular extended information. A function * instance acts as an identifier for the type of the information. Structs * with same information type must use a pointer to the same function. * * @param data * Attached data * @param flag * What to do with the data. At this time the following values are * defined: * -> 1 the data must be freed * @return * 1 in any case. * * @since 0.6.4 */ typedef int (*iso_node_xinfo_func)(void *data, int flag); /** * Add extended information to the given node. Extended info allows * applications (and libisofs itself) to add more information to an IsoNode. * You can use this facilities to associate temporary information with a given * node. This information is not written into the ISO 9660 image on media * and thus does not persist longer than the node memory object. * * Each node keeps a list of added extended info, meaning you can add several * extended info data to each node. Each extended info you add is identified * by the proc parameter, a pointer to a function that knows how to manage * the external info data. Thus, in order to add several types of extended * info, you need to define a "proc" function for each type. * * @param node * The node where to add the extended info * @param proc * A function pointer used to identify the type of the data, and that * knows how to manage it * @param data * Extended info to add. * @return * 1 if success, 0 if the given node already has extended info of the * type defined by the "proc" function, < 0 on error * * @since 0.6.4 */ int iso_node_add_xinfo(IsoNode *node, iso_node_xinfo_func proc, void *data); /** * Remove the given extended info (defined by the proc function) from the * given node. * * @return * 1 on success, 0 if node does not have extended info of the requested * type, < 0 on error * * @since 0.6.4 */ int iso_node_remove_xinfo(IsoNode *node, iso_node_xinfo_func proc); /** * Remove all extended information from the given node. * * @param node * The node where to remove all extended info * @param flag * Bitfield for control purposes, unused yet, submit 0 * @return * 1 on success, < 0 on error * * @since 1.0.2 */ int iso_node_remove_all_xinfo(IsoNode *node, int flag); /** * Get the given extended info (defined by the proc function) from the * given node. * * @param node * The node to inquire * @param proc * The function pointer which serves as key * @param data * Will after successful call point to the xinfo data corresponding * to the given proc. This is a pointer, not a feeable data copy. * @return * 1 on success, 0 if node does not have extended info of the requested * type, < 0 on error * * @since 0.6.4 */ int iso_node_get_xinfo(IsoNode *node, iso_node_xinfo_func proc, void **data); /** * Get the next pair of function pointer and data of an iteration of the * list of extended informations. Like: * iso_node_xinfo_func proc; * void *handle = NULL, *data; * while (iso_node_get_next_xinfo(node, &handle, &proc, &data) == 1) { * ... make use of proc and data ... * } * The iteration allocates no memory. So you may end it without any disposal * action. * IMPORTANT: Do not continue iterations after manipulating the extended * information of a node. Memory corruption hazard ! * @param node * The node to inquire * @param handle * The opaque iteration handle. Initialize iteration by submitting * a pointer to a void pointer with value NULL. * Do not alter its content until iteration has ended. * @param proc * The function pointer which serves as key * @param data * Will be filled with the extended info corresponding to the given proc * function * @return * 1 on success * 0 if iteration has ended (proc and data are invalid then) * < 0 on error * * @since 1.0.2 */ int iso_node_get_next_xinfo(IsoNode *node, void **handle, iso_node_xinfo_func *proc, void **data); /** * Class of functions to clone extended information. A function instance gets * associated to a particular iso_node_xinfo_func instance by function * iso_node_xinfo_make_clonable(). This is a precondition to have IsoNode * objects clonable which carry data for a particular iso_node_xinfo_func. * * @param old_data * Data item to be cloned * @param new_data * Shall return the cloned data item * @param flag * Unused yet, submit 0 * The function shall return ISO_XINFO_NO_CLONE on unknown flag bits. * @return * > 0 number of allocated bytes * 0 no size info is available * < 0 error * * @since 1.0.2 */ typedef int (*iso_node_xinfo_cloner)(void *old_data, void **new_data,int flag); /** * Associate a iso_node_xinfo_cloner to a particular class of extended * information in order to make it clonable. * * @param proc * The key and disposal function which identifies the particular * extended information class. * @param cloner * The cloner function which shall be associated with proc. * @param flag * Unused yet, submit 0 * @return * 1 success, < 0 error * * @since 1.0.2 */ int iso_node_xinfo_make_clonable(iso_node_xinfo_func proc, iso_node_xinfo_cloner cloner, int flag); /** * Inquire the registered cloner function for a particular class of * extended information. * * @param proc * The key and disposal function which identifies the particular * extended information class. * @param cloner * Will return the cloner function which is associated with proc, or NULL. * @param flag * Unused yet, submit 0 * @return * 1 success, 0 no cloner registered for proc, < 0 error * * @since 1.0.2 */ int iso_node_xinfo_get_cloner(iso_node_xinfo_func proc, iso_node_xinfo_cloner *cloner, int flag); /** * Set the name of a node. Note that if the node is already added to a dir * this can fail if dir already contains a node with the new name. * The IsoImage context defines a maximum permissible name length and a mode * how to react on oversized names. See iso_image_set_truncate_mode(). * * @param image * The image object to which the node belongs or shall belong in future. * @param node * The node of which you want to change the name. One cannot change the * name of the root directory. * @param name * The new name for the node. It may not be empty. If it is oversized * then it will be handled according to iso_image_set_truncate_mode(). * @param flag * bit0= issue warning in case of truncation * @return * 1 on success, < 0 on error * * @since 1.4.2 */ int iso_image_set_node_name(IsoImage *image, IsoNode *node, const char *name, int flag); /** * *** Deprecated *** * use iso_image_set_node_name() instead * * Set the name of a node without taking into respect name truncation mode of * an IsoImage. * * @param node * The node whose name you want to change. Note that you can't change * the name of the root. * @param name * The name for the node. If you supply an empty string or a * name greater than 255 characters this returns with failure, and * node name is not modified. * @return * 1 on success, < 0 on error * * @since 0.6.2 */ int iso_node_set_name(IsoNode *node, const char *name); /** * Get the name of a node. * The returned string belongs to the node and must not be modified nor * freed. Use strdup if you really need your own copy. * * Up to version 1.4.2 inquiry of the root directory name returned NULL, * which is a bug in the light of above description. * Since 1.4.2 the return value is an empty string. * * @since 0.6.2 */ const char *iso_node_get_name(const IsoNode *node); /** * Set the permissions for the node. This attribute is only useful when * Rock Ridge extensions are enabled. * * @param node * The node to change * @param mode * bitmask with the permissions of the node, as specified in 'man 2 stat'. * The file type bitfields will be ignored, only file permissions will be * modified. * * @since 0.6.2 */ void iso_node_set_permissions(IsoNode *node, mode_t mode); /** * Get the permissions for the node * * @since 0.6.2 */ mode_t iso_node_get_permissions(const IsoNode *node); /** * Get the mode of the node, both permissions and file type, as specified in * 'man 2 stat'. * * @since 0.6.2 */ mode_t iso_node_get_mode(const IsoNode *node); /** * Set the user id for the node. This attribute is only useful when * Rock Ridge extensions are enabled. * * @since 0.6.2 */ void iso_node_set_uid(IsoNode *node, uid_t uid); /** * Get the user id of the node. * * @since 0.6.2 */ uid_t iso_node_get_uid(const IsoNode *node); /** * Set the group id for the node. This attribute is only useful when * Rock Ridge extensions are enabled. * * @since 0.6.2 */ void iso_node_set_gid(IsoNode *node, gid_t gid); /** * Get the group id of the node. * * @since 0.6.2 */ gid_t iso_node_get_gid(const IsoNode *node); /** * Set the time of last modification of the file * * @since 0.6.2 */ void iso_node_set_mtime(IsoNode *node, time_t time); /** * Get the time of last modification of the file * * @since 0.6.2 */ time_t iso_node_get_mtime(const IsoNode *node); /** * Set the time of last access to the file * * @since 0.6.2 */ void iso_node_set_atime(IsoNode *node, time_t time); /** * Get the time of last access to the file * * @since 0.6.2 */ time_t iso_node_get_atime(const IsoNode *node); /** * Set the time of last status change of the file * * @since 0.6.2 */ void iso_node_set_ctime(IsoNode *node, time_t time); /** * Get the time of last status change of the file * * @since 0.6.2 */ time_t iso_node_get_ctime(const IsoNode *node); /** * Set whether the node will be hidden in the directory trees of RR/ISO 9660, * or of Joliet (if enabled at all), or of ISO-9660:1999 (if enabled at all). * * A hidden file does not show up by name in the affected directory tree. * For example, if a file is hidden only in Joliet, it will normally * not be visible on Windows systems, while being shown on GNU/Linux. * * If a file is not shown in any of the enabled trees, then its content will * not be written to the image, unless LIBISO_HIDE_BUT_WRITE is given (which * is available only since release 0.6.34). * * @param node * The node that is to be hidden. * @param hide_attrs * Or-combination of values from enum IsoHideNodeFlag to set the trees * in which the node's name shall be hidden. * * @since 0.6.2 */ void iso_node_set_hidden(IsoNode *node, int hide_attrs); /** * Get the hide_attrs as eventually set by iso_node_set_hidden(). * * @param node * The node to inquire. * @return * Or-combination of values from enum IsoHideNodeFlag which are * currently set for the node. * * @since 0.6.34 */ int iso_node_get_hidden(IsoNode *node); /** * Compare two nodes whether they are based on the same input and * can be considered as hardlinks to the same file objects. * * @param n1 * The first node to compare. * @param n2 * The second node to compare. * @return * -1 if n1 is smaller n2 , 0 if n1 matches n2 , 1 if n1 is larger n2 * @param flag * Bitfield for control purposes, unused yet, submit 0 * @since 0.6.20 */ int iso_node_cmp_ino(IsoNode *n1, IsoNode *n2, int flag); /** * Add a new node to a dir. Note that this function don't add a new ref to * the node, so you don't need to free it, it will be automatically freed * when the dir is deleted. Of course, if you want to keep using the node * after the dir life, you need to iso_node_ref() it. * * @param dir * the dir where to add the node * @param child * the node to add. You must ensure that the node hasn't previously added * to other dir, and that the node name is unique inside the child. * Otherwise this function will return a failure, and the child won't be * inserted. * @param replace * if the dir already contains a node with the same name, whether to * replace or not the old node with this. * @return * number of nodes in dir if succes, < 0 otherwise * Possible errors: * ISO_NULL_POINTER, if dir or child are NULL * ISO_NODE_ALREADY_ADDED, if child is already added to other dir * ISO_NODE_NAME_NOT_UNIQUE, a node with same name already exists * ISO_WRONG_ARG_VALUE, if child == dir, or replace != (0,1) * * @since 0.6.2 */ int iso_dir_add_node(IsoDir *dir, IsoNode *child, enum iso_replace_mode replace); /** * Locate a node inside a given dir. * * The IsoImage context defines a maximum permissible name length and a mode * how to react on oversized names. See iso_image_set_truncate_mode(). * If the caller looks for an oversized name and image truncate mode is 1, * then this call looks for the truncated name among the nodes of dir. * * @param image * The image object to which dir belongs. * @param dir * The dir where to look for the node. * @param name * The name of the node. (Will not be changed if truncation happens.) * @param node * Location for a pointer to the node, it will filled with NULL if the dir * doesn't have a child with the given name. * The node will be owned by the dir and shouldn't be unref(). Just call * iso_node_ref() to get your own reference to the node. * Note that you can pass NULL is the only thing you want to do is check * if a node with such name already exists on dir. * @param flag * Bitfield for control purposes. * bit0= do not truncate name but lookup exactly as given. * @return * 1 node found * 0 no name truncation was needed, name not found in dir * 2 name truncation happened, truncated name not found in dir * < 0 error, see iso_dir_get_node(). * * @since 1.4.2 */ int iso_image_dir_get_node(IsoImage *image, IsoDir *dir, const char *name, IsoNode **node, int flag); /** * *** Deprecated *** * In most cases use iso_image_dir_get_node() instead. * * Locate a node inside a given dir without taking into respect name truncation * mode of an IsoImage. * * @param dir * The dir where to look for the node. * @param name * The name of the node * @param node * Location for a pointer to the node. See iso_image_get_node(). * @return * 1 node found, 0 child has no such node, < 0 error * Possible errors: * ISO_NULL_POINTER, if dir or name are NULL * * @since 0.6.2 */ int iso_dir_get_node(IsoDir *dir, const char *name, IsoNode **node); /** * Get the number of children of a directory. * * @return * >= 0 number of items, < 0 error * Possible errors: * ISO_NULL_POINTER, if dir is NULL * * @since 0.6.2 */ int iso_dir_get_children_count(IsoDir *dir); /** * Removes a child from a directory. * The child is not freed, so you will become the owner of the node. Later * you can add the node to another dir (calling iso_dir_add_node), or free * it if you don't need it (with iso_node_unref). * * @return * 1 on success, < 0 error * Possible errors: * ISO_NULL_POINTER, if node is NULL * ISO_NODE_NOT_ADDED_TO_DIR, if node doesn't belong to a dir * * @since 0.6.2 */ int iso_node_take(IsoNode *node); /** * Removes a child from a directory and free (unref) it. * If you want to keep the child alive, you need to iso_node_ref() it * before this call, but in that case iso_node_take() is a better * alternative. * * @return * 1 on success, < 0 error * * @since 0.6.2 */ int iso_node_remove(IsoNode *node); /* * Get the parent of the given iso tree node. No extra ref is added to the * returned directory, you must take your ref. with iso_node_ref() if you * need it. * * If node is the root node, the same node will be returned as its parent. * * This returns NULL if the node doesn't pertain to any tree * (it was removed/taken). * * @since 0.6.2 */ IsoDir *iso_node_get_parent(IsoNode *node); /** * Get an iterator for the children of the given dir. * * You can iterate over the children with iso_dir_iter_next. When finished, * you should free the iterator with iso_dir_iter_free. * You musn't delete a child of the same dir, using iso_node_take() or * iso_node_remove(), while you're using the iterator. You can use * iso_dir_iter_take() or iso_dir_iter_remove() instead. * * You can use the iterator in the way like this * * IsoDirIter *iter; * IsoNode *node; * if ( iso_dir_get_children(dir, &iter) != 1 ) { * // handle error * } * while ( iso_dir_iter_next(iter, &node) == 1 ) { * // do something with the child * } * iso_dir_iter_free(iter); * * An iterator is intended to be used in a single iteration over the * children of a dir. Thus, it should be treated as a temporary object, * and free as soon as possible. * * @return * 1 success, < 0 error * Possible errors: * ISO_NULL_POINTER, if dir or iter are NULL * ISO_OUT_OF_MEM * * @since 0.6.2 */ int iso_dir_get_children(const IsoDir *dir, IsoDirIter **iter); /** * Get the next child. * Take care that the node is owned by its parent, and will be unref() when * the parent is freed. If you want your own ref to it, call iso_node_ref() * on it. * * @return * 1 success, 0 if dir has no more elements, < 0 error * Possible errors: * ISO_NULL_POINTER, if node or iter are NULL * ISO_ERROR, on wrong iter usage, usual caused by modiying the * dir during iteration * * @since 0.6.2 */ int iso_dir_iter_next(IsoDirIter *iter, IsoNode **node); /** * Check if there're more children. * * @return * 1 dir has more elements, 0 no, < 0 error * Possible errors: * ISO_NULL_POINTER, if iter is NULL * * @since 0.6.2 */ int iso_dir_iter_has_next(IsoDirIter *iter); /** * Free a dir iterator. * * @since 0.6.2 */ void iso_dir_iter_free(IsoDirIter *iter); /** * Removes a child from a directory during an iteration, without freeing it. * It's like iso_node_take(), but to be used during a directory iteration. * The node removed will be the last returned by the iteration. * * If you call this function twice without calling iso_dir_iter_next between * them is not allowed and you will get an ISO_ERROR in second call. * * @return * 1 on succes, < 0 error * Possible errors: * ISO_NULL_POINTER, if iter is NULL * ISO_ERROR, on wrong iter usage, for example by call this before * iso_dir_iter_next. * * @since 0.6.2 */ int iso_dir_iter_take(IsoDirIter *iter); /** * Removes a child from a directory during an iteration and unref() it. * Like iso_node_remove(), but to be used during a directory iteration. * The node removed will be the one returned by the previous iteration. * * It is not allowed to call this function twice without calling * iso_dir_iter_next inbetween. * * @return * 1 on succes, < 0 error * Possible errors: * ISO_NULL_POINTER, if iter is NULL * ISO_ERROR, on wrong iter usage, for example by calling this before * iso_dir_iter_next. * * @since 0.6.2 */ int iso_dir_iter_remove(IsoDirIter *iter); /** * Removes a node by iso_node_remove() or iso_dir_iter_remove(). If the node * is a directory then the whole tree of nodes underneath is removed too. * * @param node * The node to be removed. * @param iter * If not NULL, then the node will be removed by iso_dir_iter_remove(iter) * else it will be removed by iso_node_remove(node). * @return * 1 is success, <0 indicates error * * @since 1.0.2 */ int iso_node_remove_tree(IsoNode *node, IsoDirIter *boss_iter); /** * @since 0.6.4 */ typedef struct iso_find_condition IsoFindCondition; /** * Create a new condition that checks if the node name matches the given * wildcard. * * @param wildcard * @result * The created IsoFindCondition, NULL on error. * * @since 0.6.4 */ IsoFindCondition *iso_new_find_conditions_name(const char *wildcard); /** * Create a new condition that checks the node mode against a mode mask. It * can be used to check both file type and permissions. * * For example: * * iso_new_find_conditions_mode(S_IFREG) : search for regular files * iso_new_find_conditions_mode(S_IFCHR | S_IWUSR) : search for character * devices where owner has write permissions. * * @param mask * Mode mask to AND against node mode. * @result * The created IsoFindCondition, NULL on error. * * @since 0.6.4 */ IsoFindCondition *iso_new_find_conditions_mode(mode_t mask); /** * Create a new condition that checks the node gid. * * @param gid * Desired Group Id. * @result * The created IsoFindCondition, NULL on error. * * @since 0.6.4 */ IsoFindCondition *iso_new_find_conditions_gid(gid_t gid); /** * Create a new condition that checks the node uid. * * @param uid * Desired User Id. * @result * The created IsoFindCondition, NULL on error. * * @since 0.6.4 */ IsoFindCondition *iso_new_find_conditions_uid(uid_t uid); /** * Possible comparison between IsoNode and given conditions. * * @since 0.6.4 */ enum iso_find_comparisons { ISO_FIND_COND_GREATER, ISO_FIND_COND_GREATER_OR_EQUAL, ISO_FIND_COND_EQUAL, ISO_FIND_COND_LESS, ISO_FIND_COND_LESS_OR_EQUAL }; /** * Create a new condition that checks the time of last access. * * @param time * Time to compare against IsoNode atime. * @param comparison * Comparison to be done between IsoNode atime and submitted time. * Note that ISO_FIND_COND_GREATER, for example, is true if the node * time is greater than the submitted time. * @result * The created IsoFindCondition, NULL on error. * * @since 0.6.4 */ IsoFindCondition *iso_new_find_conditions_atime(time_t time, enum iso_find_comparisons comparison); /** * Create a new condition that checks the time of last modification. * * @param time * Time to compare against IsoNode mtime. * @param comparison * Comparison to be done between IsoNode mtime and submitted time. * Note that ISO_FIND_COND_GREATER, for example, is true if the node * time is greater than the submitted time. * @result * The created IsoFindCondition, NULL on error. * * @since 0.6.4 */ IsoFindCondition *iso_new_find_conditions_mtime(time_t time, enum iso_find_comparisons comparison); /** * Create a new condition that checks the time of last status change. * * @param time * Time to compare against IsoNode ctime. * @param comparison * Comparison to be done between IsoNode ctime and submitted time. * Note that ISO_FIND_COND_GREATER, for example, is true if the node * time is greater than the submitted time. * @result * The created IsoFindCondition, NULL on error. * * @since 0.6.4 */ IsoFindCondition *iso_new_find_conditions_ctime(time_t time, enum iso_find_comparisons comparison); /** * Create a new condition that check if the two given conditions are * valid. * * @param a * @param b * IsoFindCondition to compare * @result * The created IsoFindCondition, NULL on error. * * @since 0.6.4 */ IsoFindCondition *iso_new_find_conditions_and(IsoFindCondition *a, IsoFindCondition *b); /** * Create a new condition that check if at least one the two given conditions * is valid. * * @param a * @param b * IsoFindCondition to compare * @result * The created IsoFindCondition, NULL on error. * * @since 0.6.4 */ IsoFindCondition *iso_new_find_conditions_or(IsoFindCondition *a, IsoFindCondition *b); /** * Create a new condition that check if the given conditions is false. * * @param negate * @result * The created IsoFindCondition, NULL on error. * * @since 0.6.4 */ IsoFindCondition *iso_new_find_conditions_not(IsoFindCondition *negate); /** * Find all directory children that match the given condition. * * @param dir * Directory where we will search children. * @param cond * Condition that the children must match in order to be returned. * It will be free together with the iterator. Remember to delete it * if this function return error. * @param iter * Iterator that returns only the children that match condition. * @return * 1 on success, < 0 on error * * @since 0.6.4 */ int iso_dir_find_children(IsoDir* dir, IsoFindCondition *cond, IsoDirIter **iter); /** * Get the destination of a node. * The returned string belongs to the node and must not be modified nor * freed. Use strdup if you really need your own copy. * * @since 0.6.2 */ const char *iso_symlink_get_dest(const IsoSymlink *link); /** * Set the destination of a link. * * @param opts * The option set to be manipulated * @param dest * New destination for the link. It must be a non-empty string, otherwise * this function doesn't modify previous destination. * @return * 1 on success, < 0 on error * * @since 0.6.2 */ int iso_symlink_set_dest(IsoSymlink *link, const char *dest); /** * Sets the order in which a node will be written on image. The data content * of files with high weight will be written to low block addresses. * * @param node * The node which weight will be changed. If it's a dir, this function * will change the weight of all its children. For nodes other that dirs * or regular files, this function has no effect. * @param w * The weight as a integer number, the greater this value is, the * closer from the begining of image the file will be written. * Default value at IsoNode creation is 0. * * @since 0.6.2 */ void iso_node_set_sort_weight(IsoNode *node, int w); /** * Get the sort weight of a file. * * @since 0.6.2 */ int iso_file_get_sort_weight(IsoFile *file); /** * Get the size of the file, in bytes * * @since 0.6.2 */ off_t iso_file_get_size(IsoFile *file); /** * Get the device id (major/minor numbers) of the given block or * character device file. The result is undefined for other kind * of special files, of first be sure iso_node_get_mode() returns either * S_IFBLK or S_IFCHR. * * @since 0.6.6 */ dev_t iso_special_get_dev(IsoSpecial *special); /** * Get the IsoStream that represents the contents of the given IsoFile. * The stream may be a filter stream which itself get its input from a * further stream. This may be inquired by iso_stream_get_input_stream(). * * If you iso_stream_open() the stream, iso_stream_close() it before * image generation begins. * * @return * The IsoStream. No extra ref is added, so the IsoStream belongs to the * IsoFile, and it may be freed together with it. Add your own ref with * iso_stream_ref() if you need it. * * @since 0.6.4 */ IsoStream *iso_file_get_stream(IsoFile *file); /** * Get the block lba of a file node, if it was imported from an old image. * * @param file * The file * @param lba * Will be filled with the kba * @param flag * Reserved for future usage, submit 0 * @return * 1 if lba is valid (file comes from old image and has only one section), * 0 if file was newly added, i.e. it does not come from an old image, * < 0 error, especially ISO_WRONG_ARG_VALUE if the file has more than * one file section. * * @since 0.6.4 * * @deprecated Use iso_file_get_old_image_sections(), as this function does * not work with multi-extend files. */ int iso_file_get_old_image_lba(IsoFile *file, uint32_t *lba, int flag); /** * Get the start addresses and the sizes of the data extents of a file node * if it was imported from an old image. * * @param file * The file * @param section_count * Returns the number of extent entries in sections array. * @param sections * Returns the array of file sections if section_count > 0. * In this case, apply free() to dispose it. * @param flag * Reserved for future usage, submit 0 * @return * 1 if there are valid extents (file comes from old image), * 0 if file was newly added, i.e. it does not come from an old image, * < 0 error * * @since 0.6.8 */ int iso_file_get_old_image_sections(IsoFile *file, int *section_count, struct iso_file_section **sections, int flag); /* * Like iso_file_get_old_image_lba(), but take an IsoNode. * * @return * 1 if lba is valid (file comes from old image), 0 if file was newly * added, i.e. it does not come from an old image, 2 node type has no * LBA (no regular file), < 0 error * * @since 0.6.4 */ int iso_node_get_old_image_lba(IsoNode *node, uint32_t *lba, int flag); /** * Add a new directory to the iso tree. Permissions, owner and hidden atts * are taken from parent, you can modify them later. * * @param image * The image object to which the new directory shall belong. * @param parent * The directory node where the new directory will be grafted in. * @param name * Name for the new directory. If truncation mode is set to 1, * an oversized name gets truncated before further processing. * If a node with same name already exists on parent, this function * fails with ISO_NODE_NAME_NOT_UNIQUE. * @param dir * place where to store a pointer to the newly created dir. No extra * ref is addded, so you will need to call iso_node_ref() if you really * need it. You can pass NULL in this parameter if you don't need the * pointer. * @return * number of nodes in parent if success, < 0 otherwise * Possible errors: * ISO_NULL_POINTER, if parent or name are NULL * ISO_NODE_NAME_NOT_UNIQUE, a node with same name already exists * ISO_OUT_OF_MEM * ISO_RR_NAME_TOO_LONG * * @since 1.4.2 */ int iso_image_add_new_dir(IsoImage *image, IsoDir *parent, const char *name, IsoDir **dir); /** * *** Deprecated *** * use iso_image_add_new_dir() instead * * Add a new directory to the iso tree without taking into respect name * truncation mode of an IsoImage. * For detailed description of parameters, see above iso_image_add_new_dir(). * * @param parent * the dir where the new directory will be created * @param name * name for the new dir. * @param dir * place where to store a pointer to the newly created dir.i * @return * number of nodes in parent if success, < 0 otherwise * Possible errors: * ISO_NULL_POINTER, if parent or name are NULL * ISO_NODE_NAME_NOT_UNIQUE, a node with same name already exists * ISO_OUT_OF_MEM * * @since 0.6.2 */ int iso_tree_add_new_dir(IsoDir *parent, const char *name, IsoDir **dir); /** * Add a new regular file to the iso tree. Permissions are set to 0444, * owner and hidden atts are taken from parent. You can modify any of them * later. * * @param image * The image object to which the new file shall belong. * @param parent * The directory node where the new directory will be grafted in. * @param name * Name for the new file. If truncation mode is set to 1, * an oversized name gets truncated before further processing. * If a node with same name already exists on parent, this function * fails with ISO_NODE_NAME_NOT_UNIQUE. * @param stream * IsoStream for the contents of the file. The reference will be taken * by the newly created file, you will need to take an extra ref to it * if you need it. * @param file * place where to store a pointer to the newly created file. No extra * ref is addded, so you will need to call iso_node_ref() if you really * need it. You can pass NULL in this parameter if you don't need the * pointer * @return * number of nodes in parent if success, < 0 otherwise * Possible errors: * ISO_NULL_POINTER, if parent, name or dest are NULL * ISO_NODE_NAME_NOT_UNIQUE, a node with same name already exists * ISO_OUT_OF_MEM * ISO_RR_NAME_TOO_LONG * * @since 1.4.2 */ int iso_image_add_new_file(IsoImage *image, IsoDir *parent, const char *name, IsoStream *stream, IsoFile **file); /** * *** Deprecated *** * use iso_image_add_new_file() instead * * Add a new regular file to the iso tree without taking into respect name * truncation mode of an IsoImage. * For detailed description of parameters, see above iso_image_add_new_file(). * * @param parent * the dir where the new file will be created * @param name * name for the new file. * @param stream * IsoStream for the contents of the file. * @param file * place where to store a pointer to the newly created file. * @return * number of nodes in parent if success, < 0 otherwise * Possible errors: * ISO_NULL_POINTER, if parent, name or dest are NULL * ISO_NODE_NAME_NOT_UNIQUE, a node with same name already exists * ISO_OUT_OF_MEM * * @since 0.6.4 */ int iso_tree_add_new_file(IsoDir *parent, const char *name, IsoStream *stream, IsoFile **file); /** * Create an IsoStream object from content which is stored in a dynamically * allocated memory buffer. The new stream will become owner of the buffer * and apply free() to it when the stream finally gets destroyed itself. * * @param buf * The dynamically allocated memory buffer with the stream content. * @parm size * The number of bytes which may be read from buf. * @param stream * Will return a reference to the newly created stream. * @return * ISO_SUCCESS or <0 for error. E.g. ISO_NULL_POINTER, ISO_OUT_OF_MEM. * * @since 1.0.0 */ int iso_memory_stream_new(unsigned char *buf, size_t size, IsoStream **stream); /** * Add a new symbolic link to the directory tree. Permissions are set to 0777, * owner and hidden atts are taken from parent. You can modify any of them * later. * * @param image * The image object to which the new directory shall belong. * @param parent * The directory node where the new symlink will be grafted in. * @param name * Name for the new symlink. If truncation mode is set to 1, * an oversized name gets truncated before further processing. * If a node with same name already exists on parent, this function * fails with ISO_NODE_NAME_NOT_UNIQUE. * @param dest * The destination path of the link. The components of this path are * not checked for being oversized. * @param link * Place where to store a pointer to the newly created link. No extra * ref is addded, so you will need to call iso_node_ref() if you really * need it. You can pass NULL in this parameter if you don't need the * pointer * @return * number of nodes in parent if success, < 0 otherwise * Possible errors: * ISO_NULL_POINTER, if parent, name or dest are NULL * ISO_NODE_NAME_NOT_UNIQUE, a node with same name already exists * ISO_OUT_OF_MEM * ISO_RR_NAME_TOO_LONG * * @since 1.4.2 */ int iso_image_add_new_symlink(IsoImage *image, IsoDir *parent, const char *name, const char *dest, IsoSymlink **link); /** * *** Deprecated *** * use iso_image_add_new_symlink() instead * * Add a new symlink to the directory tree without taking into respect name * truncation mode of an IsoImage. * For detailed description of parameters, see above * iso_image_add_new_isymlink(). * * @param parent * the dir where the new symlink will be created * @param name * name for the new symlink. * @param dest * destination of the link * @param link * place where to store a pointer to the newly created link. * @return * number of nodes in parent if success, < 0 otherwise * Possible errors: * ISO_NULL_POINTER, if parent, name or dest are NULL * ISO_NODE_NAME_NOT_UNIQUE, a node with same name already exists * ISO_OUT_OF_MEM * * @since 0.6.2 */ int iso_tree_add_new_symlink(IsoDir *parent, const char *name, const char *dest, IsoSymlink **link); /** * Add a new special file to the directory tree. As far as libisofs concerns, * a special file is a block device, a character device, a FIFO (named pipe) * or a socket. You can choose the specific kind of file you want to add * by setting mode propertly (see man 2 stat). * * Note that special files are only written to image when Rock Ridge * extensions are enabled. Moreover, a special file is just a directory entry * in the image tree, no data is written beyond that. * * Owner and hidden atts are taken from parent. You can modify any of them * later. * * @param image * The image object to which the new special file shall belong. * @param parent * The directory node where the new special file will be grafted in. * @param name * Name for the new special file. If truncation mode is set to 1, * an oversized name gets truncated before further processing. * If a node with same name already exists on parent, this function * fails with ISO_NODE_NAME_NOT_UNIQUE. * @param mode * File type and permissions for the new node. Note that only the file * types S_IFSOCK, S_IFBLK, S_IFCHR, and S_IFIFO are allowed. * S_IFLNK, S_IFREG, or S_IFDIR are not. * @param dev * Device ID, equivalent to the st_rdev field in man 2 stat. * @param special * Place where to store a pointer to the newly created special file. No * extra ref is addded, so you will need to call iso_node_ref() if you * really need it. You can pass NULL in this parameter if you don't need * the pointer. * @return * Number of nodes in parent if success, < 0 otherwise * Possible errors: * ISO_NULL_POINTER, if parent, name or dest are NULL * ISO_NODE_NAME_NOT_UNIQUE, a node with same name already exists * ISO_WRONG_ARG_VALUE if you select a incorrect mode * ISO_OUT_OF_MEM * ISO_RR_NAME_TOO_LONG * * @since 1.4.2 */ int iso_image_add_new_special(IsoImage *image, IsoDir *parent, const char *name, mode_t mode, dev_t dev, IsoSpecial **special); /** * *** Deprecated *** * use iso_image_add_new_special() instead * * Add a new special file to the directory tree without taking into respect name * truncation mode of an IsoImage. * For detailed description of parameters, see above * iso_image_add_new_special(). * * @param parent * the dir where the new special file will be created * @param name * name for the new special file. * @param mode * file type and permissions for the new node. * @param dev * device ID, equivalent to the st_rdev field in man 2 stat. * @param special * place where to store a pointer to the newly created special file. * @return * number of nodes in parent if success, < 0 otherwise * Possible errors: * ISO_NULL_POINTER, if parent, name or dest are NULL * ISO_NODE_NAME_NOT_UNIQUE, a node with same name already exists * ISO_WRONG_ARG_VALUE if you select a incorrect mode * ISO_OUT_OF_MEM * * @since 0.6.2 */ int iso_tree_add_new_special(IsoDir *parent, const char *name, mode_t mode, dev_t dev, IsoSpecial **special); /** * Set whether to follow or not symbolic links when added a file from a source * to IsoImage. Default behavior is to not follow symlinks. * * @since 0.6.2 */ void iso_tree_set_follow_symlinks(IsoImage *image, int follow); /** * Get current setting for follow_symlinks. * * @see iso_tree_set_follow_symlinks * @since 0.6.2 */ int iso_tree_get_follow_symlinks(IsoImage *image); /** * Set whether to skip or not disk files with names beginning by '.' * when adding a directory recursively. * Default behavior is to not ignore them. * * Clarification: This is not related to the IsoNode property to be hidden * in one or more of the resulting image trees as of * IsoHideNodeFlag and iso_node_set_hidden(). * * @since 0.6.2 */ void iso_tree_set_ignore_hidden(IsoImage *image, int skip); /** * Get current setting for ignore_hidden. * * @see iso_tree_set_ignore_hidden * @since 0.6.2 */ int iso_tree_get_ignore_hidden(IsoImage *image); /** * Set the replace mode, that defines the behavior of libisofs when adding * a node whit the same name that an existent one, during a recursive * directory addition. * * @since 0.6.2 */ void iso_tree_set_replace_mode(IsoImage *image, enum iso_replace_mode mode); /** * Get current setting for replace_mode. * * @see iso_tree_set_replace_mode * @since 0.6.2 */ enum iso_replace_mode iso_tree_get_replace_mode(IsoImage *image); /** * Set whether to skip or not special files. Default behavior is to not skip * them. Note that, despite of this setting, special files will never be added * to an image unless RR extensions were enabled. * * @param image * The image to manipulate. * @param skip * Bitmask to determine what kind of special files will be skipped: * bit0: ignore FIFOs * bit1: ignore Sockets * bit2: ignore char devices * bit3: ignore block devices * * @since 0.6.2 */ void iso_tree_set_ignore_special(IsoImage *image, int skip); /** * Get current setting for ignore_special. * * @see iso_tree_set_ignore_special * @since 0.6.2 */ int iso_tree_get_ignore_special(IsoImage *image); /** * Add a excluded path. These are paths that won't never added to image, and * will be excluded even when adding recursively its parent directory. * * For example, in * * iso_tree_add_exclude(image, "/home/user/data/private"); * iso_tree_add_dir_rec(image, root, "/home/user/data"); * * the directory /home/user/data/private won't be added to image. * * However, if you explicity add a deeper dir, it won't be excluded. i.e., * in the following example. * * iso_tree_add_exclude(image, "/home/user/data"); * iso_tree_add_dir_rec(image, root, "/home/user/data/private"); * * the directory /home/user/data/private is added. On the other, side, and * following the example above, * * iso_tree_add_dir_rec(image, root, "/home/user"); * * will exclude the directory "/home/user/data". * * Absolute paths are not mandatory, you can, for example, add a relative * path such as: * * iso_tree_add_exclude(image, "private"); * iso_tree_add_exclude(image, "user/data"); * * to exclude, respectively, all files or dirs named private, and also all * files or dirs named data that belong to a folder named "user". Note that the * above rule about deeper dirs is still valid. i.e., if you call * * iso_tree_add_dir_rec(image, root, "/home/user/data/music"); * * it is included even containing "user/data" string. However, a possible * "/home/user/data/music/user/data" is not added. * * Usual wildcards, such as * or ? are also supported, with the usual meaning * as stated in "man 7 glob". For example * * // to exclude backup text files * iso_tree_add_exclude(image, "*.~"); * * @return * 1 on success, < 0 on error * * @since 0.6.2 */ int iso_tree_add_exclude(IsoImage *image, const char *path); /** * Remove a previously added exclude. * * @see iso_tree_add_exclude * @return * 1 on success, 0 exclude do not exists, < 0 on error * * @since 0.6.2 */ int iso_tree_remove_exclude(IsoImage *image, const char *path); /** * Set a callback function that libisofs will call for each file that is * added to the given image by a recursive addition function. This includes * image import. * * @param image * The image to manipulate. * @param report * pointer to a function that will be called just before a file will be * added to the image. You can control whether the file will be in fact * added or ignored. * This function should return 1 to add the file, 0 to ignore it and * continue, < 0 to abort the process * NULL is allowed if you don't want any callback. * * @since 0.6.2 */ void iso_tree_set_report_callback(IsoImage *image, int (*report)(IsoImage*, IsoFileSource*)); /** * Add a new node to the image tree, from an existing file. * * TODO comment Builder and Filesystem related issues when exposing both * * All attributes will be taken from the source file. The appropriate file * type will be created. * * @param image * The image * @param parent * The directory in the image tree where the node will be added. * @param path * The absolute path of the file in the local filesystem. * The node will have the same leaf name as the file on disk, possibly * truncated according to iso_image_set_truncate_mode(). * Its directory path depends on the parent node. * @param node * place where to store a pointer to the newly added file. No * extra ref is addded, so you will need to call iso_node_ref() if you * really need it. You can pass NULL in this parameter if you don't need * the pointer. * @return * number of nodes in parent if success, < 0 otherwise * Possible errors: * ISO_NULL_POINTER, if image, parent or path are NULL * ISO_NODE_NAME_NOT_UNIQUE, a node with same name already exists * ISO_OUT_OF_MEM * ISO_RR_NAME_TOO_LONG * * @since 0.6.2 */ int iso_tree_add_node(IsoImage *image, IsoDir *parent, const char *path, IsoNode **node); /** * This is a more versatile form of iso_tree_add_node which allows to set * the node name in ISO image already when it gets added. * * Add a new node to the image tree, from an existing file, and with the * given name, that must not exist on dir. * * @param image * The image * @param parent * The directory in the image tree where the node will be added. * @param name * The leaf name that the node will have on image, possibly truncated * according to iso_image_set_truncate_mode(). * Its directory path depends on the parent node. * @param path * The absolute path of the file in the local filesystem. * @param node * place where to store a pointer to the newly added file. No * extra ref is addded, so you will need to call iso_node_ref() if you * really need it. You can pass NULL in this parameter if you don't need * the pointer. * @return * number of nodes in parent if success, < 0 otherwise * Possible errors: * ISO_NULL_POINTER, if image, parent or path are NULL * ISO_NODE_NAME_NOT_UNIQUE, a node with same name already exists * ISO_OUT_OF_MEM * ISO_RR_NAME_TOO_LONG * * @since 0.6.4 */ int iso_tree_add_new_node(IsoImage *image, IsoDir *parent, const char *name, const char *path, IsoNode **node); /** * Add a new node to the image tree with the given name that must not exist * on dir. The node data content will be a byte interval out of the data * content of a file in the local filesystem. * * @param image * The image * @param parent * The directory in the image tree where the node will be added. * @param name * The leaf name that the node will have on image, possibly truncated * according to iso_image_set_truncate_mode(). * Its directory path depends on the parent node. * @param path * The absolute path of the file in the local filesystem. For now * only regular files and symlinks to regular files are supported. * @param offset * Byte number in the given file from where to start reading data. * @param size * Max size of the file. This may be more than actually available from * byte offset to the end of the file in the local filesystem. * @param node * place where to store a pointer to the newly added file. No * extra ref is addded, so you will need to call iso_node_ref() if you * really need it. You can pass NULL in this parameter if you don't need * the pointer. * @return * number of nodes in parent if success, < 0 otherwise * Possible errors: * ISO_NULL_POINTER, if image, parent or path are NULL * ISO_NODE_NAME_NOT_UNIQUE, a node with same name already exists * ISO_OUT_OF_MEM * ISO_RR_NAME_TOO_LONG * * @since 0.6.4 */ int iso_tree_add_new_cut_out_node(IsoImage *image, IsoDir *parent, const char *name, const char *path, off_t offset, off_t size, IsoNode **node); /** * Create a copy of the given node under a different path. If the node is * actually a directory then clone its whole subtree. * This call may fail because an IsoFile is encountered which gets fed by an * IsoStream which cannot be cloned. See also IsoStream_Iface method * clone_stream(). * Surely clonable node types are: * IsoDir, * IsoSymlink, * IsoSpecial, * IsoFile from a loaded ISO image, * IsoFile referring to local filesystem files, * IsoFile created by iso_tree_add_new_file * from a stream created by iso_memory_stream_new(), * IsoFile created by iso_tree_add_new_cut_out_node() * Silently ignored are nodes of type IsoBoot. * An IsoFile node with IsoStream filters can be cloned if all those filters * are clonable and the node would be clonable without filter. * Clonable IsoStream filters are created by: * iso_file_add_zisofs_filter() * iso_file_add_gzip_filter() * iso_file_add_external_filter() * An IsoNode with extended information as of iso_node_add_xinfo() can only be * cloned if each of the iso_node_xinfo_func instances is associated to a * clone function. See iso_node_xinfo_make_clonable(). * All internally used classes of extended information are clonable. * * The IsoImage context defines a maximum permissible name length and a mode * how to react on oversized names. See iso_image_set_truncate_mode(). * * @param image * The image object to which the node belongs. * @param node * The node to be cloned. * @param new_parent * The existing directory node where to insert the cloned node. * @param new_name * The name for the cloned node. It must not yet exist in new_parent, * unless it is a directory and node is a directory and flag bit0 is set. * @param new_node * Will return a pointer (without reference) to the newly created clone. * @param flag * Bitfield for control purposes. Submit any undefined bits as 0. * bit0= Merge directories rather than returning ISO_NODE_NAME_NOT_UNIQUE. * This will not allow to overwrite any existing node. * Attributes of existing directories will not be overwritten. * bit1= issue warning in case of new_name truncation * @return * <0 means error, 1 = new node created, * 2 = if flag bit0 is set: new_node is a directory which already existed. * * @since 1.4.2 */ int iso_image_tree_clone(IsoImage *image, IsoNode *node, IsoDir *new_parent, char *new_name, IsoNode **new_node, int flag); /** * *** Deprecated *** * use iso_image_tree_clone() instead * * Create a copy of the given node under a different path without taking * into respect name truncation mode of an IsoImage. * * @param node * The node to be cloned. * @param new_parent * The existing directory node where to insert the cloned node. * @param new_name * The name for the cloned node. It must not yet exist in new_parent, * unless it is a directory and node is a directory and flag bit0 is set. * @param new_node * Will return a pointer (without reference) to the newly created clone. * @param flag * Bitfield for control purposes. Submit any undefined bits as 0. * bit0= Merge directories rather than returning ISO_NODE_NAME_NOT_UNIQUE. * This will not allow to overwrite any existing node. * Attributes of existing directories will not be overwritten. * @return * <0 means error, 1 = new node created, * 2 = if flag bit0 is set: new_node is a directory which already existed. * * @since 1.0.2 */ int iso_tree_clone(IsoNode *node, IsoDir *new_parent, char *new_name, IsoNode **new_node, int flag); /** * Add the contents of a dir to a given directory of the iso tree. * * There are several options to control what files are added or how they are * managed. Take a look at iso_tree_set_* functions to see diferent options * for recursive directory addition. * * TODO comment Builder and Filesystem related issues when exposing both * * @param image * The image to which the directory belongs. * @param parent * Directory on the image tree where to add the contents of the dir * @param dir * Path to a dir in the filesystem * @return * number of nodes in parent if success, < 0 otherwise * * @since 0.6.2 */ int iso_tree_add_dir_rec(IsoImage *image, IsoDir *parent, const char *dir); /** * Locate a node by its absolute path in the image. * The IsoImage context defines a maximum permissible name length and a mode * how to react on oversized names. See iso_image_set_truncate_mode(). * * @param image * The image to which the node belongs. * @param path * File path beginning at the root directory of image. If truncation mode * is set to 1, oversized path components will be truncated before lookup. * @param node * Location for a pointer to the node, it will be filled with NULL if the * given path does not exists on image. * The node will be owned by the image and shouldn't be unref(). Just call * iso_node_ref() to get your own reference to the node. * Note that you can pass NULL is the only thing you want to do is check * if a node with such path really exists. * * @return * 1 node found * 0 no truncation was needed, path not found in image * 2 truncation happened, truncated path component not found in parent dir * < 0 error, see iso_dir_get_node(). * * @since 1.4.2 */ int iso_image_path_to_node(IsoImage *image, const char *path, IsoNode **node); /** * *** Deprecated *** * In most cases use iso_image_path_to_node() instead * * Locate a node by its absolute path on image without taking into respect * name truncation mode of the image. * * @param image * The image to which the node belongs. * @param path * File path beginning at the root directory of image. No truncation will * happen. * @param node * Location for a pointer to the node, it will be filled with NULL if the * given path does not exists on image. See iso_image_path_to_node(). * @return * 1 found, 0 not found, < 0 error * * @since 0.6.2 */ int iso_tree_path_to_node(IsoImage *image, const char *path, IsoNode **node); /** * Get the absolute path on image of the given node. * * @return * The path on the image, that must be freed when no more needed. If the * given node is not added to any image, this returns NULL. * @since 0.6.4 */ char *iso_tree_get_node_path(IsoNode *node); /** * Get the destination node of a symbolic link within the IsoImage. * * @param img * The image wherein to try resolving the link. * @param sym * The symbolic link node which to resolve. * @param res * Will return the found destination node, in case of success. * Call iso_node_ref() / iso_node_unref() if you intend to use the node * over API calls which might in any event delete it. * @param depth * Prevents endless loops. Submit as 0. * @param flag * Bitfield for control purposes. Submit 0 for now. * @return * 1 on success, * < 0 on failure, especially ISO_DEEP_SYMLINK and ISO_DEAD_SYMLINK * * @since 1.2.4 */ int iso_tree_resolve_symlink(IsoImage *img, IsoSymlink *sym, IsoNode **res, int *depth, int flag); /* Maximum number link resolution steps before ISO_DEEP_SYMLINK gets * returned by iso_tree_resolve_symlink(). * * @since 1.2.4 */ #define LIBISO_MAX_LINK_DEPTH 100 /** * Increments the reference counting of the given IsoDataSource. * * @since 0.6.2 */ void iso_data_source_ref(IsoDataSource *src); /** * Decrements the reference counting of the given IsoDataSource, freeing it * if refcount reach 0. * * @since 0.6.2 */ void iso_data_source_unref(IsoDataSource *src); /** * Create a new IsoDataSource from a local file. This is suitable for * accessing regular files or block devices with ISO images. * * @param path * The absolute path of the file * @param src * Will be filled with the pointer to the newly created data source. * @return * 1 on success, < 0 on error. * * @since 0.6.2 */ int iso_data_source_new_from_file(const char *path, IsoDataSource **src); /** * Get the status of the buffer used by a burn_source. * * @param b * A burn_source previously obtained with * iso_image_create_burn_source(). * @param size * Will be filled with the total size of the buffer, in bytes * @param free_bytes * Will be filled with the bytes currently available in buffer * @return * < 0 error, > 0 state: * 1="active" : input and consumption are active * 2="ending" : input has ended without error * 3="failing" : input had error and ended, * 5="abandoned" : consumption has ended prematurely * 6="ended" : consumption has ended without input error * 7="aborted" : consumption has ended after input error * * @since 0.6.2 */ int iso_ring_buffer_get_status(struct burn_source *b, size_t *size, size_t *free_bytes); #define ISO_MSGS_MESSAGE_LEN 4096 /** * Control queueing and stderr printing of messages from libisofs. * Severity may be one of "NEVER", "FATAL", "SORRY", "WARNING", "HINT", * "NOTE", "UPDATE", "DEBUG", "ALL". * * @param queue_severity Gives the minimum limit for messages to be queued. * Default: "NEVER". If you queue messages then you * must consume them by iso_obtain_msgs(). * @param print_severity Does the same for messages to be printed directly * to stderr. * @param print_id A text prefix to be printed before the message. * @return >0 for success, <=0 for error * * @since 0.6.2 */ int iso_set_msgs_severities(char *queue_severity, char *print_severity, char *print_id); /** * Obtain the oldest pending libisofs message from the queue which has at * least the given minimum_severity. This message and any older message of * lower severity will get discarded from the queue and is then lost forever. * * Severity may be one of "NEVER", "FATAL", "SORRY", "WARNING", "HINT", * "NOTE", "UPDATE", "DEBUG", "ALL". To call with minimum_severity "NEVER" * will discard the whole queue. * * @param minimum_severity * Threshhold * @param error_code * Will become a unique error code as listed at the end of this header * @param imgid * Id of the image that was issued the message. * @param msg_text * Must provide at least ISO_MSGS_MESSAGE_LEN bytes. * @param severity * Will become the severity related to the message and should provide at * least 80 bytes. * @return * 1 if a matching item was found, 0 if not, <0 for severe errors * * @since 0.6.2 */ int iso_obtain_msgs(char *minimum_severity, int *error_code, int *imgid, char msg_text[], char severity[]); /** * Submit a message to the libisofs queueing system. It will be queued or * printed as if it was generated by libisofs itself. * * @param error_code * The unique error code of your message. * Submit 0 if you do not have reserved error codes within the libburnia * project. * @param msg_text * Not more than ISO_MSGS_MESSAGE_LEN characters of message text. * @param os_errno * Eventual errno related to the message. Submit 0 if the message is not * related to a operating system error. * @param severity * One of "ABORT", "FATAL", "FAILURE", "SORRY", "WARNING", "HINT", "NOTE", * "UPDATE", "DEBUG". Defaults to "FATAL". * @param origin * Submit 0 for now. * @return * 1 if message was delivered, <=0 if failure * * @since 0.6.4 */ int iso_msgs_submit(int error_code, char msg_text[], int os_errno, char severity[], int origin); /** * Convert a severity name into a severity number, which gives the severity * rank of the name. * * @param severity_name * A name as with iso_msgs_submit(), e.g. "SORRY". * @param severity_number * The rank number: the higher, the more severe. * @return * >0 success, <=0 failure * * @since 0.6.4 */ int iso_text_to_sev(char *severity_name, int *severity_number); /** * Convert a severity number into a severity name * * @param severity_number * The rank number: the higher, the more severe. * @param severity_name * A name as with iso_msgs_submit(), e.g. "SORRY". * * @since 0.6.4 */ int iso_sev_to_text(int severity_number, char **severity_name); /** * Get the id of an IsoImage, used for message reporting. This message id, * retrieved with iso_obtain_msgs(), can be used to distinguish what * IsoImage has isssued a given message. * * @since 0.6.2 */ int iso_image_get_msg_id(IsoImage *image); /** * Get a textual description of a libisofs error. * * @since 0.6.2 */ const char *iso_error_to_msg(int errcode); /** * Get the severity of a given error code * @return * 0x10000000 -> DEBUG * 0x20000000 -> UPDATE * 0x30000000 -> NOTE * 0x40000000 -> HINT * 0x50000000 -> WARNING * 0x60000000 -> SORRY * 0x64000000 -> MISHAP * 0x68000000 -> FAILURE * 0x70000000 -> FATAL * 0x71000000 -> ABORT * * @since 0.6.2 */ int iso_error_get_severity(int e); /** * Get the priority of a given error. * @return * 0x00000000 -> ZERO * 0x10000000 -> LOW * 0x20000000 -> MEDIUM * 0x30000000 -> HIGH * * @since 0.6.2 */ int iso_error_get_priority(int e); /** * Get the message queue code of a libisofs error. */ int iso_error_get_code(int e); /** * Set the minimum error severity that causes a libisofs operation to * be aborted as soon as possible. * * @param severity * one of "FAILURE", "MISHAP", "SORRY", "WARNING", "HINT", "NOTE". * Severities greater or equal than FAILURE always cause program to abort. * Severities under NOTE won't never cause function abort. * @return * Previous abort priority on success, < 0 on error. * * @since 0.6.2 */ int iso_set_abort_severity(char *severity); /** * Return the messenger object handle used by libisofs. This handle * may be used by related libraries to their own compatible * messenger objects and thus to direct their messages to the libisofs * message queue. See also: libburn, API function burn_set_messenger(). * * @return the handle. Do only use with compatible * * @since 0.6.2 */ void *iso_get_messenger(); /** * Take a ref to the given IsoFileSource. * * @since 0.6.2 */ void iso_file_source_ref(IsoFileSource *src); /** * Drop your ref to the given IsoFileSource, eventually freeing the associated * system resources. * * @since 0.6.2 */ void iso_file_source_unref(IsoFileSource *src); /* * this are just helpers to invoque methods in class */ /** * Get the absolute path in the filesystem this file source belongs to. * * @return * the path of the FileSource inside the filesystem, it should be * freed when no more needed. * * @since 0.6.2 */ char* iso_file_source_get_path(IsoFileSource *src); /** * Get the name of the file, with the dir component of the path. * * @return * the name of the file, it should be freed when no more needed. * * @since 0.6.2 */ char* iso_file_source_get_name(IsoFileSource *src); /** * Get information about the file. * @return * 1 success, < 0 error * Error codes: * ISO_FILE_ACCESS_DENIED * ISO_FILE_BAD_PATH * ISO_FILE_DOESNT_EXIST * ISO_OUT_OF_MEM * ISO_FILE_ERROR * ISO_NULL_POINTER * * @since 0.6.2 */ int iso_file_source_lstat(IsoFileSource *src, struct stat *info); /** * Check if the process has access to read file contents. Note that this * is not necessarily related with (l)stat functions. For example, in a * filesystem implementation to deal with an ISO image, if the user has * read access to the image it will be able to read all files inside it, * despite of the particular permission of each file in the RR tree, that * are what the above functions return. * * @return * 1 if process has read access, < 0 on error * Error codes: * ISO_FILE_ACCESS_DENIED * ISO_FILE_BAD_PATH * ISO_FILE_DOESNT_EXIST * ISO_OUT_OF_MEM * ISO_FILE_ERROR * ISO_NULL_POINTER * * @since 0.6.2 */ int iso_file_source_access(IsoFileSource *src); /** * Get information about the file. If the file is a symlink, the info * returned refers to the destination. * * @return * 1 success, < 0 error * Error codes: * ISO_FILE_ACCESS_DENIED * ISO_FILE_BAD_PATH * ISO_FILE_DOESNT_EXIST * ISO_OUT_OF_MEM * ISO_FILE_ERROR * ISO_NULL_POINTER * * @since 0.6.2 */ int iso_file_source_stat(IsoFileSource *src, struct stat *info); /** * Opens the source. * @return 1 on success, < 0 on error * Error codes: * ISO_FILE_ALREADY_OPENED * ISO_FILE_ACCESS_DENIED * ISO_FILE_BAD_PATH * ISO_FILE_DOESNT_EXIST * ISO_OUT_OF_MEM * ISO_FILE_ERROR * ISO_NULL_POINTER * * @since 0.6.2 */ int iso_file_source_open(IsoFileSource *src); /** * Close a previuously openned file * @return 1 on success, < 0 on error * Error codes: * ISO_FILE_ERROR * ISO_NULL_POINTER * ISO_FILE_NOT_OPENED * * @since 0.6.2 */ int iso_file_source_close(IsoFileSource *src); /** * Attempts to read up to count bytes from the given source into * the buffer starting at buf. * * The file src must be open() before calling this, and close() when no * more needed. Not valid for dirs. On symlinks it reads the destination * file. * * @param src * The given source * @param buf * Pointer to a buffer of at least count bytes where the read data will be * stored * @param count * Bytes to read * @return * number of bytes read, 0 if EOF, < 0 on error * Error codes: * ISO_FILE_ERROR * ISO_NULL_POINTER * ISO_FILE_NOT_OPENED * ISO_WRONG_ARG_VALUE -> if count == 0 * ISO_FILE_IS_DIR * ISO_OUT_OF_MEM * ISO_INTERRUPTED * * @since 0.6.2 */ int iso_file_source_read(IsoFileSource *src, void *buf, size_t count); /** * Repositions the offset of the given IsoFileSource (must be opened) to the * given offset according to the value of flag. * * @param src * The given source * @param offset * in bytes * @param flag * 0 The offset is set to offset bytes (SEEK_SET) * 1 The offset is set to its current location plus offset bytes * (SEEK_CUR) * 2 The offset is set to the size of the file plus offset bytes * (SEEK_END). * @return * Absolute offset posistion on the file, or < 0 on error. Cast the * returning value to int to get a valid libisofs error. * @since 0.6.4 */ off_t iso_file_source_lseek(IsoFileSource *src, off_t offset, int flag); /** * Read a directory. * * Each call to this function will return a new child, until we reach * the end of file (i.e, no more children), in that case it returns 0. * * The dir must be open() before calling this, and close() when no more * needed. Only valid for dirs. * * Note that "." and ".." children MUST NOT BE returned. * * @param src * The given source * @param child * pointer to be filled with the given child. Undefined on error or OEF * @return * 1 on success, 0 if EOF (no more children), < 0 on error * Error codes: * ISO_FILE_ERROR * ISO_NULL_POINTER * ISO_FILE_NOT_OPENED * ISO_FILE_IS_NOT_DIR * ISO_OUT_OF_MEM * * @since 0.6.2 */ int iso_file_source_readdir(IsoFileSource *src, IsoFileSource **child); /** * Read the destination of a symlink. You don't need to open the file * to call this. * * @param src * An IsoFileSource corresponding to a symbolic link. * @param buf * Allocated buffer of at least bufsiz bytes. * The destination string will be copied there, and it will be 0-terminated * if the return value indicates success or ISO_RR_PATH_TOO_LONG. * @param bufsiz * Maximum number of buf characters + 1. The string will be truncated if * it is larger than bufsiz - 1 and ISO_RR_PATH_TOO_LONG. will be returned. * @return * 1 on success, < 0 on error * Error codes: * ISO_FILE_ERROR * ISO_NULL_POINTER * ISO_WRONG_ARG_VALUE -> if bufsiz <= 0 * ISO_FILE_IS_NOT_SYMLINK * ISO_OUT_OF_MEM * ISO_FILE_BAD_PATH * ISO_FILE_DOESNT_EXIST * ISO_RR_PATH_TOO_LONG (@since 1.0.6) * * @since 0.6.2 */ int iso_file_source_readlink(IsoFileSource *src, char *buf, size_t bufsiz); /** * Get the AAIP string with encoded ACL and xattr. * (Not to be confused with ECMA-119 Extended Attributes). * @param src The file source object to be inquired. * @param aa_string Returns a pointer to the AAIP string data. If no AAIP * string is available, *aa_string becomes NULL. * (See doc/susp_aaip_2_0.txt for the meaning of AAIP.) * The caller is responsible for finally calling free() * on non-NULL results. * @param flag Bitfield for control purposes * bit0= Transfer ownership of AAIP string data. * src will free the eventual cached data and might * not be able to produce it again. * bit1= No need to get ACL (but no guarantee of exclusion) * bit2= No need to get xattr (but no guarantee of exclusion) * @return 1 means success (*aa_string == NULL is possible) * <0 means failure and must b a valid libisofs error code * (e.g. ISO_FILE_ERROR if no better one can be found). * @since 0.6.14 */ int iso_file_source_get_aa_string(IsoFileSource *src, unsigned char **aa_string, int flag); /** * Get the filesystem for this source. No extra ref is added, so you * musn't unref the IsoFilesystem. * * @return * The filesystem, NULL on error * * @since 0.6.2 */ IsoFilesystem* iso_file_source_get_filesystem(IsoFileSource *src); /** * Take a ref to the given IsoFilesystem * * @since 0.6.2 */ void iso_filesystem_ref(IsoFilesystem *fs); /** * Drop your ref to the given IsoFilesystem, evetually freeing associated * resources. * * @since 0.6.2 */ void iso_filesystem_unref(IsoFilesystem *fs); /** * Create a new IsoFilesystem to access a existent ISO image. * * @param src * Data source to access data. * @param opts * Image read options * @param msgid * An image identifer, obtained with iso_image_get_msg_id(), used to * associated messages issued by the filesystem implementation with an * existent image. If you are not using this filesystem in relation with * any image context, just use 0x1fffff as the value for this parameter. * @param fs * Will be filled with a pointer to the filesystem that can be used * to access image contents. * @param * 1 on success, < 0 on error * * @since 0.6.2 */ int iso_image_filesystem_new(IsoDataSource *src, IsoReadOpts *opts, int msgid, IsoImageFilesystem **fs); /** * Get the volset identifier for an existent image. The returned string belong * to the IsoImageFilesystem and shouldn't be free() nor modified. * * @since 0.6.2 */ const char *iso_image_fs_get_volset_id(IsoImageFilesystem *fs); /** * Get the volume identifier for an existent image. The returned string belong * to the IsoImageFilesystem and shouldn't be free() nor modified. * * @since 0.6.2 */ const char *iso_image_fs_get_volume_id(IsoImageFilesystem *fs); /** * Get the publisher identifier for an existent image. The returned string * belong to the IsoImageFilesystem and shouldn't be free() nor modified. * * @since 0.6.2 */ const char *iso_image_fs_get_publisher_id(IsoImageFilesystem *fs); /** * Get the data preparer identifier for an existent image. The returned string * belong to the IsoImageFilesystem and shouldn't be free() nor modified. * * @since 0.6.2 */ const char *iso_image_fs_get_data_preparer_id(IsoImageFilesystem *fs); /** * Get the system identifier for an existent image. The returned string belong * to the IsoImageFilesystem and shouldn't be free() nor modified. * * @since 0.6.2 */ const char *iso_image_fs_get_system_id(IsoImageFilesystem *fs); /** * Get the application identifier for an existent image. The returned string * belong to the IsoImageFilesystem and shouldn't be free() nor modified. * * @since 0.6.2 */ const char *iso_image_fs_get_application_id(IsoImageFilesystem *fs); /** * Get the copyright file identifier for an existent image. The returned string * belong to the IsoImageFilesystem and shouldn't be free() nor modified. * * @since 0.6.2 */ const char *iso_image_fs_get_copyright_file_id(IsoImageFilesystem *fs); /** * Get the abstract file identifier for an existent image. The returned string * belong to the IsoImageFilesystem and shouldn't be free() nor modified. * * @since 0.6.2 */ const char *iso_image_fs_get_abstract_file_id(IsoImageFilesystem *fs); /** * Get the biblio file identifier for an existent image. The returned string * belong to the IsoImageFilesystem and shouldn't be free() nor modified. * * @since 0.6.2 */ const char *iso_image_fs_get_biblio_file_id(IsoImageFilesystem *fs); /** * Increment reference count of an IsoStream. * * @since 0.6.4 */ void iso_stream_ref(IsoStream *stream); /** * Decrement reference count of an IsoStream, and eventually free it if * refcount reach 0. * * @since 0.6.4 */ void iso_stream_unref(IsoStream *stream); /** * Opens the given stream. Remember to close the Stream before writing the * image. * * @return * 1 on success, 2 file greater than expected, 3 file smaller than * expected, < 0 on error * * @since 0.6.4 */ int iso_stream_open(IsoStream *stream); /** * Close a previously openned IsoStream. * * @return * 1 on success, < 0 on error * * @since 0.6.4 */ int iso_stream_close(IsoStream *stream); /** * Get the size of a given stream. This function should always return the same * size, even if the underlying source size changes, unless you call * iso_stream_update_size(). * * @return * IsoStream size in bytes * * @since 0.6.4 */ off_t iso_stream_get_size(IsoStream *stream); /** * Attempts to read up to count bytes from the given stream into * the buffer starting at buf. * * The stream must be open() before calling this, and close() when no * more needed. * * @return * number of bytes read, 0 if EOF, < 0 on error * * @since 0.6.4 */ int iso_stream_read(IsoStream *stream, void *buf, size_t count); /** * Whether the given IsoStream can be read several times, with the same * results. * For example, a regular file is repeatable, you can read it as many * times as you want. However, a pipe isn't. * * This function doesn't take into account if the file has been modified * between the two reads. * * @return * 1 if stream is repeatable, 0 if not, < 0 on error * * @since 0.6.4 */ int iso_stream_is_repeatable(IsoStream *stream); /** * Updates the size of the IsoStream with the current size of the * underlying source. * * @return * 1 if ok, < 0 on error (has to be a valid libisofs error code), * 0 if the IsoStream does not support this function. * @since 0.6.8 */ int iso_stream_update_size(IsoStream *stream); /** * Get an unique identifier for a given IsoStream. * * @since 0.6.4 */ void iso_stream_get_id(IsoStream *stream, unsigned int *fs_id, dev_t *dev_id, ino_t *ino_id); /** * Try to get eventual source path string of a stream. Meaning and availability * of this string depends on the stream.class . Expect valid results with * types "fsrc" and "cout". Result formats are * fsrc: result of file_source_get_path() * cout: result of file_source_get_path() " " offset " " size * @param stream * The stream to be inquired. * @param flag * Bitfield for control purposes, unused yet, submit 0 * @return * A copy of the path string. Apply free() when no longer needed. * NULL if no path string is available. * * @since 0.6.18 */ char *iso_stream_get_source_path(IsoStream *stream, int flag); /** * Compare two streams whether they are based on the same input and will * produce the same output. If in any doubt, then this comparison will * indicate no match. * * @param s1 * The first stream to compare. * @param s2 * The second stream to compare. * @return * -1 if s1 is smaller s2 , 0 if s1 matches s2 , 1 if s1 is larger s2 * @param flag * bit0= do not use s1->class->cmp_ino() even if available * * @since 0.6.20 */ int iso_stream_cmp_ino(IsoStream *s1, IsoStream *s2, int flag); /** * Produce a copy of a stream. It must be possible to operate both stream * objects concurrently. The success of this function depends on the * existence of a IsoStream_Iface.clone_stream() method with the stream * and with its eventual subordinate streams. * See iso_tree_clone() for a list of surely clonable built-in streams. * * @param old_stream * The existing stream object to be copied * @param new_stream * Will return a pointer to the copy * @param flag * Bitfield for control purposes. Submit 0 for now. * @return * >0 means success * ISO_STREAM_NO_CLONE is issued if no .clone_stream() exists * other error return values < 0 may occur depending on kind of stream * * @since 1.0.2 */ int iso_stream_clone(IsoStream *old_stream, IsoStream **new_stream, int flag); /* --------------------------------- AAIP --------------------------------- */ /** * Function to identify and manage AAIP strings as xinfo of IsoNode. * * An AAIP string contains the Attribute List with the xattr and ACL of a node * in the image tree. It is formatted according to libisofs specification * AAIP-2.0 and ready to be written into the System Use Area or Continuation * Area of a directory entry in an ISO image. * * Applications are not supposed to manipulate AAIP strings directly. * They should rather make use of the appropriate iso_node_get_* and * iso_node_set_* calls. * * AAIP represents ACLs as xattr with empty name and AAIP-specific binary * content. Local filesystems may represent ACLs as xattr with names like * "system.posix_acl_access". libisofs does not interpret those local * xattr representations of ACL directly but rather uses the ACL interface of * the local system. By default the local xattr representations of ACL will * not become part of the AAIP Attribute List via iso_local_get_attrs() and * not be attached to local files via iso_local_set_attrs(). * * @since 0.6.14 */ int aaip_xinfo_func(void *data, int flag); /** * The iso_node_xinfo_cloner function which gets associated to aaip_xinfo_func * by iso_init() or iso_init_with_flag() via iso_node_xinfo_make_clonable(). * @since 1.0.2 */ int aaip_xinfo_cloner(void *old_data, void **new_data, int flag); /** * Get the eventual ACLs which are associated with the node. * The result will be in "long" text form as of man acl and acl_to_text(). * Call this function with flag bit15 to finally release the memory * occupied by an ACL inquiry. * * @param node * The node that is to be inquired. * @param access_text * Will return a pointer to the eventual "access" ACL text or NULL if it * is not available and flag bit 4 is set. * @param default_text * Will return a pointer to the eventual "default" ACL or NULL if it * is not available. * (GNU/Linux directories can have a "default" ACL which influences * the permissions of newly created files.) * @param flag * Bitfield for control purposes * bit4= if no "access" ACL is available: return *access_text == NULL * else: produce ACL from stat(2) permissions * bit15= free memory and return 1 (node may be NULL) * @return * 2 *access_text was produced from stat(2) permissions * 1 *access_text was produced from ACL of node * 0 if flag bit4 is set and no ACL is available * < 0 on error * * @since 0.6.14 */ int iso_node_get_acl_text(IsoNode *node, char **access_text, char **default_text, int flag); /** * Set the ACLs of the given node to the lists in parameters access_text and * default_text or delete them. * * The stat(2) permission bits get updated according to the new "access" ACL if * neither bit1 of parameter flag is set nor parameter access_text is NULL. * Note that S_IRWXG permission bits correspond to ACL mask permissions * if a "mask::" entry exists in the ACL. Only if there is no "mask::" then * the "group::" entry corresponds to to S_IRWXG. * * @param node * The node that is to be manipulated. * @param access_text * The text to be set into effect as "access" ACL. NULL will delete an * eventually existing "access" ACL of the node. * @param default_text * The text to be set into effect as "default" ACL. NULL will delete an * eventually existing "default" ACL of the node. * (GNU/Linux directories can have a "default" ACL which influences * the permissions of newly created files.) * @param flag * Bitfield for control purposes * bit1= ignore text parameters but rather update eventual "access" ACL * to the stat(2) permissions of node. If no "access" ACL exists, * then do nothing and return success. * @return * > 0 success * < 0 failure * * @since 0.6.14 */ int iso_node_set_acl_text(IsoNode *node, char *access_text, char *default_text, int flag); /** * Like iso_node_get_permissions but reflecting ACL entry "group::" in S_IRWXG * rather than ACL entry "mask::". This is necessary if the permissions of a * node with ACL shall be restored to a filesystem without restoring the ACL. * The same mapping happens internally when the ACL of a node is deleted. * If the node has no ACL then the result is iso_node_get_permissions(node). * @param node * The node that is to be inquired. * @return * Permission bits as of stat(2) * * @since 0.6.14 */ mode_t iso_node_get_perms_wo_acl(const IsoNode *node); /** * Get the list of xattr which is associated with the node. * The resulting data may finally be disposed by a call to this function * with flag bit15 set, or its components may be freed one-by-one. * The following values are either NULL or malloc() memory: * *names, *value_lengths, *values, (*names)[i], (*values)[i] * with 0 <= i < *num_attrs. * It is allowed to replace or reallocate those memory items in order to * to manipulate the attribute list before submitting it to other calls. * * If enabled by flag bit0, this list possibly includes the ACLs of the node. * They are eventually encoded in a pair with empty name. It is not advisable * to alter the value or name of that pair. One may decide to erase both ACLs * by deleting this pair or to copy both ACLs by copying the content of this * pair to an empty named pair of another node. * For all other ACL purposes use iso_node_get_acl_text(). * * @param node * The node that is to be inquired. * @param num_attrs * Will return the number of name-value pairs * @param names * Will return an array of pointers to 0-terminated names * @param value_lengths * Will return an arry with the lenghts of values * @param values * Will return an array of pointers to strings of 8-bit bytes * @param flag * Bitfield for control purposes * bit0= obtain eventual ACLs as attribute with empty name * bit2= with bit0: do not obtain attributes other than ACLs * bit15= free memory (node may be NULL) * @return * 1 = ok (but *num_attrs may be 0) * < 0 = error * * @since 0.6.14 */ int iso_node_get_attrs(IsoNode *node, size_t *num_attrs, char ***names, size_t **value_lengths, char ***values, int flag); /** * Obtain the value of a particular xattr name. Eventually make a copy of * that value and add a trailing 0 byte for caller convenience. * @param node * The node that is to be inquired. * @param name * The xattr name that shall be looked up. * @param value_length * Will return the lenght of value * @param value * Will return a string of 8-bit bytes. free() it when no longer needed. * @param flag * Bitfield for control purposes, unused yet, submit 0 * @return * 1= name found , 0= name not found , <0 indicates error * * @since 0.6.18 */ int iso_node_lookup_attr(IsoNode *node, char *name, size_t *value_length, char **value, int flag); /** * Set the list of xattr which is associated with the node. * The data get copied so that you may dispose your input data afterwards. * * If enabled by flag bit0 then the submitted list of attributes will not only * overwrite xattr but also both eventual ACLs of the node. Eventual ACL in * the submitted list have to reside in an attribute with empty name. * * @param node * The node that is to be manipulated. * @param num_attrs * Number of attributes * @param names * Array of pointers to 0 terminated name strings * @param value_lengths * Array of byte lengths for each value * @param values * Array of pointers to the value bytes * @param flag * Bitfield for control purposes * bit0= Do not maintain eventual existing ACL of the node. * Set eventual new ACL from value of empty name. * bit1= Do not clear the existing attribute list but merge it with * the list given by this call. * The given values override the values of their eventually existing * names. If no xattr with a given name exists, then it will be * added as new xattr. So this bit can be used to set a single * xattr without inquiring any other xattr of the node. * bit2= Delete the attributes with the given names * bit3= Allow to affect non-user attributes. * I.e. those with a non-empty name which does not begin by "user." * (The empty name is always allowed and governed by bit0.) This * deletes all previously existing attributes if not bit1 is set. * bit4= Do not affect attributes from namespace "isofs". * To be combined with bit3 for copying attributes from local * filesystem to ISO image. * @since 1.2.4 * @return * 1 = ok * < 0 = error * * @since 0.6.14 */ int iso_node_set_attrs(IsoNode *node, size_t num_attrs, char **names, size_t *value_lengths, char **values, int flag); /* ----- This is an interface to ACL and xattr of the local filesystem ----- */ /** * libisofs has an internal system dependent adapter to ACL and xattr * operations. For the sake of completeness and simplicity it exposes this * functionality to its applications which might want to get and set ACLs * from local files. */ /** * Inquire whether local filesystem operations with ACL or xattr are enabled * inside libisofs. They may be disabled because of compile time decisions. * E.g. because the operating system does not support these features or * because libisofs has not yet an adapter to use them. * * @param flag * Bitfield for control purposes * bit0= inquire availability of ACL * bit1= inquire availability of xattr * bit2 - bit7= Reserved for future types. * It is permissibile to set them to 1 already now. * bit8 and higher: reserved, submit 0 * @return * Bitfield corresponding to flag. * bit0= ACL adapter is enabled * bit1= xattr adapter is enabled * bit2 - bit7= Reserved for future types. * bit8 and higher: reserved, do not interpret these * * @since 1.1.6 */ int iso_local_attr_support(int flag); /** * Get an ACL of the given file in the local filesystem in long text form. * * @param disk_path * Absolute path to the file * @param text * Will return a pointer to the ACL text. If not NULL the text will be * 0 terminated and finally has to be disposed by a call to this function * with bit15 set. * @param flag * Bitfield for control purposes * bit0= get "default" ACL rather than "access" ACL * bit4= set *text = NULL and return 2 * if the ACL matches st_mode permissions. * bit5= in case of symbolic link: inquire link target * bit15= free text and return 1 * @return * 1 ok * 2 ok, trivial ACL found while bit4 is set, *text is NULL * 0 no ACL manipulation adapter available / ACL not supported on fs * -1 failure of system ACL service (see errno) * -2 attempt to inquire ACL of a symbolic link without bit4 or bit5 * or with no suitable link target * * @since 0.6.14 */ int iso_local_get_acl_text(char *disk_path, char **text, int flag); /** * Set the ACL of the given file in the local filesystem to a given list * in long text form. * * @param disk_path * Absolute path to the file * @param text * The input text (0 terminated, ACL long text form) * @param flag * Bitfield for control purposes * bit0= set "default" ACL rather than "access" ACL * bit5= in case of symbolic link: manipulate link target * @return * > 0 ok * 0 no ACL manipulation adapter available for desired ACL type * -1 failure of system ACL service (see errno) * -2 attempt to manipulate ACL of a symbolic link without bit5 * or with no suitable link target * * @since 0.6.14 */ int iso_local_set_acl_text(char *disk_path, char *text, int flag); /** * Obtain permissions of a file in the local filesystem which shall reflect * ACL entry "group::" in S_IRWXG rather than ACL entry "mask::". This is * necessary if the permissions of a disk file with ACL shall be copied to * an object which has no ACL. * @param disk_path * Absolute path to the local file which may have an "access" ACL or not. * @param flag * Bitfield for control purposes * bit5= in case of symbolic link: inquire link target * @param st_mode * Returns permission bits as of stat(2) * @return * 1 success * -1 failure of lstat() or stat() (see errno) * * @since 0.6.14 */ int iso_local_get_perms_wo_acl(char *disk_path, mode_t *st_mode, int flag); /** * Get xattr and non-trivial ACLs of the given file in the local filesystem. * The resulting data has finally to be disposed by a call to this function * with flag bit15 set. * * Eventual ACLs will get encoded as attribute pair with empty name if this is * enabled by flag bit0. An ACL which simply replects stat(2) permissions * will not be put into the result. * * @param disk_path * Absolute path to the file * @param num_attrs * Will return the number of name-value pairs * @param names * Will return an array of pointers to 0-terminated names * @param value_lengths * Will return an arry with the lenghts of values * @param values * Will return an array of pointers to 8-bit values * @param flag * Bitfield for control purposes * bit0= obtain eventual ACLs as attribute with empty name * bit2= do not obtain attributes other than ACLs * bit3= do not ignore eventual non-user attributes. * I.e. those with a name which does not begin by "user." * bit5= in case of symbolic link: inquire link target * bit15= free memory * @return * 1 ok * < 0 failure * * @since 0.6.14 */ int iso_local_get_attrs(char *disk_path, size_t *num_attrs, char ***names, size_t **value_lengths, char ***values, int flag); /** * Attach a list of xattr and ACLs to the given file in the local filesystem. * * Eventual ACLs have to be encoded as attribute pair with empty name. * * @param disk_path * Absolute path to the file * @param num_attrs * Number of attributes * @param names * Array of pointers to 0 terminated name strings * @param value_lengths * Array of byte lengths for each attribute payload * @param values * Array of pointers to the attribute payload bytes * @param flag * Bitfield for control purposes * bit0= do not attach ACLs from an eventual attribute with empty name * bit3= do not ignore eventual non-user attributes. * I.e. those with a name which does not begin by "user." * bit5= in case of symbolic link: manipulate link target * bit6= @since 1.1.6 tolerate inappropriate presence or absence of * directory "default" ACL * @return * 1 = ok * < 0 = error * * @since 0.6.14 */ int iso_local_set_attrs(char *disk_path, size_t num_attrs, char **names, size_t *value_lengths, char **values, int flag); /* Default in case that the compile environment has no macro PATH_MAX. */ #define Libisofs_default_path_maX 4096 /* --------------------------- Filters in General -------------------------- */ /* * A filter is an IsoStream which uses another IsoStream as input. It gets * attached to an IsoFile by specialized calls iso_file_add_*_filter() which * replace its current IsoStream by the filter stream which takes over the * current IsoStream as input. * The consequences are: * iso_file_get_stream() will return the filter stream. * iso_stream_get_size() will return the (cached) size of the filtered data, * iso_stream_open() will start eventual child processes, * iso_stream_close() will kill eventual child processes, * iso_stream_read() will return filtered data. E.g. as data file content * during ISO image generation. * * There are external filters which run child processes * iso_file_add_external_filter() * and internal filters * iso_file_add_zisofs_filter() * iso_file_add_gzip_filter() * which may or may not be available depending on compile time settings and * installed software packages like libz. * * During image generation filters get not in effect if the original IsoStream * is an "fsrc" stream based on a file in the loaded ISO image and if the * image generation type is set to 1 by iso_write_opts_set_appendable(). */ /** * Delete the top filter stream from a data file. This is the most recent one * which was added by iso_file_add_*_filter(). * Caution: One should not do this while the IsoStream of the file is opened. * For now there is no general way to determine this state. * Filter stream implementations are urged to eventually call .close() * inside method .free() . This will close the input stream too. * @param file * The data file node which shall get rid of one layer of content * filtering. * @param flag * Bitfield for control purposes, unused yet, submit 0. * @return * 1 on success, 0 if no filter was present * <0 on error * * @since 0.6.18 */ int iso_file_remove_filter(IsoFile *file, int flag); /** * Obtain the eventual input stream of a filter stream. * @param stream * The eventual filter stream to be inquired. * @param flag * Bitfield for control purposes. * bit0= Follow the chain of input streams and return the one at the * end of the chain. * @since 1.3.2 * @return * The input stream, if one exists. Elsewise NULL. * No extra reference to the stream is taken by this call. * * @since 0.6.18 */ IsoStream *iso_stream_get_input_stream(IsoStream *stream, int flag); /* ---------------------------- External Filters --------------------------- */ /** * Representation of an external program that shall serve as filter for * an IsoStream. This object may be shared among many IsoStream objects. * It is to be created and disposed by the application. * * The filter will act as proxy between the original IsoStream of an IsoFile. * Up to completed image generation it will be run at least twice: * for IsoStream.class.get_size() and for .open() with subsequent .read(). * So the original IsoStream has to return 1 by its .class.is_repeatable(). * The filter program has to be repeateable too. I.e. it must produce the same * output on the same input. * * @since 0.6.18 */ struct iso_external_filter_command { /* Will indicate future extensions. It has to be 0 for now. */ int version; /* Tells how many IsoStream objects depend on this command object. * One may only dispose an IsoExternalFilterCommand when this count is 0. * Initially this value has to be 0. */ int refcount; /* An optional instance id. * Set to empty text if no individual name for this object is intended. */ char *name; /* Absolute local filesystem path to the executable program. */ char *path; /* Tells the number of arguments. */ int argc; /* NULL terminated list suitable for system call execv(3). * I.e. argv[0] points to the alleged program name, * argv[1] to argv[argc] point to program arguments (if argc > 0) * argv[argc+1] is NULL */ char **argv; /* A bit field which controls behavior variations: * bit0= Do not install filter if the input has size 0. * bit1= Do not install filter if the output is not smaller than the input. * bit2= Do not install filter if the number of output blocks is * not smaller than the number of input blocks. Block size is 2048. * Assume that non-empty input yields non-empty output and thus do * not attempt to attach a filter to files smaller than 2049 bytes. * bit3= suffix removed rather than added. * (Removal and adding suffixes is the task of the application. * This behavior bit serves only as reminder for the application.) */ int behavior; /* The eventual suffix which is supposed to be added to the IsoFile name * or to be removed from the name. * (This is to be done by the application, not by calls * iso_file_add_external_filter() or iso_file_remove_filter(). * The value recorded here serves only as reminder for the application.) */ char *suffix; }; typedef struct iso_external_filter_command IsoExternalFilterCommand; /** * Install an external filter command on top of the content stream of a data * file. The filter process must be repeatable. It will be run once by this * call in order to cache the output size. * @param file * The data file node which shall show filtered content. * @param cmd * The external program and its arguments which shall do the filtering. * @param flag * Bitfield for control purposes, unused yet, submit 0. * @return * 1 on success, 2 if filter installation revoked (e.g. cmd.behavior bit1) * <0 on error * * @since 0.6.18 */ int iso_file_add_external_filter(IsoFile *file, IsoExternalFilterCommand *cmd, int flag); /** * Obtain the IsoExternalFilterCommand which is eventually associated with the * given stream. (Typically obtained from an IsoFile by iso_file_get_stream() * or from an IsoStream by iso_stream_get_input_stream()). * @param stream * The stream to be inquired. * @param cmd * Will return the external IsoExternalFilterCommand. Valid only if * the call returns 1. This does not increment cmd->refcount. * @param flag * Bitfield for control purposes, unused yet, submit 0. * @return * 1 on success, 0 if the stream is not an external filter * <0 on error * * @since 0.6.18 */ int iso_stream_get_external_filter(IsoStream *stream, IsoExternalFilterCommand **cmd, int flag); /* ---------------------------- Internal Filters --------------------------- */ /** * Install a zisofs filter on top of the content stream of a data file. * zisofs is a compression format which is decompressed by some Linux kernels. * See also doc/zisofs_format.txt . * The filter will not be installed if its output size is not smaller than * the size of the input stream. * This is only enabled if the use of libz was enabled at compile time. * @param file * The data file node which shall show filtered content. * @param flag * Bitfield for control purposes * bit0= Do not install filter if the number of output blocks is * not smaller than the number of input blocks. Block size is 2048. * bit1= Install a decompression filter rather than one for compression. * bit2= Only inquire availability of zisofs filtering. file may be NULL. * If available return 2, else return error. * bit3= is reserved for internal use and will be forced to 0 * @return * 1 on success, 2 if filter available but installation revoked * <0 on error, e.g. ISO_ZLIB_NOT_ENABLED * * @since 0.6.18 */ int iso_file_add_zisofs_filter(IsoFile *file, int flag); /** * Inquire the number of zisofs compression and uncompression filters which * are in use. * @param ziso_count * Will return the number of currently installed compression filters. * @param osiz_count * Will return the number of currently installed uncompression filters. * @param flag * Bitfield for control purposes, unused yet, submit 0 * @return * 1 on success, <0 on error * * @since 0.6.18 */ int iso_zisofs_get_refcounts(off_t *ziso_count, off_t *osiz_count, int flag); /** * Parameter set for iso_zisofs_set_params(). * * @since 0.6.18 */ struct iso_zisofs_ctrl { /* Set to 0 for this version of the structure */ int version; /* Compression level for zlib function compress2(). From : * "between 0 and 9: * 1 gives best speed, 9 gives best compression, 0 gives no compression" * Default is 6. */ int compression_level; /* Log2 of the block size for compression filters. Allowed values are: * 15 = 32 kiB , 16 = 64 kiB , 17 = 128 kiB */ uint8_t block_size_log2; }; /** * Set the global parameters for zisofs filtering. * This is only allowed while no zisofs compression filters are installed. * i.e. ziso_count returned by iso_zisofs_get_refcounts() has to be 0. * @param params * Pointer to a structure with the intended settings. * @param flag * Bitfield for control purposes, unused yet, submit 0 * @return * 1 on success, <0 on error * * @since 0.6.18 */ int iso_zisofs_set_params(struct iso_zisofs_ctrl *params, int flag); /** * Get the current global parameters for zisofs filtering. * @param params * Pointer to a caller provided structure which shall take the settings. * @param flag * Bitfield for control purposes, unused yet, submit 0 * @return * 1 on success, <0 on error * * @since 0.6.18 */ int iso_zisofs_get_params(struct iso_zisofs_ctrl *params, int flag); /** * Check for the given node or for its subtree whether the data file content * effectively bears zisofs file headers and eventually mark the outcome * by an xinfo data record if not already marked by a zisofs compressor filter. * This does not install any filter but only a hint for image generation * that the already compressed files shall get written with zisofs ZF entries. * Use this if you insert the compressed reults of program mkzftree from disk * into the image. * @param node * The node which shall be checked and eventually marked. * @param flag * Bitfield for control purposes, unused yet, submit 0 * bit0= prepare for a run with iso_write_opts_set_appendable(,1). * Take into account that files from the imported image * do not get their content filtered. * bit1= permission to overwrite existing zisofs_zf_info * bit2= if no zisofs header is found: * create xinfo with parameters which indicate no zisofs * bit3= no tree recursion if node is a directory * bit4= skip files which stem from the imported image * @return * 0= no zisofs data found * 1= zf xinfo added * 2= found existing zf xinfo and flag bit1 was not set * 3= both encountered: 1 and 2 * <0 means error * * @since 0.6.18 */ int iso_node_zf_by_magic(IsoNode *node, int flag); /** * Install a gzip or gunzip filter on top of the content stream of a data file. * gzip is a compression format which is used by programs gzip and gunzip. * The filter will not be installed if its output size is not smaller than * the size of the input stream. * This is only enabled if the use of libz was enabled at compile time. * @param file * The data file node which shall show filtered content. * @param flag * Bitfield for control purposes * bit0= Do not install filter if the number of output blocks is * not smaller than the number of input blocks. Block size is 2048. * bit1= Install a decompression filter rather than one for compression. * bit2= Only inquire availability of gzip filtering. file may be NULL. * If available return 2, else return error. * bit3= is reserved for internal use and will be forced to 0 * @return * 1 on success, 2 if filter available but installation revoked * <0 on error, e.g. ISO_ZLIB_NOT_ENABLED * * @since 0.6.18 */ int iso_file_add_gzip_filter(IsoFile *file, int flag); /** * Inquire the number of gzip compression and uncompression filters which * are in use. * @param gzip_count * Will return the number of currently installed compression filters. * @param gunzip_count * Will return the number of currently installed uncompression filters. * @param flag * Bitfield for control purposes, unused yet, submit 0 * @return * 1 on success, <0 on error * * @since 0.6.18 */ int iso_gzip_get_refcounts(off_t *gzip_count, off_t *gunzip_count, int flag); /* ---------------------------- MD5 Checksums --------------------------- */ /* Production and loading of MD5 checksums is controlled by calls iso_write_opts_set_record_md5() and iso_read_opts_set_no_md5(). For data representation details see doc/checksums.txt . */ /** * Eventually obtain the recorded MD5 checksum of the session which was * loaded as ISO image. Such a checksum may be stored together with others * in a contiguous array at the end of the session. The session checksum * covers the data blocks from address start_lba to address end_lba - 1. * It does not cover the recorded array of md5 checksums. * Layout, size, and position of the checksum array is recorded in the xattr * "isofs.ca" of the session root node. * @param image * The image to inquire * @param start_lba * Eventually returns the first block address covered by md5 * @param end_lba * Eventually returns the first block address not covered by md5 any more * @param md5 * Eventually returns 16 byte of MD5 checksum * @param flag * Bitfield for control purposes, unused yet, submit 0 * @return * 1= md5 found , 0= no md5 available , <0 indicates error * * @since 0.6.22 */ int iso_image_get_session_md5(IsoImage *image, uint32_t *start_lba, uint32_t *end_lba, char md5[16], int flag); /** * Eventually obtain the recorded MD5 checksum of a data file from the loaded * ISO image. Such a checksum may be stored with others in a contiguous * array at the end of the loaded session. The data file eventually has an * xattr "isofs.cx" which gives the index in that array. * @param image * The image from which file stems. * @param file * The file object to inquire * @param md5 * Eventually returns 16 byte of MD5 checksum * @param flag * Bitfield for control purposes * bit0= only determine return value, do not touch parameter md5 * @return * 1= md5 found , 0= no md5 available , <0 indicates error * * @since 0.6.22 */ int iso_file_get_md5(IsoImage *image, IsoFile *file, char md5[16], int flag); /** * Read the content of an IsoFile object, compute its MD5 and attach it to * the IsoFile. It can then be inquired by iso_file_get_md5() and will get * written into the next session if this is enabled at write time and if the * image write process does not compute an MD5 from content which it copies. * So this call can be used to equip nodes from the old image with checksums * or to make available checksums of newly added files before the session gets * written. * @param file * The file object to read data from and to which to attach the checksum. * If the file is from the imported image, then its most original stream * will be checksummed. Else the eventual filter streams will get into * effect. * @param flag * Bitfield for control purposes. Unused yet. Submit 0. * @return * 1= ok, MD5 is computed and attached , <0 indicates error * * @since 0.6.22 */ int iso_file_make_md5(IsoFile *file, int flag); /** * Check a data block whether it is a libisofs session checksum tag and * eventually obtain its recorded parameters. These tags get written after * volume descriptors, directory tree and checksum array and can be detected * without loading the image tree. * One may start reading and computing MD5 at the suspected image session * start and look out for a session tag on the fly. See doc/checksum.txt . * @param data * A complete and aligned data block read from an ISO image session. * @param tag_type * 0= no tag * 1= session tag * 2= superblock tag * 3= tree tag * 4= relocated 64 kB superblock tag (at LBA 0 of overwriteable media) * @param pos * Returns the LBA where the tag supposes itself to be stored. * If this does not match the data block LBA then the tag might be * image data payload and should be ignored for image checksumming. * @param range_start * Returns the block address where the session is supposed to start. * If this does not match the session start on media then the image * volume descriptors have been been relocated. * A proper checksum will only emerge if computing started at range_start. * @param range_size * Returns the number of blocks beginning at range_start which are * covered by parameter md5. * @param next_tag * Returns the predicted block address of the next tag. * next_tag is valid only if not 0 and only with return values 2, 3, 4. * With tag types 2 and 3, reading shall go on sequentially and the MD5 * computation shall continue up to that address. * With tag type 4, reading shall resume either at LBA 32 for the first * session or at the given address for the session which is to be loaded * by default. In both cases the MD5 computation shall be re-started from * scratch. * @param md5 * Returns 16 byte of MD5 checksum. * @param flag * Bitfield for control purposes: * bit0-bit7= tag type being looked for * 0= any checksum tag * 1= session tag * 2= superblock tag * 3= tree tag * 4= relocated superblock tag * @return * 0= not a checksum tag, return parameters are invalid * 1= checksum tag found, return parameters are valid * <0= error * (return parameters are valid with error ISO_MD5_AREA_CORRUPTED * but not trustworthy because the tag seems corrupted) * * @since 0.6.22 */ int iso_util_decode_md5_tag(char data[2048], int *tag_type, uint32_t *pos, uint32_t *range_start, uint32_t *range_size, uint32_t *next_tag, char md5[16], int flag); /* The following functions allow to do own MD5 computations. E.g for comparing the result with a recorded checksum. */ /** * Create a MD5 computation context and hand out an opaque handle. * * @param md5_context * Returns the opaque handle. Submitted *md5_context must be NULL or * point to freeable memory. * @return * 1= success , <0 indicates error * * @since 0.6.22 */ int iso_md5_start(void **md5_context); /** * Advance the computation of a MD5 checksum by a chunk of data bytes. * * @param md5_context * An opaque handle once returned by iso_md5_start() or iso_md5_clone(). * @param data * The bytes which shall be processed into to the checksum. * @param datalen * The number of bytes to be processed. * @return * 1= success , <0 indicates error * * @since 0.6.22 */ int iso_md5_compute(void *md5_context, char *data, int datalen); /** * Create a MD5 computation context as clone of an existing one. One may call * iso_md5_clone(old, &new, 0) and then iso_md5_end(&new, result, 0) in order * to obtain an intermediate MD5 sum before the computation goes on. * * @param old_md5_context * An opaque handle once returned by iso_md5_start() or iso_md5_clone(). * @param new_md5_context * Returns the opaque handle to the new MD5 context. Submitted * *md5_context must be NULL or point to freeable memory. * @return * 1= success , <0 indicates error * * @since 0.6.22 */ int iso_md5_clone(void *old_md5_context, void **new_md5_context); /** * Obtain the MD5 checksum from a MD5 computation context and dispose this * context. (If you want to keep the context then call iso_md5_clone() and * apply iso_md5_end() to the clone.) * * @param md5_context * A pointer to an opaque handle once returned by iso_md5_start() or * iso_md5_clone(). *md5_context will be set to NULL in this call. * @param result * Gets filled with the 16 bytes of MD5 checksum. * @return * 1= success , <0 indicates error * * @since 0.6.22 */ int iso_md5_end(void **md5_context, char result[16]); /** * Inquire whether two MD5 checksums match. (This is trivial but such a call * is convenient and completes the interface.) * @param first_md5 * A MD5 byte string as returned by iso_md5_end() * @param second_md5 * A MD5 byte string as returned by iso_md5_end() * @return * 1= match , 0= mismatch * * @since 0.6.22 */ int iso_md5_match(char first_md5[16], char second_md5[16]); /* -------------------------------- For HFS+ ------------------------------- */ /** * HFS+ attributes which may be attached to IsoNode objects as data parameter * of iso_node_add_xinfo(). As parameter proc use iso_hfsplus_xinfo_func(). * Create instances of this struct by iso_hfsplus_xinfo_new(). * * @since 1.2.4 */ struct iso_hfsplus_xinfo_data { /* Currently set to 0 by iso_hfsplus_xinfo_new() */ int version; /* Attributes available with version 0. * See: http://en.wikipedia.org/wiki/Creator_code , .../Type_code * @since 1.2.4 */ uint8_t creator_code[4]; uint8_t type_code[4]; }; /** * The function that is used to mark struct iso_hfsplus_xinfo_data at IsoNodes * and finally disposes such structs when their IsoNodes get disposed. * Usually an application does not call this function, but only uses it as * parameter of xinfo calls like iso_node_add_xinfo() or iso_node_get_xinfo(). * * @since 1.2.4 */ int iso_hfsplus_xinfo_func(void *data, int flag); /** * Create an instance of struct iso_hfsplus_xinfo_new(). * * @param flag * Bitfield for control purposes. Unused yet. Submit 0. * @return * A pointer to the new object * NULL indicates failure to allocate memory * * @since 1.2.4 */ struct iso_hfsplus_xinfo_data *iso_hfsplus_xinfo_new(int flag); /** * HFS+ blessings are relationships between HFS+ enhanced ISO images and * particular files in such images. Except for ISO_HFSPLUS_BLESS_INTEL_BOOTFILE * and ISO_HFSPLUS_BLESS_MAX, these files have to be directories. * No file may have more than one blessing. Each blessing can only be issued * to one file. * * @since 1.2.4 */ enum IsoHfsplusBlessings { /* The blessing that is issued by mkisofs option -hfs-bless. */ ISO_HFSPLUS_BLESS_PPC_BOOTDIR, /* To be applied to a data file */ ISO_HFSPLUS_BLESS_INTEL_BOOTFILE, /* Further blessings for directories */ ISO_HFSPLUS_BLESS_SHOWFOLDER, ISO_HFSPLUS_BLESS_OS9_FOLDER, ISO_HFSPLUS_BLESS_OSX_FOLDER, /* Not a blessing, but telling the number of blessings in this list */ ISO_HFSPLUS_BLESS_MAX }; /** * Issue a blessing to a particular IsoNode. If the blessing is already issued * to some file, then it gets revoked from that one. * * @param image * The image to manipulate. * @param blessing * The kind of blessing to be issued. * @param node * The file that shall be blessed. It must actually be an IsoDir or * IsoFile as is appropriate for the kind of blessing. (See above enum.) * The node may not yet bear a blessing other than the desired one. * If node is NULL, then the blessing will be revoked from any node * which bears it. * @param flag * Bitfield for control purposes. * bit0= Revoke blessing if node != NULL bears it. * bit1= Revoke any blessing of the node, regardless of parameter * blessing. If node is NULL, then revoke all blessings in * the image. * @return * 1 means successful blessing or revokation of an existing blessing. * 0 means the node already bears another blessing, or is of wrong type, * or that the node was not blessed and revokation was desired. * <0 is one of the listed error codes. * * @since 1.2.4 */ int iso_image_hfsplus_bless(IsoImage *img, enum IsoHfsplusBlessings blessing, IsoNode *node, int flag); /** * Get the array of nodes which are currently blessed. * Array indice correspond to enum IsoHfsplusBlessings. * Array element value NULL means that no node bears that blessing. * * Several usage restrictions apply. See parameter blessed_nodes. * * @param image * The image to inquire. * @param blessed_nodes * Will return a pointer to an internal node array of image. * This pointer is valid only as long as image exists and only until * iso_image_hfsplus_bless() gets used to manipulate the blessings. * Do not free() this array. Do not alter the content of the array * directly, but rather use iso_image_hfsplus_bless() and re-inquire * by iso_image_hfsplus_get_blessed(). * This call does not impose an extra reference on the nodes in the * array. So do not iso_node_unref() them. * Nodes listed here are not necessarily grafted into the tree of * the IsoImage. * @param bless_max * Will return the number of elements in the array. * It is unlikely but not outruled that it will be larger than * ISO_HFSPLUS_BLESS_MAX in this libisofs.h file. * @param flag * Bitfield for control purposes. Submit 0. * @return * 1 means success, <0 means error * * @since 1.2.4 */ int iso_image_hfsplus_get_blessed(IsoImage *img, IsoNode ***blessed_nodes, int *bless_max, int flag); /* ----------------------------- Character sets ---------------------------- */ /** * Convert the characters in name from local charset to another charset or * convert name to the representation of a particular ISO image name space. * In the latter case it is assumed that the conversion result does not * collide with any other converted name in the same directory. * I.e. this function does not take into respect possible name changes * due to collision handling. * * @param opts * Defines output charset, UCS-2 versus UTF-16 for Joliet, * and naming restrictions. * @param name * The input text which shall be converted. * @param name_len * The number of bytes in input text. * @param result * Will return the conversion result in case of success. Terminated by * a trailing zero byte. * Use free() to dispose it when no longer needed. * @param result_len * Will return the number of bytes in result (excluding trailing zero) * @param flag * Bitfield for control purposes. * bit0-bit7= Name space * 0= generic (output charset is used, * no reserved characters, no length limits) * 1= Rock Ridge (output charset is used) * 2= Joliet (output charset gets overridden by UCS-2 or * UTF-16) * 3= ECMA-119 (output charset gets overridden by the * dull ISO 9660 subset of ASCII) * 4= HFS+ (output charset gets overridden by UTF-16BE) * bit8= Treat input text as directory name * (matters for Joliet and ECMA-119) * bit9= Do not issue error messages * bit15= Reverse operation (best to be done only with results of * previous conversions) * @return * 1 means success, <0 means error * * @since 1.3.6 */ int iso_conv_name_chars(IsoWriteOpts *opts, char *name, size_t name_len, char **result, size_t *result_len, int flag); /************ Error codes and return values for libisofs ********************/ /** successfully execution */ #define ISO_SUCCESS 1 /** * special return value, it could be or not an error depending on the * context. */ #define ISO_NONE 0 /** Operation canceled (FAILURE,HIGH, -1) */ #define ISO_CANCELED 0xE830FFFF /** Unknown or unexpected fatal error (FATAL,HIGH, -2) */ #define ISO_FATAL_ERROR 0xF030FFFE /** Unknown or unexpected error (FAILURE,HIGH, -3) */ #define ISO_ERROR 0xE830FFFD /** Internal programming error. Please report this bug (FATAL,HIGH, -4) */ #define ISO_ASSERT_FAILURE 0xF030FFFC /** * NULL pointer as value for an arg. that doesn't allow NULL (FAILURE,HIGH, -5) */ #define ISO_NULL_POINTER 0xE830FFFB /** Memory allocation error (FATAL,HIGH, -6) */ #define ISO_OUT_OF_MEM 0xF030FFFA /** Interrupted by a signal (FATAL,HIGH, -7) */ #define ISO_INTERRUPTED 0xF030FFF9 /** Invalid parameter value (FAILURE,HIGH, -8) */ #define ISO_WRONG_ARG_VALUE 0xE830FFF8 /** Can't create a needed thread (FATAL,HIGH, -9) */ #define ISO_THREAD_ERROR 0xF030FFF7 /** Write error (FAILURE,HIGH, -10) */ #define ISO_WRITE_ERROR 0xE830FFF6 /** Buffer read error (FAILURE,HIGH, -11) */ #define ISO_BUF_READ_ERROR 0xE830FFF5 /** Trying to add to a dir a node already added to a dir (FAILURE,HIGH, -64) */ #define ISO_NODE_ALREADY_ADDED 0xE830FFC0 /** Node with same name already exists (FAILURE,HIGH, -65) */ #define ISO_NODE_NAME_NOT_UNIQUE 0xE830FFBF /** Trying to remove a node that was not added to dir (FAILURE,HIGH, -65) */ #define ISO_NODE_NOT_ADDED_TO_DIR 0xE830FFBE /** A requested node does not exist (FAILURE,HIGH, -66) */ #define ISO_NODE_DOESNT_EXIST 0xE830FFBD /** * Try to set the boot image of an already bootable image (FAILURE,HIGH, -67) */ #define ISO_IMAGE_ALREADY_BOOTABLE 0xE830FFBC /** Trying to use an invalid file as boot image (FAILURE,HIGH, -68) */ #define ISO_BOOT_IMAGE_NOT_VALID 0xE830FFBB /** Too many boot images (FAILURE,HIGH, -69) */ #define ISO_BOOT_IMAGE_OVERFLOW 0xE830FFBA /** No boot catalog created yet ((FAILURE,HIGH, -70) */ /* @since 0.6.34 */ #define ISO_BOOT_NO_CATALOG 0xE830FFB9 /** * Error on file operation (FAILURE,HIGH, -128) * (take a look at more specified error codes below) */ #define ISO_FILE_ERROR 0xE830FF80 /** Trying to open an already opened file (FAILURE,HIGH, -129) */ #define ISO_FILE_ALREADY_OPENED 0xE830FF7F /* @deprecated use ISO_FILE_ALREADY_OPENED instead */ #define ISO_FILE_ALREADY_OPENNED 0xE830FF7F /** Access to file is not allowed (FAILURE,HIGH, -130) */ #define ISO_FILE_ACCESS_DENIED 0xE830FF7E /** Incorrect path to file (FAILURE,HIGH, -131) */ #define ISO_FILE_BAD_PATH 0xE830FF7D /** The file does not exist in the filesystem (FAILURE,HIGH, -132) */ #define ISO_FILE_DOESNT_EXIST 0xE830FF7C /** Trying to read or close a file not openned (FAILURE,HIGH, -133) */ #define ISO_FILE_NOT_OPENED 0xE830FF7B /* @deprecated use ISO_FILE_NOT_OPENED instead */ #define ISO_FILE_NOT_OPENNED ISO_FILE_NOT_OPENED /** Directory used where no dir is expected (FAILURE,HIGH, -134) */ #define ISO_FILE_IS_DIR 0xE830FF7A /** Read error (FAILURE,HIGH, -135) */ #define ISO_FILE_READ_ERROR 0xE830FF79 /** Not dir used where a dir is expected (FAILURE,HIGH, -136) */ #define ISO_FILE_IS_NOT_DIR 0xE830FF78 /** Not symlink used where a symlink is expected (FAILURE,HIGH, -137) */ #define ISO_FILE_IS_NOT_SYMLINK 0xE830FF77 /** Can't seek to specified location (FAILURE,HIGH, -138) */ #define ISO_FILE_SEEK_ERROR 0xE830FF76 /** File not supported in ECMA-119 tree and thus ignored (WARNING,MEDIUM, -139) */ #define ISO_FILE_IGNORED 0xD020FF75 /* A file is bigger than supported by used standard (WARNING,MEDIUM, -140) */ #define ISO_FILE_TOO_BIG 0xD020FF74 /* File read error during image creation (MISHAP,HIGH, -141) */ #define ISO_FILE_CANT_WRITE 0xE430FF73 /* Can't convert filename to requested charset (WARNING,MEDIUM, -142) */ #define ISO_FILENAME_WRONG_CHARSET 0xD020FF72 /* This was once a HINT. Deprecated now. */ #define ISO_FILENAME_WRONG_CHARSET_OLD 0xC020FF72 /* File can't be added to the tree (SORRY,HIGH, -143) */ #define ISO_FILE_CANT_ADD 0xE030FF71 /** * File path break specification constraints and will be ignored * (WARNING,MEDIUM, -144) */ #define ISO_FILE_IMGPATH_WRONG 0xD020FF70 /** * Offset greater than file size (FAILURE,HIGH, -150) * @since 0.6.4 */ #define ISO_FILE_OFFSET_TOO_BIG 0xE830FF6A /** Charset conversion error (FAILURE,HIGH, -256) */ #define ISO_CHARSET_CONV_ERROR 0xE830FF00 /** * Too many files to mangle, i.e. we cannot guarantee unique file names * (FAILURE,HIGH, -257) */ #define ISO_MANGLE_TOO_MUCH_FILES 0xE830FEFF /* image related errors */ /** * Wrong or damaged Primary Volume Descriptor (FAILURE,HIGH, -320) * This could mean that the file is not a valid ISO image. */ #define ISO_WRONG_PVD 0xE830FEC0 /** Wrong or damaged RR entry (SORRY,HIGH, -321) */ #define ISO_WRONG_RR 0xE030FEBF /** Unsupported RR feature (SORRY,HIGH, -322) */ #define ISO_UNSUPPORTED_RR 0xE030FEBE /** Wrong or damaged ECMA-119 (FAILURE,HIGH, -323) */ #define ISO_WRONG_ECMA119 0xE830FEBD /** Unsupported ECMA-119 feature (FAILURE,HIGH, -324) */ #define ISO_UNSUPPORTED_ECMA119 0xE830FEBC /** Wrong or damaged El-Torito catalog (WARN,HIGH, -325) */ #define ISO_WRONG_EL_TORITO 0xD030FEBB /** Unsupported El-Torito feature (WARN,HIGH, -326) */ #define ISO_UNSUPPORTED_EL_TORITO 0xD030FEBA /** Can't patch an isolinux boot image (SORRY,HIGH, -327) */ #define ISO_ISOLINUX_CANT_PATCH 0xE030FEB9 /** Unsupported SUSP feature (SORRY,HIGH, -328) */ #define ISO_UNSUPPORTED_SUSP 0xE030FEB8 /** Error on a RR entry that can be ignored (WARNING,HIGH, -329) */ #define ISO_WRONG_RR_WARN 0xD030FEB7 /** Error on a RR entry that can be ignored (HINT,MEDIUM, -330) */ #define ISO_SUSP_UNHANDLED 0xC020FEB6 /** Multiple ER SUSP entries found (WARNING,HIGH, -331) */ #define ISO_SUSP_MULTIPLE_ER 0xD030FEB5 /** Unsupported volume descriptor found (HINT,MEDIUM, -332) */ #define ISO_UNSUPPORTED_VD 0xC020FEB4 /** El-Torito related warning (WARNING,HIGH, -333) */ #define ISO_EL_TORITO_WARN 0xD030FEB3 /** Image write cancelled (MISHAP,HIGH, -334) */ #define ISO_IMAGE_WRITE_CANCELED 0xE430FEB2 /** El-Torito image is hidden (WARNING,HIGH, -335) */ #define ISO_EL_TORITO_HIDDEN 0xD030FEB1 /** AAIP info with ACL or xattr in ISO image will be ignored (NOTE, HIGH, -336) */ #define ISO_AAIP_IGNORED 0xB030FEB0 /** Error with decoding ACL from AAIP info (FAILURE, HIGH, -337) */ #define ISO_AAIP_BAD_ACL 0xE830FEAF /** Error with encoding ACL for AAIP (FAILURE, HIGH, -338) */ #define ISO_AAIP_BAD_ACL_TEXT 0xE830FEAE /** AAIP processing for ACL or xattr not enabled at compile time (FAILURE, HIGH, -339) */ #define ISO_AAIP_NOT_ENABLED 0xE830FEAD /** Error with decoding AAIP info for ACL or xattr (FAILURE, HIGH, -340) */ #define ISO_AAIP_BAD_AASTRING 0xE830FEAC /** Error with reading ACL or xattr from local file (FAILURE, HIGH, -341) */ #define ISO_AAIP_NO_GET_LOCAL 0xE830FEAB /** Error with attaching ACL or xattr to local file (FAILURE, HIGH, -342) */ #define ISO_AAIP_NO_SET_LOCAL 0xE830FEAA /** Unallowed attempt to set an xattr with non-userspace name (FAILURE, HIGH, -343) */ #define ISO_AAIP_NON_USER_NAME 0xE830FEA9 /** Too many references on a single IsoExternalFilterCommand (FAILURE, HIGH, -344) */ #define ISO_EXTF_TOO_OFTEN 0xE830FEA8 /** Use of zlib was not enabled at compile time (FAILURE, HIGH, -345) */ #define ISO_ZLIB_NOT_ENABLED 0xE830FEA7 /** Cannot apply zisofs filter to file >= 4 GiB (FAILURE, HIGH, -346) */ #define ISO_ZISOFS_TOO_LARGE 0xE830FEA6 /** Filter input differs from previous run (FAILURE, HIGH, -347) */ #define ISO_FILTER_WRONG_INPUT 0xE830FEA5 /** zlib compression/decompression error (FAILURE, HIGH, -348) */ #define ISO_ZLIB_COMPR_ERR 0xE830FEA4 /** Input stream is not in zisofs format (FAILURE, HIGH, -349) */ #define ISO_ZISOFS_WRONG_INPUT 0xE830FEA3 /** Cannot set global zisofs parameters while filters exist (FAILURE, HIGH, -350) */ #define ISO_ZISOFS_PARAM_LOCK 0xE830FEA2 /** Premature EOF of zlib input stream (FAILURE, HIGH, -351) */ #define ISO_ZLIB_EARLY_EOF 0xE830FEA1 /** * Checksum area or checksum tag appear corrupted (WARNING,HIGH, -352) * @since 0.6.22 */ #define ISO_MD5_AREA_CORRUPTED 0xD030FEA0 /** * Checksum mismatch between checksum tag and data blocks * (FAILURE, HIGH, -353) * @since 0.6.22 */ #define ISO_MD5_TAG_MISMATCH 0xE830FE9F /** * Checksum mismatch in System Area, Volume Descriptors, or directory tree. * (FAILURE, HIGH, -354) * @since 0.6.22 */ #define ISO_SB_TREE_CORRUPTED 0xE830FE9E /** * Unexpected checksum tag type encountered. (WARNING, HIGH, -355) * @since 0.6.22 */ #define ISO_MD5_TAG_UNEXPECTED 0xD030FE9D /** * Misplaced checksum tag encountered. (WARNING, HIGH, -356) * @since 0.6.22 */ #define ISO_MD5_TAG_MISPLACED 0xD030FE9C /** * Checksum tag with unexpected address range encountered. * (WARNING, HIGH, -357) * @since 0.6.22 */ #define ISO_MD5_TAG_OTHER_RANGE 0xD030FE9B /** * Detected file content changes while it was written into the image. * (MISHAP, HIGH, -358) * @since 0.6.22 */ #define ISO_MD5_STREAM_CHANGE 0xE430FE9A /** * Session does not start at LBA 0. scdbackup checksum tag not written. * (WARNING, HIGH, -359) * @since 0.6.24 */ #define ISO_SCDBACKUP_TAG_NOT_0 0xD030FE99 /** * The setting of iso_write_opts_set_ms_block() leaves not enough room * for the prescibed size of iso_write_opts_set_overwrite_buf(). * (FAILURE, HIGH, -360) * @since 0.6.36 */ #define ISO_OVWRT_MS_TOO_SMALL 0xE830FE98 /** * The partition offset is not 0 and leaves not not enough room for * system area, volume descriptors, and checksum tags of the first tree. * (FAILURE, HIGH, -361) */ #define ISO_PART_OFFST_TOO_SMALL 0xE830FE97 /** * The ring buffer is smaller than 64 kB + partition offset. * (FAILURE, HIGH, -362) */ #define ISO_OVWRT_FIFO_TOO_SMALL 0xE830FE96 /** Use of libjte was not enabled at compile time (FAILURE, HIGH, -363) */ #define ISO_LIBJTE_NOT_ENABLED 0xE830FE95 /** Failed to start up Jigdo Template Extraction (FAILURE, HIGH, -364) */ #define ISO_LIBJTE_START_FAILED 0xE830FE94 /** Failed to finish Jigdo Template Extraction (FAILURE, HIGH, -365) */ #define ISO_LIBJTE_END_FAILED 0xE830FE93 /** Failed to process file for Jigdo Template Extraction (MISHAP, HIGH, -366) */ #define ISO_LIBJTE_FILE_FAILED 0xE430FE92 /** Too many MIPS Big Endian boot files given (max. 15) (FAILURE, HIGH, -367)*/ #define ISO_BOOT_TOO_MANY_MIPS 0xE830FE91 /** Boot file missing in image (MISHAP, HIGH, -368) */ #define ISO_BOOT_FILE_MISSING 0xE430FE90 /** Partition number out of range (FAILURE, HIGH, -369) */ #define ISO_BAD_PARTITION_NO 0xE830FE8F /** Cannot open data file for appended partition (FAILURE, HIGH, -370) */ #define ISO_BAD_PARTITION_FILE 0xE830FE8E /** May not combine MBR partition with non-MBR system area (FAILURE, HIGH, -371) */ #define ISO_NON_MBR_SYS_AREA 0xE830FE8D /** Displacement offset leads outside 32 bit range (FAILURE, HIGH, -372) */ #define ISO_DISPLACE_ROLLOVER 0xE830FE8C /** File name cannot be written into ECMA-119 untranslated (FAILURE, HIGH, -373) */ #define ISO_NAME_NEEDS_TRANSL 0xE830FE8B /** Data file input stream object offers no cloning method (FAILURE, HIGH, -374) */ #define ISO_STREAM_NO_CLONE 0xE830FE8A /** Extended information class offers no cloning method (FAILURE, HIGH, -375) */ #define ISO_XINFO_NO_CLONE 0xE830FE89 /** Found copied superblock checksum tag (WARNING, HIGH, -376) */ #define ISO_MD5_TAG_COPIED 0xD030FE88 /** Rock Ridge leaf name too long (FAILURE, HIGH, -377) */ #define ISO_RR_NAME_TOO_LONG 0xE830FE87 /** Reserved Rock Ridge leaf name (FAILURE, HIGH, -378) */ #define ISO_RR_NAME_RESERVED 0xE830FE86 /** Rock Ridge path too long (FAILURE, HIGH, -379) */ #define ISO_RR_PATH_TOO_LONG 0xE830FE85 /** Attribute name cannot be represented (FAILURE, HIGH, -380) */ #define ISO_AAIP_BAD_ATTR_NAME 0xE830FE84 /** ACL text contains multiple entries of user::, group::, other:: (FAILURE, HIGH, -381) */ #define ISO_AAIP_ACL_MULT_OBJ 0xE830FE83 /** File sections do not form consecutive array of blocks (FAILURE, HIGH, -382) */ #define ISO_SECT_SCATTERED 0xE830FE82 /** Too many Apple Partition Map entries requested (FAILURE, HIGH, -383) */ #define ISO_BOOT_TOO_MANY_APM 0xE830FE81 /** Overlapping Apple Partition Map entries requested (FAILURE, HIGH, -384) */ #define ISO_BOOT_APM_OVERLAP 0xE830FE80 /** Too many GPT entries requested (FAILURE, HIGH, -385) */ #define ISO_BOOT_TOO_MANY_GPT 0xE830FE7F /** Overlapping GPT entries requested (FAILURE, HIGH, -386) */ #define ISO_BOOT_GPT_OVERLAP 0xE830FE7E /** Too many MBR partition entries requested (FAILURE, HIGH, -387) */ #define ISO_BOOT_TOO_MANY_MBR 0xE830FE7D /** Overlapping MBR partition entries requested (FAILURE, HIGH, -388) */ #define ISO_BOOT_MBR_OVERLAP 0xE830FE7C /** Attempt to use an MBR partition entry twice (FAILURE, HIGH, -389) */ #define ISO_BOOT_MBR_COLLISION 0xE830FE7B /** No suitable El Torito EFI boot image for exposure as GPT partition (FAILURE, HIGH, -390) */ #define ISO_BOOT_NO_EFI_ELTO 0xE830FE7A /** Not a supported HFS+ or APM block size (FAILURE, HIGH, -391) */ #define ISO_BOOT_HFSP_BAD_BSIZE 0xE830FE79 /** APM block size prevents coexistence with GPT (FAILURE, HIGH, -392) */ #define ISO_BOOT_APM_GPT_BSIZE 0xE830FE78 /** Name collision in HFS+, mangling not possible (FAILURE, HIGH, -393) */ #define ISO_HFSP_NO_MANGLE 0xE830FE77 /** Symbolic link cannot be resolved (FAILURE, HIGH, -394) */ #define ISO_DEAD_SYMLINK 0xE830FE76 /** Too many chained symbolic links (FAILURE, HIGH, -395) */ #define ISO_DEEP_SYMLINK 0xE830FE75 /** Unrecognized file type in ISO image (FAILURE, HIGH, -396) */ #define ISO_BAD_ISO_FILETYPE 0xE830FE74 /** Filename not suitable for character set UCS-2 (WARNING, HIGH, -397) */ #define ISO_NAME_NOT_UCS2 0xD030FE73 /** File name collision during ISO image import (WARNING, HIGH, -398) */ #define ISO_IMPORT_COLLISION 0xD030FE72 /** Incomplete HP-PA PALO boot parameters (FAILURE, HIGH, -399) */ #define ISO_HPPA_PALO_INCOMPL 0xE830FE71 /** HP-PA PALO boot address exceeds 2 GB (FAILURE, HIGH, -400) */ #define ISO_HPPA_PALO_OFLOW 0xE830FE70 /** HP-PA PALO file is not a data file (FAILURE, HIGH, -401) */ #define ISO_HPPA_PALO_NOTREG 0xE830FE6F /** HP-PA PALO command line too long (FAILURE, HIGH, -402) */ #define ISO_HPPA_PALO_CMDLEN 0xE830FE6E /** Problems encountered during inspection of System Area (WARN, HIGH, -403) */ #define ISO_SYSAREA_PROBLEMS 0xD030FE6D /** Unrecognized inquiry for system area property (FAILURE, HIGH, -404) */ #define ISO_INQ_SYSAREA_PROP 0xE830FE6C /** DEC Alpha Boot Loader file is not a data file (FAILURE, HIGH, -405) */ #define ISO_ALPHA_BOOT_NOTREG 0xE830FE6B /** No data source of imported ISO image available (WARNING, HIGH, -406) */ #define ISO_NO_KEPT_DATA_SRC 0xD030FE6A /** Malformed description string for interval reader (FAILURE, HIGH, -407) */ #define ISO_MALFORMED_READ_INTVL 0xE830FE69 /** Unreadable file, premature EOF, or failure to seek for interval reader (WARNING, HIGH, -408) */ #define ISO_INTVL_READ_PROBLEM 0xD030FE68 /** Cannot arrange content of data files in surely reproducible way (NOTE, HIGH, -409) */ #define ISO_NOT_REPRODUCIBLE 0xB030FE67 /** May not write boot info into filtered stream of boot image (FAILURE, HIGH, -410) */ #define ISO_PATCH_FILTERED_BOOT 0xE830FE66 /** Boot image to large to buffer for writing boot info (FAILURE, HIGH, -411) */ #define ISO_PATCH_OVERSIZED_BOOT 0xE830FE65 /** File name had to be truncated and MD5 marked (WARNING, HIGH, -412) */ #define ISO_RR_NAME_TRUNCATED 0xD030FE64 /** File name truncation length changed by loaded image info (NOTE, HIGH, -413) */ #define ISO_TRUNCATE_ISOFSNT 0xB030FE63 /** General note (NOTE, HIGH, -414) */ #define ISO_GENERAL_NOTE 0xB030FE62 /** Unrecognized file type of IsoFileSrc object (SORRY, HIGH, -415) */ #define ISO_BAD_FSRC_FILETYPE 0xE030FE61 /* Internal developer note: Place new error codes directly above this comment. Newly introduced errors must get a message entry in libisofs/messages.c, function iso_error_to_msg() */ /* ! PLACE NEW ERROR CODES ABOVE. NOT AFTER THIS LINE ! */ /** Read error occured with IsoDataSource (SORRY,HIGH, -513) */ #define ISO_DATA_SOURCE_SORRY 0xE030FCFF /** Read error occured with IsoDataSource (MISHAP,HIGH, -513) */ #define ISO_DATA_SOURCE_MISHAP 0xE430FCFF /** Read error occured with IsoDataSource (FAILURE,HIGH, -513) */ #define ISO_DATA_SOURCE_FAILURE 0xE830FCFF /** Read error occured with IsoDataSource (FATAL,HIGH, -513) */ #define ISO_DATA_SOURCE_FATAL 0xF030FCFF /* ! PLACE NEW ERROR CODES SEVERAL LINES ABOVE. NOT HERE ! */ /* ------------------------------------------------------------------------- */ #ifdef LIBISOFS_WITHOUT_LIBBURN /** This is a copy from the API of libburn-0.6.0 (under GPL). It is supposed to be as stable as any overall include of libburn.h. I.e. if this definition is out of sync then you cannot rely on any contract that was made with libburn.h. Libisofs does not need to be linked with libburn at all. But if it is linked with libburn then it must be libburn-0.4.2 or later. An application that provides own struct burn_source objects and does not include libburn/libburn.h has to define LIBISOFS_WITHOUT_LIBBURN before including libisofs/libisofs.h in order to make this copy available. */ /** Data source interface for tracks. This allows to use arbitrary program code as provider of track input data. Objects compliant to this interface are either provided by the application or by API calls of libburn: burn_fd_source_new(), burn_file_source_new(), and burn_fifo_source_new(). libisofs acts as "application" and implements an own class of burn_source. Instances of that class are handed out by iso_image_create_burn_source(). */ struct burn_source { /** Reference count for the data source. MUST be 1 when a new source is created and thus the first reference is handed out. Increment it to take more references for yourself. Use burn_source_free() to destroy your references to it. */ int refcount; /** Read data from the source. Semantics like with read(2), but MUST either deliver the full buffer as defined by size or MUST deliver EOF (return 0) or failure (return -1) at this call or at the next following call. I.e. the only incomplete buffer may be the last one from that source. libburn will read a single sector by each call to (*read). The size of a sector depends on BURN_MODE_*. The known range is 2048 to 2352. If this call is reading from a pipe then it will learn about the end of data only when that pipe gets closed on the feeder side. So if the track size is not fixed or if the pipe delivers less than the predicted amount or if the size is not block aligned, then burning will halt until the input process closes the pipe. IMPORTANT: If this function pointer is NULL, then the struct burn_source is of version >= 1 and the job of .(*read)() is done by .(*read_xt)(). See below, member .version. */ int (*read)(struct burn_source *, unsigned char *buffer, int size); /** Read subchannel data from the source (NULL if lib generated) WARNING: This is an obscure feature with CD raw write modes. Unless you checked the libburn code for correctness in that aspect you should not rely on raw writing with own subchannels. ADVICE: Set this pointer to NULL. */ int (*read_sub)(struct burn_source *, unsigned char *buffer, int size); /** Get the size of the source's data. Return 0 means unpredictable size. If application provided (*get_size) allows return 0, then the application MUST provide a fully functional (*set_size). */ off_t (*get_size)(struct burn_source *); /* @since 0.3.2 */ /** Program the reply of (*get_size) to a fixed value. It is advised to implement this by a attribute off_t fixed_size; in *data . The read() function does not have to take into respect this fake setting. It is rather a note of libburn to itself. Eventually necessary truncation or padding is done in libburn. Truncation is usually considered a misburn. Padding is considered ok. libburn is supposed to work even if (*get_size) ignores the setting by (*set_size). But your application will not be able to enforce fixed track sizes by burn_track_set_size() and possibly even padding might be left out. */ int (*set_size)(struct burn_source *source, off_t size); /** Clean up the source specific data. This function will be called once by burn_source_free() when the last referer disposes the source. */ void (*free_data)(struct burn_source *); /** Next source, for when a source runs dry and padding is disabled WARNING: This is an obscure feature. Set to NULL at creation and from then on leave untouched and uninterpreted. */ struct burn_source *next; /** Source specific data. Here the various source classes express their specific properties and the instance objects store their individual management data. E.g. data could point to a struct like this: struct app_burn_source { struct my_app *app_handle; ... other individual source parameters ... off_t fixed_size; }; Function (*free_data) has to be prepared to clean up and free the struct. */ void *data; /* @since 0.4.2 */ /** Valid only if above member .(*read)() is NULL. This indicates a version of struct burn_source younger than 0. From then on, member .version tells which further members exist in the memory layout of struct burn_source. libburn will only touch those announced extensions. Versions: 0 has .(*read)() != NULL, not even .version is present. 1 has .version, .(*read_xt)(), .(*cancel)() */ int version; /** This substitutes for (*read)() in versions above 0. */ int (*read_xt)(struct burn_source *, unsigned char *buffer, int size); /** Informs the burn_source that the consumer of data prematurely ended reading. This call may or may not be issued by libburn before (*free_data)() is called. */ int (*cancel)(struct burn_source *source); }; #endif /* LIBISOFS_WITHOUT_LIBBURN */ /* ----------------------------- Bug Fixes ----------------------------- */ /* currently none being tested */ /* ---------------------------- Improvements --------------------------- */ /* currently none being tested */ /* ---------------------------- Experiments ---------------------------- */ /* Experiment: Write obsolete RR entries with Rock Ridge. I suspect Solaris wants to see them. DID NOT HELP: Solaris knows only RRIP_1991A. #define Libisofs_with_rrip_rR yes */ #endif /*LIBISO_LIBISOFS_H_*/ libisofs-1.4.2/libisofs/iso1999.c0000644000175700017510000007325412321161425013375 00000000000000/* * Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2011-2014 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif #include "iso1999.h" #include "messages.h" #include "writer.h" #include "image.h" #include "filesrc.h" #include "eltorito.h" #include "util.h" #include "ecma119.h" #include #include #include static int get_iso1999_name(Ecma119Image *t, const char *str, char **fname) { int ret; char *name; if (fname == NULL) { return ISO_ASSERT_FAILURE; } if (str == NULL) { /* not an error, can be root node */ *fname = NULL; return ISO_SUCCESS; } if (!strcmp(t->input_charset, t->output_charset)) { /* no conversion needed */ name = strdup(str); } else { ret = strconv(str, t->input_charset, t->output_charset, &name); if (ret < 0) { ret = iso_msg_submit(t->image->id, ISO_FILENAME_WRONG_CHARSET, ret, "Charset conversion error. Can't convert %s from %s to %s", str, t->input_charset, t->output_charset); if (ret < 0) { return ret; /* aborted */ } /* use the original name, it's the best we can do */ name = strdup(str); } } /* ISO 9660:1999 7.5.1 */ if (strlen(name) > 207) { name[207] = '\0'; } *fname = name; return ISO_SUCCESS; } static void iso1999_node_free(Iso1999Node *node) { if (node == NULL) { return; } if (node->type == ISO1999_DIR) { size_t i; for (i = 0; i < node->info.dir->nchildren; i++) { iso1999_node_free(node->info.dir->children[i]); } if (node->info.dir->children != NULL) free(node->info.dir->children); free(node->info.dir); } iso_node_unref(node->node); free(node->name); free(node); } /** * Create a low level ISO 9660:1999 node * @return * 1 success, 0 ignored, < 0 error */ static int create_node(Ecma119Image *t, IsoNode *iso, Iso1999Node **node) { int ret; Iso1999Node *n; n = calloc(1, sizeof(Iso1999Node)); if (n == NULL) { return ISO_OUT_OF_MEM; } if (iso->type == LIBISO_DIR) { IsoDir *dir = (IsoDir*) iso; n->info.dir = calloc(1, sizeof(struct iso1999_dir_info)); if (n->info.dir == NULL) { free(n); return ISO_OUT_OF_MEM; } n->info.dir->children = NULL; if (dir->nchildren > 0) { n->info.dir->children = calloc(sizeof(void*), dir->nchildren); if (n->info.dir->children == NULL) { free(n->info.dir); free(n); return ISO_OUT_OF_MEM; } } n->type = ISO1999_DIR; } else if (iso->type == LIBISO_FILE) { /* it's a file */ off_t size; IsoFileSrc *src; IsoFile *file = (IsoFile*) iso; size = iso_stream_get_size(file->stream); if (size > (off_t)MAX_ISO_FILE_SECTION_SIZE && t->opts->iso_level != 3) { char *ipath = iso_tree_get_node_path(iso); ret = iso_msg_submit(t->image->id, ISO_FILE_TOO_BIG, 0, "File \"%s\" can't be added to image because is " "greater than 4GB", ipath); free(n); free(ipath); return ret; } ret = iso_file_src_create(t, file, &src); if (ret < 0) { free(n); return ret; } n->info.file = src; n->type = ISO1999_FILE; } else if (iso->type == LIBISO_BOOT) { /* it's a el-torito boot catalog, that we write as a file */ IsoFileSrc *src; ret = el_torito_catalog_file_src_create(t, &src); if (ret < 0) { free(n); return ret; } n->info.file = src; n->type = ISO1999_FILE; } else { /* should never happen */ free(n); return ISO_ASSERT_FAILURE; } /* take a ref to the IsoNode */ n->node = iso; iso_node_ref(iso); *node = n; return ISO_SUCCESS; } /** * Create the low level ISO 9660:1999 tree from the high level ISO tree. * * @return * 1 success, 0 file ignored, < 0 error */ static int create_tree(Ecma119Image *t, IsoNode *iso, Iso1999Node **tree, int pathlen) { int ret, max_path; Iso1999Node *node = NULL; char *iso_name = NULL; if (t == NULL || iso == NULL || tree == NULL) { return ISO_NULL_POINTER; } if (iso->hidden & LIBISO_HIDE_ON_1999) { /* file will be ignored */ return 0; } ret = get_iso1999_name(t, iso->name, &iso_name); if (ret < 0) { return ret; } max_path = pathlen + 1 + (iso_name ? strlen(iso_name): 0); if (!t->opts->allow_longer_paths && max_path > 255) { char *ipath = iso_tree_get_node_path(iso); ret = iso_msg_submit(t->image->id, ISO_FILE_IMGPATH_WRONG, 0, "File \"%s\" can't be added to ISO 9660:1999 tree, " "because its path length is larger than 255", ipath); free(iso_name); free(ipath); return ret; } switch (iso->type) { case LIBISO_FILE: ret = create_node(t, iso, &node); break; case LIBISO_DIR: { IsoNode *pos; IsoDir *dir = (IsoDir*)iso; ret = create_node(t, iso, &node); if (ret < 0) { free(iso_name); return ret; } pos = dir->children; while (pos) { int cret; Iso1999Node *child; cret = create_tree(t, pos, &child, max_path); if (cret < 0) { /* error */ iso1999_node_free(node); ret = cret; break; } else if (cret == ISO_SUCCESS) { /* add child to this node */ int nchildren = node->info.dir->nchildren++; node->info.dir->children[nchildren] = child; child->parent = node; } pos = pos->next; } } break; case LIBISO_BOOT: if (t->eltorito) { ret = create_node(t, iso, &node); } else { /* log and ignore */ ret = iso_msg_submit(t->image->id, ISO_FILE_IGNORED, 0, "El-Torito catalog found on a image without El-Torito."); } break; case LIBISO_SYMLINK: case LIBISO_SPECIAL: { char *ipath = iso_tree_get_node_path(iso); ret = iso_msg_submit(t->image->id, ISO_FILE_IGNORED, 0, "Can't add %s to ISO 9660:1999 tree. This kind of files " "can only be added to a Rock Ridget tree. Skipping.", ipath); free(ipath); } break; default: /* should never happen */ return ISO_ASSERT_FAILURE; } if (ret <= 0) { free(iso_name); return ret; } node->name = iso_name; *tree = node; return ISO_SUCCESS; } static int cmp_node(const void *f1, const void *f2) { Iso1999Node *f = *((Iso1999Node**)f1); Iso1999Node *g = *((Iso1999Node**)f2); /** * TODO #00027 Follow ISO 9660:1999 specs when sorting files * strcmp do not does exactly what ISO 9660:1999, 9.3, as characters * < 0x20 " " are allowed, so name len must be taken into accout */ return strcmp(f->name, g->name); } /** * Sort the entries inside an ISO 9660:1999 directory, according to * ISO 9660:1999, 9.3 */ static void sort_tree(Iso1999Node *root) { size_t i; if (root->info.dir->children == NULL) return; qsort(root->info.dir->children, root->info.dir->nchildren, sizeof(void*), cmp_node); for (i = 0; i < root->info.dir->nchildren; i++) { Iso1999Node *child = root->info.dir->children[i]; if (child->type == ISO1999_DIR) sort_tree(child); } } static int mangle_single_dir(Ecma119Image *img, Iso1999Node *dir) { int ret; int i, nchildren; Iso1999Node **children; IsoHTable *table = NULL; int need_sort = 0; char *full_name = NULL, *tmp = NULL; nchildren = dir->info.dir->nchildren; if (nchildren <= 0) { ret = ISO_SUCCESS; goto ex; } children = dir->info.dir->children; LIBISO_ALLOC_MEM(full_name, char, 208); LIBISO_ALLOC_MEM(tmp, char, 208); /* a hash table will temporary hold the names, for fast searching */ ret = iso_htable_create((nchildren * 100) / 80, iso_str_hash, (compare_function_t)strcmp, &table); if (ret < 0) { goto ex; } for (i = 0; i < nchildren; ++i) { char *name = children[i]->name; ret = iso_htable_add(table, name, name); if (ret < 0) { goto ex; } } for (i = 0; i < nchildren; ++i) { char *name, *ext; int max; /* computed max len for name, without extension */ int j = i; int digits = 1; /* characters to change per name */ /* first, find all child with same name */ while (j + 1 < nchildren && !cmp_node(children + i, children + j + 1)) { ++j; } if (j == i) { /* name is unique */ continue; } /* * A max of 7 characters is good enought, it allows handling up to * 9,999,999 files with same name. */ while (digits < 8) { int ok, k; char *dot; int change = 0; /* number to be written */ /* copy name to buffer */ strcpy(full_name, children[i]->name); /* compute name and extension */ dot = strrchr(full_name, '.'); if (dot != NULL && children[i]->type != ISO1999_DIR) { /* * File (not dir) with extension. */ int extlen; full_name[dot - full_name] = '\0'; name = full_name; ext = dot + 1; extlen = strlen(ext); max = 207 - extlen - 1 - digits; if (max <= 0) { /* this can happen if extension is too long */ if (extlen + max > 3) { /* * reduce extension len, to give name an extra char * note that max is negative or 0 */ extlen = extlen + max - 1; ext[extlen] = '\0'; max = 207 - extlen - 1 - digits; } else { /* * error, we don't support extensions < 3 * This can't happen with current limit of digits. */ ret = ISO_ERROR; goto ex; } } /* ok, reduce name by digits */ if (name + max < dot) { name[max] = '\0'; } } else { /* Directory, or file without extension */ if (children[i]->type == ISO1999_DIR) { dot = NULL; /* dots have no meaning in dirs */ } max = 207 - digits; name = full_name; if ((size_t) max < strlen(name)) { name[max] = '\0'; } /* let ext be an empty string */ ext = name + strlen(name); } ok = 1; /* change name of each file */ for (k = i; k <= j; ++k) { char fmt[16]; if (dot != NULL) { sprintf(fmt, "%%s%%0%dd.%%s", digits); } else { sprintf(fmt, "%%s%%0%dd%%s", digits); } while (1) { sprintf(tmp, fmt, name, change, ext); ++change; if (change > int_pow(10, digits)) { ok = 0; break; } if (!iso_htable_get(table, tmp, NULL)) { /* the name is unique, so it can be used */ break; } } if (ok) { char *new = strdup(tmp); if (new == NULL) { ret = ISO_OUT_OF_MEM; goto ex; } iso_msg_debug(img->image->id, "\"%s\" renamed to \"%s\"", children[k]->name, new); iso_htable_remove_ptr(table, children[k]->name, NULL); free(children[k]->name); children[k]->name = new; iso_htable_add(table, new, new); /* * if we change a name we need to sort again children * at the end */ need_sort = 1; } else { /* we need to increment digits */ break; } } if (ok) { break; } else { ++digits; } } if (digits == 8) { ret = ISO_MANGLE_TOO_MUCH_FILES; goto ex; } i = j; } /* * If needed, sort again the files inside dir */ if (need_sort) { qsort(children, nchildren, sizeof(void*), cmp_node); } ret = ISO_SUCCESS; ex:; iso_htable_destroy(table, NULL); LIBISO_FREE_MEM(tmp); LIBISO_FREE_MEM(full_name); return ret; } static int mangle_tree(Ecma119Image *t, Iso1999Node *dir) { int ret; size_t i; ret = mangle_single_dir(t, dir); if (ret < 0) { return ret; } /* recurse */ for (i = 0; i < dir->info.dir->nchildren; ++i) { if (dir->info.dir->children[i]->type == ISO1999_DIR) { ret = mangle_tree(t, dir->info.dir->children[i]); if (ret < 0) { /* error */ return ret; } } } return ISO_SUCCESS; } static int iso1999_tree_create(Ecma119Image *t) { int ret; Iso1999Node *root; if (t == NULL) { return ISO_NULL_POINTER; } ret = create_tree(t, (IsoNode*)t->image->root, &root, 0); if (ret <= 0) { if (ret == 0) { /* unexpected error, root ignored!! This can't happen */ ret = ISO_ASSERT_FAILURE; } return ret; } /* the ISO 9660:1999 tree is stored in Ecma119Image target */ t->iso1999_root = root; iso_msg_debug(t->image->id, "Sorting the ISO 9660:1999 tree..."); sort_tree(root); iso_msg_debug(t->image->id, "Mangling ISO 9660:1999 names..."); ret = mangle_tree(t, t->iso1999_root); if (ret < 0) { return ret; } return ISO_SUCCESS; } /** * Compute the size of a directory entry for a single node */ static size_t calc_dirent_len(Ecma119Image *t, Iso1999Node *n) { int ret = n->name ? strlen(n->name) + 33 : 34; if (ret % 2) ret++; return ret; } /** * Computes the total size of all directory entries of a single dir, as * stated in ISO 9660:1999, 6.8.1.3 */ static size_t calc_dir_size(Ecma119Image *t, Iso1999Node *dir) { size_t i, len; /* size of "." and ".." entries */ len = 34 + 34; for (i = 0; i < dir->info.dir->nchildren; ++i) { size_t remaining; int section, nsections; Iso1999Node *child = dir->info.dir->children[i]; size_t dirent_len = calc_dirent_len(t, child); nsections = (child->type == ISO1999_FILE) ? child->info.file->nsections : 1; for (section = 0; section < nsections; ++section) { remaining = BLOCK_SIZE - (len % BLOCK_SIZE); if (dirent_len > remaining) { /* child directory entry doesn't fit on block */ len += remaining + dirent_len; } else { len += dirent_len; } } } /* * The size of a dir is always a multiple of block size, as we must add * the size of the unused space after the last directory record * (ISO 9660:1999, 6.8.1.3) */ len = ROUND_UP(len, BLOCK_SIZE); /* cache the len */ dir->info.dir->len = len; return len; } static void calc_dir_pos(Ecma119Image *t, Iso1999Node *dir) { size_t i, len; t->iso1999_ndirs++; dir->info.dir->block = t->curblock; len = calc_dir_size(t, dir); t->curblock += DIV_UP(len, BLOCK_SIZE); for (i = 0; i < dir->info.dir->nchildren; i++) { Iso1999Node *child = dir->info.dir->children[i]; if (child->type == ISO1999_DIR) { calc_dir_pos(t, child); } } } /** * Compute the length of the path table (ISO 9660:1999, 6.9), in bytes. */ static uint32_t calc_path_table_size(Iso1999Node *dir) { uint32_t size; size_t i; /* size of path table for this entry */ size = 8; size += dir->name ? strlen(dir->name) : 2; size += (size % 2); /* and recurse */ for (i = 0; i < dir->info.dir->nchildren; i++) { Iso1999Node *child = dir->info.dir->children[i]; if (child->type == ISO1999_DIR) { size += calc_path_table_size(child); } } return size; } static int iso1999_writer_compute_data_blocks(IsoImageWriter *writer) { Ecma119Image *t; uint32_t path_table_size; if (writer == NULL) { return ISO_OUT_OF_MEM; } t = writer->target; /* compute position of directories */ iso_msg_debug(t->image->id, "Computing position of ISO 9660:1999 dir structure"); t->iso1999_ndirs = 0; calc_dir_pos(t, t->iso1999_root); /* compute length of pathlist */ iso_msg_debug(t->image->id, "Computing length of ISO 9660:1999 pathlist"); path_table_size = calc_path_table_size(t->iso1999_root); /* compute location for path tables */ t->iso1999_l_path_table_pos = t->curblock; t->curblock += DIV_UP(path_table_size, BLOCK_SIZE); t->iso1999_m_path_table_pos = t->curblock; t->curblock += DIV_UP(path_table_size, BLOCK_SIZE); t->iso1999_path_table_size = path_table_size; return ISO_SUCCESS; } /** * Write a single directory record (ISO 9660:1999, 9.1). * * @param file_id * if >= 0, we use it instead of the filename (for "." and ".." entries). * @param len_fi * Computed length of the file identifier. */ static void write_one_dir_record(Ecma119Image *t, Iso1999Node *node, int file_id, uint8_t *buf, size_t len_fi, int extent) { uint32_t len; uint32_t block; uint8_t len_dr; /*< size of dir entry */ int multi_extend = 0; uint8_t *name = (file_id >= 0) ? (uint8_t*)&file_id : (uint8_t*)node->name; struct ecma119_dir_record *rec = (struct ecma119_dir_record*)buf; IsoNode *iso; len_dr = 33 + len_fi + ((len_fi % 2) ? 0 : 1); memcpy(rec->file_id, name, len_fi); if (node->type == ISO1999_DIR) { /* use the cached length */ len = node->info.dir->len; block = node->info.dir->block; } else if (node->type == ISO1999_FILE) { block = node->info.file->sections[extent].block; len = node->info.file->sections[extent].size; multi_extend = (node->info.file->nsections - 1 == extent) ? 0 : 1; } else { /* * for nodes other than files and dirs, we set both * len and block to 0 */ len = 0; block = 0; } /* * For ".." entry we need to write the parent info! */ if (file_id == 1 && node->parent) node = node->parent; rec->len_dr[0] = len_dr; iso_bb(rec->block, block, 4); iso_bb(rec->length, len, 4); /* was: iso_datetime_7(rec->recording_time, t->now, t->opts->always_gmt); */ iso= node->node; iso_datetime_7(rec->recording_time, (t->opts->dir_rec_mtime & 4) ? ( t->replace_timestamps ? t->timestamp : iso->mtime ) : t->now, t->opts->always_gmt); rec->flags[0] = ((node->type == ISO1999_DIR) ? 2 : 0) | (multi_extend ? 0x80 : 0); iso_bb(rec->vol_seq_number, (uint32_t) 1, 2); rec->len_fi[0] = len_fi; } /** * Write the enhanced volume descriptor (ISO/IEC 9660:1999, 8.5) */ static int iso1999_writer_write_vol_desc(IsoImageWriter *writer) { IsoImage *image; Ecma119Image *t; /* The enhanced volume descriptor is like the sup vol desc */ struct ecma119_sup_vol_desc vol; char *vol_id = NULL, *pub_id = NULL, *data_id = NULL; char *volset_id = NULL, *system_id = NULL, *application_id = NULL; char *copyright_file_id = NULL, *abstract_file_id = NULL; char *biblio_file_id = NULL; if (writer == NULL) { return ISO_OUT_OF_MEM; } t = writer->target; image = t->image; iso_msg_debug(image->id, "Write Enhanced Vol Desc (ISO 9660:1999)"); memset(&vol, 0, sizeof(struct ecma119_sup_vol_desc)); get_iso1999_name(t, image->volume_id, &vol_id); str2a_char(t->input_charset, image->publisher_id, &pub_id); str2a_char(t->input_charset, image->data_preparer_id, &data_id); get_iso1999_name(t, image->volset_id, &volset_id); str2a_char(t->input_charset, image->system_id, &system_id); str2a_char(t->input_charset, image->application_id, &application_id); get_iso1999_name(t, image->copyright_file_id, ©right_file_id); get_iso1999_name(t, image->abstract_file_id, &abstract_file_id); get_iso1999_name(t, image->biblio_file_id, &biblio_file_id); vol.vol_desc_type[0] = 2; memcpy(vol.std_identifier, "CD001", 5); /* descriptor version is 2 (ISO/IEC 9660:1999, 8.5.2) */ vol.vol_desc_version[0] = 2; strncpy_pad((char*)vol.volume_id, vol_id, 32); iso_bb(vol.vol_space_size, t->vol_space_size, 4); iso_bb(vol.vol_set_size, (uint32_t) 1, 2); iso_bb(vol.vol_seq_number, (uint32_t) 1, 2); iso_bb(vol.block_size, (uint32_t) BLOCK_SIZE, 2); iso_bb(vol.path_table_size, t->iso1999_path_table_size, 4); iso_lsb(vol.l_path_table_pos, t->iso1999_l_path_table_pos, 4); iso_msb(vol.m_path_table_pos, t->iso1999_m_path_table_pos, 4); write_one_dir_record(t, t->iso1999_root, 0, vol.root_dir_record, 1, 0); strncpy_pad((char*)vol.vol_set_id, volset_id, 128); strncpy_pad((char*)vol.publisher_id, pub_id, 128); strncpy_pad((char*)vol.data_prep_id, data_id, 128); strncpy_pad((char*)vol.system_id, system_id, 32); strncpy_pad((char*)vol.application_id, application_id, 128); strncpy_pad((char*)vol.copyright_file_id, copyright_file_id, 37); strncpy_pad((char*)vol.abstract_file_id, abstract_file_id, 37); strncpy_pad((char*)vol.bibliographic_file_id, biblio_file_id, 37); ecma119_set_voldescr_times(writer, (struct ecma119_pri_vol_desc *) &vol); vol.file_structure_version[0] = 2; free(vol_id); free(volset_id); free(pub_id); free(data_id); free(system_id); free(application_id); free(copyright_file_id); free(abstract_file_id); free(biblio_file_id); /* Finally write the Volume Descriptor */ return iso_write(t, &vol, sizeof(struct ecma119_sup_vol_desc)); } static int write_one_dir(Ecma119Image *t, Iso1999Node *dir) { int ret; uint8_t *buffer = NULL; size_t i; size_t fi_len, len; /* buf will point to current write position on buffer */ uint8_t *buf; LIBISO_ALLOC_MEM(buffer, uint8_t, BLOCK_SIZE); buf = buffer; /* write the "." and ".." entries first */ write_one_dir_record(t, dir, 0, buf, 1, 0); buf += 34; write_one_dir_record(t, dir, 1, buf, 1, 0); buf += 34; for (i = 0; i < dir->info.dir->nchildren; i++) { int section, nsections; Iso1999Node *child = dir->info.dir->children[i]; /* compute len of directory entry */ fi_len = strlen(child->name); len = fi_len + 33 + ((fi_len % 2) ? 0 : 1); nsections = (child->type == ISO1999_FILE) ? child->info.file->nsections : 1; for (section = 0; section < nsections; ++section) { if ( (buf + len - buffer) > BLOCK_SIZE) { /* dir doesn't fit in current block */ ret = iso_write(t, buffer, BLOCK_SIZE); if (ret < 0) { goto ex; } memset(buffer, 0, BLOCK_SIZE); buf = buffer; } /* write the directory entry in any case */ write_one_dir_record(t, child, -1, buf, fi_len, section); buf += len; } } /* write the last block */ ret = iso_write(t, buffer, BLOCK_SIZE); ex:; LIBISO_FREE_MEM(buffer); return ret; } static int write_dirs(Ecma119Image *t, Iso1999Node *root) { int ret; size_t i; /* write all directory entries for this dir */ ret = write_one_dir(t, root); if (ret < 0) { return ret; } /* recurse */ for (i = 0; i < root->info.dir->nchildren; i++) { Iso1999Node *child = root->info.dir->children[i]; if (child->type == ISO1999_DIR) { ret = write_dirs(t, child); if (ret < 0) { return ret; } } } return ISO_SUCCESS; } static int write_path_table(Ecma119Image *t, Iso1999Node **pathlist, int l_type) { size_t i, len; uint8_t *buf = NULL; struct ecma119_path_table_record *rec; void (*write_int)(uint8_t*, uint32_t, int); Iso1999Node *dir; uint32_t path_table_size; int parent = 0; int ret= ISO_SUCCESS; uint8_t *zeros = NULL; /* 256 is just a convenient size large enought */ LIBISO_ALLOC_MEM(buf, uint8_t, 256); path_table_size = 0; write_int = l_type ? iso_lsb : iso_msb; for (i = 0; i < t->iso1999_ndirs; i++) { dir = pathlist[i]; /* find the index of the parent in the table */ while ((i) && pathlist[parent] != dir->parent) { parent++; } /* write the Path Table Record (ECMA-119, 9.4) */ memset(buf, 0, 256); rec = (struct ecma119_path_table_record*) buf; rec->len_di[0] = dir->parent ? (uint8_t) strlen(dir->name) : 1; rec->len_xa[0] = 0; write_int(rec->block, dir->info.dir->block, 4); write_int(rec->parent, parent + 1, 2); if (dir->parent) { memcpy(rec->dir_id, dir->name, rec->len_di[0]); } len = 8 + rec->len_di[0] + (rec->len_di[0] % 2); ret = iso_write(t, buf, len); if (ret < 0) { /* error */ goto ex; } path_table_size += len; } /* we need to fill the last block with zeros */ path_table_size %= BLOCK_SIZE; if (path_table_size) { LIBISO_ALLOC_MEM(zeros, uint8_t, BLOCK_SIZE); len = BLOCK_SIZE - path_table_size; memset(zeros, 0, len); ret = iso_write(t, zeros, len); } ex:; LIBISO_FREE_MEM(zeros); LIBISO_FREE_MEM(buf); return ret; } static int write_path_tables(Ecma119Image *t) { int ret; size_t i, j, cur; Iso1999Node **pathlist; iso_msg_debug(t->image->id, "Writing ISO 9660:1999 Path tables"); /* allocate temporal pathlist */ pathlist = malloc(sizeof(void*) * t->iso1999_ndirs); if (pathlist == NULL) { return ISO_OUT_OF_MEM; } pathlist[0] = t->iso1999_root; cur = 1; for (i = 0; i < t->iso1999_ndirs; i++) { Iso1999Node *dir = pathlist[i]; for (j = 0; j < dir->info.dir->nchildren; j++) { Iso1999Node *child = dir->info.dir->children[j]; if (child->type == ISO1999_DIR) { pathlist[cur++] = child; } } } /* Write L Path Table */ ret = write_path_table(t, pathlist, 1); if (ret < 0) { goto write_path_tables_exit; } /* Write L Path Table */ ret = write_path_table(t, pathlist, 0); write_path_tables_exit: ; free(pathlist); return ret; } static int iso1999_writer_write_data(IsoImageWriter *writer) { int ret; Ecma119Image *t; if (writer == NULL) { return ISO_NULL_POINTER; } t = writer->target; /* first of all, we write the directory structure */ ret = write_dirs(t, t->iso1999_root); if (ret < 0) { return ret; } /* and write the path tables */ ret = write_path_tables(t); return ret; } static int iso1999_writer_free_data(IsoImageWriter *writer) { /* free the ISO 9660:1999 tree */ Ecma119Image *t = writer->target; iso1999_node_free(t->iso1999_root); return ISO_SUCCESS; } int iso1999_writer_create(Ecma119Image *target) { int ret; IsoImageWriter *writer; writer = malloc(sizeof(IsoImageWriter)); if (writer == NULL) { return ISO_OUT_OF_MEM; } writer->compute_data_blocks = iso1999_writer_compute_data_blocks; writer->write_vol_desc = iso1999_writer_write_vol_desc; writer->write_data = iso1999_writer_write_data; writer->free_data = iso1999_writer_free_data; writer->data = NULL; writer->target = target; iso_msg_debug(target->image->id, "Creating low level ISO 9660:1999 tree..."); ret = iso1999_tree_create(target); if (ret < 0) { free((char *) writer); return ret; } /* add this writer to image */ target->writers[target->nwriters++] = writer; /* we need the volume descriptor */ target->curblock++; return ISO_SUCCESS; } libisofs-1.4.2/libisofs/aaip-os-linux.c0000644000175700017510000004104212607175677014750 00000000000000 /* aaip-os-linux.c Arbitrary Attribute Interchange Protocol , system adapter for getting and setting of ACLs and xattr. To be included by aaip_0_2.c for Linux Copyright (c) 2009 - 2011 Thomas Schmitt, libburnia project, GPLv2+ */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif #include #include #include #include #include #include #include #include #ifdef Libisofs_with_aaip_acL #include #endif #ifdef Libisofs_with_aaip_xattR #include #endif /* ------------------------------ Inquiry --------------------------------- */ /* See also API iso_local_attr_support(). @param flag Bitfield for control purposes bit0= inquire availability of ACL bit1= inquire availability of xattr bit2 - bit7= Reserved for future types. It is permissibile to set them to 1 already now. bit8 and higher: reserved, submit 0 @return Bitfield corresponding to flag. If bits are set, th bit0= ACL adapter is enabled bit1= xattr adapter is enabled bit2 - bit7= Reserved for future types. bit8 and higher: reserved, do not interpret these */ int aaip_local_attr_support(int flag) { int ret= 0; #ifdef Libisofs_with_aaip_acL if(flag & 1) ret|= 1; #endif #ifdef Libisofs_with_aaip_xattR if(flag & 2) ret|= 2; #endif return(ret); } /* ------------------------------ Getters --------------------------------- */ /* Obtain the ACL of the given file in long text form. @param path Path to the file @param text Will hold the result. This is a managed object which finally has to be freed by a call to this function with bit15 of flag. @param flag Bitfield for control purposes bit0= obtain default ACL rather than access ACL behave like bit4 if ACL is empty bit4= set *text = NULL and return 2 if the ACL matches st_mode permissions. bit5= in case of symbolic link: inquire link target bit15= free text and return 1 @return 1 ok 2 only st_mode permissions exist and bit 4 is set or empty ACL and bit0 is set 0 ACL support not enabled at compile time or filesystem does not support ACL -1 failure of system ACL service (see errno) -2 attempt to inquire ACL of a symbolic link without bit4 or bit5 or with no suitable link target */ int aaip_get_acl_text(char *path, char **text, int flag) { #ifdef Libisofs_with_aaip_acL acl_t acl= NULL; struct stat stbuf; int ret; if(flag & (1 << 15)) { if(*text != NULL) acl_free(*text); *text= NULL; return(1); } *text= NULL; if(flag & 32) ret= stat(path, &stbuf); else ret= lstat(path, &stbuf); if(ret == -1) return(-1); if((stbuf.st_mode & S_IFMT) == S_IFLNK) { if(flag & 16) return(2); return(-2); } acl= acl_get_file(path, (flag & 1) ? ACL_TYPE_DEFAULT : ACL_TYPE_ACCESS); if(acl == NULL) { if(errno == ENOTSUP) { /* filesystem does not support ACL */ if(flag & 16) return(2); /* >>> ??? fake ACL from POSIX permissions ? */; return(0); } return(-1); } *text= acl_to_text(acl, NULL); acl_free(acl); if(*text == NULL) return(-1); if(flag & 16) { ret = aaip_cleanout_st_mode(*text, &(stbuf.st_mode), 2); if(!(ret & (7 | 64))) (*text)[0]= 0; } if(flag & (1 | 16)) { if((*text)[0] == 0 || strcmp(*text, "\n") == 0) { acl_free(*text); *text= NULL; return(2); } } return(1); #else /* Libisofs_with_aaip_acL */ return(0); #endif /* ! Libisofs_with_aaip_acL */ } /* Obtain the Extended Attributes and/or the ACLs of the given file in a form that is ready for aaip_encode(). @param path Path to the file @param num_attrs Will return the number of name-value pairs @param names Will return an array of pointers to 0-terminated names @param value_lengths Will return an arry with the lenghts of values @param values Will return an array of pointers to 8-bit values @param flag Bitfield for control purposes bit0= obtain ACL (access and eventually default) bit1= use numeric ACL qualifiers rather than names bit2= do not obtain attributes other than ACL bit3= do not ignore eventual non-user attributes I.e. those with a name which does not begin by "user." bit4= do not return trivial ACL that matches st_mode bit5= in case of symbolic link: inquire link target bit15= free memory of names, value_lengths, values @return >0 ok <=0 error -1= out of memory -2= program error with prediction of result size -3= error with conversion of name to uid or gid */ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names, size_t **value_lengths, char ***values, int flag) { int ret; #ifdef Libisofs_with_aaip_acL unsigned char *acl= NULL; char *a_acl_text= NULL, *d_acl_text= NULL; size_t acl_len= 0; #define Libisofs_aaip_get_attr_activE yes #endif #ifdef Libisofs_with_aaip_xattR char *list= NULL; ssize_t value_ret, retry= 0, list_size= 0; #define Libisofs_aaip_get_attr_activE yes #endif #ifdef Libisofs_aaip_get_attr_activE ssize_t i, num_names= 0; #endif if(flag & (1 << 15)) { /* Free memory */ {ret= 1; goto ex;} } *num_attrs= 0; *names= NULL; *value_lengths= NULL; *values= NULL; #ifndef Libisofs_aaip_get_attr_activE ret = 1; ex:; return ret; #else /* Libisofs_aaip_get_attr_activE */ /* Set up arrays */ #ifdef Libisofs_with_aaip_xattR if(!(flag & 4)) { /* Get xattr names */ if(flag & 32) list_size= listxattr(path, list, 0); else list_size= llistxattr(path, list, 0); if(list_size == -1) { if(errno == ENOSYS) /* Function not implemented */ list_size= 0; /* Handle as if xattr was disabled at compile time */ else {ret= -1; goto ex;} } if(list_size > 0) { list= calloc(list_size, 1); if(list == NULL) {ret= -1; goto ex;} if(flag & 32) list_size= listxattr(path, list, list_size); else list_size= llistxattr(path, list, list_size); if(list_size == -1) {ret= -1; goto ex;} } for(i= 0; i < list_size; i+= strlen(list + i) + 1) num_names++; } #endif /* ! Libisofs_with_aaip_xattR */ #ifdef Libisofs_with_aaip_acL if(flag & 1) num_names++; #endif if(num_names == 0) {ret= 1; goto ex;} (*names)= calloc(num_names, sizeof(char *)); (*value_lengths)= calloc(num_names, sizeof(size_t)); (*values)= calloc(num_names, sizeof(char *)); if(*names == NULL || *value_lengths == NULL || *values == NULL) {ret= -1; goto ex;} for(i= 0; i < num_names; i++) { (*names)[i]= NULL; (*values)[i]= NULL; (*value_lengths)[i]= 0; } #ifdef Libisofs_with_aaip_xattR if(!(flag & 4)) { /* Get xattr values */ for(i= 0; i < list_size && (size_t) num_names > *num_attrs; i+= strlen(list + i) + 1) { if(!(flag & 8)) if(strncmp(list + i, "user.", 5)) continue; (*names)[(*num_attrs)++]= strdup(list + i); if((*names)[(*num_attrs) - 1] == NULL) {ret= -1; goto ex;} } for(i= 0; (size_t) i < *num_attrs; i++) { if(!(flag & 8)) if(strncmp((*names)[i], "user.", 5)) continue; if(flag & 32) value_ret= getxattr(path, (*names)[i], NULL, 0); else value_ret= lgetxattr(path, (*names)[i], NULL, 0); if(value_ret == -1) continue; (*values)[i]= calloc(value_ret + 1, 1); if((*values)[i] == NULL) {ret= -1; goto ex;} if(flag & 32) value_ret= getxattr(path, (*names)[i], (*values)[i], value_ret); else value_ret= lgetxattr(path, (*names)[i], (*values)[i], value_ret); if(value_ret == -1) { /* there could be a race condition */ if(retry++ > 5) {ret= -1; goto ex;} i--; continue; } (*value_lengths)[i]= value_ret; retry= 0; } } #endif /* Libisofs_with_aaip_xattR */ #ifdef Libisofs_with_aaip_acL if(flag & 1) { /* Obtain ACL */ aaip_get_acl_text(path, &a_acl_text, flag & (16 | 32)); aaip_get_acl_text(path, &d_acl_text, 1 | (flag & 32)); if(a_acl_text == NULL && d_acl_text == NULL) {ret= 1; goto ex;} ret= aaip_encode_both_acl(a_acl_text, d_acl_text, (mode_t) 0, &acl_len, &acl, (flag & 2)); if(ret <= 0) goto ex; /* Set as attribute with empty name */; (*names)[*num_attrs]= strdup(""); if((*names)[*num_attrs] == NULL) {ret= -1; goto ex;} (*values)[*num_attrs]= (char *) acl; acl= NULL; (*value_lengths)[*num_attrs]= acl_len; (*num_attrs)++; } #endif /* Libisofs_with_aaip_acL */ ret= 1; ex:; #ifdef Libisofs_with_aaip_acL if(a_acl_text != NULL) aaip_get_acl_text("", &a_acl_text, 1 << 15); /* free */ if(d_acl_text != NULL) aaip_get_acl_text("", &d_acl_text, 1 << 15); /* free */ if(acl != NULL) free(acl); #endif #ifdef Libisofs_with_aaip_xattR if(list != NULL) free(list); #endif if(ret <= 0 || (flag & (1 << 15))) { if(*names != NULL) { for(i= 0; (size_t) i < *num_attrs; i++) free((*names)[i]); free(*names); } *names= NULL; if(*value_lengths != NULL) free(*value_lengths); *value_lengths= NULL; if(*values != NULL) { for(i= 0; (size_t) i < *num_attrs; i++) free((*values)[i]); free(*values); } *values= NULL; *num_attrs= 0; } return(ret); #endif /* Libisofs_aaip_get_attr_activE */ } /* ------------------------------ Setters --------------------------------- */ /* Set the ACL of the given file to a given list in long text form. @param path Path to the file @param text The input text (0 terminated, ACL long text form) @param flag Bitfield for control purposes bit0= set default ACL rather than access ACL bit5= in case of symbolic link: manipulate link target @return >0 ok 0 ACL support not enabled at compile time -1 failure of system ACL service (see errno) -2 attempt to manipulate ACL of a symbolic link without bit5 or with no suitable link target */ int aaip_set_acl_text(char *path, char *text, int flag) { #ifdef Libisofs_with_aaip_acL int ret; acl_t acl= NULL; struct stat stbuf; if(flag & 32) ret= stat(path, &stbuf); else ret= lstat(path, &stbuf); if(ret == -1) return(-1); if((stbuf.st_mode & S_IFMT) == S_IFLNK) return(-2); acl= acl_from_text(text); if(acl == NULL) { ret= -1; goto ex; } ret= acl_set_file(path, (flag & 1) ? ACL_TYPE_DEFAULT : ACL_TYPE_ACCESS, acl); if(ret == -1) goto ex; ret= 1; ex: if(acl != NULL) acl_free(acl); return(ret); #else /* Libisofs_with_aaip_acL */ return(0); #endif /* ! Libisofs_with_aaip_acL */ } /* Bring the given attributes and/or ACLs into effect with the given file. @param flag Bitfield for control purposes bit0= decode and set ACLs bit1= first clear all existing attributes of the file bit2= do not set attributes other than ACLs bit3= do not ignore eventual non-user attributes. I.e. those with a name which does not begin by "user." bit5= in case of symbolic link: manipulate link target bit6= tolerate inappropriate presence or absense of directory default ACL @return 1 success -1 error memory allocation -2 error with decoding of ACL -3 error with setting ACL -4 error with setting attribute -5 error with deleting attributes -6 support of xattr not enabled at compile time -7 support of ACL not enabled at compile time ( -8 unsupported xattr namespace ) ISO_AAIP_ACL_MULT_OBJ multiple entries of user::, group::, other:: */ int aaip_set_attr_list(char *path, size_t num_attrs, char **names, size_t *value_lengths, char **values, int flag) { int ret; size_t i, consumed, acl_text_fill, acl_idx= 0; char *acl_text= NULL; #ifdef Libisofs_with_aaip_xattR char *list= NULL; ssize_t list_size= 0; #endif #ifdef Libisofs_with_aaip_acL size_t h_consumed; int has_default_acl= 0; #endif #ifdef Libisofs_with_aaip_xattR if(flag & 2) { /* Delete all file attributes */ if(flag & 32) list_size= listxattr(path, list, 0); else list_size= llistxattr(path, list, 0); } if(list_size > 0) { /* Delete all file attributes */ list= calloc(list_size, 1); if(list == NULL) {ret= -5; goto ex;} if(flag & 32) list_size= listxattr(path, list, list_size); else list_size= llistxattr(path, list, list_size); if(list_size == -1) {ret= -5; goto ex;} for(i= 0; i < (size_t) list_size; i+= strlen(list + i) + 1) { if(!(flag & 8)) if(strncmp(list + i, "user.", 5)) continue; if(flag & 32) ret= removexattr(path, list + i); else ret= lremovexattr(path, list + i); if(ret == -1) {ret= -5; goto ex;} } free(list); list= NULL; } #endif /* Libisofs_with_aaip_xattR */ for(i= 0; i < num_attrs; i++) { if(names[i] == NULL || values[i] == NULL) continue; if(names[i][0] == 0) { /* ACLs */ if(flag & 1) acl_idx= i + 1; continue; } /* Extended Attribute */ if(flag & 4) continue; if(strncmp(names[i], "isofs.", 6) == 0) continue; if(!(flag & 8)) if(strncmp(names[i], "user.", 5)) continue; #ifdef Libisofs_with_aaip_xattR if(flag & 32) ret= setxattr(path, names[i], values[i], value_lengths[i], 0); else ret= lsetxattr(path, names[i], values[i], value_lengths[i], 0); if(ret == -1) {ret= -4; goto ex;} #else {ret= -6; goto ex;} #endif /* Libisofs_with_aaip_xattR */ } /* Decode ACLs */ if(acl_idx == 0) {ret= 1; goto ex;} i= acl_idx - 1; /* "access" ACL */ ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i], &consumed, NULL, 0, &acl_text_fill, 1); if(ret < -3) goto ex; if(ret <= 0) {ret= -2; goto ex;} acl_text= calloc(acl_text_fill, 1); if(acl_text == NULL) {ret= -1; goto ex;} ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i], &consumed, acl_text, acl_text_fill, &acl_text_fill, 0); if(ret < -3) goto ex; if(ret <= 0) {ret= -2; goto ex;} #ifdef Libisofs_with_aaip_acL has_default_acl= (ret == 2); ret= aaip_set_acl_text(path, acl_text, flag & 32); if(ret <= 0) {ret= -3; goto ex;} /* "default" ACL */ if(has_default_acl) { free(acl_text); acl_text= NULL; ret= aaip_decode_acl((unsigned char *) (values[i] + consumed), value_lengths[i] - consumed, &h_consumed, NULL, 0, &acl_text_fill, 1); if(ret < -3) goto ex; if(ret <= 0) {ret= -2; goto ex;} acl_text= calloc(acl_text_fill, 1); if(acl_text == NULL) {ret= -1; goto ex;} ret= aaip_decode_acl((unsigned char *) (values[i] + consumed), value_lengths[i] - consumed, &h_consumed, acl_text, acl_text_fill, &acl_text_fill, 0); if(ret < -3) goto ex; if(ret <= 0) {ret= -2; goto ex;} ret= aaip_set_acl_text(path, acl_text, 1 | (flag & 32)); if(ret <= 0) {ret= -3; goto ex;} } else { if(!(flag & 64)) { /* >>> ??? take offense from missing default ACL ? ??? does Linux demand a default ACL for directories with access ACL ? */; } } ret= 1; #else ret= -7; #endif /* !Libisofs_with_aaip_acL */ ex:; if(acl_text != NULL) free(acl_text); #ifdef Libisofs_with_aaip_xattR if(list != NULL) free(list); #endif return(ret); } libisofs-1.4.2/libisofs/tree.c0000644000175700017510000013513212606463536013216 00000000000000/* * Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2011 - 2015 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ /* * Functions that act on the iso tree. */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif #include "libisofs.h" #include "node.h" #include "image.h" #include "fsource.h" #include "builder.h" #include "messages.h" #include "tree.h" #include "util.h" #include #include #include #include #include #include /** * Add a new directory to the iso tree. * * @param parent * the dir where the new directory will be created * @param name * name for the new dir. If a node with same name already exists on * parent, this functions fails with ISO_NODE_NAME_NOT_UNIQUE. * @param dir * place where to store a pointer to the newly created dir. No extra * ref is addded, so you will need to call iso_node_ref() if you really * need it. You can pass NULL in this parameter if you don't need the * pointer. * @return * number of nodes in dir if succes, < 0 otherwise * Possible errors: * ISO_NULL_POINTER, if parent or name are NULL * ISO_NODE_NAME_NOT_UNIQUE, a node with same name already exists */ int iso_tree_add_new_dir(IsoDir *parent, const char *name, IsoDir **dir) { int ret; char *n; IsoDir *node; IsoNode **pos; time_t now; if (parent == NULL || name == NULL) { return ISO_NULL_POINTER; } if (dir) { *dir = NULL; } /* find place where to insert and check if it exists */ if (iso_dir_exists(parent, name, &pos)) { /* a node with same name already exists */ return ISO_NODE_NAME_NOT_UNIQUE; } n = strdup(name); ret = iso_node_new_dir(n, &node); if (ret < 0) { free(n); return ret; } /* permissions from parent */ iso_node_set_permissions((IsoNode*)node, parent->node.mode); iso_node_set_uid((IsoNode*)node, parent->node.uid); iso_node_set_gid((IsoNode*)node, parent->node.gid); iso_node_set_hidden((IsoNode*)node, parent->node.hidden); /* current time */ now = time(NULL); iso_node_set_atime((IsoNode*)node, now); iso_node_set_ctime((IsoNode*)node, now); iso_node_set_mtime((IsoNode*)node, now); if (dir) { *dir = node; } /* add to dir */ return iso_dir_insert(parent, (IsoNode*)node, pos, ISO_REPLACE_NEVER); } int iso_image_add_new_dir(IsoImage *image, IsoDir *parent, const char *name, IsoDir **dir) { int ret; char *namept; ret = iso_image_truncate_name(image, name, &namept, 0); if (ret < 0) return ret; ret = iso_tree_add_new_dir(parent, namept, dir); return ret; } /** * Add a new symlink to the directory tree. Permissions are set to 0777, * owner and hidden atts are taken from parent. You can modify any of them * later. * * @param parent * the dir where the new symlink will be created * @param name * name for the new dir. If a node with same name already exists on * parent, this functions fails with ISO_NODE_NAME_NOT_UNIQUE. * @param dest * destination of the link * @param link * place where to store a pointer to the newly created link. No extra * ref is addded, so you will need to call iso_node_ref() if you really * need it. You can pass NULL in this parameter if you don't need the * pointer * @return * number of nodes in parent if success, < 0 otherwise * Possible errors: * ISO_NULL_POINTER, if parent, name or dest are NULL * ISO_NODE_NAME_NOT_UNIQUE, a node with same name already exists * ISO_OUT_OF_MEM */ int iso_tree_add_new_symlink(IsoDir *parent, const char *name, const char *dest, IsoSymlink **link) { int ret; char *n, *d; IsoSymlink *node; IsoNode **pos; time_t now; if (parent == NULL || name == NULL || dest == NULL) { return ISO_NULL_POINTER; } if (link) { *link = NULL; } /* find place where to insert */ if (iso_dir_exists(parent, name, &pos)) { /* a node with same name already exists */ return ISO_NODE_NAME_NOT_UNIQUE; } n = strdup(name); d = strdup(dest); ret = iso_node_new_symlink(n, d, &node); if (ret < 0) { free(n); free(d); return ret; } /* permissions from parent */ iso_node_set_permissions((IsoNode*)node, 0777); iso_node_set_uid((IsoNode*)node, parent->node.uid); iso_node_set_gid((IsoNode*)node, parent->node.gid); iso_node_set_hidden((IsoNode*)node, parent->node.hidden); /* current time */ now = time(NULL); iso_node_set_atime((IsoNode*)node, now); iso_node_set_ctime((IsoNode*)node, now); iso_node_set_mtime((IsoNode*)node, now); if (link) { *link = node; } /* add to dir */ return iso_dir_insert(parent, (IsoNode*)node, pos, ISO_REPLACE_NEVER); } int iso_image_add_new_symlink(IsoImage *image, IsoDir *parent, const char *name, const char *dest, IsoSymlink **link) { int ret; char *namept; ret = iso_image_truncate_name(image, name, &namept, 0); if (ret < 0) return ret; ret = iso_tree_add_new_symlink(parent, namept, dest, link); return ret; } /** * Add a new special file to the directory tree. As far as libisofs concerns, * an special file is a block device, a character device, a FIFO (named pipe) * or a socket. You can choose the specific kind of file you want to add * by setting mode propertly (see man 2 stat). * * Note that special files are only written to image when Rock Ridge * extensions are enabled. Moreover, a special file is just a directory entry * in the image tree, no data is written beyond that. * * Owner and hidden atts are taken from parent. You can modify any of them * later. * * @param parent * the dir where the new special file will be created * @param name * name for the new special file. If a node with same name already exists * on parent, this functions fails with ISO_NODE_NAME_NOT_UNIQUE. * @param mode * file type and permissions for the new node. Note that you can't * specify any kind of file here, only special types are allowed. i.e, * S_IFSOCK, S_IFBLK, S_IFCHR and S_IFIFO are valid types; S_IFLNK, * S_IFREG and S_IFDIR aren't. * @param dev * device ID, equivalent to the st_rdev field in man 2 stat. * @param special * place where to store a pointer to the newly created special file. No * extra ref is addded, so you will need to call iso_node_ref() if you * really need it. You can pass NULL in this parameter if you don't need * the pointer. * @return * number of nodes in parent if success, < 0 otherwise * Possible errors: * ISO_NULL_POINTER, if parent, name or dest are NULL * ISO_NODE_NAME_NOT_UNIQUE, a node with same name already exists * ISO_OUT_OF_MEM * */ int iso_tree_add_new_special(IsoDir *parent, const char *name, mode_t mode, dev_t dev, IsoSpecial **special) { int ret; char *n; IsoSpecial *node; IsoNode **pos; time_t now; if (parent == NULL || name == NULL) { return ISO_NULL_POINTER; } if (S_ISLNK(mode) || S_ISREG(mode) || S_ISDIR(mode)) { return ISO_WRONG_ARG_VALUE; } if (special) { *special = NULL; } /* find place where to insert */ if (iso_dir_exists(parent, name, &pos)) { /* a node with same name already exists */ return ISO_NODE_NAME_NOT_UNIQUE; } n = strdup(name); ret = iso_node_new_special(n, mode, dev, &node); if (ret < 0) { free(n); return ret; } /* atts from parent */ iso_node_set_uid((IsoNode*)node, parent->node.uid); iso_node_set_gid((IsoNode*)node, parent->node.gid); iso_node_set_hidden((IsoNode*)node, parent->node.hidden); /* current time */ now = time(NULL); iso_node_set_atime((IsoNode*)node, now); iso_node_set_ctime((IsoNode*)node, now); iso_node_set_mtime((IsoNode*)node, now); if (special) { *special = node; } /* add to dir */ return iso_dir_insert(parent, (IsoNode*)node, pos, ISO_REPLACE_NEVER); } int iso_image_add_new_special(IsoImage *image, IsoDir *parent, const char *name, mode_t mode, dev_t dev, IsoSpecial **special) { int ret; char *namept; ret = iso_image_truncate_name(image, name, &namept, 0); if (ret < 0) return ret; ret = iso_tree_add_new_special(parent, namept, mode, dev, special); return ret; } /** * Add a new regular file to the iso tree. Permissions are set to 0444, * owner and hidden atts are taken from parent. You can modify any of them * later. * * @param parent * the dir where the new file will be created * @param name * name for the new file. If a node with same name already exists on * parent, this functions fails with ISO_NODE_NAME_NOT_UNIQUE. * @param stream * IsoStream for the contents of the file * @param file * place where to store a pointer to the newly created file. No extra * ref is addded, so you will need to call iso_node_ref() if you really * need it. You can pass NULL in this parameter if you don't need the * pointer * @return * number of nodes in parent if success, < 0 otherwise * Possible errors: * ISO_NULL_POINTER, if parent, name or dest are NULL * ISO_NODE_NAME_NOT_UNIQUE, a node with same name already exists * ISO_OUT_OF_MEM * * @since 0.6.4 */ int iso_tree_add_new_file(IsoDir *parent, const char *name, IsoStream *stream, IsoFile **file) { int ret; char *n; IsoFile *node; IsoNode **pos; time_t now; if (parent == NULL || name == NULL || stream == NULL) { return ISO_NULL_POINTER; } if (file) { *file = NULL; } /* find place where to insert */ if (iso_dir_exists(parent, name, &pos)) { /* a node with same name already exists */ return ISO_NODE_NAME_NOT_UNIQUE; } n = strdup(name); ret = iso_node_new_file(n, stream, &node); if (ret < 0) { free(n); return ret; } /* permissions from parent */ iso_node_set_permissions((IsoNode*)node, 0444); iso_node_set_uid((IsoNode*)node, parent->node.uid); iso_node_set_gid((IsoNode*)node, parent->node.gid); iso_node_set_hidden((IsoNode*)node, parent->node.hidden); /* current time */ now = time(NULL); iso_node_set_atime((IsoNode*)node, now); iso_node_set_ctime((IsoNode*)node, now); iso_node_set_mtime((IsoNode*)node, now); if (file) { *file = node; } /* add to dir */ return iso_dir_insert(parent, (IsoNode*)node, pos, ISO_REPLACE_NEVER); } int iso_image_add_new_file(IsoImage *image, IsoDir *parent, const char *name, IsoStream *stream, IsoFile **file) { int ret; char *namept; ret = iso_image_truncate_name(image, name, &namept, 0); if (ret < 0) return ret; ret = iso_tree_add_new_file(parent, namept, stream, file); return ret; } /** * Set whether to follow or not symbolic links when added a file from a source * to IsoImage. */ void iso_tree_set_follow_symlinks(IsoImage *image, int follow) { image->follow_symlinks = follow ? 1 : 0; } /** * Get current setting for follow_symlinks. * * @see iso_tree_set_follow_symlinks */ int iso_tree_get_follow_symlinks(IsoImage *image) { return image->follow_symlinks; } /** * Set whether to skip or not hidden files when adding a directory recursibely. * Default behavior is to not ignore them, i.e., to add hidden files to image. */ void iso_tree_set_ignore_hidden(IsoImage *image, int skip) { image->ignore_hidden = skip ? 1 : 0; } /** * Get current setting for ignore_hidden. * * @see iso_tree_set_ignore_hidden */ int iso_tree_get_ignore_hidden(IsoImage *image) { return image->ignore_hidden; } void iso_tree_set_replace_mode(IsoImage *image, enum iso_replace_mode mode) { image->replace = mode; } enum iso_replace_mode iso_tree_get_replace_mode(IsoImage *image) { return image->replace; } /** * Set whether to skip or not special files. Default behavior is to not skip * them. Note that, despite of this setting, special files won't never be added * to an image unless RR extensions were enabled. * * @param skip * Bitmask to determine what kind of special files will be skipped: * bit0: ignore FIFOs * bit1: ignore Sockets * bit2: ignore char devices * bit3: ignore block devices */ void iso_tree_set_ignore_special(IsoImage *image, int skip) { image->ignore_special = skip & 0x0F; } /** * Get current setting for ignore_special. * * @see iso_tree_set_ignore_special */ int iso_tree_get_ignore_special(IsoImage *image) { return image->ignore_special; } /** * Set a callback function that libisofs will call for each file that is * added to the given image by a recursive addition function. This includes * image import. * * @param report * pointer to a function that will be called just before a file will be * added to the image. You can control whether the file will be in fact * added or ignored. * This function should return 1 to add the file, 0 to ignore it and * continue, < 0 to abort the process * NULL is allowed if you don't want any callback. */ void iso_tree_set_report_callback(IsoImage *image, int (*report)(IsoImage*, IsoFileSource*)) { image->report = report; } /** * Add a excluded path. These are paths that won't never added to image, * and will be excluded even when adding recursively its parent directory. * * For example, in * * iso_tree_add_exclude(image, "/home/user/data/private"); * iso_tree_add_dir_rec(image, root, "/home/user/data"); * * the directory /home/user/data/private won't be added to image. * * @return * 1 on success, < 0 on error */ int iso_tree_add_exclude(IsoImage *image, const char *path) { if (image == NULL || path == NULL) { return ISO_NULL_POINTER; } image->excludes = realloc(image->excludes, ++image->nexcludes * sizeof(void*)); if (image->excludes == NULL) { return ISO_OUT_OF_MEM; } image->excludes[image->nexcludes - 1] = strdup(path); if (image->excludes[image->nexcludes - 1] == NULL) { return ISO_OUT_OF_MEM; } return ISO_SUCCESS; } /** * Remove a previously added exclude. * * @see iso_tree_add_exclude * @return * 1 on success, 0 exclude do not exists, < 0 on error */ int iso_tree_remove_exclude(IsoImage *image, const char *path) { size_t i, j; if (image == NULL || path == NULL) { return ISO_NULL_POINTER; } for (i = 0; (int) i < image->nexcludes; ++i) { if (strcmp(image->excludes[i], path) == 0) { /* exclude found */ free(image->excludes[i]); --image->nexcludes; for (j = i; (int) j < image->nexcludes; ++j) { image->excludes[j] = image->excludes[j+1]; } image->excludes = realloc(image->excludes, image->nexcludes * sizeof(void*)); return ISO_SUCCESS; } } return 0; } static int iso_tree_add_node_builder(IsoImage *image, IsoDir *parent, IsoFileSource *src, IsoNodeBuilder *builder, IsoNode **node) { int result; IsoNode *new; IsoNode **pos; char *name = NULL, *namept; if (parent == NULL || src == NULL || builder == NULL) { result = ISO_NULL_POINTER; goto ex; } if (node) { *node = NULL; } name = iso_file_source_get_name(src); result = iso_image_truncate_name(image, name, &namept, 0); if (result < 0) return result; /* find place where to insert */ result = iso_dir_exists(parent, namept, &pos); if (result) { /* a node with same name already exists */ result = ISO_NODE_NAME_NOT_UNIQUE; goto ex; } result = builder->create_node(builder, image, src, namept, &new); if (result < 0) goto ex; if (node) { *node = new; } /* finally, add node to parent */ result = iso_dir_insert(parent, (IsoNode*)new, pos, ISO_REPLACE_NEVER); ex: if (name != NULL) free(name); return result; } int iso_tree_add_node(IsoImage *image, IsoDir *parent, const char *path, IsoNode **node) { int result; IsoFilesystem *fs; IsoFileSource *file; if (image == NULL || parent == NULL || path == NULL) { return ISO_NULL_POINTER; } fs = image->fs; result = fs->get_by_path(fs, path, &file); if (result < 0) { return result; } result = iso_tree_add_node_builder(image, parent, file, image->builder, node); /* free the file */ iso_file_source_unref(file); return result; } int iso_tree_add_new_node(IsoImage *image, IsoDir *parent, const char *name, const char *path, IsoNode **node) { int result; IsoFilesystem *fs; IsoFileSource *file; IsoNode *new; IsoNode **pos; char *namept; if (image == NULL || parent == NULL || name == NULL || path == NULL) { return ISO_NULL_POINTER; } if (node) { *node = NULL; } result = iso_image_truncate_name(image, name, &namept, 0); if (result < 0) return result; /* find place where to insert */ result = iso_dir_exists(parent, namept, &pos); if (result) { /* a node with same name already exists */ return ISO_NODE_NAME_NOT_UNIQUE; } fs = image->fs; result = fs->get_by_path(fs, path, &file); if (result < 0) { return result; } result = image->builder->create_node(image->builder, image, file, namept, &new); /* free the file */ iso_file_source_unref(file); if (result < 0) { return result; } if (node) { *node = new; } /* finally, add node to parent */ return iso_dir_insert(parent, new, pos, ISO_REPLACE_NEVER); } int iso_tree_add_new_cut_out_node(IsoImage *image, IsoDir *parent, const char *name, const char *path, off_t offset, off_t size, IsoNode **node) { int result; struct stat info; IsoFilesystem *fs; IsoFileSource *src; IsoFile *new; IsoNode **pos; IsoStream *stream; char *namept; if (image == NULL || parent == NULL || name == NULL || path == NULL) { return ISO_NULL_POINTER; } if (node) { *node = NULL; } result = iso_image_truncate_name(image, name, &namept, 0); if (result < 0) return result; /* find place where to insert */ result = iso_dir_exists(parent, namept, &pos); if (result) { /* a node with same name already exists */ return ISO_NODE_NAME_NOT_UNIQUE; } fs = image->fs; result = fs->get_by_path(fs, path, &src); if (result < 0) { return result; } result = iso_file_source_stat(src, &info); if (result < 0) { iso_file_source_unref(src); return result; } if (!S_ISREG(info.st_mode)) { return ISO_WRONG_ARG_VALUE; } if (offset >= info.st_size) { return ISO_WRONG_ARG_VALUE; } /* force regular file */ result = image->builder->create_file(image->builder, image, src, &new); /* free the file */ iso_file_source_unref(src); if (result < 0) { return result; } /* replace file iso stream with a cut-out-stream */ result = iso_cut_out_stream_new(src, offset, size, &stream); if (result < 0) { iso_node_unref((IsoNode*)new); return result; } iso_stream_unref(new->stream); new->stream = stream; result = iso_node_set_name((IsoNode*)new, namept); if (result < 0) { iso_node_unref((IsoNode*)new); return result; } if (node) { *node = (IsoNode*)new; } /* finally, add node to parent */ return iso_dir_insert(parent, (IsoNode*)new, pos, ISO_REPLACE_NEVER); } static int check_excludes(IsoImage *image, const char *path) { int i; for (i = 0; i < image->nexcludes; ++i) { char *exclude = image->excludes[i]; if (exclude[0] == '/') { /* absolute exclude, must completely match path */ if (!fnmatch(exclude, path, FNM_PERIOD|FNM_PATHNAME)) { return 1; } } else { /* relative exclude, it is enought if a part of the path matches */ char *pos = (char*)path; while (pos != NULL) { pos++; if (!fnmatch(exclude, pos, FNM_PERIOD|FNM_PATHNAME)) { return 1; } pos = strchr(pos, '/'); } } } return 0; } static int check_hidden(IsoImage *image, const char *name) { return (image->ignore_hidden && name[0] == '.'); } static int check_special(IsoImage *image, mode_t mode) { if (image->ignore_special != 0) { switch(mode & S_IFMT) { case S_IFBLK: return image->ignore_special & 0x08 ? 1 : 0; case S_IFCHR: return image->ignore_special & 0x04 ? 1 : 0; case S_IFSOCK: return image->ignore_special & 0x02 ? 1 : 0; case S_IFIFO: return image->ignore_special & 0x01 ? 1 : 0; default: return 0; } } return 0; } static void ascii_increment(char *name, int len, int pos, int rollover_carry) { int c; again:; if (pos < 0 || pos >= len) pos = len - 1; c = name[pos]; if (c >= '0' && c < '9') { c++; } else if (c == '9') { c = 'A'; } else if (c >= 'A' && c < 'Z') { c++; } else if (c == 'Z') { c = '_'; } else if (c == '_') { c = 'a'; } else if (c >= 'a' && c < 'z') { c++; } else if (c == 'z') { c = '0'; name[pos] = c; pos--; if (pos >= 0 || rollover_carry) goto again; return; } else { if (pos == len - 1 || name[pos + 1] == '.') c = '_'; /* Make first change less riddling */ else c = '0'; /* But else use the full range of valid characters */ } name[pos] = c; } static int insert_underscores(char *name, int *len, int *at_pos, int count, char **new_name) { int ret; LIBISO_ALLOC_MEM(*new_name, char, count + *len + 1); if (*at_pos > 0) memcpy(*new_name, name, *at_pos); if (count > 0) memset(*new_name + *at_pos, '_', count); if (*len > *at_pos) memcpy(*new_name + *at_pos + count, name + *at_pos, *len - *at_pos); (*new_name)[count + *len] = 0; *len += count; *at_pos += count; ret= ISO_SUCCESS; ex:; return ret; } static int make_incrementable_name(char **name, char **unique_name, int *low_pos, int *rollover_carry, int *pre_check) { char *dpt, *npt; int first, len, ret; /* The incrementable part of the file shall have at least 7 characters. There may be up to pow(2.0,32.0)*2048/33 = 266548273400 files. The set of increment result characters has 63 elements. pow(63.0,7.0) is nearly 15 times larger than 266548273400. */ static int min_incr = 7; /* At most two suffixes of total length up to 12, like .tar.bz2, shall be preserved. The incrementable part will eventually be padded up. Incrementing begins before the last suffix in any case. But when this rolls over on short prefixes, then long last suffixes will get used as high characters of the incremental part. This is indicated by *rollover_carry which corresponds to the parameter of ascii_increment() with the same name. */ static int max_suffix = 12; *rollover_carry = 0; *pre_check = 0; len = strlen(*name); /* Check if the part before the first dot is long enough. If not, then preserve the last two short suffixes. */ dpt = strchr(*name, '.'); if (dpt != NULL) if ((dpt - *name) < min_incr) dpt = strrchr(*name, '.'); if (dpt != NULL) { first= (dpt - *name); if (dpt > *name && len - first < max_suffix) { for(npt = dpt - 1; npt >= *name && *npt != '.'; npt--); if (npt >= *name) { if (len - (npt - *name) <= max_suffix) { first= (npt - *name); dpt = npt; } } } } else first= len; if (first < min_incr && (len - first) <= max_suffix) { ret = insert_underscores(*name, &len, &first, min_incr - first, unique_name); if (ret < 0) goto ex; *pre_check = 1; /* It might now already be unique */ } else if (len < 64) { /* Insert an underscore to preserve the original name at least for the first few increments */ ret = insert_underscores(*name, &len, &first, 1, unique_name); if (ret < 0) goto ex; *pre_check = 1; } else { LIBISO_ALLOC_MEM(*unique_name, char, len + 1); memcpy(*unique_name, *name, len); if (first < min_incr) *rollover_carry = 1; /* Do not get caged before the dots */ } (*unique_name)[len] = 0; *low_pos = first - 1; ret = 1; ex:; return(ret); } static int make_really_unique_name(IsoDir *parent, char **name, char **unique_name, IsoNode ***pos, int flag) { int ret, rollover_carry = 0, pre_check = 0, ascii_idx = -1, len; ret = make_incrementable_name(name, unique_name, &ascii_idx, &rollover_carry, &pre_check); if (ret < 0) goto ex; len = strlen(*unique_name); while (1) { if (!pre_check) ascii_increment(*unique_name, len, ascii_idx, !!rollover_carry); else pre_check = 0; ret = iso_dir_exists(parent, *unique_name, pos); if (ret < 0) goto ex; if (ret == 0) break; } *name = *unique_name; ret = ISO_SUCCESS; ex:; if (ret < 0) { LIBISO_FREE_MEM(*unique_name); *unique_name = NULL; } return ret; } /** * Recursively add a given directory to the image tree. * * @return * 1 continue, < 0 error (ISO_CANCELED stop) */ int iso_add_dir_src_rec(IsoImage *image, IsoDir *parent, IsoFileSource *dir) { int ret, dir_is_open = 0; IsoNodeBuilder *builder; IsoFileSource *file; IsoNode **pos; struct stat info; char *name, *path, *allocated_name = NULL; IsoNode *new; enum iso_replace_mode replace; ret = iso_file_source_open(dir); if (ret < 0) { path = iso_file_source_get_path(dir); /* instead of the probable error, we throw a sorry event */ if (path != NULL) { ret = iso_msg_submit(image->id, ISO_FILE_CANT_ADD, ret, "Can't open dir %s", path); free(path); } else { ret = iso_msg_submit(image->id, ISO_NULL_POINTER, ret, "Can't open dir. NULL pointer caught as dir name"); } goto ex; } dir_is_open = 1; builder = image->builder; /* iterate over all directory children */ while (1) { int skip = 0; ret = iso_file_source_readdir(dir, &file); if (ret <= 0) { if (ret < 0) { /* error reading dir */ ret = iso_msg_submit(image->id, ret, ret, "Error reading dir"); goto ex; } break; /* End of directory */ } path = iso_file_source_get_path(file); if (path == NULL) { ret = iso_msg_submit(image->id, ISO_NULL_POINTER, ret, "NULL pointer caught as file path"); goto ex; } name = strrchr(path, '/') + 1; if (image->follow_symlinks) { ret = iso_file_source_stat(file, &info); } else { ret = iso_file_source_lstat(file, &info); } if (ret < 0) { ret = iso_msg_submit(image->id, ISO_FILE_CANT_ADD, ret, "Error when adding file %s", path); goto dir_rec_continue; } if (check_excludes(image, path)) { iso_msg_debug(image->id, "Skipping excluded file %s", path); skip = 1; } else if (check_hidden(image, name)) { iso_msg_debug(image->id, "Skipping hidden file %s", path); skip = 1; } else if (check_special(image, info.st_mode)) { iso_msg_debug(image->id, "Skipping special file %s", path); skip = 1; } if (skip) { goto dir_rec_continue; } replace = image->replace; /* find place where to insert */ ret = iso_dir_exists(parent, name, &pos); if (ret) { /* Resolve name collision e.g. caused by fs_image.c:make_hopefully_unique_name() */ LIBISO_FREE_MEM(allocated_name); allocated_name = NULL; ret = make_really_unique_name(parent, &name, &allocated_name, &pos, 0); if (ret < 0) goto ex; image->collision_warnings++; if (image->collision_warnings < ISO_IMPORT_COLL_WARN_MAX) { ret = iso_msg_submit(image->id, ISO_IMPORT_COLLISION, 0, "File name collision resolved with %s . Now: %s", path, name); if (ret < 0) goto ex; } } /* if we are here we must insert. Give user a chance for cancel */ if (image->report) { int r = image->report(image, file); if (r <= 0) { ret = (r < 0 ? ISO_CANCELED : ISO_SUCCESS); goto dir_rec_continue; } } ret = builder->create_node(builder, image, file, name, &new); if (ret < 0) { ret = iso_msg_submit(image->id, ISO_FILE_CANT_ADD, ret, "Error when adding file %s", path); goto dir_rec_continue; } /* ok, node has correctly created, we need to add it */ ret = iso_dir_insert(parent, new, pos, replace); if (ret < 0) { iso_node_unref(new); if (ret != (int) ISO_NODE_NAME_NOT_UNIQUE) { /* error */ goto dir_rec_continue; } else { /* file ignored because a file with same node already exists */ iso_msg_debug(image->id, "Skipping file %s. A node with same " "file already exists", path); ret = 0; } } else { iso_msg_debug(image->id, "Added file %s", path); } /* finally, if the node is a directory we need to recurse */ if (new->type == LIBISO_DIR && S_ISDIR(info.st_mode)) { ret = iso_add_dir_src_rec(image, (IsoDir*)new, file); } dir_rec_continue:; free(path); iso_file_source_unref(file); /* check for error severity to decide what to do */ if (ret < 0) { ret = iso_msg_submit(image->id, ret, 0, NULL); if (ret < 0) goto ex; } } /* while */ ret = ISO_SUCCESS; ex:; if (dir_is_open) iso_file_source_close(dir); LIBISO_FREE_MEM(allocated_name); return ret; } int iso_tree_add_dir_rec(IsoImage *image, IsoDir *parent, const char *dir) { int result; struct stat info; IsoFilesystem *fs; IsoFileSource *file; if (image == NULL || parent == NULL || dir == NULL) { return ISO_NULL_POINTER; } fs = image->fs; result = fs->get_by_path(fs, dir, &file); if (result < 0) { return result; } /* we also allow dir path to be a symlink to a dir */ result = iso_file_source_stat(file, &info); if (result < 0) { iso_file_source_unref(file); return result; } if (!S_ISDIR(info.st_mode)) { iso_file_source_unref(file); return ISO_FILE_IS_NOT_DIR; } result = iso_add_dir_src_rec(image, parent, file); iso_file_source_unref(file); return result; } /* @param flag bit0= truncate according to image truncate mode and length */ int iso_tree_path_to_node_flag(IsoImage *image, const char *path, IsoNode **node, int flag) { int result; IsoNode *n; IsoDir *dir; char *ptr, *brk_info = NULL, *component; if (image == NULL || path == NULL) { return ISO_NULL_POINTER; } /* get the first child at the root of the image that is "/" */ dir = image->root; n = (IsoNode *)dir; if (!strcmp(path, "/")) { if (node) { *node = n; } return ISO_SUCCESS; } ptr = strdup(path); if (ptr == NULL) return ISO_OUT_OF_MEM; result = 0; /* get the first component of the path */ component = strtok_r(ptr, "/", &brk_info); while (component) { if (n->type != LIBISO_DIR) { n = NULL; result = 0; break; } dir = (IsoDir *)n; if ((flag & 1) && image->truncate_mode == 1) { result = iso_dir_get_node_trunc(dir, image->truncate_length, component, &n); } else { result = iso_dir_get_node(dir, component, &n); } if (result != 1) { n = NULL; break; } component = strtok_r(NULL, "/", &brk_info); } free(ptr); if (node) { *node = n; } return result; } int iso_tree_path_to_node(IsoImage *image, const char *path, IsoNode **node) { return iso_tree_path_to_node_flag(image, path, node, 0); } int iso_image_path_to_node(IsoImage *image, const char *path, IsoNode **node) { return iso_tree_path_to_node_flag(image, path, node, 1); } char *iso_tree_get_node_path(IsoNode *node) { char *path = NULL, *parent_path = NULL; if (node == NULL || node->parent == NULL) return NULL; if ((IsoNode*)node->parent == node) { return strdup("/"); } else { parent_path = iso_tree_get_node_path((IsoNode*)node->parent); if (parent_path == NULL) goto ex; if (strlen(parent_path) == 1) { path = calloc(1, strlen(node->name) + 2); if (path == NULL) goto ex; sprintf(path, "/%s", node->name); } else { path = calloc(1, strlen(parent_path) + strlen(node->name) + 2); if (path == NULL) goto ex; sprintf(path, "%s/%s", parent_path, node->name); } } ex:; if (parent_path != NULL) free(parent_path); return path; } /* Note: No reference is taken to the found node. @param flag bit0= recursion */ int iso_tree_get_node_of_block(IsoImage *image, IsoDir *dir, uint32_t block, IsoNode **found, uint32_t *next_above, int flag) { int ret, section_count, i; IsoDirIter *iter = NULL; IsoNode *node; IsoDir *subdir; IsoFile *file; struct iso_file_section *sections = NULL; uint32_t na = 0; if (dir == NULL) dir = image->root; ret = iso_dir_get_children(dir, &iter); while (iso_dir_iter_next(iter, &node) == 1 ) { if (ISO_NODE_IS_FILE(node)) { file = (IsoFile *) node; ret = iso_file_get_old_image_sections(file, §ion_count, §ions, 0); if (ret <= 0) continue; for (i = 0; i < section_count; i++) { if (sections[i].block <= block && block - sections[i].block < (((off_t) sections[i].size) + 2047) / 2048) { *found = node; ret = 1; goto ex; } if ((na == 0 || sections[i].block < na) && sections[i].block > block) na = sections[i].block; } free(sections); sections = NULL; } else if (ISO_NODE_IS_DIR(node)) { subdir = (IsoDir *) node; ret = iso_tree_get_node_of_block(image, subdir, block, found, &na, 1); if (ret != 0) goto ex; } } if (next_above != NULL && (na > 0 || !(flag & 1))) if (*next_above == 0 || *next_above > na || !(flag & 1)) *next_above = na; ret = 0; ex: if (sections != NULL) free(sections); if (iter != NULL) iso_dir_iter_free(iter); return ret; } /* ------------------------- tree cloning ------------------------------ */ static int iso_tree_copy_node_attr(IsoNode *old_node, IsoNode *new_node, int flag) { int ret; new_node->mode = old_node->mode; new_node->uid = old_node->uid; new_node->gid = old_node->gid; new_node->atime = old_node->atime; new_node->mtime = old_node->mtime; new_node->ctime = old_node->ctime; new_node->hidden = old_node->hidden; ret = iso_node_clone_xinfo(old_node, new_node, 0); if (ret < 0) return ret; return ISO_SUCCESS; } /* @param flag bit0= merge directory with *new_node */ static int iso_tree_clone_dir(IsoDir *old_dir, IsoDir *new_parent, char *new_name, IsoNode **new_node, int flag) { IsoDir *new_dir = NULL; IsoNode *sub_node = NULL, *new_sub_node = NULL; IsoDirIter *iter = NULL; int ret; if (flag & 1) { new_dir = (IsoDir *) *new_node; } else { *new_node = NULL; ret = iso_tree_add_new_dir(new_parent, new_name, &new_dir); if (ret < 0) return ret; } /* Avoid traversal of target directory to allow cloning of old_dir to a subordinate of old_dir. */ iso_node_take((IsoNode *) new_dir); ret = iso_dir_get_children(old_dir, &iter); if (ret < 0) goto ex; while(1) { ret = iso_dir_iter_next(iter, &sub_node); if (ret == 0) break; ret = iso_tree_clone(sub_node, new_dir, sub_node->name, &new_sub_node, flag & 1); if (ret < 0) goto ex; } /* Now graft in the new tree resp. graft back the merged tree */ ret = iso_dir_add_node(new_parent, (IsoNode *) new_dir, 0); if (ret < 0) goto ex; if (!(flag & 1)) *new_node = (IsoNode *) new_dir; ret = ISO_SUCCESS; ex:; if (iter != NULL) iso_dir_iter_free(iter); if (ret < 0 && new_dir != NULL) { if (flag & 1) { /* graft back the merged tree (eventually with half copy) */ iso_dir_add_node(new_parent, (IsoNode *) new_dir, 0); } else { iso_node_remove_tree((IsoNode *) new_dir, NULL); *new_node = NULL; } } return ret; } static int iso_tree_clone_file(IsoFile *old_file, IsoDir *new_parent, char *new_name, IsoNode **new_node, int flag) { IsoStream *new_stream = NULL; IsoFile *new_file = NULL; int ret; *new_node = NULL; ret = iso_stream_clone(old_file->stream, &new_stream, 0); if (ret < 0) return ret; ret = iso_tree_add_new_file(new_parent, new_name, new_stream, &new_file); if (ret < 0) goto ex; new_stream = NULL; /* now owned by new_file */ new_file->sort_weight = old_file->sort_weight; *new_node = (IsoNode *) new_file; ret = ISO_SUCCESS; ex:; if (new_stream != NULL) iso_stream_unref(new_stream); return ret; } static int iso_tree_clone_symlink(IsoSymlink *node, IsoDir *new_parent, char *new_name, IsoNode **new_node, int flag) { IsoSymlink *new_sym; int ret; *new_node = NULL; ret = iso_tree_add_new_symlink(new_parent, new_name, node->dest, &new_sym); if (ret < 0) return ret; new_sym->fs_id = node->fs_id; new_sym->st_dev = node->st_dev; new_sym->st_ino = node->st_ino; *new_node = (IsoNode *) new_sym; return ISO_SUCCESS; } static int iso_tree_clone_special(IsoSpecial *node, IsoDir *new_parent, char *new_name, IsoNode **new_node, int flag) { IsoSpecial *new_spec; IsoNode *iso_node; int ret; iso_node = (IsoNode *) node; ret = iso_tree_add_new_special(new_parent, new_name, iso_node->mode, node->dev, &new_spec); if (ret < 0) return ret; new_spec->fs_id = node->fs_id; new_spec->st_dev = node->st_dev; new_spec->st_ino = node->st_ino; *new_node = (IsoNode *) new_spec; return ISO_SUCCESS; } /* @param flag bit0= Merge directories rather than ISO_NODE_NAME_NOT_UNIQUE. bit1= issue warning in case of truncation */ int iso_tree_clone_trunc(IsoNode *node, IsoDir *new_parent, char *new_name_in, IsoNode **new_node, int truncate_length, int flag) { int ret = ISO_SUCCESS; char *new_name, *trunc = NULL; *new_node = NULL; new_name = new_name_in; if (truncate_length >= 64 && (int) strlen(new_name) > truncate_length) { trunc = strdup(new_name); if (trunc == 0) { ret = ISO_OUT_OF_MEM; goto ex; } ret = iso_truncate_rr_name(1, truncate_length, trunc, !(flag & 2)); if (ret < 0) goto ex; new_name = trunc; } if (iso_dir_get_node(new_parent, new_name, new_node) == 1) { if (! (node->type == LIBISO_DIR && (*new_node)->type == LIBISO_DIR && (flag & 1))) { *new_node = NULL; ret = ISO_NODE_NAME_NOT_UNIQUE; goto ex; } } else flag &= ~1; if (node->type == LIBISO_DIR) { ret = iso_tree_clone_dir((IsoDir *) node, new_parent, new_name, new_node, flag & 1); } else if (node->type == LIBISO_FILE) { ret = iso_tree_clone_file((IsoFile *) node, new_parent, new_name, new_node, 0); } else if (node->type == LIBISO_SYMLINK) { ret = iso_tree_clone_symlink((IsoSymlink *) node, new_parent, new_name, new_node, 0); } else if (node->type == LIBISO_SPECIAL) { ret = iso_tree_clone_special((IsoSpecial *) node, new_parent, new_name, new_node, 0); } else if (node->type == LIBISO_BOOT) { ret = ISO_SUCCESS; /* API says they are silently ignored */ } if (ret < 0) goto ex; if (flag & 1) { ret = 2; /* merged two directories, *new_node is not new */ goto ex; } ret = iso_tree_copy_node_attr(node, *new_node, 0); ex:; if (trunc != NULL) free(trunc); return ret; } /* API */ int iso_tree_clone(IsoNode *node, IsoDir *new_parent, char *new_name, IsoNode **new_node, int flag) { return iso_tree_clone_trunc(node, new_parent, new_name, new_node, 0, flag & 1); } /* API */ int iso_image_tree_clone(IsoImage *image, IsoNode *node, IsoDir *new_parent, char *new_name, IsoNode **new_node, int flag) { int length, ret; if (image->truncate_mode == 0) length = 0; else length = image->truncate_length; ret = iso_tree_clone_trunc(node, new_parent, new_name, new_node, length, flag & 3); return ret; } int iso_tree_resolve_symlink(IsoImage *img, IsoSymlink *sym, IsoNode **res, int *depth, int flag) { IsoDir *cur_dir = NULL; IsoNode *n, *resolved_node; char *dest, *dest_start, *dest_end; int ret = 0; unsigned int comp_len, dest_len; dest = sym->dest; dest_len = strlen(dest); if (dest[0] == '/') { /* ??? How to resolve absolute links without knowing the path of the future mount point ? ??? Would it be better to throw error ? I can only assume that it gets mounted at / during some stage of booting. */; cur_dir = img->root; dest_end = dest; } else { cur_dir = sym->node.parent; if (cur_dir == NULL) cur_dir = img->root; dest_end = dest - 1; } while (dest_end < dest + dest_len) { dest_start = dest_end + 1; dest_end = strchr(dest_start, '/'); if (dest_end == NULL) dest_end = dest_start + strlen(dest_start); comp_len = dest_end - dest_start; if (comp_len == 0 || (comp_len == 1 && dest_start[0] == '.')) continue; if (comp_len == 2 && dest_start[0] == '.' && dest_start[1] == '.') { cur_dir = cur_dir->node.parent; if (cur_dir == NULL) /* link shoots over root */ return ISO_DEAD_SYMLINK; continue; } /* Search node in cur_dir */ for (n = cur_dir->children; n != NULL; n = n->next) if (strncmp(dest_start, n->name, comp_len) == 0 && strlen(n->name) == comp_len) break; if (n == NULL) return ISO_DEAD_SYMLINK; if (n->type == LIBISO_DIR) { cur_dir = (IsoDir *) n; } else if (n->type == LIBISO_SYMLINK) { if (*depth >= LIBISO_MAX_LINK_DEPTH) return ISO_DEEP_SYMLINK; (*depth)++; ret = iso_tree_resolve_symlink(img, (IsoSymlink *) n, &resolved_node, depth, 0); if (ret < 0) return ret; if (resolved_node->type != LIBISO_DIR) { n = resolved_node; goto leaf_type; } cur_dir = (IsoDir *) resolved_node; } else { leaf_type:; if (dest_end < dest + dest_len) /* attempt to dive into file */ return ISO_DEAD_SYMLINK; *res = n; return ISO_SUCCESS; } } *res = (IsoNode *) cur_dir; return ISO_SUCCESS; } libisofs-1.4.2/libisofs/joliet.c0000644000175700017510000011071312321161425013525 00000000000000/* * Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2007 Mario Danic * Copyright (c) 2011-2014 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif #include "joliet.h" #include "messages.h" #include "writer.h" #include "image.h" #include "filesrc.h" #include "eltorito.h" #include "libisofs.h" #include "util.h" #include "ecma119.h" #include #include #include /* @param flag bit0= Do not issue error messages */ int iso_get_joliet_name(IsoWriteOpts *opts, char *input_charset, int imgid, char *node_name, enum IsoNodeType node_type, size_t *joliet_ucs2_failures, uint16_t **name, int flag) { int ret = ISO_SUCCESS; uint16_t *ucs_name = NULL, *utf16_name = NULL; uint16_t *jname = NULL; if (node_name == NULL) { /* it is not necessarily an error, it can be the root */ *name = NULL; return ISO_SUCCESS; } if (opts->joliet_utf16) { ret = str2utf16be(input_charset, node_name, &ucs_name); if (ret < 0) { if (!(flag & 512)) iso_msg_debug(imgid, "Cannot convert to UTF-16 : \"%s\"", node_name); goto ex; } } else { ret = str2ucs(input_charset, node_name, &ucs_name); if (ret < 0) { if (!(flag & 512)) iso_msg_debug(imgid, "Cannot convert to UCS-2 : \"%s\"", node_name); goto ex; } ret = str2utf16be(input_charset, node_name, &utf16_name); if (ret == ISO_SUCCESS) { if (ucscmp(ucs_name, utf16_name) != 0) { (*joliet_ucs2_failures)++; if (*joliet_ucs2_failures <= ISO_JOLIET_UCS2_WARN_MAX && !(flag & 512)) { iso_msg_submit(imgid, ISO_NAME_NOT_UCS2, 0, "Filename not suitable for Joliet character set UCS-2 : \"%s\"", node_name); } } } } if (node_type == LIBISO_DIR) { jname = iso_j_dir_id(ucs_name, opts->joliet_long_names << 1); } else { jname = iso_j_file_id(ucs_name, (opts->joliet_long_names << 1) | !!(opts->no_force_dots & 2)); } ret = ISO_SUCCESS; ex:; if (ucs_name != NULL) free(ucs_name); if (utf16_name != NULL) free(utf16_name); if (ret != ISO_SUCCESS) { if (jname != NULL) free(jname); return ret; } else if (jname != NULL) { *name = jname; return ISO_SUCCESS; } else { /* * only possible if mem error, as check for empty names is done * in public tree */ return ISO_OUT_OF_MEM; } } static int get_joliet_name(Ecma119Image *t, IsoNode *iso, uint16_t **name) { int ret; ret = iso_get_joliet_name(t->opts, t->input_charset, t->image->id, iso->name, iso->type, &(t->joliet_ucs2_failures), name, 0); return ret; } static void joliet_node_free(JolietNode *node) { if (node == NULL) { return; } if (node->type == JOLIET_DIR) { size_t i; for (i = 0; i < node->info.dir->nchildren; i++) { joliet_node_free(node->info.dir->children[i]); } if (node->info.dir->children != NULL) free(node->info.dir->children); free(node->info.dir); } iso_node_unref(node->node); free(node->name); free(node); } /** * Create a low level Joliet node * @return * 1 success, 0 ignored, < 0 error */ static int create_node(Ecma119Image *t, IsoNode *iso, JolietNode **node) { int ret; JolietNode *joliet; joliet = calloc(1, sizeof(JolietNode)); if (joliet == NULL) { return ISO_OUT_OF_MEM; } if (iso->type == LIBISO_DIR) { IsoDir *dir = (IsoDir*) iso; joliet->info.dir = calloc(1, sizeof(struct joliet_dir_info)); if (joliet->info.dir == NULL) { free(joliet); return ISO_OUT_OF_MEM; } joliet->info.dir->children = NULL; if (dir->nchildren > 0) { joliet->info.dir->children = calloc(sizeof(void*), dir->nchildren); if (joliet->info.dir->children == NULL) { free(joliet->info.dir); free(joliet); return ISO_OUT_OF_MEM; } } joliet->type = JOLIET_DIR; } else if (iso->type == LIBISO_FILE) { /* it's a file */ off_t size; IsoFileSrc *src; IsoFile *file = (IsoFile*) iso; size = iso_stream_get_size(file->stream); if (size > (off_t)MAX_ISO_FILE_SECTION_SIZE && t->opts->iso_level != 3) { char *ipath = iso_tree_get_node_path(iso); free(joliet); ret = iso_msg_submit(t->image->id, ISO_FILE_TOO_BIG, 0, "File \"%s\" can't be added to image because is " "greater than 4GB", ipath); free(ipath); return ret; } ret = iso_file_src_create(t, file, &src); if (ret < 0) { free(joliet); return ret; } joliet->info.file = src; joliet->type = JOLIET_FILE; } else if (iso->type == LIBISO_BOOT) { /* it's a el-torito boot catalog, that we write as a file */ IsoFileSrc *src; ret = el_torito_catalog_file_src_create(t, &src); if (ret < 0) { free(joliet); return ret; } joliet->info.file = src; joliet->type = JOLIET_FILE; } else { /* should never happen */ free(joliet); return ISO_ASSERT_FAILURE; } /* take a ref to the IsoNode */ joliet->node = iso; iso_node_ref(iso); *node = joliet; return ISO_SUCCESS; } /** * Create the low level Joliet tree from the high level ISO tree. * * @return * 1 success, 0 file ignored, < 0 error */ static int create_tree(Ecma119Image *t, IsoNode *iso, JolietNode **tree, int pathlen) { int ret, max_path; JolietNode *node = NULL; uint16_t *jname = NULL; if (t == NULL || iso == NULL || tree == NULL) { return ISO_NULL_POINTER; } if (iso->hidden & LIBISO_HIDE_ON_JOLIET) { /* file will be ignored */ return 0; } ret = get_joliet_name(t, iso, &jname); if (ret < 0) { return ret; } max_path = pathlen + 1 + (jname ? ucslen(jname) * 2 : 0); if (!t->opts->joliet_longer_paths && max_path > 240) { char *ipath = iso_tree_get_node_path(iso); /* * Wow!! Joliet is even more restrictive than plain ISO-9660, * that allows up to 255 bytes!! */ ret = iso_msg_submit(t->image->id, ISO_FILE_IMGPATH_WRONG, 0, "File \"%s\" can't be added to Joliet tree, because " "its path length is larger than 240", ipath); free(jname); free(ipath); return ret; } switch (iso->type) { case LIBISO_FILE: ret = create_node(t, iso, &node); break; case LIBISO_DIR: { IsoNode *pos; IsoDir *dir = (IsoDir*)iso; ret = create_node(t, iso, &node); if (ret < 0) { free(jname); return ret; } pos = dir->children; while (pos) { int cret; JolietNode *child; cret = create_tree(t, pos, &child, max_path); if (cret < 0) { /* error */ joliet_node_free(node); ret = cret; break; } else if (cret == ISO_SUCCESS) { /* add child to this node */ int nchildren = node->info.dir->nchildren++; node->info.dir->children[nchildren] = child; child->parent = node; } pos = pos->next; } } break; case LIBISO_BOOT: if (t->eltorito) { ret = create_node(t, iso, &node); } else { /* log and ignore */ ret = iso_msg_submit(t->image->id, ISO_FILE_IGNORED, 0, "El-Torito catalog found on a image without El-Torito."); } break; case LIBISO_SYMLINK: case LIBISO_SPECIAL: { char *ipath = iso_tree_get_node_path(iso); ret = iso_msg_submit(t->image->id, ISO_FILE_IGNORED, 0, "Cannot add %s to Joliet tree. %s can only be added to a " "Rock Ridge tree.", ipath, (iso->type == LIBISO_SYMLINK ? "Symlinks" : "Special files")); free(ipath); } break; default: /* should never happen */ return ISO_ASSERT_FAILURE; } if (ret <= 0) { free(jname); return ret; } node->name = jname; *tree = node; return ISO_SUCCESS; } static int cmp_node(const void *f1, const void *f2) { JolietNode *f = *((JolietNode**)f1); JolietNode *g = *((JolietNode**)f2); return ucscmp(f->name, g->name); } static void sort_tree(JolietNode *root) { size_t i; if (root->info.dir->children == NULL) return; qsort(root->info.dir->children, root->info.dir->nchildren, sizeof(void*), cmp_node); for (i = 0; i < root->info.dir->nchildren; i++) { JolietNode *child = root->info.dir->children[i]; if (child->type == JOLIET_DIR) sort_tree(child); } } static int cmp_node_name(const void *f1, const void *f2) { JolietNode *f = *((JolietNode**)f1); JolietNode *g = *((JolietNode**)f2); return ucscmp(f->name, g->name); } static int joliet_create_mangled_name(uint16_t *dest, uint16_t *src, int digits, int number, uint16_t *ext) { int ret, pos; uint16_t *ucsnumber; char fmt[16]; char nstr[72]; /* was: The only caller of this function allocates dest with 66 elements and limits digits to < 8 But this does not match the usage of nstr which has to take the decimal representation of an int. */ if (digits >= 8) return ISO_ASSERT_FAILURE; sprintf(fmt, "%%0%dd", digits); sprintf(nstr, fmt, number); ret = str2ucs("ASCII", nstr, &ucsnumber); if (ret < 0) { return ret; } /* copy name */ pos = ucslen(src); ucsncpy(dest, src, pos); /* copy number */ ucsncpy(dest + pos, ucsnumber, digits); pos += digits; if (ext[0] != (uint16_t)0) { size_t extlen = ucslen(ext); iso_msb((uint8_t *) (dest + pos), 0x002E, 2); /* '.' in UCS */ pos++; ucsncpy(dest + pos, ext, extlen); pos += extlen; } iso_msb((uint8_t *) (dest + pos), 0, 2); free(ucsnumber); return ISO_SUCCESS; } static int mangle_single_dir(Ecma119Image *t, JolietNode *dir) { int ret; int i, nchildren, maxchar = 64; JolietNode **children; IsoHTable *table = NULL; int need_sort = 0; uint16_t *full_name = NULL; uint16_t *tmp = NULL; nchildren = dir->info.dir->nchildren; if (nchildren <= 0) { ret = ISO_SUCCESS; goto ex; } children = dir->info.dir->children; LIBISO_ALLOC_MEM(full_name, uint16_t, LIBISO_JOLIET_NAME_MAX); LIBISO_ALLOC_MEM(tmp, uint16_t, LIBISO_JOLIET_NAME_MAX); if (t->opts->joliet_long_names) maxchar = 103; /* a hash table will temporary hold the names, for fast searching */ ret = iso_htable_create((nchildren * 100) / 80, iso_str_hash, (compare_function_t)ucscmp, &table); if (ret < 0) { goto ex; } for (i = 0; i < nchildren; ++i) { uint16_t *name = children[i]->name; ret = iso_htable_add(table, name, name); if (ret < 0) { goto mangle_cleanup; } } for (i = 0; i < nchildren; ++i) { uint16_t *name, *ext; int max; /* computed max len for name, without extension */ int j = i; int digits = 1; /* characters to change per name */ /* first, find all child with same name */ while (j + 1 < nchildren && !cmp_node_name(children + i, children + j + 1)) { ++j; } if (j == i) { /* name is unique */ continue; } /* * A max of 7 characters is good enought, it allows handling up to * 9,999,999 files with same name. */ /* Important: joliet_create_mangled_name() relies on digits < 8 */ while (digits < 8) { int ok, k; uint16_t *dot; int change = 0; /* number to be written */ /* copy name to buffer */ ucscpy(full_name, children[i]->name); /* compute name and extension */ dot = ucsrchr(full_name, '.'); if (dot != NULL && children[i]->type != JOLIET_DIR) { /* * File (not dir) with extension */ int extlen; full_name[dot - full_name] = 0; name = full_name; ext = dot + 1; extlen = ucslen(ext); max = maxchar + 1 - extlen - 1 - digits; if (max <= 0) { /* this can happen if extension is too long */ if (extlen + max > 3) { /* * reduce extension len, to give name an extra char * note that max is negative or 0 */ extlen = extlen + max - 1; ext[extlen] = 0; max = maxchar + 2 - extlen - 1 - digits; } else { /* * error, we don't support extensions < 3 * This can't happen with current limit of digits. */ ret = ISO_ERROR; goto mangle_cleanup; } } /* ok, reduce name by digits */ if (name + max < dot) { name[max] = 0; } } else { /* Directory, or file without extension */ if (children[i]->type == JOLIET_DIR) { max = maxchar + 1 - digits; dot = NULL; /* dots have no meaning in dirs */ } else { max = maxchar + 1 - digits; } name = full_name; if ((size_t) max < ucslen(name)) { name[max] = 0; } /* let ext be an empty string */ ext = name + ucslen(name); } ok = 1; /* change name of each file */ for (k = i; k <= j; ++k) { while (1) { ret = joliet_create_mangled_name(tmp, name, digits, change, ext); if (ret < 0) { goto mangle_cleanup; } ++change; if (change > int_pow(10, digits)) { ok = 0; break; } if (!iso_htable_get(table, tmp, NULL)) { /* the name is unique, so it can be used */ break; } } if (ok) { uint16_t *new = ucsdup(tmp); if (new == NULL) { ret = ISO_OUT_OF_MEM; goto mangle_cleanup; } iso_htable_remove_ptr(table, children[k]->name, NULL); free(children[k]->name); children[k]->name = new; iso_htable_add(table, new, new); /* * if we change a name we need to sort again children * at the end */ need_sort = 1; } else { /* we need to increment digits */ break; } } if (ok) { break; } else { ++digits; } } if (digits == 8) { ret = ISO_MANGLE_TOO_MUCH_FILES; goto mangle_cleanup; } i = j; } /* * If needed, sort again the files inside dir */ if (need_sort) { qsort(children, nchildren, sizeof(void*), cmp_node_name); } ret = ISO_SUCCESS; mangle_cleanup : ; ex:; iso_htable_destroy(table, NULL); LIBISO_FREE_MEM(tmp); LIBISO_FREE_MEM(full_name); return ret; } static int mangle_tree(Ecma119Image *t, JolietNode *dir) { int ret; size_t i; ret = mangle_single_dir(t, dir); if (ret < 0) { return ret; } /* recurse */ for (i = 0; i < dir->info.dir->nchildren; ++i) { if (dir->info.dir->children[i]->type == JOLIET_DIR) { ret = mangle_tree(t, dir->info.dir->children[i]); if (ret < 0) { /* error */ return ret; } } } return ISO_SUCCESS; } static int joliet_tree_create(Ecma119Image *t) { int ret; JolietNode *root; if (t == NULL) { return ISO_NULL_POINTER; } ret = create_tree(t, (IsoNode*)t->image->root, &root, 0); if (ret <= 0) { if (ret == 0) { /* unexpected error, root ignored!! This can't happen */ ret = ISO_ASSERT_FAILURE; } return ret; } /* the Joliet tree is stored in Ecma119Image target */ if (t->eff_partition_offset > 0) { t->j_part_root = root; } else { t->joliet_root = root; } iso_msg_debug(t->image->id, "Sorting the Joliet tree..."); sort_tree(root); iso_msg_debug(t->image->id, "Mangling Joliet names..."); ret = mangle_tree(t, root); if (ret < 0) return ret; return ISO_SUCCESS; } /** * Compute the size of a directory entry for a single node */ static size_t calc_dirent_len(Ecma119Image *t, JolietNode *n) { /* note than name len is always even, so we always need the pad byte */ int ret = n->name ? ucslen(n->name) * 2 + 34 : 34; if (n->type == JOLIET_FILE && !(t->opts->omit_version_numbers & 3)) { /* take into account version numbers */ ret += 4; } return ret; } /** * Computes the total size of all directory entries of a single joliet dir. * This is like ECMA-119 6.8.1.1, but taking care that names are stored in * UCS. */ static size_t calc_dir_size(Ecma119Image *t, JolietNode *dir) { size_t i, len; /* size of "." and ".." entries */ len = 34 + 34; for (i = 0; i < dir->info.dir->nchildren; ++i) { size_t remaining; int section, nsections; JolietNode *child = dir->info.dir->children[i]; size_t dirent_len = calc_dirent_len(t, child); nsections = (child->type == JOLIET_FILE) ? child->info.file->nsections : 1; for (section = 0; section < nsections; ++section) { remaining = BLOCK_SIZE - (len % BLOCK_SIZE); if (dirent_len > remaining) { /* child directory entry doesn't fit on block */ len += remaining + dirent_len; } else { len += dirent_len; } } } /* * The size of a dir is always a multiple of block size, as we must add * the size of the unused space after the last directory record * (ECMA-119, 6.8.1.3) */ len = ROUND_UP(len, BLOCK_SIZE); /* cache the len */ dir->info.dir->len = len; return len; } static void calc_dir_pos(Ecma119Image *t, JolietNode *dir) { size_t i, len; t->joliet_ndirs++; dir->info.dir->block = t->curblock; len = calc_dir_size(t, dir); t->curblock += DIV_UP(len, BLOCK_SIZE); for (i = 0; i < dir->info.dir->nchildren; i++) { JolietNode *child = dir->info.dir->children[i]; if (child->type == JOLIET_DIR) { calc_dir_pos(t, child); } } } /** * Compute the length of the joliet path table, in bytes. */ static uint32_t calc_path_table_size(JolietNode *dir) { uint32_t size; size_t i; /* size of path table for this entry */ size = 8; size += dir->name ? ucslen(dir->name) * 2 : 2; /* and recurse */ for (i = 0; i < dir->info.dir->nchildren; i++) { JolietNode *child = dir->info.dir->children[i]; if (child->type == JOLIET_DIR) { size += calc_path_table_size(child); } } return size; } static int joliet_writer_compute_data_blocks(IsoImageWriter *writer) { Ecma119Image *t; uint32_t path_table_size; size_t ndirs; if (writer == NULL) { return ISO_OUT_OF_MEM; } t = writer->target; /* compute position of directories */ iso_msg_debug(t->image->id, "Computing position of Joliet dir structure"); t->joliet_ndirs = 0; calc_dir_pos(t, t->joliet_root); /* compute length of pathlist */ iso_msg_debug(t->image->id, "Computing length of Joliet pathlist"); path_table_size = calc_path_table_size(t->joliet_root); /* compute location for path tables */ t->joliet_l_path_table_pos = t->curblock; t->curblock += DIV_UP(path_table_size, BLOCK_SIZE); t->joliet_m_path_table_pos = t->curblock; t->curblock += DIV_UP(path_table_size, BLOCK_SIZE); t->joliet_path_table_size = path_table_size; if (t->opts->partition_offset > 0) { /* Take into respect second directory tree */ ndirs = t->joliet_ndirs; t->joliet_ndirs = 0; calc_dir_pos(t, t->j_part_root); if (t->joliet_ndirs != ndirs) { iso_msg_submit(t->image->id, ISO_ASSERT_FAILURE, 0, "Number of directories differs in Joliet partiton_tree"); return ISO_ASSERT_FAILURE; } /* Take into respect second set of path tables */ path_table_size = calc_path_table_size(t->j_part_root); t->j_part_l_path_table_pos = t->curblock; t->curblock += DIV_UP(path_table_size, BLOCK_SIZE); t->j_part_m_path_table_pos = t->curblock; t->curblock += DIV_UP(path_table_size, BLOCK_SIZE); } return ISO_SUCCESS; } /** * Write a single directory record for Joliet. It is like (ECMA-119, 9.1), * but file identifier is stored in UCS. * * @param file_id * if >= 0, we use it instead of the filename (for "." and ".." entries). * @param len_fi * Computed length of the file identifier. Total size of the directory * entry will be len + 34 (ECMA-119, 9.1.12), as padding is always needed */ static void write_one_dir_record(Ecma119Image *t, JolietNode *node, int file_id, uint8_t *buf, size_t len_fi, int extent) { uint32_t len; uint32_t block; uint8_t len_dr; /*< size of dir entry */ int multi_extend = 0; uint8_t *name = (file_id >= 0) ? (uint8_t*)&file_id : (uint8_t*)node->name; struct ecma119_dir_record *rec = (struct ecma119_dir_record*)buf; IsoNode *iso; len_dr = 33 + len_fi + ((len_fi % 2) ? 0 : 1); memcpy(rec->file_id, name, len_fi); if (node->type == JOLIET_FILE && !(t->opts->omit_version_numbers & 3)) { len_dr += 4; rec->file_id[len_fi++] = 0; rec->file_id[len_fi++] = ';'; rec->file_id[len_fi++] = 0; rec->file_id[len_fi++] = '1'; } if (node->type == JOLIET_DIR) { /* use the cached length */ len = node->info.dir->len; block = node->info.dir->block; } else if (node->type == JOLIET_FILE) { block = node->info.file->sections[extent].block; len = node->info.file->sections[extent].size; multi_extend = (node->info.file->nsections - 1 == extent) ? 0 : 1; } else { /* * for nodes other than files and dirs, we set both * len and block to 0 */ len = 0; block = 0; } /* * For ".." entry we need to write the parent info! */ if (file_id == 1 && node->parent) node = node->parent; rec->len_dr[0] = len_dr; iso_bb(rec->block, block - t->eff_partition_offset, 4); iso_bb(rec->length, len, 4); /* was: iso_datetime_7(rec->recording_time, t->now, t->opts->always_gmt); */ iso= node->node; iso_datetime_7(rec->recording_time, (t->opts->dir_rec_mtime & 2) ? ( t->replace_timestamps ? t->timestamp : iso->mtime ) : t->now, t->opts->always_gmt); rec->flags[0] = ((node->type == JOLIET_DIR) ? 2 : 0) | (multi_extend ? 0x80 : 0); iso_bb(rec->vol_seq_number, (uint32_t) 1, 2); rec->len_fi[0] = len_fi; } /** * Copy up to \p max characters from \p src to \p dest. If \p src has less than * \p max characters, we pad dest with " " characters. */ static void ucsncpy_pad(uint16_t *dest, const uint16_t *src, size_t max) { char *cdest, *csrc; size_t len, i; cdest = (char*)dest; csrc = (char*)src; if (src != NULL) { len = MIN(ucslen(src) * 2, max - (max % 2)); } else { len = 0; } for (i = 0; i < len; ++i) cdest[i] = csrc[i]; if (len >= 2) iso_handle_split_utf16(dest + (len / 2 - 1)); for (i = len; i + 1 < max; i += 2) { cdest[i] = '\0'; cdest[i + 1] = ' '; } if (max % 2) cdest[max - 1] = 0; } int joliet_writer_write_vol_desc(IsoImageWriter *writer) { IsoImage *image; Ecma119Image *t; struct ecma119_sup_vol_desc vol; uint16_t *vol_id = NULL, *pub_id = NULL, *data_id = NULL; uint16_t *volset_id = NULL, *system_id = NULL, *application_id = NULL; uint16_t *copyright_file_id = NULL, *abstract_file_id = NULL; uint16_t *biblio_file_id = NULL; if (writer == NULL) { return ISO_OUT_OF_MEM; } t = writer->target; image = t->image; iso_msg_debug(image->id, "Write SVD for Joliet"); memset(&vol, 0, sizeof(struct ecma119_sup_vol_desc)); str2ucs(t->input_charset, image->volume_id, &vol_id); str2ucs(t->input_charset, image->publisher_id, &pub_id); str2ucs(t->input_charset, image->data_preparer_id, &data_id); str2ucs(t->input_charset, image->volset_id, &volset_id); str2ucs(t->input_charset, image->system_id, &system_id); str2ucs(t->input_charset, image->application_id, &application_id); str2ucs(t->input_charset, image->copyright_file_id, ©right_file_id); str2ucs(t->input_charset, image->abstract_file_id, &abstract_file_id); str2ucs(t->input_charset, image->biblio_file_id, &biblio_file_id); vol.vol_desc_type[0] = 2; memcpy(vol.std_identifier, "CD001", 5); vol.vol_desc_version[0] = 1; ucsncpy_pad((uint16_t*)vol.volume_id, vol_id, 32); /* make use of UCS-2 Level 3 */ memcpy(vol.esc_sequences, "%/E", 3); iso_bb(vol.vol_space_size, t->vol_space_size - t->eff_partition_offset, 4); iso_bb(vol.vol_set_size, (uint32_t) 1, 2); iso_bb(vol.vol_seq_number, (uint32_t) 1, 2); iso_bb(vol.block_size, (uint32_t) BLOCK_SIZE, 2); iso_bb(vol.path_table_size, t->joliet_path_table_size, 4); if (t->eff_partition_offset > 0) { /* Point to second tables and second root */ iso_lsb(vol.l_path_table_pos, t->j_part_l_path_table_pos - t->eff_partition_offset, 4); iso_msb(vol.m_path_table_pos, t->j_part_m_path_table_pos - t->eff_partition_offset, 4); write_one_dir_record(t, t->j_part_root, 0, vol.root_dir_record, 1, 0); } else { iso_lsb(vol.l_path_table_pos, t->joliet_l_path_table_pos, 4); iso_msb(vol.m_path_table_pos, t->joliet_m_path_table_pos, 4); write_one_dir_record(t, t->joliet_root, 0, vol.root_dir_record, 1, 0); } ucsncpy_pad((uint16_t*)vol.vol_set_id, volset_id, 128); ucsncpy_pad((uint16_t*)vol.publisher_id, pub_id, 128); ucsncpy_pad((uint16_t*)vol.data_prep_id, data_id, 128); ucsncpy_pad((uint16_t*)vol.system_id, system_id, 32); ucsncpy_pad((uint16_t*)vol.application_id, application_id, 128); ucsncpy_pad((uint16_t*)vol.copyright_file_id, copyright_file_id, 37); ucsncpy_pad((uint16_t*)vol.abstract_file_id, abstract_file_id, 37); ucsncpy_pad((uint16_t*)vol.bibliographic_file_id, biblio_file_id, 37); ecma119_set_voldescr_times(writer, (struct ecma119_pri_vol_desc *) &vol); vol.file_structure_version[0] = 1; free(vol_id); free(volset_id); free(pub_id); free(data_id); free(system_id); free(application_id); free(copyright_file_id); free(abstract_file_id); free(biblio_file_id); /* Finally write the Volume Descriptor */ return iso_write(t, &vol, sizeof(struct ecma119_sup_vol_desc)); } static int write_one_dir(Ecma119Image *t, JolietNode *dir) { int ret; uint8_t *buffer = NULL; size_t i; size_t fi_len, len; /* buf will point to current write position on buffer */ uint8_t *buf; /* initialize buffer with 0s */ LIBISO_ALLOC_MEM(buffer, uint8_t, BLOCK_SIZE); buf = buffer; /* write the "." and ".." entries first */ write_one_dir_record(t, dir, 0, buf, 1, 0); buf += 34; write_one_dir_record(t, dir, 1, buf, 1, 0); buf += 34; for (i = 0; i < dir->info.dir->nchildren; i++) { int section, nsections; JolietNode *child = dir->info.dir->children[i]; /* compute len of directory entry */ fi_len = ucslen(child->name) * 2; len = fi_len + 34; if (child->type == JOLIET_FILE && !(t->opts->omit_version_numbers & 3)) { len += 4; } nsections = (child->type == JOLIET_FILE) ? child->info.file->nsections : 1; for (section = 0; section < nsections; ++section) { if ( (buf + len - buffer) > BLOCK_SIZE) { /* dir doesn't fit in current block */ ret = iso_write(t, buffer, BLOCK_SIZE); if (ret < 0) { goto ex; } memset(buffer, 0, BLOCK_SIZE); buf = buffer; } /* write the directory entry in any case */ write_one_dir_record(t, child, -1, buf, fi_len, section); buf += len; } } /* write the last block */ ret = iso_write(t, buffer, BLOCK_SIZE); ex:; LIBISO_FREE_MEM(buffer); return ret; } static int write_dirs(Ecma119Image *t, JolietNode *root) { int ret; size_t i; /* write all directory entries for this dir */ ret = write_one_dir(t, root); if (ret < 0) { return ret; } /* recurse */ for (i = 0; i < root->info.dir->nchildren; i++) { JolietNode *child = root->info.dir->children[i]; if (child->type == JOLIET_DIR) { ret = write_dirs(t, child); if (ret < 0) { return ret; } } } return ISO_SUCCESS; } static int write_path_table(Ecma119Image *t, JolietNode **pathlist, int l_type) { size_t i, len; uint8_t *buf = NULL; struct ecma119_path_table_record *rec; void (*write_int)(uint8_t*, uint32_t, int); JolietNode *dir; uint32_t path_table_size; int parent = 0; int ret= ISO_SUCCESS; uint8_t *zeros = NULL; /* 256 is just a convenient size large enought */ LIBISO_ALLOC_MEM(buf, uint8_t, 256); LIBISO_ALLOC_MEM(zeros, uint8_t, BLOCK_SIZE); path_table_size = 0; write_int = l_type ? iso_lsb : iso_msb; for (i = 0; i < t->joliet_ndirs; i++) { dir = pathlist[i]; /* find the index of the parent in the table */ while ((i) && pathlist[parent] != dir->parent) { parent++; } /* write the Path Table Record (ECMA-119, 9.4) */ memset(buf, 0, 256); rec = (struct ecma119_path_table_record*) buf; rec->len_di[0] = dir->parent ? (uint8_t) ucslen(dir->name) * 2 : 1; rec->len_xa[0] = 0; write_int(rec->block, dir->info.dir->block - t->eff_partition_offset, 4); write_int(rec->parent, parent + 1, 2); if (dir->parent) { memcpy(rec->dir_id, dir->name, rec->len_di[0]); } len = 8 + rec->len_di[0] + (rec->len_di[0] % 2); ret = iso_write(t, buf, len); if (ret < 0) { /* error */ goto ex; } path_table_size += len; } /* we need to fill the last block with zeros */ path_table_size %= BLOCK_SIZE; if (path_table_size) { len = BLOCK_SIZE - path_table_size; memset(zeros, 0, len); ret = iso_write(t, zeros, len); } ex:; LIBISO_FREE_MEM(zeros); LIBISO_FREE_MEM(buf); return ret; } static int write_path_tables(Ecma119Image *t) { int ret; size_t i, j, cur; JolietNode **pathlist; iso_msg_debug(t->image->id, "Writing Joliet Path tables"); /* allocate temporal pathlist */ pathlist = malloc(sizeof(void*) * t->joliet_ndirs); if (pathlist == NULL) { return ISO_OUT_OF_MEM; } if (t->eff_partition_offset > 0) { pathlist[0] = t->j_part_root; } else { pathlist[0] = t->joliet_root; } cur = 1; for (i = 0; i < t->joliet_ndirs; i++) { JolietNode *dir = pathlist[i]; for (j = 0; j < dir->info.dir->nchildren; j++) { JolietNode *child = dir->info.dir->children[j]; if (child->type == JOLIET_DIR) { pathlist[cur++] = child; } } } /* Write L Path Table */ ret = write_path_table(t, pathlist, 1); if (ret < 0) { goto write_path_tables_exit; } /* Write L Path Table */ ret = write_path_table(t, pathlist, 0); write_path_tables_exit: ; free(pathlist); return ret; } static int joliet_writer_write_dirs(IsoImageWriter *writer) { int ret; Ecma119Image *t; JolietNode *root; t = writer->target; /* first of all, we write the directory structure */ if (t->eff_partition_offset > 0) { root = t->j_part_root; } else { root = t->joliet_root; } ret = write_dirs(t, root); if (ret < 0) { return ret; } /* and write the path tables */ ret = write_path_tables(t); return ret; } static int joliet_writer_write_data(IsoImageWriter *writer) { int ret; Ecma119Image *t; if (writer == NULL) { return ISO_NULL_POINTER; } t = writer->target; ret = joliet_writer_write_dirs(writer); if (ret < 0) return ret; if (t->opts->partition_offset > 0) { t->eff_partition_offset = t->opts->partition_offset; ret = joliet_writer_write_dirs(writer); t->eff_partition_offset = 0; if (ret < 0) return ret; } return ISO_SUCCESS; } static int joliet_writer_free_data(IsoImageWriter *writer) { /* free the Joliet tree */ Ecma119Image *t = writer->target; joliet_node_free(t->joliet_root); if (t->j_part_root != NULL) joliet_node_free(t->j_part_root); t->j_part_root = NULL; return ISO_SUCCESS; } int joliet_writer_create(Ecma119Image *target) { int ret; IsoImageWriter *writer; writer = malloc(sizeof(IsoImageWriter)); if (writer == NULL) { return ISO_OUT_OF_MEM; } writer->compute_data_blocks = joliet_writer_compute_data_blocks; writer->write_vol_desc = joliet_writer_write_vol_desc; writer->write_data = joliet_writer_write_data; writer->free_data = joliet_writer_free_data; writer->data = NULL; writer->target = target; iso_msg_debug(target->image->id, "Creating low level Joliet tree..."); ret = joliet_tree_create(target); if (ret < 0) { free((char *) writer); return ret; } /* add this writer to image */ target->writers[target->nwriters++] = writer; if(target->opts->partition_offset > 0) { /* Create second tree */ target->eff_partition_offset = target->opts->partition_offset; ret = joliet_tree_create(target); if (ret < 0) { return ret; } target->eff_partition_offset = 0; } /* we need the volume descriptor */ target->curblock++; return ISO_SUCCESS; } libisofs-1.4.2/libisofs/util.c0000644000175700017510000017171612606411401013224 00000000000000/* * Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2007 Mario Danic * Copyright (c) 2009 - 2015 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif #include "util.h" #include "libisofs.h" #include "messages.h" #include "joliet.h" #include "node.h" #include "../version.h" #include #include #include #include #include #include #include #include #include #include #include /* if we don't have eaccess, we check file access by opening it */ #ifndef HAVE_EACCESS #include #include #include #endif /* Produce possibly inflationary error messages directly to stderr */ static int iso_iconv_debug = 0; struct iso_iconv_handle { int status; /* bit0= open , bit1= identical mapping */ iconv_t descr; }; /* @param flag bit0= shortcut by identical mapping is not allowed */ static int iso_iconv_open(struct iso_iconv_handle *handle, char *tocode, char *fromcode, int flag) { handle->status = 0; handle->descr = (iconv_t) -1; if (strcmp(tocode, fromcode) == 0 && !(flag & 1)) { handle->status = 1 | 2; return 1; } handle->descr = iconv_open(tocode, fromcode); if (handle->descr == (iconv_t) -1) { if (strlen(tocode) + strlen(fromcode) <= 160 && iso_iconv_debug) fprintf(stderr, "libisofs_DEBUG: iconv_open(\"%s\", \"%s\") failed: errno= %d %s\n", tocode, fromcode, errno, strerror(errno)); return 0; } handle->status = 1; return 1; } static size_t iso_iconv(struct iso_iconv_handle *handle, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft, int flag) { size_t ret; /* The build system might indicate iconv(,const char **inbuf,) by defining ICONV_CONST const */ #ifndef ICONV_CONST #define ICONV_CONST #endif ICONV_CONST char **local_inbuf; local_inbuf = (ICONV_CONST char **) inbuf; if (!(handle->status & 1)) { if (iso_iconv_debug) fprintf(stderr, "libisofs_DEBUG: iso_iconv(): iso_iconv_handle not in open state\n"); return (size_t) -1; } if (handle->status & 2) { if (inbuf == NULL || outbuf == NULL) { null_buf:; if (iso_iconv_debug) fprintf(stderr, "libisofs_DEBUG: iso_iconv(): NULL buffers not allowed in shortcut mapping\n"); return (size_t) -1; } if (*inbuf == NULL || *outbuf == NULL) goto null_buf; while (*inbytesleft > 0 && *outbytesleft > 0) { *((*outbuf)++) = *((*inbuf)++); (*inbytesleft)--; (*outbytesleft)--; } if (*inbytesleft > 0 && *outbytesleft <= 0) return (size_t) -1; return (size_t) 0; } ret = iconv(handle->descr, local_inbuf, inbytesleft, outbuf, outbytesleft); if (ret == (size_t) -1) { if (iso_iconv_debug) fprintf(stderr, "libisofs_DEBUG: iconv() failed: errno= %d %s\n", errno, strerror(errno)); return (size_t) -1; } return ret; } static int iso_iconv_close(struct iso_iconv_handle *handle, int flag) { int ret; if (!(handle->status & 1)) { if (iso_iconv_debug) fprintf(stderr, "libisofs_DEBUG: iso_iconv_close(): iso_iconv_handle not in open state\n"); return -1; } handle->status &= ~1; if (handle->status & 2) return 0; ret = iconv_close(handle->descr); if (ret == -1) { if (iso_iconv_debug) fprintf(stderr, "libisofs_DEBUG: iconv_close() failed: errno= %d %s\n", errno, strerror(errno)); return -1; } return ret; } int int_pow(int base, int power) { int result = 1; while (--power >= 0) { result *= base; } return result; } /* This static variable can override the locale's charset by its getter function which should be used whenever the local character set name is to be inquired. I.e. instead of calling nl_langinfo(CODESET) directly. If the variable is empty then it forwards nl_langinfo(CODESET). */ static char libisofs_local_charset[4096]= {""}; /* API function */ int iso_set_local_charset(char *name, int flag) { if(strlen(name) >= sizeof(libisofs_local_charset)) return(0); strcpy(libisofs_local_charset, name); return 1; } /* API function */ char *iso_get_local_charset(int flag) { if(libisofs_local_charset[0]) return libisofs_local_charset; return nl_langinfo(CODESET); } int strconv(const char *str, const char *icharset, const char *ocharset, char **output) { size_t inbytes; size_t outbytes; size_t n; struct iso_iconv_handle conv; int conv_ret; char *out = NULL; char *src; char *ret; int retval; inbytes = strlen(str); outbytes = (inbytes + 1) * MB_LEN_MAX; out = calloc(outbytes, 1); if (out == NULL) { retval = ISO_OUT_OF_MEM; goto ex; } conv_ret = iso_iconv_open(&conv, (char *) ocharset, (char *) icharset, 0); if (conv_ret <= 0) { retval = ISO_CHARSET_CONV_ERROR; goto ex; } src = (char *)str; ret = (char *)out; n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0); if (n == (size_t) -1) { /* error */ iso_iconv_close(&conv, 0); retval = ISO_CHARSET_CONV_ERROR; goto ex; } *ret = '\0'; iso_iconv_close(&conv, 0); *output = malloc(ret - out + 1); if (*output == NULL) { retval = ISO_OUT_OF_MEM; goto ex; } memcpy(*output, out, ret - out + 1); retval = ISO_SUCCESS; ex:; if (out != NULL) free(out); return retval; } int strnconvl(const char *str, const char *icharset, const char *ocharset, size_t len, char **output, size_t *out_len) { size_t inbytes; size_t outbytes; size_t n; struct iso_iconv_handle conv; int conv_ret; char *out = NULL; char *src; char *ret; int retval; inbytes = len; outbytes = (inbytes + 1) * MB_LEN_MAX; out = calloc(outbytes, 1); if (out == NULL) { retval = ISO_OUT_OF_MEM; goto ex; } conv_ret = iso_iconv_open(&conv, (char *) ocharset, (char *) icharset, 0); if (conv_ret <= 0) { retval = ISO_CHARSET_CONV_ERROR; goto ex; } src = (char *)str; ret = (char *)out; n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0); if (n == (size_t) -1) { /* error */ iso_iconv_close(&conv, 0); retval = ISO_CHARSET_CONV_ERROR; goto ex; } *ret = '\0'; iso_iconv_close(&conv, 0); *out_len = ret - out; *output = malloc(*out_len + 1); if (*output == NULL) { retval = ISO_OUT_OF_MEM; goto ex; } memcpy(*output, out, ret - out + 1); retval = ISO_SUCCESS; ex:; if (out != NULL) free(out); return retval; } int strnconv(const char *str, const char *icharset, const char *ocharset, size_t len, char **output) { size_t l; return strnconvl(str, icharset, ocharset, len, output, &l); } /** * Convert a str in a specified codeset to WCHAR_T. * The result must be free() when no more needed * * @return * 1 success, < 0 error */ static int str2wchar(const char *icharset, const char *input, wchar_t **output) { struct iso_iconv_handle conv; int conv_ret; /* That while loop smells like a potential show stopper */ size_t loop_counter = 0, loop_limit = 3; size_t inbytes; size_t outbytes; char *ret; char *src; wchar_t *wstr; size_t n; if (icharset == NULL || input == NULL || output == NULL) { return ISO_NULL_POINTER; } conv_ret = iso_iconv_open(&conv, "WCHAR_T", (char *) icharset, 0); if (conv_ret <= 0) { return ISO_CHARSET_CONV_ERROR; } inbytes = strlen(input); loop_limit = inbytes + 3; outbytes = (inbytes + 1) * sizeof(wchar_t); /* we are sure that numchars <= inbytes */ wstr = malloc(outbytes); if (wstr == NULL) { return ISO_OUT_OF_MEM; } ret = (char *)wstr; src = (char *)input; n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0); while (n == (size_t) -1) { if (errno == E2BIG) { /* error, should never occur */ goto conv_error; } else { wchar_t *wret; /* * Invalid input string charset. * This can happen if input is in fact encoded in a charset * different than icharset. * We can't do anything better than replace by "_" and continue. */ inbytes--; src++; wret = (wchar_t*) ret; *wret++ = (wchar_t) '_'; ret = (char *) wret; outbytes -= sizeof(wchar_t); if (!inbytes) break; /* Just to appease my remorse about unclear loop ends */ loop_counter++; if (loop_counter > loop_limit) goto conv_error; n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0); } } iso_iconv_close(&conv, 0); *( (wchar_t *)ret )='\0'; *output = wstr; return ISO_SUCCESS; conv_error:; iso_iconv_close(&conv, 0); free(wstr); return ISO_CHARSET_CONV_ERROR; } int str2ascii(const char *icharset, const char *input, char **output) { int result; wchar_t *wsrc_ = NULL; char *ret = NULL; char *ret_ = NULL; char *src; struct iso_iconv_handle conv; int conv_ret; int direct_conv = 0; /* That while loop smells like a potential show stopper */ size_t loop_counter = 0, loop_limit = 3; /* Fallback in case that iconv() is too demanding for system */ unsigned char *cpt; size_t numchars; size_t outbytes; size_t inbytes; size_t n; if (icharset == NULL || input == NULL || output == NULL) { return ISO_NULL_POINTER; } /* First try the traditional way via intermediate character set WCHAR_T. * Up to August 2011 this was the only way. But it will not work if * there is no character set "WCHAR_T". E.g. on Solaris. */ /* convert the string to a wide character string. Note: outbytes * is in fact the number of characters in the string and doesn't * include the last NULL character. */ conv_ret = 0; result = str2wchar(icharset, input, &wsrc_); if (result == (int) ISO_SUCCESS) { src = (char *)wsrc_; numchars = wcslen(wsrc_); inbytes = numchars * sizeof(wchar_t); loop_limit = inbytes + 3; ret_ = malloc(numchars + 1); if (ret_ == NULL) { free(wsrc_); return ISO_OUT_OF_MEM; } outbytes = numchars; ret = ret_; /* initialize iconv */ conv_ret = iso_iconv_open(&conv, "ASCII", "WCHAR_T", 0); if (conv_ret <= 0) { free(wsrc_); wsrc_ = NULL; free(ret_); ret = ret_ = NULL; } } else if (result != (int) ISO_CHARSET_CONV_ERROR) return result; /* If this did not succeed : Try the untraditional direct conversion. */ if (conv_ret <= 0) { conv_ret = iso_iconv_open(&conv, "ASCII", (char *) icharset, 0); if (conv_ret <= 0) goto fallback; direct_conv = 1; src = (char *) input; inbytes = strlen(input); loop_limit = inbytes + 3; outbytes = (inbytes + 1) * sizeof(uint16_t); ret_ = malloc(outbytes); if (ret_ == NULL) return ISO_OUT_OF_MEM; ret = ret_; } n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0); while (n == (size_t) -1) { /* The destination buffer is too small. Stops here. */ if (errno == E2BIG) break; /* An incomplete multi bytes sequence was found. We * can't do anything here. That's quite unlikely. */ if (errno == EINVAL) break; /* The last possible error is an invalid multi bytes * sequence. Just replace the character with a "_". * Probably the character doesn't exist in ascii like * "é, è, à, ç, ..." in French. */ *ret++ = '_'; outbytes--; if (!outbytes) break; /* There was an error with one character but some other remain * to be converted. That's probably a multibyte character. * See above comment. */ if (direct_conv) { src++; inbytes--; } else { src += sizeof(wchar_t); inbytes -= sizeof(wchar_t); } if (!inbytes) break; /* Just to appease my remorse about unclear loop ends */ loop_counter++; if (loop_counter > loop_limit) break; n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0); } iso_iconv_close(&conv, 0); *ret = 0; if (wsrc_ != NULL) free(wsrc_); *output = ret_; return ISO_SUCCESS; fallback:; /* Assume to have a single byte charset with ASCII as core. Anything suspicious will be mapped to '_'. */ *output = strdup(input); for (cpt = (unsigned char *) *output; *cpt; cpt++) { if (*cpt < 32 || *cpt > 126) *cpt = '_'; } return ISO_SUCCESS; } static void set_ucsbe(uint16_t *ucs, char c) { char *v = (char*)ucs; v[0] = (char)0; v[1] = c; } /** * @return * -1, 0, 1 if *ucs <, == or > than c */ static int cmp_ucsbe(const uint16_t *ucs, char c) { char *v = (char*)ucs; if (v[0] != 0) { return 1; } else if (v[1] == c) { return 0; } else { return (uint8_t)c > (uint8_t)v[1] ? -1 : 1; } } int str2ucs(const char *icharset, const char *input, uint16_t **output) { int result; wchar_t *wsrc_ = NULL; char *src; char *ret = NULL; char *ret_ = NULL; struct iso_iconv_handle conv; int conv_ret = 0; int direct_conv = 0; /* That while loop smells like a potential show stopper */ size_t loop_counter = 0, loop_limit = 3; size_t numchars; size_t outbytes; size_t inbytes; size_t n; if (icharset == NULL || input == NULL || output == NULL) { return ISO_NULL_POINTER; } /* convert the string to a wide character string. Note: outbytes * is in fact the number of characters in the string and doesn't * include the last NULL character. */ /* First try the traditional way via intermediate character set WCHAR_T. * Up to August 2011 this was the only way. But it will not work if * there is no character set "WCHAR_T". E.g. on Solaris. */ conv_ret = 0; result = str2wchar(icharset, input, &wsrc_); if (result == (int) ISO_SUCCESS) { src = (char *)wsrc_; numchars = wcslen(wsrc_); inbytes = numchars * sizeof(wchar_t); loop_limit = inbytes + 3; ret_ = malloc((numchars+1) * sizeof(uint16_t)); if (ret_ == NULL) { free(wsrc_); return ISO_OUT_OF_MEM; } outbytes = numchars * sizeof(uint16_t); ret = ret_; /* initialize iconv */ conv_ret = iso_iconv_open(&conv, "UCS-2BE", "WCHAR_T", 0); if (conv_ret <= 0) { free(wsrc_); wsrc_ = NULL; free(ret_); ret = ret_ = NULL; } } else if (result != (int) ISO_CHARSET_CONV_ERROR) return result; /* If this did not succeed : Try the untraditional direct conversion. */ if (conv_ret <= 0) { conv_ret = iso_iconv_open(&conv, "UCS-2BE", (char *) icharset, 0); if (conv_ret <= 0) { return ISO_CHARSET_CONV_ERROR; } direct_conv = 1; src = (char *) input; inbytes = strlen(input); loop_limit = inbytes + 3; outbytes = (inbytes + 1) * sizeof(uint16_t); ret_ = malloc(outbytes); if (ret_ == NULL) return ISO_OUT_OF_MEM; ret = ret_; } n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0); while (n == (size_t) -1) { /* The destination buffer is too small. Stops here. */ if (errno == E2BIG) break; /* An incomplete multi bytes sequence was found. We * can't do anything here. That's quite unlikely. */ if (errno == EINVAL) break; /* The last possible error is an invalid multi bytes * sequence. Just replace the character with a "_". * Probably the character doesn't exist in UCS */ set_ucsbe((uint16_t*) ret, '_'); ret += sizeof(uint16_t); outbytes -= sizeof(uint16_t); if (!outbytes) break; /* There was an error with one character but some other remain * to be converted. That's probably a multibyte character. * See above comment. */ if (direct_conv) { src++; inbytes--; } else { src += sizeof(wchar_t); inbytes -= sizeof(wchar_t); } if (!inbytes) break; /* Just to appease my remorse about unclear loop ends */ loop_counter++; if (loop_counter > loop_limit) break; n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0); } iso_iconv_close(&conv, 0); /* close the ucs string */ set_ucsbe((uint16_t*) ret, '\0'); if (wsrc_ != NULL) free(wsrc_); *output = (uint16_t*)ret_; return ISO_SUCCESS; } int str2utf16be(const char *icharset, const char *input, uint16_t **output) { int result; wchar_t *wsrc_ = NULL; char *src; char *ret = NULL; char *ret_ = NULL; struct iso_iconv_handle conv; int conv_ret = 0; int direct_conv = 0; size_t loop_counter = 0, loop_limit = 3; size_t numchars; size_t outbytes; size_t inbytes; size_t n; if (icharset == NULL || input == NULL || output == NULL) { return ISO_NULL_POINTER; } /* Try the direct conversion. */ conv_ret = iso_iconv_open(&conv, "UTF-16BE", (char *) icharset, 0); if (conv_ret > 0) { direct_conv = 1; src = (char *) input; inbytes = strlen(input); loop_limit = inbytes + 3; outbytes = (2 * inbytes + 1) * sizeof(uint16_t); ret_ = malloc(outbytes); if (ret_ == NULL) return ISO_OUT_OF_MEM; ret = ret_; } else { /* Try via intermediate character set WCHAR_T. */ result = str2wchar(icharset, input, &wsrc_); if (result == (int) ISO_SUCCESS) { src = (char *)wsrc_; numchars = wcslen(wsrc_); inbytes = numchars * sizeof(wchar_t); loop_limit = inbytes + 3; ret_ = malloc((2 * numchars+1) * sizeof(uint16_t)); if (ret_ == NULL) { free(wsrc_); return ISO_OUT_OF_MEM; } outbytes = 2 * numchars * sizeof(uint16_t); ret = ret_; /* initialize iconv */ conv_ret = iso_iconv_open(&conv, "UTF-16BE", "WCHAR_T", 0); if (conv_ret <= 0) { free(wsrc_); free(ret_); } } else if (result != (int) ISO_CHARSET_CONV_ERROR) return result; } if (conv_ret <= 0) { return ISO_CHARSET_CONV_ERROR; } n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0); while (n == (size_t) -1) { /* The destination buffer is too small. Stops here. */ if (errno == E2BIG) break; /* An incomplete multi bytes sequence was found. We * can't do anything here. That's quite unlikely. */ if (errno == EINVAL) break; /* The last possible error is an invalid multi bytes * sequence. Just replace the character with a "_". * Probably the character doesn't exist in UCS */ set_ucsbe((uint16_t*) ret, '_'); ret += sizeof(uint16_t); outbytes -= sizeof(uint16_t); if (!outbytes) break; /* There was an error with one character but some other remain * to be converted. That's probably a multibyte character. * See above comment. */ if (direct_conv) { src++; inbytes--; } else { src += sizeof(wchar_t); inbytes -= sizeof(wchar_t); } if (!inbytes) break; /* Just to appease my remorse about unclear loop ends */ loop_counter++; if (loop_counter > loop_limit) break; n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0); } iso_iconv_close(&conv, 0); /* close the UTF-16 string */ set_ucsbe((uint16_t*) ret, '\0'); if (wsrc_ != NULL) free(wsrc_); *output = (uint16_t*)ret_; return ISO_SUCCESS; } static int valid_d_char(char c) { return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c == '_'); } static int valid_a_char(char c) { return (c >= ' ' && c <= '"') || (c >= '%' && c <= '?') || (c >= 'A' && c <= 'Z') || (c == '_'); } static int valid_j_char(uint16_t c) { return cmp_ucsbe(&c, ' ') != -1 && cmp_ucsbe(&c, '*') && cmp_ucsbe(&c, '/') && cmp_ucsbe(&c, ':') && cmp_ucsbe(&c, ';') && cmp_ucsbe(&c, '?') && cmp_ucsbe(&c, '\\'); } /* @param relaxed bit0+1 0= strict ECMA-119 1= additionally allow lowercase (else map to upper) 2= allow all 8-bit characters bit2 allow all 7-bit characters (but map to upper if not bit0+1 == 2) */ static char map_fileid_char(char c, int relaxed) { char upper; if (c == '/') /* Allowing slashes would cause lots of confusion */ return '_'; if ((relaxed & 3) == 2) return c; if (valid_d_char(c)) return c; if ((relaxed & 4) && (c & 0x7f) == c && (c < 'a' || c > 'z')) return c; upper= toupper(c); if (valid_d_char(upper)) { if (relaxed & 3) { /* lower chars are allowed */ return c; } return upper; } return '_'; } static char *iso_dirid(const char *src, int size, int relaxed) { size_t len, i; char name[32]; len = strlen(src); if ((int) len > size) { len = size; } for (i = 0; i < len; i++) { #ifdef Libisofs_old_ecma119_nameS char c= toupper(src[i]); name[i] = valid_d_char(c) ? c : '_'; #else /* Libisofs_old_ecma119_nameS */ name[i] = map_fileid_char(src[i], relaxed); #endif /* ! Libisofs_old_ecma119_nameS */ } name[len] = '\0'; return strdup(name); } char *iso_1_dirid(const char *src, int relaxed) { return iso_dirid(src, 8, relaxed); } char *iso_2_dirid(const char *src) { return iso_dirid(src, 31, 0); } char *iso_1_fileid(const char *src, int relaxed, int force_dots) { char *dot; /* Position of the last dot in the filename, will be used * to calculate lname and lext. */ int lname, lext, pos, i; char dest[13]; /* 13 = 8 (name) + 1 (.) + 3 (ext) + 1 (\0) */ if (src == NULL) { return NULL; } dot = strrchr(src, '.'); if (dot == src && strlen(src) > 4) dot = NULL; /* Use the long extension instead of the empty name */ lext = dot ? strlen(dot + 1) : 0; lname = strlen(src) - lext - (dot ? 1 : 0); /* If we can't build a filename, return NULL. */ if (lname == 0 && lext == 0) { return NULL; } pos = 0; /* Convert up to 8 characters of the filename. */ for (i = 0; i < lname && i < 8; i++) { #ifdef Libisofs_old_ecma119_nameS char c= toupper(src[i]); dest[pos++] = valid_d_char(c) ? c : '_'; #else /* Libisofs_old_ecma119_nameS */ if (dot == NULL && src[i] == '.') dest[pos++] = '_'; /* make sure that ignored dots do not appear */ else dest[pos++] = map_fileid_char(src[i], relaxed); #endif /* ! Libisofs_old_ecma119_nameS */ } /* This dot is mandatory, even if there is no extension. */ if (force_dots || lext > 0) dest[pos++] = '.'; /* Convert up to 3 characters of the extension, if any. */ for (i = 0; i < lext && i < 3; i++) { #ifdef Libisofs_old_ecma119_nameS char c= toupper(src[lname + 1 + i]); dest[pos++] = valid_d_char(c) ? c : '_'; #else /* Libisofs_old_ecma119_nameS */ dest[pos++] = map_fileid_char(src[lname + 1 + i], relaxed); #endif /* ! Libisofs_old_ecma119_nameS */ } dest[pos] = '\0'; return strdup(dest); } char *iso_2_fileid(const char *src) { char *dot; int lname, lext, lnname, lnext, pos, i; char dest[32]; /* 32 = 30 (name + ext) + 1 (.) + 1 (\0) */ if (src == NULL) { return NULL; } dot = strrchr(src, '.'); /* * Since the maximum length can be divided freely over the name and * extension, we need to calculate their new lengths (lnname and * lnext). If the original filename is too long, we start by trimming * the extension, but keep a minimum extension length of 3. */ if (dot == NULL || *(dot + 1) == '\0') { lname = strlen(src); lnname = (lname > 30) ? 30 : lname; lext = lnext = 0; } else { lext = strlen(dot + 1); lname = strlen(src) - lext - 1; lnext = (strlen(src) > 31 && lext > 3) ? (lname < 27 ? 30 - lname : 3) : lext; lnname = (strlen(src) > 31) ? 30 - lnext : lname; } if (lnname == 0 && lnext == 0) { return NULL; } pos = 0; /* Convert up to lnname characters of the filename. */ for (i = 0; i < lnname; i++) { char c= toupper(src[i]); dest[pos++] = valid_d_char(c) ? c : '_'; } dest[pos++] = '.'; /* Convert up to lnext characters of the extension, if any. */ for (i = 0; i < lnext; i++) { char c= toupper(src[lname + 1 + i]); dest[pos++] = valid_d_char(c) ? c : '_'; } dest[pos] = '\0'; return strdup(dest); } /** * Create a dir name suitable for an ISO image with relaxed constraints. * * @param size * Max len for the name * @param relaxed * bit0+1: 0 only allow d-characters, * 1 allow also lowe case chars, * 2 allow all 8-bit characters, * bit2: allow 7-bit characters (but map lowercase to uppercase if * not bit0+1 == 2) */ char *iso_r_dirid(const char *src, int size, int relaxed) { size_t len, i; char *dest; len = strlen(src); if ((int) len > size) { len = size; } dest = malloc(len + 1); if (dest == NULL) return NULL; for (i = 0; i < len; i++) { #ifdef Libisofs_old_ecma119_nameS char c= src[i]; if (relaxed == 2) { /* all chars are allowed */ dest[i] = c; } else if (valid_d_char(c)) { /* it is a valid char */ dest[i] = c; } else { c= toupper(src[i]); if (valid_d_char(c)) { if (relaxed) { /* lower chars are allowed */ dest[i] = src[i]; } else { dest[i] = c; } } else { dest[i] = '_'; } } #else /* Libisofs_old_ecma119_nameS */ dest[i] = map_fileid_char(src[i], relaxed); #endif /* ! Libisofs_old_ecma119_nameS */ } dest[len] = '\0'; return dest; } /** * Create a file name suitable for an ISO image with level > 1 and * with relaxed constraints. * * @param len * Max len for the name, without taken the "." into account. * @param relaxed * bit0+1: 0 only allow d-characters, * 1 allow also lowe case chars, * 2 allow all 8-bit characters, * bit2: allow 7-bit characters (but map lowercase to uppercase if * not bit0+1 == 2) * @param forcedot * Whether to ensure that "." is added */ char *iso_r_fileid(const char *src, size_t len, int relaxed, int forcedot) { char *dot, *retval = NULL; int lname, lext, lnname, lnext, pos, i; char *dest = NULL; dest = calloc(len + 1 + 1, 1); if (dest == NULL) goto ex; if (src == NULL) { goto ex; } dot = strrchr(src, '.'); /* * Since the maximum length can be divided freely over the name and * extension, we need to calculate their new lengths (lnname and * lnext). If the original filename is too long, we start by trimming * the extension, but keep a minimum extension length of 3. */ if (dot == NULL || *(dot + 1) == '\0') { lname = strlen(src); lnname = (lname > (int) len) ? (int) len : lname; lext = lnext = 0; } else { lext = strlen(dot + 1); lname = strlen(src) - lext - 1; lnext = (strlen(src) > len + 1 && lext > 3) ? (lname < (int) len - 3 ? (int) len - lname : 3) : lext; lnname = (strlen(src) > len + 1) ? (int) len - lnext : lname; } if (lnname == 0 && lnext == 0) { goto ex; } pos = 0; /* Convert up to lnname characters of the filename. */ for (i = 0; i < lnname; i++) { #ifdef Libisofs_old_ecma119_nameS char c= src[i]; if (relaxed == 2) { /* all chars are allowed */ dest[pos++] = c; } else if (valid_d_char(c)) { /* it is a valid char */ dest[pos++] = c; } else { c= toupper(src[i]); if (valid_d_char(c)) { if (relaxed) { /* lower chars are allowed */ dest[pos++] = src[i]; } else { dest[pos++] = c; } } else { dest[pos++] = '_'; } } #else /* Libisofs_old_ecma119_nameS */ dest[pos++] = map_fileid_char(src[i], relaxed); #endif /* ! Libisofs_old_ecma119_nameS */ } if (lnext > 0 || forcedot) { dest[pos++] = '.'; } /* Convert up to lnext characters of the extension, if any. */ for (i = lname + 1; i < lname + 1 + lnext; i++) { #ifdef Libisofs_old_ecma119_nameS char c= src[i]; if (relaxed == 2) { /* all chars are allowed */ dest[pos++] = c; } else if (valid_d_char(c)) { /* it is a valid char */ dest[pos++] = c; } else { c= toupper(src[i]); if (valid_d_char(c)) { if (relaxed) { /* lower chars are allowed */ dest[pos++] = src[i]; } else { dest[pos++] = c; } } else { dest[pos++] = '_'; } } #else /* Libisofs_old_ecma119_nameS */ dest[pos++] = map_fileid_char(src[i], relaxed); #endif /* ! Libisofs_old_ecma119_nameS */ } dest[pos] = '\0'; retval = strdup(dest); ex:; if (dest != NULL) free(dest); return retval; } /* bit0= no_force_dots bit1= allow 103 characters rather than 64 */ uint16_t *iso_j_file_id(const uint16_t *src, int flag) { uint16_t *dot, *retval = NULL; size_t lname, lext, lnname, lnext, pos, i, maxchar = 64; uint16_t *dest = NULL, c; LIBISO_ALLOC_MEM_VOID(dest, uint16_t, LIBISO_JOLIET_NAME_MAX); /* was: 66 = 64 (name + ext) + 1 (.) + 1 (\0) */ if (src == NULL) { goto ex; } if (flag & 2) maxchar = 103; dot = ucsrchr(src, '.'); /* * Since the maximum length can be divided freely over the name and * extension, we need to calculate their new lengths (lnname and * lnext). If the original filename is too long, we start by trimming * the extension, but keep a minimum extension length of 3. */ if (dot == NULL || cmp_ucsbe(dot + 1, '\0') == 0) { lname = ucslen(src); lnname = (lname > maxchar) ? maxchar : lname; lext = lnext = 0; } else { lext = ucslen(dot + 1); lname = ucslen(src) - lext - 1; lnext = (ucslen(src) > maxchar + 1 && lext > 3) ? (lname < maxchar - 3 ? maxchar - lname : 3) : lext; lnname = (ucslen(src) > maxchar + 1) ? maxchar - lnext : lname; } if (lnname == 0 && lnext == 0) { goto ex; } pos = 0; /* Convert up to lnname characters of the filename. */ for (i = 0; i < lnname; i++) { c = src[i]; if (valid_j_char(c)) { dest[pos++] = c; } else { set_ucsbe(dest + pos, '_'); pos++; } } if (pos > 0) iso_handle_split_utf16(dest + (pos - 1)); if ((flag & 1) && lnext <= 0) goto is_done; set_ucsbe(dest + pos, '.'); pos++; /* Convert up to lnext characters of the extension, if any. */ for (i = 0; i < lnext; i++) { uint16_t c = src[lname + 1 + i]; if (valid_j_char(c)) { dest[pos++] = c; } else { set_ucsbe(dest + pos, '_'); pos++; } } iso_handle_split_utf16(dest + (pos - 1)); is_done:; set_ucsbe(dest + pos, '\0'); retval = ucsdup(dest); ex:; LIBISO_FREE_MEM(dest); return retval; } /* @param flag bit1= allow 103 characters rather than 64 */ uint16_t *iso_j_dir_id(const uint16_t *src, int flag) { size_t len, i, maxchar = 64; uint16_t *dest = NULL, *retval = NULL; /* was: 65 = 64 + 1 (\0) */ LIBISO_ALLOC_MEM_VOID(dest, uint16_t, LIBISO_JOLIET_NAME_MAX); if (src == NULL) { goto ex; } if (flag & 2) maxchar = 103; len = ucslen(src); if (len > maxchar) { len = maxchar; } for (i = 0; i < len; i++) { uint16_t c = src[i]; if (valid_j_char(c)) { dest[i] = c; } else { set_ucsbe(dest + i, '_'); } } iso_handle_split_utf16(dest + (len - 1)); set_ucsbe(dest + len, '\0'); retval = ucsdup(dest); ex: LIBISO_FREE_MEM(dest); return retval; } size_t ucslen(const uint16_t *str) { size_t i; for (i = 0; str[i]; i++) ; return i; } uint16_t *ucsrchr(const uint16_t *str, char c) { size_t len = ucslen(str); while (len-- > 0) { if (cmp_ucsbe(str + len, c) == 0) { return (uint16_t*)(str + len); } } return NULL; } uint16_t *ucsdup(const uint16_t *str) { uint16_t *ret; size_t len = ucslen(str); ret = malloc(2 * (len + 1)); if (ret == NULL) return NULL; if (ret != NULL) { memcpy(ret, str, 2 * (len + 1)); } return ret; } /** * Although each character is 2 bytes, we actually compare byte-by-byte * because the words are big-endian. Comparing possibly swapped words * would make the sorting order depend on the machine byte order. */ int ucscmp(const uint16_t *s1, const uint16_t *s2) { const uint8_t *s = (const uint8_t*)s1; const uint8_t *t = (const uint8_t*)s2; size_t len1 = ucslen(s1); size_t len2 = ucslen(s2); size_t i, len = MIN(len1, len2) * 2; for (i = 0; i < len; i++) { if (s[i] < t[i]) { return -1; } else if (s[i] > t[i]) { return 1; } } if (len1 < len2) return -1; else if (len1 > len2) return 1; return 0; } uint16_t *ucscpy(uint16_t *dest, const uint16_t *src) { size_t n = ucslen(src) + 1; memcpy(dest, src, n*2); return dest; } uint16_t *ucsncpy(uint16_t *dest, const uint16_t *src, size_t n) { n = MIN(n, ucslen(src) + 1); memcpy(dest, src, n*2); if (n >= 2) iso_handle_split_utf16(dest + (n - 2)); return dest; } int str2d_char(const char *icharset, const char *input, char **output) { int ret; char *ascii; size_t len, i; if (output == NULL) { return ISO_OUT_OF_MEM; } /** allow NULL input */ if (input == NULL) { *output = NULL; return 0; } /* this checks for NULL parameters */ ret = str2ascii(icharset, input, &ascii); if (ret < 0) { *output = NULL; return ret; } len = strlen(ascii); for (i = 0; i < len; ++i) { char c= toupper(ascii[i]); ascii[i] = valid_d_char(c) ? c : '_'; } *output = ascii; return ISO_SUCCESS; } int str2a_char(const char *icharset, const char *input, char **output) { int ret; char *ascii; size_t len, i; if (output == NULL) { return ISO_OUT_OF_MEM; } /** allow NULL input */ if (input == NULL) { *output = NULL; return 0; } /* this checks for NULL parameters */ ret = str2ascii(icharset, input, &ascii); if (ret < 0) { *output = NULL; return ret; } len = strlen(ascii); for (i = 0; i < len; ++i) { char c= toupper(ascii[i]); ascii[i] = valid_a_char(c) ? c : '_'; } *output = ascii; return ISO_SUCCESS; } void iso_lsb(uint8_t *buf, uint32_t num, int bytes) { int i; for (i = 0; i < bytes; ++i) buf[i] = (num >> (8 * i)) & 0xff; } void iso_msb(uint8_t *buf, uint32_t num, int bytes) { int i; for (i = 0; i < bytes; ++i) buf[bytes - 1 - i] = (num >> (8 * i)) & 0xff; } void iso_bb(uint8_t *buf, uint32_t num, int bytes) { iso_lsb(buf, num, bytes); iso_msb(buf+bytes, num, bytes); } /* An alternative to iso_lsb() which advances the write pointer */ int iso_lsb_to_buf(char **wpt, uint32_t value, int bytes, int flag) { int b, bits; bits = bytes * 8; for (b = 0; b < bits; b += 8) *((unsigned char *) ((*wpt)++)) = (value >> b) & 0xff; return (1); } uint32_t iso_read_lsb(const uint8_t *buf, int bytes) { int i; uint32_t ret = 0; for (i=0; i 52 || tzoffset < -48 || always_gmt) { /* absurd timezone offset, represent time in GMT */ gmtime_r(&t, &tm); tzoffset = 0; } buf[0] = tm.tm_year; buf[1] = tm.tm_mon + 1; buf[2] = tm.tm_mday; buf[3] = tm.tm_hour; buf[4] = tm.tm_min; buf[5] = tm.tm_sec; buf[6] = tzoffset; } void iso_datetime_17(unsigned char *buf, time_t t, int always_gmt) { static int tzsetup = 0; static int tzoffset; struct tm tm; if (t == (time_t) - 1) { /* unspecified time */ memset(buf, '0', 16); buf[16] = 0; return; } if (!tzsetup) { tzset(); tzsetup = 1; } memset(&tm, 0, sizeof(tm)); tm.tm_isdst = -1; /* some OSes change tm_isdst only if it is -1 */ localtime_r(&t, &tm); localtime_r(&t, &tm); #ifdef HAVE_TM_GMTOFF tzoffset = tm.tm_gmtoff / 60 / 15; #else if (tm.tm_isdst < 0) tm.tm_isdst = 0; #ifndef Libburnia_timezonE #define Libburnia_timezonE timezone #endif #if Libburnia_timezonE == 0 always_gmt = 1; #endif tzoffset = ( - Libburnia_timezonE / 60 / 15 ) + 4 * tm.tm_isdst; #endif /* ! HAVE_TM_GMTOFF */ if (tzoffset > 52 || tzoffset < -48 || always_gmt) { /* absurd timezone offset, represent time in GMT */ gmtime_r(&t, &tm); tzoffset = 0; } sprintf((char*)&buf[0], "%04d", tm.tm_year + 1900); sprintf((char*)&buf[4], "%02d", tm.tm_mon + 1); sprintf((char*)&buf[6], "%02d", tm.tm_mday); sprintf((char*)&buf[8], "%02d", tm.tm_hour); sprintf((char*)&buf[10], "%02d", tm.tm_min); sprintf((char*)&buf[12], "%02d", MIN(59, tm.tm_sec)); memcpy(&buf[14], "00", 2); buf[16] = tzoffset; } #ifndef HAVE_TIMEGM /* putenv is SVr4, POSIX.1-2001, 4.3BSD , setenv is 4.3BSD, POSIX.1-2001. So putenv is more widely available. Also, setenv spoils eventual putenv expectation of applications because putenv installs the original string which then may be altered from its owner. setenv installs a copy that may not be altered. Both are slow. Thus first try with a naive implementation that assumes no leap seconds. If it fails a test with gmtime() then use the slow function with mktime(). */ #define Libisofs_use_putenV yes static time_t env_timegm(struct tm *tm) { time_t ret; char *tz; #ifdef Libisofs_use_putenV static char unset_name[] = {"TZ"}; tz = getenv("TZ"); putenv("TZ="); tzset(); ret = mktime(tm); if (tz != NULL) { /* tz is a pointer to the value part in a string of form "TZ="value */ putenv(tz - 3); } else putenv(unset_name); /* not daring to submit constant */ tzset(); #else /* Libisofs_use_putenV */ tz = getenv("TZ"); setenv("TZ", "", 1); tzset(); ret = mktime(tm); if (tz) setenv("TZ", tz, 1); else unsetenv("TZ"); tzset(); #endif /* ! Libisofs_use_putenV */ return ret; } static int ts_is_leapyear(int tm_year) /* years since 1900 */ { return ((tm_year % 4) == 0 && ((tm_year % 100) != 0 || (tm_year % 400) == 100)); } /* Fast implementation without leap seconds. Inspired by but not copied from code by Kungliga Tekniska Hgskolan (Royal Institute of Technology, Stockholm, Sweden), which was modified by Andrew Tridgell for Samba4. I claim own copyright 2011 Thomas Schmitt . */ static time_t ts_timegm(struct tm *tm) { time_t ret; static int month_length_normal[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; static int month_length_leap[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; int *month_length_pt; int years, i; ret = 0; years = tm->tm_year - 70; /* Years since 1970 */ if (years < 0) return ret; for (i = 0; i < years; i++) { ret += 365 * 86400; if (ts_is_leapyear(70 + i)) ret += 86400; } if (ts_is_leapyear(tm->tm_year)) month_length_pt = month_length_leap; else month_length_pt = month_length_normal; for (i = 0; i < tm->tm_mon; i++) ret += month_length_pt[i] * 86400; ret += (tm->tm_mday - 1) * 86400; ret += tm->tm_hour * 3600; ret += tm->tm_min * 60; ret += tm->tm_sec; return ret; } static time_t timegm(struct tm *tm) { time_t raw_t, ret; struct tm *test_tm, input_tm_copy; /* Beware of ill effects if tm is result of gmtime() or alike */ memcpy(&input_tm_copy, tm, sizeof(struct tm)); /* Try without leapseconds (which are rarely implemented, as it seems) */ raw_t = ts_timegm(tm); if (raw_t == 0) return raw_t; /* Check whether this translates back to the input values */ test_tm = gmtime(&raw_t); if (input_tm_copy.tm_sec == test_tm->tm_sec && input_tm_copy.tm_min == test_tm->tm_min && input_tm_copy.tm_hour == test_tm->tm_hour && input_tm_copy.tm_mday == test_tm->tm_mday && input_tm_copy.tm_mon == test_tm->tm_mon && input_tm_copy.tm_year == test_tm->tm_year) { ret = raw_t; } else { /* Mismatch. Use slow method around mktime() */ ret = env_timegm(&input_tm_copy); } return ret; } #endif /* ! HAVE_TIMEGM */ time_t iso_datetime_read_7(const uint8_t *buf) { struct tm tm; tm.tm_year = buf[0]; tm.tm_mon = buf[1] - 1; tm.tm_mday = buf[2]; tm.tm_hour = buf[3]; tm.tm_min = buf[4]; tm.tm_sec = buf[5]; tm.tm_isdst = 0; return timegm(&tm) - ((int8_t)buf[6]) * 60 * 15; } time_t iso_datetime_read_17(const uint8_t *buf) { struct tm tm; sscanf((char*)&buf[0], "%4d", &tm.tm_year); sscanf((char*)&buf[4], "%2d", &tm.tm_mon); sscanf((char*)&buf[6], "%2d", &tm.tm_mday); sscanf((char*)&buf[8], "%2d", &tm.tm_hour); sscanf((char*)&buf[10], "%2d", &tm.tm_min); sscanf((char*)&buf[12], "%2d", &tm.tm_sec); tm.tm_year -= 1900; tm.tm_mon -= 1; tm.tm_isdst = 0; return timegm(&tm) - ((int8_t)buf[6]) * 60 * 15; } /** * Check whether the caller process has read access to the given local file. * * @return * 1 on success (i.e, the process has read access), < 0 on error * (including ISO_FILE_ACCESS_DENIED on access denied to the specified file * or any directory on the path). */ int iso_eaccess(const char *path) { int access; /* use non standard eaccess when available, open() otherwise */ #ifdef HAVE_EACCESS access = !eaccess(path, R_OK); #else int fd = open(path, O_RDONLY); if (fd != -1) { close(fd); access = 1; } else { access = 0; } #endif if (!access) { int err; /* error, choose an appropriate return code */ switch (errno) { case EACCES: err = ISO_FILE_ACCESS_DENIED; break; case ENOTDIR: case ENAMETOOLONG: case ELOOP: err = ISO_FILE_BAD_PATH; break; case ENOENT: err = ISO_FILE_DOESNT_EXIST; break; case EFAULT: case ENOMEM: err = ISO_OUT_OF_MEM; break; default: err = ISO_FILE_ERROR; break; } return err; } return ISO_SUCCESS; } char *iso_util_strcopy(const char *buf, size_t len) { char *str; str = calloc(len + 1, 1); if (str == NULL) { return NULL; } strncpy(str, buf, len); str[len] = '\0'; return str; } char *iso_util_strcopy_untail(const char *buf, size_t len_in) { char *str; int len; str = iso_util_strcopy(buf, len_in); if (str == NULL) { return NULL; } /* remove trailing spaces */ for (len = len_in - 1; len >= 0; --len) { if (str[len] != ' ') break; str[len] = 0; } return str; } /** * Copy up to \p max characters from \p src to \p dest. If \p src has less than * \p max characters, we pad dest with " " characters. */ void strncpy_pad(char *dest, const char *src, size_t max) { size_t len, i; if (src != NULL) { len = MIN(strlen(src), max); for (i = 0; i < len; ++i) dest[i] = src[i]; } else { len = 0; } for (i = len; i < max; ++i) dest[i] = ' '; } char *ucs2str(const char *buf, size_t len) { size_t outbytes, inbytes; char *str, *src, *out = NULL, *retval = NULL; struct iso_iconv_handle conv; int conv_ret; size_t n; inbytes = len; outbytes = (inbytes+1) * MB_LEN_MAX; /* ensure enought space */ out = calloc(outbytes, 1); if (out == NULL) return NULL; /* convert to local charset */ conv_ret = iso_iconv_open(&conv, iso_get_local_charset(0), "UCS-2BE", 0); if (conv_ret <= 0) { goto ex; } src = (char *)buf; str = (char *)out; n = iso_iconv(&conv, &src, &inbytes, &str, &outbytes, 0); iso_iconv_close(&conv, 0); if (n == (size_t) -1) { /* error */ goto ex; } *str = '\0'; /* remove trailing spaces */ for (len = strlen(out) - 1; out[len] == ' ' && len > 0; --len) out[len] = '\0'; retval = strdup(out); ex:; if (out != NULL) free(out); return retval; } void iso_lib_version(int *major, int *minor, int *micro) { *major = LIBISOFS_MAJOR_VERSION; *minor = LIBISOFS_MINOR_VERSION; *micro = LIBISOFS_MICRO_VERSION; } int iso_lib_is_compatible(int major, int minor, int micro) { int cmajor, cminor, cmicro; /* for now, the rule is that library is compitable if requested * version is lower */ iso_lib_version(&cmajor, &cminor, &cmicro); return cmajor > major || (cmajor == major && (cminor > minor || (cminor == minor && cmicro >= micro))); } int iso_init_locale(int flag) { setlocale(LC_CTYPE, ""); return 1; } int iso_util_encode_len_bytes(uint32_t data, char *buffer, int data_len, int *result_len, int flag) { uint32_t x; int i, l; char *wpt = buffer; if (data_len <= 0) { x = data; for (i = 0; i < 4 && x != 0; i++) x = x >> 8; l = i; if (l == 0) l = 1; } else l = data_len; *((unsigned char *) (wpt++)) = l; for (i = 0; i < l; i++) *((unsigned char *) (wpt++)) = data >> (8 * (l - i - 1)); *result_len = l + 1; return ISO_SUCCESS; } int iso_util_decode_len_bytes(uint32_t *data, char *buffer, int *data_len, int buffer_len, int flag) { int i; *data = 0; *data_len = ((unsigned char *) buffer)[0]; if (*data_len > buffer_len - 1) *data_len = buffer_len - 1; for (i = 1; i <= *data_len; i++) *data = (*data << 8) | ((unsigned char *) buffer)[i]; return ISO_SUCCESS; } int iso_util_dec_to_uint32(char *dec, uint32_t *value, int flag) { double num; sscanf(dec, "%lf", &num); if (num < 0 || num > 4294967295.0) return 0; *value = num; return 1; } int iso_util_bin_to_hex(char *target, uint8_t *bytes, int num_bytes, int flag) { int i; for (i = 0; i < num_bytes; i++) sprintf(target + 2 * i, "%-2.2x", bytes[i]); target[2 * num_bytes] = 0; return 1; } int iso_util_hex_to_bin(char *hex, char *bin, int bin_size, int *bin_count, int flag) { static char *allowed = {"0123456789ABCDEFabcdef"}; char b[3]; int i; unsigned int u; b[2] = 0; *bin_count = 0; for (i = 0; i < bin_size; i++) { b[0] = hex[2 * i]; b[1] = hex[2 * i + 1]; if (strchr(allowed, b[0]) == NULL || strchr(allowed, b[1]) == NULL) break; sscanf(b, "%x", &u); ((unsigned char *) bin)[i] = u; (*bin_count)++; } return (*bin_count > 0); } int iso_util_tag_magic(int tag_type, char **tag_magic, int *len, int flag) { static char *magic[] = {"", "libisofs_checksum_tag_v1", "libisofs_sb_checksum_tag_v1", "libisofs_tree_checksum_tag_v1", "libisofs_rlsb32_checksum_tag_v1"}; static int magic_len[]= {0, 24, 27, 29, 31}; static int magic_max = 4; *tag_magic = NULL; *len = 0; if (tag_type < 0 || tag_type > magic_max) return ISO_WRONG_ARG_VALUE; *tag_magic = magic[tag_type]; *len = magic_len[tag_type]; return magic_max; } int iso_util_decode_md5_tag(char data[2048], int *tag_type, uint32_t *pos, uint32_t *range_start, uint32_t *range_size, uint32_t *next_tag, char md5[16], int flag) { int ret, bin_count, i, mode, magic_first = 1, magic_last = 4; int magic_len = 0; char *cpt, self_md5[16], tag_md5[16], *tag_magic; void *ctx = NULL; *next_tag = 0; mode = flag & 255; if (mode > magic_last) return ISO_WRONG_ARG_VALUE; if (mode > 0) magic_first = magic_last = mode; for (i = magic_first; i <= magic_last; i++) { iso_util_tag_magic(i, &tag_magic, &magic_len, 0); if (strncmp(data, tag_magic, magic_len) == 0) break; } if (i > magic_last ) return 0; *tag_type = i; cpt = data + magic_len + 1; if (strncmp(cpt, "pos=", 4) != 0) return 0; cpt+= 4; ret = iso_util_dec_to_uint32(cpt, pos, 0); if (ret <= 0) return 0; cpt = strstr(cpt, "range_start="); if (cpt == NULL) return(0); ret = iso_util_dec_to_uint32(cpt + 12, range_start, 0); if (ret <= 0) return 0; cpt = strstr(cpt, "range_size="); if (cpt == NULL) return(0); ret = iso_util_dec_to_uint32(cpt + 11, range_size, 0); if (ret <= 0) return 0; if (*tag_type == 2 || *tag_type == 3) { cpt = strstr(cpt, "next="); if (cpt == NULL) return(0); ret = iso_util_dec_to_uint32(cpt + 5, next_tag, 0); if (ret <= 0) return 0; } else if (*tag_type == 4) { cpt = strstr(cpt, "session_start="); if (cpt == NULL) return(0); ret = iso_util_dec_to_uint32(cpt + 14, next_tag, 0); if (ret <= 0) return 0; } cpt = strstr(cpt, "md5="); if (cpt == NULL) return(0); ret = iso_util_hex_to_bin(cpt + 4, md5, 16, &bin_count, 0); if (ret <= 0 || bin_count != 16) return 0; cpt += 4 + 32; ret = iso_md5_start(&ctx); if (ret < 0) return ret; iso_md5_compute(ctx, data , cpt - data); iso_md5_end(&ctx, tag_md5); cpt = strstr(cpt, "self="); if (cpt == NULL) return(0); ret = iso_util_hex_to_bin(cpt + 5, self_md5, 16, &bin_count, 0); if (ret <= 0 || bin_count != 16) return 0; for(i= 0; i < 16; i++) if(self_md5[i] != tag_md5[i]) return ISO_MD5_AREA_CORRUPTED; if (*(cpt + 5 + 32) != '\n') return 0; return(1); } int iso_util_eval_md5_tag(char *block, int desired, uint32_t lba, void *ctx, uint32_t ctx_start_lba, int *tag_type, uint32_t *next_tag, int flag) { int decode_ret, ret; char md5[16], cloned_md5[16]; uint32_t pos, range_start, range_size; void *cloned_ctx = NULL; *tag_type = 0; decode_ret = iso_util_decode_md5_tag(block, tag_type, &pos, &range_start, &range_size, next_tag, md5, 0); if (decode_ret != 1 && decode_ret != (int) ISO_MD5_AREA_CORRUPTED) return 0; if (*tag_type > 30) goto unexpected_type; if (decode_ret == (int) ISO_MD5_AREA_CORRUPTED) { ret = decode_ret; goto ex; } else if (!((1 << *tag_type) & desired)) { unexpected_type:; iso_msg_submit(-1, ISO_MD5_TAG_UNEXPECTED, 0, NULL); ret = 0; goto ex; } else if (pos != lba) { if (*tag_type == 2) { /* Superblock tag */ if (lba < 32) { /* Check whether this is a copied superblock */ range_start -= (off_t) pos - (off_t) lba; if (range_start != ctx_start_lba) { /* >>> check for matching MD5 ? */; ret = ISO_MD5_TAG_MISPLACED; } else ret = ISO_MD5_TAG_COPIED; goto ex; } } ret = ISO_MD5_TAG_MISPLACED; goto ex; } else if (range_start != ctx_start_lba) { ret = ISO_MD5_TAG_MISPLACED; goto ex; } ret = iso_md5_clone(ctx, &cloned_ctx); if (ret < 0) goto ex; iso_md5_end(&cloned_ctx, cloned_md5); if (! iso_md5_match(cloned_md5, md5)) { ret = ISO_MD5_TAG_MISMATCH; goto ex; } ret = 1; ex:; if (ret < 0) iso_msg_submit(-1, ret, 0, NULL); return ret; } void *iso_alloc_mem(size_t size, size_t count, int flag) { void *pt; pt = calloc(size, count); if(pt == NULL) iso_msg_submit(-1, ISO_OUT_OF_MEM, 0, "Out of virtual memory"); return pt; } uint16_t iso_ntohs(uint16_t v) { return iso_read_msb((uint8_t *) &v, 2); } uint16_t iso_htons(uint16_t v) { uint16_t ret; iso_msb((uint8_t *) &ret, (uint32_t) v, 2); return ret; } /* If an UTF-16 surrogate pair was split : Change to UTF-16 '_'. (UCS-2 is promised to reserve 0xd800 to 0xdbff for UTF-16). */ void iso_handle_split_utf16(uint16_t *utf_word) { unsigned char *hb; hb = (unsigned char *) utf_word; if ((hb[0] & 0xfc) == 0xd8) set_ucsbe(utf_word, '_'); } int iso_clone_mem(char *in, char **out, size_t size) { if (in == NULL) { *out = NULL; return 1; } if (size == 0) size = strlen(in) + 1; *out = calloc(1, size); if (*out == NULL) return ISO_OUT_OF_MEM; memcpy(*out, in, size); return ISO_SUCCESS; } int iso_clone_mgtd_mem(char *in, char **out, size_t size) { if (*out != NULL) free(*out); return iso_clone_mem(in, out, size); } /** Convert a text into a number of type double and multiply it by unit code [kmgt] (2^10 to 2^40) or [s] (2048) or [d] (512). (Also accepts capital letters.) @param text Input like "42", "223062s", "3m" or "-1g" @param flag Bitfield for control purposes: bit0= return -1 rathern than 0 on failure bit1= if scaled then compute the last byte of the last unit @return The derived value */ off_t iso_scanf_io_size(char *text, int flag) { int c; off_t ret = 0, fac = 1; char *rpt; for (rpt = text; *rpt >= '0' && *rpt <= '9'; rpt++) ret = ret * 10 + (*rpt - '0'); if (rpt == text) return (off_t) (flag & 1 ? -1 : 0); c = *rpt; if (c=='k' || c=='K') fac = 1024; else if (c=='m' || c=='M') fac = 1024 * 1024; else if (c=='g' || c=='G') fac = 1024 * 1024 * 1024; else if (c=='t' || c=='T') fac = ((off_t) 1024) * 1024 * 1024 * 1024; else if (c=='s' || c=='S') fac = 2048; else if (c=='d' || c=='D') fac = 512; ret *= fac; if (flag & 2) ret += fac - 1; return ret; } /* Find backward from idx the start byte of a possible UTF-8 character. https://en.wikipedia.org/wiki/UTF-8#Description */ static int find_utf8_start(char *name, int idx, int flag) { unsigned char *uname, uch; int i; uname= (unsigned char *) name; if ((uname[idx] & 0xc0) != 0x80) return idx; /* not an UTF-8 tail byte */ for (i = 0; i < 5 && idx - 1 - i >= 0; i++) { /* up to deprecated 6-byte codes */ uch = uname[idx - 1 - i]; if ((uch & 0xe0) == 0xc0 || (uch & 0xf0) == 0xe0 || (uch & 0xf8) == 0xf0 || (uch & 0xfc) == 0xf8 || (uch & 0xfe) == 0xfc) return (idx - 1 - i); /* UTF-8 start byte found */ if ((uch & 0xc0) != 0x80) return idx; /* not an UTF-8 tail byte, so no UTF-8 */ } return idx; /* no UTF-8 start found */ } /* @param flag bit0= do not issue warning message */ int iso_truncate_rr_name(int truncate_mode, int truncate_length, char *name, int flag) { int neck, goal, ret, l, i; static int hash_size = 32; void *ctx = NULL; char hashval[16]; l = strlen(name); if (l <= truncate_length) return ISO_SUCCESS; if (truncate_mode == 0) return ISO_RR_NAME_TOO_LONG; /* Compute hash */ ret = iso_md5_start(&ctx); if (ret < 0) goto ex; ret = iso_md5_compute(ctx, name, l > 4095 ? 4095 : l); if (ret < 0) goto ex; ret = iso_md5_end(&ctx, hashval); if (ret < 0) goto ex; if (!(flag & 1)) iso_msg_submit(-1, ISO_RR_NAME_TRUNCATED, 0, "File name had to be truncated and MD5 marked: %s", name); /* Avoid to produce incomplete UTF-8 characters */ goal = truncate_length - hash_size - 1; neck = find_utf8_start(name, goal, 0); for (; neck < goal; neck++) name[neck] = '_'; /* Write colon and hash text over end of truncated name */ name[goal] = ':'; goal++; for (i = 0; goal < truncate_length - 1 && i < hash_size / 2; goal += 2) { sprintf(name + goal, "%2.2x", *((unsigned char *) (hashval + i))); i++; } name[truncate_length] = 0; ret = ISO_SUCCESS; ex:; if (ctx != NULL) iso_md5_end(&ctx, hashval); return ret; } /* API */ int iso_truncate_leaf_name(int mode, int length, char *name, int flag) { int ret; if (mode < 0 || mode > 1) return ISO_WRONG_ARG_VALUE; if (length < 64 || length > LIBISOFS_NODE_NAME_MAX) return ISO_WRONG_ARG_VALUE; ret = iso_truncate_rr_name(mode, length, name, 1); return ret; } libisofs-1.4.2/libisofs/libisofs.ver0000644000175700017510000002232412575535604014442 00000000000000LIBISOFS6 { global: aaip_xinfo_cloner; aaip_xinfo_func; el_torito_get_bootable; el_torito_get_boot_media_type; el_torito_get_boot_platform_id; el_torito_get_id_string; el_torito_get_isolinux_options; el_torito_get_load_seg; el_torito_get_load_size; el_torito_get_selection_crit; el_torito_patch_isolinux_image; el_torito_seems_boot_info_table; el_torito_set_boot_platform_id; el_torito_set_id_string; el_torito_set_isolinux_options; el_torito_set_load_seg; el_torito_set_load_size; el_torito_set_no_bootable; el_torito_set_selection_crit; iso_conv_name_chars; iso_crc32_gpt; iso_data_source_new_from_file; iso_data_source_ref; iso_data_source_unref; iso_dir_add_node; iso_dir_find_children; iso_dir_get_children; iso_dir_get_children_count; iso_dir_get_node; iso_dir_iter_free; iso_dir_iter_has_next; iso_dir_iter_next; iso_dir_iter_remove; iso_dir_iter_take; iso_error_get_code; iso_error_get_priority; iso_error_get_severity; iso_error_to_msg; iso_file_add_external_filter; iso_file_add_gzip_filter; iso_file_add_zisofs_filter; iso_file_get_md5; iso_file_get_old_image_lba; iso_file_get_old_image_sections; iso_file_get_size; iso_file_get_sort_weight; iso_file_get_stream; iso_file_make_md5; iso_file_remove_filter; iso_file_source_access; iso_file_source_close; iso_file_source_get_aa_string; iso_file_source_get_filesystem; iso_file_source_get_name; iso_file_source_get_path; iso_file_source_lseek; iso_file_source_lstat; iso_file_source_open; iso_file_source_read; iso_file_source_readdir; iso_file_source_readlink; iso_file_source_ref; iso_file_source_stat; iso_file_source_unref; iso_filesystem_ref; iso_filesystem_unref; iso_finish; iso_fs_global_id; iso_get_local_charset; iso_get_messenger; iso_gzip_get_refcounts; iso_hfsplus_xinfo_func; iso_hfsplus_xinfo_new; iso_image_add_boot_image; iso_image_add_mips_boot_file; iso_image_add_new_dir; iso_image_add_new_file; iso_image_add_new_special; iso_image_add_new_symlink; iso_image_attach_data; iso_image_create_burn_source; iso_image_filesystem_new; iso_image_fs_get_abstract_file_id; iso_image_fs_get_application_id; iso_image_fs_get_biblio_file_id; iso_image_fs_get_copyright_file_id; iso_image_fs_get_data_preparer_id; iso_image_fs_get_publisher_id; iso_image_fs_get_system_id; iso_image_fs_get_volset_id; iso_image_fs_get_volume_id; iso_image_generator_is_running; iso_image_get_abstract_file_id; iso_image_get_all_boot_imgs; iso_image_get_alpha_boot; iso_image_get_app_use; iso_image_get_application_id; iso_image_get_attached_data; iso_image_get_biblio_file_id; iso_image_get_bootcat; iso_image_get_boot_image; iso_image_get_copyright_file_id; iso_image_get_data_preparer_id; iso_image_dir_get_node; iso_image_get_hppa_palo; iso_image_get_mips_boot_files; iso_image_get_msg_id; iso_image_get_publisher_id; iso_image_get_pvd_times; iso_image_get_root; iso_image_get_session_md5; iso_image_get_sparc_core; iso_image_get_system_area; iso_image_get_system_id; iso_image_get_truncate_mode; iso_image_get_volset_id; iso_image_get_volume_id; iso_image_give_up_mips_boot; iso_image_hfsplus_bless; iso_image_hfsplus_get_blessed; iso_image_import; iso_image_new; iso_image_path_to_node; iso_image_ref; iso_image_remove_boot_image; iso_image_report_el_torito; iso_image_report_system_area; iso_image_set_abstract_file_id; iso_image_set_alpha_boot; iso_image_set_app_use; iso_image_set_application_id; iso_image_set_biblio_file_id; iso_image_set_boot_catalog_hidden; iso_image_set_boot_catalog_weight; iso_image_set_boot_image; iso_image_set_copyright_file_id; iso_image_set_data_preparer_id; iso_image_set_hppa_palo; iso_image_set_ignore_aclea; iso_image_set_node_name; iso_image_set_publisher_id; iso_image_set_sparc_core; iso_image_set_system_id; iso_image_set_truncate_mode; iso_image_set_volset_id; iso_image_set_volume_id; iso_image_tree_clone; iso_image_unref; iso_image_update_sizes; iso_init; iso_init_with_flag; iso_interval_reader_destroy; iso_interval_reader_new; iso_interval_reader_read; iso_lib_is_compatible; iso_lib_version; iso_local_attr_support; iso_local_get_acl_text; iso_local_get_attrs; iso_local_get_perms_wo_acl; iso_local_set_acl_text; iso_local_set_attrs; iso_md5_clone; iso_md5_compute; iso_md5_end; iso_md5_match; iso_md5_start; iso_memory_stream_new; iso_msgs_submit; iso_new_find_conditions_and; iso_new_find_conditions_atime; iso_new_find_conditions_ctime; iso_new_find_conditions_gid; iso_new_find_conditions_mode; iso_new_find_conditions_mtime; iso_new_find_conditions_name; iso_new_find_conditions_not; iso_new_find_conditions_or; iso_new_find_conditions_uid; iso_node_add_xinfo; iso_node_cmp_ino; iso_node_get_acl_text; iso_node_get_atime; iso_node_get_attrs; iso_node_get_ctime; iso_node_get_gid; iso_node_get_hidden; iso_node_get_mode; iso_node_get_mtime; iso_node_get_name; iso_node_get_next_xinfo; iso_node_get_old_image_lba; iso_node_get_parent; iso_node_get_permissions; iso_node_get_perms_wo_acl; iso_node_get_type; iso_node_get_uid; iso_node_get_xinfo; iso_node_lookup_attr; iso_node_ref; iso_node_remove; iso_node_remove_all_xinfo; iso_node_remove_tree; iso_node_remove_xinfo; iso_node_set_acl_text; iso_node_set_atime; iso_node_set_attrs; iso_node_set_ctime; iso_node_set_gid; iso_node_set_hidden; iso_node_set_mtime; iso_node_set_name; iso_node_set_permissions; iso_node_set_sort_weight; iso_node_set_uid; iso_node_take; iso_node_unref; iso_node_xinfo_get_cloner; iso_node_xinfo_make_clonable; iso_node_zf_by_magic; iso_obtain_msgs; iso_read_image_features_destroy; iso_read_image_features_get_size; iso_read_image_features_has_eltorito; iso_read_image_features_has_iso1999; iso_read_image_features_has_joliet; iso_read_image_features_has_rockridge; iso_read_opts_auto_input_charset; iso_read_opts_free; iso_read_opts_keep_import_src; iso_read_opts_load_system_area; iso_read_opts_new; iso_read_opts_set_default_gid; iso_read_opts_set_default_permissions; iso_read_opts_set_default_uid; iso_read_opts_set_ecma119_map; iso_read_opts_set_input_charset; iso_read_opts_set_new_inos; iso_read_opts_set_no_aaip; iso_read_opts_set_no_iso1999; iso_read_opts_set_no_joliet; iso_read_opts_set_no_md5; iso_read_opts_set_no_rockridge; iso_read_opts_set_preferjoliet; iso_read_opts_set_start_block; iso_ring_buffer_get_status; iso_set_abort_severity; iso_set_local_charset; iso_set_msgs_severities; iso_sev_to_text; iso_special_get_dev; iso_stream_clone; iso_stream_close; iso_stream_cmp_ino; iso_stream_get_external_filter; iso_stream_get_id; iso_stream_get_input_stream; iso_stream_get_size; iso_stream_get_source_path; iso_stream_is_repeatable; iso_stream_open; iso_stream_read; iso_stream_ref; iso_stream_unref; iso_stream_update_size; iso_symlink_get_dest; iso_symlink_set_dest; iso_text_to_sev; iso_tree_add_dir_rec; iso_tree_add_exclude; iso_tree_add_new_cut_out_node; iso_tree_add_new_dir; iso_tree_add_new_file; iso_tree_add_new_node; iso_tree_add_new_special; iso_tree_add_new_symlink; iso_tree_add_node; iso_tree_clone; iso_tree_get_follow_symlinks; iso_tree_get_ignore_hidden; iso_tree_get_ignore_special; iso_tree_get_node_path; iso_tree_get_replace_mode; iso_tree_path_to_node; iso_tree_remove_exclude; iso_tree_resolve_symlink; iso_tree_set_follow_symlinks; iso_tree_set_ignore_hidden; iso_tree_set_ignore_special; iso_tree_set_replace_mode; iso_tree_set_report_callback; iso_truncate_leaf_name; iso_util_decode_md5_tag; iso_write_opts_attach_jte; iso_write_opts_detach_jte; iso_write_opts_free; iso_write_opts_get_data_start; iso_write_opts_new; iso_write_opts_set_aaip; iso_write_opts_set_aaip_susp_1_10; iso_write_opts_set_allow_7bit_ascii; iso_write_opts_set_allow_deep_paths; iso_write_opts_set_allow_dir_id_ext; iso_write_opts_set_allow_full_ascii; iso_write_opts_set_allow_longer_paths; iso_write_opts_set_allow_lowercase; iso_write_opts_set_always_gmt; iso_write_opts_set_appendable; iso_write_opts_set_appended_as_gpt; iso_write_opts_set_default_dir_mode; iso_write_opts_set_default_file_mode; iso_write_opts_set_default_gid; iso_write_opts_set_default_timestamp; iso_write_opts_set_default_uid; iso_write_opts_set_dir_rec_mtime; iso_write_opts_set_disc_label; iso_write_opts_set_efi_bootp; iso_write_opts_set_fat; iso_write_opts_set_fifo_size; iso_write_opts_set_hardlinks; iso_write_opts_set_hfsp_block_size; iso_write_opts_set_hfsp_serial_number; iso_write_opts_set_hfsplus; iso_write_opts_set_iso1999; iso_write_opts_set_iso_level; iso_write_opts_set_joliet; iso_write_opts_set_joliet_long_names; iso_write_opts_set_joliet_longer_paths; iso_write_opts_set_joliet_utf16; iso_write_opts_set_max_37_char_filenames; iso_write_opts_set_ms_block; iso_write_opts_set_no_force_dots; iso_write_opts_set_old_empty; iso_write_opts_set_omit_version_numbers; iso_write_opts_set_output_charset; iso_write_opts_set_overwrite_buf; iso_write_opts_set_part_offset; iso_write_opts_set_partition_img; iso_write_opts_set_prep_img; iso_write_opts_set_pvd_times; iso_write_opts_set_record_md5; iso_write_opts_set_relaxed_vol_atts; iso_write_opts_set_replace_mode; iso_write_opts_set_replace_timestamps; iso_write_opts_set_rockridge; iso_write_opts_set_rr_reloc; iso_write_opts_set_rrip_1_10_px_ino; iso_write_opts_set_rrip_version_1_10; iso_write_opts_set_scdbackup_tag; iso_write_opts_set_sort_files; iso_write_opts_set_system_area; iso_write_opts_set_tail_blocks; iso_write_opts_set_untranslated_name_len; iso_write_opts_set_will_cancel; iso_zisofs_get_params; iso_zisofs_get_refcounts; iso_zisofs_set_params; serial_id; local: *; }; libisofs-1.4.2/libisofs/image.c0000644000175700017510000007761612575534435013357 00000000000000/* * Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2009 - 2015 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif #include "libisofs.h" #include "image.h" #include "node.h" #include "messages.h" #include "eltorito.h" #include #include #include int iso_imported_sa_new(struct iso_imported_sys_area **boots, int flag) { struct iso_imported_sys_area *b; *boots = NULL; b = calloc(1, sizeof(struct iso_imported_sys_area)); if (b == NULL) return ISO_OUT_OF_MEM; b->mbr_req = NULL; b->apm_req = NULL; b->gpt_req = NULL; b->gpt_backup_comments = NULL; b->mips_boot_file_paths = NULL; b->mips_vd_entries = NULL; b->sparc_disc_label = NULL; b->sparc_core_node = NULL; b->sparc_entries = NULL; b->hppa_cmdline = NULL; b->hppa_bootloader = NULL; b->hppa_kernel_32 = NULL; b->hppa_kernel_64 = NULL; b->hppa_ramdisk = NULL; b->alpha_boot_image = NULL; *boots = b; return 1; } int iso_imported_sa_unref(struct iso_imported_sys_area **boots, int flag) { int i; struct iso_imported_sys_area *b; b = *boots; if (b == NULL) return 2; if (b->refcount > 0) b->refcount--; if (b->refcount > 0) return 2; if (b->mbr_req != NULL) { for (i = 0; i < b->mbr_req_count; i++) LIBISO_FREE_MEM(b->mbr_req[i]); LIBISO_FREE_MEM(b->mbr_req); } if (b->apm_req != NULL) { for (i = 0; i < b->apm_req_count; i++) LIBISO_FREE_MEM(b->apm_req[i]); LIBISO_FREE_MEM(b->apm_req); } if (b->gpt_req != NULL) { for (i = 0; i < b->gpt_req_count; i++) LIBISO_FREE_MEM(b->gpt_req[i]); LIBISO_FREE_MEM(b->gpt_req); } LIBISO_FREE_MEM(b->gpt_backup_comments); if (b->mips_boot_file_paths != NULL) { for (i = 0; i < b->num_mips_boot_files; i++) LIBISO_FREE_MEM(b->mips_boot_file_paths[i]); LIBISO_FREE_MEM(b->mips_boot_file_paths); } if (b->mips_vd_entries != NULL) { for (i = 0; i < b->num_mips_boot_files; i++) LIBISO_FREE_MEM(b->mips_vd_entries[i]); LIBISO_FREE_MEM(b->mips_vd_entries); } LIBISO_FREE_MEM(b->mipsel_boot_file_path); LIBISO_FREE_MEM(b->sparc_disc_label); if (b->sparc_core_node != NULL) iso_node_unref((IsoNode *) b->sparc_core_node); LIBISO_FREE_MEM(b->sparc_entries); LIBISO_FREE_MEM(b->hppa_cmdline); LIBISO_FREE_MEM(b->hppa_bootloader); LIBISO_FREE_MEM(b->hppa_kernel_32); LIBISO_FREE_MEM(b->hppa_kernel_64); LIBISO_FREE_MEM(b->hppa_ramdisk); LIBISO_FREE_MEM(b->alpha_boot_image); LIBISO_FREE_MEM(b); *boots = NULL; return 1; } /** * Create a new image, empty. * * The image will be owned by you and should be unref() when no more needed. * * @param name * Name of the image. This will be used as volset_id and volume_id. * @param image * Location where the image pointer will be stored. * @return * 1 success, < 0 error */ int iso_image_new(const char *name, IsoImage **image) { int res, i; IsoImage *img; if (image == NULL) { return ISO_NULL_POINTER; } img = calloc(1, sizeof(IsoImage)); if (img == NULL) { return ISO_OUT_OF_MEM; } /* local filesystem will be used by default */ res = iso_local_filesystem_new(&(img->fs)); if (res < 0) { free(img); return ISO_OUT_OF_MEM; } /* use basic builder as default */ res = iso_node_basic_builder_new(&(img->builder)); if (res < 0) { iso_filesystem_unref(img->fs); free(img); return ISO_OUT_OF_MEM; } /* fill image fields */ res = iso_node_new_root(&img->root); if (res < 0) { iso_node_builder_unref(img->builder); iso_filesystem_unref(img->fs); free(img); return res; } img->refcount = 1; img->id = iso_message_id++; if (name != NULL) { img->volset_id = strdup(name); img->volume_id = strdup(name); } memset(img->application_use, 0, 512); img->system_area_data = NULL; img->system_area_options = 0; img->num_mips_boot_files = 0; for (i = 0; i < 15; i++) img->mips_boot_file_paths[i] = NULL; img->sparc_core_node = NULL; img->hppa_cmdline= NULL; img->hppa_bootloader = NULL; img->hppa_kernel_32 = NULL; img->hppa_kernel_64 = NULL; img->hppa_ramdisk = NULL; img->alpha_boot_image = NULL; img->import_src = NULL; img->builder_ignore_acl = 1; img->builder_ignore_ea = 1; img->truncate_mode = 1; img->truncate_length = LIBISOFS_NODE_NAME_MAX; img->truncate_buffer[0] = 0; img->inode_counter = 0; img->used_inodes = NULL; img->used_inodes_start = 0; img->checksum_start_lba = 0; img->checksum_end_lba = 0; img->checksum_idx_count = 0; img->checksum_array = NULL; img->generator_is_running = 0; for (i = 0; i < ISO_HFSPLUS_BLESS_MAX; i++) img->hfsplus_blessed[i] = NULL; img->collision_warnings = 0; img->imported_sa_info = NULL; *image = img; return ISO_SUCCESS; } /** * Increments the reference counting of the given image. */ void iso_image_ref(IsoImage *image) { ++image->refcount; } /** * Decrements the reference counting of the given image. * If it reaches 0, the image is free, together with its tree nodes (whether * their refcount reach 0 too, of course). */ void iso_image_unref(IsoImage *image) { int nexcl, i; if (--image->refcount == 0) { /* we need to free the image */ if (image->user_data_free != NULL) { /* free attached data */ image->user_data_free(image->user_data); } for (nexcl = 0; nexcl < image->nexcludes; ++nexcl) { free(image->excludes[nexcl]); } free(image->excludes); for (i = 0; i < ISO_HFSPLUS_BLESS_MAX; i++) if (image->hfsplus_blessed[i] != NULL) iso_node_unref(image->hfsplus_blessed[i]); iso_node_unref((IsoNode*)image->root); iso_node_builder_unref(image->builder); iso_filesystem_unref(image->fs); el_torito_boot_catalog_free(image->bootcat); iso_image_give_up_mips_boot(image, 0); if (image->sparc_core_node != NULL) iso_node_unref((IsoNode *) image->sparc_core_node); iso_image_set_hppa_palo(image, NULL, NULL, NULL, NULL, NULL, 1); if (image->alpha_boot_image != NULL) free(image->alpha_boot_image); if (image->import_src != NULL) iso_data_source_unref(image->import_src); free(image->volset_id); free(image->volume_id); free(image->publisher_id); free(image->data_preparer_id); free(image->system_id); free(image->application_id); free(image->copyright_file_id); free(image->abstract_file_id); free(image->biblio_file_id); free(image->creation_time); free(image->modification_time); free(image->expiration_time); free(image->effective_time); if (image->used_inodes != NULL) free(image->used_inodes); if (image->system_area_data != NULL) free(image->system_area_data); iso_image_free_checksums(image, 0); iso_imported_sa_unref(&(image->imported_sa_info), 0); free(image); } } int iso_image_free_checksums(IsoImage *image, int flag) { image->checksum_start_lba = 0; image->checksum_end_lba = 0; image->checksum_idx_count = 0; if (image->checksum_array != NULL) free(image->checksum_array); image->checksum_array = NULL; return 1; } /** * Attach user defined data to the image. Use this if your application needs * to store addition info together with the IsoImage. If the image already * has data attached, the old data will be freed. * * @param data * Pointer to application defined data that will be attached to the * image. You can pass NULL to remove any already attached data. * @param give_up * Function that will be called when the image does not need the data * any more. It receives the data pointer as an argumente, and eventually * causes data to be free. It can be NULL if you don't need it. */ int iso_image_attach_data(IsoImage *image, void *data, void (*give_up)(void*)) { if (image == NULL) { return ISO_NULL_POINTER; } if (image->user_data != NULL) { /* free previously attached data */ if (image->user_data_free != NULL) { image->user_data_free(image->user_data); } image->user_data = NULL; image->user_data_free = NULL; } if (data != NULL) { image->user_data = data; image->user_data_free = give_up; } return ISO_SUCCESS; } /** * The the data previously attached with iso_image_attach_data() */ void *iso_image_get_attached_data(IsoImage *image) { return image->user_data; } IsoDir *iso_image_get_root(const IsoImage *image) { return image->root; } void iso_image_set_volset_id(IsoImage *image, const char *volset_id) { free(image->volset_id); image->volset_id = strdup(volset_id); } const char *iso_image_get_volset_id(const IsoImage *image) { if (image->volset_id == NULL) return ""; return image->volset_id; } void iso_image_set_volume_id(IsoImage *image, const char *volume_id) { free(image->volume_id); image->volume_id = strdup(volume_id); } const char *iso_image_get_volume_id(const IsoImage *image) { if (image->volume_id == NULL) return ""; return image->volume_id; } void iso_image_set_publisher_id(IsoImage *image, const char *publisher_id) { free(image->publisher_id); image->publisher_id = strdup(publisher_id); } const char *iso_image_get_publisher_id(const IsoImage *image) { if (image->publisher_id == NULL) return ""; return image->publisher_id; } void iso_image_set_data_preparer_id(IsoImage *image, const char *data_preparer_id) { free(image->data_preparer_id); image->data_preparer_id = strdup(data_preparer_id); } const char *iso_image_get_data_preparer_id(const IsoImage *image) { if (image->data_preparer_id == NULL) return ""; return image->data_preparer_id; } void iso_image_set_system_id(IsoImage *image, const char *system_id) { free(image->system_id); image->system_id = strdup(system_id); } const char *iso_image_get_system_id(const IsoImage *image) { if (image->system_id == NULL) return ""; return image->system_id; } void iso_image_set_application_id(IsoImage *image, const char *application_id) { free(image->application_id); image->application_id = strdup(application_id); } const char *iso_image_get_application_id(const IsoImage *image) { if (image->application_id == NULL) return ""; return image->application_id; } void iso_image_set_copyright_file_id(IsoImage *image, const char *copyright_file_id) { free(image->copyright_file_id); image->copyright_file_id = strdup(copyright_file_id); } const char *iso_image_get_copyright_file_id(const IsoImage *image) { if (image->copyright_file_id == NULL) return ""; return image->copyright_file_id; } void iso_image_set_abstract_file_id(IsoImage *image, const char *abstract_file_id) { free(image->abstract_file_id); image->abstract_file_id = strdup(abstract_file_id); } const char *iso_image_get_abstract_file_id(const IsoImage *image) { if (image->abstract_file_id == NULL) return ""; return image->abstract_file_id; } void iso_image_set_biblio_file_id(IsoImage *image, const char *biblio_file_id) { free(image->biblio_file_id); image->biblio_file_id = strdup(biblio_file_id); } const char *iso_image_get_biblio_file_id(const IsoImage *image) { if (image->biblio_file_id == NULL) return ""; return image->biblio_file_id; } int iso_image_set_pvd_times(IsoImage *image, char *creation_time, char *modification_time, char *expiration_time, char *effective_time) { if (creation_time == NULL || modification_time == NULL || expiration_time == NULL || effective_time == NULL) return ISO_NULL_POINTER; image->creation_time = calloc(18, 1); /* Surely including a trailing 0 */ image->modification_time = calloc(18, 1); image->expiration_time = calloc(18, 1); image->effective_time = calloc(18, 1); if (image->creation_time == NULL || image->modification_time == NULL || image->expiration_time == NULL || image->effective_time == NULL) return ISO_OUT_OF_MEM; /* (If the string is too short, a non-zero timezone will not be stored) */ strncpy(image->creation_time, creation_time, 17); strncpy(image->modification_time, modification_time, 17); strncpy(image->expiration_time, expiration_time, 17); strncpy(image->effective_time, effective_time, 17); return ISO_SUCCESS; } int iso_image_get_pvd_times(IsoImage *image, char **creation_time, char **modification_time, char **expiration_time, char **effective_time) { if (image->creation_time == NULL || image->modification_time == NULL || image->expiration_time == NULL || image->effective_time == NULL) return ISO_NULL_POINTER; *creation_time = image->creation_time; *modification_time = image->modification_time; *expiration_time = image->expiration_time; *effective_time = image->effective_time; return ISO_SUCCESS; } void iso_image_set_app_use(IsoImage *image, const char *app_use_data, int count) { if (count < 0) count= 0; else if(count > 512) count= 512; if (count > 0) memcpy(image->application_use, app_use_data, count); if (count < 512) memset(image->application_use + count, 0, 512 - count); } int iso_image_get_msg_id(IsoImage *image) { return image->id; } int iso_image_get_system_area(IsoImage *img, char system_area_data[32768], int *options, int flag) { *options = img->system_area_options; if (img->system_area_data == NULL) return 0; memcpy(system_area_data, img->system_area_data, 32768); return 1; } static int dir_update_size(IsoImage *image, IsoDir *dir) { IsoNode *pos; int ret; #ifdef Libisofs_update_sizes_abortablE char *path= NULL; IsoStream *base_stream; int cancel_ret, ret; uint32_t lba; #endif pos = dir->children; while (pos) { if (pos->type == LIBISO_FILE) { ret = iso_stream_update_size(ISO_FILE(pos)->stream); } else if (pos->type == LIBISO_DIR) { /* recurse */ ret = dir_update_size(image, ISO_DIR(pos)); #ifdef Libisofs_update_sizes_abortablE if (ret == ISO_CANCELED) return ret; /* Message already issued by dir_update_size */ #endif } else { ret = 1; } #ifdef Libisofs_update_sizes_abortablE /* This would report error and abort according to severity threshold. But it is desirable to let the update_size crawler continue its work after e.g. a file has vanished from hard disk. So normally this macro case should be disabled. */ if (ret < 0) { cancel_ret = iso_msg_submit(image->id, ret, 0, NULL); path = iso_tree_get_node_path(pos); if (path != NULL) { iso_msg_submit(image->id, ret, 0, "ISO path : %s", path); free(path); } /* Report source path with streams which do not come from the loaded ISO filesystem */ if (pos->type == LIBISO_FILE && iso_node_get_old_image_lba(pos, &lba, 0) == 0) { base_stream = iso_stream_get_input_stream( ISO_FILE(pos)->stream, 1); if (base_stream == NULL) base_stream = ISO_FILE(pos)->stream; path = iso_stream_get_source_path(base_stream, 0); if (path != NULL) { iso_msg_submit(image->id, ret, 0, "Local path: %s", path); free(path); } } if (cancel_ret < 0) return cancel_ret; /* cancel due error threshold */ } #else if (ret < 0) ret = 1; /* ignore error */ #endif /* ! Libisofs_update_sizes_abortablE */ pos = pos->next; } return ISO_SUCCESS; } int iso_image_update_sizes(IsoImage *image) { if (image == NULL) { return ISO_NULL_POINTER; } return dir_update_size(image, image->root); } void iso_image_set_ignore_aclea(IsoImage *image, int what) { image->builder_ignore_acl = (what & 1); image->builder_ignore_ea = !!(what & 2); } static int img_register_ino(IsoImage *image, IsoNode *node, int flag) { int ret; ino_t ino; unsigned int fs_id; dev_t dev_id; ret = iso_node_get_id(node, &fs_id, &dev_id, &ino, 1); if (ret < 0) return ret; if (ret > 0 && ino >= image->used_inodes_start && ino <= image->used_inodes_start + (ISO_USED_INODE_RANGE - 1)) { /* without -1 : rollover hazard on 32 bit */ image->used_inodes[(ino - image->used_inodes_start) / 8] |= (1 << (ino % 8)); } return 1; } /* Collect the bitmap of used inode numbers in the range of _ImageFsData.used_inodes_start + ISO_USED_INODE_RANGE @param flag bit0= recursion is active */ int img_collect_inos(IsoImage *image, IsoDir *dir, int flag) { int ret, register_dir = 1; IsoDirIter *iter = NULL; IsoNode *node; IsoDir *subdir; if (dir == NULL) dir = image->root; if (image->used_inodes == NULL) { image->used_inodes = calloc(ISO_USED_INODE_RANGE / 8, 1); if (image->used_inodes == NULL) return ISO_OUT_OF_MEM; } else if(!(flag & 1)) { memset(image->used_inodes, 0, ISO_USED_INODE_RANGE / 8); } else { register_dir = 0; } if (register_dir) { node = (IsoNode *) dir; ret = img_register_ino(image, node, 0); if (ret < 0) return ret; } ret = iso_dir_get_children(dir, &iter); if (ret < 0) return ret; while (iso_dir_iter_next(iter, &node) == 1 ) { ret = img_register_ino(image, node, 0); if (ret < 0) goto ex; if (iso_node_get_type(node) == LIBISO_DIR) { subdir = (IsoDir *) node; ret = img_collect_inos(image, subdir, flag | 1); if (ret < 0) goto ex; } } ret = 1; ex:; if (iter != NULL) iso_dir_iter_free(iter); return ret; } /** * A global counter for Rock Ridge inode numbers in the ISO image filesystem. * * On image import it gets maxed by the eventual inode numbers from PX * entries. Up to the first 32 bit rollover it simply increments the counter. * After the first rollover it uses a look ahead bitmap which gets filled * by a full tree traversal. It covers the next inode numbers to come * (somewhere between 1 and ISO_USED_INODE_RANGE which is quite many) * and advances when being exhausted. * @param image The image where the number shall be used * @param flag bit0= reset count (Caution: image must get new inos then) * @return * Since 0 is used as default and considered self-unique, * the value 0 should only be returned in case of error. */ uint32_t img_give_ino_number(IsoImage *image, int flag) { int ret; uint64_t new_ino, ino_idx; static uint64_t limit = 0xffffffff; if (flag & 1) { image->inode_counter = 0; if (image->used_inodes != NULL) free(image->used_inodes); image->used_inodes = NULL; image->used_inodes_start = 0; } new_ino = ((uint64_t) image->inode_counter) + 1; if (image->used_inodes == NULL) { if (new_ino > 0 && new_ino <= limit) { image->inode_counter = (uint32_t) new_ino; return image->inode_counter; } } /* Look for free number in used territory */ while (1) { if (new_ino <= 0 || new_ino > limit || new_ino >= image->used_inodes_start + ISO_USED_INODE_RANGE ) { /* Collect a bitmap of used inode numbers ahead */ image->used_inodes_start += ISO_USED_INODE_RANGE; if (image->used_inodes_start > 0xffffffff || image->used_inodes_start <= 0) image->used_inodes_start = 0; ret = img_collect_inos(image, NULL, 0); if (ret < 0) goto return_result; /* >>> need error return value */ new_ino = image->used_inodes_start + !image->used_inodes_start; } ino_idx = (new_ino - image->used_inodes_start) / 8; if (!(image->used_inodes[ino_idx] & (1 << (new_ino % 8)))) { image->used_inodes[ino_idx] |= (1 << (new_ino % 8)); break; } new_ino++; } return_result:; image->inode_counter = new_ino; return image->inode_counter; } /* @param flag bit0= overwrite any ino, else only ino == 0 bit1= install inode with non-data, non-directory files bit2= install inode with directories */ static int img_update_ino(IsoImage *image, IsoNode *node, int flag) { int ret; ino_t ino; unsigned int fs_id; dev_t dev_id; ret = iso_node_get_id(node, &fs_id, &dev_id, &ino, 1); if (ret < 0) return ret; if (ret == 0) ino = 0; if (((flag & 1) || ino == 0) && (iso_node_get_type(node) == LIBISO_FILE || (flag & (2 | 4))) && ((flag & 4) || iso_node_get_type(node) != LIBISO_DIR)) { ret = iso_node_set_unique_id(node, image, 0); if (ret < 0) return ret; } return 1; } /* @param flag bit0= overwrite any ino, else only ino == 0 bit1= install inode with non-data, non-directory files bit2= install inode with directories bit3= with bit2: install inode on parameter dir */ int img_make_inos(IsoImage *image, IsoDir *dir, int flag) { int ret; IsoDirIter *iter = NULL; IsoNode *node; IsoDir *subdir; if (flag & 8) { node = (IsoNode *) dir; ret = img_update_ino(image, node, flag & 7); if (ret < 0) goto ex; } ret = iso_dir_get_children(dir, &iter); if (ret < 0) return ret; while (iso_dir_iter_next(iter, &node) == 1) { ret = img_update_ino(image, node, flag & 7); if (ret < 0) goto ex; if (iso_node_get_type(node) == LIBISO_DIR) { subdir = (IsoDir *) node; ret = img_make_inos(image, subdir, flag & ~8); if (ret < 0) goto ex; } } ret = 1; ex:; if (iter != NULL) iso_dir_iter_free(iter); return ret; } /* API */ int iso_image_get_session_md5(IsoImage *image, uint32_t *start_lba, uint32_t *end_lba, char md5[16], int flag) { if (image->checksum_array == NULL || image->checksum_idx_count < 1) return 0; *start_lba = image->checksum_start_lba; *end_lba = image->checksum_end_lba; memcpy(md5, image->checksum_array, 16); return ISO_SUCCESS; } int iso_image_set_checksums(IsoImage *image, char *checksum_array, uint32_t start_lba, uint32_t end_lba, uint32_t idx_count, int flag) { iso_image_free_checksums(image, 0); image->checksum_array = checksum_array; image->checksum_start_lba = start_lba; image->checksum_end_lba = end_lba; image->checksum_idx_count = idx_count; return 1; } int iso_image_generator_is_running(IsoImage *image) { return image->generator_is_running; } /* API */ int iso_image_add_mips_boot_file(IsoImage *image, char *path, int flag) { if (image->num_mips_boot_files >= 15) return ISO_BOOT_TOO_MANY_MIPS; image->mips_boot_file_paths[image->num_mips_boot_files] = strdup(path); if (image->mips_boot_file_paths[image->num_mips_boot_files] == NULL) return ISO_OUT_OF_MEM; image->num_mips_boot_files++; return ISO_SUCCESS; } /* API */ int iso_image_get_mips_boot_files(IsoImage *image, char *paths[15], int flag) { int i; for (i = 0; i < image->num_mips_boot_files; i++) paths[i] = image->mips_boot_file_paths[i]; for (; i < 15; i++) paths[i] = NULL; return image->num_mips_boot_files; } /* API */ int iso_image_give_up_mips_boot(IsoImage *image, int flag) { int i; for (i = 0; i < image->num_mips_boot_files; i++) if (image->mips_boot_file_paths[i] != NULL) { free(image->mips_boot_file_paths[i]); image->mips_boot_file_paths[i] = NULL; } image->num_mips_boot_files = 0; return ISO_SUCCESS; } static void unset_blessing(IsoImage *img, unsigned int idx) { if (img->hfsplus_blessed[idx] != NULL) iso_node_unref(img->hfsplus_blessed[idx]); img->hfsplus_blessed[idx] = NULL; } /* API */ int iso_image_hfsplus_bless(IsoImage *img, enum IsoHfsplusBlessings blessing, IsoNode *node, int flag) { unsigned int i, ok = 0; if (flag & 2) { /* Delete any blessing */ for (i = 0; i < ISO_HFSPLUS_BLESS_MAX; i++) { if (img->hfsplus_blessed[i] == node || node == NULL) { unset_blessing(img, i); ok = 1; } } return ok; } if (blessing == ISO_HFSPLUS_BLESS_MAX) return ISO_WRONG_ARG_VALUE; if (flag & 1) { /* Delete a particular blessing */ if (img->hfsplus_blessed[blessing] == node || node == NULL) { unset_blessing(img, (unsigned int) blessing); return 1; } return 0; } if (node == NULL) { unset_blessing(img, (unsigned int) blessing); return 1; } /* No two hats on one node */ for (i = 0; i < ISO_HFSPLUS_BLESS_MAX && node != NULL; i++) if (i != blessing && img->hfsplus_blessed[i] == node) return 0; /* Enforce correct file type */ if (blessing == ISO_HFSPLUS_BLESS_INTEL_BOOTFILE) { if (node->type != LIBISO_FILE) return 0; } else { if (node->type != LIBISO_DIR) return 0; } unset_blessing(img, (unsigned int) blessing); img->hfsplus_blessed[blessing] = node; if (node != NULL) iso_node_ref(node); return 1; } /* API */ int iso_image_hfsplus_get_blessed(IsoImage *img, IsoNode ***blessed_nodes, int *bless_max, int flag) { *blessed_nodes = img->hfsplus_blessed; *bless_max = ISO_HFSPLUS_BLESS_MAX; return 1; } /* API */ int iso_image_set_sparc_core(IsoImage *img, IsoFile *sparc_core, int flag) { if (img->sparc_core_node != NULL) iso_node_unref((IsoNode *) img->sparc_core_node); img->sparc_core_node = sparc_core; if (sparc_core != NULL) iso_node_ref((IsoNode *) sparc_core); return 1; } /* API */ int iso_image_get_sparc_core(IsoImage *img, IsoFile **sparc_core, int flag) { *sparc_core = img->sparc_core_node; return 1; } /* @param flag bit0= Let NULL parameters free the corresponding image properties. Else only the non-NULL parameters of this call have an effect. */ static int hppa_palo_set_path(IsoImage *img, char *path, char **target, char *what, int flag) { int ret, err; IsoNode *node; IsoFile *file; if (path == NULL && !(flag & 1)) return ISO_SUCCESS; if (iso_clone_mgtd_mem(path, target, 0) < 0) return ISO_OUT_OF_MEM; if (path == NULL) return ISO_SUCCESS; ret = iso_tree_path_to_node(img, path, &node); if (ret < 0) return ret; if (ret == 0) { iso_msg_submit(img->id, ISO_BOOT_FILE_MISSING, 0, "Cannot find in ISO image: %s file '%s'", what, path); return ISO_BOOT_FILE_MISSING; } if (iso_node_get_type(node) != LIBISO_FILE) { err = ISO_HPPA_PALO_NOTREG; if (strncmp(what, "DEC Alpha", 9) == 0) err = ISO_ALPHA_BOOT_NOTREG; iso_msg_submit(img->id, err, 0, "%s file is not a data file: '%s'", what, path); return err; } file = (IsoFile *) node; if (!(file->explicit_weight || file->from_old_session)) file->sort_weight = 2; return ISO_SUCCESS; } /* API */ /* @param flag Bitfield for control purposes bit0= Let NULL parameters free the corresponding image properties. Else only the non-NULL parameters of this call have an effect. */ int iso_image_set_hppa_palo(IsoImage *img, char *cmdline, char *bootloader, char *kernel_32, char *kernel_64, char *ramdisk, int flag) { int ret; static char *what = "HP-PA PALO"; if (cmdline != NULL || (flag & 1)) if (iso_clone_mgtd_mem(cmdline, &(img->hppa_cmdline), 0) < 0) return ISO_OUT_OF_MEM; ret = hppa_palo_set_path(img, bootloader, &(img->hppa_bootloader), what, flag & 1); if (ret < 0) return ret; ret = hppa_palo_set_path(img, kernel_32, &(img->hppa_kernel_32), what, flag & 1); if (ret < 0) return ret; ret = hppa_palo_set_path(img, kernel_64, &(img->hppa_kernel_64), what, flag & 1); if (ret < 0) return ret; ret = hppa_palo_set_path(img, ramdisk, &(img->hppa_ramdisk), what, flag & 1); if (ret < 0) return ret; return ISO_SUCCESS; } /* API */ int iso_image_get_hppa_palo(IsoImage *img, char **cmdline, char **bootloader, char **kernel_32, char **kernel_64, char **ramdisk) { *cmdline = img->hppa_cmdline; *bootloader = img->hppa_bootloader; *kernel_32 = img->hppa_kernel_32; *kernel_64 = img->hppa_kernel_64; *ramdisk = img->hppa_ramdisk; return ISO_SUCCESS; } /* API */ int iso_image_set_alpha_boot(IsoImage *img, char *boot_loader_path, int flag) { int ret; ret = hppa_palo_set_path(img, boot_loader_path, &(img->alpha_boot_image), "DEC Alpha Bootloader", 1); if (ret < 0) return ret; return ISO_SUCCESS; } /* API */ int iso_image_get_alpha_boot(IsoImage *img, char **boot_loader_path) { *boot_loader_path = img->alpha_boot_image; return ISO_SUCCESS; } /* API */ int iso_image_set_truncate_mode(IsoImage *img, int mode, int length) { if (mode < 0 || mode > 1) return ISO_WRONG_ARG_VALUE; if (length < 64 || length > LIBISOFS_NODE_NAME_MAX) return ISO_WRONG_ARG_VALUE; img->truncate_mode = mode; img->truncate_length = length; return ISO_SUCCESS; } /* API */ int iso_image_get_truncate_mode(IsoImage *img, int *mode, int *length) { *mode = img->truncate_mode; *length = img->truncate_length; return ISO_SUCCESS; } /* Warning: Not thread-safe */ int iso_image_truncate_name(IsoImage *image, const char *name, char **namept, int flag) { int ret; if (name == NULL) return ISO_NULL_POINTER; if ((int) strlen(name) <= image->truncate_length) { *namept = (char *) name; return ISO_SUCCESS; } *namept = image->truncate_buffer; if (name != image->truncate_buffer) strncpy(image->truncate_buffer, name, 4095); image->truncate_buffer[4095] = 0; ret = iso_truncate_rr_name(image->truncate_mode, image->truncate_length, image->truncate_buffer, 0); return ret; } libisofs-1.4.2/libisofs/image.h0000644000175700017510000003256512575532234013351 00000000000000/* * Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2009 - 2015 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ #ifndef LIBISO_IMAGE_H_ #define LIBISO_IMAGE_H_ #include "libisofs.h" #include "node.h" #include "fsource.h" #include "builder.h" /* Size of a inode recycling window. Each new window causes a tree traversal. Window memory consumption is ISO_USED_INODE_RANGE / 8. This must be a power of 2 smaller than 30 bit and larger than 8 bit. Here: 32 kB memory for 256k inodes. */ #define ISO_USED_INODE_RANGE (1 << 18) /* How many warnings to issue about name collisions during iso_image_import() */ #define ISO_IMPORT_COLL_WARN_MAX 10 /* * Image is a context for image manipulation. * Global objects such as the message_queues must belogn to that * context. Thus we will have, for example, a msg queue per image, * so images are completelly independent and can be managed together. * (Usefull, for example, in Multiple-Document-Interface GUI apps. * [The stuff we have in init belongs really to image!] */ struct Iso_Image { int refcount; IsoDir *root; char *volset_id; char *volume_id; /**< Volume identifier. */ char *publisher_id; /**< Volume publisher. */ char *data_preparer_id; /**< Volume data preparer. */ char *system_id; /**< Volume system identifier. */ char *application_id; /**< Volume application id */ char *copyright_file_id; char *abstract_file_id; char *biblio_file_id; char *creation_time; char *modification_time; char *expiration_time; char *effective_time; char application_use[512]; /* el-torito boot catalog */ struct el_torito_boot_catalog *bootcat; /* Eventually loaded system area data, or NULL */ char *system_area_data; /* Prescribed/detected options, see iso_write_opts_set_system_area() */ /* >>> Needs to be coordinated with .imported_sa_info->system_area_options */ int system_area_options; /* * Up to 15 boot files can be referred by a MIPS Big Endian Volume Header. The mips_boot_file_paths are ISO 9660 Rock Ridge paths. */ int num_mips_boot_files; char *mips_boot_file_paths[15]; /* ISO 9660 Rock Ridge Paths */ /* A data file of which the position and size shall be written after a SUN Disk Label. */ IsoFile *sparc_core_node; /* * Parameters for HP-PA PALO boot sector. cmdline is a string. The other * four are absolute paths to data files in the ISO image. */ char *hppa_cmdline; char *hppa_bootloader; char *hppa_kernel_32; char *hppa_kernel_64; char *hppa_ramdisk; /* Absolute DEC Alpha boot image path in the ISO image */ char *alpha_boot_image; /* image identifier, for message origin identifier */ int id; /** * Default filesystem to use when adding files to the image tree. */ IsoFilesystem *fs; /** * Block storage of imported ISO if demanded by IsoReadOpts. */ IsoDataSource *import_src; /* * Default builder to use when adding files to the image tree. */ IsoNodeBuilder *builder; /** * Whether to follow symlinks or just add them as symlinks */ unsigned int follow_symlinks : 1; /** * Whether to skip hidden files */ unsigned int ignore_hidden : 1; /** * Flags that determine what special files should be ignore. It is a * bitmask: * bit0: ignore FIFOs * bit1: ignore Sockets * bit2: ignore char devices * bit3: ignore block devices */ int ignore_special; /** * Whether to ignore ACL when inserting nodes into the image. * Not in effect with loading a complete ISO image but only with image * manipulation. */ unsigned int builder_ignore_acl : 1; /** * Whether to ignore EAs when inserting nodes into the image. * Not in effect with loading a complete ISO image but only with image * manipulation. ACL does not count as EA. */ unsigned int builder_ignore_ea : 1; /** * Files to exclude. Wildcard support is included. */ char** excludes; int nexcludes; /** * if the dir already contains a node with the same name, whether to * replace or not the old node with the new. */ enum iso_replace_mode replace; /* TODO enum iso_replace_mode (*confirm_replace)(IsoFileSource *src, IsoNode *node); */ /** * What to do in case of name longer than truncate_length: * 0= throw FAILURE * 1= truncate to truncate_length with MD5 of whole name at end */ int truncate_mode; int truncate_length; /** * This is a convenience buffer for name truncation during image * manipulation where libisofs is not thread-safe anyway. */ char truncate_buffer[4096]; /** * When this is not NULL, it is a pointer to a function that will * be called just before a file will be added. You can control where * the file will be in fact added or ignored. * * @return * 1 add, 0 ignore, < 0 cancel */ int (*report)(IsoImage *image, IsoFileSource *src); /** * User supplied data */ void *user_data; void (*user_data_free)(void *ptr); /** * Inode number management. inode_counter is taken over from * IsoImageFilesystem._ImageFsData after image import. * It is to be used with img_give_ino_number() * This is a Rock Ridge file serial number. Thus 32 bit. */ uint32_t inode_counter; /* * A bitmap of used inode numbers in an interval beginning at * used_inodes_start and holding ISO_USED_INODE_RANGE bits. * If a bit is set, then the corresponding inode number is occupied. * This interval is kept around inode_counter and eventually gets * advanced by ISO_USED_INODE_RANGE numbers in a tree traversal * done by img_collect_inos(). The value will stay in the 32 bit range, * although used_inodes_start is 64 bit to better handle rollovers. */ uint8_t *used_inodes; uint64_t used_inodes_start; /** * Array of MD5 checksums as announced by xattr "isofs.ca" of the * root node. Array element 0 contains an overall image checksum for the * block range checksum_start_lba,checksum_end_lba. Element size is * 16 bytes. IsoFile objects in the image may have xattr "isofs.cx" * which gives their index in checksum_array. */ uint32_t checksum_start_lba; uint32_t checksum_end_lba; uint32_t checksum_idx_count; char *checksum_array; /** * Whether a write run has been started by iso_image_create_burn_source() * and has not yet been finished. */ int generator_is_running; /* Pointers to directories or files which shall be get a HFS+ blessing. * libisofs/hfsplus.c et.al. will compare these pointers * with the ->node pointer of Ecma119Nodes. * See libisofs.h */ IsoNode *hfsplus_blessed[ISO_HFSPLUS_BLESS_MAX]; /* Counts the name collisions while iso_image_import() */ size_t collision_warnings; /* Contains the assessment of boot aspects of the loaded image */ struct iso_imported_sys_area *imported_sa_info; }; /* Apply truncation mode to name, using image->truncate_buffer to perform truncation if needed. Warning: Not thread-safe ! */ int iso_image_truncate_name(IsoImage *image, const char *name, char **namept, int flag); /* Collect the bitmap of used inode numbers in the range of _ImageFsData.used_inodes_start + ISO_USED_INODE_RANGE @param flag bit0= recursion is active */ int img_collect_inos(IsoImage *image, IsoDir *dir, int flag); /** * A global counter for inode numbers for the ISO image filesystem. * On image import it gets maxed by the eventual inode numbers from PX * entries. Up to the first 32 bit rollover it simply increments the counter. * After the first rollover it uses a look ahead bitmap which gets filled * by a full tree traversal. It covers the next inode numbers to come * (somewhere between 1 and ISO_USED_INODE_RANGE which is quite many) * and advances when being exhausted. * @param image The image where the number shall be used * @param flag bit0= reset count (Caution: image must get new inos then) * @return * Since 0 is used as default and considered self-unique, * the value 0 should only be returned in case of error. */ uint32_t img_give_ino_number(IsoImage *image, int flag); /* @param flag bit0= overwrite any ino, else only ino == 0 bit1= install inode with non-data, non-directory files bit2= install inode with directories bit3= with bit2: install inode on parameter dir */ int img_make_inos(IsoImage *image, IsoDir *dir, int flag); /* Free the checksum array of an image and reset its layout parameters */ int iso_image_free_checksums(IsoImage *image, int flag); /* Equip an ISO image with a new checksum array buffer (after isofs.ca and isofs.cx have already been adjusted). */ int iso_image_set_checksums(IsoImage *image, char *checksum_array, uint32_t start_lba, uint32_t end_lba, uint32_t idx_count, int flag); int iso_image_set_pvd_times(IsoImage *image, char *creation_time, char *modification_time, char *expiration_time, char *effective_time); /* Collects boot block information obtained from the system area of imported images */ struct iso_imported_sys_area { int refcount; /* Whether there was some System Area data at all */ int is_not_zero; /* Giving the error number if the assessment ended by an error */ int overall_return; /* Block address of loaded Primar Volume Descriptor */ uint32_t pvd_block; /* Size of the imported ISO image */ uint32_t image_size; /* see libisofs.h : iso_write_opts_set_system_area() */ int system_area_options; /* The perceived MBR partitions */ struct iso_mbr_partition_request **mbr_req; int mbr_req_count; /* see ecma119.h : struct ecma119_image , struct iso_write_opts */ /* Effective partition table parameter: 1 to 63, 0= disabled/default */ int partition_secs_per_head; /* 1 to 255, 0= disabled/default */ int partition_heads_per_cyl; /* see ecma119.h : struct iso_write_opts */ uint32_t partition_offset; /* 2048-byte start LBA and block count of PreP partition */ uint32_t prep_part_start; uint32_t prep_part_size; /* see ecma119.h : struct ecma119_image */ struct iso_apm_partition_request **apm_req; int apm_req_count; int apm_req_flags; /* Number of found "GapNN", "ISO9660_data" partitions in APM */ int apm_gap_count; /* see ecma119.h : struct iso_write_opts */ int apm_block_size; /* >>> see ecma119.h : struct iso_write_opts */ int hfsp_block_size; /* see ecma119.h : struct ecma119_image */ struct iso_gpt_partition_request **gpt_req; int gpt_req_count; int gpt_req_flags; /* see ecma119.h : struct ecma119_image */ uint8_t gpt_disk_guid[16]; /* Start of GPT entries in System Area, block size 512 */ uint64_t gpt_part_start; uint32_t gpt_max_entries; uint64_t gpt_first_lba; uint64_t gpt_last_lba; uint64_t gpt_backup_lba; char *gpt_backup_comments; uint32_t gpt_head_crc_found; uint32_t gpt_head_crc_should; uint32_t gpt_array_crc_found; uint32_t gpt_array_crc_should; /* see image.h : struct Iso_Image */ int num_mips_boot_files; char **mips_boot_file_paths; /* ISO 9660 Rock Ridge Paths */ struct iso_mips_voldir_entry **mips_vd_entries; /* see ecma119.h : struct ecma119_image */ /* Memorized ELF parameters from MIPS Little Endian boot file */ uint32_t mipsel_e_entry; uint32_t mipsel_p_offset; uint32_t mipsel_p_vaddr; uint32_t mipsel_p_filesz; uint32_t mipsel_seg_start; char *mipsel_boot_file_path; /* see image.h : struct Iso_Image */ char *sparc_disc_label; int sparc_secs_per_head; int sparc_heads_per_cyl; struct iso_sun_disk_label_entry *sparc_entries; int sparc_entry_count; /* grub2-sparc-core : a node in the ISO image published at bytes 0x228 to 0x233 */ uint64_t sparc_grub2_core_adr; uint32_t sparc_grub2_core_size; IsoFile *sparc_core_node; /* see image.h : struct Iso_Image */ int hppa_hdrversion; char *hppa_cmdline; uint32_t hppa_kern32_adr; uint32_t hppa_kern32_len; uint32_t hppa_kern64_adr; uint32_t hppa_kern64_len; uint32_t hppa_ramdisk_adr; uint32_t hppa_ramdisk_len; uint32_t hppa_bootloader_adr; uint32_t hppa_bootloader_len; uint32_t hppa_ipl_entry; char *hppa_kernel_32; char *hppa_kernel_64; char *hppa_ramdisk; char *hppa_bootloader; uint64_t alpha_boot_image_size; uint64_t alpha_boot_image_adr; char *alpha_boot_image; /* Some block addresses of active and first session: PVD, L Pathtable, Opt L, M Pathtable, Opt M, root directory */ uint32_t meta_struct_blocks[12]; int num_meta_struct_blocks; }; int iso_imported_sa_new(struct iso_imported_sys_area **sa_info, int flag); int iso_imported_sa_unref(struct iso_imported_sys_area **sa_info, int flag); #endif /*LIBISO_IMAGE_H_*/ libisofs-1.4.2/libisofs/aaip_0_2.h0000644000175700017510000006052112607500475013630 00000000000000 /* Arbitrary Attribute Interchange Protocol , AAIP versions 0.2 and 1.0. Implementation for encoding and decoding xattr and ACL. See http://libburnia-project.org/wiki/AAIP or doc/susp_aaip_2_0.txt test/aaip_0_2.h - Public declarations Copyright (c) 2009 Thomas Schmitt, libburnia project, GPLv2+ */ #ifndef Aaip_h_is_includeD #define Aaip_h_is_includeD yes /* --------------------------------- Encoder ---------------------------- */ /* Convert an array of Arbitrary Attributes into a series of AAIP fields. @param num_attrs Number of attributes @param names Array of pointers to 0 terminated name strings @param value_lengths Array of byte lengths for each value @param values Array of pointers to the value bytes @param result_len Number of bytes in the resulting SUSP field string @param result *result will point to the start of the result string. This is malloc() memory which needs to be freed when no longer needed @param flag Bitfield for control purposes bit0= set CONTINUE bit of last AAIP field to 1 @return >= 0 is the number of SUSP fields generated, < 0 means error */ ssize_t aaip_encode(size_t num_attrs, char **names, size_t *value_lengths, char **values, size_t *result_len, unsigned char **result, int flag); /* ------ ACL representation ------ */ /* Convert an ACL from long text form into the value of an Arbitrary Attribute. According to AAIP this value is to be stored together with an empty name. @param acl_text The ACL in long text form @param st_mode The stat(2) permission bits to be used with flag bit3 @param result_len Number of bytes in the resulting value @param result *result will point to the start of the result string. This is malloc() memory which needs to be freed when no longer needed @param flag Bitfield for control purposes bit0= count only bit1= use numeric qualifiers rather than names bit2= this is a default ACL, prepend SWITCH_MARK bit3= check for completeness of list and eventually fill up with entries deduced from st_mode @return >0 means ok <=0 means error -1= out of memory -2= program error with prediction of result size -3= error with conversion of name to uid or gid ISO_AAIP_ACL_MULT_OBJ= multiple entries of user::, group::, other:: */ int aaip_encode_acl(char *acl_text, mode_t st_mode, size_t *result_len, unsigned char **result, int flag); /* Convert an "access" and "default" ACL from long text form into the value of an Arbitrary Attribute. According to AAIP this value is to be stored together with an empty name. @param a_acl_text The "access" ACL in long text form. Submit NULL if there is no such ACL to be encoded. @param d_acl_text The "default" ACL in long text form. Submit NULL if there is no such ACL to be encoded. @param st_mode The stat(2) permission bits to be used with flag bit3 @param result_len Number of bytes in the resulting value @param result *result will point to the start of the result string. This is malloc() memory which needs to be freed when no longer needed @param flag Bitfield for control purposes bit0= count only bit1= use numeric qualifiers rather than names bit3= check for completeness of list and eventually fill up with entries deduced from st_mode @return >0 means ok <=0 means error, see aaip_encode_acl */ int aaip_encode_both_acl(char *a_acl_text, char *d_acl_text, mode_t st_mode, size_t *result_len, unsigned char **result, int flag); /* Analyze occurence of ACL tag types in long text form. If not disabled by parameter flag remove the entries of type "user::" , "group::" , "other::" , or "other:" from an ACL in long text form if they match the bits in st_mode as described by man 2 stat and man 5 acl. @param acl_text The text to be analyzed and eventually shortened. @param st_mode The component of struct stat which tells permission bits and eventually shall take equivalent bits as read from the ACL. The caller should submit a pointer to the st_mode variable which holds permissions as indicated by stat(2) resp. ECMA-119 and RRIP data. @param flag bit0= do not remove entries, only determine return value bit1= like bit0 but return immediately if a non-st_mode ACL entry is found bit2= update *st_mode by acl_text ("user::" -> S_IRWXU, "mask::"|"group::" -> S_IRWXG, "other::" -> S_IRWXO) bit3= update acl_text by *st_mode (same mapping as bit 2 but with reversed transfer direction) bit4= map "group::" <-> S_IRWXG in any case. I.e. ignore "mask::". @return <0 failure >=0 tells in its bits which tag types were found. The first three tell which types deviate from the corresponding st_mode settings: bit0= "other::" overrides S_IRWXO bit1= "group::" overrides S_IRWXG (no "mask::" found) bit2= "user::" overrides S_IRWXU The second three tell which types comply with st_mode: bit3= "other::" matches S_IRWXO bit4= "group::" matches S_IRWXG (no "mask::" found) bit5= "user::" matches S_IRWXU Given the nature of ACLs nearly all combinations are possible although some would come from invalid ACLs. bit6= other ACL tag types are present. Particularly: bit7= "user:...:" is present bit8= "group:...:" is present bit9= "mask::" is present bit10= "group::" found and "mask::" exists */ int aaip_cleanout_st_mode(char *acl_text, mode_t *st_mode, int flag); /* Append entries of type "user::" , "group::" , "other::" representing the permission bits in st_mode if those tag types are not present in the ACL text. Append "mask::" if missing although "user:...:" or "group:...:" is present. Eventually set it to S_IRWXG bits of st_mode. @param acl_text The text to be made longer. It must offer 43 bytes more storage space than its length when it is submitted. @param st_mode The component of struct stat which shall provide the permission information. @param flag Unused yet. Submit 0. @return <0 failure */ int aaip_add_acl_st_mode(char *acl_text, mode_t st_mode, int flag); /* ------ OS interface ------ */ /* See also API iso_local_attr_support(). @param flag Bitfield for control purposes bit0= inquire availability of ACL bit1= inquire availability of xattr bit2 - bit7= Reserved for future types. It is permissibile to set them to 1 already now. bit8 and higher: reserved, submit 0 @return Bitfield corresponding to flag. If bits are set, th bit0= ACL adapter is enabled bit1= xattr adapter is enabled bit2 - bit7= Reserved for future types. bit8 and higher: reserved, do not interpret these */ int aaip_local_attr_support(int flag); /* Obtain the ACL of the given file in long text form. @param path Path to the file @param text Will hold the result. This is a managed object which finally has to be freed by a call to this function with bit15 of flag. @param flag Bitfield for control purposes bit0= obtain default ACL rather than access ACL bit4= set *text = NULL and return 2 if the ACL matches st_mode permissions. bit15= free text and return 1 @return 1 ok 2 only st_mode permissions exist and bit 4 is set 0 ACL support not enabled at compile time -1 failure of system ACL service (see errno) */ int aaip_get_acl_text(char *path, char **text, int flag); /* Obtain the Extended Attributes and/or the ACLs of the given file in a form that is ready for aaip_encode(). The returned data objects finally have to be freed by a call with flag bit 15. @param path Path to the file @param num_attrs Will return the number of name-value pairs @param names Will return an array of pointers to 0-terminated names @param value_lengths Will return an arry with the lenghts of values @param values Will return an array of pointers to 8-bit values @param flag Bitfield for control purposes bit0= obtain ACLs (access and eventually default) via system ACL API and encode bit1= use numeric ACL qualifiers rather than names bit2= do not obtain attributes other than ACLs bit3= do not ignore eventual non-user attributes. I.e. those with a name which does not begin by "user." bit4= do not return trivial ACL that matches st_mode bit15= free memory of names, value_lengths, values @return >0 ok <=0 error */ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names, size_t **value_lengths, char ***values, int flag); /* --------------------------------- Decoder ---------------------------- */ /* The AAIP decoder offers several levels of abstraction of which the lower two avoid the use of dynamic memory. It provides a stateful decoding context with a small buffer which delivers results to caller provided memory locations. The lowest level is the stream-like Component Level Interface. It allows to decode very many very long attributes. Next is the Pair Level Interface which delivers to fixly sized storage for name and value. It allows to decode very many attributes. The List Level Interface uses dynamic memory allocation to provide arrays of names, values and value lengths. It is intended for moderately sized attribute lists but may also be used as alternative to Pair Level. */ /* Operations on complete AAIP field strings which need no decoder context. These function expect to get submitted a complete chain of AAIP fields. */ /* Determine the size of the AAIP string by interpreting the SUSP structure. @param data An arbitrary number of bytes beginning with the complete chain of AAIP fields. Trailing trash is ignored. @param flag Unused yet. Submit 0. @return The number of bytes of the AAIP field chain. */ size_t aaip_count_bytes(unsigned char *data, int flag); /* The AAIP decoder context. */ struct aaip_state; /* Obtain the size in bytes of an aaip_state object. */ size_t aaip_sizeof_aaip_state(void); /* Initialize a AAIP decoder context. This has to be done before the first AAIP field of a node is processed. The caller has to provide the storage of the struct aaip_state. @param aaip The AAIP decoder context to be initialized @param flag Bitfield for control purposes submit 0 @return <=0 error , >0 ok */ int aaip_init_aaip_state(struct aaip_state *aaip, int flag); /* ------------------------- Component Level Interface ------------------- */ /* Provides support for unlimited component size but demands the caller to have a growing storage facility resp. to do own oversize handling. This interface expects moderatly sized input pieces and will hand out moderately sized result pieces. The number of transactions is virtually unlimited. */ /* Submit small data chunk for decoding. The return value will tell whether data are pending for being fetched. @param aaip The AAIP decoder context @param data Not more than 2048 bytes input for the decoder @param num_data Number of bytes in data 0 inquires the buffer status avoiding replies <= 0 @param ready_bytes Number of decoded bytes ready for delivery @param flag Bitfield for control purposes @return -1= non-AAIP field detected *ready_bytes gives number of consumed bytes in data 0= cannot accept data because buffer full 1= no component record complete, submit more data 2= component record complete, may be delivered 3= component complete, may be delivered 4= no component available, no more data expected, done */ int aaip_submit_data(struct aaip_state *aaip, unsigned char *data, size_t num_data, size_t *ready_bytes, int flag); /* Fetch the available part of current component. The return value will tell whether it belongs to name or to value and whether that name or value is completed now. @param aaip The AAIP decoder context @param result Has to point to storage for the component data @param result_size Gives the amount of provided result storage @param num_result Will tell the number of fetched result bytes @param flag Bitfield for control purposes bit0= discard data rather than copying to result @return -2 = insufficient result_size -1 = no data ready for delivery 0 = result holds the final part of a name 1 = result holds an intermediate part of a name 2 = result holds the final part of a value 3 = result holds an intermediate part of a value */ int aaip_fetch_data(struct aaip_state *aaip, char *result, size_t result_size, size_t *num_result, int flag); /* Skip the current component and eventually the following value component. This has to be called if fetching of a component shall be aborted but the next component resp. pair shall be fetchable again. aaip_submit_data() will not indicate readiness for fetching until all bytes of the skipped components are submitted. Those bytes get discarded. @param aaip The AAIP decoder context @param flag Bitfield for control purposes bit0= do not skip value if current component is name @return <=0 error , 1= now in skip state, 2= not in skip state */ int aaip_skip_component(struct aaip_state *aaip, int flag); /* ------------------------- Pair Level Interface ------------------------ */ /* Provides support for names and values of limited size. The limits are given by the caller who has to provide the storage for name and value. This interface expects moderatly sized input pieces. The number of input transcations is virtually unlimited. The number of pair transactions after aaip_init() should be limited to 4 billion. */ /* Accept raw input data and collect a pair of name and value. The return value will indicate whether the pair is complete, whether more pairs are complete or whether more data are desired. No input data will be accepted as long as complete pairs are pending. The end of the attribute list will be indicated. @param aaip The AAIP decoder context @param data The raw data to decode @param num_data Number of data bytes provided @param consumed Returns the number of consumed data bytes @param name Buffer to build the name string @param name_size Maximum number of bytes in name @param name_fill Holds the current buffer fill of name @param value Buffer to build the value string @param value_size Maximum number of bytes in value @param value_fill Holds the current buffer fill of value @param flag Bitfield for control purposes - submit 0 for now @return <0 error 0 data not accepted, first fetch pending pairs with num_data == 0 1 name and value are not valid yet, submit more data 2 name and value are valid, submit more data 3 name and value are valid, pairs pending, fetch with num_data == 0 4 name and value are valid, no more data expected 5 name and value are not valid, no more data expected */ int aaip_decode_pair(struct aaip_state *aaip, unsigned char *data, size_t num_data, size_t *consumed, char *name, size_t name_size, size_t *name_fill, char *value, size_t value_size, size_t *value_fill, int flag); /* Inquire the number of pairs which were skipped because being oversized. @param aaip The AAIP decoder context @param flag Bitfield for control purposes - submit 0 for now @return The number of pairs skipped since aaip_init() */ unsigned int aaip_get_pairs_skipped(struct aaip_state *aaip, int flag); /* ------------------------- List Level Interface ------------------------ */ /* Provides support for names and values of limited size. The limits are given for total memory consumption and for number of attributes. Iterated decoding is supported as long as no single attribute exceeds the memory limit. */ /* Accept raw input data and collect arrays of name pointers, value lengths and value pointers. A handle object will emerge which finally has to be be freed by a call with bit 15. @param handle The decoding context. It will be created by this call with flag bit 0 or if *handle == NULL. This handle has to be the same as long as decoding goes on and finally has to be freed by a call with bit15. @param memory_limit Maximum number of bytes to allocate @param num_attr_limit Maximum number of name-value pairs to allocate @param data The raw data to decode @param num_data Number of data bytes provided @param consumed Returns the number of consumed data bytes @param flag Bitfield for control purposes bit0= this is the first call for a file object bit15= end decoding : Free handle and its intermediate list memory. @return <=0 error 1 not complete yet, submit more data 2 arrays are complete, call aaip_get_decoded_attrs() 3 limit exceeded, not complete yet, call with bit15 and give up 4 limit exceeded, call aaip_get_decoded_attrs() and try again */ int aaip_decode_attrs(struct aaip_state **handle, size_t memory_limit, size_t num_attr_limit, unsigned char *data, size_t num_data, size_t *consumed, int flag); /* Obtain the resulting attributes when aaip_decode_attrs() indicates to be done or to have the maximum possible amount of result ready. The returned data objects get detached from handle making it ready for the next round of decoding with possibly a different input source. The returned data objects finally have to be freed by a call with flag bit 15. @param handle The decoding context created by aaip_decode_attrs() @param num_attrs Will return the number of name-value pairs @param names Will return an array of pointers to 0-terminated names @param value_lengths Will return an arry with the lenghts of values @param values Will return an array of pointers to 8-bit values @param flag Bitfield for control purposes bit15= free memory of names, value_lengths, values */ int aaip_get_decoded_attrs(struct aaip_state **handle, size_t *num_attrs, char ***names, size_t **value_lengths, char ***values, int flag); /* ------ ACL representation ------ */ /* Convert an AAIP ACL attribute value into the long text form of ACL. @param data The raw data to decode @param num_data Number of data bytes provided @param consumed Returns the number of consumed data bytes @param acl_text Will be filled with ACL long text form @param acl_text_size Maximum number of bytes to be written to acl_text @param acl_text_fill Will return the number of bytes in acl_text @param flag Bitfield for control purposes bit0= count only, do not really produce bytes: acl_text will not be touched, acl_text_size will be ignored, *acl_text_fill will return the counted number bit1= expected is a default ACL (see return value 2) @return 1 success 2 success, begin of default/access ACL encountered, submit data + *consumed for access/default ACL -1 error with reading of qualifier -2 error with writing of ACL text line -3 version mismatch -4 unknown tag type encountered */ int aaip_decode_acl(unsigned char *data, size_t num_data, size_t *consumed, char *acl_text, size_t acl_text_size, size_t *acl_text_fill, int flag); /* ------ OS interface ------ */ /* Set the ACL of the given file to a given list in long text form. @param path Path to the file @param text The input text (0 terminated, ACL long text form) @param flag Bitfield for control purposes bit0= set default ACL rather than access ACL @return >0 ok 0 ACL support not enabled at compile time -1 failure of system ACL service (see errno) */ int aaip_set_acl_text(char *path, char *text, int flag); /* Bring the given attributes and/or ACLs into effect with the given file. @param path Path to the file @param num_attrs Number of attributes @param names Array of pointers to 0 terminated name strings @param value_lengths Array of byte lengths for each attribute payload @param values Array of pointers to the attribute payload bytes @param flag Bitfield for control purposes bit0= decode and set ACLs bit1= first clear all existing attributes of the file bit2= do not set attributes other than ACLs bit3= do not ignore eventual non-user attributes. I.e. those with a name which does not begin by "user." @return 1 success -1 error memory allocation -2 error with decoding of ACL -3 error with setting ACL -4 error with setting attribute -5 error with deleting attributes -6 support of xattr not enabled at compile time -7 support of ACL not enabled at compile time -8 unsupported xattr namespace ISO_AAIP_ACL_MULT_OBJ multiple entries of user::, group::, other:: */ int aaip_set_attr_list(char *path, size_t num_attrs, char **names, size_t *value_lengths, char **values, int flag); #endif /* ! Aaip_h_is_includeD */ libisofs-1.4.2/libisofs/rockridge_read.c0000644000175700017510000004116112605556657015227 00000000000000/* * Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2009 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ /* * This file contains functions related to the reading of SUSP, * Rock Ridge and AAIP extensions on an ECMA-119 image. */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif #include "libisofs.h" #include "ecma119.h" #include "util.h" #include "rockridge.h" #include "messages.h" #include #include #include struct susp_iterator { uint8_t* base; int pos; int size; IsoDataSource *src; int msgid; /* block and offset for next continuation area */ uint32_t ce_block; uint32_t ce_off; /** Length of the next continuation area, 0 if no more CA are specified */ uint32_t ce_len; uint8_t *buffer; /*< If there are continuation areas */ }; SuspIterator* susp_iter_new(IsoDataSource *src, struct ecma119_dir_record *record, uint8_t len_skp, int msgid) { int pad = (record->len_fi[0] + 1) % 2; struct susp_iterator *iter = malloc(sizeof(struct susp_iterator)); if (iter == NULL) { return NULL; } iter->base = record->file_id + record->len_fi[0] + pad; iter->pos = len_skp; /* 0 in most cases */ iter->size = record->len_dr[0] - record->len_fi[0] - 33 - pad; iter->src = src; iter->msgid = msgid; iter->ce_len = 0; iter->buffer = NULL; return iter; } int susp_iter_next(SuspIterator *iter, struct susp_sys_user_entry **sue) { struct susp_sys_user_entry *entry; entry = (struct susp_sys_user_entry*)(iter->base + iter->pos); if ( (iter->pos + 4 > iter->size) || (SUSP_SIG(entry, 'S', 'T'))) { /* * End of the System Use Area or Continuation Area. * Note that ST is not needed when the space left is less than 4. * (IEEE 1281, SUSP. section 4) */ if (iter->ce_len) { uint32_t block, nblocks; /* A CE has found, there is another continuation area */ nblocks = DIV_UP(iter->ce_off + iter->ce_len, BLOCK_SIZE); iter->buffer = realloc(iter->buffer, nblocks * BLOCK_SIZE); /* read all blocks needed to cache the full CE */ for (block = 0; block < nblocks; ++block) { int ret; ret = iter->src->read_block(iter->src, iter->ce_block + block, iter->buffer + block * BLOCK_SIZE); if (ret < 0) { return ret; } } iter->base = iter->buffer + iter->ce_off; iter->pos = 0; iter->size = iter->ce_len; iter->ce_len = 0; entry = (struct susp_sys_user_entry*)iter->base; } else { return 0; } } if (entry->len_sue[0] == 0) { /* a wrong image with this lead us to a infinity loop */ iso_msg_submit(iter->msgid, ISO_WRONG_RR, 0, "Damaged RR/SUSP information."); return ISO_WRONG_RR; } iter->pos += entry->len_sue[0]; if (SUSP_SIG(entry, 'C', 'E')) { /* Continuation entry */ if (iter->ce_len) { int ret; ret = iso_msg_submit(iter->msgid, ISO_UNSUPPORTED_SUSP, 0, "More than one CE System user entry has found in a single " "System Use field or continuation area. This breaks SUSP " "standard and it's not supported. Ignoring last CE. Maybe " "the image is damaged."); if (ret < 0) { return ret; } } else { iter->ce_block = iso_read_bb(entry->data.CE.block, 4, NULL); iter->ce_off = iso_read_bb(entry->data.CE.offset, 4, NULL); iter->ce_len = iso_read_bb(entry->data.CE.len, 4, NULL); } /* we don't want to return CE entry to the user */ return susp_iter_next(iter, sue); } else if (SUSP_SIG(entry, 'P', 'D')) { /* skip padding */ return susp_iter_next(iter, sue); } *sue = entry; return ISO_SUCCESS; } void susp_iter_free(SuspIterator *iter) { free(iter->buffer); free(iter); } /** * Fills a struct stat with the values of a Rock Ridge PX entry (RRIP, 4.1.1). * * @return * 1 on success, < 0 on error */ int read_rr_PX(struct susp_sys_user_entry *px, struct stat *st) { if (px == NULL || st == NULL) { return ISO_NULL_POINTER; } if (px->sig[0] != 'P' || px->sig[1] != 'X') { return ISO_WRONG_ARG_VALUE; } if (px->len_sue[0] != 44 && px->len_sue[0] != 36) { return ISO_WRONG_RR; } st->st_mode = iso_read_bb(px->data.PX.mode, 4, NULL); st->st_nlink = iso_read_bb(px->data.PX.links, 4, NULL); st->st_uid = iso_read_bb(px->data.PX.uid, 4, NULL); st->st_gid = iso_read_bb(px->data.PX.gid, 4, NULL); st->st_ino = 0; if (px->len_sue[0] == 44) { /* this corresponds to RRIP 1.12, so we have inode serial number */ st->st_ino = iso_read_bb(px->data.PX.serial, 4, NULL); /* Indicate that st_ino is valid */ return 2; } return 1; } /** * Fills a struct stat with the values of a Rock Ridge TF entry (RRIP, 4.1.6) * * @return * 1 on success, < 0 on error */ int read_rr_TF(struct susp_sys_user_entry *tf, struct stat *st) { time_t time; int s; int nts = 0; if (tf == NULL || st == NULL) { return ISO_NULL_POINTER; } if (tf->sig[0] != 'T' || tf->sig[1] != 'F') { return ISO_WRONG_ARG_VALUE; } if (tf->data.TF.flags[0] & (1 << 7)) { /* long form */ s = 17; } else { s = 7; } /* 1. Creation time */ if (tf->data.TF.flags[0] & (1 << 0)) { /* Linux accepts ctime by Creation time and by Attributes time. * If both are given, then Attribute time will win. */ if (tf->len_sue[0] < 5 + (nts+1) * s) { /* RR TF entry too short. */ return ISO_WRONG_RR; } if (s == 7) { time = iso_datetime_read_7(&tf->data.TF.t_stamps[nts*7]); } else { time = iso_datetime_read_17(&tf->data.TF.t_stamps[nts*17]); } st->st_ctime = time; ++nts; } /* 2. modify time */ if (tf->data.TF.flags[0] & (1 << 1)) { if (tf->len_sue[0] < 5 + (nts+1) * s) { /* RR TF entry too short. */ return ISO_WRONG_RR; } if (s == 7) { time = iso_datetime_read_7(&tf->data.TF.t_stamps[nts*7]); } else { time = iso_datetime_read_17(&tf->data.TF.t_stamps[nts*17]); } st->st_mtime = time; ++nts; } /* 3. access time */ if (tf->data.TF.flags[0] & (1 << 2)) { if (tf->len_sue[0] < 5 + (nts+1) * s) { /* RR TF entry too short. */ return ISO_WRONG_RR; } if (s == 7) { time = iso_datetime_read_7(&tf->data.TF.t_stamps[nts*7]); } else { time = iso_datetime_read_17(&tf->data.TF.t_stamps[nts*17]); } st->st_atime = time; ++nts; } /* 4. attributes time */ if (tf->data.TF.flags[0] & (1 << 3)) { if (tf->len_sue[0] < 5 + (nts+1) * s) { /* RR TF entry too short. */ return ISO_WRONG_RR; } if (s == 7) { time = iso_datetime_read_7(&tf->data.TF.t_stamps[nts*7]); } else { time = iso_datetime_read_17(&tf->data.TF.t_stamps[nts*17]); } st->st_ctime = time; ++nts; } /* we ignore backup, expire and effect times */ return ISO_SUCCESS; } /** * Read a RR NM entry (RRIP, 4.1.4), and appends the name stored there to * the given name. You can pass a pointer to NULL as name. * * @return * 1 on success, < 0 on error */ int read_rr_NM(struct susp_sys_user_entry *nm, char **name, int *cont) { if (nm == NULL || name == NULL) { return ISO_NULL_POINTER; } if (nm->sig[0] != 'N' || nm->sig[1] != 'M') { return ISO_WRONG_ARG_VALUE; } if (nm->len_sue[0] == 5) { if (nm->data.NM.flags[0] & 0x2) { /* it is a "." entry */ if (*name == NULL) { return ISO_SUCCESS; } else { /* we can't have a previous not-NULL name */ return ISO_WRONG_RR; } } } if (nm->len_sue[0] <= 5) { /* ".." entry is an error, as we will never call it */ return ISO_WRONG_RR; } /* concatenate the results */ if (*cont) { *name = realloc(*name, strlen(*name) + nm->len_sue[0] - 5 + 1); strncat(*name, (char*)nm->data.NM.name, nm->len_sue[0] - 5); } else { *name = iso_util_strcopy((char*)nm->data.NM.name, nm->len_sue[0] - 5); } if (*name == NULL) { return ISO_OUT_OF_MEM; } /* and set cond according to the value of CONTINUE flag */ *cont = nm->data.NM.flags[0] & 0x01; return ISO_SUCCESS; } /** * Read a SL RR entry (RRIP, 4.1.3), checking if the destination continues. * * @param cont * 0 not continue, 1 continue, 2 continue component * @return * 1 on success, < 0 on error */ int read_rr_SL(struct susp_sys_user_entry *sl, char **dest, int *cont) { int pos; if (sl == NULL || dest == NULL) { return ISO_NULL_POINTER; } if (sl->sig[0] != 'S' || sl->sig[1] != 'L') { return ISO_WRONG_ARG_VALUE; } for (pos = 0; pos + 5 < sl->len_sue[0]; pos += 2 + sl->data.SL.comps[pos + 1]) { char *comp; uint8_t len; uint8_t flags = sl->data.SL.comps[pos]; if (flags & 0x2) { /* current directory */ len = 1; comp = "."; } else if (flags & 0x4) { /* parent directory */ len = 2; comp = ".."; } else if (flags & 0x8) { /* root directory */ len = 1; comp = "/"; } else if (flags & ~0x01) { /* unsupported flag component */ return ISO_UNSUPPORTED_RR; } else { len = sl->data.SL.comps[pos + 1]; comp = (char*)&sl->data.SL.comps[pos + 2]; } if (*cont == 1) { /* new component */ size_t size = strlen(*dest); *dest = realloc(*dest, strlen(*dest) + len + 2); if (*dest == NULL) { return ISO_OUT_OF_MEM; } /* it is a new compoenent, add the '/' */ if ((*dest)[size-1] != '/') { (*dest)[size] = '/'; (*dest)[size+1] = '\0'; } strncat(*dest, comp, len); } else if (*cont == 2) { /* the component continues */ *dest = realloc(*dest, strlen(*dest) + len + 1); if (*dest == NULL) { return ISO_OUT_OF_MEM; } /* we don't have to add the '/' */ strncat(*dest, comp, len); } else { *dest = iso_util_strcopy(comp, len); } if (*dest == NULL) { return ISO_OUT_OF_MEM; } /* do the component continue or not? */ *cont = (flags & 0x01) ? 2 : 1; } if (*cont == 2) { /* TODO check that SL flag is set to continute too ?*/ } else { *cont = sl->data.SL.flags[0] & 0x1 ? 1 : 0; } return ISO_SUCCESS; } /** * Fills a struct stat with the values of a Rock Ridge PN entry (RRIP, 4.1.2). * * @return * 1 on success, < 0 on error */ int read_rr_PN(struct susp_sys_user_entry *pn, struct stat *st) { int high_shift= 0; if (pn == NULL || st == NULL) { return ISO_NULL_POINTER; } if (pn->sig[0] != 'P' || pn->sig[1] != 'N') { return ISO_WRONG_ARG_VALUE; } if (pn->len_sue[0] != 20) { return ISO_WRONG_RR; } /* (dev_t << 32) causes compiler warnings on FreeBSD because sizeof(dev_t) is 4. */ st->st_rdev = (dev_t)iso_read_bb(pn->data.PN.low, 4, NULL); if (sizeof(st->st_rdev) > 4) { high_shift = 32; st->st_rdev |= (dev_t)((dev_t)iso_read_bb(pn->data.PN.high, 4, NULL) << high_shift); } /* was originally: st->st_rdev = (dev_t)((dev_t)iso_read_bb(pn->data.PN.high, 4, NULL) << 32) | (dev_t)iso_read_bb(pn->data.PN.low, 4, NULL); */ return ISO_SUCCESS; } /* AA is the obsolete field signature of AAIP versions < 2.0 */ int read_aaip_AA(struct susp_sys_user_entry *sue, unsigned char **aa_string, size_t *aa_size, size_t *aa_len, size_t *prev_field, int *is_done, int flag) { unsigned char *aapt; if (*is_done) { /* To coexist with Apple ISO : Gracefully react on eventually trailing Apple AA */ if (sue->version[0] != 1 || sue->len_sue[0] == 7) return ISO_SUCCESS; return ISO_WRONG_RR; } /* Eventually create or grow storage */ if (*aa_size == 0 || *aa_string == NULL) { /* Gracefully react on eventually leading Apple AA */ if (sue->version[0] != 1 || sue->len_sue[0] < 9) { return ISO_SUCCESS; } *aa_size = *aa_len + sue->len_sue[0]; *aa_string = calloc(*aa_size, 1); *aa_len = 0; } else if (*aa_len + sue->len_sue[0] > *aa_size) { if (sue->version[0] != 1) { /* Apple ISO within the AAIP field group is not AAIP compliant */ return ISO_WRONG_RR; } *aa_size += *aa_len + sue->len_sue[0]; *aa_string = realloc(*aa_string, *aa_size); } if (*aa_string == NULL) return ISO_OUT_OF_MEM; if (*aa_len > 0) { /* Mark prev_field as being continued */ (*aa_string)[*prev_field + 4] = 1; } *prev_field = *aa_len; /* Compose new SUSP header with signature aa[], cont == 0 */ aapt = *aa_string + *aa_len; aapt[0] = 'A'; aapt[1] = 'L'; aapt[2] = sue->len_sue[0]; aapt[3] = 1; aapt[4] = 0; /* Append sue payload */ memcpy(aapt + 5, sue->data.AL.comps, sue->len_sue[0] - 5); *is_done = !(sue->data.AL.flags[0] & 1); *aa_len += sue->len_sue[0]; return ISO_SUCCESS; } /* AL is the field signature of AAIP versions >= 2.0 */ int read_aaip_AL(struct susp_sys_user_entry *sue, unsigned char **aa_string, size_t *aa_size, size_t *aa_len, size_t *prev_field, int *is_done, int flag) { unsigned char *aapt; if (*is_done) return ISO_WRONG_RR; if (sue->version[0] != 1) return ISO_WRONG_RR; /* Eventually create or grow storage */ if (*aa_size == 0 || *aa_string == NULL) { *aa_size = *aa_len + sue->len_sue[0]; *aa_string = calloc(*aa_size, 1); *aa_len = 0; } else if (*aa_len + sue->len_sue[0] > *aa_size) { *aa_size += *aa_len + sue->len_sue[0]; *aa_string = realloc(*aa_string, *aa_size); } if (*aa_string == NULL) return ISO_OUT_OF_MEM; if (*aa_len > 0) { /* Mark prev_field as being continued */ (*aa_string)[*prev_field + 4] = 1; } *prev_field = *aa_len; /* Compose new SUSP header with signature aa[], cont == 0 */ aapt = *aa_string + *aa_len; aapt[0] = 'A'; aapt[1] = 'L'; aapt[2] = sue->len_sue[0]; aapt[3] = 1; aapt[4] = 0; /* Append sue payload */ memcpy(aapt + 5, sue->data.AL.comps, sue->len_sue[0] - 5); *is_done = !(sue->data.AL.flags[0] & 1); *aa_len += sue->len_sue[0]; return ISO_SUCCESS; } /** * Reads the zisofs parameters from a ZF field (see doc/zisofs_format.txt). * * @return * 1 on success, < 0 on error */ int read_zisofs_ZF(struct susp_sys_user_entry *zf, uint8_t algorithm[2], uint8_t *header_size_div4, uint8_t *block_size_log2, uint32_t *uncompressed_size, int flag) { if (zf == NULL) { return ISO_NULL_POINTER; } if (zf->sig[0] != 'Z' || zf->sig[1] != 'F') { return ISO_WRONG_ARG_VALUE; } if (zf->len_sue[0] != 16) { return ISO_WRONG_RR; } algorithm[0] = zf->data.ZF.parameters[0]; algorithm[1] = zf->data.ZF.parameters[1]; *header_size_div4 = zf->data.ZF.parameters[2]; *block_size_log2 = zf->data.ZF.parameters[3]; *uncompressed_size = iso_read_bb(&(zf->data.ZF.parameters[4]), 4, NULL); return ISO_SUCCESS; } libisofs-1.4.2/libisofs/filesrc.c0000644000175700017510000005255312551162352013702 00000000000000/* * Copyright (c) 2007 Vreixo Formoso * 2010 - 2012 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif #include "libisofs.h" #include "filesrc.h" #include "node.h" #include "util.h" #include "writer.h" #include "messages.h" #include "image.h" #include "stream.h" #include "md5.h" #include #include #include /* <<< */ #include #ifdef Xorriso_standalonE #ifdef Xorriso_with_libjtE #include "../libjte/libjte.h" #endif #else #ifdef Libisofs_with_libjtE #include #endif #endif /* ! Xorriso_standalonE */ #ifndef PATH_MAX #define PATH_MAX Libisofs_default_path_maX #endif int iso_file_src_cmp(const void *n1, const void *n2) { int ret; const IsoFileSrc *f1, *f2; if (n1 == n2) { return 0; /* Normally just a shortcut. But important if Libisofs_file_src_cmp_non_zerO */ } f1 = (const IsoFileSrc *)n1; f2 = (const IsoFileSrc *)n2; ret = iso_stream_cmp_ino(f1->stream, f2->stream, 0); return ret; } int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src) { int ret, i; IsoFileSrc *fsrc; unsigned int fs_id; dev_t dev_id; ino_t ino_id; int cret, no_md5= 0; void *xipt = NULL; if (img == NULL || file == NULL || src == NULL) { return ISO_NULL_POINTER; } iso_stream_get_id(file->stream, &fs_id, &dev_id, &ino_id); fsrc = calloc(1, sizeof(IsoFileSrc)); if (fsrc == NULL) { return ISO_OUT_OF_MEM; } /* fill key and other atts */ fsrc->no_write = (file->from_old_session && img->opts->appendable); if (file->from_old_session && img->opts->appendable) { /* * On multisession discs we keep file sections from old image. */ int ret = iso_file_get_old_image_sections(file, &(fsrc->nsections), &(fsrc->sections), 0); if (ret < 0) { free(fsrc); return ISO_OUT_OF_MEM; } } else { /* * For new files, or for image copy, we compute our own file sections. * Block and size of each section will be filled later. */ off_t section_size = iso_stream_get_size(file->stream); if (section_size > (off_t) MAX_ISO_FILE_SECTION_SIZE) { fsrc->nsections = DIV_UP(section_size - (off_t) MAX_ISO_FILE_SECTION_SIZE, (off_t)ISO_EXTENT_SIZE) + 1; } else { fsrc->nsections = 1; } fsrc->sections = calloc(fsrc->nsections, sizeof(struct iso_file_section)); if (fsrc->sections == NULL) { free(fsrc); return ISO_OUT_OF_MEM; } for (i = 0; i < fsrc->nsections; i++) fsrc->sections[i].block = 0; } fsrc->sort_weight = file->sort_weight; fsrc->stream = file->stream; /* insert the filesrc in the tree */ ret = iso_rbtree_insert(img->files, fsrc, (void**)src); if (ret <= 0) { if (ret == 0 && (*src)->checksum_index > 0 && !img->opts->will_cancel) { /* Duplicate file source was mapped to previously registered source */ cret = iso_file_set_isofscx(file, (*src)->checksum_index, 0); if (cret < 0) ret = cret; } free(fsrc->sections); free(fsrc); return ret; } iso_stream_ref(fsrc->stream); if ((img->opts->md5_file_checksums & 1) && file->from_old_session && img->opts->appendable) { ret = iso_node_get_xinfo((IsoNode *) file, checksum_md5_xinfo_func, &xipt); if (ret <= 0) ret = iso_node_get_xinfo((IsoNode *) file, checksum_cx_xinfo_func, &xipt); if (ret <= 0) /* Omit MD5 indexing with old image nodes which have no MD5 */ no_md5 = 1; } if ((img->opts->md5_file_checksums & 1) && !(no_md5 || img->opts->will_cancel)) { img->checksum_idx_counter++; if (img->checksum_idx_counter < 0x7fffffff) { fsrc->checksum_index = img->checksum_idx_counter; } else { fsrc->checksum_index= 0; img->checksum_idx_counter= 0x7ffffffe; /* keep from rolling over */ } cret = iso_file_set_isofscx(file, (*src)->checksum_index, 0); if (cret < 0) return cret; } return ISO_SUCCESS; } /** * Add a given IsoFileSrc to the given image target. * * The IsoFileSrc will be cached in a tree to prevent the same file for * being written several times to image. If you call again this function * with a node that refers to the same source file, the previously * created one will be returned. * * @param img * The image where this file is to be written * @param new * The IsoFileSrc to add * @param src * Will be filled with a pointer to the IsoFileSrc really present in * the tree. It could be different than new if the same file already * exists in the tree. * @return * 1 on success, 0 if file already exists on tree, < 0 error */ int iso_file_src_add(Ecma119Image *img, IsoFileSrc *new, IsoFileSrc **src) { int ret; if (img == NULL || new == NULL || src == NULL) { return ISO_NULL_POINTER; } /* insert the filesrc in the tree */ ret = iso_rbtree_insert(img->files, new, (void**)src); return ret; } void iso_file_src_free(void *node) { iso_stream_unref(((IsoFileSrc*)node)->stream); free(((IsoFileSrc*)node)->sections); free(node); } off_t iso_file_src_get_size(IsoFileSrc *file) { return iso_stream_get_size(file->stream); } static int cmp_by_weight(const void *f1, const void *f2) { IsoFileSrc *f = *((IsoFileSrc**)f1); IsoFileSrc *g = *((IsoFileSrc**)f2); /* higher weighted first */ return g->sort_weight - f->sort_weight; } static int shall_be_written(void *arg) { IsoFileSrc *f = (IsoFileSrc *)arg; return f->no_write ? 0 : 1; } static int shall_be_written_if_not_taken(void *arg) { IsoFileSrc *f = (IsoFileSrc *)arg; return f->no_write || f->taken ? 0 : 1; } int filesrc_writer_pre_compute(IsoImageWriter *writer) { size_t i, size, is_external; Ecma119Image *t; IsoFileSrc **filelist; int (*inc_item)(void *); size_t omitted_count; IsoFileSrc **iso_ecma119_to_filesrc_array(Ecma119Image *t, int (*include_item)(void *), size_t *size); if (writer == NULL) { return ISO_ASSERT_FAILURE; } t = writer->target; t->filesrc_blocks = 0; /* Normally reserve a single zeroed block for all files which have no block address: symbolic links, device files, empty data files. */ if (! t->opts->old_empty) t->filesrc_blocks++; /* on appendable images, ms files shouldn't be included */ if (t->opts->appendable) { inc_item = shall_be_written; } else { inc_item = NULL; } /* store the filesrcs in a array */ filelist = (IsoFileSrc**) iso_ecma119_to_filesrc_array(t, inc_item, &size); omitted_count = iso_rbtree_count_array(t->files, (size_t) 0, shall_be_written_if_not_taken); if (omitted_count > 0) { iso_msg_submit(t->image->id, ISO_NOT_REPRODUCIBLE, 0, "Cannot arrange content of data files in surely reproducible way"); LIBISO_FREE_MEM(filelist); filelist = (IsoFileSrc**)iso_rbtree_to_array( t->files, inc_item, &size); } if (filelist == NULL) { return ISO_OUT_OF_MEM; } /* sort files by weight, if needed */ if (t->opts->sort_files) { qsort(filelist, size, sizeof(void*), cmp_by_weight); } /* fill block value */ for (i = 0; i < size; ++i) { int extent = 0; IsoFileSrc *file = filelist[i]; off_t section_size; /* 0xfffffffe in emerging image means that this is an external partition. Only assess extent sizes but do not count as part of filesrc_writer output. */ is_external = (file->no_write == 0 && file->sections[0].block == 0xfffffffe); section_size = iso_stream_get_size(file->stream); for (extent = 0; extent < file->nsections - 1; ++extent) { file->sections[extent].block = t->filesrc_blocks + extent * (ISO_EXTENT_SIZE / BLOCK_SIZE); file->sections[extent].size = ISO_EXTENT_SIZE; section_size -= (off_t) ISO_EXTENT_SIZE; } /* * final section */ if (section_size <= 0) { /* Will become t->empty_file_block in filesrc_writer_compute_data_blocks() Special use of 0xffffffe0 to 0xffffffff is covered by mspad_writer which enforces a minimum start of filesrc at block 0x00000020. */ file->sections[extent].block = 0xffffffff; } else { file->sections[extent].block = t->filesrc_blocks + extent * (ISO_EXTENT_SIZE / BLOCK_SIZE); } file->sections[extent].size = (uint32_t)section_size; /* 0xfffffffe in emerging image means that this is an external partition. Others will take care of the content data. */ if (is_external) { file->sections[0].block = 0xfffffffe; file->no_write = 1; /* Ban for filesrc_writer */ continue; } t->filesrc_blocks += DIV_UP(iso_file_src_get_size(file), BLOCK_SIZE); } /* the list is only needed by this writer, store locally */ writer->data = filelist; return ISO_SUCCESS; } static int filesrc_writer_compute_data_blocks(IsoImageWriter *writer) { Ecma119Image *t; int extent = 0; size_t i; IsoFileSrc *file; IsoFileSrc **filelist; if (writer == NULL) { return ISO_ASSERT_FAILURE; } t = writer->target; filelist = (IsoFileSrc **) writer->data; /* >>> HFS: need to align to allocation block size */; /* >>> HFS: ??? how to handle multi-extent files ? */; t->filesrc_start = t->curblock; /* Give all extent addresses their final absolute value */ i = 0; while ((file = filelist[i++]) != NULL) { /* Skip external partitions */ if (file->no_write) continue; for (extent = 0; extent < file->nsections; ++extent) { if (file->sections[extent].block == 0xffffffff) file->sections[extent].block = t->empty_file_block; else file->sections[extent].block += t->curblock; } } t->curblock += t->filesrc_blocks; return ISO_SUCCESS; } static int filesrc_writer_write_vol_desc(IsoImageWriter *writer) { /* nothing needed */ return ISO_SUCCESS; } /* open a file, i.e., its Stream */ static inline int filesrc_open(IsoFileSrc *file) { return iso_stream_open(file->stream); } static inline int filesrc_close(IsoFileSrc *file) { return iso_stream_close(file->stream); } /** * @return * 1 ok, 0 EOF, < 0 error */ static int filesrc_read(IsoFileSrc *file, char *buf, size_t count) { size_t got; return iso_stream_read_buffer(file->stream, buf, count, &got); } /* @return 1=ok, md5 is valid, 0= not ok, go on, <0 fatal error, abort */ static int filesrc_make_md5(Ecma119Image *t, IsoFileSrc *file, char md5[16], int flag) { return iso_stream_make_md5(file->stream, md5, 0); } /* name must be NULL or offer at least PATH_MAX characters. buffer must be NULL or offer at least BLOCK_SIZE characters. */ int iso_filesrc_write_data(Ecma119Image *t, IsoFileSrc *file, char *name, char *buffer, int flag) { int res, ret, was_error; char *name_data = NULL; char *buffer_data = NULL; size_t b; off_t file_size; uint32_t nblocks; void *ctx= NULL; char md5[16], pre_md5[16]; int pre_md5_valid = 0; IsoStream *stream, *inp; #ifdef Libisofs_with_libjtE int jte_begun = 0; #endif if (name == NULL) { LIBISO_ALLOC_MEM(name_data, char, PATH_MAX); name = name_data; } if (buffer == NULL) { LIBISO_ALLOC_MEM(buffer_data, char, BLOCK_SIZE); buffer = buffer_data; } was_error = 0; file_size = iso_file_src_get_size(file); nblocks = DIV_UP(file_size, BLOCK_SIZE); pre_md5_valid = 0; if (file->checksum_index > 0 && (t->opts->md5_file_checksums & 2)) { /* Obtain an MD5 of content by a first read pass */ pre_md5_valid = filesrc_make_md5(t, file, pre_md5, 0); } res = filesrc_open(file); /* Get file name from end of filter chain */ for (stream = file->stream; ; stream = inp) { inp = iso_stream_get_input_stream(stream, 0); if (inp == NULL) break; } iso_stream_get_file_name(stream, name); if (res < 0) { /* * UPS, very ugly error, the best we can do is just to write * 0's to image */ iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0); was_error = 1; res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, res, "File \"%s\" can't be opened. Filling with 0s.", name); if (res < 0) { ret = res; /* aborted due to error severity */ goto ex; } memset(buffer, 0, BLOCK_SIZE); for (b = 0; b < nblocks; ++b) { res = iso_write(t, buffer, BLOCK_SIZE); if (res < 0) { /* ko, writer error, we need to go out! */ ret = res; goto ex; } } ret = ISO_SUCCESS; goto ex; } else if (res > 1) { iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0); was_error = 1; res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, 0, "Size of file \"%s\" has changed. It will be %s", name, (res == 2 ? "truncated" : "padded with 0's")); if (res < 0) { filesrc_close(file); ret = res; /* aborted due to error severity */ goto ex; } } #ifdef LIBISOFS_VERBOSE_DEBUG else { iso_msg_debug(t->image->id, "Writing file %s", name); } #endif /* >>> HFS: need to align to allocation block size */; #ifdef Libisofs_with_libjtE if (t->opts->libjte_handle != NULL) { res = libjte_begin_data_file(t->opts->libjte_handle, name, BLOCK_SIZE, file_size); if (res <= 0) { res = iso_libjte_forward_msgs(t->opts->libjte_handle, t->image->id, ISO_LIBJTE_FILE_FAILED, 0); if (res < 0) { filesrc_close(file); ret = ISO_LIBJTE_FILE_FAILED; goto ex; } } jte_begun = 1; } #endif /* Libisofs_with_libjtE */ if (file->checksum_index > 0) { /* initialize file checksum */ res = iso_md5_start(&ctx); if (res <= 0) file->checksum_index = 0; } /* write file contents to image */ for (b = 0; b < nblocks; ++b) { int wres; res = filesrc_read(file, buffer, BLOCK_SIZE); if (res < 0) { /* read error */ break; } wres = iso_write(t, buffer, BLOCK_SIZE); if (wres < 0) { /* ko, writer error, we need to go out! */ filesrc_close(file); ret = wres; goto ex; } if (file->checksum_index > 0) { /* Add to file checksum */ if (file_size - b * BLOCK_SIZE > BLOCK_SIZE) res = BLOCK_SIZE; else res = file_size - b * BLOCK_SIZE; res = iso_md5_compute(ctx, buffer, res); if (res <= 0) file->checksum_index = 0; } } filesrc_close(file); if (b < nblocks) { /* premature end of file, due to error or eof */ iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0); was_error = 1; if (res < 0) { /* error */ res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, res, "Read error in file %s.", name); } else { /* eof */ res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, 0, "Premature end of file %s.", name); } if (res < 0) { ret = res; /* aborted due error severity */ goto ex; } /* fill with 0s */ iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, 0, "Filling with 0"); memset(buffer, 0, BLOCK_SIZE); while (b++ < nblocks) { res = iso_write(t, buffer, BLOCK_SIZE); if (res < 0) { /* ko, writer error, we need to go out! */ ret = res; goto ex; } if (file->checksum_index > 0) { /* Add to file checksum */ if (file_size - b * BLOCK_SIZE > BLOCK_SIZE) res = BLOCK_SIZE; else res = file_size - b * BLOCK_SIZE; res = iso_md5_compute(ctx, buffer, res); if (res <= 0) file->checksum_index = 0; } } } if (file->checksum_index > 0 && file->checksum_index <= t->checksum_idx_counter) { /* Obtain checksum and dispose checksum context */ res = iso_md5_end(&ctx, md5); if (res <= 0) file->checksum_index = 0; if ((t->opts->md5_file_checksums & 2) && pre_md5_valid > 0 && !was_error) { if (! iso_md5_match(md5, pre_md5)) { /* Issue MISHAP event */ iso_report_errfile(name, ISO_MD5_STREAM_CHANGE, 0, 0); was_error = 1; res = iso_msg_submit(t->image->id, ISO_MD5_STREAM_CHANGE,0, "Content of file '%s' changed while it was written into the image.", name); if (res < 0) { ret = res; /* aborted due to error severity */ goto ex; } } } /* Write md5 into checksum buffer at file->checksum_index */ memcpy(t->checksum_buffer + 16 * file->checksum_index, md5, 16); } ret = ISO_SUCCESS; ex:; if (ctx != NULL) /* avoid any memory leak */ iso_md5_end(&ctx, md5); #ifdef Libisofs_with_libjtE if (jte_begun) { res = libjte_end_data_file(t->opts->libjte_handle); iso_libjte_forward_msgs(t->opts->libjte_handle, t->image->id, ISO_LIBJTE_END_FAILED, 0); if (res <= 0 && ret >= 0) ret = ISO_LIBJTE_FILE_FAILED; } #endif /* Libisofs_with_libjtE */ LIBISO_FREE_MEM(buffer_data); LIBISO_FREE_MEM(name_data); return ret; } static int filesrc_writer_write_data(IsoImageWriter *writer) { int ret; size_t i; Ecma119Image *t = NULL; IsoFileSrc *file; IsoFileSrc **filelist; char *name = NULL; char *buffer = NULL; if (writer == NULL) { ret = ISO_ASSERT_FAILURE; goto ex; } LIBISO_ALLOC_MEM(name, char, PATH_MAX); LIBISO_ALLOC_MEM(buffer, char, BLOCK_SIZE); t = writer->target; filelist = writer->data; iso_msg_debug(t->image->id, "Writing Files..."); /* Normally write a single zeroed block as block address target for all files which have no block address: symbolic links, device files, empty data files. */ if (! t->opts->old_empty) { ret = iso_write(t, buffer, BLOCK_SIZE); if (ret < 0) goto ex; } i = 0; while ((file = filelist[i++]) != NULL) { if (file->no_write) { /* Do not write external partitions */ iso_msg_debug(t->image->id, "filesrc_writer: Skipping no_write-src [%.f , %.f]", (double) file->sections[0].block, (double) (file->sections[0].block - 1 + (file->sections[0].size + 2047) / BLOCK_SIZE)); continue; } ret = iso_filesrc_write_data(t, file, name, buffer, 0); if (ret < 0) goto ex; } ret = ISO_SUCCESS; ex:; LIBISO_FREE_MEM(buffer); LIBISO_FREE_MEM(name); return ret; } static int filesrc_writer_free_data(IsoImageWriter *writer) { /* free the list of files (contents are free together with the tree) */ free(writer->data); return ISO_SUCCESS; } int iso_file_src_writer_create(Ecma119Image *target) { IsoImageWriter *writer; writer = calloc(1, sizeof(IsoImageWriter)); if (writer == NULL) { return ISO_OUT_OF_MEM; } writer->compute_data_blocks = filesrc_writer_compute_data_blocks; writer->write_vol_desc = filesrc_writer_write_vol_desc; writer->write_data = filesrc_writer_write_data; writer->free_data = filesrc_writer_free_data; writer->data = NULL; writer->target = target; /* add this writer to image */ target->writers[target->nwriters++] = writer; return ISO_SUCCESS; } libisofs-1.4.2/libisofs/joliet.h0000644000175700017510000000321012321161425013523 00000000000000/* * Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2007 Mario Danic * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ /** * Declare Joliet related structures. */ #ifndef LIBISO_JOLIET_H #define LIBISO_JOLIET_H #include "libisofs.h" #include "ecma119.h" /* was formerly 66 = 64 + 2. Now 105 = 103 + 2. */ #define LIBISO_JOLIET_NAME_MAX 105 enum joliet_node_type { JOLIET_FILE, JOLIET_DIR }; struct joliet_dir_info { JolietNode **children; size_t nchildren; size_t len; size_t block; }; struct joliet_node { uint16_t *name; /**< Name in UCS-2BE. */ JolietNode *parent; IsoNode *node; /*< reference to the iso node */ enum joliet_node_type type; union { IsoFileSrc *file; struct joliet_dir_info *dir; } info; }; /** * Create a IsoWriter to deal with Joliet estructures, and add it to the given * target. * * @return * 1 on success, < 0 on error */ int joliet_writer_create(Ecma119Image *target); /* Not to be called but only for comparison with target->writers[i] */ int joliet_writer_write_vol_desc(IsoImageWriter *writer); /** * Determine the Joliet name from node name. * @param flag bit0= Do not issue error messages */ int iso_get_joliet_name(IsoWriteOpts *opts, char *input_charset, int imgid, char *node_name, enum IsoNodeType node_type, size_t *joliet_ucs2_failures, uint16_t **name, int flag); #endif /* LIBISO_JOLIET_H */ libisofs-1.4.2/libisofs/util_htable.c0000644000175700017510000002065012321161425014533 00000000000000/* * Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2014 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif #include "util.h" #include "libisofs.h" #include #include /* * Hash table implementation */ struct iso_hnode { void *key; void *data; /** next node for chaining */ struct iso_hnode *next; }; struct iso_htable { struct iso_hnode **table; size_t size; /**< number of items in table */ size_t cap; /**< number of slots in table */ hash_funtion_t hash; compare_function_t compare; }; static struct iso_hnode *iso_hnode_new(void *key, void *data) { struct iso_hnode *node = malloc(sizeof(struct iso_hnode)); if (node == NULL) return NULL; node->data = data; node->key = key; node->next = NULL; return node; } /** * Put an element in a Hash Table. The element will be identified by * the given key, that you should use to retrieve the element again. * * This function allow duplicates, i.e., two items with the same key. In those * cases, the value returned by iso_htable_get() is undefined. If you don't * want to allow duplicates, use iso_htable_put() instead; * * Both the key and data pointers will be stored internally, so you should * free the objects they point to. Use iso_htable_remove() to delete an * element from the table. */ int iso_htable_add(IsoHTable *table, void *key, void *data) { struct iso_hnode *node; struct iso_hnode *new; unsigned int hash; if (table == NULL || key == NULL) { return ISO_NULL_POINTER; } new = iso_hnode_new(key, data); if (new == NULL) { return ISO_OUT_OF_MEM; } hash = table->hash(key) % table->cap; node = table->table[hash]; table->size++; new->next = node; table->table[hash] = new; return ISO_SUCCESS; } /** * Like iso_htable_add(), but this doesn't allow dulpicates. * * @return * 1 success, 0 if an item with the same key already exists, < 0 error */ int iso_htable_put(IsoHTable *table, void *key, void *data) { struct iso_hnode *node; struct iso_hnode *new; unsigned int hash; if (table == NULL || key == NULL) { return ISO_NULL_POINTER; } hash = table->hash(key) % table->cap; node = table->table[hash]; while (node) { if (!table->compare(key, node->key)) { return 0; } node = node->next; } new = iso_hnode_new(key, data); if (new == NULL) { return ISO_OUT_OF_MEM; } table->size++; new->next = table->table[hash]; table->table[hash] = new; return ISO_SUCCESS; } /** * Retrieve an element from the given table. * * @param table * Hash table * @param key * Key of the element that will be removed * @param data * Will be filled with the element found. Remains untouched if no * element with the given key is found. * @return * 1 if found, 0 if not, < 0 on error */ int iso_htable_get(IsoHTable *table, void *key, void **data) { struct iso_hnode *node; unsigned int hash; if (table == NULL || key == NULL) { return ISO_NULL_POINTER; } hash = table->hash(key) % table->cap; node = table->table[hash]; while (node) { if (!table->compare(key, node->key)) { if (data) { *data = node->data; } return 1; } node = node->next; } return 0; } /** * Remove an item with the given key from the table. In tables that allow * duplicates, it is undefined the element that will be deleted. * * @param table * Hash table * @param key * Key of the element that will be removed * @param free_data * Function that will be called passing as parameters both the key and * the element that will be deleted. The user can use it to free the * element. You can pass NULL if you don't want to delete the item itself. * @return * 1 success, 0 no element exists with the given key, < 0 error */ int iso_htable_remove(IsoHTable *table, void *key, hfree_data_t free_data) { struct iso_hnode *node, *prev; unsigned int hash; if (table == NULL || key == NULL) { return ISO_NULL_POINTER; } hash = table->hash(key) % table->cap; node = table->table[hash]; prev = NULL; while (node) { if (!table->compare(key, node->key)) { if (free_data) free_data(node->key, node->data); if (prev) { prev->next = node->next; } else { table->table[hash] = node->next; } free(node); table->size--; return 1; } prev = node; node = node->next; } return 0; } /** * Like remove, but instead of checking for key equality using the compare * function, it just compare the key pointers. If the table allows duplicates, * and you provide different keys (i.e. different pointers) to elements * with same key (i.e. same content), this function ensure the exact element * is removed. * * It has the problem that you must provide the same key pointer, and not just * a key whose contents are equal. Moreover, if you use the same key (same * pointer) to identify several objects, what of those are removed is * undefined. * * @param table * Hash table * @param key * Key of the element that will be removed * @param free_data * Function that will be called passing as parameters both the key and * the element that will be deleted. The user can use it to free the * element. You can pass NULL if you don't want to delete the item itself. * @return * 1 success, 0 no element exists with the given key, < 0 error */ int iso_htable_remove_ptr(IsoHTable *table, void *key, hfree_data_t free_data) { struct iso_hnode *node, *prev; unsigned int hash; if (table == NULL || key == NULL) { return ISO_NULL_POINTER; } hash = table->hash(key) % table->cap; node = table->table[hash]; prev = NULL; while (node) { if (key == node->key) { if (free_data) free_data(node->key, node->data); if (prev) { prev->next = node->next; } else { table->table[hash] = node->next; } free(node); table->size--; return 1; } prev = node; node = node->next; } return 0; } /** * Hash function suitable for keys that are char strings. */ unsigned int iso_str_hash(const void *key) { int i, len; const char *p = key; unsigned int h = 2166136261u; len = strlen(p); for (i = 0; i < len; i++) h = (h * 16777619 ) ^ p[i]; return h; } /** * Destroy the given hash table. * * Note that you're responsible to actually destroy the elements by providing * a valid free_data function. You can pass NULL if you only want to delete * the hash structure. */ void iso_htable_destroy(IsoHTable *table, hfree_data_t free_data) { size_t i; struct iso_hnode *node, *tmp; if (table == NULL) { return; } for (i = 0; i < table->cap; ++i) { node = table->table[i]; while (node) { tmp = node->next; if (free_data) free_data(node->key, node->data); free(node); node = tmp; } } free(table->table); free(table); } /** * Create a new hash table. * * @param size * Number of slots in table. * @param hash * Function used to generate */ int iso_htable_create(size_t size, hash_funtion_t hash, compare_function_t compare, IsoHTable **table) { IsoHTable *t; if (size <= 0) return ISO_WRONG_ARG_VALUE; if (table == NULL) return ISO_NULL_POINTER; t = malloc(sizeof(IsoHTable)); if (t == NULL) { return ISO_OUT_OF_MEM; } t->table = calloc(size, sizeof(void*)); if (t->table == NULL) { free(t); return ISO_OUT_OF_MEM; } t->cap = size; t->size = 0; t->hash = hash; t->compare = compare; *table = t; return ISO_SUCCESS; } libisofs-1.4.2/libisofs/builder.c0000644000175700017510000002023112606500575013671 00000000000000/* * Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2009 - 2015 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif /* libisofs.h defines aaip_xinfo_func */ #include "libisofs.h" #include "builder.h" #include "node.h" #include "fsource.h" #include "image.h" #include "aaip_0_2.h" #include "util.h" #include "messages.h" #include #include #include #include void iso_node_builder_ref(IsoNodeBuilder *builder) { ++builder->refcount; } void iso_node_builder_unref(IsoNodeBuilder *builder) { if (--builder->refcount == 0) { /* free private data */ builder->free(builder); free(builder); } } static int default_create_file(IsoNodeBuilder *builder, IsoImage *image, IsoFileSource *src, IsoFile **file) { int ret; struct stat info; IsoStream *stream; IsoFile *node; char *name; if (builder == NULL || src == NULL || file == NULL) { return ISO_NULL_POINTER; } ret = iso_file_source_stat(src, &info); if (ret < 0) { return ret; } /* this will fail if src is a dir, is not accessible... */ ret = iso_file_source_stream_new(src, &stream); if (ret < 0) { return ret; } /* take a ref to the src, as stream has taken our ref */ iso_file_source_ref(src); name = iso_file_source_get_name(src); if ((int) strlen(name) > image->truncate_length) { ret = iso_truncate_rr_name(image->truncate_mode, image->truncate_length, name, 0); if (ret < 0) { iso_stream_unref(stream); free(name); return ret; } } ret = iso_node_new_file(name, stream, &node); if (ret < 0) { iso_stream_unref(stream); free(name); return ret; } /* fill node fields */ iso_node_set_permissions((IsoNode*)node, info.st_mode); iso_node_set_uid((IsoNode*)node, info.st_uid); iso_node_set_gid((IsoNode*)node, info.st_gid); iso_node_set_atime((IsoNode*)node, info.st_atime); iso_node_set_mtime((IsoNode*)node, info.st_mtime); iso_node_set_ctime((IsoNode*)node, info.st_ctime); iso_node_set_uid((IsoNode*)node, info.st_uid); *file = node; return ISO_SUCCESS; } static int default_create_node(IsoNodeBuilder *builder, IsoImage *image, IsoFileSource *src, char *in_name, IsoNode **node) { int ret, name_is_attached = 0; struct stat info; IsoNode *new; IsoFilesystem *fs; char *name = NULL; unsigned char *aa_string = NULL; char *a_text = NULL, *d_text = NULL; char *dest = NULL; IsoSymlink *link; if (builder == NULL || src == NULL || node == NULL) { {ret = ISO_NULL_POINTER; goto ex;} } /* get info about source */ if (iso_tree_get_follow_symlinks(image)) { ret = iso_file_source_stat(src, &info); } else { ret = iso_file_source_lstat(src, &info); } if (ret < 0) { goto ex; } if (in_name == NULL) { name = iso_file_source_get_name(src); } else { name = strdup(in_name); if (name == NULL) { ret = ISO_OUT_OF_MEM; goto ex; } } if ((int) strlen(name) > image->truncate_length) { ret = iso_truncate_rr_name(image->truncate_mode, image->truncate_length, name, 0); if (ret < 0) goto ex; } fs = iso_file_source_get_filesystem(src); new = NULL; switch (info.st_mode & S_IFMT) { case S_IFREG: { /* source is a regular file */ IsoStream *stream; IsoFile *file; ret = iso_file_source_stream_new(src, &stream); if (ret < 0) { break; } /* take a ref to the src, as stream has taken our ref */ iso_file_source_ref(src); /* create the file */ ret = iso_node_new_file(name, stream, &file); if (ret < 0) { iso_stream_unref(stream); } new = (IsoNode*) file; } break; case S_IFDIR: { /* source is a directory */ IsoDir *dir; ret = iso_node_new_dir(name, &dir); new = (IsoNode*)dir; } break; case S_IFLNK: { /* source is a symbolic link */ LIBISO_ALLOC_MEM(dest, char, LIBISOFS_NODE_PATH_MAX); ret = iso_file_source_readlink(src, dest, LIBISOFS_NODE_PATH_MAX); if (ret < 0) { break; } ret = iso_node_new_symlink(name, strdup(dest), &link); new = (IsoNode*) link; if (fs != NULL) { link->fs_id = fs->get_id(fs); if (link->fs_id != 0) { link->st_ino = info.st_ino; link->st_dev = info.st_dev; } } } break; case S_IFSOCK: case S_IFBLK: case S_IFCHR: case S_IFIFO: { /* source is an special file */ IsoSpecial *special; ret = iso_node_new_special(name, info.st_mode, info.st_rdev, &special); new = (IsoNode*) special; if (fs != NULL) { special->fs_id = fs->get_id(fs); if (special->fs_id != 0) { special->st_ino = info.st_ino; special->st_dev = info.st_dev; } } } break; default: ret = ISO_BAD_FSRC_FILETYPE; goto ex; } if (ret < 0) goto ex; name_is_attached = 1; /* fill fields */ iso_node_set_perms_internal(new, info.st_mode, 1); iso_node_set_uid(new, info.st_uid); iso_node_set_gid(new, info.st_gid); iso_node_set_atime(new, info.st_atime); iso_node_set_mtime(new, info.st_mtime); iso_node_set_ctime(new, info.st_ctime); iso_node_set_uid(new, info.st_uid); /* Eventually set S_IRWXG from ACL */ if (image->builder_ignore_acl) { ret = iso_file_source_get_aa_string(src, &aa_string, 4); if (ret >= 0 && aa_string != NULL) iso_aa_get_acl_text(aa_string, info.st_mode, &a_text, &d_text, 16); if (ret >= 0 && a_text != NULL) { aaip_cleanout_st_mode(a_text, &(info.st_mode), 4 | 16); iso_node_set_perms_internal(new, info.st_mode, 1); } iso_aa_get_acl_text(aa_string, info.st_mode, &a_text, &d_text, 1 << 15); /* free ACL texts */ if(aa_string != NULL) free(aa_string); aa_string = NULL; } /* Obtain ownership of eventual AAIP string */ ret = iso_file_source_get_aa_string(src, &aa_string, 1 | (image->builder_ignore_acl << 1) | (image->builder_ignore_ea << 2 )); if (ret == 1 && aa_string != NULL) { ret = iso_node_add_xinfo(new, aaip_xinfo_func, aa_string); if (ret < 0) goto ex; } else if(aa_string != NULL) { free(aa_string); } *node = new; ret = ISO_SUCCESS; ex:; if (name != NULL && !name_is_attached) free(name); LIBISO_FREE_MEM(dest); return ret; } static void default_free(IsoNodeBuilder *builder) { /* The .free() method of IsoNodeBuilder shall free private data but not the builder itself. The latter is done in iso_node_builder_unref(). */ return; } int iso_node_basic_builder_new(IsoNodeBuilder **builder) { IsoNodeBuilder *b; if (builder == NULL) { return ISO_NULL_POINTER; } b = malloc(sizeof(IsoNodeBuilder)); if (b == NULL) { return ISO_OUT_OF_MEM; } b->refcount = 1; b->create_file_data = NULL; b->create_node_data = NULL; b->create_file = default_create_file; b->create_node = default_create_node; b->free = default_free; *builder = b; return ISO_SUCCESS; } libisofs-1.4.2/libisofs/stream.h0000644000175700017510000001012112546752026013543 00000000000000/* * Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2009 - 2011 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ #ifndef LIBISO_STREAM_H_ #define LIBISO_STREAM_H_ /* * Definitions of streams. */ #include "fsource.h" /* IMPORTANT: Any change must be reflected by fsrc_clone_stream */ typedef struct { IsoFileSource *src; /* key for file identification inside filesystem */ dev_t dev_id; ino_t ino_id; off_t size; /**< size of this file */ } FSrcStreamData; /** * Get an identifier for the file of the source, for debug purposes * @param name * Must provide at least PATH_MAX bytes. If no PATH_MAX is defined * then assume PATH_MAX = Libisofs_default_path_maX from libisofs.h */ void iso_stream_get_file_name(IsoStream *stream, char *name); /** * Create a stream to read from a IsoFileSource. * The stream will take the ref. to the IsoFileSource, so after a successfully * exectution of this function, you musn't unref() the source, unless you * take an extra ref. * * @return * 1 sucess, < 0 error * Possible errors: * */ int iso_file_source_stream_new(IsoFileSource *src, IsoStream **stream); /** * Create a new stream to read a chunk of an IsoFileSource.. * The stream will add a ref. to the IsoFileSource. * * @return * 1 sucess, < 0 error */ int iso_cut_out_stream_new(IsoFileSource *src, off_t offset, off_t size, IsoStream **stream); /** * Obtain eventual zisofs ZF field entry parameters from a file source out * of a loaded ISO image. * To make hope for non-zero reply the stream has to be the original stream * of an IsoFile with .from_old_session==1. The call is safe with any stream * type, though, unless fsrc_stream_class would be used without FSrcStreamData. * @return 1= returned parameters are valid, 0=no ZF info found , <0 error */ int iso_stream_get_src_zf(IsoStream *stream, int *header_size_div4, int *block_size_log2, uint32_t *uncompressed_size, int flag); /** * Set the inode number of a stream that is based on FSrcStreamData, i.e. * stems from the imported ISO image. * @return 1 = ok , 0 = not an ISO image stream , <0 = error */ int iso_stream_set_image_ino(IsoStream *stream, ino_t ino, int flag); /** * Read the full required amount of data unless error or EOF occurs. * Fill missing bytes by 0s. * @param count Required amount * @param got Returns number of actually read bytes * @return * 1 no problem encountered, 0 EOF encountered, < 0 error */ int iso_stream_read_buffer(IsoStream *stream, char *buf, size_t count, size_t *got); /** * @return 1=ok, md5 is valid, * 0= not ok * <0 fatal error, abort */ int iso_stream_make_md5(IsoStream *stream, char md5[16], int flag); /** * Create a clone of the input stream of old_stream and a roughly initialized * clone of old_stream which has the same class and refcount 1. Its data * pointer will be NULL and needs to be filled by an expert which knows how * to clone the data of old_stream. * @param old_stream The existing stream which is in process of cloning * @param new_stream Will return the uninitialized memory object which shall * later become the clone of old_stream. * @param new_input The clone of the input stream of old stream. * @param flag Submit 0 for now. * @return ISO_SUCCESS or an error code <0 */ int iso_stream_clone_filter_common(IsoStream *old_stream, IsoStream **new_stream, IsoStream **new_input, int flag); /** * Dispose the internal list of stream class cmp_ino() functions. It is * a static global of stream.c, created and used by iso_stream_cmp_ino(). * This function is supposed to be called by iso_finish() only. */ int iso_stream_destroy_cmpranks(int flag); #endif /*STREAM_H_*/ libisofs-1.4.2/libisofs/ecma119.c0000644000175700017510000037537412606460000013414 00000000000000/* * Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2007 Mario Danic * Copyright (c) 2009 - 2015 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif /* Use the copy of the struct burn_source definition in libisofs.h */ #define LIBISOFS_WITHOUT_LIBBURN yes #include "libisofs.h" #include "ecma119.h" #include "joliet.h" #include "hfsplus.h" #include "iso1999.h" #include "eltorito.h" #include "ecma119_tree.h" #include "filesrc.h" #include "image.h" #include "writer.h" #include "messages.h" #include "rockridge.h" #include "util.h" #include "system_area.h" #include "md5.h" #include #include #include #include #include #include #include #ifdef Xorriso_standalonE #ifdef Xorriso_with_libjtE #include "../libjte/libjte.h" #endif #else #ifdef Libisofs_with_libjtE #include #endif #endif /* ! Xorriso_standalonE */ int iso_write_opts_clone(IsoWriteOpts *in, IsoWriteOpts **out, int flag); /* * TODO #00011 : guard against bad path table usage with more than 65535 dirs * image with more than 65535 directories have path_table related problems * due to 16 bits parent id. Note that this problem only affects to folders * that are parent of another folder. */ static void ecma119_image_free(Ecma119Image *t) { size_t i; if (t == NULL) return; if (t->refcount > 1) { t->refcount--; return; } if (t->root != NULL) ecma119_node_free(t->root); if (t->opts != NULL) iso_write_opts_free(t->opts); if (t->image != NULL) iso_image_unref(t->image); if (t->files != NULL) iso_rbtree_destroy(t->files, iso_file_src_free); if (t->ecma119_hidden_list != NULL) iso_filesrc_list_destroy(&(t->ecma119_hidden_list)); if (t->buffer != NULL) iso_ring_buffer_free(t->buffer); for (i = 0; i < t->nwriters; ++i) { IsoImageWriter *writer = t->writers[i]; writer->free_data(writer); free(writer); } if (t->input_charset != NULL) free(t->input_charset); if (t->output_charset != NULL) free(t->output_charset); if (t->bootsrc != NULL) free(t->bootsrc); if (t->system_area_data != NULL) free(t->system_area_data); if (t->checksum_ctx != NULL) { /* dispose checksum context */ char md5[16]; iso_md5_end(&(t->checksum_ctx), md5); } if (t->checksum_buffer != NULL) free(t->checksum_buffer); if (t->writers != NULL) free(t->writers); if (t->partition_root != NULL) ecma119_node_free(t->partition_root); for (i = 0; i < ISO_HFSPLUS_BLESS_MAX; i++) if (t->hfsplus_blessed[i] != NULL) iso_node_unref(t->hfsplus_blessed[i]); for (i = 0; (int) i < t->apm_req_count; i++) if (t->apm_req[i] != NULL) free(t->apm_req[i]); for (i = 0; (int) i < t->mbr_req_count; i++) if (t->mbr_req[i] != NULL) free(t->mbr_req[i]); for (i = 0; (int) i < t->gpt_req_count; i++) if (t->gpt_req[i] != NULL) free(t->gpt_req[i]); free(t); } static int show_chunk_to_jte(Ecma119Image *target, char *buf, int count) { #ifdef Libisofs_with_libjtE int ret; if (target->opts->libjte_handle == NULL) return ISO_SUCCESS; ret = libjte_show_data_chunk(target->opts->libjte_handle, buf, count, 1); if (ret <= 0) { iso_libjte_forward_msgs(target->opts->libjte_handle, target->image->id, ISO_LIBJTE_FILE_FAILED, 0); return ISO_LIBJTE_FILE_FAILED; } #endif /* Libisofs_with_libjtE */ return ISO_SUCCESS; } /** * Check if we should add version number ";" to the given node name. */ static int need_version_number(IsoWriteOpts *opts, enum ecma119_node_type node_type) { if ((opts->omit_version_numbers & 1) || opts->max_37_char_filenames || opts->untranslated_name_len > 0) { return 0; } if (node_type == ECMA119_DIR || node_type == ECMA119_PLACEHOLDER) { return 0; } else { return 1; } } /** * Compute the size of a directory entry for a single node */ static size_t calc_dirent_len(Ecma119Image *t, Ecma119Node *n) { int ret = n->iso_name ? strlen(n->iso_name) + 33 : 34; if (need_version_number(t->opts, n->type)) { ret += 2; /* take into account version numbers */ } if (ret % 2) ret++; return ret; } /** * Computes the total size of all directory entries of a single dir, * acording to ECMA-119 6.8.1.1 * * This also take into account the size needed for RR entries and * SUSP continuation areas (SUSP, 5.1). * * @param ce * Will be filled with the size needed for Continuation Areas * @return * The size needed for all dir entries of the given dir, without * taking into account the continuation areas. */ static size_t calc_dir_size(Ecma119Image *t, Ecma119Node *dir, size_t *ce) { size_t i, len; size_t ce_len = 0; /* size of "." and ".." entries */ len = 34 + 34; if (t->opts->rockridge) { len += rrip_calc_len(t, dir, 1, 34, &ce_len, *ce); *ce += ce_len; len += rrip_calc_len(t, dir, 2, 34, &ce_len, *ce); *ce += ce_len; } for (i = 0; i < dir->info.dir->nchildren; ++i) { size_t remaining; int section, nsections; Ecma119Node *child = dir->info.dir->children[i]; nsections = (child->type == ECMA119_FILE) ? child->info.file->nsections : 1; for (section = 0; section < nsections; ++section) { size_t dirent_len = calc_dirent_len(t, child); if (t->opts->rockridge) { dirent_len += rrip_calc_len(t, child, 0, dirent_len, &ce_len, *ce); *ce += ce_len; } remaining = BLOCK_SIZE - (len % BLOCK_SIZE); if (dirent_len > remaining) { /* child directory entry doesn't fit on block */ len += remaining + dirent_len; } else { len += dirent_len; } } } /* * The size of a dir is always a multiple of block size, as we must add * the size of the unused space after the last directory record * (ECMA-119, 6.8.1.3) */ len = ROUND_UP(len, BLOCK_SIZE); /* cache the len */ dir->info.dir->len = len; return len; } static void calc_dir_pos(Ecma119Image *t, Ecma119Node *dir) { size_t i, len; size_t ce_len = 0; t->ndirs++; dir->info.dir->block = t->curblock; len = calc_dir_size(t, dir, &ce_len); t->curblock += DIV_UP(len, BLOCK_SIZE); if (t->opts->rockridge) { t->curblock += DIV_UP(ce_len, BLOCK_SIZE); } for (i = 0; i < dir->info.dir->nchildren; i++) { Ecma119Node *child = dir->info.dir->children[i]; if (child->type == ECMA119_DIR) { calc_dir_pos(t, child); } } } /** * Compute the length of the path table, in bytes. */ static uint32_t calc_path_table_size(Ecma119Node *dir) { uint32_t size; size_t i; /* size of path table for this entry */ size = 8; size += dir->iso_name ? strlen(dir->iso_name) : 1; size += (size % 2); /* and recurse */ for (i = 0; i < dir->info.dir->nchildren; i++) { Ecma119Node *child = dir->info.dir->children[i]; if (child->type == ECMA119_DIR) { size += calc_path_table_size(child); } } return size; } static int ecma119_writer_compute_data_blocks(IsoImageWriter *writer) { Ecma119Image *target; uint32_t path_table_size; size_t ndirs; if (writer == NULL) { return ISO_ASSERT_FAILURE; } target = writer->target; /* compute position of directories */ iso_msg_debug(target->image->id, "Computing position of dir structure"); target->ndirs = 0; calc_dir_pos(target, target->root); /* compute length of pathlist */ iso_msg_debug(target->image->id, "Computing length of pathlist"); path_table_size = calc_path_table_size(target->root); /* compute location for path tables */ target->l_path_table_pos = target->curblock; target->curblock += DIV_UP(path_table_size, BLOCK_SIZE); target->m_path_table_pos = target->curblock; target->curblock += DIV_UP(path_table_size, BLOCK_SIZE); target->path_table_size = path_table_size; if (target->opts->md5_session_checksum) { /* Account for first tree checksum tag */ target->checksum_tree_tag_pos = target->curblock; target->curblock++; } if (target->opts->partition_offset > 0) { /* Take into respect the second directory tree */ ndirs = target->ndirs; target->ndirs = 0; calc_dir_pos(target, target->partition_root); if (target->ndirs != ndirs) { iso_msg_submit(target->image->id, ISO_ASSERT_FAILURE, 0, "Number of directories differs in ECMA-119 partiton_tree"); return ISO_ASSERT_FAILURE; } /* Take into respect the second set of path tables */ path_table_size = calc_path_table_size(target->partition_root); target->partition_l_table_pos = target->curblock; target->curblock += DIV_UP(path_table_size, BLOCK_SIZE); target->partition_m_table_pos = target->curblock; target->curblock += DIV_UP(path_table_size, BLOCK_SIZE); /* >>> TWINTREE: >>> For now, checksum tags are only for the image start and not for the partition */; } target->tree_end_block = target->curblock; return ISO_SUCCESS; } /** * Write a single directory record (ECMA-119, 9.1) * * @param file_id * if >= 0, we use it instead of the filename (for "." and ".." entries). * @param len_fi * Computed length of the file identifier. Total size of the directory * entry will be len + 33 + padding if needed (ECMA-119, 9.1.12) * @param info * SUSP entries for the given directory record. It will be NULL for the * root directory record in the PVD (ECMA-119, 8.4.18) (in order to * distinguish it from the "." entry in the root directory) */ static void write_one_dir_record(Ecma119Image *t, Ecma119Node *node, int file_id, uint8_t *buf, size_t len_fi, struct susp_info *info, int extent) { uint32_t len; uint32_t block; uint8_t len_dr; /*< size of dir entry without SUSP fields */ int multi_extend = 0; uint8_t *name = (file_id >= 0) ? (uint8_t*)&file_id : (uint8_t*)node->iso_name; struct ecma119_dir_record *rec = (struct ecma119_dir_record*)buf; IsoNode *iso; len_dr = 33 + len_fi + ((len_fi % 2) ? 0 : 1); memcpy(rec->file_id, name, len_fi); if (need_version_number(t->opts, node->type)) { len_dr += 2; rec->file_id[len_fi++] = ';'; rec->file_id[len_fi++] = '1'; } if (node->type == ECMA119_DIR) { /* use the cached length */ len = node->info.dir->len; block = node->info.dir->block; } else if (node->type == ECMA119_FILE) { block = node->info.file->sections[extent].block; len = node->info.file->sections[extent].size; multi_extend = (node->info.file->nsections - 1 == extent) ? 0 : 1; } else { /* * for nodes other than files and dirs, we set len to 0, and * the content block address to a dummy value. */ len = 0; if (! t->opts->old_empty) block = t->empty_file_block; else block = 0; } /* * For ".." entry we need to write the parent info! */ if (file_id == 1 && node->parent) node = node->parent; rec->len_dr[0] = len_dr + (info != NULL ? info->suf_len : 0); iso_bb(rec->block, block - t->eff_partition_offset, 4); iso_bb(rec->length, len, 4); if (t->opts->dir_rec_mtime & 1) { iso= node->node; iso_datetime_7(rec->recording_time, t->replace_timestamps ? t->timestamp : iso->mtime, t->opts->always_gmt); } else { iso_datetime_7(rec->recording_time, t->now, t->opts->always_gmt); } rec->flags[0] = ((node->type == ECMA119_DIR) ? 2 : 0) | (multi_extend ? 0x80 : 0); iso_bb(rec->vol_seq_number, (uint32_t) 1, 2); rec->len_fi[0] = len_fi; /* * and finally write the SUSP fields. */ if (info != NULL) { rrip_write_susp_fields(t, info, buf + len_dr); } } static char *get_relaxed_vol_id(Ecma119Image *t, const char *name) { int ret; if (name == NULL) { return NULL; } if (strcmp(t->input_charset, t->output_charset)) { /* charset conversion needed */ char *str; ret = strconv(name, t->input_charset, t->output_charset, &str); if (ret == ISO_SUCCESS) { return str; } iso_msg_submit(t->image->id, ISO_FILENAME_WRONG_CHARSET, ret, "Charset conversion error. Cannot convert from %s to %s", t->input_charset, t->output_charset); } return strdup(name); } /** * Set the timestamps of Primary, Supplementary, or Enhanced Volume Descriptor. */ void ecma119_set_voldescr_times(IsoImageWriter *writer, struct ecma119_pri_vol_desc *vol) { Ecma119Image *t = writer->target; IsoWriteOpts *o; int i; o = t->opts; if (o->vol_uuid[0]) { for(i = 0; i < 16; i++) if(o->vol_uuid[i] < '0' || o->vol_uuid[i] > '9') break; else vol->vol_creation_time[i] = o->vol_uuid[i]; for(; i < 16; i++) vol->vol_creation_time[i] = '1'; vol->vol_creation_time[16] = 0; } else if (o->vol_creation_time > 0) iso_datetime_17(vol->vol_creation_time, o->vol_creation_time, o->always_gmt); else iso_datetime_17(vol->vol_creation_time, t->now, o->always_gmt); if (o->vol_uuid[0]) { for(i = 0; i < 16; i++) if(o->vol_uuid[i] < '0' || o->vol_uuid[i] > '9') break; else vol->vol_modification_time[i] = o->vol_uuid[i]; for(; i < 16; i++) vol->vol_modification_time[i] = '1'; vol->vol_modification_time[16] = 0; } else if (o->vol_modification_time > 0) iso_datetime_17(vol->vol_modification_time, o->vol_modification_time, o->always_gmt); else iso_datetime_17(vol->vol_modification_time, t->now, o->always_gmt); if (o->vol_expiration_time > 0) { iso_datetime_17(vol->vol_expiration_time, o->vol_expiration_time, o->always_gmt); } else { for(i = 0; i < 16; i++) vol->vol_expiration_time[i] = '0'; vol->vol_expiration_time[16] = 0; } if (o->vol_effective_time > 0) { iso_datetime_17(vol->vol_effective_time, o->vol_effective_time, o->always_gmt); } else { for(i = 0; i < 16; i++) vol->vol_effective_time[i] = '0'; vol->vol_effective_time[16] = 0; } } /** * Write the Primary Volume Descriptor (ECMA-119, 8.4) */ static int ecma119_writer_write_vol_desc(IsoImageWriter *writer) { IsoImage *image; Ecma119Image *t; struct ecma119_pri_vol_desc vol; char *vol_id, *pub_id, *data_id, *volset_id; char *system_id, *application_id, *copyright_file_id; char *abstract_file_id, *biblio_file_id; if (writer == NULL) { return ISO_ASSERT_FAILURE; } t = writer->target; image = t->image; iso_msg_debug(image->id, "Write Primary Volume Descriptor"); memset(&vol, 0, sizeof(struct ecma119_pri_vol_desc)); if (t->opts->relaxed_vol_atts) { vol_id = get_relaxed_vol_id(t, image->volume_id); volset_id = get_relaxed_vol_id(t, image->volset_id); } else { str2d_char(t->input_charset, image->volume_id, &vol_id); str2d_char(t->input_charset, image->volset_id, &volset_id); } str2a_char(t->input_charset, image->publisher_id, &pub_id); str2a_char(t->input_charset, image->data_preparer_id, &data_id); str2a_char(t->input_charset, image->system_id, &system_id); str2a_char(t->input_charset, image->application_id, &application_id); str2d_char(t->input_charset, image->copyright_file_id, ©right_file_id); str2d_char(t->input_charset, image->abstract_file_id, &abstract_file_id); str2d_char(t->input_charset, image->biblio_file_id, &biblio_file_id); vol.vol_desc_type[0] = 1; memcpy(vol.std_identifier, "CD001", 5); vol.vol_desc_version[0] = 1; strncpy_pad((char*)vol.system_id, system_id, 32); strncpy_pad((char*)vol.volume_id, vol_id, 32); iso_bb(vol.vol_space_size, t->vol_space_size - t->eff_partition_offset, 4); iso_bb(vol.vol_set_size, (uint32_t) 1, 2); iso_bb(vol.vol_seq_number, (uint32_t) 1, 2); iso_bb(vol.block_size, (uint32_t) BLOCK_SIZE, 2); iso_bb(vol.path_table_size, t->path_table_size, 4); if (t->eff_partition_offset > 0) { /* Point to second tables and second root */ iso_lsb(vol.l_path_table_pos, t->partition_l_table_pos - t->eff_partition_offset, 4); iso_msb(vol.m_path_table_pos, t->partition_m_table_pos - t->eff_partition_offset, 4); write_one_dir_record(t, t->partition_root, 0, vol.root_dir_record, 1, NULL, 0); } else { iso_lsb(vol.l_path_table_pos, t->l_path_table_pos, 4); iso_msb(vol.m_path_table_pos, t->m_path_table_pos, 4); write_one_dir_record(t, t->root, 0, vol.root_dir_record, 1, NULL, 0); } strncpy_pad((char*)vol.vol_set_id, volset_id, 128); strncpy_pad((char*)vol.publisher_id, pub_id, 128); strncpy_pad((char*)vol.data_prep_id, data_id, 128); strncpy_pad((char*)vol.application_id, application_id, 128); strncpy_pad((char*)vol.copyright_file_id, copyright_file_id, 37); strncpy_pad((char*)vol.abstract_file_id, abstract_file_id, 37); strncpy_pad((char*)vol.bibliographic_file_id, biblio_file_id, 37); ecma119_set_voldescr_times(writer, &vol); vol.file_structure_version[0] = 1; memcpy(vol.app_use, image->application_use, 512); free(vol_id); free(volset_id); free(pub_id); free(data_id); free(system_id); free(application_id); free(copyright_file_id); free(abstract_file_id); free(biblio_file_id); /* Finally write the Volume Descriptor */ return iso_write(t, &vol, sizeof(struct ecma119_pri_vol_desc)); } static int write_one_dir(Ecma119Image *t, Ecma119Node *dir, Ecma119Node *parent) { int ret; uint8_t *buffer = NULL; size_t i; size_t fi_len, len; struct susp_info info; /* buf will point to current write position on buffer */ uint8_t *buf; LIBISO_ALLOC_MEM(buffer, uint8_t, BLOCK_SIZE); buf = buffer; /* * set susp_info to 0's, this way code for both plain ECMA-119 and * RR is very similar */ memset(&info, 0, sizeof(struct susp_info)); if (t->opts->rockridge) { /* initialize the ce_block, it might be needed */ info.ce_block = dir->info.dir->block + DIV_UP(dir->info.dir->len, BLOCK_SIZE); info.ce_susp_fields = NULL; } /* write the "." and ".." entries first */ if (t->opts->rockridge) { ret = rrip_get_susp_fields(t, dir, 1, 34, &info); if (ret < 0) { goto ex; } } len = 34 + info.suf_len; write_one_dir_record(t, dir, 0, buf, 1, &info, 0); buf += len; if (t->opts->rockridge) { ret = rrip_get_susp_fields(t, dir, 2, 34, &info); if (ret < 0) { goto ex; } } len = 34 + info.suf_len; write_one_dir_record(t, parent, 1, buf, 1, &info, 0); buf += len; for (i = 0; i < dir->info.dir->nchildren; i++) { int section, nsections; Ecma119Node *child = dir->info.dir->children[i]; fi_len = strlen(child->iso_name); nsections = (child->type == ECMA119_FILE) ? child->info.file->nsections : 1; for (section = 0; section < nsections; ++section) { /* compute len of directory entry */ len = fi_len + 33 + ((fi_len % 2) ? 0 : 1); if (need_version_number(t->opts, child->type)) { len += 2; } /* get the SUSP fields if rockridge is enabled */ if (t->opts->rockridge) { ret = rrip_get_susp_fields(t, child, 0, len, &info); if (ret < 0) { goto ex; } len += info.suf_len; } if ( (buf + len - buffer) > BLOCK_SIZE) { /* dir doesn't fit in current block */ ret = iso_write(t, buffer, BLOCK_SIZE); if (ret < 0) { goto ex; } memset(buffer, 0, BLOCK_SIZE); buf = buffer; } /* write the directory entry in any case */ write_one_dir_record(t, child, -1, buf, fi_len, &info, section); buf += len; } } /* write the last block */ ret = iso_write(t, buffer, BLOCK_SIZE); if (ret < 0) { goto ex; } /* write the Continuation Area if needed */ if (info.ce_len > 0) { ret = rrip_write_ce_fields(t, &info); } ex:; LIBISO_FREE_MEM(buffer); return ret; } static int write_dirs(Ecma119Image *t, Ecma119Node *root, Ecma119Node *parent) { int ret; size_t i; /* write all directory entries for this dir */ ret = write_one_dir(t, root, parent); if (ret < 0) { return ret; } /* recurse */ for (i = 0; i < root->info.dir->nchildren; i++) { Ecma119Node *child = root->info.dir->children[i]; if (child->type == ECMA119_DIR) { ret = write_dirs(t, child, root); if (ret < 0) { return ret; } } } return ISO_SUCCESS; } static int write_path_table(Ecma119Image *t, Ecma119Node **pathlist, int l_type) { size_t i, len; uint8_t buf[64]; /* 64 is just a convenient size larger enought */ struct ecma119_path_table_record *rec; void (*write_int)(uint8_t*, uint32_t, int); Ecma119Node *dir; uint32_t path_table_size; int parent = 0; int ret= ISO_SUCCESS; uint8_t *zeros = NULL; path_table_size = 0; write_int = l_type ? iso_lsb : iso_msb; for (i = 0; i < t->ndirs; i++) { dir = pathlist[i]; /* find the index of the parent in the table */ while ((i) && pathlist[parent] != dir->parent) { parent++; } /* write the Path Table Record (ECMA-119, 9.4) */ memset(buf, 0, 64); rec = (struct ecma119_path_table_record*) buf; rec->len_di[0] = dir->parent ? (uint8_t) strlen(dir->iso_name) : 1; rec->len_xa[0] = 0; write_int(rec->block, dir->info.dir->block - t->eff_partition_offset, 4); write_int(rec->parent, parent + 1, 2); if (dir->parent) { memcpy(rec->dir_id, dir->iso_name, rec->len_di[0]); } len = 8 + rec->len_di[0] + (rec->len_di[0] % 2); ret = iso_write(t, buf, len); if (ret < 0) { /* error */ goto ex; } path_table_size += len; } /* we need to fill the last block with zeros */ path_table_size %= BLOCK_SIZE; if (path_table_size) { len = BLOCK_SIZE - path_table_size; LIBISO_ALLOC_MEM(zeros, uint8_t, len); ret = iso_write(t, zeros, len); } ex:; LIBISO_FREE_MEM(zeros); return ret; } static int write_path_tables(Ecma119Image *t) { int ret; size_t i, j, cur; Ecma119Node **pathlist; iso_msg_debug(t->image->id, "Writing ISO Path tables"); /* allocate temporal pathlist */ pathlist = malloc(sizeof(void*) * t->ndirs); if (pathlist == NULL) { return ISO_OUT_OF_MEM; } if (t->eff_partition_offset > 0) { pathlist[0] = t->partition_root; } else { pathlist[0] = t->root; } cur = 1; for (i = 0; i < t->ndirs; i++) { Ecma119Node *dir = pathlist[i]; for (j = 0; j < dir->info.dir->nchildren; j++) { Ecma119Node *child = dir->info.dir->children[j]; if (child->type == ECMA119_DIR) { pathlist[cur++] = child; } } } /* Write L Path Table */ ret = write_path_table(t, pathlist, 1); if (ret < 0) { goto write_path_tables_exit; } /* Write L Path Table */ ret = write_path_table(t, pathlist, 0); write_path_tables_exit: ; free(pathlist); return ret; } /** * Write the directory structure (ECMA-119, 6.8) and the L and M * Path Tables (ECMA-119, 6.9). */ static int ecma119_writer_write_dirs(IsoImageWriter *writer) { int ret, isofs_ca_changed = 0; Ecma119Image *t; Ecma119Node *root; char *value = NULL; size_t value_length; t = writer->target; /* first of all, we write the directory structure */ if (t->eff_partition_offset > 0) { root = t->partition_root; if ((t->opts->md5_file_checksums & 1) || t->opts->md5_session_checksum) { /* Take into respect the address offset in "isofs.ca" */ ret = iso_node_lookup_attr((IsoNode *) t->image->root, "isofs.ca", &value_length, &value, 0); if (value != NULL) free(value); if (ret == 1 && value_length == 20) { /* "isofs.ca" does really exist and has the expected length */ ret = iso_root_set_isofsca((IsoNode *) t->image->root, t->checksum_range_start - t->eff_partition_offset, t->checksum_array_pos - t->eff_partition_offset, t->checksum_idx_counter + 2, 16, "MD5", 0); if (ret < 0) return ret; isofs_ca_changed = 1; } } } else { root = t->root; } ret = write_dirs(t, root, root); if (ret < 0) { return ret; } /* and write the path tables */ ret = write_path_tables(t); if (ret < 0) return ret; if (t->opts->md5_session_checksum) { /* Write tree checksum tag */ if (t->eff_partition_offset > 0) { /* >>> TWINTREE: >>> For now, tags are only for the image start and not for the partition */; } else { ret = iso_md5_write_tag(t, 3); } } if (isofs_ca_changed) { /* Restore old addresses offset in "isofs.ca" of root node */ ret = iso_root_set_isofsca((IsoNode *) t->image->root, t->checksum_range_start, t->checksum_array_pos, t->checksum_idx_counter + 2, 16, "MD5", 0); if (ret < 0) return ret; } return ret; } /** * Write directory structure and Path Tables of the ECMA-119 tree. * This happens eventually a second time for the duplicates which use * addresses with partition offset. */ static int ecma119_writer_write_data(IsoImageWriter *writer) { int ret; Ecma119Image *t; uint32_t curblock; char *msg = NULL; if (writer == NULL) {ret = ISO_ASSERT_FAILURE; goto ex;} t = writer->target; ret = ecma119_writer_write_dirs(writer); if (ret < 0) goto ex; if (t->opts->partition_offset > 0) { t->eff_partition_offset = t->opts->partition_offset; ret = ecma119_writer_write_dirs(writer); t->eff_partition_offset = 0; if (ret < 0) goto ex; } curblock = (t->bytes_written / 2048) + t->opts->ms_block; if (curblock != t->tree_end_block) { LIBISO_ALLOC_MEM(msg, char, 100); sprintf(msg, "Calculated and written ECMA-119 tree end differ: %lu <> %lu", (unsigned long) t->tree_end_block, (unsigned long) curblock); iso_msgs_submit(0, msg, 0, "WARNING", 0); t->tree_end_block = 1;/* Mark for harsher reaction at end of writing */ } ret = ISO_SUCCESS; ex:; LIBISO_FREE_MEM(msg); return ret; } static int ecma119_writer_free_data(IsoImageWriter *writer) { /* nothing to do */ return ISO_SUCCESS; } int ecma119_writer_create(Ecma119Image *target) { int ret; IsoImageWriter *writer; writer = malloc(sizeof(IsoImageWriter)); if (writer == NULL) { return ISO_OUT_OF_MEM; } writer->compute_data_blocks = ecma119_writer_compute_data_blocks; writer->write_vol_desc = ecma119_writer_write_vol_desc; writer->write_data = ecma119_writer_write_data; writer->free_data = ecma119_writer_free_data; writer->data = NULL; writer->target = target; /* add this writer to image */ target->writers[target->nwriters++] = writer; iso_msg_debug(target->image->id, "Creating low level ECMA-119 tree..."); ret = ecma119_tree_create(target); if (ret < 0) { return ret; } if (target->image->sparc_core_node != NULL) { /* Obtain a duplicate of the IsoFile's Ecma119Node->file */ ret = iso_file_src_create(target, target->image->sparc_core_node, &target->sparc_core_src); if (ret < 0) return ret; } if(target->opts->partition_offset > 0) { /* Create second tree */ target->eff_partition_offset = target->opts->partition_offset; ret = ecma119_tree_create(target); target->eff_partition_offset = 0; if (ret < 0) return ret; } /* we need the volume descriptor */ target->curblock++; return ISO_SUCCESS; } /** compute how many padding bytes are needed */ static int mspad_writer_compute_data_blocks(IsoImageWriter *writer) { Ecma119Image *target; uint32_t min_size; if (writer == NULL) { return ISO_ASSERT_FAILURE; } target = writer->target; min_size = 32 + target->opts->partition_offset; if (target->curblock < min_size) { target->mspad_blocks = min_size - target->curblock; target->curblock = min_size; } return ISO_SUCCESS; } static int mspad_writer_write_vol_desc(IsoImageWriter *writer) { /* nothing to do */ return ISO_SUCCESS; } static int mspad_writer_write_data(IsoImageWriter *writer) { int ret; Ecma119Image *t; uint8_t *pad = NULL; size_t i; if (writer == NULL) { {ret = ISO_ASSERT_FAILURE; goto ex;} } t = writer->target; if (t->mspad_blocks == 0) { {ret = ISO_SUCCESS; goto ex;} } LIBISO_ALLOC_MEM(pad, uint8_t, BLOCK_SIZE); for (i = 0; i < t->mspad_blocks; ++i) { ret = iso_write(t, pad, BLOCK_SIZE); if (ret < 0) { goto ex; } } ret = ISO_SUCCESS; ex:; LIBISO_FREE_MEM(pad); return ret; } static int mspad_writer_free_data(IsoImageWriter *writer) { /* nothing to do */ return ISO_SUCCESS; } static int mspad_writer_create(Ecma119Image *target) { IsoImageWriter *writer; writer = malloc(sizeof(IsoImageWriter)); if (writer == NULL) { return ISO_OUT_OF_MEM; } writer->compute_data_blocks = mspad_writer_compute_data_blocks; writer->write_vol_desc = mspad_writer_write_vol_desc; writer->write_data = mspad_writer_write_data; writer->free_data = mspad_writer_free_data; writer->data = NULL; writer->target = target; /* add this writer to image */ target->writers[target->nwriters++] = writer; return ISO_SUCCESS; } /** ----- Zero padding writer ----- */ struct iso_zero_writer_data_struct { uint32_t num_blocks; }; static int zero_writer_compute_data_blocks(IsoImageWriter *writer) { Ecma119Image *target; struct iso_zero_writer_data_struct *data; if (writer == NULL) return ISO_ASSERT_FAILURE; target = writer->target; data = (struct iso_zero_writer_data_struct *) writer->data; target->curblock += data->num_blocks; return ISO_SUCCESS; } static int zero_writer_write_vol_desc(IsoImageWriter *writer) { /* nothing to do */ return ISO_SUCCESS; } static int zero_writer_write_data(IsoImageWriter *writer) { int ret; Ecma119Image *t; struct iso_zero_writer_data_struct *data; uint8_t *pad = NULL; size_t i; if (writer == NULL) {ret = ISO_ASSERT_FAILURE; goto ex;} t = writer->target; data = (struct iso_zero_writer_data_struct *) writer->data; if (data->num_blocks == 0) {ret = ISO_SUCCESS; goto ex;} LIBISO_ALLOC_MEM(pad, uint8_t, BLOCK_SIZE); for (i = 0; i < data->num_blocks; ++i) { ret = iso_write(t, pad, BLOCK_SIZE); if (ret < 0) goto ex; } ret = ISO_SUCCESS; ex:; LIBISO_FREE_MEM(pad); return ret; } static int zero_writer_free_data(IsoImageWriter *writer) { if (writer == NULL) return ISO_SUCCESS; if (writer->data == NULL) return ISO_SUCCESS; free(writer->data); writer->data = NULL; return ISO_SUCCESS; } static int tail_writer_compute_data_blocks(IsoImageWriter *writer) { int ret; Ecma119Image *target; struct iso_zero_writer_data_struct *data; char msg[80]; target = writer->target; ret = iso_align_isohybrid(target, 0); if (ret < 0) return ret; data = (struct iso_zero_writer_data_struct *) writer->data; if (data->num_blocks != target->opts->tail_blocks) { sprintf(msg, "Aligned image size to cylinder size by %d blocks", target->opts->tail_blocks - data->num_blocks); iso_msgs_submit(0, msg, 0, "NOTE", 0); data->num_blocks = target->opts->tail_blocks; } if (target->opts->tail_blocks <= 0) return ISO_SUCCESS; ret = zero_writer_compute_data_blocks(writer); return ret; } /* @param flag bit0= use tail_writer_compute_data_blocks rather than zero_writer_compute_data_blocks */ static int zero_writer_create(Ecma119Image *target, uint32_t num_blocks, int flag) { IsoImageWriter *writer; struct iso_zero_writer_data_struct *data; writer = malloc(sizeof(IsoImageWriter)); if (writer == NULL) { return ISO_OUT_OF_MEM; } data = calloc(1, sizeof(struct iso_zero_writer_data_struct)); if (data == NULL) { free(writer); return ISO_OUT_OF_MEM; } data->num_blocks = num_blocks; if (flag & 1) { writer->compute_data_blocks = tail_writer_compute_data_blocks; } else { writer->compute_data_blocks = zero_writer_compute_data_blocks; } writer->write_vol_desc = zero_writer_write_vol_desc; writer->write_data = zero_writer_write_data; writer->free_data = zero_writer_free_data; writer->data = data; writer->target = target; /* add this writer to image */ target->writers[target->nwriters++] = writer; return ISO_SUCCESS; } /* @param flag bit0= restore preserved cx (else dispose them) */ static int process_preserved_cx(IsoDir *dir, int flag) { int ret, i; unsigned int cx_value; void *xipt; IsoNode *pos; pos = dir->children; for (pos = dir->children; pos != NULL; pos = pos->next) { if (pos->type == LIBISO_FILE) { if (flag & 1) { /* Restore preserved cx state of nodes */ ret = iso_node_get_xinfo(pos, checksum_cx_xinfo_func, &xipt); if (ret == 1) { /* xipt is an int disguised as void pointer */ cx_value = 0; for (i = 0; i < 4; i++) cx_value = (cx_value << 8) | ((unsigned char *) &xipt)[i]; ret = iso_file_set_isofscx((IsoFile *) pos, cx_value, 0); if (ret < 0) return ret; } else if (ret == 0) { /* Node had no cx before the write run. Delete cx. */ iso_file_set_isofscx((IsoFile *) pos, 0, 1); } } iso_node_remove_xinfo(pos, checksum_cx_xinfo_func); } else if (pos->type == LIBISO_DIR) { ret = process_preserved_cx((IsoDir *) pos, flag); if (ret != 0) return ret; } } return 0; } static int transplant_checksum_buffer(Ecma119Image *target, int flag) { /* Transplant checksum buffer from Ecma119Image to IsoImage */ iso_image_set_checksums(target->image, target->checksum_buffer, target->checksum_range_start, target->checksum_array_pos, target->checksum_idx_counter + 2, 0); target->checksum_buffer = NULL; target->checksum_idx_counter = 0; /* Delete recorded cx xinfo */ process_preserved_cx(target->image->root, 0); return 1; } static int write_vol_desc_terminator(Ecma119Image *target) { int ret; uint8_t *buf = NULL; struct ecma119_vol_desc_terminator *vol; LIBISO_ALLOC_MEM(buf, uint8_t, BLOCK_SIZE); vol = (struct ecma119_vol_desc_terminator *) buf; vol->vol_desc_type[0] = 255; memcpy(vol->std_identifier, "CD001", 5); vol->vol_desc_version[0] = 1; ret = iso_write(target, buf, BLOCK_SIZE); ex: LIBISO_FREE_MEM(buf); return ret; } /* @param flag bit0= initialize system area by target->opts_overwrite bit1= fifo is not yet draining. Inquire write_count from fifo. */ static int write_head_part1(Ecma119Image *target, int *write_count, int flag) { int res, i, ret; uint8_t *sa, *sa_local = NULL; IsoImageWriter *writer; size_t buffer_size = 0, buffer_free = 0, buffer_start_free = 0; if (target->sys_area_already_written) { LIBISO_ALLOC_MEM(sa_local, uint8_t, 16 * BLOCK_SIZE); sa = sa_local; } else { sa = target->sys_area_as_written; target->sys_area_already_written = 1; } iso_ring_buffer_get_buf_status(target->buffer, &buffer_size, &buffer_start_free); *write_count = 0; /* Write System Area (ECMA-119, 6.2.1) */ if ((flag & 1) && target->opts_overwrite != NULL) memcpy(sa, target->opts_overwrite, 16 * BLOCK_SIZE); res = iso_write_system_area(target, sa); if (res < 0) goto write_error; res = iso_write(target, sa, 16 * BLOCK_SIZE); if (res < 0) goto write_error; *write_count = 16; /* write volume descriptors, one per writer */ iso_msg_debug(target->image->id, "Write volume descriptors"); for (i = 0; i < (int) target->nwriters; ++i) { writer = target->writers[i]; res = writer->write_vol_desc(writer); if (res < 0) goto write_error; } /* write Volume Descriptor Set Terminator (ECMA-119, 8.3) */ res = write_vol_desc_terminator(target); if (res < 0) goto write_error; if(flag & 2) { iso_ring_buffer_get_buf_status(target->buffer, &buffer_size, &buffer_free); *write_count = ( buffer_start_free - buffer_free ) / BLOCK_SIZE; } else { *write_count = target->bytes_written / BLOCK_SIZE; } ret = ISO_SUCCESS; goto ex; write_error:; ret = res; goto ex; ex: LIBISO_FREE_MEM(sa_local); return ret; } static int write_head_part2(Ecma119Image *target, int *write_count, int flag) { int ret, i; uint8_t *buf = NULL; IsoImageWriter *writer; if (target->opts->partition_offset <= 0) {ret = ISO_SUCCESS; goto ex;} /* Write multi-session padding up to target->opts->partition_offset + 16 */ LIBISO_ALLOC_MEM(buf, uint8_t, BLOCK_SIZE); for(; *write_count < (int) target->opts->partition_offset + 16; (*write_count)++) { ret = iso_write(target, buf, BLOCK_SIZE); if (ret < 0) goto ex; } /* Write volume descriptors subtracting target->partiton_offset from any LBA pointer. */ target->eff_partition_offset = target->opts->partition_offset; for (i = 0; i < (int) target->nwriters; ++i) { writer = target->writers[i]; /* Not all writers have an entry in the partion volume descriptor set. It must be guaranteed that they write exactly one block. */ /* >>> TWINTREE: Enhance ISO1999 writer and add it here */ if(writer->write_vol_desc != ecma119_writer_write_vol_desc && writer->write_vol_desc != joliet_writer_write_vol_desc) continue; ret = writer->write_vol_desc(writer); if (ret < 0) goto ex; (*write_count)++; } ret = write_vol_desc_terminator(target); if (ret < 0) goto ex; (*write_count)++; target->eff_partition_offset = 0; /* >>> TWINTREE: Postponed for now: Write second superblock checksum tag */; ret = ISO_SUCCESS; ex:; if (buf != NULL) free(buf); return ret; } static int write_head_part(Ecma119Image *target, int flag) { int res, write_count = 0; /* System area and volume descriptors */ res = write_head_part1(target, &write_count, 0); if (res < 0) return res; /* Write superblock checksum tag */ if (target->opts->md5_session_checksum && target->checksum_ctx != NULL) { res = iso_md5_write_tag(target, 2); if (res < 0) return res; write_count++; } /* Second set of system area and volume descriptors for partition_offset */ res = write_head_part2(target, &write_count, 0); if (res < 0) return res; return ISO_SUCCESS; } /* Eventually end Jigdo Template Extraction */ static int finish_libjte(Ecma119Image *target) { #ifdef Libisofs_with_libjtE int ret; if (target->opts->libjte_handle != NULL) { ret = libjte_write_footer(target->opts->libjte_handle); if (ret <= 0) { iso_libjte_forward_msgs(target->opts->libjte_handle, target->image->id, ISO_LIBJTE_END_FAILED, 0); return ISO_LIBJTE_END_FAILED; } } #endif /* Libisofs_with_libjtE */ return 1; } /* >>> need opportunity to just mark a partition in the older sessions */ struct iso_interval_zeroizer { int z_type; /* 0= $zero_start"-"$zero_end , 1= "zero_mbrpt" , 2= "zero_gpt" , 3= "zero_apm" */ off_t zero_start; off_t zero_end; }; struct iso_interval_reader { /* Setup */ IsoImage *image; char *path; int flags; /* bit0= imported_iso, else local_fs */ off_t start_byte; off_t end_byte; struct iso_interval_zeroizer *zeroizers; int num_zeroizers; char *source_pt; /* This is a parasite pointer of path. Do not free */ /* State information */ int initialized; int is_block_aligned; off_t cur_block; int fd; uint8_t read_buf[BLOCK_SIZE]; uint8_t *pending_read_pt; int pending_read_bytes; off_t read_count; int eof; int src_is_open; uint32_t apm_block_size; }; static int iso_ivr_next_comp(char *read_pt, char **next_pt, int flag) { *next_pt = NULL; if (read_pt == NULL) return 0; *next_pt = strchr(read_pt, ':'); if (*next_pt != NULL) (*next_pt)++; return 1; } /* @param flag bit1= end number requested, forward to iso_scanf_io_size() */ static int iso_ivr_read_number(char *start_pt, char *end_pt, off_t *result, int flag) { char txt[20]; off_t num; if (end_pt - start_pt <= 0 || end_pt - start_pt > 16) { iso_msg_submit(-1, ISO_MALFORMED_READ_INTVL, 0, "Number text too short or too long in interval reader description string"); return ISO_MALFORMED_READ_INTVL; } if (end_pt - start_pt > 0) strncpy(txt, start_pt, end_pt - start_pt); txt[end_pt - start_pt] = 0; num = iso_scanf_io_size(start_pt, 1 | (flag & 2)); if (num < 0.0 || num > 281474976710655.0) { iso_msg_submit(-1, ISO_MALFORMED_READ_INTVL, 0, "Negative or overly large number in interval reader description string"); return ISO_MALFORMED_READ_INTVL; } *result = num; return 1; } static int iso_ivr_parse_interval(char *start_pt, char *end_pt, off_t *start_byte, off_t *end_byte, int flag) { int ret; char *m_pt; m_pt = strchr(start_pt, '-'); if (m_pt == NULL) { iso_msg_submit(-1, ISO_MALFORMED_READ_INTVL, 0, "Malformed byte interval in interval reader description string"); return ISO_MALFORMED_READ_INTVL; } ret = iso_ivr_read_number(start_pt, m_pt, start_byte, 0); if (ret < 0) return ret; ret = iso_ivr_read_number(m_pt + 1, end_pt - 1, end_byte, 2); if (ret < 0) return ret; return ISO_SUCCESS; } static int iso_ivr_parse_zeroizers(struct iso_interval_reader *ivr, char *pathpt, char *end_pt, int flag) { int ret, num_zs = 1, idx, i; char *rpt, *cpt; ivr->num_zeroizers = 0; if (pathpt[0] == 0 || pathpt == end_pt) return ISO_SUCCESS; for(cpt = pathpt - 1; cpt != NULL && cpt < end_pt; num_zs++) cpt = strchr(cpt + 1, ','); LIBISO_ALLOC_MEM(ivr->zeroizers, struct iso_interval_zeroizer, num_zs); for (i = 0; i < num_zs; i++) ivr->zeroizers[i].zero_end = -1; idx = 0; for (rpt = pathpt; rpt != NULL && rpt < end_pt; idx++) { cpt = strchr(rpt, ','); if (cpt == NULL || cpt > end_pt) cpt = end_pt; if (cpt == rpt) { continue; } else if (strncmp(rpt, "zero_mbrpt", cpt - rpt) == 0) { ivr->zeroizers[idx].z_type = 1; } else if (strncmp(rpt, "zero_gpt", cpt - rpt) == 0) { ivr->zeroizers[idx].z_type = 2; } else if (strncmp(rpt, "zero_apm", cpt - rpt) == 0) { ivr->zeroizers[idx].z_type = 3; } else { ivr->zeroizers[idx].z_type = 0; ret = iso_ivr_parse_interval(rpt, cpt, &(ivr->zeroizers[idx].zero_start), &(ivr->zeroizers[idx].zero_end), 0); if (ret < 0) goto ex; } rpt = cpt + 1; ivr->num_zeroizers++; } ret = ISO_SUCCESS; ex:; return ret; } static int iso_ivr_parse(struct iso_interval_reader *ivr, char *path, int flag) { int ret; char *flags_pt, *interval_pt, *zeroize_pt; flags_pt = path; iso_ivr_next_comp(flags_pt, &interval_pt, 0); iso_ivr_next_comp(interval_pt, &zeroize_pt, 0); iso_ivr_next_comp(zeroize_pt, &(ivr->source_pt), 0); if (ivr->source_pt == NULL) { iso_msg_submit(-1, ISO_MALFORMED_READ_INTVL, 0, "Not enough components in interval reader description string"); return ISO_MALFORMED_READ_INTVL; } ivr->flags = 0; if (strncmp(flags_pt, "imported_iso", 12) == 0) { ivr->flags |= 1; } else if (strncmp(flags_pt, "local_fs", 8) == 0) { ; } else { iso_msg_submit(-1, ISO_MALFORMED_READ_INTVL, 0, "Unknown flag name in first component of interval reader description string"); return ISO_MALFORMED_READ_INTVL; } ret = iso_ivr_parse_interval(interval_pt, zeroize_pt, &(ivr->start_byte), &(ivr->end_byte), 0); if (ret < 0) goto ex; ret = iso_ivr_parse_zeroizers(ivr, zeroize_pt, ivr->source_pt - 1, 0); if (ret < 0) goto ex; ret = ISO_SUCCESS; ex:; return ret; } int iso_interval_reader_destroy(struct iso_interval_reader **ivr, int flag) { struct iso_interval_reader *o; if (*ivr == NULL) return 0; o = *ivr; LIBISO_FREE_MEM(o->path); LIBISO_FREE_MEM(o->zeroizers); if (o->fd != -1) close(o->fd); if (o->src_is_open) (*o->image->import_src->close)(o->image->import_src); LIBISO_FREE_MEM(*ivr); return ISO_SUCCESS; } /* @param flag bit0= tolerate lack of import_src */ int iso_interval_reader_new(IsoImage *img, char *path, struct iso_interval_reader **ivr, off_t *byte_count, int flag) { int ret, no_img = 0; struct iso_interval_reader *o = NULL; *ivr = NULL; *byte_count = 0; LIBISO_ALLOC_MEM(o, struct iso_interval_reader, 1); o->image = img; o->path = NULL; o->zeroizers = NULL; o->num_zeroizers = 0; o->source_pt = NULL; o->initialized = 0; o->is_block_aligned = 0; o->fd = -1; o->pending_read_pt = NULL; o->pending_read_bytes = 0; o->eof = 0; o->read_count = 0; o->src_is_open = 0; o->apm_block_size = 0; LIBISO_ALLOC_MEM(o->path, char, strlen(path) + 1); strcpy(o->path, path); ret = iso_ivr_parse(o, path, 0); if (ret < 0) goto ex; if (o->image == NULL) no_img = 1; else if (o->image->import_src == NULL) no_img = 1; if ((o->flags & 1) && no_img) { iso_msg_submit(-1, ISO_NO_KEPT_DATA_SRC, 0, "Interval reader lacks of data source object of imported ISO"); if (!(flag & 1)) { ret = ISO_BAD_PARTITION_FILE; goto ex; } o->eof = 1; } *byte_count = o->end_byte - o->start_byte + 1; *ivr = o; ret = ISO_SUCCESS; ex:; if (ret < 0) iso_interval_reader_destroy(&o, 0); return ret; } static int iso_ivr_zeroize(struct iso_interval_reader *ivr, uint8_t *buf, int buf_fill, int flag) { int i; off_t low, high, part_start, entry_count, apm_offset = -1, map_entries; uint8_t *apm_buf; struct iso_interval_zeroizer *zr; for (i = 0; i < ivr->num_zeroizers; i++) { zr = ivr->zeroizers + i; if (zr->z_type == 1) { /* zero_mbrpt */ if (ivr->read_count > 0 || buf_fill < 512) continue; if (buf[510] != 0x55 || buf[511] != 0xaa) continue; memset(buf + 446, 0, 64); } else if (zr->z_type == 2) { /* zero_gpt */ if (zr->zero_start <= zr->zero_end) goto process_interval; if (ivr->read_count > 0 || buf_fill < 512 + 92) continue; if (strncmp((char *) buf + 512, "EFI PART", 8) != 0 || buf[520] != 0 || buf[521] != 0 || buf[522] != 1 || buf[523] != 0) continue; /* head_size , curr_lba , entry_size */ if (iso_read_lsb(buf + 524, 4) != 92 || iso_read_lsb(buf + 536, 4) != 1 || iso_read_lsb(buf + 596, 4) != 128) continue; part_start = iso_read_lsb(buf + 584, 4); entry_count = iso_read_lsb(buf + 592, 4); if (part_start < 2 || part_start + (entry_count + 3) / 4 > 64) continue; zr->zero_start = part_start * 512; zr->zero_end = (part_start + (entry_count + 3) / 4) * 512 - 1; memset(buf + 512, 0, 92); } else if (zr->z_type == 3) { /* zero_apm */ if (zr->zero_start <= zr->zero_end) goto process_interval; if (ivr->read_count == 0) { if (buf_fill < 512) continue; if (buf[0] != 'E' || buf[1] != 'R') continue; ivr->apm_block_size = iso_read_msb(buf + 2, 2); if ((ivr->apm_block_size != 512 && ivr->apm_block_size != 1024 && ivr->apm_block_size != 2048) || ((uint32_t) buf_fill) < ivr->apm_block_size) { ivr->apm_block_size = 0; continue; } if (ivr->read_count + buf_fill >= 2 * ivr->apm_block_size) apm_offset = ivr->apm_block_size; } else if (ivr->read_count == 2048 && ivr->apm_block_size == 2048 && buf_fill == 2048) { apm_offset = 0; } if (apm_offset < 0) continue; /* Check for first APM entry */ apm_buf = buf + apm_offset; if(apm_buf[0] != 'P' || apm_buf[1] != 'M') continue; if (iso_read_msb(apm_buf + 8, 4) != 1) continue; map_entries = iso_read_msb(apm_buf + 4, 4); if ((1 + map_entries) * ivr->apm_block_size > 16 * 2048) continue; zr->zero_start = ivr->apm_block_size; zr->zero_end = (1 + map_entries) * ivr->apm_block_size; } process_interval:; /* If an interval is defined by now: zeroize its intersection with buf */ if (zr->zero_start <= zr->zero_end) { low = ivr->read_count >= zr->zero_start ? ivr->read_count : zr->zero_start; high = ivr->read_count + buf_fill - 1 <= zr->zero_end ? ivr->read_count + buf_fill - 1 : zr->zero_end; if (low <= high) memset(buf + low - ivr->read_count, 0, high - low + 1); } } return ISO_SUCCESS; } int iso_interval_reader_read(struct iso_interval_reader *ivr, uint8_t *buf, int *buf_fill, int flag) { int ret, read_done, to_copy, initializing = 0; IsoDataSource *src; uint8_t *read_buf; off_t to_read; *buf_fill = 0; src = ivr->image->import_src; if (ivr->eof) { eof:; memset(buf, 0, BLOCK_SIZE); return 0; } if (ivr->initialized) { ivr->cur_block++; } else { initializing = 1; ivr->cur_block = ivr->start_byte / BLOCK_SIZE; ivr->is_block_aligned = !(ivr->start_byte % BLOCK_SIZE); if (ivr->flags & 1) { if (src == NULL) goto eof; ret = (*src->open)(src); if (ret < 0) { ivr->eof = 1; return ret; } ivr->src_is_open = 1; } else { ivr->fd = open(ivr->source_pt, O_RDONLY); if (ivr->fd == -1) { iso_msg_submit(-1, ISO_BAD_PARTITION_FILE, 0, "Cannot open local file for interval reading"); ivr->eof = 1; return ISO_BAD_PARTITION_FILE; } if (ivr->cur_block != 0) { if (lseek(ivr->fd, ivr->cur_block * BLOCK_SIZE, SEEK_SET) == -1) { iso_msg_submit(-1, ISO_INTVL_READ_PROBLEM, 0, "Cannot address interval start in local file"); ivr->eof = 1; goto eof; } } } ivr->initialized = 1; } if (ivr->is_block_aligned) { read_buf = buf; } else { process_pending:; read_buf = ivr->read_buf; /* Copy pending bytes from previous read */ if (ivr->pending_read_bytes > 0) { memcpy(buf, ivr->pending_read_pt, ivr->pending_read_bytes); *buf_fill = ivr->pending_read_bytes; ivr->pending_read_bytes = 0; } } /* Read next block */ read_done = 0; if (ivr->cur_block * BLOCK_SIZE <= ivr->end_byte) { if (ivr->flags & 1) { ret = (*src->read_block)(src, (uint32_t) ivr->cur_block, read_buf); if (ret < 0) { if (iso_error_get_severity(ret) > 0x68000000) /* > FAILURE */ return ret; iso_msg_submit(-1, ISO_INTVL_READ_PROBLEM, 0, "Premature EOF while interval reading from imported ISO"); ivr->eof = 1; } read_done = BLOCK_SIZE; } else { read_done = 0; to_read = ivr->end_byte - ivr->start_byte + 1 - ivr->read_count; if (to_read > BLOCK_SIZE) to_read = BLOCK_SIZE; while (read_done < to_read) { ret = read(ivr->fd, read_buf, to_read - read_done); if (ret == -1) { iso_msg_submit(-1, ISO_INTVL_READ_PROBLEM, 0, "Read error while interval reading from local file"); ivr->eof = 1; break; } else if (ret == 0) { iso_msg_submit(-1, ISO_INTVL_READ_PROBLEM, 0, "Premature EOF while interval reading from local file"); ivr->eof = 1; break; } else read_done += ret; } } } if (ivr->is_block_aligned) { *buf_fill = read_done; } else if (initializing) { ivr->pending_read_pt = ivr->read_buf + (ivr->start_byte - ivr->cur_block * BLOCK_SIZE); ivr->pending_read_bytes = (((off_t) ivr->cur_block) + 1) * BLOCK_SIZE - ivr->start_byte; initializing = 0; goto process_pending; } else if (read_done > 0) { /* Copy bytes from new read */ to_copy = read_done > BLOCK_SIZE - *buf_fill ? BLOCK_SIZE - *buf_fill : read_done; memcpy(buf + *buf_fill, ivr->read_buf, to_copy); *buf_fill += to_copy; ivr->pending_read_pt = ivr->read_buf + to_copy; ivr->pending_read_bytes = read_done - to_copy; } if (ivr->start_byte + ivr->read_count + *buf_fill - 1 > ivr->end_byte) { *buf_fill = ivr->end_byte - ivr->start_byte + 1 - ivr->read_count; ivr->eof = 1; } if (*buf_fill < BLOCK_SIZE) memset(buf + *buf_fill, 0, BLOCK_SIZE - *buf_fill); ret = iso_ivr_zeroize(ivr, buf, *buf_fill, 0); if (ret < 0) return ret; ivr->read_count += *buf_fill; return ISO_SUCCESS; } int iso_write_partition_file(Ecma119Image *target, char *path, uint32_t prepad, uint32_t blocks, int flag) { struct iso_interval_reader *ivr = NULL; int buf_fill; off_t byte_count; FILE *fp = NULL; uint32_t i; uint8_t *buf = NULL; int ret; LIBISO_ALLOC_MEM(buf, uint8_t, BLOCK_SIZE); for (i = 0; i < prepad; i++) { ret = iso_write(target, buf, BLOCK_SIZE); if (ret < 0) goto ex; } if (flag & 1) { ret = iso_interval_reader_new(target->image, path, &ivr, &byte_count, 0); if (ret < 0) goto ex; for (i = 0; i < blocks; i++) { ret = iso_interval_reader_read(ivr, buf, &buf_fill, 0); if (ret < 0) goto ex; ret = iso_write(target, buf, BLOCK_SIZE); if (ret < 0) goto ex; } } else { fp = fopen(path, "rb"); if (fp == NULL) {ret = ISO_BAD_PARTITION_FILE; goto ex;} for (i = 0; i < blocks; i++) { memset(buf, 0, BLOCK_SIZE); if (fp != NULL) { ret = fread(buf, 1, BLOCK_SIZE, fp); if (ret != BLOCK_SIZE) { fclose(fp); fp = NULL; } } ret = iso_write(target, buf, BLOCK_SIZE); if (ret < 0) { if (fp != NULL) fclose(fp); goto ex; } } if (fp != NULL) fclose(fp); } ret = ISO_SUCCESS; ex:; iso_interval_reader_destroy(&ivr, 0); LIBISO_FREE_MEM(buf); return ret; } void issue_ucs2_warning_summary(size_t failures) { if (failures > ISO_JOLIET_UCS2_WARN_MAX) { iso_msg_submit(-1, ISO_NAME_NOT_UCS2, 0, "More filenames found which were not suitable for Joliet character set UCS-2"); } if (failures > 0) { iso_msg_submit(-1, ISO_NAME_NOT_UCS2, 0, "Sum of filenames not suitable for Joliet character set UCS-2: %.f", (double) failures); } } static void *write_function(void *arg) { int res, i; #ifndef Libisofs_appended_partitions_inlinE int first_partition = 1, last_partition = 0, sa_type; #endif IsoImageWriter *writer; Ecma119Image *target = (Ecma119Image*)arg; iso_msg_debug(target->image->id, "Starting image writing..."); target->bytes_written = (off_t) 0; target->percent_written = 0; res = write_head_part(target, 0); if (res < 0) goto write_error; /* write data for each writer */ for (i = 0; i < (int) target->nwriters; ++i) { writer = target->writers[i]; if (target->gpt_backup_outside && writer->write_vol_desc == gpt_tail_writer_write_vol_desc) continue; res = writer->write_data(writer); if (res < 0) { goto write_error; } } #ifndef Libisofs_appended_partitions_inlinE /* Append partition data */ sa_type = (target->system_area_options >> 2) & 0x3f; if (sa_type == 0) { /* MBR */ first_partition = 1; last_partition = 4; } else if (sa_type == 3) { /* SUN Disk Label */ first_partition = 2; last_partition = 8; } for (i = first_partition - 1; i <= last_partition - 1; i++) { if (target->opts->appended_partitions[i] == NULL) continue; if (target->opts->appended_partitions[i][0] == 0) continue; res = iso_write_partition_file(target, target->opts->appended_partitions[i], target->appended_part_prepad[i], target->appended_part_size[i], target->opts->appended_part_flags[i] & 1); if (res < 0) goto write_error; } #endif /* ! Libisofs_appended_partitions_inlinE */ if (target->gpt_backup_outside) { for (i = 0; i < (int) target->nwriters; ++i) { writer = target->writers[i]; if (writer->write_vol_desc != gpt_tail_writer_write_vol_desc) continue; res = writer->write_data(writer); if (res < 0) goto write_error; } } /* Transplant checksum buffer from Ecma119Image to IsoImage */ transplant_checksum_buffer(target, 0); iso_ring_buffer_writer_close(target->buffer, 0); res = finish_libjte(target); if (res <= 0) goto write_error; issue_ucs2_warning_summary(target->joliet_ucs2_failures); target->image->generator_is_running = 0; /* Give up reference claim made in ecma119_image_new(). Eventually free target */ ecma119_image_free(target); if (target->tree_end_block == 1) { iso_msgs_submit(0, "Image is most likely damaged. Calculated/written tree end address mismatch.", 0, "FATAL", 0); } if (target->bytes_written != target->total_size) { iso_msg_debug(target->image->id, "bytes_written = %.f <-> total_size = %.f", (double) target->bytes_written, (double) target->total_size); iso_msgs_submit(0, "Image is most likely damaged. Calculated/written image end address mismatch.", 0, "FATAL", 0); } #ifdef Libisofs_with_pthread_exiT pthread_exit(NULL); #else return NULL; #endif write_error: ; if (res != (int) ISO_LIBJTE_END_FAILED) finish_libjte(target); target->eff_partition_offset = 0; if (res == (int) ISO_CANCELED) { /* canceled */ if (!target->opts->will_cancel) iso_msg_submit(target->image->id, ISO_IMAGE_WRITE_CANCELED, 0, NULL); } else { /* image write error */ iso_msg_submit(target->image->id, ISO_WRITE_ERROR, res, "Image write error"); } iso_ring_buffer_writer_close(target->buffer, 1); /* Re-activate recorded cx xinfo */ process_preserved_cx(target->image->root, 1); target->image->generator_is_running = 0; /* Give up reference claim made in ecma119_image_new(). Eventually free target */ ecma119_image_free(target); #ifdef Libisofs_with_pthread_exiT pthread_exit(NULL); #else return NULL; #endif } static int checksum_prepare_image(IsoImage *src, int flag) { int ret; /* Set provisory value of isofs.ca with 4 byte LBA, 4 byte count, size 16, name MD5 */ ret = iso_root_set_isofsca((IsoNode *) src->root, 0, 0, 0, 16, "MD5", 0); if (ret < 0) return ret; return ISO_SUCCESS; } /* @flag bit0= recursion */ static int checksum_prepare_nodes(Ecma119Image *target, IsoNode *node, int flag) { IsoNode *pos; IsoFile *file; IsoImage *img; int ret, i, no_md5 = 0, has_xinfo = 0, has_attr = 0; size_t old_cx_value_length = 0; unsigned int idx = 0; char *old_cx_value= NULL; void *xipt = NULL; img= target->image; if (node->type == LIBISO_FILE) { file = (IsoFile *) node; if (file->from_old_session) { /* Record attribute isofs.cx as xinfo before it can get overwritten for the emerging image. The recorded index will be used to retrieve the loaded MD5 and it will be brought back into effect if cancellation of image production prevents that the old MD5 array gets replaced by the new one. */ has_attr = iso_node_lookup_attr(node, "isofs.cx", &old_cx_value_length, &old_cx_value, 0); if (has_attr == 1 && old_cx_value_length == 4) { for (i = 0; i < 4; i++) idx = (idx << 8) | ((unsigned char *) old_cx_value)[i]; if (idx > 0 && idx < 0x8000000) { /* xipt is an int disguised as void pointer */ for (i = 0; i < 4; i++) ((char *) &xipt)[i] = old_cx_value[i]; ret = iso_node_add_xinfo(node, checksum_cx_xinfo_func, xipt); if (ret < 0) goto ex; } else no_md5 = 1; } } if (file->from_old_session && target->opts->appendable) { /* Save MD5 data of files from old image which will not be copied and have an MD5 recorded in the old image. */ has_xinfo = iso_node_get_xinfo(node, checksum_md5_xinfo_func, &xipt); if (has_xinfo > 0) { /* xinfo MD5 overrides everything else unless data get copied and checksummed during that copying */; } else if (has_attr == 1 && img->checksum_array == NULL) { /* No checksum array loaded. Delete "isofs.cx" */ if (!target->opts->will_cancel) iso_file_set_isofscx((IsoFile *) node, 0, 1); no_md5 = 1; } else if (!(has_attr == 1 && old_cx_value_length == 4)) { no_md5 = 1; } } /* Equip nodes with provisory isofs.cx numbers: 4 byte, all 0. Omit those from old image which will not be copied and have no MD5. Do not alter the nodes if this is only a will_cancel run. */ if (!(target->opts->will_cancel || no_md5)) { /* Record provisory new index */ ret = iso_file_set_isofscx(file, (unsigned int) 0, 0); if (ret < 0) goto ex; } } else if (node->type == LIBISO_DIR) { for (pos = ((IsoDir *) node)->children; pos != NULL; pos = pos->next) { ret = checksum_prepare_nodes(target, pos, 1); if (ret < 0) goto ex; } } ret = ISO_SUCCESS; ex:; if (old_cx_value != NULL) free(old_cx_value); return ret; } static int ecma119_image_new(IsoImage *src, IsoWriteOpts *in_opts, Ecma119Image **img) { int ret, i, voldesc_size, nwriters, tag_pos; int sa_type; Ecma119Image *target; IsoWriteOpts *opts; IsoImageWriter *writer; int file_src_writer_index = -1; int system_area_options = 0; char *system_area = NULL; int write_count = 0, write_count_mem; /* 1. Allocate target and attach a copy of in_opts there */ target = calloc(1, sizeof(Ecma119Image)); if (target == NULL) { return ISO_OUT_OF_MEM; } /* This reference will be transfered to the burn_source and released by bs_free_data. */ target->refcount = 1; target->opts = NULL; /* Record a copy of in_opts. It is a copy because in_opts is prone to manipulations from the application thread while the image production thread is running. */ ret = iso_write_opts_clone(in_opts, &(target->opts), 0); if (ret != ISO_SUCCESS) goto target_cleanup; opts = target->opts; /* create the tree for file caching */ ret = iso_rbtree_new(iso_file_src_cmp, &(target->files)); if (ret < 0) { goto target_cleanup; } target->ecma119_hidden_list = NULL; target->image = src; iso_image_ref(src); target->rr_reloc_node = NULL; target->replace_uid = opts->replace_uid ? 1 : 0; target->replace_gid = opts->replace_gid ? 1 : 0; target->replace_dir_mode = opts->replace_dir_mode ? 1 : 0; target->replace_file_mode = opts->replace_file_mode ? 1 : 0; target->uid = opts->replace_uid == 2 ? opts->uid : 0; target->gid = opts->replace_gid == 2 ? opts->gid : 0; target->dir_mode = opts->replace_dir_mode == 2 ? opts->dir_mode : 0555; target->file_mode = opts->replace_file_mode == 2 ? opts->file_mode : 0444; target->now = time(NULL); target->replace_timestamps = opts->replace_timestamps ? 1 : 0; target->timestamp = opts->replace_timestamps == 2 ? opts->timestamp : target->now; /* el-torito? */ target->eltorito = (src->bootcat == NULL ? 0 : 1); target->catalog = src->bootcat; if (target->catalog != NULL) { target->num_bootsrc = target->catalog->num_bootimages; target->bootsrc = calloc(target->num_bootsrc + 1, sizeof(IsoFileSrc *)); if (target->bootsrc == NULL) { ret = ISO_OUT_OF_MEM; goto target_cleanup; } for (i= 0; i < target->num_bootsrc; i++) target->bootsrc[i] = NULL; } else { target->num_bootsrc = 0; target->bootsrc = NULL; } if (opts->system_area_data != NULL) { system_area = opts->system_area_data; system_area_options = opts->system_area_options; } else if (src->system_area_data != NULL) { system_area = src->system_area_data; system_area_options = src->system_area_options; } else { system_area_options = opts->system_area_options & 0xfffffffc; } sa_type = (system_area_options >> 2) & 0x3f; if (sa_type != 0 && sa_type != 3) for (i = 0; i < ISO_MAX_PARTITIONS; i++) if (opts->appended_partitions[i] != NULL) { ret = ISO_NON_MBR_SYS_AREA; goto target_cleanup; } if (sa_type != 0 && opts->prep_partition != NULL) { ret = ISO_NON_MBR_SYS_AREA; goto target_cleanup; } target->system_area_data = NULL; if (system_area != NULL) { target->system_area_data = calloc(32768, 1); if (target->system_area_data == NULL) { ret = ISO_OUT_OF_MEM; goto target_cleanup; } memcpy(target->system_area_data, system_area, 32768); } target->system_area_options = system_area_options; target->partition_secs_per_head = opts->partition_secs_per_head; target->partition_heads_per_cyl = opts->partition_heads_per_cyl; if (target->partition_secs_per_head == 0) target->partition_secs_per_head = 32; if (target->partition_heads_per_cyl == 0) target->partition_heads_per_cyl = 64; target->eff_partition_offset = 0; target->partition_root = NULL; target->partition_l_table_pos = 0; target->partition_m_table_pos = 0; target->j_part_root = NULL; target->j_part_l_path_table_pos = 0; target->j_part_m_path_table_pos = 0; target->input_charset = strdup(iso_get_local_charset(0)); if (target->input_charset == NULL) { ret = ISO_OUT_OF_MEM; goto target_cleanup; } if (opts->output_charset != NULL) { target->output_charset = strdup(opts->output_charset); } else { target->output_charset = strdup(target->input_charset); } if (target->output_charset == NULL) { ret = ISO_OUT_OF_MEM; goto target_cleanup; } target->checksum_idx_counter = 0; target->checksum_ctx = NULL; target->checksum_counter = 0; target->checksum_rlsb_tag_pos = 0; target->checksum_sb_tag_pos = 0; target->checksum_tree_tag_pos = 0; target->checksum_tag_pos = 0; target->checksum_buffer = NULL; target->checksum_array_pos = 0; target->checksum_range_start = 0; target->checksum_range_size = 0; target->opts_overwrite = NULL; #ifdef Libisofs_with_libjtE /* Eventually start Jigdo Template Extraction */ if (opts->libjte_handle != NULL) { ret = libjte_write_header(opts->libjte_handle); if (ret <= 0) { iso_libjte_forward_msgs(opts->libjte_handle, target->image->id, ISO_LIBJTE_START_FAILED, 0); ret = ISO_LIBJTE_START_FAILED; goto target_cleanup; } } #endif /* Libisofs_with_libjtE */ target->mipsel_e_entry = 0; target->mipsel_p_offset = 0; target->mipsel_p_vaddr = 0; target->mipsel_p_filesz = 0; target->sparc_core_src = NULL; target->empty_file_block = 0; target->tree_end_block = 0; target->wthread_is_running = 0; target->post_iso_part_pad = 0; target->prep_part_size = 0; target->efi_boot_part_size = 0; target->efi_boot_part_filesrc = NULL; for (i = 0; i < ISO_MAX_PARTITIONS; i++) { target->appended_part_prepad[i] = 0; target->appended_part_start[i] = target->appended_part_size[i] = 0; } target->have_appended_partitions = 0; for (i = 0; i < ISO_HFSPLUS_BLESS_MAX; i++) { target->hfsplus_blessed[i] = src->hfsplus_blessed[i]; if (target->hfsplus_blessed[i] != NULL) iso_node_ref(target->hfsplus_blessed[i]); } target->hfsp_cat_node_size = 0; target->hfsp_iso_block_fac = 0; target->hfsp_collision_count = 0; target->apm_req_count = 0; target->apm_req_flags = 0; for (i = 0; i < ISO_APM_ENTRIES_MAX; i++) target->apm_req[i] = NULL; for (i = 0; i < ISO_MBR_ENTRIES_MAX; i++) target->mbr_req[i] = NULL; target->mbr_req_count = 0; for (i = 0; i < ISO_GPT_ENTRIES_MAX; i++) target->gpt_req[i] = NULL; target->gpt_req_count = 0; target->gpt_req_flags = 0; target->gpt_backup_outside = 0; target->gpt_disk_guid_set = 0; target->gpt_part_start = 0; target->gpt_backup_end = 0; target->gpt_backup_size = 0; target->gpt_max_entries = 0; target->gpt_is_computed = 0; target->sys_area_already_written = 0; target->filesrc_start = 0; target->filesrc_blocks = 0; target->joliet_ucs2_failures = 0; /* If partitions get appended, then the backup GPT cannot be part of the ISO filesystem. */ for (i = 0; i < ISO_MAX_PARTITIONS; i++) if (target->opts->appended_partitions[i] != NULL) { target->gpt_backup_outside = 1; target->have_appended_partitions = 1; break; } ret = iso_root_set_isofsnt((IsoNode *) (src->root), (uint32_t) src->truncate_mode, (uint32_t) src->truncate_length, 0); if (ret < 0) goto target_cleanup; /* * 2. Based on those options, create needed writers: iso, joliet... * Each writer inits its structures and stores needed info into * target. * If the writer needs an volume descriptor, it increments image * current block. * Finally, create Writer for files. */ target->curblock = opts->ms_block + 16; if (opts->overwrite != NULL && opts->ms_block != 0 && opts->ms_block < opts->partition_offset + 32) { /* Not enough room for superblock relocation */ ret = ISO_OVWRT_MS_TOO_SMALL; goto target_cleanup; } /* the number of writers is dependent of the extensions */ nwriters = 1 + 1 + 1; /* ECMA-119 + multi-session padding + files */ if (target->eltorito) { nwriters++; } if (opts->joliet) { nwriters++; } if (opts->iso1999) { nwriters++; } nwriters++; /* Partition Prepend writer */ if (opts->hfsplus || opts->fat) { nwriters+= 2; } #ifdef Libisofs_appended_partitions_inlinE nwriters++; /* Inline Partition Append Writer */ #endif nwriters++; /* GPT backup tail writer */ nwriters++; /* Tail padding writer */ if ((opts->md5_file_checksums & 1) || opts->md5_session_checksum) { nwriters++; ret = checksum_prepare_image(src, 0); if (ret < 0) goto target_cleanup; if (opts->appendable) { ret = checksum_prepare_nodes(target, (IsoNode *) src->root, 0); if (ret < 0) goto target_cleanup; } target->checksum_idx_counter = 0; } target->writers = malloc(nwriters * sizeof(void*)); if (target->writers == NULL) { ret = ISO_OUT_OF_MEM; goto target_cleanup; } /* create writer for ECMA-119 structure */ ret = ecma119_writer_create(target); if (ret < 0) { goto target_cleanup; } /* create writer for El-Torito */ if (target->eltorito) { ret = eltorito_writer_create(target); if (ret < 0) { goto target_cleanup; } } /* create writer for Joliet structure */ if (opts->joliet) { ret = joliet_writer_create(target); if (ret < 0) { goto target_cleanup; } } /* create writer for ISO 9660:1999 structure */ if (opts->iso1999) { ret = iso1999_writer_create(target); if (ret < 0) { goto target_cleanup; } } voldesc_size = target->curblock - opts->ms_block - 16; /* Volume Descriptor Set Terminator */ target->curblock++; /* All empty files point to the Volume Descriptor Set Terminator * rather than to addresses of non-empty files. */ target->empty_file_block = target->curblock - 1; /* * Create the writer for possible padding to ensure that in case of image * growing we can safely overwrite the first 64 KiB of image. */ ret = mspad_writer_create(target); if (ret < 0) { goto target_cleanup; } /* The writer for MBR and GPT partitions outside iso_file_src. * If PreP or FAT are desired, it creates MBR partition entries and * surrounding protecting partition entries. * If EFI boot partition is desired, it creates a GPT entry for it. */ ret = partprepend_writer_create(target); if (ret < 0) goto target_cleanup; /* create writer for HFS+/FAT structure */ /* Impotant: It must be created directly before iso_file_src_writer_create. */ if (opts->hfsplus || opts->fat) { ret = hfsplus_writer_create(target); if (ret < 0) { goto target_cleanup; } } /* create writer for file contents */ ret = iso_file_src_writer_create(target); if (ret < 0) { goto target_cleanup; } file_src_writer_index = target->nwriters - 1; /* create writer for HFS+ structure */ if (opts->hfsplus || opts->fat) { ret = hfsplus_tail_writer_create(target); if (ret < 0) { goto target_cleanup; } } /* >>> Decide whether the GPT tail writer can be the last of all */ #define Libisofs_gpt_writer_lasT yes #ifndef Libisofs_gpt_writer_lasT /* This writer has to be added to the list after any writer which might request production of APM or GPT partition entries by its compute_data_blocks() method. Its compute_data_blocks() fills the gaps in APM requests. It determines the position of primary GPT and backup GPT. Further it reserves blocks for the backup GPT. */ ret = gpt_tail_writer_create(target); if (ret < 0) goto target_cleanup; #endif /* ! Libisofs_gpt_writer_lasT */ /* >>> Should not the checksum writer come before the zero writer ? */ #define Libisofs_checksums_before_paddinG yes #ifndef Libisofs_checksums_before_paddinG /* >>> ??? Why is this important ? */ /* IMPORTANT: This must be the last writer before the checksum writer */ ret = zero_writer_create(target, opts->tail_blocks, 1); if (ret < 0) goto target_cleanup; #endif /* !Libisofs_checksums_before_paddinG */ if ((opts->md5_file_checksums & 1) || opts->md5_session_checksum) { ret = checksum_writer_create(target); if (ret < 0) goto target_cleanup; } #ifdef Libisofs_checksums_before_paddinG ret = zero_writer_create(target, opts->tail_blocks, 1); if (ret < 0) goto target_cleanup; #endif /* Libisofs_checksums_before_paddinG */ #ifdef Libisofs_appended_partitions_inlinE ret = partappend_writer_create(target); if (ret < 0) goto target_cleanup; #endif /* Libisofs_appended_partitions_inlinE */ #ifdef Libisofs_gpt_writer_lasT /* This writer shall be the last one in the list, because it protects the image on media which are seen as GPT partitioned. In any case it has to come after any writer which might request production of APM or GPT partition entries by its compute_data_blocks() method. gpt_tail_writer_compute_data_blocks() fills the gaps in APM requests. It determines the position of primary GPT and backup GPT. Further it reserves blocks for the backup GPT. */ ret = gpt_tail_writer_create(target); if (ret < 0) goto target_cleanup; #endif /* Libisofs_gpt_writer_lasT */ if (opts->partition_offset > 0) { /* After volume descriptors and superblock tag are accounted for: account for second volset */ if (opts->ms_block + opts->partition_offset + 16 < target->curblock) { /* Overflow of partition system area */ ret = ISO_PART_OFFST_TOO_SMALL; goto target_cleanup; } target->curblock = opts->ms_block + opts->partition_offset + 16; /* Account for partition tree volume descriptors */ for (i = 0; i < (int) target->nwriters; ++i) { /* Not all writers have an entry in the partition volume descriptor set. */ writer = target->writers[i]; /* >>> TWINTREE: Enhance ISO1999 writer and add it here */ if(writer->write_vol_desc != ecma119_writer_write_vol_desc && writer->write_vol_desc != joliet_writer_write_vol_desc) continue; target->curblock++; } target->curblock++; /* + Terminator */ /* >>> TWINTREE: eventually later : second superblock checksum tag */; } /* At least the FAT computation needs to know the size of filesrc data in advance. So this call produces target->filesrc_blocks and relative extent addresses, which get absolute in filesrc_writer_compute_data_blocks(). */ ret = filesrc_writer_pre_compute(target->writers[file_src_writer_index]); if (ret < 0) goto target_cleanup; /* * 3. * Call compute_data_blocks() in each Writer. * That function computes the size needed by its structures and * increments image current block propertly. */ for (i = 0; i < (int) target->nwriters; ++i) { IsoImageWriter *writer = target->writers[i]; if (target->gpt_backup_outside && writer->write_vol_desc == gpt_tail_writer_write_vol_desc) continue; /* Exposing address of data start to IsoWriteOpts and memorizing this address for all files which have no block address: symbolic links, device files, empty data files. filesrc_writer_compute_data_blocks() and filesrc_writer_write_data() will account resp. write this single block. */ if (i == file_src_writer_index) { if (! opts->old_empty) target->empty_file_block = target->curblock; in_opts->data_start_lba = opts->data_start_lba = target->curblock; } ret = writer->compute_data_blocks(writer); if (ret < 0) { goto target_cleanup; } #ifdef Libisofs_appended_partitions_inlinE target->vol_space_size = target->curblock - opts->ms_block; target->total_size = (off_t) target->vol_space_size * BLOCK_SIZE; #endif } ret = iso_patch_eltoritos(target); if (ret < 0) goto target_cleanup; if (((target->system_area_options & 0xfc) >> 2) == 2) { ret = iso_read_mipsel_elf(target, 0); if (ret < 0) goto target_cleanup; } #ifndef Libisofs_appended_partitions_inlinE /* * The volume space size is just the size of the last session, in * case of ms images. */ target->vol_space_size = target->curblock - opts->ms_block; target->total_size = (off_t) target->vol_space_size * BLOCK_SIZE; /* Add sizes of eventually appended partitions */ ret = iso_compute_append_partitions(target, 0); if (ret < 0) goto target_cleanup; #endif /* ! Libisofs_appended_partitions_inlinE */ if (target->gpt_backup_outside) { for (i = 0; i < (int) target->nwriters; ++i) { IsoImageWriter *writer = target->writers[i]; if (writer->write_vol_desc != gpt_tail_writer_write_vol_desc) continue; ret = writer->compute_data_blocks(writer); if (ret < 0) goto target_cleanup; } } /* create the ring buffer */ if (opts->overwrite != NULL && opts->fifo_size < 32 + opts->partition_offset) { /* The ring buffer must be large enough to take opts->overwrite */ ret = ISO_OVWRT_FIFO_TOO_SMALL; goto target_cleanup; } ret = iso_ring_buffer_new(opts->fifo_size, &target->buffer); if (ret < 0) { goto target_cleanup; } /* check if we need to provide a copy of volume descriptors */ if (opts->overwrite != NULL) { /* opts->overwrite must be larger by partion_offset This storage is provided by the application. */ /* * In the PVM to be written in the 16th sector of the disc, we * need to specify the full size. */ target->vol_space_size = target->curblock; /* System area and volume descriptors */ target->opts_overwrite = (char *) opts->overwrite; ret = write_head_part1(target, &write_count, 1 | 2); target->opts_overwrite = NULL; if (ret < 0) goto target_cleanup; /* copy the volume descriptors to the overwrite buffer... */ voldesc_size *= BLOCK_SIZE; ret = iso_ring_buffer_read(target->buffer, opts->overwrite, write_count * BLOCK_SIZE); if (ret < 0) { iso_msg_debug(target->image->id, "Error reading overwrite volume descriptors"); goto target_cleanup; } /* Write relocated superblock checksum tag */ tag_pos = voldesc_size / BLOCK_SIZE + 16 + 1; if (opts->md5_session_checksum) { target->checksum_rlsb_tag_pos = tag_pos; if (target->checksum_rlsb_tag_pos < 32) { ret = iso_md5_start(&(target->checksum_ctx)); if (ret < 0) goto target_cleanup; target->opts_overwrite = (char *) opts->overwrite; iso_md5_compute(target->checksum_ctx, target->opts_overwrite, target->checksum_rlsb_tag_pos * 2048); ret = iso_md5_write_tag(target, 4); target->opts_overwrite = NULL; /* opts might not persist */ if (ret < 0) goto target_cleanup; } tag_pos++; write_count++; } /* Clean out eventual obsolete checksum tags */ for (i = tag_pos; i < 32; i++) { int tag_type; uint32_t pos, range_start, range_size, next_tag; char md5[16]; ret = iso_util_decode_md5_tag((char *)(opts->overwrite + i * 2048), &tag_type, &pos, &range_start, &range_size, &next_tag, md5, 0); if (ret > 0) opts->overwrite[i * 2048] = 0; } /* Write second set of volume descriptors */ write_count_mem= write_count; ret = write_head_part2(target, &write_count, 0); if (ret < 0) goto target_cleanup; /* Read written data into opts->overwrite */ ret = iso_ring_buffer_read(target->buffer, opts->overwrite + write_count_mem * BLOCK_SIZE, (write_count - write_count_mem) * BLOCK_SIZE); if (ret < 0) { iso_msg_debug(target->image->id, "Error reading overwrite volume descriptors"); goto target_cleanup; } } /* This was possibly altered by above overwrite buffer production */ target->vol_space_size = target->curblock - opts->ms_block; /* */ #define Libisofs_print_size_no_forK 1 #ifdef Libisofs_print_size_no_forK if (opts->will_cancel) { iso_msg_debug(target->image->id, "Will not start write thread because of iso_write_opts_set_will_cancel"); *img = target; return ISO_SUCCESS; } #endif /* 4. Create and start writing thread */ if (opts->md5_session_checksum) { /* After any fake writes are done: Initialize image checksum context */ if (target->checksum_ctx != NULL) iso_md5_end(&(target->checksum_ctx), target->image_md5); ret = iso_md5_start(&(target->checksum_ctx)); if (ret < 0) goto target_cleanup; } if (opts->apm_block_size == 0) { if (target->gpt_req_count) opts->apm_block_size = 2048; /* Combinable with GPT */ else opts->apm_block_size = 512; /* Mountable on Linux */ } /* ensure the thread is created joinable */ pthread_attr_init(&(target->th_attr)); pthread_attr_setdetachstate(&(target->th_attr), PTHREAD_CREATE_JOINABLE); /* To avoid race conditions with the caller, this mark must be set before the thread starts. So the caller can rely on a value of 0 really meaning that the write has ended, and not that it might not have begun yet. In normal processing, the value will be changed to 0 at the end of write_function(). */ target->image->generator_is_running = 1; /* Claim that target may not get destroyed by bs_free_data() before write_function() is done with it */ target->refcount++; ret = pthread_create(&(target->wthread), &(target->th_attr), write_function, (void *) target); if (ret != 0) { target->refcount--; iso_msg_submit(target->image->id, ISO_THREAD_ERROR, 0, "Cannot create writer thread"); ret = ISO_THREAD_ERROR; goto target_cleanup; } target->wthread_is_running= 1; /* * Notice that once we reach this point, target belongs to the writer * thread and should not be modified until the writer thread finished. * There're however, specific fields in target that can be accessed, or * even modified by the read thread (look inside bs_* functions) */ *img = target; return ISO_SUCCESS; target_cleanup: ; target->image->generator_is_running = 0; ecma119_image_free(target); return ret; } static int bs_read(struct burn_source *bs, unsigned char *buf, int size) { int ret; Ecma119Image *t = (Ecma119Image*)bs->data; ret = iso_ring_buffer_read(t->buffer, buf, size); if (ret == ISO_SUCCESS) { return size; } else if (ret < 0) { /* error */ iso_msg_submit(t->image->id, ISO_BUF_READ_ERROR, ret, NULL); return -1; } else { /* EOF */ return 0; } } static off_t bs_get_size(struct burn_source *bs) { Ecma119Image *target = (Ecma119Image*)bs->data; return target->total_size; } static void bs_free_data(struct burn_source *bs) { int st; Ecma119Image *target = (Ecma119Image*)bs->data; st = iso_ring_buffer_get_status(bs, NULL, NULL); /* was read already finished (i.e, canceled)? */ if (st < 4) { /* forces writer to stop if it is still running */ iso_ring_buffer_reader_close(target->buffer, 0); /* wait until writer thread finishes */ if (target->wthread_is_running) { pthread_join(target->wthread, NULL); target->wthread_is_running = 0; iso_msg_debug(target->image->id, "Writer thread joined"); } } iso_msg_debug(target->image->id, "Ring buffer was %d times full and %d times empty", iso_ring_buffer_get_times_full(target->buffer), iso_ring_buffer_get_times_empty(target->buffer)); /* The reference to target was inherited from ecma119_image_new() */ ecma119_image_free(target); } static int bs_cancel(struct burn_source *bs) { int st; size_t cap, free; Ecma119Image *target = (Ecma119Image*)bs->data; st = iso_ring_buffer_get_status(bs, &cap, &free); if (free == cap && (st == 2 || st == 3)) { /* image was already consumed */ iso_ring_buffer_reader_close(target->buffer, 0); } else { iso_msg_debug(target->image->id, "Reader thread being cancelled"); /* forces writer to stop if it is still running */ iso_ring_buffer_reader_close(target->buffer, ISO_CANCELED); } /* wait until writer thread finishes */ if (target->wthread_is_running) { pthread_join(target->wthread, NULL); target->wthread_is_running = 0; iso_msg_debug(target->image->id, "Writer thread joined"); } return ISO_SUCCESS; } static int bs_set_size(struct burn_source *bs, off_t size) { Ecma119Image *target = (Ecma119Image*)bs->data; /* * just set the value to be returned by get_size. This is not used at * all by libisofs, it is here just for helping libburn to correctly pad * the image if needed. */ target->total_size = size; return 1; } static int dive_to_depth_8(IsoDir *dir, int depth) { int ret; IsoNode *pos; if (depth >= 8) return 1; pos = dir->children; for (pos = dir->children; pos != NULL; pos = pos->next) { if (pos->type != LIBISO_DIR) continue; ret = dive_to_depth_8((IsoDir *) pos, depth + 1); if (ret != 0) return ret; } return 0; } static int make_reloc_dir_if_needed(IsoImage *img, IsoWriteOpts *opts, int flag) { int ret; IsoDir *dir; /* Two forms to express the root directory */ if (opts->rr_reloc_dir == NULL) return 1; if (opts->rr_reloc_dir[0] == 0) return 1; if (strchr(opts->rr_reloc_dir, '/') != NULL) return 0; /* Check existence of opts->rr_reloc_dir */ ret = iso_dir_get_node(img->root, opts->rr_reloc_dir, NULL); if (ret > 0) return 1; if (ret < 0) return ret; /* Check whether there is a directory of depth 8 (root is depth 1) */ ret = dive_to_depth_8(img->root, 1); if (ret < 0) return ret; if (ret == 0) return 1; /* Make IsoDir with same permissions as root directory */ ret = iso_tree_add_new_dir(img->root, opts->rr_reloc_dir, &dir); if (ret < 0) return ret; opts->rr_reloc_flags |= 2; /* Auto-created relocation directory */ return 1; } int iso_image_create_burn_source(IsoImage *image, IsoWriteOpts *opts, struct burn_source **burn_src) { int ret; struct burn_source *source; Ecma119Image *target= NULL; if (image == NULL || opts == NULL || burn_src == NULL) { return ISO_NULL_POINTER; } source = calloc(1, sizeof(struct burn_source)); if (source == NULL) { return ISO_OUT_OF_MEM; } if (!opts->allow_deep_paths) { ret = make_reloc_dir_if_needed(image, opts, 0); if (ret < 0) { free(source); return ret; } } ret = ecma119_image_new(image, opts, &target); if (ret < 0) { free(source); return ret; } source->refcount = 1; source->version = 1; source->read = NULL; source->get_size = bs_get_size; source->set_size = bs_set_size; source->free_data = bs_free_data; source->read_xt = bs_read; source->cancel = bs_cancel; source->data = target; *burn_src = source; return ISO_SUCCESS; } int iso_write(Ecma119Image *target, void *buf, size_t count) { int ret; if (target->bytes_written + (off_t) count > target->total_size) { iso_msg_submit(target->image->id, ISO_ASSERT_FAILURE, 0, "ISO overwrite"); return ISO_ASSERT_FAILURE; } ret = iso_ring_buffer_write(target->buffer, buf, count); if (ret == 0) { /* reader cancelled */ return ISO_CANCELED; } if (ret < 0) return ret; if (target->checksum_ctx != NULL) { /* Add to image checksum */ target->checksum_counter += count; iso_md5_compute(target->checksum_ctx, (char *) buf, (int) count); } ret = show_chunk_to_jte(target, buf, count); if (ret != ISO_SUCCESS) return ret; /* total size is 0 when writing the overwrite buffer */ if (target->total_size != (off_t) 0){ unsigned int kbw, kbt; int percent; target->bytes_written += (off_t) count; kbw = (unsigned int) (target->bytes_written >> 10); kbt = (unsigned int) (target->total_size >> 10); percent = (kbw * 100) / kbt; /* only report in 5% chunks */ if (percent >= target->percent_written + 5) { iso_msg_debug(target->image->id, "Processed %u of %u KB (%d %%)", kbw, kbt, percent); target->percent_written = percent; } } return ISO_SUCCESS; } int iso_write_opts_new(IsoWriteOpts **opts, int profile) { int i; IsoWriteOpts *wopts; if (opts == NULL) { return ISO_NULL_POINTER; } if (profile < 0 || profile > 2) { return ISO_WRONG_ARG_VALUE; } wopts = calloc(1, sizeof(IsoWriteOpts)); if (wopts == NULL) { return ISO_OUT_OF_MEM; } wopts->scdbackup_tag_written = NULL; switch (profile) { case 0: wopts->iso_level = 1; break; case 1: wopts->iso_level = 3; wopts->rockridge = 1; break; case 2: wopts->iso_level = 2; wopts->rockridge = 1; wopts->joliet = 1; wopts->replace_dir_mode = 1; wopts->replace_file_mode = 1; wopts->replace_uid = 1; wopts->replace_gid = 1; wopts->replace_timestamps = 1; wopts->always_gmt = 1; break; default: /* should never happen */ free(wopts); return ISO_ASSERT_FAILURE; break; } wopts->hfsplus = 0; wopts->fat = 0; wopts->fifo_size = 1024; /* 2 MB buffer */ wopts->sort_files = 1; /* file sorting is always good */ wopts->joliet_utf16 = 0; wopts->rr_reloc_dir = NULL; wopts->rr_reloc_flags = 0; wopts->system_area_data = NULL; wopts->system_area_size = 0; wopts->system_area_options = 0; wopts->vol_creation_time = 0; wopts->vol_modification_time = 0; wopts->vol_expiration_time = 0; wopts->vol_effective_time = 0; wopts->vol_uuid[0] = 0; wopts->partition_offset = 0; wopts->partition_secs_per_head = 0; wopts->partition_heads_per_cyl = 0; #ifdef Libisofs_with_libjtE wopts->libjte_handle = NULL; #endif /* Libisofs_with_libjtE */ wopts->tail_blocks = 0; wopts->prep_partition = NULL; wopts->prep_part_flag = 0; wopts->efi_boot_partition = NULL; wopts->efi_boot_part_flag = 0; for (i = 0; i < ISO_MAX_PARTITIONS; i++) { wopts->appended_partitions[i] = NULL; wopts->appended_part_types[i] = 0; wopts->appended_part_flags[i] = 0; } wopts->appended_as_gpt = 0; wopts->ascii_disc_label[0] = 0; wopts->will_cancel = 0; wopts->allow_dir_id_ext = 0; wopts->old_empty = 0; wopts->untranslated_name_len = 0; for (i = 0; i < 8; i++) wopts->hfsp_serial_number[i] = 0; wopts->apm_block_size = 0; wopts->hfsp_block_size = 0; *opts = wopts; return ISO_SUCCESS; } int iso_write_opts_clone(IsoWriteOpts *in, IsoWriteOpts **out, int flag) { int ret, i; IsoWriteOpts *o = NULL; ret = iso_write_opts_new(&o, 0); if (ret != 1) return ret; *out = o; /* Provisory copy of all values and un-managed pointers */ memcpy(o, in, sizeof(IsoWriteOpts)); /* Set managed pointers to NULL */ o->output_charset = NULL; o->rr_reloc_dir = NULL; o->system_area_data = NULL; o->prep_partition = NULL; o->efi_boot_partition = NULL; for (i = 0; i < ISO_MAX_PARTITIONS; i++) o->appended_partitions[i] = NULL; /* Clone managed objects */ if (iso_clone_mem(in->output_charset, &(o->output_charset), 0) != 1) goto out_of_mem; if (iso_clone_mem(in->rr_reloc_dir, &(o->rr_reloc_dir), 0) != 1) goto out_of_mem; if (iso_clone_mem(in->system_area_data, &(o->system_area_data), in->system_area_size) != 1) goto out_of_mem; if (iso_clone_mem(in->prep_partition, &(o->prep_partition), 0) != 1) goto out_of_mem; if (iso_clone_mem(in->efi_boot_partition, &(o->efi_boot_partition), 0) != 1) goto out_of_mem; for (i = 0; i < ISO_MAX_PARTITIONS; i++) if (iso_clone_mem(in->appended_partitions[i], &(o->appended_partitions[i]), 0) != 1) goto out_of_mem; return ISO_SUCCESS; out_of_mem:; iso_write_opts_free(o); return ISO_OUT_OF_MEM; } void iso_write_opts_free(IsoWriteOpts *opts) { int i; if (opts == NULL) { return; } free(opts->output_charset); if (opts->rr_reloc_dir != NULL) free(opts->rr_reloc_dir); if (opts->system_area_data != NULL) free(opts->system_area_data); if (opts->prep_partition != NULL) free(opts->prep_partition); if (opts->efi_boot_partition != NULL) free(opts->efi_boot_partition); for (i = 0; i < ISO_MAX_PARTITIONS; i++) if (opts->appended_partitions[i] != NULL) free(opts->appended_partitions[i]); free(opts); } int iso_write_opts_set_will_cancel(IsoWriteOpts *opts, int will_cancel) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->will_cancel = !!will_cancel; return ISO_SUCCESS; } int iso_write_opts_set_iso_level(IsoWriteOpts *opts, int level) { if (opts == NULL) { return ISO_NULL_POINTER; } if (level != 1 && level != 2 && level != 3) { return ISO_WRONG_ARG_VALUE; } opts->iso_level = level; return ISO_SUCCESS; } int iso_write_opts_set_rockridge(IsoWriteOpts *opts, int enable) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->rockridge = enable ? 1 : 0; return ISO_SUCCESS; } int iso_write_opts_set_joliet(IsoWriteOpts *opts, int enable) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->joliet = enable ? 1 : 0; return ISO_SUCCESS; } int iso_write_opts_set_hfsplus(IsoWriteOpts *opts, int enable) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->hfsplus = enable ? 1 : 0; return ISO_SUCCESS; } int iso_write_opts_set_fat(IsoWriteOpts *opts, int enable) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->fat = enable ? 1 : 0; return ISO_SUCCESS; } int iso_write_opts_set_iso1999(IsoWriteOpts *opts, int enable) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->iso1999 = enable ? 1 : 0; return ISO_SUCCESS; } int iso_write_opts_set_hardlinks(IsoWriteOpts *opts, int enable) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->hardlinks = enable ? 1 : 0; return ISO_SUCCESS; } int iso_write_opts_set_aaip(IsoWriteOpts *opts, int enable) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->aaip = enable ? 1 : 0; return ISO_SUCCESS; } int iso_write_opts_set_old_empty(IsoWriteOpts *opts, int enable) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->old_empty = enable ? 1 : 0; return ISO_SUCCESS; } int iso_write_opts_set_untranslated_name_len(IsoWriteOpts *opts, int len) { if (opts == NULL) { return ISO_NULL_POINTER; } if (len == -1) opts->untranslated_name_len = ISO_UNTRANSLATED_NAMES_MAX; else if(len == 0) opts->untranslated_name_len = 0; else if(len > ISO_UNTRANSLATED_NAMES_MAX || len < 0) return ISO_WRONG_ARG_VALUE; else opts->untranslated_name_len = len; return opts->untranslated_name_len; } int iso_write_opts_set_allow_dir_id_ext(IsoWriteOpts *opts, int allow) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->allow_dir_id_ext = allow ? 1 : 0; return ISO_SUCCESS; } int iso_write_opts_set_omit_version_numbers(IsoWriteOpts *opts, int omit) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->omit_version_numbers = omit & 3; return ISO_SUCCESS; } int iso_write_opts_set_allow_deep_paths(IsoWriteOpts *opts, int allow) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->allow_deep_paths = allow ? 1 : 0; return ISO_SUCCESS; } int iso_write_opts_set_allow_longer_paths(IsoWriteOpts *opts, int allow) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->allow_longer_paths = allow ? 1 : 0; return ISO_SUCCESS; } int iso_write_opts_set_max_37_char_filenames(IsoWriteOpts *opts, int allow) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->max_37_char_filenames = allow ? 1 : 0; return ISO_SUCCESS; } int iso_write_opts_set_no_force_dots(IsoWriteOpts *opts, int no) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->no_force_dots = no & 3; return ISO_SUCCESS; } int iso_write_opts_set_allow_lowercase(IsoWriteOpts *opts, int allow) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->allow_lowercase = allow ? 1 : 0; return ISO_SUCCESS; } int iso_write_opts_set_allow_full_ascii(IsoWriteOpts *opts, int allow) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->allow_full_ascii = allow ? 1 : 0; return ISO_SUCCESS; } int iso_write_opts_set_allow_7bit_ascii(IsoWriteOpts *opts, int allow) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->allow_7bit_ascii = allow ? 1 : 0; return ISO_SUCCESS; } int iso_write_opts_set_relaxed_vol_atts(IsoWriteOpts *opts, int allow) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->relaxed_vol_atts = allow ? 1 : 0; return ISO_SUCCESS; } int iso_write_opts_set_joliet_longer_paths(IsoWriteOpts *opts, int allow) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->joliet_longer_paths = allow ? 1 : 0; return ISO_SUCCESS; } int iso_write_opts_set_joliet_long_names(IsoWriteOpts *opts, int allow) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->joliet_long_names = allow ? 1 : 0; return ISO_SUCCESS; } int iso_write_opts_set_joliet_utf16(IsoWriteOpts *opts, int allow) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->joliet_utf16 = allow ? 1 : 0; return ISO_SUCCESS; } int iso_write_opts_set_rrip_version_1_10(IsoWriteOpts *opts, int oldvers) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->rrip_version_1_10 = oldvers ? 1 : 0; return ISO_SUCCESS; } int iso_write_opts_set_rrip_1_10_px_ino(IsoWriteOpts *opts, int enable) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->rrip_1_10_px_ino = enable ? 1 : 0; return ISO_SUCCESS; } int iso_write_opts_set_aaip_susp_1_10(IsoWriteOpts *opts, int oldvers) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->aaip_susp_1_10 = oldvers ? 1 : 0; return ISO_SUCCESS; } int iso_write_opts_set_dir_rec_mtime(IsoWriteOpts *opts, int allow) { if (opts == NULL) { return ISO_NULL_POINTER; } if (allow < 0) allow = 1; else if (allow & (1 << 14)) allow &= ~1; else if (allow & 6) allow |= 1; opts->dir_rec_mtime = allow & 7; return ISO_SUCCESS; } int iso_write_opts_set_rr_reloc(IsoWriteOpts *opts, char *name, int flags) { if (opts->rr_reloc_dir != name) { if (opts->rr_reloc_dir != NULL) free(opts->rr_reloc_dir); opts->rr_reloc_dir = NULL; if (name != NULL) { opts->rr_reloc_dir = strdup(name); if (opts->rr_reloc_dir == NULL) return ISO_OUT_OF_MEM; } } opts->rr_reloc_flags = flags & 1; return ISO_SUCCESS; } int iso_write_opts_set_sort_files(IsoWriteOpts *opts, int sort) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->sort_files = sort ? 1 : 0; return ISO_SUCCESS; } int iso_write_opts_set_record_md5(IsoWriteOpts *opts, int session, int files) { opts->md5_session_checksum = session & 1; opts->md5_file_checksums = files & 3; return ISO_SUCCESS; } int iso_write_opts_set_scdbackup_tag(IsoWriteOpts *opts, char *name, char *timestamp, char *tag_written) { char eff_name[81], eff_time[19]; int i; for (i = 0; name[i] != 0 && i < 80; i++) if (isspace((int) ((unsigned char *) name)[i])) eff_name[i] = '_'; else eff_name[i] = name[i]; if (i == 0) eff_name[i++] = '_'; eff_name[i] = 0; for (i = 0; timestamp[i] != 0 && i < 18; i++) if (isspace((int) ((unsigned char *) timestamp)[i])) eff_time[i] = '_'; else eff_time[i] = timestamp[i]; if (i == 0) eff_time[i++] = '_'; eff_time[i] = 0; sprintf(opts->scdbackup_tag_parm, "%s %s", eff_name, eff_time); opts->scdbackup_tag_written = tag_written; if (tag_written != NULL) tag_written[0] = 0; return ISO_SUCCESS; } int iso_write_opts_set_replace_mode(IsoWriteOpts *opts, int dir_mode, int file_mode, int uid, int gid) { if (opts == NULL) { return ISO_NULL_POINTER; } if (dir_mode < 0 || dir_mode > 2) { return ISO_WRONG_ARG_VALUE; } if (file_mode < 0 || file_mode > 2) { return ISO_WRONG_ARG_VALUE; } if (uid < 0 || uid > 2) { return ISO_WRONG_ARG_VALUE; } if (gid < 0 || gid > 2) { return ISO_WRONG_ARG_VALUE; } opts->replace_dir_mode = dir_mode; opts->replace_file_mode = file_mode; opts->replace_uid = uid; opts->replace_gid = gid; return ISO_SUCCESS; } int iso_write_opts_set_default_dir_mode(IsoWriteOpts *opts, mode_t dir_mode) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->dir_mode = dir_mode; return ISO_SUCCESS; } int iso_write_opts_set_default_file_mode(IsoWriteOpts *opts, mode_t file_mode) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->file_mode = file_mode; return ISO_SUCCESS; } int iso_write_opts_set_default_uid(IsoWriteOpts *opts, uid_t uid) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->uid = uid; return ISO_SUCCESS; } int iso_write_opts_set_default_gid(IsoWriteOpts *opts, gid_t gid) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->gid = gid; return ISO_SUCCESS; } int iso_write_opts_set_replace_timestamps(IsoWriteOpts *opts, int replace) { if (opts == NULL) { return ISO_NULL_POINTER; } if (replace < 0 || replace > 2) { return ISO_WRONG_ARG_VALUE; } opts->replace_timestamps = replace; return ISO_SUCCESS; } int iso_write_opts_set_default_timestamp(IsoWriteOpts *opts, time_t timestamp) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->timestamp = timestamp; return ISO_SUCCESS; } int iso_write_opts_set_always_gmt(IsoWriteOpts *opts, int gmt) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->always_gmt = gmt ? 1 : 0; return ISO_SUCCESS; } int iso_write_opts_set_output_charset(IsoWriteOpts *opts, const char *charset) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->output_charset = charset ? strdup(charset) : NULL; return ISO_SUCCESS; } int iso_write_opts_set_appendable(IsoWriteOpts *opts, int appendable) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->appendable = appendable ? 1 : 0; return ISO_SUCCESS; } int iso_write_opts_set_ms_block(IsoWriteOpts *opts, uint32_t ms_block) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->ms_block = ms_block; return ISO_SUCCESS; } int iso_write_opts_set_overwrite_buf(IsoWriteOpts *opts, uint8_t *overwrite) { if (opts == NULL) { return ISO_NULL_POINTER; } opts->overwrite = overwrite; return ISO_SUCCESS; } int iso_write_opts_set_fifo_size(IsoWriteOpts *opts, size_t fifo_size) { if (opts == NULL) { return ISO_NULL_POINTER; } if (fifo_size < 32) { return ISO_WRONG_ARG_VALUE; } opts->fifo_size = fifo_size; return ISO_SUCCESS; } int iso_write_opts_get_data_start(IsoWriteOpts *opts, uint32_t *data_start, int flag) { if (opts->data_start_lba == 0) return ISO_ERROR; *data_start = opts->data_start_lba; return ISO_SUCCESS; } /* * @param data Either NULL or 32 kB of data. Do not submit less bytes ! * @param options * Can cause manipulations of submitted data before they get written: * bit0= apply a --protective-msdos-label as of grub-mkisofs. * This means to patch bytes 446 to 512 of the system area so * that one partition is defined which begins at the second * 512-byte block of the image and ends where the image ends. * This works with and without system_area_data. * bit1= apply isohybrid MBR patching to the system area. * This works only with system area data from SYSLINUX plus an * ISOLINUX boot image (see iso_image_set_boot_image()) and * only if not bit0 is set. * bit2-7= System area type * bit8-9= Only with System area type 0 = MBR * Cylinder alignment mode * bit10-13= System area sub type * @param flag bit0 = invalidate any attached system area data * same as data == NULL * bit1 = keep data unaltered * bit2 = keep options unaltered */ int iso_write_opts_set_system_area(IsoWriteOpts *opts, char data[32768], int options, int flag) { if (data == NULL || (flag & 1)) { /* Disable */ if (opts->system_area_data != NULL) free(opts->system_area_data); opts->system_area_data = NULL; opts->system_area_size = 0; } else if (!(flag & 2)) { if (opts->system_area_data == NULL) { opts->system_area_data = calloc(32768, 1); if (opts->system_area_data == NULL) return ISO_OUT_OF_MEM; } memcpy(opts->system_area_data, data, 32768); opts->system_area_size = 32768; } if (!(flag & 4)) opts->system_area_options = options & 0x7fff; return ISO_SUCCESS; } int iso_write_opts_set_pvd_times(IsoWriteOpts *opts, time_t vol_creation_time, time_t vol_modification_time, time_t vol_expiration_time, time_t vol_effective_time, char *vol_uuid) { opts->vol_creation_time = vol_creation_time; opts->vol_modification_time = vol_modification_time; opts->vol_expiration_time = vol_expiration_time; opts->vol_effective_time = vol_effective_time; strncpy(opts->vol_uuid, vol_uuid, 16); opts->vol_uuid[16] = 0; return ISO_SUCCESS; } int iso_write_opts_set_part_offset(IsoWriteOpts *opts, uint32_t block_offset_2k, int secs_512_per_head, int heads_per_cyl) { if (block_offset_2k > 0 && block_offset_2k < 16) return ISO_PART_OFFST_TOO_SMALL; opts->partition_offset = block_offset_2k; opts->partition_secs_per_head = secs_512_per_head; opts->partition_heads_per_cyl = heads_per_cyl; return ISO_SUCCESS; } int iso_write_opts_attach_jte(IsoWriteOpts *opts, void *libjte_handle) { #ifdef Libisofs_with_libjtE opts->libjte_handle = libjte_handle; return ISO_SUCCESS; #else return ISO_LIBJTE_NOT_ENABLED; #endif /* Libisofs_with_libjtE */ } int iso_write_opts_detach_jte(IsoWriteOpts *opts, void **libjte_handle) { #ifdef Libisofs_with_libjtE if (*libjte_handle != NULL) *libjte_handle = opts->libjte_handle; opts->libjte_handle = NULL; return ISO_SUCCESS; #else return ISO_LIBJTE_NOT_ENABLED; #endif /* Libisofs_with_libjtE */ } int iso_write_opts_set_tail_blocks(IsoWriteOpts *opts, uint32_t num_blocks) { opts->tail_blocks = num_blocks; return ISO_SUCCESS; } int iso_write_opts_set_prep_img(IsoWriteOpts *opts, char *image_path, int flag) { if (opts->prep_partition != NULL) free(opts->prep_partition); if (image_path == NULL) return ISO_SUCCESS; opts->prep_partition = strdup(image_path); if (opts->prep_partition == NULL) return ISO_OUT_OF_MEM; opts->prep_part_flag = (flag & 1); return ISO_SUCCESS; } int iso_write_opts_set_efi_bootp(IsoWriteOpts *opts, char *image_path, int flag) { if (opts->efi_boot_partition != NULL) free(opts->efi_boot_partition); if (image_path == NULL) return ISO_SUCCESS; opts->efi_boot_partition = strdup(image_path); if (opts->efi_boot_partition == NULL) return ISO_OUT_OF_MEM; opts->efi_boot_part_flag = (flag & 1); return ISO_SUCCESS; } int iso_write_opts_set_partition_img(IsoWriteOpts *opts, int partition_number, uint8_t partition_type, char *image_path, int flag) { if (partition_number < 1 || partition_number > ISO_MAX_PARTITIONS) return ISO_BAD_PARTITION_NO; if (opts->appended_partitions[partition_number - 1] != NULL) free(opts->appended_partitions[partition_number - 1]); if (image_path == NULL) return ISO_SUCCESS; opts->appended_partitions[partition_number - 1] = strdup(image_path); if (opts->appended_partitions[partition_number - 1] == NULL) return ISO_OUT_OF_MEM; opts->appended_part_types[partition_number - 1] = partition_type; opts->appended_part_flags[partition_number - 1] = (flag & 1); return ISO_SUCCESS; } int iso_write_opts_set_appended_as_gpt(IsoWriteOpts *opts, int gpt) { opts->appended_as_gpt = !!gpt; return ISO_SUCCESS; } int iso_write_opts_set_disc_label(IsoWriteOpts *opts, char *label) { strncpy(opts->ascii_disc_label, label, ISO_DISC_LABEL_SIZE - 1); opts->ascii_disc_label[ISO_DISC_LABEL_SIZE - 1] = 0; return ISO_SUCCESS; } int iso_write_opts_set_hfsp_serial_number(IsoWriteOpts *opts, uint8_t serial_number[8]) { memcpy(opts->hfsp_serial_number, serial_number, 8); return ISO_SUCCESS; } int iso_write_opts_set_hfsp_block_size(IsoWriteOpts *opts, int hfsp_block_size, int apm_block_size) { if (hfsp_block_size != 0 && hfsp_block_size != 512 && hfsp_block_size != 2048) return ISO_BOOT_HFSP_BAD_BSIZE; opts->hfsp_block_size = hfsp_block_size; if (apm_block_size != 0 && apm_block_size != 512 && apm_block_size != 2048) return ISO_BOOT_HFSP_BAD_BSIZE; opts->apm_block_size = apm_block_size; return ISO_SUCCESS; } /* * @param flag * Bitfield for control purposes. * bit0-bit7= Name space * 0= generic (to_charset is valid, no reserved characters, * no length limits) * 1= Rock Ridge (to_charset is valid) * 2= Joliet (to_charset gets overriden by UCS-2 or UTF-16) * 3= ECMA-119 (dull ISO 9660 character set) * 4= HFS+ (to_charset gets overridden by UTF-16BE) * bit8= Treat input text as directory name * (matters for Joliet and ECMA-119) * bit9= Do not issue error messages * bit15= Reverse operation (best to be done only with results of * previous conversions) */ int iso_conv_name_chars(IsoWriteOpts *opts, char *in_name, size_t name_len, char **result, size_t *result_len, int flag) { int name_space, ret, reverse; size_t i; size_t joliet_ucs2_failures = ISO_JOLIET_UCS2_WARN_MAX + 1;/* no warning */ size_t conved_len; char *from_charset, *to_charset, *conved, *smashed = NULL, *name; char *tr, *with_version = NULL; uint16_t *ucs = NULL, *hfspcmp = NULL; uint32_t ucs_len; enum IsoNodeType node_type; *result = NULL; *result_len = 0; name = in_name; name_space = flag & 0xff; reverse = !!(flag & (1 << 15)); node_type = (flag & 256) ? LIBISO_DIR : LIBISO_FILE; from_charset = iso_get_local_charset(0); /* Note: Joliet, ECMA-119, HFS+ actually use to_charset only for the reverse conversion case */ if (opts->output_charset != NULL) to_charset = opts->output_charset; else to_charset = from_charset; if (name_space == 1) { /* Rock Ridge */ if (!reverse) { LIBISO_ALLOC_MEM(smashed, char, name_len + 1); memcpy(smashed, name, name_len); smashed[name_len] = 0; for (i = 0; i < name_len; i++) if (smashed[i] == '/') smashed[i] = '_'; name = smashed; /* >>> ??? truncate to 255 chars */ } } else if (name_space == 2) { /* Joliet */ if (opts->joliet_utf16) to_charset = "UTF-16BE"; else to_charset = "UCS-2BE"; } else if (name_space == 3) { /* ECMA-119 */ to_charset = "ASCII"; } else if (name_space == 4) { /* HFS+ */ to_charset= "UTF-16BE"; } if (reverse) { tr = from_charset; from_charset = to_charset; to_charset = tr; } if (name_space == 0 || reverse) { ret = strnconvl(name, from_charset, to_charset, name_len, &conved, &conved_len); if (ret != ISO_SUCCESS) goto ex; } else if (name_space == 1) { /* Rock Ridge */ ret = iso_get_rr_name(opts, from_charset, to_charset, -1, name, &conved, !!(flag & 512)); if (ret != ISO_SUCCESS) goto ex; conved_len = strlen(conved); } else if (name_space == 2) { /* Joliet */ ret = iso_get_joliet_name(opts, from_charset, -1, name, node_type, &joliet_ucs2_failures, &ucs, !!(flag & 512)); if (ret != ISO_SUCCESS) goto ex; conved_len = ucslen(ucs) * 2; conved = (char *) ucs; ucs = NULL; if (node_type != LIBISO_DIR && !(opts->omit_version_numbers & 3)) { LIBISO_ALLOC_MEM(with_version, char, conved_len + 6); memcpy(with_version, conved, conved_len); with_version[conved_len++] = 0; with_version[conved_len++] = ';'; with_version[conved_len++] = 0; with_version[conved_len++] = '1'; with_version[conved_len] = 0; with_version[conved_len + 1] = 0; free(conved); conved = with_version; with_version = NULL; } } else if (name_space == 3) { /* ECMA-119 */ ret = iso_get_ecma119_name(opts, from_charset, -1, name, node_type, &conved, !!(flag & 512)); if (ret != ISO_SUCCESS) goto ex; conved_len = strlen(conved); if (need_version_number(opts, node_type == LIBISO_DIR ? ECMA119_DIR : ECMA119_FILE)) { LIBISO_ALLOC_MEM(with_version, char, conved_len + 3); memcpy(with_version, conved, conved_len + 1); strcat(with_version, ";1"); free(conved); conved = with_version; with_version = NULL; conved_len += 2; } } else if (name_space == 4) { /* HFS+ */ ret = iso_get_hfsplus_name(from_charset, -1, name, &ucs, &ucs_len, &hfspcmp); if (ret != ISO_SUCCESS) goto ex; conved = (char *) ucs; ucs = NULL; conved_len = ucs_len * 2; } else { ret = ISO_WRONG_ARG_VALUE; goto ex; } *result = conved; *result_len = conved_len; ret = ISO_SUCCESS; ex: LIBISO_FREE_MEM(with_version); LIBISO_FREE_MEM(smashed); LIBISO_FREE_MEM(ucs); LIBISO_FREE_MEM(hfspcmp); return ret; } static void ecma119_filesrc_array(Ecma119Node *dir, int (*include_item)(void *), IsoFileSrc **filelist, size_t *size, int just_count) { size_t i; Ecma119Node *child; for (i = 0; i < dir->info.dir->nchildren; i++) { child = dir->info.dir->children[i]; if (child->type == ECMA119_DIR) { ecma119_filesrc_array(child, include_item, filelist, size, just_count); } else if (child->type == ECMA119_FILE) { if (include_item != NULL) if (!include_item((void *) child->info.file)) continue; if (just_count) { (*size)++; } else { if (!child->info.file->taken) { filelist[*size] = child->info.file; child->info.file->taken = 1; (*size)++; } } } } } static void hidden_filesrc_array(Ecma119Image *t, int (*include_item)(void *), IsoFileSrc **filelist, size_t *size, int just_count) { struct iso_filesrc_list_item *item; for (item = t->ecma119_hidden_list; item != NULL; item = item->next) { if (include_item != NULL) if (!include_item((void *) item->src)) continue; if (just_count) { (*size)++; } else { if (!item->src->taken) { filelist[*size] = item->src; item->src->taken = 1; (*size)++; } } } } IsoFileSrc **iso_ecma119_to_filesrc_array(Ecma119Image *t, int (*include_item)(void *), size_t *size) { IsoFileSrc **filelist = NULL; /* Count nodes */ *size = 0; ecma119_filesrc_array(t->root, include_item, filelist, size, 1); hidden_filesrc_array(t, include_item, filelist, size, 1); LIBISO_ALLOC_MEM_VOID(filelist, IsoFileSrc *, *size + 1); /* Fill array */ *size = 0; ecma119_filesrc_array(t->root, include_item, filelist, size, 0); hidden_filesrc_array(t, include_item, filelist, size, 0); filelist[*size] = NULL; return filelist; ex: /* LIBISO_ALLOC_MEM failed */ *size = 0; return NULL; } libisofs-1.4.2/libisofs/filter.c0000644000175700017510000000313012321161425013516 00000000000000/* * Copyright (c) 2008 Vreixo Formoso * Copyright (c) 2009 Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif #include "libisofs.h" #include "filter.h" #include "node.h" void iso_filter_ref(FilterContext *filter) { ++filter->refcount; } void iso_filter_unref(FilterContext *filter) { if (--filter->refcount == 0) { filter->free(filter); free(filter); } } int iso_file_add_filter(IsoFile *file, FilterContext *filter, int flag) { int ret; IsoStream *original, *filtered; if (file == NULL || filter == NULL) { return ISO_NULL_POINTER; } original = file->stream; if (!iso_stream_is_repeatable(original)) { /* TODO use custom error */ return ISO_WRONG_ARG_VALUE; } ret = filter->get_filter(filter, original, &filtered); if (ret < 0) { return ret; } iso_stream_unref(original); file->stream = filtered; return ISO_SUCCESS; } int iso_file_remove_filter(IsoFile *file, int flag) { IsoStream *file_stream, *input_stream; file_stream = file->stream; input_stream = iso_stream_get_input_stream(file_stream, 0); if (input_stream == NULL) return 0; file->stream = input_stream; iso_stream_ref(input_stream); /* Protect against _unref(file_stream) */ iso_stream_unref(file_stream); return 1; } libisofs-1.4.2/ChangeLog0000644000175700017510000005530212626304521012041 00000000000000libisofs-1.4.2.tar.gz Sat Nov 28 2015 =============================================================================== * Bug fix: zisofs compression caused SIGSEGV (by reading) with files larger than 524160 KiB. * Bug fix: iso_node_get_name() of root node returned NULL pointer rather than an empty string * Bug fix: Names read from Joliet tree where stripped of trailing ";1" * Now sorting the data file content extents by ECMA-119 tree, rather than by the red-black tree which shall consolidate files with identical source object. * New API call iso_read_opts_set_ecma119_map(). * New AAIP variable isofs.nt records name truncation parameters. * Rectified handling of oversized filenames by new API calls: iso_image_set_truncate_mode, iso_image_get_truncate_mode, iso_truncate_leaf_name, iso_image_set_node_name, iso_image_tree_clone, iso_image_add_new_dir, iso_image_add_new_file, iso_image_add_new_special, iso_image_add_new_symlink, iso_image_dir_get_node, iso_image_path_to_node * Result of a Coverity audit: 50+ code changes, but no easy-to-trigger bugs libisofs-1.4.0.tar.gz Sun May 17 2015 =============================================================================== * Bug fix: iso_image_report_system_area() caused SIGSEGV by NULL if no valid ISO 9660 image was loeaded. Thanks to OmegaPhil. * Bug fix: A SIGSEGV could happen when loading a faulty ISO filesystem. Debian bug 774152. Thanks to Jakub Wilk. * Bug fix: Rock Ridge Continuation Area could be produced crossing a block boundary. This is heavily disliked by the Linux kernel and spoils the representation of directories which contain many symbolic links. * Bug fix: If iso_write_opts_set_hardlinks() enabled automatic inode numbers, then they did not get into effect with nodes were zisofs decoder filters got attached during the image load process. * Bug fix: The header indicator of the last El Torito catalog section header was set to 0x90 rather than 0x91 if more than one boot image is in that section. * Bug fix: Only 128 bytes of an emerging GPT header block were zeroized. * Bug fix: iso_image_report_system_area() did not show GPT partitions of size 0. * Bug fix: A zero sized GPT partition was marked after the last appended GPT partition. * Bug fix: GPT production did not yield proper results with appended sessions or with TOC emulation enabled. * Increased default weight of El Torito boot catalog to 1 billion. * Improved handling of cylinder alignment if the resulting image size is not divisible by 2048. Old behavior was to not align. New is to pad up by a few blocks of 512 bytes. * New API call iso_write_opts_set_appended_as_gpt() and marking of appended partitions in GPT if GPT emerges for other reasons. * New system area type 6 = DEC Alpha SRM boot sector. New API calls iso_image_set_alpha_boot(), iso_image_get_alpha_boot(). Thanks to Helge Deller. * New API object iso_interval_reader. Enabling flag bits for older API calls iso_write_opts_set_prep_img(), iso_write_opts_set_efi_bootp(), and iso_write_opts_set_partition_img(). libisofs-1.3.8.tar.gz Sat Jun 28 2014 =============================================================================== * Bug fix: Prevent allocation of empty hash tables. Thanks Richard Nolde. * Bug fix: Prevent allocation of empty directory children lists. Thanks Richard Nolde. * Bug fix: The GUIDs of main GPT and backup GPT differed if more than one System Area was written into the ISO image. * New API calls iso_image_report_el_torito() and iso_image_report_system_area() * New API call iso_crc32_gpt() libisofs-1.3.6.tar.gz Tue Mar 04 2014 =============================================================================== * Bug fix: Division by zero if HFS+ was combined with TOC emulation for overwritable media. * New API call iso_write_opts_set_joliet_utf16() and ability to read Joliet names as UTF-16BE * New API call iso_conv_name_chars() libisofs-1.3.4.tar.gz Thu Dec 12 2013 =============================================================================== * Giving sort weight 2 as default to El Torito boot images * Encoding HFS+ names in UTF-16 rather than UCS-2. libisofs-1.3.2.tar.gz Wed Aug 07 2013 =============================================================================== * Bug fix: iso_finish() left an invalid global pointer, which a subsequent call of iso_init() would try to dereference. * The sort weight of data files loaded from ISO image is now 2 exp 28 to 1 rather than 2 exp 31 - 1 to - 2 exp 31 libisofs-1.3.0.tar.gz Fri May 17 2013 =============================================================================== * Bug fix: GPT header CRC was computed from all 512 bytes rather than from 92. * Bug fix: Unspecified Expiration Time and Effective Time of ISO volume was represented by 0-bytes rather than ASCII '0' digits. * Bug fix: Reserved and unused fields of APM entries were not zeroed. * Bug fix: The protective MBR partition for GPT started at block 0 instead of 1. * New option bits with el_torito_set_isolinux_options() and iso_write_opts_set_system_area() to control GRUB2 patching of boot image and MBR. * New API calls iso_image_set_sparc_core() and iso_image_get_sparc_core(). libisofs-1.2.8.tar.gz Mon Mar 18 2013 =============================================================================== * Bug fix: Image size prediction altered the pointers to MD5 of data files which stem from a previous session. * Bug fix: Reading damaged Rock Ridge data could cause SIGSEGV by NULL. * New API call iso_image_get_pvd_times(). libisofs-1.2.6.tar.gz Tue Jan 08 2013 =============================================================================== * Bug fix: Appended partitions did not obey cylinder alignment * Bug fix: Non-zero partition offset zeroized the MBR copies of GPT partition table entries * Bug fix: Isohybrid production without any boot image led to SIGSEGV by NULL * Bug fix: Prevented a memory fault when reading damaged Rock Ridge information libisofs-1.2.4.tar.gz Fri Jul 20 2012 =============================================================================== * Bug fix: Memory corruption when reading bootable image that was truncated before the storage location of the boot catalog * Bug fix: Symbol iso_fs_global_id was missing in libisofs.ver. * Bug fix: Volume descriptors of Joliet and ISO 9660:1999 beared non-zero Effective Date, involuntarily restricting the early end of their lifetime. * Bug fix: File Structure Version field of ISO 9660:1999 Enhanced Volume Descriptor was 1 instead of 2. * Bug fix: The separator dot of Joliet names was byte swapped on big-endian machines. * Bug fix: Joliet name comparison was done as signed bytes and thus produced a peculiar sorting order. * Bug fix: Partition cylinder alignment worked only if both, El Torito and application provided system area data were present. * New API function iso_write_opts_set_hfsplus * New API functions iso_hfsplus_xinfo_func(), iso_hfsplus_xinfo_new(), and new struct iso_hfsplus_xinfo_data. * New API call iso_write_opts_set_hfsp_serial_number() * New API calls iso_image_hfsplus_bless and iso_image_hfsplus_get_blessed(), and new public enum IsoHfsplusBlessings. * New API calls so_write_opts_set_prep_img(), iso_write_opts_set_efi_bootp() * New API call iso_write_opts_set_hfsp_block_size() * New API call iso_tree_resolve_symlink() * New system area sub type CHRP with iso_write_opts_set_system_area() * New option bits 2 to 8 for GPT and APM with el_torito_set_isolinux_options() * New flag bit with iso_node_set_attrs() to protect namespace "isofs" * New IsoHideNodeFlag value LIBISO_HIDE_ON_HFSPLUS libisofs-1.2.2.tar.gz Mon Apr 02 2012 =============================================================================== * New API call iso_write_opts_set_rr_reloc() * Bug fix: Directory name mapping to ISO level 1 was too liberal if iso_write_opts_set_allow_dir_id_ext() was enabled * New API call iso_write_opts_set_allow_7bit_ascii() * Improved standards compliance for ISO level 1 names with partly relaxed constraints. libisofs-1.2.0.tar.gz Sat Jan 28 2012 =============================================================================== * Extended influence of iso_write_opts_set_dir_rec_mtime() to Joliet and ISO 9660:1999. libisofs-1.1.6.tar.gz Tue Sep 27 2011 =============================================================================== * Bug fix: On Solaris: False out-of-memory errors when writing images. * Bug fix: On FreeBSD: No ACLs were recorded. * Bug fix: ACL entries of groups and of user id 0 were not properly recorded and cannot be restored. * Bug fix: On FreeBSD: The function for restoring ACLs and xattr returned error, even if no xattr were to be restored. * New API call iso_local_attr_support() * Enabled recording and restoring of extattr on FreeBSD. libisofs-1.1.4.tar.gz Mon Aug 08 2011 =============================================================================== * Bug fix: The function for restoring ACLs and xattr returned error on systems other than Linux and FreeBSD, even if nothing was to be restored. libisofs-1.1.2.tar.gz Fri Jul 08 2011 =============================================================================== * New API call iso_image_get_bootcat() libisofs-1.1.0.tar.gz Sat Jun 18 2011 =============================================================================== * Bug fix: Padding as of iso_write_opts_set_tail_blocks() was added only after cylinder alignment as of iso_write_opts_set_system_area() and thus spoiled this alignment. libisofs-1.0.8.tar.gz Thu May 12 2011 =============================================================================== * Bug fix: iso_write_opts_set_system_area() with system area types 1=MIPS Big Endian and 2=MIPS Little Endian caused SIGSEGV. * Bug fix: SIGSEGV if the path given by iso_image_add_mips_boot_file() does not exist in the image at image production time. * Bug fix: While loading an ISO image: Several reads to malloc memory occured with byte index -1. (Found by Valgrind after years of operation without visible problems.) * Bug fix: Closed a memory leak of 32 kB per loaded ISO image. libisofs-1.0.6.tar.gz Sat Apr 09 2011 =============================================================================== * New API call iso_write_opts_set_joliet_long_names() * New error codes for oversized file addresses libisofs-1.0.4.tar.gz Thu Mar 10 2011 =============================================================================== * Bug fix: Compilation failed if --disable-zlib was configured * Bug fix: isohybrid image size was not aligned to cylinder boundary. * New no_md5 value 2 for API call iso_read_opts_set_no_md5() * New option bits 8 and 9 with iso_write_opts_set_system_area() libisofs-1.0.2.tar.gz Tue Feb 23 2011 =============================================================================== * Bug fix: iso_write_opts_set_aaip(opts, 1) could cause fatal miscalculation of the root directory size. This eventually truncated directory tree and spoiled all data file content. * Bug fix: Volume Descriptor Set Terminator contained non-zero bytes in the reserved field (ECMA-119 8.3.4). The bytes stem from the previously written Volume Descriptor. * New API calls iso_tree_clone(), iso_stream_clone. * New IsoFileSourceIface version 2 with method clone_src(). * New IsoStreamIface version 4 with method clone_stream(). * New public function prototype iso_node_xinfo_cloner. * New API calls iso_node_xinfo_make_clonable(), iso_node_xinfo_get_cloner(). * New public iso_node_xinfo_cloner instance aaip_xinfo_cloner(). * New API calls iso_node_get_next_xinfo(), iso_node_remove_all_xinfo(). * New API call iso_node_remove_tree(). * New API call iso_write_opts_set_old_empty(). libisofs-1.0.0.tar.gz Mon Jan 17 2011 =============================================================================== * Bug fix: ECMA-119 directory names were truncated to 8 characters if lowercase characters or full ASCII are allowed. * New API call iso_write_opts_set_untranslated_name_len() * New API call iso_write_opts_set_allow_dir_id_ext() * New API call iso_memory_stream_new(). (Was formely a private call.) libisofs-0.6.40.tar.gz Fri Dec 10 2010 =============================================================================== * New API call iso_write_opts_set_disc_label(), new system area type 3 = SUN Disk Label for booting SUN SPARC systems. * New API call iso_write_opts_set_will_cancel() avoids start of write thread and is to be used to inquire the future image size. * New error reply code ISO_DISPLACE_ROLLOVER for external data sources with address displacement. libisofs-0.6.38.tar.gz Sat Oct 23 2010 =============================================================================== * New API calls iso_write_opts_attach_jte() and iso_write_opts_detach_jte() allow to use libjte for jigdo production. * New API call iso_write_opts_set_tail_blocks() for tail padding inside ISO image. * New API call iso_image_generator_is_running() to learn when the write thread is done. * New API calls iso_image_add_mips_boot_file(), iso_image_get_mips_boot_files(), iso_image_give_up_mips_boot(). * New API call iso_write_opts_set_partition_img() for appending e.g. a small empty FAT12 filesystem which may be used on USB stick. libisofs-0.6.36.tar.gz Wed Sep 15 2010 =============================================================================== * New API function iso_write_opts_set_part_offset() controls creation of an MBR with a first partiton table entry that bears non-zero start address. A second set of volume descriptors and directory tree+tables gets created which can be used to mount the image at the partition start. * Hiding all non-API symbols from the linker by use of --version-script * Automatic C++ detection in libisofs.h by using macro __cplusplus * Corrected several memory leaks and potential NULL pointer evaluations in case of memory shortage. * Now with history of release notes in ./ChangeLog file. libisofs-0.6.34.tar.gz Tue Jun 29 2010 =============================================================================== * New API call iso_image_set_boot_catalog_hidden() * New API call iso_node_get_hidden() * New IsoHideNodeFlag bit LIBISO_HIDE_BUT_WRITE * New error code ISO_BOOT_NO_CATALOG * Opportunity to reduce compile line length by including "config.h" libisofs-0.6.32.tar.gz Mon May 03 2010 =============================================================================== * New API call iso_image_set_boot_catalog_weight() * New API call iso_image_add_boot_image() * New API calls el_torito_set_boot_platform_id(), el_torito_set_id_string(), el_torito_set_selection_crit() * New API calls iso_image_get_all_boot_imgs(), el_torito_get_boot_platform_id(), el_torito_get_load_seg(), el_torito_get_load_size(), el_torito_get_bootable(), el_torito_get_id_string(), el_torito_get_selection_crit(), el_torito_get_isolinux_options(), el_torito_get_boot_media_type() * New API call el_torito_seems_boot_info_table() libisofs-0.6.30.tar.gz Sat Apr 17 2010 =============================================================================== * New API call iso_write_opts_set_system_area() acts like mkisofs option -G. * New API call iso_write_opts_set_pvd_times(). * Now able to produce a bootable System Area from an ISOLINUX mbr/isohdp [fp]x*.bin file and an ISOLINUX El Torito bootable image (isolinux.bin). * Now able to produce the same Joliet names as mkisofs. * New API calls iso_read_opts_load_system_area() and iso_image_get_system_area() for multi-session handling of MBRs. libisofs-0.6.28.tar.gz Wed Feb 10 2010 =============================================================================== * Bug fix: Random checksum index could sneak in via boot catalog node and cause a SIGSEGV. * Improved compilability out of the box on FreeBSD. libisofs-0.6.26.tar.gz Wed Jan 20 2010 =============================================================================== * Bug fix: Invalid old checksum tags were preserved with iso_write_opts_set_overwrite_buf(), if the new session produced no checksums. * The checksum buffer for the emerging image gets now marked as invalid if image generation is canceled. * More graceful reaction on filesystems where ACL are not enabled but nevertheless requested by the application. * Adaptions to problems reported by Debian buildd. libisofs-0.6.24.tar.gz Thu Oct 08 2009 =============================================================================== * Bug fix: Short Rock Ridge names got stripped of trailing blanks when loaded and written again to a follow-up session. Long names could lose inner blanks. * Bug fix: Avoided to return NULL or single blanks as content of id strings by API calls iso_image_get_volset_id() ... iso_image_get_biblio_file_id(). * New API call iso_write_opts_set_scdbackup_tag(). libisofs-0.6.22.tar.gz Tue Aug 25 2009 =============================================================================== * New API call iso_write_opts_set_record_md5() for writing MD5 sums. * New API call iso_read_opts_set_no_md5() for importing MD5 sums. * New API calls iso_image_get_session_md5() and iso_file_get_md5(). * New API calls iso_md5_start(), iso_md5_compute(), iso_md5_clone(), iso_md5_end(), iso_md5_match() for own MD5 computations. * New API call iso_util_decode_md5_tag() to recognize and parse checksum tags. * New API call iso_file_make_md5() to equip old file nodes with MD5. * Improvements with ./configure and its help text. libisofs-0.6.20.tar.gz Sun May 30 2009 =============================================================================== * Optional automatic detection and recording of hard link relations between files. * Support for restoring hard link relations by the app. libisofs-0.6.18.tar.gz Fri Apr 17 2009 =============================================================================== * Opportunity to set the input charset automatically from an eventual xattr "isofs.cs" of the image root node. * New general filter API to inquire and remove filters. * Specialized APIs for installing filters which are based on external processes or based on zlib. * New API call to inquire the original source path of a data file in an emerging image. libisofs-0.6.16.tar.gz Wed Mar 11 =============================================================================== * Bug fix: The ".." directory record pointed to the same data block as the "." entry. * Bug fix: The use of iso_write_opts_set_rrip_version_1_10() caused a wrong size announcement in the CE entry which points to the ER signature of the image root. * New API call iso_write_opts_get_data_start() inquires the start address of the data section of an emerging ISO image. * ISO image generation does not absolutely depend on the availability of character set "WCHAR_T" with iconv_open(3) any more. libisofs-0.6.14.tar.gz Sat Feb 28 2009 =============================================================================== * New API calls iso_image_set_ignore_aclea(), iso_read_opts_set_no_aaip() control import of ACL and xattr. * New API calls iso_write_opts_set_aaip(), iso_write_opts_set_aaip_susp_1_10() control output of ACL and xattr into generated ISO image. * New API call iso_file_source_get_aa_string(), new function member get_aa_string() in IsoFileSource_Iface allow to access opaquely encoded ACL and xattr. New function handle aaip_xinfo_func attaches aa_strings to IsoNode objects. * New API calls iso_node_get_acl_text(), iso_node_set_acl_text(), iso_node_get_perms_wo_acl() allow inquiry and manipulation of ACLs in IsoNode objects. * New API calls iso_node_get_attrs(), iso_node_set_attrs() allow inquiry and manipulation of xattr in IsoNode objects. libisofs-0.6.12.tar.gz Wed Nov 26 2008 =============================================================================== * New API calls iso_set_local_charset() and iso_get_local_charset() * New API calls iso_write_opts_set_rrip_version_1_10() and iso_write_opts_set_dir_rec_mtime() * New API call el_torito_set_isolinux_options() allows to patch ISOLINUX boot images and to generate a isohybrid MBR on the fly. Such an MBR makes the ISO image bootable from disk-like hardware, e.g. from USB stick. The ISOLINUX boot image has to be of syslinux 3.72 or later to allow MBR generation. * Old API call el_torito_patch_isolinux_image() is deprecated now. libisofs-0.6.10.pl01.tar.gz Wed Nov 19 2008 =============================================================================== * Bug fix: If images generated by mkisofs were loaded then files of size 0 could share their size information with files that contain data. Ticket #144. * Bug fix: ISOLINUX boot images were patched suitable for El Torito but not for an eventual MBR added by SYSLINUX script isohybrid. libisofs 0.6.10 Mon Oct 6 2008: =============================================================================== * Bug fix: Patching of existing ISOLINUX boot images led to a SIGSEGV. * Bug fix: Adding a new ISOLINUX boot image or patching of an existing one caused a read operation although writing had already begun. libisofs-0.6.8.tar.gz Thu Sep 18 2008 =============================================================================== * Support for very large data files in the ISO 9660 image (Level 3, multi-extent) * Bug fix: it was assumed that isolinux images were always a multiple of 4 bytes * New API call iso_image_update_sizes() to refresh recorded file sizes immediately before image generation begins libisofs-0.6.6.tar.gz Sun Jun 1 2008 =============================================================================== * Bug fix: major,minor numbers of device files were not read properly from existing images * Bug fix: iso_tree_path_to_node() returned 1 if a directory path component was a non-directory file * New API call iso_special_get_dev() retrieves major, minor numbers of device files libisofs-0.6.4.tar.gz Sun Apr 27 2008 =============================================================================== * Extended information: iso_node_add_xinfo() * New node iteration: iso_dir_find_children() * Custom image file content via iso_tree_add_new_file() * Missing feature added to map a disk file to an arbitrary image file path via iso_tree_add_new_node() * Obtain image path of a node object via iso_tree_get_node_path() * Various bugfixes libisofs-0.6.2.1.tar.gz Thu Feb 14 2008 =============================================================================== * FIX: missing buffer.h preventing build from succeeding Libisofs 0.6.2 =============================================================================== * Initial release of new generation libisofs * Completely new API * Long term commitment to ABI libisofs.so.6 libisofs-1.4.2/COPYRIGHT0000644000175700017510000000151712555470477011600 00000000000000Vreixo Formoso , Mario Danic , Thomas Schmitt Copyright (C) 2007-2015 Vreixo Formoso, Mario Danic, Thomas Schmitt This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 or later as published by the Free Software Foundation. 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 libisofs-1.4.2/configure.ac0000644000175700017510000002051512626304673012563 00000000000000AC_INIT([libisofs], [1.4.2], [http://libburnia-project.org]) AC_PREREQ([2.50]) dnl AC_CONFIG_HEADER([config.h]) AC_CANONICAL_HOST AC_CANONICAL_TARGET LIBBURNIA_SET_FLAGS AM_INIT_AUTOMAKE([subdir-objects]) AC_CONFIG_MACRO_DIR([./]) dnl dnl if MAJOR or MINOR version changes, be sure to change AC_INIT above to match dnl dnl CURRENT and AGE describe the binary compatibility interval of a dnl dynamic library. dnl See also http://www.gnu.org/software/libtool/manual.html#Interfaces dnl dnl The name of the library will be libisofs.so.$CURRENT-$AGE.$AGE.$REV dnl In the terminology of this file: dnl CURRENT = LT_CURRENT dnl REV = LT_REVISION dnl AGE = LT_AGE dnl dnl LT_CURRENT, LT_REVISION and LT_AGE get set directly now. dnl dnl SONAME of the emerging library is LT_CURRENT - LT_AGE. dnl The linker will do no finer checks. Especially no age range check for dnl the cdrskin binary. If SONAME matches, then the couple starts. dnl dnl Therefore a run time check is provided by libisofs function dnl iso_lib_version(). It returns the major, minor and micro revision of the dnl library. This means LIBISOFS_*_VERSION kept its second job which does not dnl comply to the usual ways of configure.ac . I.e. now *officially* this is dnl the source code release version as announced to the public. It has no dnl connection to SONAME or libtool version numbering. dnl It rather feeds the API function iso_lib_version(). dnl dnl If LIBISOFS_*_VERSION changes, be sure to change AC_INIT above to match. dnl LIBISOFS_MAJOR_VERSION=1 LIBISOFS_MINOR_VERSION=4 LIBISOFS_MICRO_VERSION=2 LIBISOFS_VERSION=$LIBISOFS_MAJOR_VERSION.$LIBISOFS_MINOR_VERSION.$LIBISOFS_MICRO_VERSION AC_SUBST(LIBISOFS_MAJOR_VERSION) AC_SUBST(LIBISOFS_MINOR_VERSION) AC_SUBST(LIBISOFS_MICRO_VERSION) AC_SUBST(LIBISOFS_VERSION) dnl Libtool versioning LT_RELEASE=$LIBISOFS_MAJOR_VERSION.$LIBISOFS_MINOR_VERSION # 2015.11.28 development jump has not yet happened # SONAME = 84 - 78 = 6 . Library name = libisofs.6.78.0 LT_CURRENT=84 LT_AGE=78 LT_REVISION=0 LT_CURRENT_MINUS_AGE=`expr $LT_CURRENT - $LT_AGE` AC_SUBST(LT_RELEASE) AC_SUBST(LT_CURRENT) AC_SUBST(LT_REVISION) AC_SUBST(LT_AGE) AC_SUBST(LT_CURRENT_MINUS_AGE) AC_PREFIX_DEFAULT([/usr/local]) test "$prefix" = "NONE" && prefix=$ac_default_prefix AM_MAINTAINER_MODE AM_PROG_CC_C_O AC_C_CONST AC_C_INLINE AC_C_BIGENDIAN dnl Large file support AC_SYS_LARGEFILE AC_FUNC_FSEEKO AC_CHECK_FUNC([fseeko]) if test ! $ac_cv_func_fseeko; then AC_MSG_ERROR([Libisofs requires largefile support.]) fi dnl If iconv(3) is in an extra lib, then it gets added to variable LIBS. dnl If not, then no -liconv will be added. LIBBURNIA_CHECK_ICONV dnl To abort configuration if iconv() still cannot be compiled LIBBURNIA_ASSERT_ICONV AC_PROG_LIBTOOL AC_SUBST(LIBTOOL_DEPS) LIBTOOL="$LIBTOOL --silent" AC_PROG_INSTALL AC_CHECK_HEADERS() dnl Use GNU extensions if available AC_DEFINE(_GNU_SOURCE, 1) dnl Check for tm_gmtoff field in struct tm AC_CHECK_MEMBER([struct tm.tm_gmtoff], [AC_DEFINE(HAVE_TM_GMTOFF, 1, [Define this if tm structure includes a tm_gmtoff entry.])], , [#include ]) dnl Check if non standard timegm() function is available AC_CHECK_DECL([timegm], [AC_DEFINE(HAVE_TIMEGM, 1, [Define this if timegm function is available])], , [#include ]) dnl Whether timezone is an integer variable AH_TEMPLATE([Libburnia_timezonE], [Either timezone or 0]) LIBBURNIA_TRY_TIMEZONE if test x$LIBBURNIA_TIMEZONE = xtimezone then AC_DEFINE([Libburnia_timezonE], [timezone]) else AC_DEFINE([Libburnia_timezonE], [0]) fi dnl Check if non standard eaccess() function is available AC_CHECK_DECL([eaccess], [AC_DEFINE(HAVE_EACCESS, 1, [Define this if eaccess function is available])], , [#include ]) THREAD_LIBS=-lpthread AC_SUBST(THREAD_LIBS) TARGET_SHIZZLE AC_SUBST(ARCH) AC_SUBST(LIBBURN_ARCH_LIBS) dnl See if the user wants aggressive optimizations of the code AC_ARG_ENABLE(debug, [ --enable-debug Disable aggressive optimizations, default=yes], , enable_debug=yes) if test x$enable_debug != xyes; then if test x$GCC = xyes; then CFLAGS="-O3 $CFLAGS" CFLAGS="-fexpensive-optimizations $CFLAGS" fi CFLAGS="-DNDEBUG $CFLAGS" else if test x$GCC = xyes; then CFLAGS="-g -pedantic -Wall -Wextra -Wno-unused-parameter -Wno-char-subscripts $CFLAGS" fi CFLAGS="-DDEBUG $CFLAGS" fi dnl Verbose debug to make libisofs issue more debug messages AC_ARG_ENABLE(verbose-debug, [ --enable-verbose-debug Enable verbose debug messages, default=no], AC_DEFINE(LIBISOFS_VERBOSE_DEBUG, 1)) dnl Determine target directory for libisofs-*.pc dnl Important: Must be performed _after_ TARGET_SHIZZLE dnl LIBBURNIA_SET_PKGCONFIG dnl Add compiler-specific flags AC_ARG_ENABLE(libacl, [ --enable-libacl Enable use of ACL functions by libisofs, default=yes], , enable_libacl=yes) if test "x$enable_libacl" = xyes; then dnl Check whether there is libacl-devel and libacl-runtime. dnl If not, erase this macro which would enable use of acl_to_text and others LIBACL_DEF="-DLibisofs_with_aaip_acL" dnl The empty yes case obviously causes -lacl to be linked has_acl_h_but_no_func=0 AC_CHECK_HEADER(sys/acl.h, AC_CHECK_LIB(acl, acl_to_text, , has_acl_h_but_no_libacl=1 ), LIBACL_DEF= ) if test "$has_acl_h_but_no_libacl" = 1 then AC_CHECK_LIB(c, acl_to_text, X= , LIBACL_DEF= ) fi else LIBACL_DEF= fi AC_SUBST(LIBACL_DEF) dnl ts A90123 AC_ARG_ENABLE(xattr, [ --enable-xattr Enable use of xattr by libisofs, default=yes], , enable_xattr=yes) if test "x$enable_xattr" = xyes; then dnl Check whether there is the header for Linux xattr. dnl If not, erase this macro which would enable use of listxattr and others XATTR_DEF="-DLibisofs_with_aaip_xattR" AC_CHECK_HEADER(attr/xattr.h, AC_CHECK_LIB(c, listxattr, X= , XATTR_DEF= ), XATTR_DEF= ) if test "x$XATTR_DEF" = x then XATTR_DEF="-DLibisofs_with_freebsd_extattR" AC_CHECK_HEADER(sys/extattr.h, AC_CHECK_LIB(c, extattr_list_file, X=, XATTR_DEF= ), XATTR_DEF= ) fi else XATTR_DEF= fi AC_SUBST(XATTR_DEF) dnl ts A90409 AC_ARG_ENABLE(zlib, [ --enable-zlib Enable use of zlib by libisofs, default=yes], , enable_zlib=yes) if test "x$enable_zlib" = xyes; then dnl Check whether there is the header for zlib. dnl If not, erase this macro which would enable use of compress2() and others. dnl Linking fails on SuSE 9.0 because zlib has compress2() but lacks dnl compressBound(). So compressBound is the more modern thing to test. dnl The empty parameter after "compressBound" causes -lz. ZLIB_DEF="-DLibisofs_with_zliB" AC_CHECK_HEADER(zlib.h, AC_CHECK_LIB(z, compressBound, , ZLIB_DEF= ), ZLIB_DEF= ) else ZLIB_DEF= fi AC_SUBST(ZLIB_DEF) dnl ts B00927 AC_ARG_ENABLE(libjte, [ --enable-libjte Enable use of libjte by libisofs, default=yes], , enable_libjte=yes) if test "x$enable_libjte" = xyes; then LIBJTE_DEF="-DLibisofs_with_libjtE" AC_CHECK_HEADER(libjte/libjte.h, AC_CHECK_LIB(jte, libjte_new, , LIBJTE_DEF= ), LIBJTE_DEF= ) else LIBJTE_DEF= fi AC_SUBST(LIBJTE_DEF) # Library versioning normally serves a complex purpose. # Since libisofs obeys strict ABI backward compatibility, it needs only the # simple feature to declare function names "global:" or "local:". Only the # global ones are visible to applications at library load time. AC_ARG_ENABLE(versioned-libs, [ --enable-versioned-libs Enable strict symbol encapsulation , default=yes], , enable_versioned_libs=yes) if test x$enable_versioned_libs = xyes; then vers_libs_test=no LIBISOFS_ASSERT_VERS_LIBS if test x$vers_libs_test = xno then echo "disabled strict symbol encapsulation (test failed)" else echo "enabled strict symbol encapsulation" fi else echo "disabled strict symbol encapsulation" fi AC_ARG_ENABLE(ldconfig-at-install, [ --enable-ldconfig-at-install On GNU/Linux run ldconfig, default=yes], , ldconfig_at_install=yes) if test x$ldconfig_at_install = xyes; then dummy=dummy else LIBBURNIA_LDCONFIG_CMD="echo 'NOTE: ldconfig is disabled. If needed, configure manually for:'" echo "disabled run of ldconfig during installation on GNU/Linux" fi AC_SUBST(LIBBURNIA_LDCONFIG_CMD) AC_CONFIG_FILES([ Makefile doc/doxygen.conf version.h libisofs-1.pc ]) AC_OUTPUT libisofs-1.4.2/libtool.m40000644000175700017510000106022712626305073012203 00000000000000# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010, 2011 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) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010, 2011 Free Software # Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is part of GNU Libtool. # # 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 GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, or # obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ]) # serial 57 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.58])dnl We use AC_INCLUDES_DEFAULT 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_CC_BASENAME(CC) # ------------------- # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. m4_defun([_LT_CC_BASENAME], [for cc_temp in $1""; do case $cc_temp in compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` ]) # _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_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 _LT_CONFIG_LIBTOOL_INIT([ # See if we are running on zsh, and set the options which 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 "X${COLLECT_NAMES+set}" != Xset; 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, # which needs '.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\\"\\\`\\\\\\"" ;; *) 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\\"\\\`\\\\\\"" ;; *) 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 $lt_write_fail = 0 && 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 "$silent" = yes && 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 which 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 # `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $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. # _LT_COPYING _LT_LIBTOOL_TAGS # ### BEGIN LIBTOOL CONFIG _LT_LIBTOOL_CONFIG_VARS _LT_LIBTOOL_TAG_VARS # ### END LIBTOOL CONFIG _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 "X${COLLECT_NAMES+set}" != Xset; 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) _LT_PROG_REPLACE_SHELLFNS 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' TIMESTAMP='$TIMESTAMP' 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 $_lt_result -eq 0; 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 cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD $AR cru 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 $_lt_result -eq 0 && $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*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; 10.[[012]]*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test "$lt_cv_apple_cc_single_mod" = "yes"; then _lt_dar_single_mod='$single_module' fi if test "$lt_cv_ld_exported_symbols_list" = "yes"; 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 "$lt_cv_ld_force_load" = "no"; 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 "$lt_cv_ld_force_load" = "yes"; 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*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test "$_lt_dar_can_shared" = "yes"; 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 "$lt_cv_apple_cc_single_mod" != "yes"; 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 "${lt_cv_aix_libpath+set}" = 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 which will find a shell with a builtin # printf (which 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], [AC_MSG_CHECKING([for sysroot]) AC_ARG_WITH([sysroot], [ --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 "$GCC" = yes; 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 in which 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 "x$enable_libtool_lock" != xno && 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 which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE="32" ;; *ELF-64*) HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file 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* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) case `/usr/bin/file conftest.o` in *x86-64*) LD="${LD-ld} -m elf32_x86_64" ;; *) LD="${LD-ld} -m elf_i386" ;; esac ;; powerpc64le-*) LD="${LD-ld} -m elf32lppclinux" ;; powerpc64-*) 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-*) LD="${LD-ld} -m elf64lppc" ;; powerpc-*) 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 x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; *-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-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} : ${AR_FLAGS=cru} _LT_DECL([], [AR], [1], [The archiver]) _LT_DECL([], [AR_FLAGS], [1], [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 "$ac_status" -eq 0; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a AC_TRY_EVAL([lt_ar_try]) if test "$ac_status" -ne 0; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a ]) ]) if test "x$lt_cv_ar_at_file" = xno; 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 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" # 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 x"[$]$2" = xyes; 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 x"[$]$2" = xyes; 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; ;; netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) # 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 $i != 17 # 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 "$cross_compiling" = yes; 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 -fvisbility=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 "x$enable_dlopen" != xyes; 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 ]) ;; *) 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 "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && 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 "x$lt_cv_dlopen_self" = xyes; 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 "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; 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 "$hard_links" = no; 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 in which 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 "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then # We can hardcode non-existent directories. if test "$_LT_TAGVAR(hardcode_direct, $1)" != no && # 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 "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no && test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; 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 "$_LT_TAGVAR(hardcode_action, $1)" = relink || test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; 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 -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" AC_MSG_RESULT([yes]) else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" old_striplib="$STRIP -S" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi ;; *) AC_MSG_RESULT([no]) ;; esac fi _LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) _LT_DECL([], [striplib], [1]) ])# _LT_CMD_STRIPLIB # _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 AC_MSG_CHECKING([dynamic linker characteristics]) m4_if([$1], [], [ if test "$GCC" = yes; 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` 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" else 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 "$host_cpu" = ia64; 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 # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # 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}' else # 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' fi 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%'\''`; test $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*) # Native MSVC 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 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*) # 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} $libname${shared_ext}' 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=yes 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 "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; 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 "$lt_cv_prog_gnu_ld" = yes; 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 ;; # 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 # Append ld.so.conf contents 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' ;; netbsdelf*-gnu) version_type=linux 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='NetBSD ld.elf_so' ;; netbsd*) # ts B51007 : changed version_type for lt_main.sh from "sunos" to "netbsd" version_type=netbsd 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*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac 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 if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[[89]] | openbsd2.[[89]].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; 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 "$with_gnu_ld" = yes; 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=freebsd-elf 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 "$with_gnu_ld" = yes; 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 "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi _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], [2], [Run-time system search path for libraries]) ])# _LT_SYS_DYNAMIC_LINKER # _LT_PATH_TOOL_PREFIX(TOOL) # -------------------------- # find a file program which 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 which 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 "$withval" = no || with_gnu_ld=yes], [with_gnu_ld=no])dnl ac_prog=ld if test "$GCC" = yes; 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 "$with_gnu_ld" = yes; 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 /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*) 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=/usr/bin/file 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=/usr/bin/file 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* | netbsdelf*-gnu) 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=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; 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 ;; 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 case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) 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 "$lt_cv_path_NM" != "no"; 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 /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols" ;; *) 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 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 "x$lt_cv_path_mainfest_tool" != xyes; then MANIFEST_TOOL=: fi _LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl ])# _LT_PATH_MANIFEST_TOOL # 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 "$GCC" = yes; 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 "$host_cpu" = ia64; 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 # 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 -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$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 -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'" lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/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 # and D for any global variable. # Also find C++ and __fastcall symbols from MSVC++, # 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};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ " {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ " s[1]~/^[@?]/{print s[1], s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print 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 con'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* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$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 "$pipe_works" = yes; 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_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_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 "$GXX" = yes; 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 "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; 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']) ;; 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 "$host_cpu" = ia64; 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*) # 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 "$host_cpu" != ia64; 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* | netbsdelf*-gnu) ;; *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 "$GCC" = yes; 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 "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; 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']) ;; 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 "$host_cpu" = ia64; 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 ;; 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']) ;; 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' ;; 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 which 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 AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global defined # symbols, whereas GNU nm marks them as "W". 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) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi ;; pw32*) _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" ;; cygwin* | mingw* | cegcc*) case $cc_basename in cl*) _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 ;; linux* | k*bsd*-gnu | gnu*) _LT_TAGVAR(link_all_deplibs, $1)=no ;; *) _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++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; linux* | k*bsd*-gnu | gnu*) _LT_TAGVAR(link_all_deplibs, $1)=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 "$with_gnu_ld" = yes; 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 "$lt_use_gnu_ld_interface" = yes; 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 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 "$host_cpu" != ia64; 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 (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; 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 ;; 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 "$host_os" = linux-dietlibc; 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 "$tmp_diet" = no 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' ;; 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 "x$supports_anon_versioning" = xyes; 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 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 "x$supports_anon_versioning" = xyes; 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* | netbsdelf*-gnu) 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 can not *** 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 "$_LT_TAGVAR(ld_shlibs, $1)" = no; 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 "$GCC" = yes && 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 "$host_cpu" = ia64; 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 AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global # defined symbols, whereas GNU nm marks them as "W". 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) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | 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 # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; 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,' if test "$GCC" = yes; 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 "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi _LT_TAGVAR(link_all_deplibs, $1)=no else # not using gcc if test "$host_cpu" = ia64; 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 "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi 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_use_runtimelinking" = yes; 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 "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; 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 "$with_gnu_ld" = yes; 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 # This is similar to how AIX traditionally builds its shared libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' 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++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC _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~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $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 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*) _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 "$GCC" = yes; 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 $output_objdir/$soname = $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 $output_objdir/$soname = $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 "$GCC" = yes && test "$with_gnu_ld" = no; 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 "$with_gnu_ld" = no; 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 "$GCC" = yes && test "$with_gnu_ld" = no; 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 "$with_gnu_ld" = no; 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 "$GCC" = yes; 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 "$lt_cv_irix_exported_symbol" = yes; 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 ;; netbsd* | netbsdelf*-gnu) 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*) 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__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; 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 case $host_os in openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' ;; *) _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' ;; esac 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 _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; 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 "$GCC" = yes; 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 "$GCC" = yes; 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 "$GCC" = yes; 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 "x$host_vendor" = xsequent; 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 "$GCC" = yes; 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 can NOT 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 "$GCC" = yes; 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 x$host_vendor = xsni; 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 "$_LT_TAGVAR(ld_shlibs, $1)" = no && 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 "$enable_shared" = yes && test "$GCC" = yes; 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 which 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 "$can_build_shared" = "no" && 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 "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no 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 "$enable_shared" = yes || 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 "X$CXX" != "Xno" && ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || (test "X$CXX" != "Xg++"))) ; 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 "$_lt_caught_CXX_error" != yes; 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 "$GXX" = yes; 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 "$GXX" = yes; 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 "$with_gnu_ld" = yes; 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 "$host_cpu" = ia64; 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 # need to do runtime linking. 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 ;; 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,' if test "$GXX" = yes; 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 "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; 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 "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi 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_use_runtimelinking" = yes; 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 "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; 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 "$with_gnu_ld" = yes; 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 # This is similar to how AIX traditionally builds its shared # libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' 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*) # Native MSVC # 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~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $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 (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; 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) ;; 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*) # 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 $output_objdir/$soname = $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 "$GXX" = yes; 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 $output_objdir/$soname = $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 $with_gnu_ld = no; 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 "$GXX" = yes; then if test $with_gnu_ld = no; 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 "$GXX" = yes; then if test "$with_gnu_ld" = no; 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 "x$supports_anon_versioning" = xyes; 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 ;; openbsd2*) # C++ shared libraries are fairly broken _LT_TAGVAR(ld_shlibs, $1)=no ;; openbsd*) 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__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; 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 "$GXX" = yes && test "$with_gnu_ld" = no; 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 "$GXX" = yes && test "$with_gnu_ld" = no; 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 $LDFLAGS $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 -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 $LDFLAGS $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 -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 can NOT 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 "$_LT_TAGVAR(ld_shlibs, $1)" = no && 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 "$_lt_caught_CXX_error" != yes 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 ${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 ])# _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 $p = "-L" || test $p = "-R"; 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 "$pre_test_object_deps_done" = no; 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 "$pre_test_object_deps_done" = no; 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)= ;; linux*) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac if test "$solaris_use_stlport4" != yes; then _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' fi ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac # Adding this requires a known-good setup of shared libraries for # Sun compiler versions before 5.6, else PIC objects from an old # archive will be linked into the output, leading to subtle bugs. if test "$solaris_use_stlport4" != yes; then _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' fi ;; esac ;; 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 "X$F77" = "Xno"; 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 "$_lt_disable_F77" != yes; 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 "$can_build_shared" = "no" && 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 "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no 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 "$enable_shared" = yes || 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 "$_lt_disable_F77" != yes 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 "X$FC" = "Xno"; 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 "$_lt_disable_FC" != yes; 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 "$can_build_shared" = "no" && 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 "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no 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 "$enable_shared" = yes || 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 "$_lt_disable_FC" != yes 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 "x${GCJFLAGS+set}" = xset || 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_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 $lt_ac_count -gt 10 && 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], [AC_MSG_CHECKING([whether the shell understands some XSI constructs]) # Try some XSI features xsi_shell=no ( _lt_dummy="a/b/c" test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ = c,a/b,b/c, \ && eval 'test $(( 1 + 1 )) -eq 2 \ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ && xsi_shell=yes AC_MSG_RESULT([$xsi_shell]) _LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell']) AC_MSG_CHECKING([whether the shell understands "+="]) lt_shell_append=no ( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \ >/dev/null 2>&1 \ && lt_shell_append=yes AC_MSG_RESULT([$lt_shell_append]) _LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append']) 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_PROG_FUNCTION_REPLACE (FUNCNAME, REPLACEMENT-BODY) # ------------------------------------------------------ # In `$cfgfile', look for function FUNCNAME delimited by `^FUNCNAME ()$' and # '^} FUNCNAME ', and replace its body with REPLACEMENT-BODY. m4_defun([_LT_PROG_FUNCTION_REPLACE], [dnl { sed -e '/^$1 ()$/,/^} # $1 /c\ $1 ()\ {\ m4_bpatsubsts([$2], [$], [\\], [^\([ ]\)], [\\\1]) } # Extended-shell $1 implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: ]) # _LT_PROG_REPLACE_SHELLFNS # ------------------------- # Replace existing portable implementations of several shell functions with # equivalent extended shell implementations where those features are available.. m4_defun([_LT_PROG_REPLACE_SHELLFNS], [if test x"$xsi_shell" = xyes; then _LT_PROG_FUNCTION_REPLACE([func_dirname], [dnl case ${1} in */*) func_dirname_result="${1%/*}${2}" ;; * ) func_dirname_result="${3}" ;; esac]) _LT_PROG_FUNCTION_REPLACE([func_basename], [dnl func_basename_result="${1##*/}"]) _LT_PROG_FUNCTION_REPLACE([func_dirname_and_basename], [dnl case ${1} in */*) func_dirname_result="${1%/*}${2}" ;; * ) func_dirname_result="${3}" ;; esac func_basename_result="${1##*/}"]) _LT_PROG_FUNCTION_REPLACE([func_stripname], [dnl # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are # positional parameters, so assign one to ordinary parameter first. func_stripname_result=${3} func_stripname_result=${func_stripname_result#"${1}"} func_stripname_result=${func_stripname_result%"${2}"}]) _LT_PROG_FUNCTION_REPLACE([func_split_long_opt], [dnl func_split_long_opt_name=${1%%=*} func_split_long_opt_arg=${1#*=}]) _LT_PROG_FUNCTION_REPLACE([func_split_short_opt], [dnl func_split_short_opt_arg=${1#??} func_split_short_opt_name=${1%"$func_split_short_opt_arg"}]) _LT_PROG_FUNCTION_REPLACE([func_lo2o], [dnl case ${1} in *.lo) func_lo2o_result=${1%.lo}.${objext} ;; *) func_lo2o_result=${1} ;; esac]) _LT_PROG_FUNCTION_REPLACE([func_xform], [ func_xform_result=${1%.*}.lo]) _LT_PROG_FUNCTION_REPLACE([func_arith], [ func_arith_result=$(( $[*] ))]) _LT_PROG_FUNCTION_REPLACE([func_len], [ func_len_result=${#1}]) fi if test x"$lt_shell_append" = xyes; then _LT_PROG_FUNCTION_REPLACE([func_append], [ eval "${1}+=\\${2}"]) _LT_PROG_FUNCTION_REPLACE([func_append_quoted], [dnl func_quote_for_eval "${2}" dnl m4 expansion turns \\\\ into \\, and then the shell eval turns that into \ eval "${1}+=\\\\ \\$func_quote_for_eval_result"]) # Save a `func_append' function call where possible by direct use of '+=' sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: else # Save a `func_append' function call even when '+=' is not available sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: fi if test x"$_lt_function_replace_fail" = x":"; then AC_MSG_WARN([Unable to substitute extended shell functions in $ofile]) fi ]) # _LT_PATH_CONVERSION_FUNCTIONS # ----------------------------- # Determine which 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