commit
9b92536e6c
@ -0,0 +1,6 @@
|
|||||||
|
Timothy Pearson (kb9vqf at pearsoncomputing dot net)
|
||||||
|
|
||||||
|
Erich Hoover (ehoover at mines dot edu)
|
||||||
|
|
||||||
|
Read-only Backend:
|
||||||
|
Martin Rosenau
|
@ -0,0 +1,39 @@
|
|||||||
|
0.6.0:
|
||||||
|
* Fixed some bugs with libbfd on Ubuntu 10.10.
|
||||||
|
* Added some additional error checking for libbfd.
|
||||||
|
* Deprecated "GUID naming" in favor of "UUID naming".
|
||||||
|
* Added support for extracting special 'one canvas' SVG icons.
|
||||||
|
0.5.0:
|
||||||
|
* Added read-only backend.
|
||||||
|
* Added documentation for the icon management API.
|
||||||
|
* Added pkg-config file generation and installation.
|
||||||
|
* Added initial support for manpages through doxygen.
|
||||||
|
* Added documentation for the main resource management API.
|
||||||
|
0.4.2:
|
||||||
|
* Temporary files are no-longer stored in the active directory.
|
||||||
|
* Handles are now automatically cleaned up when libr exits memory.
|
||||||
|
0.4.1:
|
||||||
|
* New procedure for producing packages.
|
||||||
|
* Fixed a bug with sscanf under specific new GCC versions.
|
||||||
|
0.4.0:
|
||||||
|
* Created a convenience API for using libr with gettext.
|
||||||
|
* Added support for GtkBuilder in GTK+ convenience functions.
|
||||||
|
* Now using weak linking to simplify testing whether GTK+ symbols are available.
|
||||||
|
* GTK+ routines can now auto-load other resources (such as bitmaps) from binaries.
|
||||||
|
|
||||||
|
Major bug fixes:
|
||||||
|
1) Fixed a problem with dynamically loading GTK+ on 64-bit systems.
|
||||||
|
2) Fixed several problems keeping libr from being statically linked in applications.
|
||||||
|
0.3.1:
|
||||||
|
* Report descriptive errors for problems.
|
||||||
|
* Made icon routines thread safe.
|
||||||
|
|
||||||
|
Major bug fixes:
|
||||||
|
1) Replacing an icon added duplicate entries to the icon table
|
||||||
|
2) File uid and gid were not preserved
|
||||||
|
0.3.0:
|
||||||
|
* Created a convenience API for using libr with GTK+.
|
||||||
|
0.2.1:
|
||||||
|
* Minor bug fixes.
|
||||||
|
0.2.0:
|
||||||
|
* Initial public "libr" library implementation with option (default) of using libbfd.
|
@ -0,0 +1,302 @@
|
|||||||
|
Installation Instructions
|
||||||
|
*************************
|
||||||
|
|
||||||
|
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
|
||||||
|
2006, 2007, 2008, 2009 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.
|
||||||
|
|
||||||
|
6. Often, you can also type `make uninstall' to remove the installed
|
||||||
|
files again.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
On MacOS X 10.5 and later systems, you can create libraries and
|
||||||
|
executables that work on multiple system types--known as "fat" or
|
||||||
|
"universal" binaries--by specifying multiple `-arch' options to the
|
||||||
|
compiler but only a single `-arch' option to the preprocessor. Like
|
||||||
|
this:
|
||||||
|
|
||||||
|
./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
|
||||||
|
CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
|
||||||
|
CPP="gcc -E" CXXCPP="g++ -E"
|
||||||
|
|
||||||
|
This is not guaranteed to produce working output in all cases, you
|
||||||
|
may have to build one architecture at a time and combine the results
|
||||||
|
using the `lipo' tool if you have problems.
|
||||||
|
|
||||||
|
Installation Names
|
||||||
|
==================
|
||||||
|
|
||||||
|
By default, `make install' installs the package's commands under
|
||||||
|
`/usr/local/bin', include files under `/usr/local/include', etc. You
|
||||||
|
can specify an installation prefix other than `/usr/local' by giving
|
||||||
|
`configure' the option `--prefix=PREFIX'.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
Particular systems
|
||||||
|
==================
|
||||||
|
|
||||||
|
On HP-UX, the default C compiler is not ANSI C compatible. If GNU
|
||||||
|
CC is not installed, it is recommended to use the following options in
|
||||||
|
order to use an ANSI C compiler:
|
||||||
|
|
||||||
|
./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
|
||||||
|
|
||||||
|
and if that doesn't work, install pre-built binaries of GCC for HP-UX.
|
||||||
|
|
||||||
|
On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
|
||||||
|
parse its `<wchar.h>' header file. The option `-nodtk' can be used as
|
||||||
|
a workaround. If GNU CC is not installed, it is therefore recommended
|
||||||
|
to try
|
||||||
|
|
||||||
|
./configure CC="cc"
|
||||||
|
|
||||||
|
and if that doesn't work, try
|
||||||
|
|
||||||
|
./configure CC="cc -nodtk"
|
||||||
|
|
||||||
|
On Solaris, don't put `/usr/ucb' early in your `PATH'. This
|
||||||
|
directory contains several dysfunctional programs; working variants of
|
||||||
|
these programs are available in `/usr/bin'. So, if you need `/usr/ucb'
|
||||||
|
in your `PATH', put it _after_ `/usr/bin'.
|
||||||
|
|
||||||
|
On Haiku, software installed for all users goes in `/boot/common',
|
||||||
|
not `/usr/local'. It is recommended to use the following options:
|
||||||
|
|
||||||
|
./configure --prefix=/boot/common
|
||||||
|
|
||||||
|
Specifying the System Type
|
||||||
|
==========================
|
||||||
|
|
||||||
|
There may be some features `configure' cannot figure out
|
||||||
|
automatically, but needs to determine by the type of machine the package
|
||||||
|
will run on. Usually, assuming the package is built to be run on the
|
||||||
|
_same_ architectures, `configure' can figure that out, but if it prints
|
||||||
|
a message saying it cannot guess the machine type, give it the
|
||||||
|
`--build=TYPE' option. TYPE can either be a short name for the system
|
||||||
|
type, such as `sun4', or a canonical name which has the form:
|
||||||
|
|
||||||
|
CPU-COMPANY-SYSTEM
|
||||||
|
|
||||||
|
where SYSTEM can have one of these forms:
|
||||||
|
|
||||||
|
OS
|
||||||
|
KERNEL-OS
|
||||||
|
|
||||||
|
See the file `config.sub' for the possible values of each field. If
|
||||||
|
`config.sub' isn't included in this package, then this package doesn't
|
||||||
|
need to know the machine type.
|
||||||
|
|
||||||
|
If you are _building_ compiler tools for cross-compiling, you should
|
||||||
|
use the option `--target=TYPE' to select the type of system they will
|
||||||
|
produce code for.
|
||||||
|
|
||||||
|
If you want to _use_ a cross compiler, that generates code for a
|
||||||
|
platform different from the build platform, you should specify the
|
||||||
|
"host" platform (i.e., that on which the generated programs will
|
||||||
|
eventually be run) with `--host=TYPE'.
|
||||||
|
|
||||||
|
Sharing Defaults
|
||||||
|
================
|
||||||
|
|
||||||
|
If you want to set default values for `configure' scripts to share,
|
||||||
|
you can create a site shell script called `config.site' that gives
|
||||||
|
default values for variables like `CC', `cache_file', and `prefix'.
|
||||||
|
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
||||||
|
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
||||||
|
`CONFIG_SITE' environment variable to the location of the site script.
|
||||||
|
A warning: not all `configure' scripts look for a site script.
|
||||||
|
|
||||||
|
Defining Variables
|
||||||
|
==================
|
||||||
|
|
||||||
|
Variables not defined in a site shell script can be set in the
|
||||||
|
environment passed to `configure'. However, some packages may run
|
||||||
|
configure again during the build, and the customized values of these
|
||||||
|
variables may be lost. In order to avoid this problem, you should set
|
||||||
|
them in the `configure' command line, using `VAR=value'. For example:
|
||||||
|
|
||||||
|
./configure CC=/usr/local2/bin/gcc
|
||||||
|
|
||||||
|
causes the specified `gcc' to be used as the C compiler (unless it is
|
||||||
|
overridden in the site shell script).
|
||||||
|
|
||||||
|
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
|
||||||
|
an Autoconf 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 all of the options to `configure', and exit.
|
||||||
|
|
||||||
|
`--help=short'
|
||||||
|
`--help=recursive'
|
||||||
|
Print a summary of the options unique to this package's
|
||||||
|
`configure', and exit. The `short' variant lists options used
|
||||||
|
only in the top level, while the `recursive' variant lists options
|
||||||
|
also present in any nested packages.
|
||||||
|
|
||||||
|
`--version'
|
||||||
|
`-V'
|
||||||
|
Print the version of Autoconf used to generate the `configure'
|
||||||
|
script, and exit.
|
||||||
|
|
||||||
|
`--cache-file=FILE'
|
||||||
|
Enable the cache: use and save the results of the tests in FILE,
|
||||||
|
traditionally `config.cache'. FILE defaults to `/dev/null' to
|
||||||
|
disable caching.
|
||||||
|
|
||||||
|
`--config-cache'
|
||||||
|
`-C'
|
||||||
|
Alias for `--cache-file=config.cache'.
|
||||||
|
|
||||||
|
`--quiet'
|
||||||
|
`--silent'
|
||||||
|
`-q'
|
||||||
|
Do not print messages saying which checks are being made. To
|
||||||
|
suppress all normal output, redirect it to `/dev/null' (any error
|
||||||
|
messages will still be shown).
|
||||||
|
|
||||||
|
`--srcdir=DIR'
|
||||||
|
Look for the package's source code in directory DIR. Usually
|
||||||
|
`configure' can determine that directory automatically.
|
||||||
|
|
||||||
|
`--prefix=DIR'
|
||||||
|
Use DIR as the installation prefix. *Note Installation Names::
|
||||||
|
for more details, including other options available for fine-tuning
|
||||||
|
the installation locations.
|
||||||
|
|
||||||
|
`--no-create'
|
||||||
|
`-n'
|
||||||
|
Run the configure checks, but stop before creating any output
|
||||||
|
files.
|
||||||
|
|
||||||
|
`configure' also accepts some other, not widely useful, options. Run
|
||||||
|
`configure --help' for more details.
|
||||||
|
|
@ -0,0 +1,24 @@
|
|||||||
|
EXTRA_DIST = config.rpath m4/ChangeLog
|
||||||
|
LIBTOOL_DEPS = @LIBTOOL_DEPS@
|
||||||
|
instdir = @libdir@/pkgconfig
|
||||||
|
ACLOCAL_AMFLAGS = -I m4
|
||||||
|
SUBDIRS = po src man
|
||||||
|
SED_REPLACE = \
|
||||||
|
-e 's=\@prefix\@=@prefix@=' \
|
||||||
|
-e 's=\@libdir\@=@libdir@=' \
|
||||||
|
-e 's=\@VERSION\@=@VERSION@=' \
|
||||||
|
-e 's=\@exec_prefix\@=@exec_prefix@=' \
|
||||||
|
-e 's=\@includedir\@=@includedir@/libr='
|
||||||
|
|
||||||
|
libtool: $(LIBTOOL_DEPS)
|
||||||
|
$(SHELL) ./config.status --recheck
|
||||||
|
|
||||||
|
# Generate the pkg-config configuration file with all of
|
||||||
|
# the accurate installation parameters
|
||||||
|
libr.pc: libr.pc.in
|
||||||
|
cat libr.pc.in | sed $(SED_REPLACE) > libr.pc
|
||||||
|
CLEANFILES=libr.pc
|
||||||
|
|
||||||
|
# Install the pkg-config configuration file
|
||||||
|
dist_inst_DATA = \
|
||||||
|
libr.pc
|
@ -0,0 +1,41 @@
|
|||||||
|
libr - Library to manage resources in ELF binaries
|
||||||
|
|
||||||
|
See the INSTALL file for general installation instructions.
|
||||||
|
|
||||||
|
* What is the purpose of this library?
|
||||||
|
This library is intended to provide an easy to use mechanism for managing
|
||||||
|
(embedding, retrieving, deleting) resources in ELF binaries. The library
|
||||||
|
provides a solid API and ABI that implements the preliminary spec for adding
|
||||||
|
ELF resources (icons or otherwise) documented at:
|
||||||
|
https://wiki.ubuntu.com/ELFIconSpec
|
||||||
|
Please note that should a backward-incompatible change occur to the API/ABI
|
||||||
|
then the shared library version code will be bumped.
|
||||||
|
|
||||||
|
* Why are there multiple backends?
|
||||||
|
Originally this library was written to use libelf, unfortunately libelf has
|
||||||
|
some issues with reordering data in small executables. Until these issues are
|
||||||
|
resolved please use libbfd (the default backend) or the read-only backend.
|
||||||
|
If you would like to experiment with the libelf backend you can try and set
|
||||||
|
resources on the application "alsamixer", which is a commonly installed
|
||||||
|
application that is known to break.
|
||||||
|
|
||||||
|
* What is the read-only backend?
|
||||||
|
The read-only backend is a dependency-free backend that is capable of reading
|
||||||
|
libr resources. Support for this backend is thanks to Martin Rosenau.
|
||||||
|
This backend is currently a new edition to libr, however, in the long-run the
|
||||||
|
read-only backend will be the recommended (default) backend for the purpose of
|
||||||
|
most applications. Only a special class of application (primarily elfres)
|
||||||
|
needs to actually add and remove resources in a binary, most applications
|
||||||
|
need only read resources already added by elfres.
|
||||||
|
|
||||||
|
NOTICE! This library is licensed under the LGPL v2.1 while the backend for
|
||||||
|
libbfd is licensed under the LGPL v3. You may choose to distribute your
|
||||||
|
modifications to this variant of the library under the LGPL v3, in accordance
|
||||||
|
with Section 5 of that license. Should you wish to excise libbfd from this
|
||||||
|
library you may choose to remove libr_bfd.h and libr_bfd.c and compile against
|
||||||
|
libelf instead, the backend may be selected at configure time:
|
||||||
|
./configure --libr-backend=libelf
|
||||||
|
|
||||||
|
I consider the ability to select the library backend as satisfying the LGPL v3
|
||||||
|
Section 5a requirement and this notice (and the notice contained within
|
||||||
|
libr_bfd.c) to satisfy the Section 5b requirement.
|
@ -0,0 +1,177 @@
|
|||||||
|
|
||||||
|
#ifdef __LINK_AT_RUNTIME__
|
||||||
|
DEFINE_SYMBOL(long, bfd_canonicalize_reloc,
|
||||||
|
bfd *abfd, asection *sec, arelent **loc, asymbol **syms);
|
||||||
|
DEFINE_SYMBOL(bfd_boolean, bfd_close,
|
||||||
|
bfd *abfd);
|
||||||
|
DEFINE_SYMBOL(bfd_boolean, bfd_check_format,
|
||||||
|
bfd *abfd, bfd_format format);
|
||||||
|
DEFINE_SYMBOL(const char *, bfd_errmsg,
|
||||||
|
bfd_error_type error_tag);
|
||||||
|
DEFINE_SYMBOL(enum bfd_architecture, bfd_get_arch,
|
||||||
|
bfd *abfd);
|
||||||
|
DEFINE_SYMBOL(bfd_error_type, bfd_get_error,
|
||||||
|
void);
|
||||||
|
DEFINE_SYMBOL(unsigned long, bfd_get_mach,
|
||||||
|
bfd *abfd);
|
||||||
|
DEFINE_SYMBOL(long, bfd_get_reloc_upper_bound,
|
||||||
|
bfd *abfd, asection *sect);
|
||||||
|
DEFINE_SYMBOL(bfd_boolean, bfd_get_section_contents,
|
||||||
|
bfd *abfd, asection *section, void *location, file_ptr offset,
|
||||||
|
bfd_size_type count);
|
||||||
|
DEFINE_SYMBOL(asection *, bfd_make_section,
|
||||||
|
bfd *, const char *name);
|
||||||
|
DEFINE_SYMBOL(asection *, bfd_make_section_anyway_with_flags,
|
||||||
|
bfd *abfd, const char *name, flagword flags);
|
||||||
|
DEFINE_SYMBOL(bfd *, bfd_openr, const char *filename,
|
||||||
|
const char *target);
|
||||||
|
DEFINE_SYMBOL(bfd *, bfd_openw,
|
||||||
|
const char *filename, const char *target);
|
||||||
|
DEFINE_SYMBOL(bfd_boolean, bfd_set_file_flags,
|
||||||
|
bfd *abfd, flagword flags);
|
||||||
|
DEFINE_SYMBOL(void, bfd_set_reloc,
|
||||||
|
bfd *abfd, asection *sec, arelent **rel, unsigned int count);
|
||||||
|
DEFINE_SYMBOL(bfd_boolean, bfd_set_section_contents,
|
||||||
|
bfd *abfd, asection *section, const void *data, file_ptr offset,
|
||||||
|
bfd_size_type count);
|
||||||
|
DEFINE_SYMBOL(bfd_boolean, bfd_set_format,
|
||||||
|
bfd *abfd, bfd_format format);
|
||||||
|
DEFINE_SYMBOL(bfd_boolean, bfd_set_section_flags,
|
||||||
|
bfd *abfd, asection *sec, flagword flags);
|
||||||
|
DEFINE_SYMBOL(bfd_boolean, bfd_set_section_size,
|
||||||
|
bfd *abfd, asection *sec, bfd_size_type val);
|
||||||
|
DEFINE_SYMBOL(bfd_boolean, bfd_set_start_address,
|
||||||
|
bfd *abfd, bfd_vma vma);
|
||||||
|
DEFINE_SYMBOL(bfd_boolean, bfd_set_symtab,
|
||||||
|
bfd *abfd, asymbol **location, unsigned int count);
|
||||||
|
|
||||||
|
#define bfd_canonicalize_reloc
|
||||||
|
OVERRIDE_SYMBOL(bfd_canonicalize_reloc)
|
||||||
|
#define bfd_close OVERRIDE_SYMBOL(bfd_close)
|
||||||
|
#define bfd_check_format
|
||||||
|
OVERRIDE_SYMBOL(bfd_check_format)
|
||||||
|
#define bfd_errmsg OVERRIDE_SYMBOL(bfd_errmsg)
|
||||||
|
#define bfd_get_arch OVERRIDE_SYMBOL(bfd_get_arch)
|
||||||
|
#define bfd_get_error
|
||||||
|
OVERRIDE_SYMBOL(bfd_get_error)
|
||||||
|
#define bfd_get_mach OVERRIDE_SYMBOL(bfd_get_mach)
|
||||||
|
#define bfd_get_reloc_upper_bound
|
||||||
|
OVERRIDE_SYMBOL(bfd_get_reloc_upper_bound)
|
||||||
|
#define bfd_get_section_contents
|
||||||
|
OVERRIDE_SYMBOL(bfd_get_section_contents)
|
||||||
|
#define bfd_make_section
|
||||||
|
OVERRIDE_SYMBOL(bfd_make_section)
|
||||||
|
#define bfd_make_section_anyway_with_flags
|
||||||
|
OVERRIDE_SYMBOL(bfd_make_section_anyway_with_flags)
|
||||||
|
#define bfd_openr OVERRIDE_SYMBOL(bfd_openr)
|
||||||
|
#define bfd_openw OVERRIDE_SYMBOL(bfd_openw)
|
||||||
|
#define bfd_set_file_flags
|
||||||
|
OVERRIDE_SYMBOL(bfd_set_file_flags)
|
||||||
|
#define bfd_set_format
|
||||||
|
OVERRIDE_SYMBOL(bfd_set_format)
|
||||||
|
#define bfd_set_reloc
|
||||||
|
OVERRIDE_SYMBOL(bfd_set_reloc)
|
||||||
|
#define bfd_set_section_contents
|
||||||
|
OVERRIDE_SYMBOL(bfd_set_section_contents)
|
||||||
|
#define bfd_set_section_flags
|
||||||
|
OVERRIDE_SYMBOL(bfd_set_section_flags)
|
||||||
|
#define bfd_set_section_size
|
||||||
|
OVERRIDE_SYMBOL(bfd_set_section_size)
|
||||||
|
#define bfd_set_start_address
|
||||||
|
OVERRIDE_SYMBOL(bfd_set_start_address)
|
||||||
|
#define bfd_set_symtab
|
||||||
|
OVERRIDE_SYMBOL(bfd_set_symtab)
|
||||||
|
|
||||||
|
SYMBOL_TABLE(libbfd_symbols,
|
||||||
|
SYMBOL(bfd_openr),
|
||||||
|
SYMBOL(bfd_set_format),
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <librsvg/rsvg.h>
|
||||||
|
|
||||||
|
DEFINE_SYMBOL(void, rsvg_init, void);
|
||||||
|
DEFINE_SYMBOL(RsvgHandle *, rsvg_handle_new, void);
|
||||||
|
DEFINE_SYMBOL(GdkPixbuf *, rsvg_handle_get_pixbuf, RsvgHandle *handle);
|
||||||
|
DEFINE_SYMBOL(gboolean, rsvg_handle_close, RsvgHandle * handle, GError ** error);
|
||||||
|
DEFINE_SYMBOL(void, rsvg_handle_get_dimensions, RsvgHandle * handle, RsvgDimensionData * dimension_data);
|
||||||
|
DEFINE_SYMBOL(gboolean, rsvg_handle_write, RsvgHandle * handle, const guchar * buf, gsize count, GError ** error);
|
||||||
|
DEFINE_SYMBOL(void, rsvg_handle_set_size_callback, RsvgHandle * handle, RsvgSizeFunc size_func, gpointer user_data, GDestroyNotify user_data_destroy);
|
||||||
|
|
||||||
|
#define rsvg_init OVERRIDE_SYMBOL(rsvg_init)
|
||||||
|
#define rsvg_handle_new OVERRIDE_SYMBOL(rsvg_handle_new)
|
||||||
|
#define rsvg_handle_get_pixbuf OVERRIDE_SYMBOL(rsvg_handle_get_pixbuf)
|
||||||
|
#define rsvg_handle_close OVERRIDE_SYMBOL(rsvg_handle_close)
|
||||||
|
#define rsvg_handle_write OVERRIDE_SYMBOL(rsvg_handle_write)
|
||||||
|
#define rsvg_handle_set_size_callback OVERRIDE_SYMBOL(rsvg_handle_set_size_callback)
|
||||||
|
#define rsvg_handle_get_dimensions OVERRIDE_SYMBOL(rsvg_handle_get_dimensions)
|
||||||
|
|
||||||
|
SYMBOL_TABLE(librsvg_symbols,
|
||||||
|
SYMBOL(rsvg_init),
|
||||||
|
SYMBOL(rsvg_handle_new),
|
||||||
|
SYMBOL(rsvg_handle_close),
|
||||||
|
SYMBOL(rsvg_handle_write),
|
||||||
|
SYMBOL(rsvg_handle_get_pixbuf),
|
||||||
|
SYMBOL(rsvg_handle_get_dimensions),
|
||||||
|
SYMBOL(rsvg_handle_set_size_callback),
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Scale the SVG image to the required icon size
|
||||||
|
*/
|
||||||
|
static void rsvg_set_iconsize(int *width, int *height, gpointer data)
|
||||||
|
{
|
||||||
|
float multiplier = *(float*)data;
|
||||||
|
|
||||||
|
(*width) *= multiplier;
|
||||||
|
(*height) *= multiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!rsvg_linked)
|
||||||
|
{
|
||||||
|
if(!LOAD_SYMBOLS("librsvg-2.so", librsvg_symbols))
|
||||||
|
{
|
||||||
|
// libr_icon_gtk requires that your application be linked to librsvg
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RsvgHandle *rsvg = NULL;
|
||||||
|
libr_icontype_t type;
|
||||||
|
type = icon_handle->type;
|
||||||
|
if(type == LIBR_SVG)
|
||||||
|
{
|
||||||
|
RsvgHandle *rsvg = rsvg_handle_new();
|
||||||
|
if(rsvg != NULL)
|
||||||
|
{
|
||||||
|
if(rsvg_handle_write(rsvg, iconfile, iconfile_size, NULL))
|
||||||
|
{
|
||||||
|
if(rsvg_handle_close(rsvg, NULL))
|
||||||
|
{
|
||||||
|
RsvgDimensionData dim;
|
||||||
|
float multiplier;
|
||||||
|
int old_size;
|
||||||
|
|
||||||
|
rsvg_handle_get_dimensions(rsvg, &dim);
|
||||||
|
if(dim.width > dim.height)
|
||||||
|
old_size = dim.width;
|
||||||
|
else
|
||||||
|
old_size = dim.height;
|
||||||
|
multiplier = ((float)sizes[i])/old_size;
|
||||||
|
rsvg_handle_set_size_callback(rsvg, rsvg_set_iconsize, (void *) &multiplier, NULL);
|
||||||
|
icon = rsvg_handle_get_pixbuf(rsvg);
|
||||||
|
icons = g_list_append(icons, icon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(iconfile);
|
||||||
|
}
|
||||||
|
else if(type == LIBR_PNG)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Unhandled image type */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
|||||||
|
printf("loads...\n");
|
||||||
|
if(!LOAD_SYMBOLS("libgtk-x11-2.0", null_symbols))
|
||||||
|
printf("err 0\n");
|
||||||
|
if(!LOAD_SYMBOLS("libgdk-x11-2.0", null_symbols))
|
||||||
|
printf("err 1\n");
|
||||||
|
if(!LOAD_SYMBOLS("libatk-1.0", null_symbols))
|
||||||
|
printf("err 2\n");
|
||||||
|
if(!LOAD_SYMBOLS("libgdk_pixbuf-2.0", null_symbols))
|
||||||
|
printf("err 3\n");
|
||||||
|
if(!LOAD_SYMBOLS("libpangocairo-1.0", null_symbols))
|
||||||
|
printf("err 4\n");
|
||||||
|
if(!LOAD_SYMBOLS("libpango-1.0", null_symbols))
|
||||||
|
printf("err 5\n");
|
||||||
|
if(!LOAD_SYMBOLS("libcairo", null_symbols))
|
||||||
|
printf("err 6\n");
|
||||||
|
if(!LOAD_SYMBOLS("libfreetype", null_symbols))
|
||||||
|
printf("err 7\n");
|
||||||
|
if(!LOAD_SYMBOLS("libxml2", null_symbols))
|
||||||
|
printf("err 8\n");
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,93 @@
|
|||||||
|
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||||
|
|
||||||
|
/* Define to 1 if translation of program messages to the user's native
|
||||||
|
language is requested. */
|
||||||
|
#undef ENABLE_NLS
|
||||||
|
|
||||||
|
/* Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the
|
||||||
|
CoreFoundation framework. */
|
||||||
|
#undef HAVE_CFLOCALECOPYCURRENT
|
||||||
|
|
||||||
|
/* Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in
|
||||||
|
the CoreFoundation framework. */
|
||||||
|
#undef HAVE_CFPREFERENCESCOPYAPPVALUE
|
||||||
|
|
||||||
|
/* Define if the GNU dcgettext() function is already present or preinstalled.
|
||||||
|
*/
|
||||||
|
#undef HAVE_DCGETTEXT
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||||
|
#undef HAVE_DLFCN_H
|
||||||
|
|
||||||
|
/* Define if the GNU gettext() function is already present or preinstalled. */
|
||||||
|
#undef HAVE_GETTEXT
|
||||||
|
|
||||||
|
/* Define if you have the iconv() function and it works. */
|
||||||
|
#undef HAVE_ICONV
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||||
|
#undef HAVE_INTTYPES_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <math.h> header file. */
|
||||||
|
#undef HAVE_MATH_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <memory.h> header file. */
|
||||||
|
#undef HAVE_MEMORY_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <pthread.h> header file. */
|
||||||
|
#undef HAVE_PTHREAD_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <stdint.h> header file. */
|
||||||
|
#undef HAVE_STDINT_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||||
|
#undef HAVE_STDLIB_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <strings.h> header file. */
|
||||||
|
#undef HAVE_STRINGS_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <string.h> header file. */
|
||||||
|
#undef HAVE_STRING_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||||
|
#undef HAVE_SYS_STAT_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||||
|
#undef HAVE_SYS_TYPES_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <unistd.h> header file. */
|
||||||
|
#undef HAVE_UNISTD_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <zlib.h> header file. */
|
||||||
|
#undef HAVE_ZLIB_H
|
||||||
|
|
||||||
|
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
||||||
|
*/
|
||||||
|
#undef LT_OBJDIR
|
||||||
|
|
||||||
|
/* Name of package */
|
||||||
|
#undef PACKAGE
|
||||||
|
|
||||||
|
/* Define to the address where bug reports for this package should be sent. */
|
||||||
|
#undef PACKAGE_BUGREPORT
|
||||||
|
|
||||||
|
/* Define to the full name of this package. */
|
||||||
|
#undef PACKAGE_NAME
|
||||||
|
|
||||||
|
/* Define to the full name and version of this package. */
|
||||||
|
#undef PACKAGE_STRING
|
||||||
|
|
||||||
|
/* Define to the one symbol short name of this package. */
|
||||||
|
#undef PACKAGE_TARNAME
|
||||||
|
|
||||||
|
/* Define to the home page for this package. */
|
||||||
|
#undef PACKAGE_URL
|
||||||
|
|
||||||
|
/* Define to the version of this package. */
|
||||||
|
#undef PACKAGE_VERSION
|
||||||
|
|
||||||
|
/* Define to 1 if you have the ANSI C header files. */
|
||||||
|
#undef STDC_HEADERS
|
||||||
|
|
||||||
|
/* Version number of package */
|
||||||
|
#undef VERSION
|
@ -0,0 +1,666 @@
|
|||||||
|
#! /bin/sh
|
||||||
|
# Output a system dependent set of variables, describing how to set the
|
||||||
|
# run time search path of shared libraries in an executable.
|
||||||
|
#
|
||||||
|
# Copyright 1996-2007 Free Software Foundation, Inc.
|
||||||
|
# Taken from GNU libtool, 2001
|
||||||
|
# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 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.
|
||||||
|
#
|
||||||
|
# The first argument passed to this file is the canonical host specification,
|
||||||
|
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
|
||||||
|
# or
|
||||||
|
# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
|
||||||
|
# The environment variables CC, GCC, LDFLAGS, LD, with_gnu_ld
|
||||||
|
# should be set by the caller.
|
||||||
|
#
|
||||||
|
# The set of defined variables is at the end of this script.
|
||||||
|
|
||||||
|
# Known limitations:
|
||||||
|
# - On IRIX 6.5 with CC="cc", the run time search patch must not be longer
|
||||||
|
# than 256 bytes, otherwise the compiler driver will dump core. The only
|
||||||
|
# known workaround is to choose shorter directory names for the build
|
||||||
|
# directory and/or the installation directory.
|
||||||
|
|
||||||
|
# All known linkers require a `.a' archive for static linking (except MSVC,
|
||||||
|
# which needs '.lib').
|
||||||
|
libext=a
|
||||||
|
shrext=.so
|
||||||
|
|
||||||
|
host="$1"
|
||||||
|
host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
|
||||||
|
host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
|
||||||
|
host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
|
||||||
|
|
||||||
|
# Code taken from libtool.m4's _LT_CC_BASENAME.
|
||||||
|
|
||||||
|
for cc_temp in $CC""; do
|
||||||
|
case $cc_temp in
|
||||||
|
compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
|
||||||
|
distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
|
||||||
|
\-*) ;;
|
||||||
|
*) break;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
cc_basename=`echo "$cc_temp" | sed -e 's%^.*/%%'`
|
||||||
|
|
||||||
|
# Code taken from libtool.m4's AC_LIBTOOL_PROG_COMPILER_PIC.
|
||||||
|
|
||||||
|
wl=
|
||||||
|
if test "$GCC" = yes; then
|
||||||
|
wl='-Wl,'
|
||||||
|
else
|
||||||
|
case "$host_os" in
|
||||||
|
aix*)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
darwin*)
|
||||||
|
case $cc_basename in
|
||||||
|
xlc*)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
mingw* | cygwin* | pw32* | os2*)
|
||||||
|
;;
|
||||||
|
hpux9* | hpux10* | hpux11*)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
irix5* | irix6* | nonstopux*)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
newsos6)
|
||||||
|
;;
|
||||||
|
linux* | k*bsd*-gnu)
|
||||||
|
case $cc_basename in
|
||||||
|
icc* | ecc*)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
pgcc | pgf77 | pgf90)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
ccc*)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
como)
|
||||||
|
wl='-lopt='
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
case `$CC -V 2>&1 | sed 5q` in
|
||||||
|
*Sun\ C*)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
osf3* | osf4* | osf5*)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
rdos*)
|
||||||
|
;;
|
||||||
|
solaris*)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
sunos4*)
|
||||||
|
wl='-Qoption ld '
|
||||||
|
;;
|
||||||
|
sysv4 | sysv4.2uw2* | sysv4.3*)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
sysv4*MP*)
|
||||||
|
;;
|
||||||
|
sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
unicos*)
|
||||||
|
wl='-Wl,'
|
||||||
|
;;
|
||||||
|
uts4*)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Code taken from libtool.m4's AC_LIBTOOL_PROG_LD_SHLIBS.
|
||||||
|
|
||||||
|
hardcode_libdir_flag_spec=
|
||||||
|
hardcode_libdir_separator=
|
||||||
|
hardcode_direct=no
|
||||||
|
hardcode_minus_L=no
|
||||||
|
|
||||||
|
case "$host_os" in
|
||||||
|
cygwin* | mingw* | pw32*)
|
||||||
|
# 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
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
ld_shlibs=yes
|
||||||
|
if test "$with_gnu_ld" = yes; then
|
||||||
|
# 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.
|
||||||
|
# Unlike libtool, we use -rpath here, not --rpath, since the documented
|
||||||
|
# option of GNU ld is called -rpath, not --rpath.
|
||||||
|
hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
|
||||||
|
case "$host_os" in
|
||||||
|
aix3* | aix4* | aix5*)
|
||||||
|
# On AIX/PPC, the GNU linker is very broken
|
||||||
|
if test "$host_cpu" != ia64; then
|
||||||
|
ld_shlibs=no
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
amigaos*)
|
||||||
|
hardcode_libdir_flag_spec='-L$libdir'
|
||||||
|
hardcode_minus_L=yes
|
||||||
|
# Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
|
||||||
|
# that the semantics of dynamic libraries on AmigaOS, at least up
|
||||||
|
# to version 4, is to share data among multiple programs linked
|
||||||
|
# with the same dynamic library. Since this doesn't match the
|
||||||
|
# behavior of shared libraries on other platforms, we cannot use
|
||||||
|
# them.
|
||||||
|
ld_shlibs=no
|
||||||
|
;;
|
||||||
|
beos*)
|
||||||
|
if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
|
||||||
|
:
|
||||||
|
else
|
||||||
|
ld_shlibs=no
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
cygwin* | mingw* | pw32*)
|
||||||
|
# hardcode_libdir_flag_spec is actually meaningless, as there is
|
||||||
|
# no search path for DLLs.
|
||||||
|
hardcode_libdir_flag_spec='-L$libdir'
|
||||||
|
if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
|
||||||
|
:
|
||||||
|
else
|
||||||
|
ld_shlibs=no
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
interix[3-9]*)
|
||||||
|
hardcode_direct=no
|
||||||
|
hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
|
||||||
|
;;
|
||||||
|
gnu* | linux* | k*bsd*-gnu)
|
||||||
|
if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
|
||||||
|
:
|
||||||
|
else
|
||||||
|
ld_shlibs=no
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
netbsd*)
|
||||||
|
;;
|
||||||
|
solaris*)
|
||||||
|
if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
|
||||||
|
ld_shlibs=no
|
||||||
|
elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
|
||||||
|
:
|
||||||
|
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
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
|
||||||
|
hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
|
||||||
|
else
|
||||||
|
ld_shlibs=no
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
sunos4*)
|
||||||
|
hardcode_direct=yes
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
|
||||||
|
:
|
||||||
|
else
|
||||||
|
ld_shlibs=no
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
if test "$ld_shlibs" = no; then
|
||||||
|
hardcode_libdir_flag_spec=
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
case "$host_os" in
|
||||||
|
aix3*)
|
||||||
|
# Note: this linker hardcodes the directories in LIBPATH if there
|
||||||
|
# are no directories specified by -L.
|
||||||
|
hardcode_minus_L=yes
|
||||||
|
if test "$GCC" = yes; then
|
||||||
|
# Neither direct hardcoding nor static linking is supported with a
|
||||||
|
# broken collect2.
|
||||||
|
hardcode_direct=unsupported
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
aix4* | aix5*)
|
||||||
|
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
|
||||||
|
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].*|aix5*)
|
||||||
|
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
|
||||||
|
fi
|
||||||
|
hardcode_direct=yes
|
||||||
|
hardcode_libdir_separator=':'
|
||||||
|
if test "$GCC" = yes; then
|
||||||
|
case $host_os in aix4.[012]|aix4.[012].*)
|
||||||
|
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
|
||||||
|
hardcode_minus_L=yes
|
||||||
|
hardcode_libdir_flag_spec='-L$libdir'
|
||||||
|
hardcode_libdir_separator=
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
# Begin _LT_AC_SYS_LIBPATH_AIX.
|
||||||
|
echo 'int main () { return 0; }' > conftest.c
|
||||||
|
${CC} ${LDFLAGS} conftest.c -o conftest
|
||||||
|
aix_libpath=`dump -H conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
|
||||||
|
}'`
|
||||||
|
if test -z "$aix_libpath"; then
|
||||||
|
aix_libpath=`dump -HX64 conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
|
||||||
|
}'`
|
||||||
|
fi
|
||||||
|
if test -z "$aix_libpath"; then
|
||||||
|
aix_libpath="/usr/lib:/lib"
|
||||||
|
fi
|
||||||
|
rm -f conftest.c conftest
|
||||||
|
# End _LT_AC_SYS_LIBPATH_AIX.
|
||||||
|
if test "$aix_use_runtimelinking" = yes; then
|
||||||
|
hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
|
||||||
|
else
|
||||||
|
if test "$host_cpu" = ia64; then
|
||||||
|
hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
|
||||||
|
else
|
||||||
|
hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
amigaos*)
|
||||||
|
hardcode_libdir_flag_spec='-L$libdir'
|
||||||
|
hardcode_minus_L=yes
|
||||||
|
# see comment about different semantics on the GNU ld section
|
||||||
|
ld_shlibs=no
|
||||||
|
;;
|
||||||
|
bsdi[45]*)
|
||||||
|
;;
|
||||||
|
cygwin* | mingw* | pw32*)
|
||||||
|
# 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.
|
||||||
|
hardcode_libdir_flag_spec=' '
|
||||||
|
libext=lib
|
||||||
|
;;
|
||||||
|
darwin* | rhapsody*)
|
||||||
|
hardcode_direct=no
|
||||||
|
if test "$GCC" = yes ; then
|
||||||
|
:
|
||||||
|
else
|
||||||
|
case $cc_basename in
|
||||||
|
xlc*)
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
ld_shlibs=no
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
dgux*)
|
||||||
|
hardcode_libdir_flag_spec='-L$libdir'
|
||||||
|
;;
|
||||||
|
freebsd1*)
|
||||||
|
ld_shlibs=no
|
||||||
|
;;
|
||||||
|
freebsd2.2*)
|
||||||
|
hardcode_libdir_flag_spec='-R$libdir'
|
||||||
|
hardcode_direct=yes
|
||||||
|
;;
|
||||||
|
freebsd2*)
|
||||||
|
hardcode_direct=yes
|
||||||
|
hardcode_minus_L=yes
|
||||||
|
;;
|
||||||
|
freebsd* | dragonfly*)
|
||||||
|
hardcode_libdir_flag_spec='-R$libdir'
|
||||||
|
hardcode_direct=yes
|
||||||
|
;;
|
||||||
|
hpux9*)
|
||||||
|
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
|
||||||
|
;;
|
||||||
|
hpux10*)
|
||||||
|
if test "$with_gnu_ld" = no; then
|
||||||
|
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
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
hpux11*)
|
||||||
|
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_direct=yes
|
||||||
|
# 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*)
|
||||||
|
hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
|
||||||
|
hardcode_libdir_separator=:
|
||||||
|
;;
|
||||||
|
netbsd*)
|
||||||
|
hardcode_libdir_flag_spec='-R$libdir'
|
||||||
|
hardcode_direct=yes
|
||||||
|
;;
|
||||||
|
newsos6)
|
||||||
|
hardcode_direct=yes
|
||||||
|
hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
|
||||||
|
hardcode_libdir_separator=:
|
||||||
|
;;
|
||||||
|
openbsd*)
|
||||||
|
if test -f /usr/libexec/ld.so; then
|
||||||
|
hardcode_direct=yes
|
||||||
|
if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
|
||||||
|
hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
|
||||||
|
else
|
||||||
|
case "$host_os" in
|
||||||
|
openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
|
||||||
|
hardcode_libdir_flag_spec='-R$libdir'
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
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
|
||||||
|
;;
|
||||||
|
osf3*)
|
||||||
|
hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
|
||||||
|
hardcode_libdir_separator=:
|
||||||
|
;;
|
||||||
|
osf4* | osf5*)
|
||||||
|
if test "$GCC" = yes; then
|
||||||
|
hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
|
||||||
|
else
|
||||||
|
# Both cc and cxx compiler support -rpath directly
|
||||||
|
hardcode_libdir_flag_spec='-rpath $libdir'
|
||||||
|
fi
|
||||||
|
hardcode_libdir_separator=:
|
||||||
|
;;
|
||||||
|
solaris*)
|
||||||
|
hardcode_libdir_flag_spec='-R$libdir'
|
||||||
|
;;
|
||||||
|
sunos4*)
|
||||||
|
hardcode_libdir_flag_spec='-L$libdir'
|
||||||
|
hardcode_direct=yes
|
||||||
|
hardcode_minus_L=yes
|
||||||
|
;;
|
||||||
|
sysv4)
|
||||||
|
case $host_vendor in
|
||||||
|
sni)
|
||||||
|
hardcode_direct=yes # is this really true???
|
||||||
|
;;
|
||||||
|
siemens)
|
||||||
|
hardcode_direct=no
|
||||||
|
;;
|
||||||
|
motorola)
|
||||||
|
hardcode_direct=no #Motorola manual says yes, but my tests say they lie
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
sysv4.3*)
|
||||||
|
;;
|
||||||
|
sysv4*MP*)
|
||||||
|
if test -d /usr/nec; then
|
||||||
|
ld_shlibs=yes
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
|
||||||
|
;;
|
||||||
|
sysv5* | sco3.2v5* | sco5v6*)
|
||||||
|
hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
|
||||||
|
hardcode_libdir_separator=':'
|
||||||
|
;;
|
||||||
|
uts4*)
|
||||||
|
hardcode_libdir_flag_spec='-L$libdir'
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
ld_shlibs=no
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check dynamic linker characteristics
|
||||||
|
# Code taken from libtool.m4's AC_LIBTOOL_SYS_DYNAMIC_LINKER.
|
||||||
|
# Unlike libtool.m4, here we don't care about _all_ names of the library, but
|
||||||
|
# only about the one the linker finds when passed -lNAME. This is the last
|
||||||
|
# element of library_names_spec in libtool.m4, or possibly two of them if the
|
||||||
|
# linker has special search rules.
|
||||||
|
library_names_spec= # the last element of library_names_spec in libtool.m4
|
||||||
|
libname_spec='lib$name'
|
||||||
|
case "$host_os" in
|
||||||
|
aix3*)
|
||||||
|
library_names_spec='$libname.a'
|
||||||
|
;;
|
||||||
|
aix4* | aix5*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
amigaos*)
|
||||||
|
library_names_spec='$libname.a'
|
||||||
|
;;
|
||||||
|
beos*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
bsdi[45]*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
cygwin* | mingw* | pw32*)
|
||||||
|
shrext=.dll
|
||||||
|
library_names_spec='$libname.dll.a $libname.lib'
|
||||||
|
;;
|
||||||
|
darwin* | rhapsody*)
|
||||||
|
shrext=.dylib
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
dgux*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
freebsd1*)
|
||||||
|
;;
|
||||||
|
freebsd* | dragonfly*)
|
||||||
|
case "$host_os" in
|
||||||
|
freebsd[123]*)
|
||||||
|
library_names_spec='$libname$shrext$versuffix' ;;
|
||||||
|
*)
|
||||||
|
library_names_spec='$libname$shrext' ;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
gnu*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
hpux9* | hpux10* | hpux11*)
|
||||||
|
case $host_cpu in
|
||||||
|
ia64*)
|
||||||
|
shrext=.so
|
||||||
|
;;
|
||||||
|
hppa*64*)
|
||||||
|
shrext=.sl
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
shrext=.sl
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
interix[3-9]*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
irix5* | irix6* | nonstopux*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
case "$host_os" in
|
||||||
|
irix5* | nonstopux*)
|
||||||
|
libsuff= shlibsuff=
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
case $LD in
|
||||||
|
*-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= ;;
|
||||||
|
*-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 ;;
|
||||||
|
*-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 ;;
|
||||||
|
*) libsuff= shlibsuff= ;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
linux*oldld* | linux*aout* | linux*coff*)
|
||||||
|
;;
|
||||||
|
linux* | k*bsd*-gnu)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
knetbsd*-gnu)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
netbsd*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
newsos6)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
nto-qnx*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
openbsd*)
|
||||||
|
library_names_spec='$libname$shrext$versuffix'
|
||||||
|
;;
|
||||||
|
os2*)
|
||||||
|
libname_spec='$name'
|
||||||
|
shrext=.dll
|
||||||
|
library_names_spec='$libname.a'
|
||||||
|
;;
|
||||||
|
osf3* | osf4* | osf5*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
rdos*)
|
||||||
|
;;
|
||||||
|
solaris*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
sunos4*)
|
||||||
|
library_names_spec='$libname$shrext$versuffix'
|
||||||
|
;;
|
||||||
|
sysv4 | sysv4.3*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
sysv4*MP*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
uts4*)
|
||||||
|
library_names_spec='$libname$shrext'
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
|
||||||
|
escaped_wl=`echo "X$wl" | sed -e 's/^X//' -e "$sed_quote_subst"`
|
||||||
|
shlibext=`echo "$shrext" | sed -e 's,^\.,,'`
|
||||||
|
escaped_libname_spec=`echo "X$libname_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
|
||||||
|
escaped_library_names_spec=`echo "X$library_names_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
|
||||||
|
escaped_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
|
||||||
|
|
||||||
|
LC_ALL=C sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' <<EOF
|
||||||
|
|
||||||
|
# How to pass a linker flag through the compiler.
|
||||||
|
wl="$escaped_wl"
|
||||||
|
|
||||||
|
# Static library suffix (normally "a").
|
||||||
|
libext="$libext"
|
||||||
|
|
||||||
|
# Shared library suffix (normally "so").
|
||||||
|
shlibext="$shlibext"
|
||||||
|
|
||||||
|
# Format of library name prefix.
|
||||||
|
libname_spec="$escaped_libname_spec"
|
||||||
|
|
||||||
|
# Library names that the linker finds when passed -lNAME.
|
||||||
|
library_names_spec="$escaped_library_names_spec"
|
||||||
|
|
||||||
|
# Flag to hardcode \$libdir into a binary during linking.
|
||||||
|
# This must work even if \$libdir does not exist.
|
||||||
|
hardcode_libdir_flag_spec="$escaped_hardcode_libdir_flag_spec"
|
||||||
|
|
||||||
|
# Whether we need a single -rpath flag with a separated argument.
|
||||||
|
hardcode_libdir_separator="$hardcode_libdir_separator"
|
||||||
|
|
||||||
|
# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the
|
||||||
|
# resulting binary.
|
||||||
|
hardcode_direct="$hardcode_direct"
|
||||||
|
|
||||||
|
# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
|
||||||
|
# resulting binary.
|
||||||
|
hardcode_minus_L="$hardcode_minus_L"
|
||||||
|
|
||||||
|
EOF
|
@ -0,0 +1,81 @@
|
|||||||
|
AC_INIT(libr.c)
|
||||||
|
AM_INIT_AUTOMAKE(libr,0.6.0)
|
||||||
|
AC_CONFIG_SRCDIR([src/libr.c])
|
||||||
|
|
||||||
|
AC_PROG_CC
|
||||||
|
AC_PROG_CC_STDC
|
||||||
|
AC_HEADER_STDC
|
||||||
|
AC_PROG_INSTALL
|
||||||
|
AM_GNU_GETTEXT([external])
|
||||||
|
|
||||||
|
# It is important to build both a static and a shared version of the libr
|
||||||
|
# library. The shared version is for future-proofing, whereas the static
|
||||||
|
# version should be used to make a more portable binary until libr is
|
||||||
|
# more widely distributed (as in distributed at all).
|
||||||
|
AC_ENABLE_SHARED
|
||||||
|
AC_ENABLE_STATIC
|
||||||
|
|
||||||
|
# Setup libtool
|
||||||
|
AC_PROG_LIBTOOL
|
||||||
|
AC_SUBST(LIBTOOL_DEPS)
|
||||||
|
|
||||||
|
## Handle optional libraries (only header files are used)
|
||||||
|
PKG_CHECK_MODULES(LIBGLADE, libglade-2.0 >= 2.0.0)
|
||||||
|
|
||||||
|
## Handle required components
|
||||||
|
# Is this the best check for zlib that can be made?
|
||||||
|
AC_CHECK_HEADERS(zlib.h math.h pthread.h)
|
||||||
|
EXTRA_LIBS="-lz -lm -lpthread"
|
||||||
|
EXTRA_CFLAGS="-fvisibility=hidden"
|
||||||
|
AC_SUBST(EXTRA_CFLAGS)
|
||||||
|
AC_SUBST(EXTRA_LIBS)
|
||||||
|
|
||||||
|
## Handle backend configuration
|
||||||
|
LIBR_BACKEND="bfd"
|
||||||
|
BACKEND_NAME="libbfd"
|
||||||
|
AC_ARG_ENABLE(libelf, [ --enable-libelf use the libelf backend ], [
|
||||||
|
if test "$enableval" = "yes" ; then
|
||||||
|
LIBR_BACKEND="elf"
|
||||||
|
BACKEND_NAME="libelf"
|
||||||
|
fi
|
||||||
|
])
|
||||||
|
AC_ARG_ENABLE(libbfd, [ --enable-libbfd use the libbfd backend (default) ], [
|
||||||
|
if test "$enableval" == "yes" ; then
|
||||||
|
LIBR_BACKEND="bfd"
|
||||||
|
BACKEND_NAME="libbfd"
|
||||||
|
fi
|
||||||
|
])
|
||||||
|
AC_ARG_ENABLE(ro, [ --enable-ro use the read-only backend ], [
|
||||||
|
if test "$enableval" == "yes" ; then
|
||||||
|
LIBR_BACKEND="ro"
|
||||||
|
BACKEND_NAME="readonly"
|
||||||
|
fi
|
||||||
|
])
|
||||||
|
echo "Using ${BACKEND_NAME} backend."
|
||||||
|
if test "${LIBR_BACKEND}" == "bfd" ; then
|
||||||
|
AC_CHECK_HEADER([bfd.h], [], [
|
||||||
|
AC_MSG_ERROR([Could not find libbfd header file (bfd.h)! This file is usually included in the package binutils-dev.])
|
||||||
|
])
|
||||||
|
BACKEND_PKG="binutils"
|
||||||
|
BACKEND_LIBS="-lbfd"
|
||||||
|
BACKEND_CFLAGS=""
|
||||||
|
AC_SUBST(BACKEND_LIBS)
|
||||||
|
AC_SUBST(BACKEND_CFLAGS)
|
||||||
|
elif test "${LIBR_BACKEND}" == "elf" ; then
|
||||||
|
# Is libelf 0.8.2 safe enough? testing is currently on 0.8.6
|
||||||
|
BACKEND_PKG="elfutils"
|
||||||
|
pkg_modules="libelf >= 0.8.2"
|
||||||
|
PKG_CHECK_MODULES(BACKEND, [$pkg_modules])
|
||||||
|
fi
|
||||||
|
AC_SUBST(BACKEND_NAME)
|
||||||
|
AC_SUBST(LIBR_BACKEND)
|
||||||
|
AC_SUBST(BACKEND_PKG)
|
||||||
|
|
||||||
|
|
||||||
|
AC_CONFIG_HEADERS(config.h)
|
||||||
|
AC_OUTPUT(
|
||||||
|
src/Makefile
|
||||||
|
man/Makefile
|
||||||
|
po/Makefile.in
|
||||||
|
Makefile
|
||||||
|
)
|
@ -0,0 +1,630 @@
|
|||||||
|
#! /bin/sh
|
||||||
|
# depcomp - compile a program generating dependencies as side-effects
|
||||||
|
|
||||||
|
scriptversion=2009-04-28.21; # UTC
|
||||||
|
|
||||||
|
# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009 Free
|
||||||
|
# Software Foundation, Inc.
|
||||||
|
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2, or (at your option)
|
||||||
|
# any later version.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# 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 <oliva@dcc.unicamp.br>.
|
||||||
|
|
||||||
|
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 <bug-automake@gnu.org>.
|
||||||
|
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
|
||||||
|
|
||||||
|
cygpath_u="cygpath -u -f -"
|
||||||
|
if test "$depmode" = msvcmsys; then
|
||||||
|
# This is just like msvisualcpp but w/o cygpath translation.
|
||||||
|
# Just convert the backslash-escaped backslashes to single forward
|
||||||
|
# slashes to satisfy depend.m4
|
||||||
|
cygpath_u="sed s,\\\\\\\\,/,g"
|
||||||
|
depmode=msvisualcpp
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$depmode" in
|
||||||
|
gcc3)
|
||||||
|
## gcc 3 implements dependency tracking that does exactly what
|
||||||
|
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
|
||||||
|
## it if -MD -MP comes after the -MF stuff. Hmm.
|
||||||
|
## Unfortunately, FreeBSD c89 acceptance of flags depends upon
|
||||||
|
## the command line argument order; so add the flags where they
|
||||||
|
## appear in depend2.am. Note that the slowdown incurred here
|
||||||
|
## affects only configure: in makefiles, %FASTDEP% shortcuts this.
|
||||||
|
for arg
|
||||||
|
do
|
||||||
|
case $arg in
|
||||||
|
-c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
|
||||||
|
*) set fnord "$@" "$arg" ;;
|
||||||
|
esac
|
||||||
|
shift # fnord
|
||||||
|
shift # $arg
|
||||||
|
done
|
||||||
|
"$@"
|
||||||
|
stat=$?
|
||||||
|
if test $stat -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.
|
||||||
|
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
|
||||||
|
tmpdepfile1=$dir$base.u
|
||||||
|
tmpdepfile2=$base.u
|
||||||
|
tmpdepfile3=$dir.libs/$base.u
|
||||||
|
"$@" -Wc,-M
|
||||||
|
else
|
||||||
|
tmpdepfile1=$dir$base.u
|
||||||
|
tmpdepfile2=$dir$base.u
|
||||||
|
tmpdepfile3=$dir$base.u
|
||||||
|
"$@" -M
|
||||||
|
fi
|
||||||
|
stat=$?
|
||||||
|
|
||||||
|
if test $stat -eq 0; then :
|
||||||
|
else
|
||||||
|
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||||
|
exit $stat
|
||||||
|
fi
|
||||||
|
|
||||||
|
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||||
|
do
|
||||||
|
test -f "$tmpdepfile" && break
|
||||||
|
done
|
||||||
|
if test -f "$tmpdepfile"; then
|
||||||
|
# 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,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
|
||||||
|
# That's a tab and a space in the [].
|
||||||
|
sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$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"
|
||||||
|
;;
|
||||||
|
|
||||||
|
hp2)
|
||||||
|
# The "hp" stanza above does not work with aCC (C++) and HP's ia64
|
||||||
|
# compilers, which have integrated preprocessors. The correct option
|
||||||
|
# to use with these is +Maked; it writes dependencies to a file named
|
||||||
|
# 'foo.d', which lands next to the object file, wherever that
|
||||||
|
# happens to be.
|
||||||
|
# Much of this is similar to the tru64 case; see comments there.
|
||||||
|
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
|
||||||
|
tmpdepfile1=$dir$base.d
|
||||||
|
tmpdepfile2=$dir.libs/$base.d
|
||||||
|
"$@" -Wc,+Maked
|
||||||
|
else
|
||||||
|
tmpdepfile1=$dir$base.d
|
||||||
|
tmpdepfile2=$dir$base.d
|
||||||
|
"$@" +Maked
|
||||||
|
fi
|
||||||
|
stat=$?
|
||||||
|
if test $stat -eq 0; then :
|
||||||
|
else
|
||||||
|
rm -f "$tmpdepfile1" "$tmpdepfile2"
|
||||||
|
exit $stat
|
||||||
|
fi
|
||||||
|
|
||||||
|
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
|
||||||
|
do
|
||||||
|
test -f "$tmpdepfile" && break
|
||||||
|
done
|
||||||
|
if test -f "$tmpdepfile"; then
|
||||||
|
sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile"
|
||||||
|
# Add `dependent.h:' lines.
|
||||||
|
sed -ne '2,${
|
||||||
|
s/^ *//
|
||||||
|
s/ \\*$//
|
||||||
|
s/$/:/
|
||||||
|
p
|
||||||
|
}' "$tmpdepfile" >> "$depfile"
|
||||||
|
else
|
||||||
|
echo "#dummy" > "$depfile"
|
||||||
|
fi
|
||||||
|
rm -f "$tmpdepfile" "$tmpdepfile2"
|
||||||
|
;;
|
||||||
|
|
||||||
|
tru64)
|
||||||
|
# The Tru64 compiler uses -MD to generate dependencies as a side
|
||||||
|
# effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
|
||||||
|
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
|
||||||
|
# dependencies in `foo.d' instead, so we check for that too.
|
||||||
|
# Subdirectories are respected.
|
||||||
|
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 mechanism 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 $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 "X$1" != 'X--mode=compile'; do
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Remove `-o $object'.
|
||||||
|
IFS=" "
|
||||||
|
for arg
|
||||||
|
do
|
||||||
|
case $arg in
|
||||||
|
-o)
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
$object)
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
set fnord "$@" "$arg"
|
||||||
|
shift # fnord
|
||||||
|
shift # $arg
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
test -z "$dashmflag" && dashmflag=-M
|
||||||
|
# Require at least two characters before searching for `:'
|
||||||
|
# in the target name. This is to cope with DOS-style filenames:
|
||||||
|
# a dependency such as `c:/foo/bar' could be seen as target `c' otherwise.
|
||||||
|
"$@" $dashmflag |
|
||||||
|
sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$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 "X$1" != 'X--mode=compile'; do
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
# X makedepend
|
||||||
|
shift
|
||||||
|
cleared=no eat=no
|
||||||
|
for arg
|
||||||
|
do
|
||||||
|
case $cleared in
|
||||||
|
no)
|
||||||
|
set ""; shift
|
||||||
|
cleared=yes ;;
|
||||||
|
esac
|
||||||
|
if test $eat = yes; then
|
||||||
|
eat=no
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
case "$arg" in
|
||||||
|
-D*|-I*)
|
||||||
|
set fnord "$@" "$arg"; shift ;;
|
||||||
|
# Strip any option that makedepend may not understand. Remove
|
||||||
|
# the object too, otherwise makedepend will parse it as a source file.
|
||||||
|
-arch)
|
||||||
|
eat=yes ;;
|
||||||
|
-*|$object)
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
set fnord "$@" "$arg"; shift ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
obj_suffix=`echo "$object" | sed 's/^.*\././'`
|
||||||
|
touch "$tmpdepfile"
|
||||||
|
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
|
||||||
|
rm -f "$depfile"
|
||||||
|
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 "X$1" != 'X--mode=compile'; do
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Remove `-o $object'.
|
||||||
|
IFS=" "
|
||||||
|
for arg
|
||||||
|
do
|
||||||
|
case $arg in
|
||||||
|
-o)
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
$object)
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
set fnord "$@" "$arg"
|
||||||
|
shift # fnord
|
||||||
|
shift # $arg
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
"$@" -E |
|
||||||
|
sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
|
||||||
|
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
|
||||||
|
sed '$ s: \\$::' > "$tmpdepfile"
|
||||||
|
rm -f "$depfile"
|
||||||
|
echo "$object : \\" > "$depfile"
|
||||||
|
cat < "$tmpdepfile" >> "$depfile"
|
||||||
|
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
;;
|
||||||
|
|
||||||
|
msvisualcpp)
|
||||||
|
# Important note: in order to support this mode, a compiler *must*
|
||||||
|
# always write the preprocessed file to stdout.
|
||||||
|
"$@" || exit $?
|
||||||
|
|
||||||
|
# Remove the call to Libtool.
|
||||||
|
if test "$libtool" = yes; then
|
||||||
|
while test "X$1" != 'X--mode=compile'; do
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
|
||||||
|
IFS=" "
|
||||||
|
for arg
|
||||||
|
do
|
||||||
|
case "$arg" in
|
||||||
|
-o)
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
$object)
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
|
||||||
|
set fnord "$@"
|
||||||
|
shift
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
set fnord "$@" "$arg"
|
||||||
|
shift
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
"$@" -E 2>/dev/null |
|
||||||
|
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
|
||||||
|
rm -f "$depfile"
|
||||||
|
echo "$object : \\" > "$depfile"
|
||||||
|
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile"
|
||||||
|
echo " " >> "$depfile"
|
||||||
|
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
|
||||||
|
rm -f "$tmpdepfile"
|
||||||
|
;;
|
||||||
|
|
||||||
|
msvcmsys)
|
||||||
|
# This case exists only to let depend.m4 do its work. It works by
|
||||||
|
# looking at the text of this script. This case will never be run,
|
||||||
|
# since it is checked for above.
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
|
||||||
|
none)
|
||||||
|
exec "$@"
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "Unknown depmode $depmode" 1>&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
|
||||||
|
# Local Variables:
|
||||||
|
# mode: shell-script
|
||||||
|
# sh-indentation: 2
|
||||||
|
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||||
|
# time-stamp-start: "scriptversion="
|
||||||
|
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||||
|
# time-stamp-time-zone: "UTC"
|
||||||
|
# time-stamp-end: "; # UTC"
|
||||||
|
# End:
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,520 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# install - install a program, script, or datafile
|
||||||
|
|
||||||
|
scriptversion=2009-04-28.21; # UTC
|
||||||
|
|
||||||
|
# This originates from X11R5 (mit/util/scripts/install.sh), which was
|
||||||
|
# later released in X11R6 (xc/config/util/install.sh) with the
|
||||||
|
# following copyright and license.
|
||||||
|
#
|
||||||
|
# Copyright (C) 1994 X Consortium
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to
|
||||||
|
# deal in the Software without restriction, including without limitation the
|
||||||
|
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
# sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in
|
||||||
|
# all copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
|
||||||
|
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
#
|
||||||
|
# Except as contained in this notice, the name of the X Consortium shall not
|
||||||
|
# be used in advertising or otherwise to promote the sale, use or other deal-
|
||||||
|
# ings in this Software without prior written authorization from the X Consor-
|
||||||
|
# tium.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# FSF changes to this file are in the public domain.
|
||||||
|
#
|
||||||
|
# Calling this script install-sh is preferred over install.sh, to prevent
|
||||||
|
# `make' implicit rules from creating a file called install from it
|
||||||
|
# when there is no Makefile.
|
||||||
|
#
|
||||||
|
# This script is compatible with the BSD install script, but was written
|
||||||
|
# from scratch.
|
||||||
|
|
||||||
|
nl='
|
||||||
|
'
|
||||||
|
IFS=" "" $nl"
|
||||||
|
|
||||||
|
# set DOITPROG to echo to test this script
|
||||||
|
|
||||||
|
# Don't use :- since 4.3BSD and earlier shells don't like it.
|
||||||
|
doit=${DOITPROG-}
|
||||||
|
if test -z "$doit"; then
|
||||||
|
doit_exec=exec
|
||||||
|
else
|
||||||
|
doit_exec=$doit
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Put in absolute file names if you don't have them in your path;
|
||||||
|
# or use environment vars.
|
||||||
|
|
||||||
|
chgrpprog=${CHGRPPROG-chgrp}
|
||||||
|
chmodprog=${CHMODPROG-chmod}
|
||||||
|
chownprog=${CHOWNPROG-chown}
|
||||||
|
cmpprog=${CMPPROG-cmp}
|
||||||
|
cpprog=${CPPROG-cp}
|
||||||
|
mkdirprog=${MKDIRPROG-mkdir}
|
||||||
|
mvprog=${MVPROG-mv}
|
||||||
|
rmprog=${RMPROG-rm}
|
||||||
|
stripprog=${STRIPPROG-strip}
|
||||||
|
|
||||||
|
posix_glob='?'
|
||||||
|
initialize_posix_glob='
|
||||||
|
test "$posix_glob" != "?" || {
|
||||||
|
if (set -f) 2>/dev/null; then
|
||||||
|
posix_glob=
|
||||||
|
else
|
||||||
|
posix_glob=:
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
'
|
||||||
|
|
||||||
|
posix_mkdir=
|
||||||
|
|
||||||
|
# Desired mode of installed file.
|
||||||
|
mode=0755
|
||||||
|
|
||||||
|
chgrpcmd=
|
||||||
|
chmodcmd=$chmodprog
|
||||||
|
chowncmd=
|
||||||
|
mvcmd=$mvprog
|
||||||
|
rmcmd="$rmprog -f"
|
||||||
|
stripcmd=
|
||||||
|
|
||||||
|
src=
|
||||||
|
dst=
|
||||||
|
dir_arg=
|
||||||
|
dst_arg=
|
||||||
|
|
||||||
|
copy_on_change=false
|
||||||
|
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:
|
||||||
|
--help display this help and exit.
|
||||||
|
--version display version info and exit.
|
||||||
|
|
||||||
|
-c (ignored)
|
||||||
|
-C install only if different (preserve the last data modification time)
|
||||||
|
-d create directories instead of installing files.
|
||||||
|
-g GROUP $chgrpprog installed files to GROUP.
|
||||||
|
-m MODE $chmodprog installed files to MODE.
|
||||||
|
-o USER $chownprog installed files to USER.
|
||||||
|
-s $stripprog installed files.
|
||||||
|
-t DIRECTORY install into DIRECTORY.
|
||||||
|
-T report an error if DSTFILE is a directory.
|
||||||
|
|
||||||
|
Environment variables override the default commands:
|
||||||
|
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
|
||||||
|
RMPROG STRIPPROG
|
||||||
|
"
|
||||||
|
|
||||||
|
while test $# -ne 0; do
|
||||||
|
case $1 in
|
||||||
|
-c) ;;
|
||||||
|
|
||||||
|
-C) copy_on_change=true;;
|
||||||
|
|
||||||
|
-d) dir_arg=true;;
|
||||||
|
|
||||||
|
-g) chgrpcmd="$chgrpprog $2"
|
||||||
|
shift;;
|
||||||
|
|
||||||
|
--help) echo "$usage"; exit $?;;
|
||||||
|
|
||||||
|
-m) mode=$2
|
||||||
|
case $mode in
|
||||||
|
*' '* | *' '* | *'
|
||||||
|
'* | *'*'* | *'?'* | *'['*)
|
||||||
|
echo "$0: invalid mode: $mode" >&2
|
||||||
|
exit 1;;
|
||||||
|
esac
|
||||||
|
shift;;
|
||||||
|
|
||||||
|
-o) chowncmd="$chownprog $2"
|
||||||
|
shift;;
|
||||||
|
|
||||||
|
-s) stripcmd=$stripprog;;
|
||||||
|
|
||||||
|
-t) dst_arg=$2
|
||||||
|
shift;;
|
||||||
|
|
||||||
|
-T) no_target_directory=true;;
|
||||||
|
|
||||||
|
--version) echo "$0 $scriptversion"; exit $?;;
|
||||||
|
|
||||||
|
--) shift
|
||||||
|
break;;
|
||||||
|
|
||||||
|
-*) echo "$0: invalid option: $1" >&2
|
||||||
|
exit 1;;
|
||||||
|
|
||||||
|
*) break;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
|
||||||
|
# When -d is used, all remaining arguments are directories to create.
|
||||||
|
# When -t is used, the destination is already specified.
|
||||||
|
# Otherwise, the last argument is the destination. Remove it from $@.
|
||||||
|
for arg
|
||||||
|
do
|
||||||
|
if test -n "$dst_arg"; then
|
||||||
|
# $@ is not empty: it contains at least $arg.
|
||||||
|
set fnord "$@" "$dst_arg"
|
||||||
|
shift # fnord
|
||||||
|
fi
|
||||||
|
shift # arg
|
||||||
|
dst_arg=$arg
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test $# -eq 0; then
|
||||||
|
if test -z "$dir_arg"; then
|
||||||
|
echo "$0: no input file specified." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# It's OK to call `install-sh -d' without argument.
|
||||||
|
# This can happen when creating conditional directories.
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -z "$dir_arg"; then
|
||||||
|
trap '(exit $?); exit' 1 2 13 15
|
||||||
|
|
||||||
|
# Set umask so as not to create temps with too-generous modes.
|
||||||
|
# However, 'strip' requires both read and write access to temps.
|
||||||
|
case $mode in
|
||||||
|
# Optimize common cases.
|
||||||
|
*644) cp_umask=133;;
|
||||||
|
*755) cp_umask=22;;
|
||||||
|
|
||||||
|
*[0-7])
|
||||||
|
if test -z "$stripcmd"; then
|
||||||
|
u_plus_rw=
|
||||||
|
else
|
||||||
|
u_plus_rw='% 200'
|
||||||
|
fi
|
||||||
|
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
|
||||||
|
*)
|
||||||
|
if test -z "$stripcmd"; then
|
||||||
|
u_plus_rw=
|
||||||
|
else
|
||||||
|
u_plus_rw=,u+rw
|
||||||
|
fi
|
||||||
|
cp_umask=$mode$u_plus_rw;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
for src
|
||||||
|
do
|
||||||
|
# Protect names starting with `-'.
|
||||||
|
case $src in
|
||||||
|
-*) src=./$src;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if test -n "$dir_arg"; then
|
||||||
|
dst=$src
|
||||||
|
dstdir=$dst
|
||||||
|
test -d "$dstdir"
|
||||||
|
dstdir_status=$?
|
||||||
|
else
|
||||||
|
|
||||||
|
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
|
||||||
|
# might cause directories to be created, which would be especially bad
|
||||||
|
# if $src (and thus $dsttmp) contains '*'.
|
||||||
|
if test ! -f "$src" && test ! -d "$src"; then
|
||||||
|
echo "$0: $src does not exist." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -z "$dst_arg"; then
|
||||||
|
echo "$0: no destination specified." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
dst=$dst_arg
|
||||||
|
# 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: $dst_arg: Is a directory" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
dstdir=$dst
|
||||||
|
dst=$dstdir/`basename "$src"`
|
||||||
|
dstdir_status=0
|
||||||
|
else
|
||||||
|
# Prefer dirname, but fall back on a substitute if dirname fails.
|
||||||
|
dstdir=`
|
||||||
|
(dirname "$dst") 2>/dev/null ||
|
||||||
|
expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
|
||||||
|
X"$dst" : 'X\(//\)[^/]' \| \
|
||||||
|
X"$dst" : 'X\(//\)$' \| \
|
||||||
|
X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
|
||||||
|
echo X"$dst" |
|
||||||
|
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
|
||||||
|
s//\1/
|
||||||
|
q
|
||||||
|
}
|
||||||
|
/^X\(\/\/\)[^/].*/{
|
||||||
|
s//\1/
|
||||||
|
q
|
||||||
|
}
|
||||||
|
/^X\(\/\/\)$/{
|
||||||
|
s//\1/
|
||||||
|
q
|
||||||
|
}
|
||||||
|
/^X\(\/\).*/{
|
||||||
|
s//\1/
|
||||||
|
q
|
||||||
|
}
|
||||||
|
s/.*/./; q'
|
||||||
|
`
|
||||||
|
|
||||||
|
test -d "$dstdir"
|
||||||
|
dstdir_status=$?
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
obsolete_mkdir_used=false
|
||||||
|
|
||||||
|
if test $dstdir_status != 0; then
|
||||||
|
case $posix_mkdir in
|
||||||
|
'')
|
||||||
|
# Create intermediate dirs using mode 755 as modified by the umask.
|
||||||
|
# This is like FreeBSD 'install' as of 1997-10-28.
|
||||||
|
umask=`umask`
|
||||||
|
case $stripcmd.$umask in
|
||||||
|
# Optimize common cases.
|
||||||
|
*[2367][2367]) mkdir_umask=$umask;;
|
||||||
|
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
|
||||||
|
|
||||||
|
*[0-7])
|
||||||
|
mkdir_umask=`expr $umask + 22 \
|
||||||
|
- $umask % 100 % 40 + $umask % 20 \
|
||||||
|
- $umask % 10 % 4 + $umask % 2
|
||||||
|
`;;
|
||||||
|
*) mkdir_umask=$umask,go-w;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# With -d, create the new directory with the user-specified mode.
|
||||||
|
# Otherwise, rely on $mkdir_umask.
|
||||||
|
if test -n "$dir_arg"; then
|
||||||
|
mkdir_mode=-m$mode
|
||||||
|
else
|
||||||
|
mkdir_mode=
|
||||||
|
fi
|
||||||
|
|
||||||
|
posix_mkdir=false
|
||||||
|
case $umask in
|
||||||
|
*[123567][0-7][0-7])
|
||||||
|
# POSIX mkdir -p sets u+wx bits regardless of umask, which
|
||||||
|
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
|
||||||
|
trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
|
||||||
|
|
||||||
|
if (umask $mkdir_umask &&
|
||||||
|
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
if test -z "$dir_arg" || {
|
||||||
|
# Check for POSIX incompatibilities with -m.
|
||||||
|
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
|
||||||
|
# other-writeable bit of parent directory when it shouldn't.
|
||||||
|
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
|
||||||
|
ls_ld_tmpdir=`ls -ld "$tmpdir"`
|
||||||
|
case $ls_ld_tmpdir in
|
||||||
|
d????-?r-*) different_mode=700;;
|
||||||
|
d????-?--*) different_mode=755;;
|
||||||
|
*) false;;
|
||||||
|
esac &&
|
||||||
|
$mkdirprog -m$different_mode -p -- "$tmpdir" && {
|
||||||
|
ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
|
||||||
|
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
then posix_mkdir=:
|
||||||
|
fi
|
||||||
|
rmdir "$tmpdir/d" "$tmpdir"
|
||||||
|
else
|
||||||
|
# Remove any dirs left behind by ancient mkdir implementations.
|
||||||
|
rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
|
||||||
|
fi
|
||||||
|
trap '' 0;;
|
||||||
|
esac;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if
|
||||||
|
$posix_mkdir && (
|
||||||
|
umask $mkdir_umask &&
|
||||||
|
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
|
||||||
|
)
|
||||||
|
then :
|
||||||
|
else
|
||||||
|
|
||||||
|
# The umask is ridiculous, or mkdir does not conform to POSIX,
|
||||||
|
# or it failed possibly due to a race condition. Create the
|
||||||
|
# directory the slow way, step by step, checking for races as we go.
|
||||||
|
|
||||||
|
case $dstdir in
|
||||||
|
/*) prefix='/';;
|
||||||
|
-*) prefix='./';;
|
||||||
|
*) prefix='';;
|
||||||
|
esac
|
||||||
|
|
||||||
|
eval "$initialize_posix_glob"
|
||||||
|
|
||||||
|
oIFS=$IFS
|
||||||
|
IFS=/
|
||||||
|
$posix_glob set -f
|
||||||
|
set fnord $dstdir
|
||||||
|
shift
|
||||||
|
$posix_glob set +f
|
||||||
|
IFS=$oIFS
|
||||||
|
|
||||||
|
prefixes=
|
||||||
|
|
||||||
|
for d
|
||||||
|
do
|
||||||
|
test -z "$d" && continue
|
||||||
|
|
||||||
|
prefix=$prefix$d
|
||||||
|
if test -d "$prefix"; then
|
||||||
|
prefixes=
|
||||||
|
else
|
||||||
|
if $posix_mkdir; then
|
||||||
|
(umask=$mkdir_umask &&
|
||||||
|
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
|
||||||
|
# Don't fail if two instances are running concurrently.
|
||||||
|
test -d "$prefix" || exit 1
|
||||||
|
else
|
||||||
|
case $prefix in
|
||||||
|
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
|
||||||
|
*) qprefix=$prefix;;
|
||||||
|
esac
|
||||||
|
prefixes="$prefixes '$qprefix'"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
prefix=$prefix/
|
||||||
|
done
|
||||||
|
|
||||||
|
if test -n "$prefixes"; then
|
||||||
|
# Don't fail if two instances are running concurrently.
|
||||||
|
(umask $mkdir_umask &&
|
||||||
|
eval "\$doit_exec \$mkdirprog $prefixes") ||
|
||||||
|
test -d "$dstdir" || exit 1
|
||||||
|
obsolete_mkdir_used=true
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -n "$dir_arg"; then
|
||||||
|
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
|
||||||
|
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
|
||||||
|
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
|
||||||
|
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
|
||||||
|
else
|
||||||
|
|
||||||
|
# Make a couple of temp file names in the proper directory.
|
||||||
|
dsttmp=$dstdir/_inst.$$_
|
||||||
|
rmtmp=$dstdir/_rm.$$_
|
||||||
|
|
||||||
|
# Trap to clean up those temp files at exit.
|
||||||
|
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
|
||||||
|
|
||||||
|
# Copy the file name to the temp name.
|
||||||
|
(umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
|
||||||
|
|
||||||
|
# and set any options; do chmod last to preserve setuid bits.
|
||||||
|
#
|
||||||
|
# If any of these fail, we abort the whole thing. If we want to
|
||||||
|
# ignore errors from any of these, just make sure not to ignore
|
||||||
|
# errors from the above "$doit $cpprog $src $dsttmp" command.
|
||||||
|
#
|
||||||
|
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
|
||||||
|
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
|
||||||
|
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
|
||||||
|
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
|
||||||
|
|
||||||
|
# If -C, don't bother to copy if it wouldn't change the file.
|
||||||
|
if $copy_on_change &&
|
||||||
|
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
|
||||||
|
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
|
||||||
|
|
||||||
|
eval "$initialize_posix_glob" &&
|
||||||
|
$posix_glob set -f &&
|
||||||
|
set X $old && old=:$2:$4:$5:$6 &&
|
||||||
|
set X $new && new=:$2:$4:$5:$6 &&
|
||||||
|
$posix_glob set +f &&
|
||||||
|
|
||||||
|
test "$old" = "$new" &&
|
||||||
|
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
rm -f "$dsttmp"
|
||||||
|
else
|
||||||
|
# Rename the file to the real destination.
|
||||||
|
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
|
||||||
|
|
||||||
|
# The rename failed, perhaps because mv can't rename something else
|
||||||
|
# to itself, or perhaps because mv is so ancient that it does not
|
||||||
|
# support -f.
|
||||||
|
{
|
||||||
|
# Now remove or move aside any old file at destination location.
|
||||||
|
# We try this two ways since rm can't unlink itself on some
|
||||||
|
# systems and the destination file might be busy for other
|
||||||
|
# reasons. In this case, the final cleanup might fail but the new
|
||||||
|
# file should still install successfully.
|
||||||
|
{
|
||||||
|
test ! -f "$dst" ||
|
||||||
|
$doit $rmcmd -f "$dst" 2>/dev/null ||
|
||||||
|
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
|
||||||
|
{ $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
|
||||||
|
} ||
|
||||||
|
{ echo "$0: cannot unlink or rename $dst" >&2
|
||||||
|
(exit 1); exit 1
|
||||||
|
}
|
||||||
|
} &&
|
||||||
|
|
||||||
|
# Now rename the file to the real destination.
|
||||||
|
$doit $mvcmd "$dsttmp" "$dst"
|
||||||
|
}
|
||||||
|
fi || exit 1
|
||||||
|
|
||||||
|
trap '' 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Local variables:
|
||||||
|
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||||
|
# time-stamp-start: "scriptversion="
|
||||||
|
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||||
|
# time-stamp-time-zone: "UTC"
|
||||||
|
# time-stamp-end: "; # UTC"
|
||||||
|
# End:
|
@ -0,0 +1,12 @@
|
|||||||
|
prefix=@prefix@
|
||||||
|
exec_prefix=@exec_prefix@
|
||||||
|
libdir=@libdir@
|
||||||
|
includedir=@includedir@
|
||||||
|
|
||||||
|
Name: libr
|
||||||
|
Description: libr ELF resource manager library
|
||||||
|
Version: @VERSION@
|
||||||
|
|
||||||
|
Requires:
|
||||||
|
Libs: -L${libdir} -lr
|
||||||
|
Cflags: -I${includedir}
|
@ -0,0 +1,11 @@
|
|||||||
|
2009-09-08 gettextize <bug-gnu-gettext@gnu.org>
|
||||||
|
|
||||||
|
* gettext.m4: New file, from gettext-0.17.
|
||||||
|
* iconv.m4: New file, from gettext-0.17.
|
||||||
|
* lib-ld.m4: New file, from gettext-0.17.
|
||||||
|
* lib-link.m4: New file, from gettext-0.17.
|
||||||
|
* lib-prefix.m4: New file, from gettext-0.17.
|
||||||
|
* nls.m4: New file, from gettext-0.17.
|
||||||
|
* po.m4: New file, from gettext-0.17.
|
||||||
|
* progtest.m4: New file, from gettext-0.17.
|
||||||
|
|
@ -0,0 +1,5 @@
|
|||||||
|
man3/*.3:
|
||||||
|
doxygen ../doc/libr.cfg
|
||||||
|
|
||||||
|
man_MANS = man3/*.3
|
||||||
|
CLEANFILES = man3/*.3
|
@ -0,0 +1,471 @@
|
|||||||
|
# Makefile.in generated by automake 1.11.1 from Makefile.am.
|
||||||
|
# @configure_input@
|
||||||
|
|
||||||
|
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||||
|
# 2003, 2004, 2005, 2006, 2007, 2008, 2009 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@
|
||||||
|
pkgdatadir = $(datadir)/@PACKAGE@
|
||||||
|
pkgincludedir = $(includedir)/@PACKAGE@
|
||||||
|
pkglibdir = $(libdir)/@PACKAGE@
|
||||||
|
pkglibexecdir = $(libexecdir)/@PACKAGE@
|
||||||
|
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||||
|
install_sh_DATA = $(install_sh) -c -m 644
|
||||||
|
install_sh_PROGRAM = $(install_sh) -c
|
||||||
|
install_sh_SCRIPT = $(install_sh) -c
|
||||||
|
INSTALL_HEADER = $(INSTALL_DATA)
|
||||||
|
transform = $(program_transform_name)
|
||||||
|
NORMAL_INSTALL = :
|
||||||
|
PRE_INSTALL = :
|
||||||
|
POST_INSTALL = :
|
||||||
|
NORMAL_UNINSTALL = :
|
||||||
|
PRE_UNINSTALL = :
|
||||||
|
POST_UNINSTALL = :
|
||||||
|
build_triplet = @build@
|
||||||
|
host_triplet = @host@
|
||||||
|
subdir = man
|
||||||
|
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
|
||||||
|
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||||
|
am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \
|
||||||
|
$(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \
|
||||||
|
$(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \
|
||||||
|
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
|
||||||
|
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
|
||||||
|
$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \
|
||||||
|
$(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \
|
||||||
|
$(top_srcdir)/configure.ac
|
||||||
|
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||||
|
$(ACLOCAL_M4)
|
||||||
|
mkinstalldirs = $(install_sh) -d
|
||||||
|
CONFIG_HEADER = $(top_builddir)/config.h
|
||||||
|
CONFIG_CLEAN_FILES =
|
||||||
|
CONFIG_CLEAN_VPATH_FILES =
|
||||||
|
SOURCES =
|
||||||
|
DIST_SOURCES =
|
||||||
|
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'
|
||||||
|
man3dir = $(mandir)/man3
|
||||||
|
am__installdirs = "$(DESTDIR)$(man3dir)"
|
||||||
|
NROFF = nroff
|
||||||
|
MANS = $(man_MANS)
|
||||||
|
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||||
|
ACLOCAL = @ACLOCAL@
|
||||||
|
AMTAR = @AMTAR@
|
||||||
|
AR = @AR@
|
||||||
|
AUTOCONF = @AUTOCONF@
|
||||||
|
AUTOHEADER = @AUTOHEADER@
|
||||||
|
AUTOMAKE = @AUTOMAKE@
|
||||||
|
AWK = @AWK@
|
||||||
|
BACKEND_CFLAGS = @BACKEND_CFLAGS@
|
||||||
|
BACKEND_LIBS = @BACKEND_LIBS@
|
||||||
|
BACKEND_NAME = @BACKEND_NAME@
|
||||||
|
BACKEND_PKG = @BACKEND_PKG@
|
||||||
|
CC = @CC@
|
||||||
|
CCDEPMODE = @CCDEPMODE@
|
||||||
|
CFLAGS = @CFLAGS@
|
||||||
|
CPP = @CPP@
|
||||||
|
CPPFLAGS = @CPPFLAGS@
|
||||||
|
CYGPATH_W = @CYGPATH_W@
|
||||||
|
DEFS = @DEFS@
|
||||||
|
DEPDIR = @DEPDIR@
|
||||||
|
DSYMUTIL = @DSYMUTIL@
|
||||||
|
DUMPBIN = @DUMPBIN@
|
||||||
|
ECHO_C = @ECHO_C@
|
||||||
|
ECHO_N = @ECHO_N@
|
||||||
|
ECHO_T = @ECHO_T@
|
||||||
|
EGREP = @EGREP@
|
||||||
|
EXEEXT = @EXEEXT@
|
||||||
|
EXTRA_CFLAGS = @EXTRA_CFLAGS@
|
||||||
|
EXTRA_LIBS = @EXTRA_LIBS@
|
||||||
|
FGREP = @FGREP@
|
||||||
|
GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
|
||||||
|
GMSGFMT = @GMSGFMT@
|
||||||
|
GMSGFMT_015 = @GMSGFMT_015@
|
||||||
|
GREP = @GREP@
|
||||||
|
INSTALL = @INSTALL@
|
||||||
|
INSTALL_DATA = @INSTALL_DATA@
|
||||||
|
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||||
|
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||||
|
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||||
|
INTLLIBS = @INTLLIBS@
|
||||||
|
INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
|
||||||
|
LD = @LD@
|
||||||
|
LDFLAGS = @LDFLAGS@
|
||||||
|
LIBGLADE_CFLAGS = @LIBGLADE_CFLAGS@
|
||||||
|
LIBGLADE_LIBS = @LIBGLADE_LIBS@
|
||||||
|
LIBICONV = @LIBICONV@
|
||||||
|
LIBINTL = @LIBINTL@
|
||||||
|
LIBOBJS = @LIBOBJS@
|
||||||
|
LIBR_BACKEND = @LIBR_BACKEND@
|
||||||
|
LIBS = @LIBS@
|
||||||
|
LIBTOOL = @LIBTOOL@
|
||||||
|
LIBTOOL_DEPS = @LIBTOOL_DEPS@
|
||||||
|
LIPO = @LIPO@
|
||||||
|
LN_S = @LN_S@
|
||||||
|
LTLIBICONV = @LTLIBICONV@
|
||||||
|
LTLIBINTL = @LTLIBINTL@
|
||||||
|
LTLIBOBJS = @LTLIBOBJS@
|
||||||
|
MAKEINFO = @MAKEINFO@
|
||||||
|
MKDIR_P = @MKDIR_P@
|
||||||
|
MSGFMT = @MSGFMT@
|
||||||
|
MSGFMT_015 = @MSGFMT_015@
|
||||||
|
MSGMERGE = @MSGMERGE@
|
||||||
|
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@
|
||||||
|
PKG_CONFIG = @PKG_CONFIG@
|
||||||
|
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
|
||||||
|
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
|
||||||
|
POSUB = @POSUB@
|
||||||
|
RANLIB = @RANLIB@
|
||||||
|
SED = @SED@
|
||||||
|
SET_MAKE = @SET_MAKE@
|
||||||
|
SHELL = @SHELL@
|
||||||
|
STRIP = @STRIP@
|
||||||
|
USE_NLS = @USE_NLS@
|
||||||
|
VERSION = @VERSION@
|
||||||
|
XGETTEXT = @XGETTEXT@
|
||||||
|
XGETTEXT_015 = @XGETTEXT_015@
|
||||||
|
XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
|
||||||
|
abs_builddir = @abs_builddir@
|
||||||
|
abs_srcdir = @abs_srcdir@
|
||||||
|
abs_top_builddir = @abs_top_builddir@
|
||||||
|
abs_top_srcdir = @abs_top_srcdir@
|
||||||
|
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 = @docdir@
|
||||||
|
dvidir = @dvidir@
|
||||||
|
exec_prefix = @exec_prefix@
|
||||||
|
host = @host@
|
||||||
|
host_alias = @host_alias@
|
||||||
|
host_cpu = @host_cpu@
|
||||||
|
host_os = @host_os@
|
||||||
|
host_vendor = @host_vendor@
|
||||||
|
htmldir = @htmldir@
|
||||||
|
includedir = @includedir@
|
||||||
|
infodir = @infodir@
|
||||||
|
install_sh = @install_sh@
|
||||||
|
libdir = @libdir@
|
||||||
|
libexecdir = @libexecdir@
|
||||||
|
localedir = @localedir@
|
||||||
|
localstatedir = @localstatedir@
|
||||||
|
lt_ECHO = @lt_ECHO@
|
||||||
|
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_alias = @target_alias@
|
||||||
|
top_build_prefix = @top_build_prefix@
|
||||||
|
top_builddir = @top_builddir@
|
||||||
|
top_srcdir = @top_srcdir@
|
||||||
|
man_MANS = man3/*.3
|
||||||
|
CLEANFILES = man3/*.3
|
||||||
|
all: all-am
|
||||||
|
|
||||||
|
.SUFFIXES:
|
||||||
|
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
||||||
|
@for dep in $?; do \
|
||||||
|
case '$(am__configure_deps)' in \
|
||||||
|
*$$dep*) \
|
||||||
|
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
|
||||||
|
&& { if test -f $@; then exit 0; else break; fi; }; \
|
||||||
|
exit 1;; \
|
||||||
|
esac; \
|
||||||
|
done; \
|
||||||
|
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu man/Makefile'; \
|
||||||
|
$(am__cd) $(top_srcdir) && \
|
||||||
|
$(AUTOMAKE) --gnu man/Makefile
|
||||||
|
.PRECIOUS: Makefile
|
||||||
|
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||||
|
@case '$?' in \
|
||||||
|
*config.status*) \
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||||
|
*) \
|
||||||
|
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||||
|
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||||
|
esac;
|
||||||
|
|
||||||
|
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||||
|
|
||||||
|
$(top_srcdir)/configure: $(am__configure_deps)
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||||
|
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||||
|
$(am__aclocal_m4_deps):
|
||||||
|
|
||||||
|
mostlyclean-libtool:
|
||||||
|
-rm -f *.lo
|
||||||
|
|
||||||
|
clean-libtool:
|
||||||
|
-rm -rf .libs _libs
|
||||||
|
install-man3: $(man_MANS)
|
||||||
|
@$(NORMAL_INSTALL)
|
||||||
|
test -z "$(man3dir)" || $(MKDIR_P) "$(DESTDIR)$(man3dir)"
|
||||||
|
@list=''; test -n "$(man3dir)" || exit 0; \
|
||||||
|
{ for i in $$list; do echo "$$i"; done; \
|
||||||
|
l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \
|
||||||
|
sed -n '/\.3[a-z]*$$/p'; \
|
||||||
|
} | while read p; do \
|
||||||
|
if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
|
||||||
|
echo "$$d$$p"; echo "$$p"; \
|
||||||
|
done | \
|
||||||
|
sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \
|
||||||
|
-e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
|
||||||
|
sed 'N;N;s,\n, ,g' | { \
|
||||||
|
list=; while read file base inst; do \
|
||||||
|
if test "$$base" = "$$inst"; then list="$$list $$file"; else \
|
||||||
|
echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man3dir)/$$inst'"; \
|
||||||
|
$(INSTALL_DATA) "$$file" "$(DESTDIR)$(man3dir)/$$inst" || exit $$?; \
|
||||||
|
fi; \
|
||||||
|
done; \
|
||||||
|
for i in $$list; do echo "$$i"; done | $(am__base_list) | \
|
||||||
|
while read files; do \
|
||||||
|
test -z "$$files" || { \
|
||||||
|
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man3dir)'"; \
|
||||||
|
$(INSTALL_DATA) $$files "$(DESTDIR)$(man3dir)" || exit $$?; }; \
|
||||||
|
done; }
|
||||||
|
|
||||||
|
uninstall-man3:
|
||||||
|
@$(NORMAL_UNINSTALL)
|
||||||
|
@list=''; test -n "$(man3dir)" || exit 0; \
|
||||||
|
files=`{ for i in $$list; do echo "$$i"; done; \
|
||||||
|
l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \
|
||||||
|
sed -n '/\.3[a-z]*$$/p'; \
|
||||||
|
} | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \
|
||||||
|
-e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
|
||||||
|
test -z "$$files" || { \
|
||||||
|
echo " ( cd '$(DESTDIR)$(man3dir)' && rm -f" $$files ")"; \
|
||||||
|
cd "$(DESTDIR)$(man3dir)" && rm -f $$files; }
|
||||||
|
tags: TAGS
|
||||||
|
TAGS:
|
||||||
|
|
||||||
|
ctags: CTAGS
|
||||||
|
CTAGS:
|
||||||
|
|
||||||
|
|
||||||
|
distdir: $(DISTFILES)
|
||||||
|
@list='$(MANS)'; if test -n "$$list"; then \
|
||||||
|
list=`for p in $$list; do \
|
||||||
|
if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
|
||||||
|
if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \
|
||||||
|
if test -n "$$list" && \
|
||||||
|
grep 'ab help2man is required to generate this page' $$list >/dev/null; then \
|
||||||
|
echo "error: found man pages containing the \`missing help2man' replacement text:" >&2; \
|
||||||
|
grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \
|
||||||
|
echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \
|
||||||
|
echo " typically \`make maintainer-clean' will remove them" >&2; \
|
||||||
|
exit 1; \
|
||||||
|
else :; fi; \
|
||||||
|
else :; fi
|
||||||
|
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||||
|
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||||
|
list='$(DISTFILES)'; \
|
||||||
|
dist_files=`for file in $$list; do echo $$file; done | \
|
||||||
|
sed -e "s|^$$srcdirstrip/||;t" \
|
||||||
|
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||||
|
case $$dist_files in \
|
||||||
|
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||||
|
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||||
|
sort -u` ;; \
|
||||||
|
esac; \
|
||||||
|
for file in $$dist_files; do \
|
||||||
|
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||||
|
if test -d $$d/$$file; then \
|
||||||
|
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||||
|
if test -d "$(distdir)/$$file"; then \
|
||||||
|
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||||
|
fi; \
|
||||||
|
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||||
|
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
|
||||||
|
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||||
|
fi; \
|
||||||
|
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
|
||||||
|
else \
|
||||||
|
test -f "$(distdir)/$$file" \
|
||||||
|
|| cp -p $$d/$$file "$(distdir)/$$file" \
|
||||||
|
|| exit 1; \
|
||||||
|
fi; \
|
||||||
|
done
|
||||||
|
check-am: all-am
|
||||||
|
check: check-am
|
||||||
|
all-am: Makefile $(MANS)
|
||||||
|
installdirs:
|
||||||
|
for dir in "$(DESTDIR)$(man3dir)"; 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:
|
||||||
|
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||||
|
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||||
|
`test -z '$(STRIP)' || \
|
||||||
|
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
|
||||||
|
mostlyclean-generic:
|
||||||
|
|
||||||
|
clean-generic:
|
||||||
|
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
maintainer-clean-generic:
|
||||||
|
@echo "This command is intended for maintainers to use"
|
||||||
|
@echo "it deletes files that may require special tools to rebuild."
|
||||||
|
clean: clean-am
|
||||||
|
|
||||||
|
clean-am: clean-generic clean-libtool mostlyclean-am
|
||||||
|
|
||||||
|
distclean: distclean-am
|
||||||
|
-rm -f Makefile
|
||||||
|
distclean-am: clean-am distclean-generic
|
||||||
|
|
||||||
|
dvi: dvi-am
|
||||||
|
|
||||||
|
dvi-am:
|
||||||
|
|
||||||
|
html: html-am
|
||||||
|
|
||||||
|
html-am:
|
||||||
|
|
||||||
|
info: info-am
|
||||||
|
|
||||||
|
info-am:
|
||||||
|
|
||||||
|
install-data-am: install-man
|
||||||
|
|
||||||
|
install-dvi: install-dvi-am
|
||||||
|
|
||||||
|
install-dvi-am:
|
||||||
|
|
||||||
|
install-exec-am:
|
||||||
|
|
||||||
|
install-html: install-html-am
|
||||||
|
|
||||||
|
install-html-am:
|
||||||
|
|
||||||
|
install-info: install-info-am
|
||||||
|
|
||||||
|
install-info-am:
|
||||||
|
|
||||||
|
install-man: install-man3
|
||||||
|
|
||||||
|
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 Makefile
|
||||||
|
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||||
|
|
||||||
|
mostlyclean: mostlyclean-am
|
||||||
|
|
||||||
|
mostlyclean-am: mostlyclean-generic mostlyclean-libtool
|
||||||
|
|
||||||
|
pdf: pdf-am
|
||||||
|
|
||||||
|
pdf-am:
|
||||||
|
|
||||||
|
ps: ps-am
|
||||||
|
|
||||||
|
ps-am:
|
||||||
|
|
||||||
|
uninstall-am: uninstall-man
|
||||||
|
|
||||||
|
uninstall-man: uninstall-man3
|
||||||
|
|
||||||
|
.MAKE: install-am install-strip
|
||||||
|
|
||||||
|
.PHONY: all all-am check check-am clean clean-generic clean-libtool \
|
||||||
|
distclean distclean-generic distclean-libtool distdir dvi \
|
||||||
|
dvi-am html html-am info info-am install install-am \
|
||||||
|
install-data install-data-am install-dvi install-dvi-am \
|
||||||
|
install-exec install-exec-am install-html install-html-am \
|
||||||
|
install-info install-info-am install-man install-man3 \
|
||||||
|
install-pdf install-pdf-am install-ps install-ps-am \
|
||||||
|
install-strip installcheck installcheck-am installdirs \
|
||||||
|
maintainer-clean maintainer-clean-generic mostlyclean \
|
||||||
|
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
|
||||||
|
uninstall uninstall-am uninstall-man uninstall-man3
|
||||||
|
|
||||||
|
man3/*.3:
|
||||||
|
doxygen ../doc/libr.cfg
|
||||||
|
|
||||||
|
# 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:
|
@ -0,0 +1,376 @@
|
|||||||
|
#! /bin/sh
|
||||||
|
# Common stub for a few missing GNU programs while installing.
|
||||||
|
|
||||||
|
scriptversion=2009-04-28.21; # UTC
|
||||||
|
|
||||||
|
# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006,
|
||||||
|
# 2008, 2009 Free Software Foundation, Inc.
|
||||||
|
# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
|
||||||
|
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2, or (at your option)
|
||||||
|
# any later version.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# 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=:
|
||||||
|
sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p'
|
||||||
|
sed_minuso='s/.* -o \([^ ]*\).*/\1/p'
|
||||||
|
|
||||||
|
# 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'
|
||||||
|
autom4te touch the output file, or create a stub one
|
||||||
|
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]
|
||||||
|
|
||||||
|
Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and
|
||||||
|
\`g' are ignored when checking the name.
|
||||||
|
|
||||||
|
Send bug reports to <bug-automake@gnu.org>."
|
||||||
|
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
|
||||||
|
|
||||||
|
# normalize program name to check for.
|
||||||
|
program=`echo "$1" | sed '
|
||||||
|
s/^gnu-//; t
|
||||||
|
s/^gnu//; t
|
||||||
|
s/^g//; t'`
|
||||||
|
|
||||||
|
# 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). This is about non-GNU programs, so use $1 not
|
||||||
|
# $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 $program 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 "$sed_output"`
|
||||||
|
test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
|
||||||
|
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 test $# -ne 1; then
|
||||||
|
eval LASTARG="\${$#}"
|
||||||
|
case $LASTARG in
|
||||||
|
*.y)
|
||||||
|
SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
|
||||||
|
if test -f "$SRCFILE"; then
|
||||||
|
cp "$SRCFILE" y.tab.c
|
||||||
|
fi
|
||||||
|
SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
|
||||||
|
if test -f "$SRCFILE"; then
|
||||||
|
cp "$SRCFILE" y.tab.h
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
if test ! -f y.tab.h; then
|
||||||
|
echo >y.tab.h
|
||||||
|
fi
|
||||||
|
if test ! -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 test $# -ne 1; then
|
||||||
|
eval LASTARG="\${$#}"
|
||||||
|
case $LASTARG in
|
||||||
|
*.l)
|
||||||
|
SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
|
||||||
|
if test -f "$SRCFILE"; then
|
||||||
|
cp "$SRCFILE" lex.yy.c
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
if test ! -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 "$sed_output"`
|
||||||
|
test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
|
||||||
|
if test -f "$file"; then
|
||||||
|
touch $file
|
||||||
|
else
|
||||||
|
test -z "$file" || exec >$file
|
||||||
|
echo ".ab help2man is required to generate this page"
|
||||||
|
exit $?
|
||||||
|
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 "$sed_output"`
|
||||||
|
test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
|
||||||
|
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-time-zone: "UTC"
|
||||||
|
# time-stamp-end: "; # UTC"
|
||||||
|
# End:
|
@ -0,0 +1,12 @@
|
|||||||
|
2009-09-08 gettextize <bug-gnu-gettext@gnu.org>
|
||||||
|
|
||||||
|
* Makefile.in.in: New file, from gettext-0.17.
|
||||||
|
* Rules-quot: New file, from gettext-0.17.
|
||||||
|
* boldquot.sed: New file, from gettext-0.17.
|
||||||
|
* en@boldquot.header: New file, from gettext-0.17.
|
||||||
|
* en@quot.header: New file, from gettext-0.17.
|
||||||
|
* insert-header.sin: New file, from gettext-0.17.
|
||||||
|
* quot.sed: New file, from gettext-0.17.
|
||||||
|
* remove-potcdate.sin: New file, from gettext-0.17.
|
||||||
|
* POTFILES.in: New file.
|
||||||
|
|
@ -0,0 +1,433 @@
|
|||||||
|
# Makefile for PO directory in any package using GNU gettext.
|
||||||
|
# Copyright (C) 1995-1997, 2000-2007 by Ulrich Drepper <drepper@gnu.ai.mit.edu>
|
||||||
|
#
|
||||||
|
# This file can be copied and used freely without restrictions. It can
|
||||||
|
# be used in projects which are not available under the GNU General Public
|
||||||
|
# License but which still want to provide support for the GNU gettext
|
||||||
|
# functionality.
|
||||||
|
# Please note that the actual code of GNU gettext is covered by the GNU
|
||||||
|
# General Public License and is *not* in the public domain.
|
||||||
|
#
|
||||||
|
# Origin: gettext-0.17
|
||||||
|
GETTEXT_MACRO_VERSION = 0.17
|
||||||
|
|
||||||
|
PACKAGE = @PACKAGE@
|
||||||
|
VERSION = @VERSION@
|
||||||
|
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||||
|
|
||||||
|
SHELL = /bin/sh
|
||||||
|
@SET_MAKE@
|
||||||
|
|
||||||
|
srcdir = @srcdir@
|
||||||
|
top_srcdir = @top_srcdir@
|
||||||
|
VPATH = @srcdir@
|
||||||
|
|
||||||
|
prefix = @prefix@
|
||||||
|
exec_prefix = @exec_prefix@
|
||||||
|
datarootdir = @datarootdir@
|
||||||
|
datadir = @datadir@
|
||||||
|
localedir = @localedir@
|
||||||
|
gettextsrcdir = $(datadir)/gettext/po
|
||||||
|
|
||||||
|
INSTALL = @INSTALL@
|
||||||
|
INSTALL_DATA = @INSTALL_DATA@
|
||||||
|
|
||||||
|
# We use $(mkdir_p).
|
||||||
|
# In automake <= 1.9.x, $(mkdir_p) is defined either as "mkdir -p --" or as
|
||||||
|
# "$(mkinstalldirs)" or as "$(install_sh) -d". For these automake versions,
|
||||||
|
# @install_sh@ does not start with $(SHELL), so we add it.
|
||||||
|
# In automake >= 1.10, @mkdir_p@ is derived from ${MKDIR_P}, which is defined
|
||||||
|
# either as "/path/to/mkdir -p" or ".../install-sh -c -d". For these automake
|
||||||
|
# versions, $(mkinstalldirs) and $(install_sh) are unused.
|
||||||
|
mkinstalldirs = $(SHELL) @install_sh@ -d
|
||||||
|
install_sh = $(SHELL) @install_sh@
|
||||||
|
MKDIR_P = @MKDIR_P@
|
||||||
|
mkdir_p = @mkdir_p@
|
||||||
|
|
||||||
|
GMSGFMT_ = @GMSGFMT@
|
||||||
|
GMSGFMT_no = @GMSGFMT@
|
||||||
|
GMSGFMT_yes = @GMSGFMT_015@
|
||||||
|
GMSGFMT = $(GMSGFMT_$(USE_MSGCTXT))
|
||||||
|
MSGFMT_ = @MSGFMT@
|
||||||
|
MSGFMT_no = @MSGFMT@
|
||||||
|
MSGFMT_yes = @MSGFMT_015@
|
||||||
|
MSGFMT = $(MSGFMT_$(USE_MSGCTXT))
|
||||||
|
XGETTEXT_ = @XGETTEXT@
|
||||||
|
XGETTEXT_no = @XGETTEXT@
|
||||||
|
XGETTEXT_yes = @XGETTEXT_015@
|
||||||
|
XGETTEXT = $(XGETTEXT_$(USE_MSGCTXT))
|
||||||
|
MSGMERGE = msgmerge
|
||||||
|
MSGMERGE_UPDATE = @MSGMERGE@ --update
|
||||||
|
MSGINIT = msginit
|
||||||
|
MSGCONV = msgconv
|
||||||
|
MSGFILTER = msgfilter
|
||||||
|
|
||||||
|
POFILES = @POFILES@
|
||||||
|
GMOFILES = @GMOFILES@
|
||||||
|
UPDATEPOFILES = @UPDATEPOFILES@
|
||||||
|
DUMMYPOFILES = @DUMMYPOFILES@
|
||||||
|
DISTFILES.common = Makefile.in.in remove-potcdate.sin \
|
||||||
|
$(DISTFILES.common.extra1) $(DISTFILES.common.extra2) $(DISTFILES.common.extra3)
|
||||||
|
DISTFILES = $(DISTFILES.common) Makevars POTFILES.in \
|
||||||
|
$(POFILES) $(GMOFILES) \
|
||||||
|
$(DISTFILES.extra1) $(DISTFILES.extra2) $(DISTFILES.extra3)
|
||||||
|
|
||||||
|
POTFILES = \
|
||||||
|
|
||||||
|
CATALOGS = @CATALOGS@
|
||||||
|
|
||||||
|
# Makevars gets inserted here. (Don't remove this line!)
|
||||||
|
|
||||||
|
.SUFFIXES:
|
||||||
|
.SUFFIXES: .po .gmo .mo .sed .sin .nop .po-create .po-update
|
||||||
|
|
||||||
|
.po.mo:
|
||||||
|
@echo "$(MSGFMT) -c -o $@ $<"; \
|
||||||
|
$(MSGFMT) -c -o t-$@ $< && mv t-$@ $@
|
||||||
|
|
||||||
|
.po.gmo:
|
||||||
|
@lang=`echo $* | sed -e 's,.*/,,'`; \
|
||||||
|
test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
|
||||||
|
echo "$${cdcmd}rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics -o $${lang}.gmo $${lang}.po"; \
|
||||||
|
cd $(srcdir) && rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics -o t-$${lang}.gmo $${lang}.po && mv t-$${lang}.gmo $${lang}.gmo
|
||||||
|
|
||||||
|
.sin.sed:
|
||||||
|
sed -e '/^#/d' $< > t-$@
|
||||||
|
mv t-$@ $@
|
||||||
|
|
||||||
|
|
||||||
|
all: check-macro-version all-@USE_NLS@
|
||||||
|
|
||||||
|
all-yes: stamp-po
|
||||||
|
all-no:
|
||||||
|
|
||||||
|
# Ensure that the gettext macros and this Makefile.in.in are in sync.
|
||||||
|
check-macro-version:
|
||||||
|
@test "$(GETTEXT_MACRO_VERSION)" = "@GETTEXT_MACRO_VERSION@" \
|
||||||
|
|| { echo "*** error: gettext infrastructure mismatch: using a Makefile.in.in from gettext version $(GETTEXT_MACRO_VERSION) but the autoconf macros are from gettext version @GETTEXT_MACRO_VERSION@" 1>&2; \
|
||||||
|
exit 1; \
|
||||||
|
}
|
||||||
|
|
||||||
|
# $(srcdir)/$(DOMAIN).pot is only created when needed. When xgettext finds no
|
||||||
|
# internationalized messages, no $(srcdir)/$(DOMAIN).pot is created (because
|
||||||
|
# we don't want to bother translators with empty POT files). We assume that
|
||||||
|
# LINGUAS is empty in this case, i.e. $(POFILES) and $(GMOFILES) are empty.
|
||||||
|
# In this case, stamp-po is a nop (i.e. a phony target).
|
||||||
|
|
||||||
|
# stamp-po is a timestamp denoting the last time at which the CATALOGS have
|
||||||
|
# been loosely updated. Its purpose is that when a developer or translator
|
||||||
|
# checks out the package via CVS, and the $(DOMAIN).pot file is not in CVS,
|
||||||
|
# "make" will update the $(DOMAIN).pot and the $(CATALOGS), but subsequent
|
||||||
|
# invocations of "make" will do nothing. This timestamp would not be necessary
|
||||||
|
# if updating the $(CATALOGS) would always touch them; however, the rule for
|
||||||
|
# $(POFILES) has been designed to not touch files that don't need to be
|
||||||
|
# changed.
|
||||||
|
stamp-po: $(srcdir)/$(DOMAIN).pot
|
||||||
|
test ! -f $(srcdir)/$(DOMAIN).pot || \
|
||||||
|
test -z "$(GMOFILES)" || $(MAKE) $(GMOFILES)
|
||||||
|
@test ! -f $(srcdir)/$(DOMAIN).pot || { \
|
||||||
|
echo "touch stamp-po" && \
|
||||||
|
echo timestamp > stamp-poT && \
|
||||||
|
mv stamp-poT stamp-po; \
|
||||||
|
}
|
||||||
|
|
||||||
|
# Note: Target 'all' must not depend on target '$(DOMAIN).pot-update',
|
||||||
|
# otherwise packages like GCC can not be built if only parts of the source
|
||||||
|
# have been downloaded.
|
||||||
|
|
||||||
|
# This target rebuilds $(DOMAIN).pot; it is an expensive operation.
|
||||||
|
# Note that $(DOMAIN).pot is not touched if it doesn't need to be changed.
|
||||||
|
$(DOMAIN).pot-update: $(POTFILES) $(srcdir)/POTFILES.in remove-potcdate.sed
|
||||||
|
if LC_ALL=C grep 'GNU @PACKAGE@' $(top_srcdir)/* 2>/dev/null | grep -v 'libtool:' >/dev/null; then \
|
||||||
|
package_gnu='GNU '; \
|
||||||
|
else \
|
||||||
|
package_gnu=''; \
|
||||||
|
fi; \
|
||||||
|
if test -n '$(MSGID_BUGS_ADDRESS)' || test '$(PACKAGE_BUGREPORT)' = '@'PACKAGE_BUGREPORT'@'; then \
|
||||||
|
msgid_bugs_address='$(MSGID_BUGS_ADDRESS)'; \
|
||||||
|
else \
|
||||||
|
msgid_bugs_address='$(PACKAGE_BUGREPORT)'; \
|
||||||
|
fi; \
|
||||||
|
case `$(XGETTEXT) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
|
||||||
|
'' | 0.[0-9] | 0.[0-9].* | 0.1[0-5] | 0.1[0-5].* | 0.16 | 0.16.[0-1]*) \
|
||||||
|
$(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \
|
||||||
|
--add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) @XGETTEXT_EXTRA_OPTIONS@ \
|
||||||
|
--files-from=$(srcdir)/POTFILES.in \
|
||||||
|
--copyright-holder='$(COPYRIGHT_HOLDER)' \
|
||||||
|
--msgid-bugs-address="$$msgid_bugs_address" \
|
||||||
|
;; \
|
||||||
|
*) \
|
||||||
|
$(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \
|
||||||
|
--add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) @XGETTEXT_EXTRA_OPTIONS@ \
|
||||||
|
--files-from=$(srcdir)/POTFILES.in \
|
||||||
|
--copyright-holder='$(COPYRIGHT_HOLDER)' \
|
||||||
|
--package-name="$${package_gnu}@PACKAGE@" \
|
||||||
|
--package-version='@VERSION@' \
|
||||||
|
--msgid-bugs-address="$$msgid_bugs_address" \
|
||||||
|
;; \
|
||||||
|
esac
|
||||||
|
test ! -f $(DOMAIN).po || { \
|
||||||
|
if test -f $(srcdir)/$(DOMAIN).pot; then \
|
||||||
|
sed -f remove-potcdate.sed < $(srcdir)/$(DOMAIN).pot > $(DOMAIN).1po && \
|
||||||
|
sed -f remove-potcdate.sed < $(DOMAIN).po > $(DOMAIN).2po && \
|
||||||
|
if cmp $(DOMAIN).1po $(DOMAIN).2po >/dev/null 2>&1; then \
|
||||||
|
rm -f $(DOMAIN).1po $(DOMAIN).2po $(DOMAIN).po; \
|
||||||
|
else \
|
||||||
|
rm -f $(DOMAIN).1po $(DOMAIN).2po $(srcdir)/$(DOMAIN).pot && \
|
||||||
|
mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot; \
|
||||||
|
fi; \
|
||||||
|
else \
|
||||||
|
mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot; \
|
||||||
|
fi; \
|
||||||
|
}
|
||||||
|
|
||||||
|
# This rule has no dependencies: we don't need to update $(DOMAIN).pot at
|
||||||
|
# every "make" invocation, only create it when it is missing.
|
||||||
|
# Only "make $(DOMAIN).pot-update" or "make dist" will force an update.
|
||||||
|
$(srcdir)/$(DOMAIN).pot:
|
||||||
|
$(MAKE) $(DOMAIN).pot-update
|
||||||
|
|
||||||
|
# This target rebuilds a PO file if $(DOMAIN).pot has changed.
|
||||||
|
# Note that a PO file is not touched if it doesn't need to be changed.
|
||||||
|
$(POFILES): $(srcdir)/$(DOMAIN).pot
|
||||||
|
@lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \
|
||||||
|
if test -f "$(srcdir)/$${lang}.po"; then \
|
||||||
|
test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
|
||||||
|
echo "$${cdcmd}$(MSGMERGE_UPDATE) $${lang}.po $(DOMAIN).pot"; \
|
||||||
|
cd $(srcdir) && $(MSGMERGE_UPDATE) $${lang}.po $(DOMAIN).pot; \
|
||||||
|
else \
|
||||||
|
$(MAKE) $${lang}.po-create; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
install: install-exec install-data
|
||||||
|
install-exec:
|
||||||
|
install-data: install-data-@USE_NLS@
|
||||||
|
if test "$(PACKAGE)" = "gettext-tools"; then \
|
||||||
|
$(mkdir_p) $(DESTDIR)$(gettextsrcdir); \
|
||||||
|
for file in $(DISTFILES.common) Makevars.template; do \
|
||||||
|
$(INSTALL_DATA) $(srcdir)/$$file \
|
||||||
|
$(DESTDIR)$(gettextsrcdir)/$$file; \
|
||||||
|
done; \
|
||||||
|
for file in Makevars; do \
|
||||||
|
rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \
|
||||||
|
done; \
|
||||||
|
else \
|
||||||
|
: ; \
|
||||||
|
fi
|
||||||
|
install-data-no: all
|
||||||
|
install-data-yes: all
|
||||||
|
$(mkdir_p) $(DESTDIR)$(datadir)
|
||||||
|
@catalogs='$(CATALOGS)'; \
|
||||||
|
for cat in $$catalogs; do \
|
||||||
|
cat=`basename $$cat`; \
|
||||||
|
lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \
|
||||||
|
dir=$(localedir)/$$lang/LC_MESSAGES; \
|
||||||
|
$(mkdir_p) $(DESTDIR)$$dir; \
|
||||||
|
if test -r $$cat; then realcat=$$cat; else realcat=$(srcdir)/$$cat; fi; \
|
||||||
|
$(INSTALL_DATA) $$realcat $(DESTDIR)$$dir/$(DOMAIN).mo; \
|
||||||
|
echo "installing $$realcat as $(DESTDIR)$$dir/$(DOMAIN).mo"; \
|
||||||
|
for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \
|
||||||
|
if test -n "$$lc"; then \
|
||||||
|
if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \
|
||||||
|
link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \
|
||||||
|
mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \
|
||||||
|
mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \
|
||||||
|
(cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \
|
||||||
|
for file in *; do \
|
||||||
|
if test -f $$file; then \
|
||||||
|
ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \
|
||||||
|
fi; \
|
||||||
|
done); \
|
||||||
|
rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \
|
||||||
|
else \
|
||||||
|
if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \
|
||||||
|
:; \
|
||||||
|
else \
|
||||||
|
rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \
|
||||||
|
mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \
|
||||||
|
fi; \
|
||||||
|
fi; \
|
||||||
|
rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \
|
||||||
|
ln -s ../LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \
|
||||||
|
ln $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \
|
||||||
|
cp -p $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \
|
||||||
|
echo "installing $$realcat link as $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo"; \
|
||||||
|
fi; \
|
||||||
|
done; \
|
||||||
|
done
|
||||||
|
|
||||||
|
install-strip: install
|
||||||
|
|
||||||
|
installdirs: installdirs-exec installdirs-data
|
||||||
|
installdirs-exec:
|
||||||
|
installdirs-data: installdirs-data-@USE_NLS@
|
||||||
|
if test "$(PACKAGE)" = "gettext-tools"; then \
|
||||||
|
$(mkdir_p) $(DESTDIR)$(gettextsrcdir); \
|
||||||
|
else \
|
||||||
|
: ; \
|
||||||
|
fi
|
||||||
|
installdirs-data-no:
|
||||||
|
installdirs-data-yes:
|
||||||
|
$(mkdir_p) $(DESTDIR)$(datadir)
|
||||||
|
@catalogs='$(CATALOGS)'; \
|
||||||
|
for cat in $$catalogs; do \
|
||||||
|
cat=`basename $$cat`; \
|
||||||
|
lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \
|
||||||
|
dir=$(localedir)/$$lang/LC_MESSAGES; \
|
||||||
|
$(mkdir_p) $(DESTDIR)$$dir; \
|
||||||
|
for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \
|
||||||
|
if test -n "$$lc"; then \
|
||||||
|
if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \
|
||||||
|
link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \
|
||||||
|
mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \
|
||||||
|
mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \
|
||||||
|
(cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \
|
||||||
|
for file in *; do \
|
||||||
|
if test -f $$file; then \
|
||||||
|
ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \
|
||||||
|
fi; \
|
||||||
|
done); \
|
||||||
|
rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \
|
||||||
|
else \
|
||||||
|
if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \
|
||||||
|
:; \
|
||||||
|
else \
|
||||||
|
rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \
|
||||||
|
mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \
|
||||||
|
fi; \
|
||||||
|
fi; \
|
||||||
|
fi; \
|
||||||
|
done; \
|
||||||
|
done
|
||||||
|
|
||||||
|
# Define this as empty until I found a useful application.
|
||||||
|
installcheck:
|
||||||
|
|
||||||
|
uninstall: uninstall-exec uninstall-data
|
||||||
|
uninstall-exec:
|
||||||
|
uninstall-data: uninstall-data-@USE_NLS@
|
||||||
|
if test "$(PACKAGE)" = "gettext-tools"; then \
|
||||||
|
for file in $(DISTFILES.common) Makevars.template; do \
|
||||||
|
rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \
|
||||||
|
done; \
|
||||||
|
else \
|
||||||
|
: ; \
|
||||||
|
fi
|
||||||
|
uninstall-data-no:
|
||||||
|
uninstall-data-yes:
|
||||||
|
catalogs='$(CATALOGS)'; \
|
||||||
|
for cat in $$catalogs; do \
|
||||||
|
cat=`basename $$cat`; \
|
||||||
|
lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \
|
||||||
|
for lc in LC_MESSAGES $(EXTRA_LOCALE_CATEGORIES); do \
|
||||||
|
rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \
|
||||||
|
done; \
|
||||||
|
done
|
||||||
|
|
||||||
|
check: all
|
||||||
|
|
||||||
|
info dvi ps pdf html tags TAGS ctags CTAGS ID:
|
||||||
|
|
||||||
|
mostlyclean:
|
||||||
|
rm -f remove-potcdate.sed
|
||||||
|
rm -f stamp-poT
|
||||||
|
rm -f core core.* $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po
|
||||||
|
rm -fr *.o
|
||||||
|
|
||||||
|
clean: mostlyclean
|
||||||
|
|
||||||
|
distclean: clean
|
||||||
|
rm -f Makefile Makefile.in POTFILES *.mo
|
||||||
|
|
||||||
|
maintainer-clean: distclean
|
||||||
|
@echo "This command is intended for maintainers to use;"
|
||||||
|
@echo "it deletes files that may require special tools to rebuild."
|
||||||
|
rm -f stamp-po $(GMOFILES)
|
||||||
|
|
||||||
|
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
|
||||||
|
dist distdir:
|
||||||
|
$(MAKE) update-po
|
||||||
|
@$(MAKE) dist2
|
||||||
|
# This is a separate target because 'update-po' must be executed before.
|
||||||
|
dist2: stamp-po $(DISTFILES)
|
||||||
|
dists="$(DISTFILES)"; \
|
||||||
|
if test "$(PACKAGE)" = "gettext-tools"; then \
|
||||||
|
dists="$$dists Makevars.template"; \
|
||||||
|
fi; \
|
||||||
|
if test -f $(srcdir)/$(DOMAIN).pot; then \
|
||||||
|
dists="$$dists $(DOMAIN).pot stamp-po"; \
|
||||||
|
fi; \
|
||||||
|
if test -f $(srcdir)/ChangeLog; then \
|
||||||
|
dists="$$dists ChangeLog"; \
|
||||||
|
fi; \
|
||||||
|
for i in 0 1 2 3 4 5 6 7 8 9; do \
|
||||||
|
if test -f $(srcdir)/ChangeLog.$$i; then \
|
||||||
|
dists="$$dists ChangeLog.$$i"; \
|
||||||
|
fi; \
|
||||||
|
done; \
|
||||||
|
if test -f $(srcdir)/LINGUAS; then dists="$$dists LINGUAS"; fi; \
|
||||||
|
for file in $$dists; do \
|
||||||
|
if test -f $$file; then \
|
||||||
|
cp -p $$file $(distdir) || exit 1; \
|
||||||
|
else \
|
||||||
|
cp -p $(srcdir)/$$file $(distdir) || exit 1; \
|
||||||
|
fi; \
|
||||||
|
done
|
||||||
|
|
||||||
|
update-po: Makefile
|
||||||
|
$(MAKE) $(DOMAIN).pot-update
|
||||||
|
test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES)
|
||||||
|
$(MAKE) update-gmo
|
||||||
|
|
||||||
|
# General rule for creating PO files.
|
||||||
|
|
||||||
|
.nop.po-create:
|
||||||
|
@lang=`echo $@ | sed -e 's/\.po-create$$//'`; \
|
||||||
|
echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \
|
||||||
|
exit 1
|
||||||
|
|
||||||
|
# General rule for updating PO files.
|
||||||
|
|
||||||
|
.nop.po-update:
|
||||||
|
@lang=`echo $@ | sed -e 's/\.po-update$$//'`; \
|
||||||
|
if test "$(PACKAGE)" = "gettext-tools"; then PATH=`pwd`/../src:$$PATH; fi; \
|
||||||
|
tmpdir=`pwd`; \
|
||||||
|
echo "$$lang:"; \
|
||||||
|
test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
|
||||||
|
echo "$${cdcmd}$(MSGMERGE) $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \
|
||||||
|
cd $(srcdir); \
|
||||||
|
if $(MSGMERGE) $$lang.po $(DOMAIN).pot -o $$tmpdir/$$lang.new.po; then \
|
||||||
|
if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
|
||||||
|
rm -f $$tmpdir/$$lang.new.po; \
|
||||||
|
else \
|
||||||
|
if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
|
||||||
|
:; \
|
||||||
|
else \
|
||||||
|
echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
|
||||||
|
exit 1; \
|
||||||
|
fi; \
|
||||||
|
fi; \
|
||||||
|
else \
|
||||||
|
echo "msgmerge for $$lang.po failed!" 1>&2; \
|
||||||
|
rm -f $$tmpdir/$$lang.new.po; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
$(DUMMYPOFILES):
|
||||||
|
|
||||||
|
update-gmo: Makefile $(GMOFILES)
|
||||||
|
@:
|
||||||
|
|
||||||
|
# Recreate Makefile by invoking config.status. Explicitly invoke the shell,
|
||||||
|
# because execution permission bits may not work on the current file system.
|
||||||
|
# Use @SHELL@, which is the shell determined by autoconf for the use by its
|
||||||
|
# scripts, not $(SHELL) which is hardwired to /bin/sh and may be deficient.
|
||||||
|
Makefile: Makefile.in.in Makevars $(top_builddir)/config.status @POMAKEFILEDEPS@
|
||||||
|
cd $(top_builddir) \
|
||||||
|
&& @SHELL@ ./config.status $(subdir)/$@.in po-directories
|
||||||
|
|
||||||
|
force:
|
||||||
|
|
||||||
|
# Tell versions [3.59,3.63) of GNU make not to export all variables.
|
||||||
|
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||||
|
.NOEXPORT:
|
@ -0,0 +1,41 @@
|
|||||||
|
# Makefile variables for PO directory in any package using GNU gettext.
|
||||||
|
|
||||||
|
# Usually the message domain is the same as the package name.
|
||||||
|
DOMAIN = $(PACKAGE)
|
||||||
|
|
||||||
|
# These two variables depend on the location of this directory.
|
||||||
|
subdir = po
|
||||||
|
top_builddir = ..
|
||||||
|
|
||||||
|
# These options get passed to xgettext.
|
||||||
|
XGETTEXT_OPTIONS = --keyword=_ --keyword=N_
|
||||||
|
|
||||||
|
# This is the copyright holder that gets inserted into the header of the
|
||||||
|
# $(DOMAIN).pot file. Set this to the copyright holder of the surrounding
|
||||||
|
# package. (Note that the msgstr strings, extracted from the package's
|
||||||
|
# sources, belong to the copyright holder of the package.) Translators are
|
||||||
|
# expected to transfer the copyright for their translations to this person
|
||||||
|
# or entity, or to disclaim their copyright. The empty string stands for
|
||||||
|
# the public domain; in this case the translators are expected to disclaim
|
||||||
|
# their copyright.
|
||||||
|
COPYRIGHT_HOLDER = Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
# This is the email address or URL to which the translators shall report
|
||||||
|
# bugs in the untranslated strings:
|
||||||
|
# - Strings which are not entire sentences, see the maintainer guidelines
|
||||||
|
# in the GNU gettext documentation, section 'Preparing Strings'.
|
||||||
|
# - Strings which use unclear terms or require additional context to be
|
||||||
|
# understood.
|
||||||
|
# - Strings which make invalid assumptions about notation of date, time or
|
||||||
|
# money.
|
||||||
|
# - Pluralisation problems.
|
||||||
|
# - Incorrect English spelling.
|
||||||
|
# - Incorrect formatting.
|
||||||
|
# It can be your email address, or a mailing list address where translators
|
||||||
|
# can write to without being subscribed, or the URL of a web page through
|
||||||
|
# which the translators can contact you.
|
||||||
|
MSGID_BUGS_ADDRESS =
|
||||||
|
|
||||||
|
# This is the list of locale categories, beyond LC_MESSAGES, for which the
|
||||||
|
# message catalogs shall be used. It is usually empty.
|
||||||
|
EXTRA_LOCALE_CATEGORIES =
|
@ -0,0 +1 @@
|
|||||||
|
# List of source files which contain translatable strings.
|
@ -0,0 +1,47 @@
|
|||||||
|
# Special Makefile rules for English message catalogs with quotation marks.
|
||||||
|
|
||||||
|
DISTFILES.common.extra1 = quot.sed boldquot.sed en@quot.header en@boldquot.header insert-header.sin Rules-quot
|
||||||
|
|
||||||
|
.SUFFIXES: .insert-header .po-update-en
|
||||||
|
|
||||||
|
en@quot.po-create:
|
||||||
|
$(MAKE) en@quot.po-update
|
||||||
|
en@boldquot.po-create:
|
||||||
|
$(MAKE) en@boldquot.po-update
|
||||||
|
|
||||||
|
en@quot.po-update: en@quot.po-update-en
|
||||||
|
en@boldquot.po-update: en@boldquot.po-update-en
|
||||||
|
|
||||||
|
.insert-header.po-update-en:
|
||||||
|
@lang=`echo $@ | sed -e 's/\.po-update-en$$//'`; \
|
||||||
|
if test "$(PACKAGE)" = "gettext"; then PATH=`pwd`/../src:$$PATH; GETTEXTLIBDIR=`cd $(top_srcdir)/src && pwd`; export GETTEXTLIBDIR; fi; \
|
||||||
|
tmpdir=`pwd`; \
|
||||||
|
echo "$$lang:"; \
|
||||||
|
ll=`echo $$lang | sed -e 's/@.*//'`; \
|
||||||
|
LC_ALL=C; export LC_ALL; \
|
||||||
|
cd $(srcdir); \
|
||||||
|
if $(MSGINIT) -i $(DOMAIN).pot --no-translator -l $$ll -o - 2>/dev/null | sed -f $$tmpdir/$$lang.insert-header | $(MSGCONV) -t UTF-8 | $(MSGFILTER) sed -f `echo $$lang | sed -e 's/.*@//'`.sed 2>/dev/null > $$tmpdir/$$lang.new.po; then \
|
||||||
|
if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
|
||||||
|
rm -f $$tmpdir/$$lang.new.po; \
|
||||||
|
else \
|
||||||
|
if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
|
||||||
|
:; \
|
||||||
|
else \
|
||||||
|
echo "creation of $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
|
||||||
|
exit 1; \
|
||||||
|
fi; \
|
||||||
|
fi; \
|
||||||
|
else \
|
||||||
|
echo "creation of $$lang.po failed!" 1>&2; \
|
||||||
|
rm -f $$tmpdir/$$lang.new.po; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
en@quot.insert-header: insert-header.sin
|
||||||
|
sed -e '/^#/d' -e 's/HEADER/en@quot.header/g' $(srcdir)/insert-header.sin > en@quot.insert-header
|
||||||
|
|
||||||
|
en@boldquot.insert-header: insert-header.sin
|
||||||
|
sed -e '/^#/d' -e 's/HEADER/en@boldquot.header/g' $(srcdir)/insert-header.sin > en@boldquot.insert-header
|
||||||
|
|
||||||
|
mostlyclean: mostlyclean-quot
|
||||||
|
mostlyclean-quot:
|
||||||
|
rm -f *.insert-header
|
@ -0,0 +1,25 @@
|
|||||||
|
# All this catalog "translates" are quotation characters.
|
||||||
|
# The msgids must be ASCII and therefore cannot contain real quotation
|
||||||
|
# characters, only substitutes like grave accent (0x60), apostrophe (0x27)
|
||||||
|
# and double quote (0x22). These substitutes look strange; see
|
||||||
|
# http://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html
|
||||||
|
#
|
||||||
|
# This catalog translates grave accent (0x60) and apostrophe (0x27) to
|
||||||
|
# left single quotation mark (U+2018) and right single quotation mark (U+2019).
|
||||||
|
# It also translates pairs of apostrophe (0x27) to
|
||||||
|
# left single quotation mark (U+2018) and right single quotation mark (U+2019)
|
||||||
|
# and pairs of quotation mark (0x22) to
|
||||||
|
# left double quotation mark (U+201C) and right double quotation mark (U+201D).
|
||||||
|
#
|
||||||
|
# When output to an UTF-8 terminal, the quotation characters appear perfectly.
|
||||||
|
# When output to an ISO-8859-1 terminal, the single quotation marks are
|
||||||
|
# transliterated to apostrophes (by iconv in glibc 2.2 or newer) or to
|
||||||
|
# grave/acute accent (by libiconv), and the double quotation marks are
|
||||||
|
# transliterated to 0x22.
|
||||||
|
# When output to an ASCII terminal, the single quotation marks are
|
||||||
|
# transliterated to apostrophes, and the double quotation marks are
|
||||||
|
# transliterated to 0x22.
|
||||||
|
#
|
||||||
|
# This catalog furthermore displays the text between the quotation marks in
|
||||||
|
# bold face, assuming the VT100/XTerm escape sequences.
|
||||||
|
#
|
@ -0,0 +1,22 @@
|
|||||||
|
# All this catalog "translates" are quotation characters.
|
||||||
|
# The msgids must be ASCII and therefore cannot contain real quotation
|
||||||
|
# characters, only substitutes like grave accent (0x60), apostrophe (0x27)
|
||||||
|
# and double quote (0x22). These substitutes look strange; see
|
||||||
|
# http://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html
|
||||||
|
#
|
||||||
|
# This catalog translates grave accent (0x60) and apostrophe (0x27) to
|
||||||
|
# left single quotation mark (U+2018) and right single quotation mark (U+2019).
|
||||||
|
# It also translates pairs of apostrophe (0x27) to
|
||||||
|
# left single quotation mark (U+2018) and right single quotation mark (U+2019)
|
||||||
|
# and pairs of quotation mark (0x22) to
|
||||||
|
# left double quotation mark (U+201C) and right double quotation mark (U+201D).
|
||||||
|
#
|
||||||
|
# When output to an UTF-8 terminal, the quotation characters appear perfectly.
|
||||||
|
# When output to an ISO-8859-1 terminal, the single quotation marks are
|
||||||
|
# transliterated to apostrophes (by iconv in glibc 2.2 or newer) or to
|
||||||
|
# grave/acute accent (by libiconv), and the double quotation marks are
|
||||||
|
# transliterated to 0x22.
|
||||||
|
# When output to an ASCII terminal, the single quotation marks are
|
||||||
|
# transliterated to apostrophes, and the double quotation marks are
|
||||||
|
# transliterated to 0x22.
|
||||||
|
#
|
@ -0,0 +1,23 @@
|
|||||||
|
# Sed script that inserts the file called HEADER before the header entry.
|
||||||
|
#
|
||||||
|
# At each occurrence of a line starting with "msgid ", we execute the following
|
||||||
|
# commands. At the first occurrence, insert the file. At the following
|
||||||
|
# occurrences, do nothing. The distinction between the first and the following
|
||||||
|
# occurrences is achieved by looking at the hold space.
|
||||||
|
/^msgid /{
|
||||||
|
x
|
||||||
|
# Test if the hold space is empty.
|
||||||
|
s/m/m/
|
||||||
|
ta
|
||||||
|
# Yes it was empty. First occurrence. Read the file.
|
||||||
|
r HEADER
|
||||||
|
# Output the file's contents by reading the next line. But don't lose the
|
||||||
|
# current line while doing this.
|
||||||
|
g
|
||||||
|
N
|
||||||
|
bb
|
||||||
|
:a
|
||||||
|
# The hold space was nonempty. Following occurrences. Do nothing.
|
||||||
|
x
|
||||||
|
:b
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
# Sed script that remove the POT-Creation-Date line in the header entry
|
||||||
|
# from a POT file.
|
||||||
|
#
|
||||||
|
# The distinction between the first and the following occurrences of the
|
||||||
|
# pattern is achieved by looking at the hold space.
|
||||||
|
/^"POT-Creation-Date: .*"$/{
|
||||||
|
x
|
||||||
|
# Test if the hold space is empty.
|
||||||
|
s/P/P/
|
||||||
|
ta
|
||||||
|
# Yes it was empty. First occurrence. Remove the line.
|
||||||
|
g
|
||||||
|
d
|
||||||
|
bb
|
||||||
|
:a
|
||||||
|
# The hold space was nonempty. Following occurrences. Do nothing.
|
||||||
|
x
|
||||||
|
:b
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
libr_la_includedir = $(includedir)/libr
|
||||||
|
LIBTOOL_DEPS = @LIBTOOL_DEPS@
|
||||||
|
|
||||||
|
INCLUDES = \
|
||||||
|
-D__LIBR_BACKEND_@BACKEND_NAME@__ \
|
||||||
|
-D__LIBR_BUILD__ \
|
||||||
|
@LIBGLADE_CFLAGS@ \
|
||||||
|
@BACKEND_CFLAGS@ \
|
||||||
|
@EXTRA_CFLAGS@
|
||||||
|
|
||||||
|
lib_LTLIBRARIES = \
|
||||||
|
libr.la
|
||||||
|
|
||||||
|
libr_la_SOURCES = \
|
||||||
|
libr-@LIBR_BACKEND@.c \
|
||||||
|
tempfiles.c \
|
||||||
|
onecanvas.c \
|
||||||
|
libr-icons.c \
|
||||||
|
libr-i18n.c \
|
||||||
|
libr-gtk.c \
|
||||||
|
libr.c
|
||||||
|
|
||||||
|
libr_la_include_HEADERS = \
|
||||||
|
gettext.h \
|
||||||
|
libr-icons.h \
|
||||||
|
libr-i18n.h \
|
||||||
|
libr-gtk.h \
|
||||||
|
libr.h
|
||||||
|
|
||||||
|
libr_la_LIBADD = \
|
||||||
|
@BACKEND_LIBS@ \
|
||||||
|
@EXTRA_LIBS@
|
||||||
|
|
||||||
|
# If not in a fakeroot environment then run ldconfig
|
||||||
|
install: install-am
|
||||||
|
@if [ ! -n "${FAKEROOTKEY}" ]; then \
|
||||||
|
echo "Regenerating system dependencies..."; \
|
||||||
|
ldconfig; \
|
||||||
|
fi
|
@ -0,0 +1,94 @@
|
|||||||
|
/* config.h. Generated from config.h.in by configure. */
|
||||||
|
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||||
|
|
||||||
|
/* Define to 1 if translation of program messages to the user's native
|
||||||
|
language is requested. */
|
||||||
|
#define ENABLE_NLS 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the
|
||||||
|
CoreFoundation framework. */
|
||||||
|
/* #undef HAVE_CFLOCALECOPYCURRENT */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in
|
||||||
|
the CoreFoundation framework. */
|
||||||
|
/* #undef HAVE_CFPREFERENCESCOPYAPPVALUE */
|
||||||
|
|
||||||
|
/* Define if the GNU dcgettext() function is already present or preinstalled.
|
||||||
|
*/
|
||||||
|
#define HAVE_DCGETTEXT 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||||
|
#define HAVE_DLFCN_H 1
|
||||||
|
|
||||||
|
/* Define if the GNU gettext() function is already present or preinstalled. */
|
||||||
|
#define HAVE_GETTEXT 1
|
||||||
|
|
||||||
|
/* Define if you have the iconv() function and it works. */
|
||||||
|
/* #undef HAVE_ICONV */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||||
|
#define HAVE_INTTYPES_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <math.h> header file. */
|
||||||
|
#define HAVE_MATH_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <memory.h> header file. */
|
||||||
|
#define HAVE_MEMORY_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <pthread.h> header file. */
|
||||||
|
#define HAVE_PTHREAD_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <stdint.h> header file. */
|
||||||
|
#define HAVE_STDINT_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||||
|
#define HAVE_STDLIB_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <strings.h> header file. */
|
||||||
|
#define HAVE_STRINGS_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <string.h> header file. */
|
||||||
|
#define HAVE_STRING_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||||
|
#define HAVE_SYS_STAT_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||||
|
#define HAVE_SYS_TYPES_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <unistd.h> header file. */
|
||||||
|
#define HAVE_UNISTD_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <zlib.h> header file. */
|
||||||
|
#define HAVE_ZLIB_H 1
|
||||||
|
|
||||||
|
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
||||||
|
*/
|
||||||
|
#define LT_OBJDIR ".libs/"
|
||||||
|
|
||||||
|
/* Name of package */
|
||||||
|
#define PACKAGE "libr"
|
||||||
|
|
||||||
|
/* Define to the address where bug reports for this package should be sent. */
|
||||||
|
#define PACKAGE_BUGREPORT ""
|
||||||
|
|
||||||
|
/* Define to the full name of this package. */
|
||||||
|
#define PACKAGE_NAME ""
|
||||||
|
|
||||||
|
/* Define to the full name and version of this package. */
|
||||||
|
#define PACKAGE_STRING ""
|
||||||
|
|
||||||
|
/* Define to the one symbol short name of this package. */
|
||||||
|
#define PACKAGE_TARNAME ""
|
||||||
|
|
||||||
|
/* Define to the home page for this package. */
|
||||||
|
#define PACKAGE_URL ""
|
||||||
|
|
||||||
|
/* Define to the version of this package. */
|
||||||
|
#define PACKAGE_VERSION ""
|
||||||
|
|
||||||
|
/* Define to 1 if you have the ANSI C header files. */
|
||||||
|
#define STDC_HEADERS 1
|
||||||
|
|
||||||
|
/* Version number of package */
|
||||||
|
#define VERSION "0.4.0"
|
@ -0,0 +1,48 @@
|
|||||||
|
#ifndef __CVTENDIAN_H
|
||||||
|
#define __CVTENDIAN_H
|
||||||
|
|
||||||
|
/* Support for swapping bytes (endian conversion) */
|
||||||
|
#include <byteswap.h>
|
||||||
|
|
||||||
|
/* For obtaining the host endian type */
|
||||||
|
#include <endian.h>
|
||||||
|
#if (__BYTE_ORDER == __LITTLE_ENDIAN)
|
||||||
|
# define HOST_ENDIAN ELFDATA2LSB
|
||||||
|
#elif (__BYTE_ORDER == __BIG_ENDIAN)
|
||||||
|
# define HOST_ENDIAN ELFDATA2MSB
|
||||||
|
#else
|
||||||
|
# error "Failed to detect host endian type"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert the endian of a parameter
|
||||||
|
*/
|
||||||
|
static int ConvertEndian(void *ptr, int bytes)
|
||||||
|
{
|
||||||
|
switch(bytes)
|
||||||
|
{
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
uint16_t *value = (uint16_t *) ptr;
|
||||||
|
|
||||||
|
*value = bswap_16(*value);
|
||||||
|
} return 1;
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
uint32_t *value = (uint32_t *) ptr;
|
||||||
|
|
||||||
|
*value = bswap_32(*value);
|
||||||
|
} return 1;
|
||||||
|
case 8:
|
||||||
|
{
|
||||||
|
uint64_t *value = (uint64_t *) ptr;
|
||||||
|
|
||||||
|
*value = bswap_64(*value);
|
||||||
|
} return 1;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __CVTENDIAN_H */
|
@ -0,0 +1,271 @@
|
|||||||
|
/* Convenience header for conditional use of GNU <libintl.h>.
|
||||||
|
Copyright (C) 1995-1998, 2000-2002, 2004-2006 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
|
||||||
|
Library 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. */
|
||||||
|
|
||||||
|
#ifndef _LIBGETTEXT_H
|
||||||
|
#define _LIBGETTEXT_H 1
|
||||||
|
|
||||||
|
/* NLS can be disabled through the configure --disable-nls option. */
|
||||||
|
#if ENABLE_NLS
|
||||||
|
|
||||||
|
/* Get declarations of GNU message catalog functions. */
|
||||||
|
# include <libintl.h>
|
||||||
|
|
||||||
|
/* You can set the DEFAULT_TEXT_DOMAIN macro to specify the domain used by
|
||||||
|
the gettext() and ngettext() macros. This is an alternative to calling
|
||||||
|
textdomain(), and is useful for libraries. */
|
||||||
|
# ifdef DEFAULT_TEXT_DOMAIN
|
||||||
|
# undef gettext
|
||||||
|
# define gettext(Msgid) \
|
||||||
|
dgettext (DEFAULT_TEXT_DOMAIN, Msgid)
|
||||||
|
# undef ngettext
|
||||||
|
# define ngettext(Msgid1, Msgid2, N) \
|
||||||
|
dngettext (DEFAULT_TEXT_DOMAIN, Msgid1, Msgid2, N)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which
|
||||||
|
chokes if dcgettext is defined as a macro. So include it now, to make
|
||||||
|
later inclusions of <locale.h> a NOP. We don't include <libintl.h>
|
||||||
|
as well because people using "gettext.h" will not include <libintl.h>,
|
||||||
|
and also including <libintl.h> would fail on SunOS 4, whereas <locale.h>
|
||||||
|
is OK. */
|
||||||
|
#if defined(__sun)
|
||||||
|
# include <locale.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Many header files from the libstdc++ coming with g++ 3.3 or newer include
|
||||||
|
<libintl.h>, which chokes if dcgettext is defined as a macro. So include
|
||||||
|
it now, to make later inclusions of <libintl.h> a NOP. */
|
||||||
|
#if defined(__cplusplus) && defined(__GNUG__) && (__GNUC__ >= 3)
|
||||||
|
# include <cstdlib>
|
||||||
|
# if (__GLIBC__ >= 2) || _GLIBCXX_HAVE_LIBINTL_H
|
||||||
|
# include <libintl.h>
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Disabled NLS.
|
||||||
|
The casts to 'const char *' serve the purpose of producing warnings
|
||||||
|
for invalid uses of the value returned from these functions.
|
||||||
|
On pre-ANSI systems without 'const', the config.h file is supposed to
|
||||||
|
contain "#define const". */
|
||||||
|
# define gettext(Msgid) ((const char *) (Msgid))
|
||||||
|
# define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid))
|
||||||
|
# define dcgettext(Domainname, Msgid, Category) \
|
||||||
|
((void) (Category), dgettext (Domainname, Msgid))
|
||||||
|
# define ngettext(Msgid1, Msgid2, N) \
|
||||||
|
((N) == 1 \
|
||||||
|
? ((void) (Msgid2), (const char *) (Msgid1)) \
|
||||||
|
: ((void) (Msgid1), (const char *) (Msgid2)))
|
||||||
|
# define dngettext(Domainname, Msgid1, Msgid2, N) \
|
||||||
|
((void) (Domainname), ngettext (Msgid1, Msgid2, N))
|
||||||
|
# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
|
||||||
|
((void) (Category), dngettext(Domainname, Msgid1, Msgid2, N))
|
||||||
|
# define textdomain(Domainname) ((const char *) (Domainname))
|
||||||
|
# define bindtextdomain(Domainname, Dirname) \
|
||||||
|
((void) (Domainname), (const char *) (Dirname))
|
||||||
|
# define bind_textdomain_codeset(Domainname, Codeset) \
|
||||||
|
((void) (Domainname), (const char *) (Codeset))
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* A pseudo function call that serves as a marker for the automated
|
||||||
|
extraction of messages, but does not call gettext(). The run-time
|
||||||
|
translation is done at a different place in the code.
|
||||||
|
The argument, String, should be a literal string. Concatenated strings
|
||||||
|
and other string expressions won't work.
|
||||||
|
The macro's expansion is not parenthesized, so that it is suitable as
|
||||||
|
initializer for static 'char[]' or 'const char[]' variables. */
|
||||||
|
#define gettext_noop(String) String
|
||||||
|
|
||||||
|
/* The separator between msgctxt and msgid in a .mo file. */
|
||||||
|
#define GETTEXT_CONTEXT_GLUE "\004"
|
||||||
|
|
||||||
|
/* Pseudo function calls, taking a MSGCTXT and a MSGID instead of just a
|
||||||
|
MSGID. MSGCTXT and MSGID must be string literals. MSGCTXT should be
|
||||||
|
short and rarely need to change.
|
||||||
|
The letter 'p' stands for 'particular' or 'special'. */
|
||||||
|
#ifdef DEFAULT_TEXT_DOMAIN
|
||||||
|
# define pgettext(Msgctxt, Msgid) \
|
||||||
|
pgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
|
||||||
|
#else
|
||||||
|
# define pgettext(Msgctxt, Msgid) \
|
||||||
|
pgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
|
||||||
|
#endif
|
||||||
|
#define dpgettext(Domainname, Msgctxt, Msgid) \
|
||||||
|
pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
|
||||||
|
#define dcpgettext(Domainname, Msgctxt, Msgid, Category) \
|
||||||
|
pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, Category)
|
||||||
|
#ifdef DEFAULT_TEXT_DOMAIN
|
||||||
|
# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
|
||||||
|
npgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
|
||||||
|
#else
|
||||||
|
# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
|
||||||
|
npgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
|
||||||
|
#endif
|
||||||
|
#define dnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
|
||||||
|
npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
|
||||||
|
#define dcnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N, Category) \
|
||||||
|
npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, Category)
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
__inline
|
||||||
|
#else
|
||||||
|
#ifdef __cplusplus
|
||||||
|
inline
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
static const char *
|
||||||
|
pgettext_aux (const char *domain,
|
||||||
|
const char *msg_ctxt_id, const char *msgid,
|
||||||
|
int category)
|
||||||
|
{
|
||||||
|
const char *translation = dcgettext (domain, msg_ctxt_id, category);
|
||||||
|
if (translation == msg_ctxt_id)
|
||||||
|
return msgid;
|
||||||
|
else
|
||||||
|
return translation;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
__inline
|
||||||
|
#else
|
||||||
|
#ifdef __cplusplus
|
||||||
|
inline
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
static const char *
|
||||||
|
npgettext_aux (const char *domain,
|
||||||
|
const char *msg_ctxt_id, const char *msgid,
|
||||||
|
const char *msgid_plural, unsigned long int n,
|
||||||
|
int category)
|
||||||
|
{
|
||||||
|
const char *translation =
|
||||||
|
dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
|
||||||
|
if (translation == msg_ctxt_id || translation == msgid_plural)
|
||||||
|
return (n == 1 ? msgid : msgid_plural);
|
||||||
|
else
|
||||||
|
return translation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The same thing extended for non-constant arguments. Here MSGCTXT and MSGID
|
||||||
|
can be arbitrary expressions. But for string literals these macros are
|
||||||
|
less efficient than those above. */
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS \
|
||||||
|
(((__GNUC__ >= 3 || __GNUG__ >= 2) && !__STRICT_ANSI__) \
|
||||||
|
/* || __STDC_VERSION__ >= 199901L */ )
|
||||||
|
|
||||||
|
#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define pgettext_expr(Msgctxt, Msgid) \
|
||||||
|
dcpgettext_expr (NULL, Msgctxt, Msgid, LC_MESSAGES)
|
||||||
|
#define dpgettext_expr(Domainname, Msgctxt, Msgid) \
|
||||||
|
dcpgettext_expr (Domainname, Msgctxt, Msgid, LC_MESSAGES)
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
__inline
|
||||||
|
#else
|
||||||
|
#ifdef __cplusplus
|
||||||
|
inline
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
static const char *
|
||||||
|
dcpgettext_expr (const char *domain,
|
||||||
|
const char *msgctxt, const char *msgid,
|
||||||
|
int category)
|
||||||
|
{
|
||||||
|
size_t msgctxt_len = strlen (msgctxt) + 1;
|
||||||
|
size_t msgid_len = strlen (msgid) + 1;
|
||||||
|
const char *translation;
|
||||||
|
#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
|
||||||
|
char msg_ctxt_id[msgctxt_len + msgid_len];
|
||||||
|
#else
|
||||||
|
char buf[1024];
|
||||||
|
char *msg_ctxt_id =
|
||||||
|
(msgctxt_len + msgid_len <= sizeof (buf)
|
||||||
|
? buf
|
||||||
|
: (char *) malloc (msgctxt_len + msgid_len));
|
||||||
|
if (msg_ctxt_id != NULL)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1);
|
||||||
|
msg_ctxt_id[msgctxt_len - 1] = '\004';
|
||||||
|
memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len);
|
||||||
|
translation = dcgettext (domain, msg_ctxt_id, category);
|
||||||
|
#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
|
||||||
|
if (msg_ctxt_id != buf)
|
||||||
|
free (msg_ctxt_id);
|
||||||
|
#endif
|
||||||
|
if (translation != msg_ctxt_id)
|
||||||
|
return translation;
|
||||||
|
}
|
||||||
|
return msgid;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \
|
||||||
|
dcnpgettext_expr (NULL, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
|
||||||
|
#define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
|
||||||
|
dcnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
__inline
|
||||||
|
#else
|
||||||
|
#ifdef __cplusplus
|
||||||
|
inline
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
static const char *
|
||||||
|
dcnpgettext_expr (const char *domain,
|
||||||
|
const char *msgctxt, const char *msgid,
|
||||||
|
const char *msgid_plural, unsigned long int n,
|
||||||
|
int category)
|
||||||
|
{
|
||||||
|
size_t msgctxt_len = strlen (msgctxt) + 1;
|
||||||
|
size_t msgid_len = strlen (msgid) + 1;
|
||||||
|
const char *translation;
|
||||||
|
#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
|
||||||
|
char msg_ctxt_id[msgctxt_len + msgid_len];
|
||||||
|
#else
|
||||||
|
char buf[1024];
|
||||||
|
char *msg_ctxt_id =
|
||||||
|
(msgctxt_len + msgid_len <= sizeof (buf)
|
||||||
|
? buf
|
||||||
|
: (char *) malloc (msgctxt_len + msgid_len));
|
||||||
|
if (msg_ctxt_id != NULL)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1);
|
||||||
|
msg_ctxt_id[msgctxt_len - 1] = '\004';
|
||||||
|
memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len);
|
||||||
|
translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
|
||||||
|
#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
|
||||||
|
if (msg_ctxt_id != buf)
|
||||||
|
free (msg_ctxt_id);
|
||||||
|
#endif
|
||||||
|
if (!(translation == msg_ctxt_id || translation == msgid_plural))
|
||||||
|
return translation;
|
||||||
|
}
|
||||||
|
return (n == 1 ? msgid : msgid_plural);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _LIBGETTEXT_H */
|
@ -0,0 +1,22 @@
|
|||||||
|
#ifndef __LIBR_BACKENDS_H
|
||||||
|
#define __LIBR_BACKENDS_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* All of the backend functions are explicitly declared internal to prevent any custom backend
|
||||||
|
* from leaving out one of these critical functions.
|
||||||
|
*/
|
||||||
|
INTERNAL_FN libr_intstatus add_section(libr_file *file_handle, char *resource_name, libr_section **retscn);
|
||||||
|
INTERNAL_FN void *data_pointer(libr_section *scn, libr_data *data);
|
||||||
|
INTERNAL_FN size_t data_size(libr_section *scn, libr_data *data);
|
||||||
|
INTERNAL_FN libr_intstatus find_section(libr_file *file_handle, char *section, libr_section **retscn);
|
||||||
|
INTERNAL_FN libr_data *get_data(libr_file *file_handle, libr_section *scn);
|
||||||
|
INTERNAL_FN void initialize_backend(void);
|
||||||
|
INTERNAL_FN libr_data *new_data(libr_file *file_handle, libr_section *scn);
|
||||||
|
INTERNAL_FN libr_section *next_section(libr_file *file_handle, libr_section *scn);
|
||||||
|
INTERNAL_FN libr_intstatus remove_section(libr_file *file_handle, libr_section *scn);
|
||||||
|
INTERNAL_FN char *section_name(libr_file *file_handle, libr_section *scn);
|
||||||
|
INTERNAL_FN libr_intstatus set_data(libr_file *file_handle, libr_section *scn, libr_data *data, off_t offset, char *buffer, size_t size);
|
||||||
|
INTERNAL_FN libr_intstatus open_handles(libr_file *file_handle, char *filename, libr_access_t access);
|
||||||
|
INTERNAL_FN void write_output(libr_file *file_handle);
|
||||||
|
|
||||||
|
#endif /* __LIBR_BACKENDS_H */
|
@ -0,0 +1,533 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008-2011 Erich Hoover
|
||||||
|
*
|
||||||
|
* libr libbfd Backend - Add resources into ELF binaries using libbfd
|
||||||
|
*
|
||||||
|
* *** PLEASE READ THE README FILE FOR LICENSE DETAILS SPECIFIC TO THIS FILE ***
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* To provide feedback, report bugs, or otherwise contact me:
|
||||||
|
* ehoover at mines dot edu
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Include compile-time parameters */
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "libr.h"
|
||||||
|
#include "libr-internal.h"
|
||||||
|
|
||||||
|
/* File access */
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
/* Safe rename requires some errno() knowledge */
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Build the libr_file handle for processing with libbfd
|
||||||
|
*/
|
||||||
|
libr_intstatus open_handles(libr_file *file_handle, char *filename, libr_access_t access)
|
||||||
|
{
|
||||||
|
bfd *handle = NULL;
|
||||||
|
|
||||||
|
handle = bfd_openr(filename, "default");
|
||||||
|
if(!handle)
|
||||||
|
RETURN(LIBR_ERROR_OPENFAILED, "Failed to open input file");
|
||||||
|
if(!bfd_check_format(handle, bfd_object))
|
||||||
|
RETURN(LIBR_ERROR_WRONGFORMAT, "Invalid input file format: not a libbfd object");
|
||||||
|
if(bfd_get_flavour(handle) != bfd_target_elf_flavour)
|
||||||
|
RETURN(LIBR_ERROR_WRONGFORMAT, "Invalid input file format: not an ELF file");
|
||||||
|
bfd_set_error(bfd_error_no_error);
|
||||||
|
file_handle->filename = filename;
|
||||||
|
file_handle->bfd_read = handle;
|
||||||
|
file_handle->access = access;
|
||||||
|
if(access == LIBR_READ_WRITE)
|
||||||
|
{
|
||||||
|
struct stat file_stat;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
/* Check for write permission on the file */
|
||||||
|
fd = open(filename, O_WRONLY);
|
||||||
|
if(fd == ERROR)
|
||||||
|
RETURN(LIBR_ERROR_WRITEPERM, "No write permission for file");
|
||||||
|
close(fd);
|
||||||
|
/* Obtain the access mode of the input file */
|
||||||
|
if(stat(filename, &file_stat) == ERROR)
|
||||||
|
RETURN(LIBR_ERROR_NOSIZE, "Failed to obtain file size");
|
||||||
|
file_handle->filemode = file_stat.st_mode;
|
||||||
|
file_handle->fileowner = file_stat.st_uid;
|
||||||
|
file_handle->filegroup = file_stat.st_gid;
|
||||||
|
/* Open a temporary file with the same settings as the input file */
|
||||||
|
strcpy(file_handle->tempfile, LIBR_TEMPFILE);
|
||||||
|
file_handle->fd_handle = mkstemp(file_handle->tempfile);
|
||||||
|
handle = bfd_openw(file_handle->tempfile, bfd_get_target(file_handle->bfd_read));
|
||||||
|
if(!bfd_set_format(handle, bfd_get_format(file_handle->bfd_read)))
|
||||||
|
RETURN(LIBR_ERROR_SETFORMAT, "Failed to set output file format to input file format");
|
||||||
|
if(!bfd_set_arch_mach(handle, bfd_get_arch(file_handle->bfd_read), bfd_get_mach(file_handle->bfd_read)))
|
||||||
|
RETURN(LIBR_ERROR_SETARCH, "Failed to set output file architecture to input file architecture");
|
||||||
|
/* twice needed ? */
|
||||||
|
if(!bfd_set_format(handle, bfd_get_format(file_handle->bfd_read)))
|
||||||
|
RETURN(LIBR_ERROR_SETFORMAT, "Failed to set output file format to input file format");
|
||||||
|
file_handle->bfd_write = handle;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
file_handle->fd_handle = 0;
|
||||||
|
file_handle->bfd_write = NULL;
|
||||||
|
}
|
||||||
|
RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check to see if a symbol should be kept
|
||||||
|
*/
|
||||||
|
int keep_symbol(libr_section *sections, libr_section *chkscn)
|
||||||
|
{
|
||||||
|
libr_section *scn;
|
||||||
|
|
||||||
|
/* Check that the section is publicly exposed */
|
||||||
|
for(scn = sections; scn != NULL; scn = scn->next)
|
||||||
|
{
|
||||||
|
if(scn == chkscn)
|
||||||
|
{
|
||||||
|
/* if it is, and has size zero, then it was marked for deletion */
|
||||||
|
if(bfd_get_section_size(chkscn) == 0)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove the symbol corresponding to a deleted section
|
||||||
|
*/
|
||||||
|
void remove_sections(libr_section *sections, void *symtab_buffer, long *symtab_count)
|
||||||
|
{
|
||||||
|
asymbol **symtab = (asymbol **) symtab_buffer;
|
||||||
|
long i, cnt = *symtab_count;
|
||||||
|
|
||||||
|
for(i=0;i<cnt;i++)
|
||||||
|
{
|
||||||
|
libr_section *chkscn = NULL;
|
||||||
|
asymbol *symbol = symtab[i];
|
||||||
|
|
||||||
|
if(symbol != NULL)
|
||||||
|
chkscn = bfd_get_section(symbol);
|
||||||
|
if(chkscn != NULL && !keep_symbol(sections, chkscn))
|
||||||
|
{
|
||||||
|
/* remove the symbol from the table */
|
||||||
|
asymbol **tmp = (asymbol **) malloc(sizeof(asymbol *) * (cnt-(i+1)));
|
||||||
|
memcpy(&tmp[0], &symtab[i+1], sizeof(asymbol *) * (cnt-(i+1)));
|
||||||
|
memcpy(&symtab[i], &tmp[0], sizeof(asymbol *) * (cnt-(i+1)));
|
||||||
|
free(tmp);
|
||||||
|
cnt--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*symtab_count = cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
int setup_sections(bfd *ihandle, bfd *ohandle)
|
||||||
|
{
|
||||||
|
libr_section *iscn, *oscn;
|
||||||
|
bfd_vma vma;
|
||||||
|
|
||||||
|
for(iscn = ihandle->sections; iscn != NULL; iscn = iscn->next)
|
||||||
|
{
|
||||||
|
if(bfd_get_section_size(iscn) == 0)
|
||||||
|
{
|
||||||
|
continue; /* Section has been marked for deletion */
|
||||||
|
}
|
||||||
|
/* Use SEC_LINKER_CREATED to ask the libbfd backend to take care of configuring the section */
|
||||||
|
|
||||||
|
// Keep the ARM_ATTRIBUTES section type intact on armhf systems
|
||||||
|
// If this is not done, readelf -A will not print any architecture information for the modified library,
|
||||||
|
// and ldd will report that the library cannot be found
|
||||||
|
if (strcmp(iscn->name, ".ARM.attributes") == 0)
|
||||||
|
{
|
||||||
|
oscn = bfd_make_section_anyway_with_flags(ohandle, iscn->name, iscn->flags);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
oscn = bfd_make_section_anyway_with_flags(ohandle, iscn->name, iscn->flags | SEC_LINKER_CREATED);
|
||||||
|
}
|
||||||
|
if(oscn == NULL)
|
||||||
|
{
|
||||||
|
printf("failed to create out section: %s\n", bfd_errmsg(bfd_get_error()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(!bfd_set_section_size(ohandle, oscn, iscn->size))
|
||||||
|
{
|
||||||
|
printf("failed to set data size: %s\n", bfd_errmsg(bfd_get_error()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
vma = bfd_section_vma(ihandle, iscn);
|
||||||
|
if(!bfd_set_section_vma(ohandle, oscn, vma))
|
||||||
|
{
|
||||||
|
printf("failed to set virtual memory address: %s\n", bfd_errmsg(bfd_get_error()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
oscn->lma = iscn->lma;
|
||||||
|
if(!bfd_set_section_alignment(ohandle, oscn, bfd_section_alignment(ihandle, iscn)))
|
||||||
|
{
|
||||||
|
printf("failed to compute section alignment: %s\n", bfd_errmsg(bfd_get_error()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
oscn->entsize = iscn->entsize;
|
||||||
|
iscn->output_section = oscn;
|
||||||
|
iscn->output_offset = vma;
|
||||||
|
if(!bfd_copy_private_section_data(ihandle, iscn, ohandle, oscn))
|
||||||
|
{
|
||||||
|
printf("failed to compute section alignment: %s\n", bfd_errmsg(bfd_get_error()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Go through the rather complicated process of using libbfd to build the output file
|
||||||
|
*/
|
||||||
|
int build_output(libr_file *file_handle)
|
||||||
|
{
|
||||||
|
void *symtab_buffer = NULL, *reloc_buffer = NULL, *buffer = NULL;
|
||||||
|
bfd_size_type symtab_size, reloc_size, size;
|
||||||
|
bfd *ohandle = file_handle->bfd_write;
|
||||||
|
bfd *ihandle = file_handle->bfd_read;
|
||||||
|
long symtab_count, reloc_count;
|
||||||
|
libr_section *iscn, *oscn;
|
||||||
|
|
||||||
|
if(!bfd_set_start_address(ohandle, bfd_get_start_address(ihandle)))
|
||||||
|
{
|
||||||
|
printf("failed to set start address: %s\n", bfd_errmsg(bfd_get_error()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(!bfd_set_file_flags(ohandle, bfd_get_file_flags(ihandle)))
|
||||||
|
{
|
||||||
|
printf("failed to set file flags: %s\n", bfd_errmsg(bfd_get_error()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/* Setup the sections in the output file */
|
||||||
|
if(!setup_sections(ihandle, ohandle))
|
||||||
|
return false; /* error already printed */
|
||||||
|
if(!bfd_copy_private_header_data(ihandle, ohandle))
|
||||||
|
{
|
||||||
|
printf("failed to copy header: %s\n", bfd_errmsg(bfd_get_error()));
|
||||||
|
return false; /* failed to create section */
|
||||||
|
}
|
||||||
|
/* Get the old symbol table */
|
||||||
|
if((bfd_get_file_flags(ihandle) & HAS_SYMS) == 0)
|
||||||
|
{
|
||||||
|
printf("file has no symbol table: %s\n", bfd_errmsg(bfd_get_error()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
symtab_size = bfd_get_symtab_upper_bound(ihandle);
|
||||||
|
if((signed)symtab_size < 0)
|
||||||
|
{
|
||||||
|
printf("failed to get symbol table size: %s\n", bfd_errmsg(bfd_get_error()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
symtab_buffer = malloc(symtab_size);
|
||||||
|
symtab_count = bfd_canonicalize_symtab(ihandle, symtab_buffer);
|
||||||
|
if(symtab_count < 0)
|
||||||
|
{
|
||||||
|
printf("failed to get symbol table number of entries: %s\n", bfd_errmsg(bfd_get_error()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/* Tweak the symbol table to remove sections that no-longer exist */
|
||||||
|
remove_sections(ihandle->sections, symtab_buffer, &symtab_count);
|
||||||
|
bfd_set_symtab(ohandle, symtab_buffer, symtab_count);
|
||||||
|
/* Actually copy section data */
|
||||||
|
for(iscn = ihandle->sections; iscn != NULL; iscn = iscn->next)
|
||||||
|
{
|
||||||
|
size = bfd_get_section_size(iscn);
|
||||||
|
if(size == 0)
|
||||||
|
continue; /* Section has been marked for deletion */
|
||||||
|
oscn = iscn->output_section;
|
||||||
|
reloc_size = bfd_get_reloc_upper_bound(ihandle, iscn);
|
||||||
|
if(reloc_size == 0)
|
||||||
|
bfd_set_reloc(ohandle, oscn, NULL, 0);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reloc_buffer = malloc(reloc_size);
|
||||||
|
reloc_count = bfd_canonicalize_reloc(ihandle, iscn, reloc_buffer, symtab_buffer);
|
||||||
|
bfd_set_reloc(ohandle, oscn, reloc_buffer, reloc_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(bfd_get_section_flags(ihandle, iscn) & SEC_HAS_CONTENTS)
|
||||||
|
{
|
||||||
|
/* NOTE: if the section is just being copied then do that, otherwise grab
|
||||||
|
* the user data for the section (stored previously by set_data)
|
||||||
|
*/
|
||||||
|
if(iscn->userdata == NULL)
|
||||||
|
{
|
||||||
|
buffer = malloc(size);
|
||||||
|
if(!bfd_get_section_contents(ihandle, iscn, buffer, 0, size))
|
||||||
|
{
|
||||||
|
printf("failed to get section contents: %s\n", bfd_errmsg(bfd_get_error()));
|
||||||
|
free(buffer);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
buffer = iscn->userdata;
|
||||||
|
if(!bfd_set_section_contents(ohandle, oscn, buffer, 0, size))
|
||||||
|
{
|
||||||
|
printf("failed to set section contents: %s\n", bfd_errmsg(bfd_get_error()));
|
||||||
|
free(buffer);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
free(buffer);
|
||||||
|
if(!bfd_copy_private_section_data(ihandle, iscn, ohandle, oscn))
|
||||||
|
{
|
||||||
|
printf("failed to copy private section data: %s\n", bfd_errmsg(bfd_get_error()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!bfd_copy_private_bfd_data(ihandle, ohandle))
|
||||||
|
{
|
||||||
|
printf("failed to copy private data: %s\n", bfd_errmsg(bfd_get_error()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Perform a cross-device safe rename
|
||||||
|
*/
|
||||||
|
int safe_rename(const char *old, const char *new)
|
||||||
|
{
|
||||||
|
char buffer[1024];
|
||||||
|
FILE *in, *out;
|
||||||
|
int read;
|
||||||
|
|
||||||
|
in = fopen(old, "r");
|
||||||
|
if(!in)
|
||||||
|
return -1;
|
||||||
|
out = fopen(new, "w");
|
||||||
|
if(!out)
|
||||||
|
return -1;
|
||||||
|
while(!feof(in) && !ferror(in))
|
||||||
|
{
|
||||||
|
read = fread(buffer, 1, sizeof(buffer), in);
|
||||||
|
fwrite(buffer, read, 1, out);
|
||||||
|
}
|
||||||
|
fclose(in);
|
||||||
|
fclose(out);
|
||||||
|
if(ferror(in))
|
||||||
|
{
|
||||||
|
remove(new);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return remove(old);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write the output file using the libbfd method
|
||||||
|
*/
|
||||||
|
void write_output(libr_file *file_handle)
|
||||||
|
{
|
||||||
|
int write_ok = false;
|
||||||
|
|
||||||
|
if(file_handle->bfd_write != NULL)
|
||||||
|
{
|
||||||
|
write_ok = true;
|
||||||
|
if(!build_output(file_handle))
|
||||||
|
{
|
||||||
|
printf("failed to build output file.\n");
|
||||||
|
write_ok = false;
|
||||||
|
}
|
||||||
|
if(!bfd_close(file_handle->bfd_write))
|
||||||
|
{
|
||||||
|
printf("failed to close write handle.\n");
|
||||||
|
write_ok = false;
|
||||||
|
}
|
||||||
|
if(file_handle->fd_handle != 0 && close(file_handle->fd_handle))
|
||||||
|
{
|
||||||
|
write_ok = false;
|
||||||
|
printf("failed to close write file descriptor.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* The read handle must be closed last since it is used in the write process */
|
||||||
|
if(!bfd_close(file_handle->bfd_read))
|
||||||
|
printf("failed to close read handle.\n");
|
||||||
|
/* Copy the temporary output over the input */
|
||||||
|
if(write_ok)
|
||||||
|
{
|
||||||
|
if(rename(file_handle->tempfile, file_handle->filename) < 0)
|
||||||
|
{
|
||||||
|
if(errno != EXDEV || safe_rename(file_handle->tempfile, file_handle->filename) < 0)
|
||||||
|
printf("failed to rename output file: %m\n");
|
||||||
|
}
|
||||||
|
if(chmod(file_handle->filename, file_handle->filemode) < 0)
|
||||||
|
printf("failed to set file mode.\n");
|
||||||
|
if(chown(file_handle->filename, file_handle->fileowner, file_handle->filegroup) < 0)
|
||||||
|
printf("failed to set file ownership.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find a named section from the ELF file using libbfd
|
||||||
|
*/
|
||||||
|
libr_intstatus find_section(libr_file *file_handle, char *section_name, libr_section **retscn)
|
||||||
|
{
|
||||||
|
libr_section *scn;
|
||||||
|
|
||||||
|
for(scn = file_handle->bfd_read->sections; scn != NULL; scn = scn->next)
|
||||||
|
{
|
||||||
|
if(strcmp(scn->name, section_name) == 0)
|
||||||
|
{
|
||||||
|
*retscn = scn;
|
||||||
|
RETURN_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RETURN(LIBR_ERROR_NOSECTION, "ELF resource section not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Obtain the data from a section using libbfd
|
||||||
|
*/
|
||||||
|
libr_data *get_data(libr_file *file_handle, libr_section *scn)
|
||||||
|
{
|
||||||
|
libr_data *data = malloc(scn->size);
|
||||||
|
|
||||||
|
if(!bfd_get_section_contents(file_handle->bfd_read, scn, data, 0, scn->size))
|
||||||
|
{
|
||||||
|
free(data);
|
||||||
|
data = NULL;
|
||||||
|
}
|
||||||
|
scn->userdata = data;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create new data for a section using libbfd
|
||||||
|
*/
|
||||||
|
libr_data *new_data(libr_file *file_handle, libr_section *scn)
|
||||||
|
{
|
||||||
|
/* NOTE: expanding data is handled by set_data for libbfd */
|
||||||
|
if(scn->userdata != NULL)
|
||||||
|
return scn->userdata;
|
||||||
|
scn->size = 0;
|
||||||
|
scn->userdata = malloc(0);
|
||||||
|
return scn->userdata;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create new data for a section using libbfd (at least, do so memory-wise)
|
||||||
|
*/
|
||||||
|
libr_intstatus set_data(libr_file *file_handle, libr_section *scn, libr_data *data, off_t offset, char *buffer, size_t size)
|
||||||
|
{
|
||||||
|
char *intbuffer = NULL;
|
||||||
|
|
||||||
|
/* special case: clear buffer */
|
||||||
|
if(buffer == NULL)
|
||||||
|
{
|
||||||
|
scn->size = 0;
|
||||||
|
if(scn->userdata != NULL)
|
||||||
|
free(scn->userdata);
|
||||||
|
RETURN_OK;
|
||||||
|
}
|
||||||
|
/* normal case: add new data to the buffer */
|
||||||
|
scn->size = offset + size;
|
||||||
|
scn->userdata = realloc(data, scn->size);
|
||||||
|
if(scn->userdata == NULL)
|
||||||
|
RETURN(LIBR_ERROR_MEMALLOC, "Failed to allocate memory for data");
|
||||||
|
intbuffer = scn->userdata;
|
||||||
|
memcpy(&intbuffer[offset], buffer, size);
|
||||||
|
RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a new section using libbfd
|
||||||
|
*/
|
||||||
|
libr_intstatus add_section(libr_file *file_handle, char *resource_name, libr_section **retscn)
|
||||||
|
{
|
||||||
|
libr_section *scn = NULL;
|
||||||
|
|
||||||
|
scn = bfd_make_section(file_handle->bfd_read, resource_name);
|
||||||
|
if(scn == NULL)
|
||||||
|
RETURN(LIBR_ERROR_NEWSECTION, "Failed to create new section");
|
||||||
|
if(!bfd_set_section_flags(file_handle->bfd_read, scn, SEC_HAS_CONTENTS | SEC_DATA | SEC_IN_MEMORY))
|
||||||
|
RETURN(LIBR_ERROR_SETFLAGS, "Failed to set flags for section");
|
||||||
|
*retscn = scn;
|
||||||
|
RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove a section and eliminate it from the ELF string table using libbfd
|
||||||
|
*/
|
||||||
|
libr_intstatus remove_section(libr_file *file_handle, libr_section *scn)
|
||||||
|
{
|
||||||
|
scn->size = 0;
|
||||||
|
RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the pointer to the actual data in the section
|
||||||
|
*/
|
||||||
|
void *data_pointer(libr_section *scn, libr_data *data)
|
||||||
|
{
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the size of the data in the section
|
||||||
|
*/
|
||||||
|
size_t data_size(libr_section *scn, libr_data *data)
|
||||||
|
{
|
||||||
|
return scn->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the next section in the ELF file
|
||||||
|
*/
|
||||||
|
libr_section *next_section(libr_file *file_handle, libr_section *scn)
|
||||||
|
{
|
||||||
|
/* get the first section */
|
||||||
|
if(scn == NULL)
|
||||||
|
{
|
||||||
|
if(file_handle->bfd_read == NULL)
|
||||||
|
return NULL;
|
||||||
|
return file_handle->bfd_read->sections;
|
||||||
|
}
|
||||||
|
return scn->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the name of a section
|
||||||
|
*/
|
||||||
|
char *section_name(libr_file *file_handle, libr_section *scn)
|
||||||
|
{
|
||||||
|
return (char *) scn->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize libbfd
|
||||||
|
*/
|
||||||
|
void initialize_backend(void)
|
||||||
|
{
|
||||||
|
bfd_init();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,40 @@
|
|||||||
|
#ifndef __LIBR_BFD_H
|
||||||
|
#define __LIBR_BFD_H
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <bfd.h>
|
||||||
|
|
||||||
|
#if BFD_HOST_64BIT_LONG
|
||||||
|
#if defined(__i386)
|
||||||
|
#error "Using incorrect binutils header file for architecture."
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#if defined(__amd64)
|
||||||
|
#error "Using incorrect binutils header file for architecture."
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||||
|
|
||||||
|
typedef struct _libr_file {
|
||||||
|
int fd_handle;
|
||||||
|
bfd *bfd_read;
|
||||||
|
bfd *bfd_write;
|
||||||
|
char *filename;
|
||||||
|
mode_t filemode;
|
||||||
|
uid_t fileowner;
|
||||||
|
gid_t filegroup;
|
||||||
|
char tempfile[LIBR_TEMPFILE_LEN];
|
||||||
|
libr_access_t access;
|
||||||
|
} libr_file;
|
||||||
|
|
||||||
|
#endif /* DOXYGEN_SHOULD_SKIP_THIS */
|
||||||
|
|
||||||
|
/* for a clean internal API */
|
||||||
|
typedef asection libr_section;
|
||||||
|
typedef void libr_data;
|
||||||
|
|
||||||
|
#endif /* __LIBR_BFD_H */
|
@ -0,0 +1,412 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008 Erich Hoover
|
||||||
|
*
|
||||||
|
* libr libelf Backend - Add resources into ELF binaries using libelf
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* To provide feedback, report bugs, or otherwise contact me:
|
||||||
|
* ehoover at mines dot edu
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Include compile-time parameters */
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "libr.h"
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
//#define MANUAL_LAYOUT true
|
||||||
|
|
||||||
|
extern void libr_set_error(libr_intstatus error);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write the output file using libelf
|
||||||
|
*/
|
||||||
|
void write_output(libr_file *file_handle)
|
||||||
|
{
|
||||||
|
/* Update the ELF file on the disk */
|
||||||
|
if(elf_update(file_handle->elf_handle, ELF_C_NULL) < 0)
|
||||||
|
{
|
||||||
|
printf("elf_update() failed: %s.", elf_errmsg(-1));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(elf_update(file_handle->elf_handle, ELF_C_WRITE) < 0)
|
||||||
|
{
|
||||||
|
printf("elf_update() failed: %s.", elf_errmsg(-1));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* Close the handles */
|
||||||
|
elf_end(file_handle->elf_handle);
|
||||||
|
close(file_handle->fd_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the size of the file represented by the file descriptor
|
||||||
|
*/
|
||||||
|
off_t file_size(int fd)
|
||||||
|
{
|
||||||
|
struct stat file_stat;
|
||||||
|
|
||||||
|
if(fstat(fd, &file_stat) == ERROR)
|
||||||
|
return ERROR;
|
||||||
|
return file_stat.st_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Open the handles for working with the file using libelf
|
||||||
|
*/
|
||||||
|
libr_intstatus open_handles(libr_file *file_handle, char *filename, libr_access_t access)
|
||||||
|
{
|
||||||
|
const int elf_access[2] = {ELF_C_READ, ELF_C_RDWR};
|
||||||
|
const int fd_access[2] = {O_RDONLY, O_RDWR};
|
||||||
|
Elf *e = NULL;
|
||||||
|
int fd = 0;
|
||||||
|
|
||||||
|
if((fd = open(filename, fd_access[access], 0)) < 0)
|
||||||
|
RETURN(LIBR_ERROR_OPENFAILED, "Failed to open input file");
|
||||||
|
if((e = elf_begin(fd, elf_access[access], NULL)) == NULL)
|
||||||
|
RETURN(LIBR_ERROR_BEGINFAILED, "Failed to open ELF file: %s.", elf_errmsg(-1));
|
||||||
|
if(elf_kind(e) != ELF_K_ELF)
|
||||||
|
RETURN(LIBR_ERROR_WRONGFORMAT, "Invalid input file format");
|
||||||
|
|
||||||
|
file_handle->access = access;
|
||||||
|
file_handle->fd_handle = fd;
|
||||||
|
file_handle->elf_handle = e;
|
||||||
|
file_handle->file_size = file_size(fd);
|
||||||
|
file_handle->version = EV_CURRENT; /* This should probably match the rest of the file */
|
||||||
|
RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Expand a section
|
||||||
|
* (Only used when manually controlling ELF layout)
|
||||||
|
*/
|
||||||
|
#ifdef MANUAL_LAYOUT
|
||||||
|
libr_intstatus expand_section(Elf *e, Elf_Scn *scn, size_t size, int reset)
|
||||||
|
{
|
||||||
|
size_t offset = 0, delta = 0;
|
||||||
|
Elf_Scn *tmpscn = NULL;
|
||||||
|
GElf_Shdr shdr;
|
||||||
|
|
||||||
|
if(gelf_getshdr(scn, &shdr) != &shdr)
|
||||||
|
RETURN(LIBR_INTERROR_GETSHDR, "Failed to obtain ELF header: %s", elf_errmsg(-1));
|
||||||
|
if(reset)
|
||||||
|
{
|
||||||
|
delta = (size-shdr.sh_size);
|
||||||
|
shdr.sh_size = size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
delta = size;
|
||||||
|
shdr.sh_size += size;
|
||||||
|
}
|
||||||
|
offset = shdr.sh_offset;
|
||||||
|
if(gelf_update_shdr(scn, &shdr) < 0)
|
||||||
|
RETURN(LIBR_ERROR_UPDATE, "Failed to perform dynamic update: %s.", elf_errmsg(-1));
|
||||||
|
if(elf_update(e, ELF_C_NULL) < 0)
|
||||||
|
RETURN(LIBR_ERROR_UPDATE, "Failed to perform dynamic update: %s.", elf_errmsg(-1));
|
||||||
|
/* Update any section that follows this one data-wise */
|
||||||
|
/*
|
||||||
|
****** This does not work yet
|
||||||
|
while((tmpscn = elf_nextscn(e, tmpscn)) != NULL)
|
||||||
|
{
|
||||||
|
if(tmpscn == scn)
|
||||||
|
continue;
|
||||||
|
if(gelf_getshdr(tmpscn, &shdr) != &shdr)
|
||||||
|
return LIBR_INTERROR_GETSHDR;
|
||||||
|
if(offset < shdr.sh_offset)
|
||||||
|
{
|
||||||
|
if((name = elf_strptr(e, ehdr.e_shstrndx, shdr.sh_name)) == NULL)
|
||||||
|
RETURN(LIBR_ERROR_STRPTR, "Failed to obtain section string pointer: %s.", elf_errmsg(-1));
|
||||||
|
shdr.sh_offset += delta;
|
||||||
|
if(gelf_update_shdr(tmpscn, &shdr) < 0)
|
||||||
|
RETURN(LIBR_ERROR_UPDATE, "Failed to perform dynamic update: %s.", elf_errmsg(-1));
|
||||||
|
if(elf_update(e, ELF_C_NULL) < 0)
|
||||||
|
RETURN(LIBR_ERROR_UPDATE, "Failed to perform dynamic update: %s.", elf_errmsg(-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
return LIBR_OK;
|
||||||
|
}
|
||||||
|
#endif /* MANUAL_LAYOUT */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Obtain the data from a section using libelf
|
||||||
|
*/
|
||||||
|
libr_data *get_data(libr_file *file_handle, libr_section *scn)
|
||||||
|
{
|
||||||
|
return elf_getdata(scn, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create new data for a section using libelf
|
||||||
|
*/
|
||||||
|
libr_data *new_data(libr_file *file_handle, libr_section *scn)
|
||||||
|
{
|
||||||
|
return elf_newdata(scn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set data for a section using libelf (not written yet)
|
||||||
|
*/
|
||||||
|
libr_intstatus set_data(libr_file *file_handle, libr_section *scn, libr_data *data, off_t offset, char *buffer, size_t size)
|
||||||
|
{
|
||||||
|
data->d_align = 1;
|
||||||
|
data->d_off = offset;
|
||||||
|
data->d_buf = buffer;
|
||||||
|
data->d_type = ELF_T_BYTE;
|
||||||
|
data->d_size = size;
|
||||||
|
data->d_version = file_handle->version;
|
||||||
|
#ifdef MANUAL_LAYOUT
|
||||||
|
if(expand_section(file_handle->elf_handle, scn, data->d_size, true) != LIBR_OK)
|
||||||
|
RETURN(LIBR_ERROR_EXPANDSECTION, "Failed to expand section");
|
||||||
|
#else
|
||||||
|
if(elf_update(file_handle->elf_handle, ELF_C_NULL) < 0)
|
||||||
|
RETURN(LIBR_ERROR_UPDATE, "Failed to perform dynamic update: %s.", elf_errmsg(-1));
|
||||||
|
if(elf_update(file_handle->elf_handle, ELF_C_WRITE) < 0)
|
||||||
|
RETURN(LIBR_ERROR_UPDATE, "Failed to perform dynamic update: %s.", elf_errmsg(-1));
|
||||||
|
#endif /* MANUAL_LAYOUT */
|
||||||
|
RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find a named section from the ELF file using libelf
|
||||||
|
*/
|
||||||
|
libr_intstatus find_section(libr_file *file_handle, char *section, libr_section **retscn)
|
||||||
|
{
|
||||||
|
Elf *e = file_handle->elf_handle;
|
||||||
|
Elf_Scn *scn = NULL;
|
||||||
|
char *name = NULL;
|
||||||
|
GElf_Ehdr ehdr;
|
||||||
|
GElf_Shdr shdr;
|
||||||
|
uintmax_t si;
|
||||||
|
|
||||||
|
if(gelf_getehdr(e, &ehdr) == NULL)
|
||||||
|
RETURN(LIBR_ERROR_GETEHDR, "Failed to obtain ELF header: %s", elf_errmsg(-1));
|
||||||
|
while((scn = elf_nextscn(e, scn)) != NULL)
|
||||||
|
{
|
||||||
|
if(gelf_getshdr(scn, &shdr) != &shdr)
|
||||||
|
RETURN(LIBR_ERROR_GETSHDR, "Failed to obtain ELF section header: %s", elf_errmsg(-1));
|
||||||
|
if((name = elf_strptr(e, ehdr.e_shstrndx, shdr.sh_name)) == NULL)
|
||||||
|
RETURN(LIBR_ERROR_STRPTR, "Failed to obtain section string pointer: %s.", elf_errmsg(-1));
|
||||||
|
|
||||||
|
si = (uintmax_t) elf_ndxscn(scn);
|
||||||
|
/*
|
||||||
|
printf("%d: %s (%d %d)\n", (long) si, name, (long) shdr.sh_offset, (long) shdr.sh_size);
|
||||||
|
*/
|
||||||
|
if(strcmp(name, section) == 0)
|
||||||
|
{
|
||||||
|
*retscn = scn;
|
||||||
|
RETURN_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RETURN(LIBR_ERROR_NOSECTION, "ELF resource section not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add a new section and create a name for it in the ELF string table using libelf
|
||||||
|
*/
|
||||||
|
libr_intstatus add_section(libr_file *file_handle, char *section, Elf_Scn **retscn)
|
||||||
|
{
|
||||||
|
Elf_Scn *scn = NULL, *strscn = NULL;
|
||||||
|
Elf *e = file_handle->elf_handle;
|
||||||
|
#ifdef MANUAL_LAYOUT
|
||||||
|
size_t tblsize = 0;
|
||||||
|
#endif /* MANUAL_LAYOUT */
|
||||||
|
Elf_Data *data;
|
||||||
|
GElf_Ehdr ehdr;
|
||||||
|
GElf_Shdr shdr;
|
||||||
|
|
||||||
|
if(gelf_getehdr(e, &ehdr) == NULL)
|
||||||
|
RETURN(LIBR_ERROR_GETEHDR, "Failed to obtain ELF header: %s", elf_errmsg(-1));
|
||||||
|
/* TODO: Support creating a string table for objects that don't have one */
|
||||||
|
if(!ehdr.e_shstrndx)
|
||||||
|
RETURN(LIBR_ERROR_NOTABLE, "No ELF string table");
|
||||||
|
strscn = elf_getscn(e, ehdr.e_shstrndx);
|
||||||
|
if(strscn == NULL)
|
||||||
|
RETURN(LIBR_ERROR_TABLE, "Failed to open string table: %s.", elf_errmsg(-1));
|
||||||
|
data = elf_newdata(strscn);
|
||||||
|
if(data == NULL)
|
||||||
|
RETURN(LIBR_ERROR_NEWDATA, "Failed to create data for section");
|
||||||
|
data->d_align = 1;
|
||||||
|
|
||||||
|
#ifdef MANUAL_LAYOUT
|
||||||
|
{
|
||||||
|
GElf_Shdr strshdr;
|
||||||
|
|
||||||
|
if(gelf_getshdr(strscn, &strshdr) != &strshdr)
|
||||||
|
RETURN(LIBR_ERROR_GETSHDR, "Failed to obtain ELF section header: %s", elf_errmsg(-1));
|
||||||
|
data->d_off = strshdr.sh_size;
|
||||||
|
#endif /* MANUAL_LAYOUT */
|
||||||
|
|
||||||
|
data->d_size = (size_t) strlen(section)+1;
|
||||||
|
data->d_type = ELF_T_BYTE;
|
||||||
|
data->d_buf = section;
|
||||||
|
data->d_version = file_handle->version;
|
||||||
|
|
||||||
|
#ifdef MANUAL_LAYOUT
|
||||||
|
if(expand_section(e, strscn, data->d_size, false) != LIBR_OK)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/* Update the internal offset information */
|
||||||
|
if(elf_update(e, ELF_C_NULL) < 0)
|
||||||
|
RETURN(LIBR_ERROR_UPDATE, "Failed to perform dynamic update: %s.", elf_errmsg(-1));
|
||||||
|
#endif /* MANUAL_LAYOUT */
|
||||||
|
|
||||||
|
/* seek to the end of the section data */
|
||||||
|
if((scn = elf_newscn(e)) == NULL)
|
||||||
|
RETURN(LIBR_ERROR_NEWSECTION, "Failed to create new section");
|
||||||
|
if(gelf_getshdr(scn, &shdr) != &shdr)
|
||||||
|
RETURN(LIBR_ERROR_GETSHDR, "Failed to obtain ELF section header: %s", elf_errmsg(-1));
|
||||||
|
shdr.sh_addralign = 1;
|
||||||
|
#ifdef MANUAL_LAYOUT
|
||||||
|
shdr.sh_offset = file_handle->file_size;
|
||||||
|
#endif /* MANUAL_LAYOUT */
|
||||||
|
shdr.sh_size = 0;
|
||||||
|
shdr.sh_name = data->d_off;
|
||||||
|
shdr.sh_type = SHT_NOTE; /* TODO: Does "NOTE" type fit best? */
|
||||||
|
shdr.sh_flags = SHF_WRITE;
|
||||||
|
shdr.sh_entsize = 0;
|
||||||
|
if(gelf_update_shdr(scn, &shdr) < 0)
|
||||||
|
RETURN(LIBR_ERROR_UPDATE, "Failed to perform dynamic update: %s.", elf_errmsg(-1));
|
||||||
|
*retscn = scn;
|
||||||
|
RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove a section and eliminate it from the ELF string table using libelf
|
||||||
|
*/
|
||||||
|
libr_intstatus remove_section(libr_file *file_handle, libr_section *scn)
|
||||||
|
{
|
||||||
|
unsigned int table_size, str_size;
|
||||||
|
char *buffer = NULL, *tmp = NULL;
|
||||||
|
Elf *e = file_handle->elf_handle;
|
||||||
|
int remaining_size;
|
||||||
|
Elf_Scn *strscn;
|
||||||
|
Elf_Data *data;
|
||||||
|
GElf_Ehdr ehdr;
|
||||||
|
GElf_Shdr shdr;
|
||||||
|
|
||||||
|
if(gelf_getehdr(e, &ehdr) == NULL)
|
||||||
|
RETURN(LIBR_ERROR_GETEHDR, "Failed to obtain ELF header: %s", elf_errmsg(-1));
|
||||||
|
/* Grab the string table */
|
||||||
|
if(!ehdr.e_shstrndx)
|
||||||
|
RETURN(LIBR_ERROR_NOTABLE, "No ELF string table");
|
||||||
|
strscn = elf_getscn(e, ehdr.e_shstrndx);
|
||||||
|
if(strscn == NULL)
|
||||||
|
RETURN(LIBR_ERROR_TABLE, "Failed to open string table: %s.", elf_errmsg(-1));
|
||||||
|
if((data = elf_getdata(strscn, NULL)) == NULL)
|
||||||
|
RETURN(LIBR_ERROR_GETDATA, "Failed to obtain data of section");
|
||||||
|
/* Find where the section name is in the string table */
|
||||||
|
if(gelf_getshdr(scn, &shdr) != &shdr)
|
||||||
|
RETURN(LIBR_ERROR_GETSHDR, "Failed to obtain ELF section header: %s", elf_errmsg(-1));
|
||||||
|
table_size = data->d_size;
|
||||||
|
buffer = (char *) data->d_buf;
|
||||||
|
/* Excise the string from the table */
|
||||||
|
str_size = strlen(&buffer[shdr.sh_name])+1;
|
||||||
|
remaining_size = table_size-(shdr.sh_name+str_size);
|
||||||
|
if(remaining_size < 0)
|
||||||
|
RETURN(LIBR_ERROR_SIZEMISMATCH, "Section's data size does not make sense");
|
||||||
|
if(remaining_size > 0)
|
||||||
|
{
|
||||||
|
/* If there is data after our icon entry in the table then it must be moved before resizing
|
||||||
|
* NOTE: Using memcpy with overlapping addresses is not allowed, use temporary buffer.
|
||||||
|
*/
|
||||||
|
tmp = (char *) malloc(remaining_size);
|
||||||
|
memcpy(tmp, &buffer[shdr.sh_name+str_size], remaining_size);
|
||||||
|
memcpy(&buffer[shdr.sh_name], tmp, remaining_size);
|
||||||
|
free(tmp);
|
||||||
|
}
|
||||||
|
data->d_size -= str_size;
|
||||||
|
/* Update the internal offset information */
|
||||||
|
if(elf_update(e, ELF_C_NULL) < 0)
|
||||||
|
RETURN(LIBR_ERROR_UPDATE, "Failed to perform dynamic update: %s.", elf_errmsg(-1));
|
||||||
|
#ifdef MANUAL_LAYOUT
|
||||||
|
{
|
||||||
|
GElf_Shdr strshdr;
|
||||||
|
|
||||||
|
if(gelf_getshdr(strscn, &strshdr) != &strshdr)
|
||||||
|
RETURN(LIBR_ERROR_GETSHDR, "Failed to obtain ELF section header: %s", elf_errmsg(-1));
|
||||||
|
strshdr.sh_size -= str_size;
|
||||||
|
if(gelf_update_shdr(strscn, &strshdr) < 0)
|
||||||
|
RETURN(LIBR_ERROR_UPDATE, "Failed to perform dynamic update: %s.", elf_errmsg(-1));
|
||||||
|
}
|
||||||
|
#endif /* MANUAL_LAYOUT */
|
||||||
|
|
||||||
|
/* Clear the section itself and update the offsets */
|
||||||
|
if(elfx_remscn(e, scn) == 0)
|
||||||
|
RETURN(LIBR_ERROR_REMOVESECTION, "Failed to remove section: %s.", elf_errmsg(-1));
|
||||||
|
RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the pointer to the actual data in the section
|
||||||
|
*/
|
||||||
|
void *data_pointer(libr_section *scn, libr_data *data)
|
||||||
|
{
|
||||||
|
return data->d_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the size of the data in the section
|
||||||
|
*/
|
||||||
|
size_t data_size(libr_section *scn, libr_data *data)
|
||||||
|
{
|
||||||
|
return data->d_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the next section in the ELF file
|
||||||
|
*/
|
||||||
|
libr_section *next_section(libr_file *file_handle, libr_section *scn)
|
||||||
|
{
|
||||||
|
return elf_nextscn(file_handle->elf_handle, scn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Retrieve the name of a section
|
||||||
|
*/
|
||||||
|
char *section_name(libr_file *file_handle, libr_section *scn)
|
||||||
|
{
|
||||||
|
char *name = NULL;
|
||||||
|
GElf_Shdr shdr;
|
||||||
|
GElf_Ehdr ehdr;
|
||||||
|
|
||||||
|
if(gelf_getehdr(file_handle->elf_handle, &ehdr) == NULL)
|
||||||
|
return NULL;
|
||||||
|
if(gelf_getshdr(scn, &shdr) != &shdr)
|
||||||
|
return NULL;
|
||||||
|
if((name = elf_strptr(file_handle->elf_handle, ehdr.e_shstrndx, shdr.sh_name)) == NULL)
|
||||||
|
return NULL;
|
||||||
|
return strdup(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize the libelf backend
|
||||||
|
*/
|
||||||
|
void initialize_backend(void)
|
||||||
|
{
|
||||||
|
if(elf_version(EV_CURRENT) == EV_NONE)
|
||||||
|
return; //errx(EX_SOFTWARE, "ELF library initialization failed: %s", elf_errmsg(-1));
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
#ifndef __LIBR_ELF_H
|
||||||
|
#define __LIBR_ELF_H
|
||||||
|
|
||||||
|
/* Handle ELF files */
|
||||||
|
#include <libelf.h>
|
||||||
|
#include <gelf.h>
|
||||||
|
|
||||||
|
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||||
|
|
||||||
|
typedef struct _libr_file {
|
||||||
|
int fd_handle;
|
||||||
|
Elf *elf_handle;
|
||||||
|
size_t file_size;
|
||||||
|
libr_access_t access;
|
||||||
|
unsigned int version;
|
||||||
|
} libr_file;
|
||||||
|
|
||||||
|
#endif /* DOXYGEN_SHOULD_SKIP_THIS */
|
||||||
|
|
||||||
|
/* for a clean internal API */
|
||||||
|
typedef Elf_Scn libr_section;
|
||||||
|
typedef Elf_Data libr_data;
|
||||||
|
|
||||||
|
#endif /* __LIBR_ELF_H */
|
@ -0,0 +1,443 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008-2009 Erich Hoover
|
||||||
|
*
|
||||||
|
* libr GTK support - Convenience functions for using resources in GTK applications
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* To provide feedback, report bugs, or otherwise contact me:
|
||||||
|
* ehoover at mines dot edu
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Include compile-time parameters */
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "libr.h"
|
||||||
|
#include "libr-gtk.h"
|
||||||
|
#include "libr-icons.h"
|
||||||
|
#include "tempfiles.h"
|
||||||
|
|
||||||
|
/* For loading GTK/GDK images */
|
||||||
|
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
/* For loading GLADE files */
|
||||||
|
#include <glade/glade.h>
|
||||||
|
|
||||||
|
/* For loading GTK+ Builder files */
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
/* For malloc/free */
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* For string handling */
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
typedef gchar * (*GladeFileCallback)(GladeXML *, const gchar *, guint *);
|
||||||
|
GladeFileCallback glade_set_file_callback(GladeFileCallback callback, gpointer user_data);
|
||||||
|
|
||||||
|
/* Use weak binding for all glade and GTK+ requirements */
|
||||||
|
#pragma weak glade_set_file_callback
|
||||||
|
|
||||||
|
#pragma weak gtk_window_set_default_icon_list
|
||||||
|
#pragma weak gdk_pixbuf_loader_get_pixbuf
|
||||||
|
#pragma weak gtk_builder_add_from_string
|
||||||
|
#pragma weak gdk_pixbuf_loader_set_size
|
||||||
|
#pragma weak g_type_check_instance_cast
|
||||||
|
#pragma weak gtk_builder_add_from_file
|
||||||
|
#pragma weak glade_xml_new_from_buffer
|
||||||
|
#pragma weak gdk_pixbuf_loader_write
|
||||||
|
#pragma weak gdk_pixbuf_loader_close
|
||||||
|
#pragma weak gdk_pixbuf_loader_new
|
||||||
|
#pragma weak g_signal_connect_data
|
||||||
|
#pragma weak g_signal_connect
|
||||||
|
#pragma weak gtk_builder_new
|
||||||
|
#pragma weak g_object_unref
|
||||||
|
#pragma weak glade_xml_new
|
||||||
|
#pragma weak g_list_append
|
||||||
|
#pragma weak glade_init
|
||||||
|
#pragma weak gtk_init
|
||||||
|
#pragma weak g_free
|
||||||
|
|
||||||
|
#define GLADE_SECTION ".glade"
|
||||||
|
#define BUILDER_SECTION ".ui"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle the resource request from libglade
|
||||||
|
*/
|
||||||
|
gchar *libr_glade_read_resource(GladeXML *gladefile, const gchar *filename, guint *size, gpointer user_data)
|
||||||
|
{
|
||||||
|
return libr_malloc((libr_file *) user_data, (char *) filename, (size_t *) size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle the resource request from GtkBuilder
|
||||||
|
*/
|
||||||
|
gboolean libr_gtk_read_resource(GtkBuilder *builder, const gchar *filename, gchar **data, gsize *size, GError **error, gpointer user_data)
|
||||||
|
{
|
||||||
|
if(data == NULL)
|
||||||
|
return FALSE;
|
||||||
|
*data = libr_malloc((libr_file *) user_data, (char *) filename, (size_t *) size);
|
||||||
|
if(*data == NULL)
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Load the libglade resource appropriately for the currently installed version
|
||||||
|
* (AKA, hurray hacks!)
|
||||||
|
*/
|
||||||
|
GladeXML *libr_new_glade(libr_file *handle, char *gladefile, size_t gladefile_size)
|
||||||
|
{
|
||||||
|
if(glade_set_file_callback) /* The not-yet (ever?) existing way */
|
||||||
|
{
|
||||||
|
/* Register a callback for libglade to load our resources */
|
||||||
|
if(glade_set_file_callback((GladeFileCallback) libr_glade_read_resource, handle) != NULL)
|
||||||
|
printf("warning: over-wrote an application callback!\n");
|
||||||
|
/* Initialize libglade almost as usual, just use a buffer instead of a file */
|
||||||
|
return glade_xml_new_from_buffer(gladefile, gladefile_size, NULL, NULL);
|
||||||
|
}
|
||||||
|
else /* The hacky way */
|
||||||
|
{
|
||||||
|
char *glade_file[PATH_MAX];
|
||||||
|
GladeXML *ret = NULL;
|
||||||
|
char *temp_folder;
|
||||||
|
|
||||||
|
temp_folder = libr_extract_resources(handle);
|
||||||
|
if(temp_folder == NULL)
|
||||||
|
return NULL;
|
||||||
|
strcpy((char*)glade_file, temp_folder);
|
||||||
|
strcat((char*)glade_file, "/");
|
||||||
|
strcat((char*)glade_file, GLADE_SECTION);
|
||||||
|
ret = glade_xml_new((char*)glade_file, NULL, NULL);
|
||||||
|
if(ret == NULL)
|
||||||
|
cleanup_folder(temp_folder);
|
||||||
|
else
|
||||||
|
register_folder_cleanup(temp_folder);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Load the GtkBuilder resource appropriately for the currently installed version
|
||||||
|
* (AKA, hurray hacks!)
|
||||||
|
*/
|
||||||
|
int libr_new_builder(libr_file *handle, char *builderfile, size_t builderfile_size, GtkBuilder *builder)
|
||||||
|
{
|
||||||
|
/* Register a callback for GtkBuilder to load our resources */
|
||||||
|
if(g_signal_connect(builder, "load-resource", (GCallback) libr_gtk_read_resource, handle))
|
||||||
|
{
|
||||||
|
/* Initialize GtkBuilder almost as usual, just use a buffer instead of a file */
|
||||||
|
if(gtk_builder_add_from_string(builder, builderfile, builderfile_size, NULL) == 0)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else /* The hacky way */
|
||||||
|
{
|
||||||
|
char *builder_file[PATH_MAX];
|
||||||
|
char *temp_folder;
|
||||||
|
int ret = false;
|
||||||
|
|
||||||
|
temp_folder = libr_extract_resources(handle);
|
||||||
|
if(temp_folder == NULL)
|
||||||
|
return false;
|
||||||
|
strcpy((char*)builder_file, temp_folder);
|
||||||
|
strcat((char*)builder_file, "/");
|
||||||
|
strcat((char*)builder_file, BUILDER_SECTION);
|
||||||
|
ret = gtk_builder_add_from_file(builder, (char*)builder_file, NULL);
|
||||||
|
if(ret == 0)
|
||||||
|
cleanup_folder(temp_folder);
|
||||||
|
else
|
||||||
|
register_folder_cleanup(temp_folder);
|
||||||
|
g_free(temp_folder);
|
||||||
|
return (ret != 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return a GTK icon list
|
||||||
|
*/
|
||||||
|
EXPORT_FN IconList *libr_gtk_iconlist(libr_file *handle)
|
||||||
|
{
|
||||||
|
int sizes[] = {16, 32, 48, 96, 128};
|
||||||
|
IconList *icons = NULL;
|
||||||
|
GdkPixbuf *icon = NULL;
|
||||||
|
int sizes_len = 5, i;
|
||||||
|
|
||||||
|
if(handle == NULL)
|
||||||
|
{
|
||||||
|
/* Must pass a file handle to obtain the icons from */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if(gtk_init == NULL)
|
||||||
|
{
|
||||||
|
/* GTK+ was not linked with the application */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/* Go through the list of GTK "required" image sizes and build the icons */
|
||||||
|
for(i=0;i<sizes_len;i++)
|
||||||
|
{
|
||||||
|
libr_icon *icon_handle = libr_icon_geticon_bysize(handle, sizes[i]);
|
||||||
|
GdkPixbufLoader *stream = gdk_pixbuf_loader_new();
|
||||||
|
char *iconfile = NULL;
|
||||||
|
size_t iconfile_size;
|
||||||
|
|
||||||
|
if(icon_handle == NULL)
|
||||||
|
{
|
||||||
|
/* Failed to find an icon */
|
||||||
|
printf("Failed to find an icon\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
iconfile = libr_icon_malloc(icon_handle, &iconfile_size);
|
||||||
|
if(iconfile == NULL)
|
||||||
|
{
|
||||||
|
/* Failed to obtain embedded icon */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
libr_icon_close(icon_handle);
|
||||||
|
/* TODO: Use the "size-prepared" signal to properly scale the width and height
|
||||||
|
void user_function (GdkPixbufLoader *loader, gint width, gint height, gpointer user_data)
|
||||||
|
*/
|
||||||
|
gdk_pixbuf_loader_set_size(stream, sizes[i], sizes[i]);
|
||||||
|
if(!gdk_pixbuf_loader_write(stream, (unsigned char *)iconfile, iconfile_size, NULL))
|
||||||
|
{
|
||||||
|
/* Failed to process image */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(!gdk_pixbuf_loader_close(stream, NULL))
|
||||||
|
{
|
||||||
|
/* Failed to create image */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
icon = gdk_pixbuf_loader_get_pixbuf(stream);
|
||||||
|
if(icon == NULL)
|
||||||
|
{
|
||||||
|
/* Failed to convert image to pixbuf */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
icons = g_list_append(icons, icon);
|
||||||
|
}
|
||||||
|
return icons;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Shared GtkBuilder resource loading
|
||||||
|
*/
|
||||||
|
GtkBuilder *libr_gtk_load_internal(libr_file *handle, char *resource_name)
|
||||||
|
{
|
||||||
|
GtkBuilder *builder = NULL;
|
||||||
|
size_t builder_length;
|
||||||
|
char *builder_data;
|
||||||
|
|
||||||
|
/* Obtain the GtkBuilder XML definition */
|
||||||
|
builder_data = libr_malloc(handle, resource_name, &builder_length);
|
||||||
|
if(builder_data == NULL)
|
||||||
|
{
|
||||||
|
/* Failed to obtain embedded GtkBuilder definition file */
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
/* Setup the GtkBuilder environment */
|
||||||
|
builder = gtk_builder_new();
|
||||||
|
if(builder == NULL)
|
||||||
|
goto failed;
|
||||||
|
if(!libr_new_builder(handle, builder_data, builder_length, builder))
|
||||||
|
{
|
||||||
|
/* Failed to build interface from resource file */
|
||||||
|
g_object_unref(G_OBJECT(builder));
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
failed:
|
||||||
|
free(builder_data);
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Load the requested GtkBuilder resource and any applicable icons
|
||||||
|
*/
|
||||||
|
EXPORT_FN int libr_gtk_load(BuilderHandle **gtk_ret, char *resource_name)
|
||||||
|
{
|
||||||
|
libr_file *handle;
|
||||||
|
int ret = false;
|
||||||
|
|
||||||
|
if(gtk_ret == NULL)
|
||||||
|
{
|
||||||
|
/* Why on earth would you call this without obtaining the handle to the resource? */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(gtk_builder_new == NULL)
|
||||||
|
{
|
||||||
|
/* GtkBuilder was not linked with the application */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/* Obtain the handle to the executable */
|
||||||
|
if((handle = libr_open(NULL, LIBR_READ)) == NULL)
|
||||||
|
{
|
||||||
|
/* "Failed to open this executable (%s) for resources", progname() */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
register_internal_handle(handle);
|
||||||
|
*gtk_ret = libr_gtk_load_internal(handle, resource_name);
|
||||||
|
if(*gtk_ret == NULL)
|
||||||
|
goto failed;
|
||||||
|
ret = true;
|
||||||
|
failed:
|
||||||
|
if(!ret)
|
||||||
|
libr_close(handle);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Automatically load the ".ui" GtkBuilder resource and any applicable icons
|
||||||
|
*/
|
||||||
|
EXPORT_FN int libr_gtk_autoload(BuilderHandle **gtk_ret, IconList **icons_ret, int set_default_icon)
|
||||||
|
{
|
||||||
|
GList *icons = NULL;
|
||||||
|
libr_file *handle;
|
||||||
|
int ret = false;
|
||||||
|
|
||||||
|
if(gtk_ret == NULL)
|
||||||
|
{
|
||||||
|
/* Why on earth would you call this without obtaining the handle to the resource? */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(gtk_builder_new == NULL)
|
||||||
|
{
|
||||||
|
/* GtkBuilder was not linked with the application */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/* Obtain the handle to the executable */
|
||||||
|
if((handle = libr_open(NULL, LIBR_READ)) == NULL)
|
||||||
|
{
|
||||||
|
/* "Failed to open this executable (%s) for resources", progname() */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
register_internal_handle(handle);
|
||||||
|
/* Obtain the icons from the ELF binary */
|
||||||
|
icons = libr_gtk_iconlist(handle);
|
||||||
|
/* Set the embedded icons as the default icon list (if requested) */
|
||||||
|
if(icons != NULL && set_default_icon)
|
||||||
|
gtk_window_set_default_icon_list(icons);
|
||||||
|
*gtk_ret = libr_gtk_load_internal(handle, BUILDER_SECTION);
|
||||||
|
if(*gtk_ret == NULL)
|
||||||
|
goto failed;
|
||||||
|
if(icons_ret)
|
||||||
|
*icons_ret = icons;
|
||||||
|
ret = true;
|
||||||
|
failed:
|
||||||
|
if(!ret)
|
||||||
|
libr_close(handle);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Shared libglade resource loading
|
||||||
|
*/
|
||||||
|
GladeXML *libr_glade_load_internal(libr_file *handle, char *resource_name)
|
||||||
|
{
|
||||||
|
GladeXML *glade = NULL;
|
||||||
|
size_t glade_length;
|
||||||
|
char *glade_data;
|
||||||
|
|
||||||
|
/* Obtain the GLADE XML definition */
|
||||||
|
glade_data = libr_malloc(handle, resource_name, &glade_length);
|
||||||
|
if(glade_data == NULL)
|
||||||
|
{
|
||||||
|
/* Failed to obtain embedded glade file */
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
/* Initialize libglade appropriate for the available version */
|
||||||
|
glade = libr_new_glade(handle, glade_data, glade_length);
|
||||||
|
if(glade == NULL)
|
||||||
|
{
|
||||||
|
/* Failed to initialize embedded glade file */
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
failed:
|
||||||
|
free(glade_data);
|
||||||
|
return glade;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Load the requested libglade resource and any applicable icons
|
||||||
|
*/
|
||||||
|
EXPORT_FN int libr_glade_load(GladeHandle **glade_ret, char *resource_name)
|
||||||
|
{
|
||||||
|
libr_file *handle;
|
||||||
|
int ret = false;
|
||||||
|
|
||||||
|
if(glade_ret == NULL)
|
||||||
|
{
|
||||||
|
/* Why on earth would you call this without obtaining the handle to the resource? */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(glade_init == NULL)
|
||||||
|
{
|
||||||
|
/* libglade was not linked with the application */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/* Obtain the handle to the executable */
|
||||||
|
if((handle = libr_open(NULL, LIBR_READ)) == NULL)
|
||||||
|
{
|
||||||
|
/* "Failed to open this executable (%s) for resources", progname() */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
register_internal_handle(handle);
|
||||||
|
*glade_ret = libr_glade_load_internal(handle, resource_name);
|
||||||
|
if(*glade_ret == NULL)
|
||||||
|
goto failed;
|
||||||
|
ret = true;
|
||||||
|
failed:
|
||||||
|
if(!ret)
|
||||||
|
libr_close(handle);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Automatically load the ".glade" resource and any applicable icons
|
||||||
|
*/
|
||||||
|
EXPORT_FN int libr_glade_autoload(GladeHandle **glade_ret, IconList **icons_ret, int set_default_icon)
|
||||||
|
{
|
||||||
|
libr_file *handle = NULL;
|
||||||
|
GList *icons = NULL;
|
||||||
|
|
||||||
|
if(glade_ret == NULL)
|
||||||
|
{
|
||||||
|
/* Why on earth would you call this without obtaining the handle to the resource? */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(glade_init == NULL)
|
||||||
|
{
|
||||||
|
/* libglade was not linked with the application */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/* Obtain the handle to the executable */
|
||||||
|
if((handle = libr_open(NULL, LIBR_READ)) == NULL)
|
||||||
|
{
|
||||||
|
/* "Failed to open this executable (%s) for resources", progname() */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
register_internal_handle(handle);
|
||||||
|
icons = libr_gtk_iconlist(handle);
|
||||||
|
/* Set the embedded icons as the default icon list (if requested) */
|
||||||
|
if(icons != NULL && set_default_icon)
|
||||||
|
gtk_window_set_default_icon_list(icons);
|
||||||
|
/* Return the libglade and icon handles for the application */
|
||||||
|
*glade_ret = libr_glade_load_internal(handle, GLADE_SECTION);
|
||||||
|
if(icons_ret)
|
||||||
|
*icons_ret = icons;
|
||||||
|
return true;
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008 Erich Hoover
|
||||||
|
*
|
||||||
|
* libr-gtk - Convenience support for GTK+
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* To provide feedback, report bugs, or otherwise contact me:
|
||||||
|
* ehoover at mines dot edu
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __LIBR_GTK_H
|
||||||
|
#define __LIBR_GTK_H
|
||||||
|
|
||||||
|
#include "libr.h"
|
||||||
|
|
||||||
|
#ifndef GLADE_H
|
||||||
|
typedef void GladeHandle;
|
||||||
|
#else
|
||||||
|
typedef GladeXML GladeHandle;
|
||||||
|
#endif
|
||||||
|
#ifndef __GTK_BUILDER_H__
|
||||||
|
typedef void BuilderHandle;
|
||||||
|
#else
|
||||||
|
typedef GtkBuilder BuilderHandle;
|
||||||
|
#endif
|
||||||
|
#ifndef __G_LIB_H__
|
||||||
|
typedef void IconList;
|
||||||
|
#else
|
||||||
|
typedef GList IconList;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* GTK Convenience API */
|
||||||
|
IconList *libr_gtk_iconlist(libr_file *handle);
|
||||||
|
int libr_gtk_autoload(BuilderHandle **gtk_ret, IconList **icons_ret, int set_default_icon);
|
||||||
|
int libr_gtk_load(BuilderHandle **gtk_ret, char *resource_name);
|
||||||
|
int libr_glade_autoload(GladeHandle **glade_ret, IconList **icons_ret, int set_default_icon);
|
||||||
|
int libr_glade_load(GladeHandle **glade_ret, char *resource_name);
|
||||||
|
|
||||||
|
#endif /* __LIBR_GTK_H */
|
||||||
|
|
@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009 Erich Hoover
|
||||||
|
*
|
||||||
|
* libr i18n - Add language resources into ELF binaries
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* To provide feedback, report bugs, or otherwise contact me:
|
||||||
|
* ehoover at mines dot edu
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Include compile-time parameters */
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "libr-i18n.h"
|
||||||
|
#include "tempfiles.h"
|
||||||
|
|
||||||
|
/* Internationalization support */
|
||||||
|
#include <locale.h>
|
||||||
|
|
||||||
|
/* For string handling */
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extract the internationalization resources from the binary
|
||||||
|
* and setup gettext with the extracted folder.
|
||||||
|
*/
|
||||||
|
EXPORT_FN int libr_i18n_load(libr_file *handle, const char *domain)
|
||||||
|
{
|
||||||
|
char *temp_folder;
|
||||||
|
int ret = true;
|
||||||
|
|
||||||
|
temp_folder = libr_extract_resources(handle);
|
||||||
|
if(temp_folder == NULL)
|
||||||
|
return false;
|
||||||
|
if(!setlocale(LC_ALL, ""))
|
||||||
|
ret = false;
|
||||||
|
if(!bindtextdomain(domain, temp_folder))
|
||||||
|
ret = false;
|
||||||
|
if(!textdomain(domain))
|
||||||
|
ret = false;
|
||||||
|
if(!ret)
|
||||||
|
cleanup_folder(temp_folder);
|
||||||
|
else
|
||||||
|
register_folder_cleanup(temp_folder);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT_FN int libr_i18n_autoload(const char *domain)
|
||||||
|
{
|
||||||
|
libr_file *handle;
|
||||||
|
|
||||||
|
/* Obtain the handle to the executable */
|
||||||
|
if((handle = libr_open(NULL, LIBR_READ)) == NULL)
|
||||||
|
{
|
||||||
|
/* "Failed to open this executable (%s) for resources", progname() */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/* Obtain the language files from the ELF binary */
|
||||||
|
if(!libr_i18n_load(handle, domain))
|
||||||
|
{
|
||||||
|
/* "Failed to load language resources!" */
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
failed:
|
||||||
|
libr_close(handle);
|
||||||
|
return true;
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
#ifndef __LIBR_I18N_H
|
||||||
|
#define __LIBR_I18N_H
|
||||||
|
|
||||||
|
#include "libr.h"
|
||||||
|
#include "gettext.h"
|
||||||
|
|
||||||
|
#define _(string) gettext(string)
|
||||||
|
/* for strings used in structures (must manually call gettext!): */
|
||||||
|
#define N_(string) (string)
|
||||||
|
|
||||||
|
int libr_i18n_autoload(const char *domain);
|
||||||
|
int libr_i18n_load(libr_file *handle, const char *domain);
|
||||||
|
|
||||||
|
#endif /* __LIBR_I18N_H */
|
@ -0,0 +1,643 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008-2011 Erich Hoover
|
||||||
|
*
|
||||||
|
* libr icons - Add icon resources into ELF binaries
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* To provide feedback, report bugs, or otherwise contact me:
|
||||||
|
* ehoover at mines dot edu
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Include compile-time parameters */
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "libr-icons.h"
|
||||||
|
|
||||||
|
/* For "one canvas" SVG documents */
|
||||||
|
#include "onecanvas.h"
|
||||||
|
|
||||||
|
/* For string manipulation */
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
/* For handling files */
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
/* For C99 number types */
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define ICON_SECTION ".icon"
|
||||||
|
#define TERM_LEN 1
|
||||||
|
|
||||||
|
#define OFFSET_ENTRIES 0
|
||||||
|
#define OFFSET_GUID OFFSET_ENTRIES+sizeof(uint32_t)
|
||||||
|
|
||||||
|
#if defined(__i386)
|
||||||
|
#define ID12FORMAT "%012llx"
|
||||||
|
#elif defined(__x86_64)
|
||||||
|
#define ID12FORMAT "%012lx"
|
||||||
|
#else
|
||||||
|
#define ID12FORMAT "%012lx"
|
||||||
|
#warning "string formatting may be incorrect on this architecture."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||||
|
|
||||||
|
typedef uint32_t ID8;
|
||||||
|
typedef uint16_t ID4;
|
||||||
|
typedef struct {uint64_t p:48;} __attribute__((__packed__)) ID12;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ID8 g1;
|
||||||
|
ID4 g2;
|
||||||
|
ID4 g3;
|
||||||
|
ID4 g4;
|
||||||
|
ID12 g5;
|
||||||
|
} __attribute__((__packed__)) UUID;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *name;
|
||||||
|
size_t offset;
|
||||||
|
size_t entry_size;
|
||||||
|
libr_icontype_t type;
|
||||||
|
unsigned int icon_size;
|
||||||
|
} iconentry;
|
||||||
|
|
||||||
|
typedef struct{
|
||||||
|
size_t size;
|
||||||
|
char *buffer;
|
||||||
|
iconentry entry;
|
||||||
|
} iconlist;
|
||||||
|
|
||||||
|
#endif /* DOXYGEN_SHOULD_SKIP_THIS */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decode a UUID to its binary representation
|
||||||
|
*
|
||||||
|
* NOTE: The last 12-bit parameter cannot be obtained using (uint64_t *) with
|
||||||
|
* some versions of GCC using some optimization levels. This problem is very
|
||||||
|
* frustrating to debug, so I do not recommend playing with it yourself.
|
||||||
|
*/
|
||||||
|
UUID guid_decode(char *guid)
|
||||||
|
{
|
||||||
|
UUID id = {0x00000000, 0x0000, 0x0000, 0x0000, {0x000000000000} };
|
||||||
|
uint64_t tmp12;
|
||||||
|
|
||||||
|
sscanf(guid, "%08x-%04hx-%04hx-%04hx-" ID12FORMAT, &id.g1, &id.g2, &id.g3, &id.g4, &tmp12);
|
||||||
|
id.g5.p = tmp12;
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the size of the file represented by the file stream
|
||||||
|
*/
|
||||||
|
off_t fsize(FILE *handle)
|
||||||
|
{
|
||||||
|
struct stat file_stat;
|
||||||
|
|
||||||
|
if(fstat(fileno(handle), &file_stat) == ERROR)
|
||||||
|
return ERROR;
|
||||||
|
return file_stat.st_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a new icon handle
|
||||||
|
*/
|
||||||
|
libr_icon *new_icon_handle(libr_icontype_t type, unsigned int icon_size, char *buffer, size_t buffer_size)
|
||||||
|
{
|
||||||
|
libr_icon *icon_handle = (libr_icon *) malloc(sizeof(libr_icon));
|
||||||
|
|
||||||
|
icon_handle->type = type;
|
||||||
|
icon_handle->buffer = buffer;
|
||||||
|
icon_handle->icon_size = icon_size;
|
||||||
|
icon_handle->buffer_size = buffer_size;
|
||||||
|
return icon_handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Obtain an existing icon resource list
|
||||||
|
*/
|
||||||
|
int get_iconlist(libr_file *file_handle, iconlist *icons)
|
||||||
|
{
|
||||||
|
if(icons == NULL)
|
||||||
|
{
|
||||||
|
/* Need to be able to return SOMETHING */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/* Obtain the icon resource list */
|
||||||
|
icons->buffer = libr_malloc(file_handle, ICON_SECTION, &(icons->size));
|
||||||
|
if(icons->buffer == NULL)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the next entry in an icon resource list
|
||||||
|
*/
|
||||||
|
iconentry *get_nexticon(iconlist *icons, iconentry *last_entry)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
/* The icon list is needed both for the data buffer and for a call-specific iconentry instance */
|
||||||
|
if(icons == NULL)
|
||||||
|
return NULL;
|
||||||
|
/* If this is the first call (last_entry == NULL) then return the first entry */
|
||||||
|
if(last_entry == NULL)
|
||||||
|
icons->entry.offset = sizeof(uint32_t)+sizeof(UUID);
|
||||||
|
else
|
||||||
|
icons->entry.offset += icons->entry.entry_size;
|
||||||
|
/* Check to see if we've run out of entries */
|
||||||
|
if(icons->entry.offset >= icons->size)
|
||||||
|
return NULL;
|
||||||
|
i = icons->entry.offset;
|
||||||
|
memcpy(&(icons->entry.entry_size), &(icons->buffer[i]), sizeof(uint32_t));
|
||||||
|
i += sizeof(uint32_t);
|
||||||
|
icons->entry.type = icons->buffer[i];
|
||||||
|
i += sizeof(unsigned char);
|
||||||
|
switch(icons->entry.type)
|
||||||
|
{
|
||||||
|
case LIBR_SVG:
|
||||||
|
icons->entry.icon_size = 0;
|
||||||
|
icons->entry.name = &(icons->buffer[i]);
|
||||||
|
break;
|
||||||
|
case LIBR_PNG:
|
||||||
|
memcpy(&(icons->entry.icon_size), &(icons->buffer[i]), sizeof(uint32_t));
|
||||||
|
i += sizeof(uint32_t);
|
||||||
|
icons->entry.name = &(icons->buffer[i]);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Invalid entry type */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return &(icons->entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Free an icon handle
|
||||||
|
*/
|
||||||
|
EXPORT_FN int libr_icon_close(libr_icon *icon)
|
||||||
|
{
|
||||||
|
if(icon == NULL)
|
||||||
|
return false;
|
||||||
|
if(icon->buffer == NULL)
|
||||||
|
return false;
|
||||||
|
free(icon->buffer);
|
||||||
|
free(icon);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read an icon resource from an ELF file by name
|
||||||
|
*/
|
||||||
|
EXPORT_FN libr_icon *libr_icon_geticon_byname(libr_file *handle, char *icon_name)
|
||||||
|
{
|
||||||
|
iconentry *entry = NULL;
|
||||||
|
libr_icon *icon = NULL;
|
||||||
|
size_t buffer_size = 0;
|
||||||
|
unsigned int icon_size;
|
||||||
|
libr_icontype_t type;
|
||||||
|
char *buffer = NULL;
|
||||||
|
int inlist = false;
|
||||||
|
iconlist icons;
|
||||||
|
|
||||||
|
if(!get_iconlist(handle, &icons))
|
||||||
|
{
|
||||||
|
/* Failed to obtain a list of ELF icons */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/* Look for the icon name in the entry list */
|
||||||
|
while((entry = get_nexticon(&icons, entry)) != NULL)
|
||||||
|
{
|
||||||
|
if(!strcmp(entry->name, icon_name))
|
||||||
|
{
|
||||||
|
type = entry->type;
|
||||||
|
icon_size = entry->icon_size;
|
||||||
|
inlist = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!inlist)
|
||||||
|
{
|
||||||
|
/* Could not find icon name in the list of icons */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/* Get the icon from the ELF binary */
|
||||||
|
if(!libr_size(handle, icon_name, &buffer_size))
|
||||||
|
{
|
||||||
|
/* Failed to obtain ELF icon size */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/* Allocate memory for the icon */
|
||||||
|
buffer = (char *) malloc(buffer_size);
|
||||||
|
if(buffer == NULL)
|
||||||
|
{
|
||||||
|
/* Failed to allocate memory for icon */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/* Get the compressed icon from the ELF file */
|
||||||
|
if(!libr_read(handle, icon_name, buffer))
|
||||||
|
{
|
||||||
|
/* Failed to obtain ELF icon */
|
||||||
|
goto geticon_byname_complete;
|
||||||
|
}
|
||||||
|
icon = new_icon_handle(type, icon_size, buffer, buffer_size);
|
||||||
|
|
||||||
|
geticon_byname_complete:
|
||||||
|
if(icon == NULL)
|
||||||
|
free(buffer);
|
||||||
|
return icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read an icon resource from an ELF file by the square icon size
|
||||||
|
*/
|
||||||
|
EXPORT_FN libr_icon *libr_icon_geticon_bysize(libr_file *handle, unsigned int iconsize)
|
||||||
|
{
|
||||||
|
unsigned int closest_id = 0, i = 0, j = 0;
|
||||||
|
int found_png = false, found_svg = false;
|
||||||
|
unsigned long closest_size = 0;
|
||||||
|
iconentry *entry = NULL;
|
||||||
|
iconlist icons;
|
||||||
|
|
||||||
|
if(!get_iconlist(handle, &icons))
|
||||||
|
{
|
||||||
|
/* Failed to obtain a list of ELF icons */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/* Look for the closest size match, ignore SVG in case there are multiple icons */
|
||||||
|
while((entry = get_nexticon(&icons, entry)) != NULL)
|
||||||
|
{
|
||||||
|
if(entry->type == LIBR_SVG)
|
||||||
|
found_svg = true;
|
||||||
|
if(entry->type == LIBR_PNG)
|
||||||
|
{
|
||||||
|
if(j == 0)
|
||||||
|
{
|
||||||
|
closest_size = entry->icon_size;
|
||||||
|
found_png = true;
|
||||||
|
}
|
||||||
|
if(abs(iconsize-entry->icon_size) < closest_size)
|
||||||
|
{
|
||||||
|
closest_size = entry->icon_size;
|
||||||
|
closest_id = i;
|
||||||
|
}
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
/* If any PNG files were found then use the file if:
|
||||||
|
* 1) There are no SVG files <OR>
|
||||||
|
* 2) The PNG is an EXACT size match
|
||||||
|
*/
|
||||||
|
if(found_png)
|
||||||
|
{
|
||||||
|
i=0;
|
||||||
|
entry = NULL;
|
||||||
|
while((entry = get_nexticon(&icons, entry)) != NULL)
|
||||||
|
{
|
||||||
|
if(i == closest_id)
|
||||||
|
{
|
||||||
|
if(entry->icon_size == iconsize || !found_svg)
|
||||||
|
return libr_icon_geticon_byname(handle, entry->name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Otherwise use the SVG (provided that there is one) */
|
||||||
|
if(found_svg)
|
||||||
|
{
|
||||||
|
entry = NULL;
|
||||||
|
while((entry = get_nexticon(&icons, entry)) != NULL)
|
||||||
|
{
|
||||||
|
if(entry->type == LIBR_SVG)
|
||||||
|
{
|
||||||
|
libr_icon *icon = libr_icon_geticon_byname(handle, entry->name);
|
||||||
|
if (icon) {
|
||||||
|
libr_icon *icon_onecanvas;
|
||||||
|
char *buffer;
|
||||||
|
|
||||||
|
/* should we report the requested size for SVG? */
|
||||||
|
icon->icon_size = iconsize;
|
||||||
|
|
||||||
|
/* if the SVG is a "one canvas" document then extract the correctly sized icon */
|
||||||
|
if((buffer = onecanvas_geticon_bysize(icon->buffer, iconsize)) != NULL)
|
||||||
|
{
|
||||||
|
libr_icon_close(icon);
|
||||||
|
icon_onecanvas = new_icon_handle(LIBR_SVG, iconsize, buffer, strlen(buffer));
|
||||||
|
return icon_onecanvas;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return icon;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Give up */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Obtains the icon UUID for the ELF file
|
||||||
|
*/
|
||||||
|
EXPORT_FN int libr_icon_getuuid(libr_file *handle, char *uuid)
|
||||||
|
{
|
||||||
|
UUID id = {0x00000000, 0x0000, 0x0000, 0x0000, {0x000000000000} };
|
||||||
|
iconlist icons;
|
||||||
|
|
||||||
|
if(!get_iconlist(handle, &icons))
|
||||||
|
{
|
||||||
|
/* Failed to obtain the list of ELF icons */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/* Now store the GUID to the return string */
|
||||||
|
memcpy(&id, &(icons.buffer[OFFSET_GUID]), sizeof(UUID));
|
||||||
|
snprintf(uuid, GUIDSTR_LENGTH, "%08x-%04hx-%04hx-%04hx-" ID12FORMAT "\n", id.g1, id.g2, id.g3, id.g4, (uint64_t) id.g5.p);
|
||||||
|
free(icons.buffer);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
EXPORT_FN int libr_icon_getguid(libr_file *handle, char *uuid) ALIAS_FN(libr_icon_getuuid);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate a buffer containing the data of an icon
|
||||||
|
*/
|
||||||
|
EXPORT_FN char *libr_icon_malloc(libr_icon *icon, size_t *size)
|
||||||
|
{
|
||||||
|
char *iconfile = NULL;
|
||||||
|
|
||||||
|
if(size == NULL)
|
||||||
|
{
|
||||||
|
/* No return size passed */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if(!libr_icon_size(icon, size))
|
||||||
|
{
|
||||||
|
/* Failed to obtain embedded icon file size */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
iconfile = (char *) malloc(*size);
|
||||||
|
if(!libr_icon_read(icon, iconfile))
|
||||||
|
{
|
||||||
|
/* Failed to obtain embedded icon file */
|
||||||
|
free(iconfile);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return iconfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create an icon resource to represent a file on the hard disk
|
||||||
|
*/
|
||||||
|
EXPORT_FN libr_icon *libr_icon_newicon_byfile(libr_icontype_t type, unsigned int icon_size, char *icon_file)
|
||||||
|
{
|
||||||
|
libr_icon *icon_handle = NULL;
|
||||||
|
size_t len, buffer_size = 0;
|
||||||
|
char *buffer = NULL;
|
||||||
|
FILE *handle = NULL;
|
||||||
|
|
||||||
|
/* Open a handle to the icon file */
|
||||||
|
if((handle = fopen(icon_file, "r")) == NULL)
|
||||||
|
{
|
||||||
|
/* Failed to open icon file */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/* Get the size of the icon file */
|
||||||
|
if((buffer_size = fsize(handle)) == ERROR)
|
||||||
|
{
|
||||||
|
/* Failed to obtain the icon's file size */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/* Allocate a buffer for the uncompressed icon */
|
||||||
|
buffer = (char *) malloc(buffer_size);
|
||||||
|
if(buffer == NULL)
|
||||||
|
{
|
||||||
|
/* Failed to allocate a buffer for the icon data */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/* Read the uncompressed image from the disk */
|
||||||
|
if((len = fread(buffer, 1, buffer_size, handle)) <= 0)
|
||||||
|
{
|
||||||
|
/* Failed to read icon from disk */
|
||||||
|
goto newicon_complete;
|
||||||
|
}
|
||||||
|
fclose(handle);
|
||||||
|
if(len != buffer_size)
|
||||||
|
{
|
||||||
|
/* Failed to read the entire icon */
|
||||||
|
goto newicon_complete;
|
||||||
|
}
|
||||||
|
/* Allocate the icon handle */
|
||||||
|
icon_handle = new_icon_handle(type, icon_size, buffer, buffer_size);
|
||||||
|
|
||||||
|
newicon_complete:
|
||||||
|
if(icon_handle == NULL)
|
||||||
|
free(buffer);
|
||||||
|
return icon_handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy the icon resource into a buffer
|
||||||
|
*/
|
||||||
|
EXPORT_FN int libr_icon_read(libr_icon *icon, char *buffer)
|
||||||
|
{
|
||||||
|
if(icon == NULL)
|
||||||
|
return false;
|
||||||
|
memcpy(buffer, icon->buffer, icon->buffer_size);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the memory size of an icon resource
|
||||||
|
*/
|
||||||
|
EXPORT_FN int libr_icon_size(libr_icon *icon, size_t *size)
|
||||||
|
{
|
||||||
|
if(icon == NULL)
|
||||||
|
return false;
|
||||||
|
*size = icon->buffer_size;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save the icon resource to a file
|
||||||
|
*/
|
||||||
|
EXPORT_FN int libr_icon_save(libr_icon *icon, char *filename)
|
||||||
|
{
|
||||||
|
FILE *file = NULL;
|
||||||
|
int ret = false;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if(icon == NULL)
|
||||||
|
return false;
|
||||||
|
/* Open the file to store the image */
|
||||||
|
if((file = fopen(filename, "w")) == NULL)
|
||||||
|
{
|
||||||
|
/* Failed to open file to write the icon */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/* Store the uncompressed icon to disk */
|
||||||
|
if((len = fwrite(icon->buffer, 1, icon->buffer_size, file)) <= 0)
|
||||||
|
{
|
||||||
|
/* Failed to write output file */
|
||||||
|
goto saveicon_complete;
|
||||||
|
}
|
||||||
|
if(len != icon->buffer_size)
|
||||||
|
{
|
||||||
|
/* Did not write the entire file */
|
||||||
|
goto saveicon_complete;
|
||||||
|
}
|
||||||
|
ret = true;
|
||||||
|
|
||||||
|
saveicon_complete:
|
||||||
|
/* Close remaining resources */
|
||||||
|
fclose(file);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sets the icon GUID for the ELF file
|
||||||
|
*/
|
||||||
|
EXPORT_FN int libr_icon_setuuid(libr_file *handle, char *guid)
|
||||||
|
{
|
||||||
|
int ret = false;
|
||||||
|
iconlist icons;
|
||||||
|
UUID id;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* First check the GUID string */
|
||||||
|
for(i=0;i<strlen(guid);i++)
|
||||||
|
{
|
||||||
|
if(!isxdigit(guid[i]))
|
||||||
|
{
|
||||||
|
if(guid[i] == '-' && (i == 8 || i == 13 || i == 18 || i == 23))
|
||||||
|
continue;
|
||||||
|
/* not a valid GUID string */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
id = guid_decode(guid);
|
||||||
|
/* Now check existing resources */
|
||||||
|
if(!get_iconlist(handle, &icons))
|
||||||
|
{
|
||||||
|
/* No icons exist in the file, create a new icon section with the GUID */
|
||||||
|
uint32_t entries = 0;
|
||||||
|
|
||||||
|
icons.size = sizeof(uint32_t)+sizeof(UUID);
|
||||||
|
icons.buffer = (char *) malloc(icons.size);
|
||||||
|
memcpy(&(icons.buffer[OFFSET_ENTRIES]), &entries, sizeof(uint32_t));
|
||||||
|
}
|
||||||
|
/* Set the GUID and write the resource */
|
||||||
|
if(!libr_write(handle, ICON_SECTION, icons.buffer, icons.size, LIBR_UNCOMPRESSED, LIBR_OVERWRITE))
|
||||||
|
{
|
||||||
|
/* failed to write icon resource */
|
||||||
|
goto setguid_complete;
|
||||||
|
}
|
||||||
|
ret = true;
|
||||||
|
|
||||||
|
setguid_complete:
|
||||||
|
free(icons.buffer);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_FN int libr_icon_setguid(libr_file *handle, char *uuid) ALIAS_FN(libr_icon_setuuid);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add an icon resource to an ELF file
|
||||||
|
*/
|
||||||
|
EXPORT_FN int libr_icon_write(libr_file *handle, libr_icon *icon, char *icon_name, libr_overwrite_t overwrite)
|
||||||
|
{
|
||||||
|
size_t entry_size, i;
|
||||||
|
iconentry *entry = NULL;
|
||||||
|
iconlist icons;
|
||||||
|
int ret = false;
|
||||||
|
|
||||||
|
/* Check to make sure the user did not make a poor name choice */
|
||||||
|
if(!strcmp(icon_name, ICON_SECTION))
|
||||||
|
{
|
||||||
|
/* ".icon" is a reserved section name */
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
/* Check to make sure the file supports icon resources */
|
||||||
|
if(!get_iconlist(handle, &icons))
|
||||||
|
{
|
||||||
|
/* A GUID must be set first */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/* First add the icon as a new named section */
|
||||||
|
if(!libr_write(handle, icon_name, icon->buffer, icon->buffer_size, LIBR_COMPRESSED, overwrite))
|
||||||
|
{
|
||||||
|
/* Failed to add the icon as a resource */
|
||||||
|
goto writeicon_complete;
|
||||||
|
}
|
||||||
|
/* Look to see if the icon already has an entry */
|
||||||
|
while((entry = get_nexticon(&icons, entry)) != NULL)
|
||||||
|
{
|
||||||
|
if(!strcmp(entry->name, icon_name))
|
||||||
|
{
|
||||||
|
ret = true;
|
||||||
|
goto writeicon_complete;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Now add the icon to the list of icon resources in the ".icon" section */
|
||||||
|
switch(icon->type)
|
||||||
|
{
|
||||||
|
case LIBR_SVG:
|
||||||
|
entry_size = sizeof(uint32_t)+sizeof(unsigned char)+strlen(icon_name)+TERM_LEN;
|
||||||
|
break;
|
||||||
|
case LIBR_PNG:
|
||||||
|
entry_size = sizeof(uint32_t)+sizeof(unsigned char)+sizeof(uint32_t)+strlen(icon_name)+TERM_LEN;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Unhandled icon type */
|
||||||
|
goto writeicon_complete;
|
||||||
|
}
|
||||||
|
icons.buffer = (char *) realloc(icons.buffer, icons.size+entry_size);
|
||||||
|
if(icons.buffer == NULL)
|
||||||
|
{
|
||||||
|
/* Failed to expand memory size */
|
||||||
|
goto writeicon_complete;
|
||||||
|
}
|
||||||
|
i = icons.size;
|
||||||
|
memcpy(&(icons.buffer[i]), &entry_size, sizeof(uint32_t));
|
||||||
|
i+=sizeof(uint32_t);
|
||||||
|
icons.buffer[i] = icon->type;
|
||||||
|
i+=sizeof(unsigned char);
|
||||||
|
if(icon->type == LIBR_PNG)
|
||||||
|
{
|
||||||
|
memcpy(&(icons.buffer[i]), &icon->icon_size, sizeof(uint32_t));
|
||||||
|
i+=sizeof(uint32_t);
|
||||||
|
}
|
||||||
|
memcpy(&(icons.buffer[i]), icon_name, strlen(icon_name));
|
||||||
|
i+=strlen(icon_name);
|
||||||
|
icons.buffer[i] = '\0';
|
||||||
|
icons.size += entry_size;
|
||||||
|
if(i != (icons.size-1))
|
||||||
|
printf("Really dangerous, buffer size mismatch!\n");
|
||||||
|
/* Write the updated icon table */
|
||||||
|
if(!libr_write(handle, ICON_SECTION, icons.buffer, icons.size, LIBR_UNCOMPRESSED, LIBR_OVERWRITE))
|
||||||
|
{
|
||||||
|
/* failed to write icon resource */
|
||||||
|
goto writeicon_complete;
|
||||||
|
}
|
||||||
|
ret = true;
|
||||||
|
|
||||||
|
writeicon_complete:
|
||||||
|
if(icons.buffer)
|
||||||
|
free(icons.buffer);
|
||||||
|
return ret;
|
||||||
|
}
|
@ -0,0 +1,201 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008-2010 Erich Hoover
|
||||||
|
*
|
||||||
|
* libr-icons - Handle icon resources in ELF binaries
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* To provide feedback, report bugs, or otherwise contact me:
|
||||||
|
* ehoover at mines dot edu
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __LIBR_ICONS_H
|
||||||
|
#define __LIBR_ICONS_H
|
||||||
|
|
||||||
|
#include "libr.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
LIBR_SVG = 0,
|
||||||
|
LIBR_PNG = 1
|
||||||
|
} libr_icontype_t;
|
||||||
|
|
||||||
|
#define UUIDSTR_LENGTH 37
|
||||||
|
#define GUIDSTR_LENGTH UUIDSTR_LENGTH
|
||||||
|
|
||||||
|
#ifdef __LIBR_BUILD__
|
||||||
|
typedef struct {
|
||||||
|
char *buffer;
|
||||||
|
size_t buffer_size;
|
||||||
|
libr_icontype_t type;
|
||||||
|
unsigned int icon_size;
|
||||||
|
} libr_icon;
|
||||||
|
#else
|
||||||
|
typedef void libr_icon;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* libr Icon API
|
||||||
|
*************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @page libr_icon_close Release an icon resource handle.
|
||||||
|
* @section SYNOPSIS
|
||||||
|
* \#include <libr.h>
|
||||||
|
*
|
||||||
|
* <b>int libr_icon_close(libr_icon *icon);</b>
|
||||||
|
*
|
||||||
|
* @section DESCRIPTION
|
||||||
|
* Release the icon resource allocated by a call to
|
||||||
|
* <b>libr_icon_geticon_byid</b>(3), <b>libr_icon_geticon_byname</b>(3),
|
||||||
|
* <b>libr_icon_geticon_bysize</b>(3), <b>libr_icon_newicon_byfile</b>(3),
|
||||||
|
* or <b>libr_icon_newicon_frombuffer</b>(3).
|
||||||
|
*
|
||||||
|
* @param icon The icon handle to release.
|
||||||
|
* @return Returns 1 on success, 0 on failure.
|
||||||
|
*
|
||||||
|
* @section SA SEE ALSO
|
||||||
|
* <b>libr_icon_geticon_byid</b>(3), <b>libr_icon_geticon_byname</b>(3),
|
||||||
|
* <b>libr_icon_geticon_bysize</b>(3), <b>libr_icon_newicon_byfile</b>(3),
|
||||||
|
* <b>libr_icon_newicon_frombuffer</b>(3)
|
||||||
|
*
|
||||||
|
* @section AUTHOR
|
||||||
|
* Erich Hoover <ehoover@mines.edu>
|
||||||
|
*/
|
||||||
|
int libr_icon_close(libr_icon *icon);
|
||||||
|
|
||||||
|
/*
|
||||||
|
libr_icon *libr_icon_geticon_byid(libr_file *handle, unsigned int iconid);
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @page libr_icon_geticon_byname Retrieve an icon resource from an ELF
|
||||||
|
* binary (by the icon resource's name).
|
||||||
|
* @section SYNOPSIS
|
||||||
|
* \#include <libr.h>
|
||||||
|
*
|
||||||
|
* <b>libr_icon *libr_icon_geticon_byname(libr_file *handle, char *iconname);</b>
|
||||||
|
*
|
||||||
|
* @section DESCRIPTION
|
||||||
|
* Return a resource handle to an icon stored in a libr-compatible ELF
|
||||||
|
* binary. When this handle is no-longer needed it must be unallocated
|
||||||
|
* using <b>libr_icon_close</b>(3).
|
||||||
|
*
|
||||||
|
* @param handle A handle returned by <b>libr_open</b>(3).
|
||||||
|
* @param iconname The exact name of the resource to return.
|
||||||
|
* @return Returns a handle on success, NULL on failure.
|
||||||
|
*
|
||||||
|
* @section SA SEE ALSO
|
||||||
|
* <b>libr_open</b>(3), <b>libr_icon_close</b>(3)
|
||||||
|
*
|
||||||
|
* @section AUTHOR
|
||||||
|
* Erich Hoover <ehoover@mines.edu>
|
||||||
|
*/
|
||||||
|
libr_icon *libr_icon_geticon_byname(libr_file *handle, char *iconname);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @page libr_icon_geticon_bysize Retrieve an icon resource from an ELF
|
||||||
|
* binary (by the desired icon size).
|
||||||
|
* @section SYNOPSIS
|
||||||
|
* \#include <libr.h>
|
||||||
|
*
|
||||||
|
* <b>libr_icon *libr_icon_geticon_bysize(libr_file *handle, unsigned int iconsize);</b>
|
||||||
|
*
|
||||||
|
* @section DESCRIPTION
|
||||||
|
* Return a resource handle to the closest requested size icon stored
|
||||||
|
* in a libr-compatible ELF binary. When this handle is no-longer
|
||||||
|
* needed it must be unallocated using <b>libr_icon_close</b>(3).
|
||||||
|
*
|
||||||
|
* @param handle A handle returned by <b>libr_open</b>(3).
|
||||||
|
* @param iconsize The size of the resource to return, use 0
|
||||||
|
* to request an SVG icon.
|
||||||
|
* @return Returns a handle on success, NULL on failure.
|
||||||
|
*
|
||||||
|
* @section SA SEE ALSO
|
||||||
|
* <b>libr_open</b>(3), <b>libr_icon_close</b>(3)
|
||||||
|
*
|
||||||
|
* @section AUTHOR
|
||||||
|
* Erich Hoover <ehoover@mines.edu>
|
||||||
|
*/
|
||||||
|
libr_icon *libr_icon_geticon_bysize(libr_file *handle, unsigned int iconsize);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @page libr_icon_getuuid Retrieve the UUID of an application.
|
||||||
|
* @section SYNOPSIS
|
||||||
|
* \#include <libr.h>
|
||||||
|
*
|
||||||
|
* <b>int libr_icon_getuuid(libr_file *handle, char *uuid);</b>
|
||||||
|
*
|
||||||
|
* @section DESCRIPTION
|
||||||
|
* Returns the icon UUID corresponding to the ELF binary in hex notation
|
||||||
|
* (XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX), which requires a 37 character
|
||||||
|
* buffer (36 data characters and a NULL terminator).
|
||||||
|
*
|
||||||
|
* @param handle A handle returned by <b>libr_open</b>(3).
|
||||||
|
* @param uuid A buffer to store the UUID of the application.
|
||||||
|
* @return Returns 1 on success, 0 on failure.
|
||||||
|
*
|
||||||
|
* @section SA SEE ALSO
|
||||||
|
* <b>libr_open</b>(3), <b>libr_icon_close</b>(3),
|
||||||
|
* <b>libr_icon_setuuid</b>(3)
|
||||||
|
*
|
||||||
|
* @section AUTHOR
|
||||||
|
* Erich Hoover <ehoover@mines.edu>
|
||||||
|
*/
|
||||||
|
int libr_icon_getuuid(libr_file *handle, char *uuid);
|
||||||
|
DEPRECATED_FN int libr_icon_getguid(libr_file *handle, char *uuid);
|
||||||
|
|
||||||
|
char *libr_icon_malloc(libr_icon *icon, size_t *size);
|
||||||
|
/*
|
||||||
|
libr_icon *libr_icon_newicon_frombuffer(libr_icontype_t type, int iconsize, char *buffer, size_t size);
|
||||||
|
*/
|
||||||
|
libr_icon *libr_icon_newicon_byfile(libr_icontype_t type, unsigned int iconsize, char *iconfile);
|
||||||
|
/*
|
||||||
|
unsigned int libr_icon_num(libr_file *handle);
|
||||||
|
*/
|
||||||
|
int libr_icon_read(libr_icon *icon, char *buffer);
|
||||||
|
int libr_icon_size(libr_icon *icon, size_t *size);
|
||||||
|
int libr_icon_save(libr_icon *icon, char *filename);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @page libr_icon_setuuid Write a UUID into an application binary.
|
||||||
|
* @section SYNOPSIS
|
||||||
|
* \#include <libr.h>
|
||||||
|
*
|
||||||
|
* <b>int libr_icon_setuuid(libr_file *handle, char *uuid);</b>
|
||||||
|
*
|
||||||
|
* @section DESCRIPTION
|
||||||
|
* Sets the icon UUID corresponding to the ELF binary in hex notation
|
||||||
|
* (XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX), which requires a 37 character
|
||||||
|
* buffer (36 data characters and a NULL terminator).
|
||||||
|
*
|
||||||
|
* @param handle A handle returned by <b>libr_open</b>(3).
|
||||||
|
* @param uuid A UUID to set for the application, can be generated by
|
||||||
|
* the terminal program "uuid".
|
||||||
|
* @return Returns 1 on success, 0 on failure.
|
||||||
|
*
|
||||||
|
* @section SA SEE ALSO
|
||||||
|
* <b>libr_open</b>(3), <b>libr_icon_close</b>(3),
|
||||||
|
* <b>libr_icon_getuuid</b>(3)
|
||||||
|
*
|
||||||
|
* @section AUTHOR
|
||||||
|
* Erich Hoover <ehoover@mines.edu>
|
||||||
|
*/
|
||||||
|
int libr_icon_setuuid(libr_file *handle, char *uuid);
|
||||||
|
DEPRECATED_FN int libr_icon_setguid(libr_file *handle, char *guid);
|
||||||
|
int libr_icon_write(libr_file *handle, libr_icon *icon, char *iconname, libr_overwrite_t overwrite);
|
||||||
|
|
||||||
|
#endif /* __LIBR_ICONS_H */
|
@ -0,0 +1,34 @@
|
|||||||
|
#ifndef __LIBR_INTERNAL_H
|
||||||
|
#define __LIBR_INTERNAL_H
|
||||||
|
|
||||||
|
#define false 0
|
||||||
|
#define true 1
|
||||||
|
#define ERROR -1
|
||||||
|
#define EXPORT_FN __attribute__((visibility ("protected")))
|
||||||
|
#define INTERNAL_FN __attribute__ ((visibility ("internal")))
|
||||||
|
#define LIBR_TEMPFILE "/tmp/libr-temp.XXXXXX"
|
||||||
|
#define LIBR_TEMPFILE_LEN 22
|
||||||
|
|
||||||
|
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *message;
|
||||||
|
libr_status status;
|
||||||
|
const char *function;
|
||||||
|
} libr_intstatus;
|
||||||
|
|
||||||
|
#endif /* DOXYGEN_SHOULD_SKIP_THIS */
|
||||||
|
|
||||||
|
struct _libr_file;
|
||||||
|
|
||||||
|
void libr_set_error(libr_intstatus error);
|
||||||
|
libr_intstatus make_status(const char *function, libr_status code, char *message, ...);
|
||||||
|
/* Only called directly by cleanup routine, all other calls should be through libr_close */
|
||||||
|
void libr_close_internal(struct _libr_file *file_handle);
|
||||||
|
|
||||||
|
#define SET_ERROR(code,...) make_status(__FUNCTION__, code, __VA_ARGS__)
|
||||||
|
#define RETURN(code,...) return SET_ERROR(code, __VA_ARGS__)
|
||||||
|
#define RETURN_OK return SET_ERROR(LIBR_OK, NULL)
|
||||||
|
#define PUBLIC_RETURN(code,message) {SET_ERROR(code, message); return (code == LIBR_OK);}
|
||||||
|
|
||||||
|
#endif /* __LIBR_INTERNAL_H */
|
@ -0,0 +1,26 @@
|
|||||||
|
#ifndef __LIBR_LINK_H
|
||||||
|
#define __LIBR_LINK_H
|
||||||
|
|
||||||
|
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void **symbol;
|
||||||
|
char *name;
|
||||||
|
} symbol_table;
|
||||||
|
|
||||||
|
#endif /* DOXYGEN_SHOULD_SKIP_THIS */
|
||||||
|
|
||||||
|
#define SYMBOL_TABLE(tbl, ...) \
|
||||||
|
const symbol_table tbl[] = { \
|
||||||
|
__VA_ARGS__ \
|
||||||
|
{NULL, NULL} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define OVERRIDE_SYMBOL(a) FN_##a
|
||||||
|
#define SYMBOL(sym) {(void **)&FN_##sym, #sym}
|
||||||
|
#define DEFINE_SYMBOL(ret, fn, ...) ret (*OVERRIDE_SYMBOL(fn))(__VA_ARGS__)
|
||||||
|
#define LOAD_SYMBOLS(lib, tbl) load_symbols(lib, tbl, sizeof(tbl)/sizeof(symbol_table))
|
||||||
|
|
||||||
|
int load_symbols(const char *library, const symbol_table *table, int entries);
|
||||||
|
|
||||||
|
#endif /* __LIBR_LINK_H */
|
@ -0,0 +1,351 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009 Erich Hoover
|
||||||
|
* Copyright (c) 2008-2009 Martin Rosenau
|
||||||
|
*
|
||||||
|
* libr read-only Backend - Read resources from ELF binaries
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* To provide feedback, report bugs, or otherwise contact me:
|
||||||
|
* ehoover at mines dot edu
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Include compile-time parameters */
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "libr.h"
|
||||||
|
#include "libr-internal.h"
|
||||||
|
|
||||||
|
/* malloc/free */
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* For memory byte-wise compare */
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* For endian conversion */
|
||||||
|
#include "cvtendian.h"
|
||||||
|
|
||||||
|
#define RETURN_UNSUPPORTED RETURN(LIBR_ERROR_UNSUPPORTED, "The read-only backend does not support this operation");
|
||||||
|
|
||||||
|
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned char magic[4];
|
||||||
|
eClass byte_size;
|
||||||
|
eEncoding endian;
|
||||||
|
unsigned char version;
|
||||||
|
unsigned char padding[9];
|
||||||
|
} ElfPreHeader;
|
||||||
|
|
||||||
|
#endif /* DOXYGEN_SHOULD_SKIP_THIS */
|
||||||
|
|
||||||
|
#define ELF_HALF(b) sizeof(uint16_t)
|
||||||
|
#define ELF_WORD(b) sizeof(uint32_t)
|
||||||
|
#define ELF_XWORD(b) ((b == ELFCLASS32) ? sizeof(uint32_t) : sizeof(uint64_t))
|
||||||
|
#define ELF_ADDR(b) ELF_XWORD(b)
|
||||||
|
#define ELF_OFF(b) ELF_XWORD(b)
|
||||||
|
|
||||||
|
/* ELF Header Offsets */
|
||||||
|
#define HDROFF_TYPE(b) sizeof(ElfPreHeader) /* ElfXX_Half e_type; */
|
||||||
|
#define HDROFF_MACHINE(b) HDROFF_TYPE(b)+ELF_HALF(b) /* ElfXX_Half e_machine; */
|
||||||
|
#define HDROFF_VERSION(b) HDROFF_MACHINE(b)+ELF_HALF(b) /* ElfXX_Word e_version; */
|
||||||
|
#define HDROFF_ENTRY(b) HDROFF_VERSION(b)+ELF_WORD(b) /* ElfXX_Addr e_entry; */
|
||||||
|
#define HDROFF_PHOFF(b) HDROFF_ENTRY(b)+ELF_ADDR(b) /* ElfXX_Off e_phoff; */
|
||||||
|
#define HDROFF_SHOFF(b) HDROFF_PHOFF(b)+ELF_OFF(b) /* ElfXX_Off e_shoff; */
|
||||||
|
#define HDROFF_FLAGS(b) HDROFF_SHOFF(b)+ELF_OFF(b) /* ElfXX_Word e_flags; */
|
||||||
|
#define HDROFF_EHSIZE(b) HDROFF_FLAGS(b)+ELF_WORD(b) /* ElfXX_Half e_ehsize; */
|
||||||
|
#define HDROFF_PHENTSIZE(b) HDROFF_EHSIZE(b)+ELF_HALF(b) /* ElfXX_Half e_phentsize; */
|
||||||
|
#define HDROFF_PHNUM(b) HDROFF_PHENTSIZE(b)+ELF_HALF(b) /* ElfXX_Half e_phnum; */
|
||||||
|
#define HDROFF_SHENTSIZE(b) HDROFF_PHNUM(b)+ELF_HALF(b) /* ElfXX_Half e_shentsize; */
|
||||||
|
#define HDROFF_SHNUM(b) HDROFF_SHENTSIZE(b)+ELF_HALF(b) /* ElfXX_Half e_shnum; */
|
||||||
|
#define HDROFF_SHSTRNDX(b) HDROFF_SHNUM(b)+ELF_HALF(b) /* ElfXX_Half e_shstrndx; */
|
||||||
|
|
||||||
|
/* ELF Section Offsets */
|
||||||
|
#define SECOFF_NAME(b) 0 /* ElfXX_Word sh_name; */
|
||||||
|
#define SECOFF_TYPE(b) SECOFF_NAME(b)+ELF_WORD(b) /* ElfXX_Word sh_type; */
|
||||||
|
#define SECOFF_FLAGS(b) SECOFF_TYPE(b)+ELF_WORD(b) /* ElfXX_XWord sh_flags; */
|
||||||
|
#define SECOFF_ADDR(b) SECOFF_FLAGS(b)+ELF_XWORD(b) /* ElfXX_Addr sh_addr; */
|
||||||
|
#define SECOFF_OFFSET(b) SECOFF_ADDR(b)+ELF_ADDR(b) /* ElfXX_Off sh_offset; */
|
||||||
|
#define SECOFF_SIZE(b) SECOFF_OFFSET(b)+ELF_OFF(b) /* ElfXX_XWord sh_size; */
|
||||||
|
#define SECOFF_LINK(b) SECOFF_SIZE(b)+ELF_XWORD(b) /* ElfXX_Word sh_link; */
|
||||||
|
#define SECOFF_INFO(b) SECOFF_LINK(b)+ELF_WORD(b) /* ElfXX_Word sh_info; */
|
||||||
|
#define SECOFF_ADDRALIGN SECOFF_INFO(b)+ELF_WORD(b) /* ElfXX_XWord sh_addralign; */
|
||||||
|
#define SECOFF_ENTSIZE SECOFF_ADDRALIGN(b)+ELF_XWORD(b) /* ElfXX_XWord sh_entsize; */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Safely read a parameter from the ELF binary
|
||||||
|
*/
|
||||||
|
static int read_param(FILE *handle, void *result, size_t bytes, eClass endian)
|
||||||
|
{
|
||||||
|
if(fread(result, 1, bytes, handle) != bytes)
|
||||||
|
return 0;
|
||||||
|
if(ferror(handle))
|
||||||
|
return 0;
|
||||||
|
if(endian != HOST_ENDIAN && !ConvertEndian(result, bytes))
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The read-only backend requires no initialization
|
||||||
|
*/
|
||||||
|
void initialize_backend(void)
|
||||||
|
{
|
||||||
|
if(sizeof(ElfPreHeader) != 16)
|
||||||
|
fprintf(stderr, "WARNING: Your compiler did not properly pack important structures!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The read-only backend cannot write an output file
|
||||||
|
*/
|
||||||
|
void write_output(libr_file *file_handle) {}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The read-only backend cannot add sections
|
||||||
|
*/
|
||||||
|
libr_intstatus add_section(libr_file *file_handle, char *resource_name, libr_section **retscn)
|
||||||
|
{
|
||||||
|
RETURN_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the name of a section
|
||||||
|
*/
|
||||||
|
char *section_name(libr_file *file_handle, libr_section *scn)
|
||||||
|
{
|
||||||
|
if(scn == NULL)
|
||||||
|
return NULL;
|
||||||
|
return scn->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the pointer to the actual data in the section
|
||||||
|
*/
|
||||||
|
void *data_pointer(libr_section *scn, libr_data *data)
|
||||||
|
{
|
||||||
|
return (void *) data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the size of the data in the section
|
||||||
|
*/
|
||||||
|
size_t data_size(libr_section *scn, libr_data *data)
|
||||||
|
{
|
||||||
|
return scn->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find the resource stored in the ELF binary
|
||||||
|
*/
|
||||||
|
libr_intstatus find_section(libr_file *file_handle, char *section, libr_section **retscn)
|
||||||
|
{
|
||||||
|
char *test_name;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i=0; i<file_handle->total_sections; i++)
|
||||||
|
{
|
||||||
|
test_name = section_name(file_handle, &(file_handle->secdata[i]));
|
||||||
|
if(test_name != NULL && strcmp(test_name, section) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(i >= file_handle->total_sections)
|
||||||
|
RETURN(LIBR_ERROR_NOSECTION, "ELF resource section not found");
|
||||||
|
|
||||||
|
/* Found the resource, hurray! */
|
||||||
|
*retscn = &(file_handle->secdata[i]);
|
||||||
|
RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read the section from the ELF binary
|
||||||
|
*/
|
||||||
|
libr_data *get_data(libr_file *file_handle, libr_section *scn)
|
||||||
|
{
|
||||||
|
FILE *handle = file_handle->handle;
|
||||||
|
libr_data *data = NULL;
|
||||||
|
size_t n;
|
||||||
|
|
||||||
|
fseek(handle, scn->data_offset, SEEK_SET);
|
||||||
|
data = (libr_data *) malloc(scn->size);
|
||||||
|
n = fread(data, 1, scn->size, handle);
|
||||||
|
if(n == 0)
|
||||||
|
goto failed; /* Empty section? */
|
||||||
|
if(ferror(handle))
|
||||||
|
goto failed;
|
||||||
|
|
||||||
|
/* Succeeded in reading the data */
|
||||||
|
return data;
|
||||||
|
failed:
|
||||||
|
free(data);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* UNSUPORTED BY BACKEND: Create a new data section
|
||||||
|
*/
|
||||||
|
libr_data *new_data(libr_file *file_handle, libr_section *scn)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find the next section given a section pointer
|
||||||
|
*/
|
||||||
|
libr_section *next_section(libr_file *file_handle, libr_section *scn)
|
||||||
|
{
|
||||||
|
int total_sections = file_handle->total_sections;
|
||||||
|
libr_section *test_scn = NULL;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if(total_sections == 0)
|
||||||
|
return NULL;
|
||||||
|
/* Requesting the first section */
|
||||||
|
if(scn == NULL)
|
||||||
|
{
|
||||||
|
i = 0;
|
||||||
|
/* Do not return an empty section */
|
||||||
|
while(test_scn == NULL || test_scn->size == 0)
|
||||||
|
{
|
||||||
|
if(i > total_sections)
|
||||||
|
return NULL;
|
||||||
|
test_scn = &(file_handle->secdata[i++]);
|
||||||
|
}
|
||||||
|
return test_scn;
|
||||||
|
}
|
||||||
|
/* Return the next section given a section pointer */
|
||||||
|
for(i=0; i<total_sections; i++)
|
||||||
|
{
|
||||||
|
test_scn = &(file_handle->secdata[i]);
|
||||||
|
|
||||||
|
if(test_scn == scn && (i+1) < total_sections)
|
||||||
|
{
|
||||||
|
libr_section *next_scn = &(file_handle->secdata[i+1]);
|
||||||
|
|
||||||
|
/* Returning empty sections is pointless */
|
||||||
|
if(next_scn->size != 0)
|
||||||
|
return next_scn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* UNSUPORTED BY BACKEND: Remove a section
|
||||||
|
*/
|
||||||
|
libr_intstatus remove_section(libr_file *file_handle, libr_section *scn)
|
||||||
|
{
|
||||||
|
RETURN_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* UNSUPORTED BY BACKEND: Set the data for a section
|
||||||
|
*/
|
||||||
|
libr_intstatus set_data(libr_file *file_handle, libr_section *scn, libr_data *data, off_t offset, char *buffer, size_t size)
|
||||||
|
{
|
||||||
|
RETURN_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Open a handle to the ELF binary (provided that read-only access is requested)
|
||||||
|
*/
|
||||||
|
libr_intstatus open_handles(libr_file *file_handle, char *filename, libr_access_t access)
|
||||||
|
{
|
||||||
|
const char elf_magic[] = {'\x7F','E','L','F'};
|
||||||
|
uint16_t total_sections, sh_size, strings_sec;
|
||||||
|
ElfPreHeader file_info;
|
||||||
|
libr_section *secdata;
|
||||||
|
FILE *handle = NULL;
|
||||||
|
uint64_t sh_offset;
|
||||||
|
unsigned long i;
|
||||||
|
|
||||||
|
if(access == LIBR_READ_WRITE)
|
||||||
|
RETURN_UNSUPPORTED;
|
||||||
|
handle = fopen(filename, "rb");
|
||||||
|
if(!handle)
|
||||||
|
RETURN(LIBR_ERROR_OPENFAILED, "Failed to open input file");
|
||||||
|
if(fread(&file_info, 1, sizeof(ElfPreHeader), handle) != sizeof(ElfPreHeader))
|
||||||
|
RETURN(LIBR_ERROR_WRONGFORMAT, "Failed to read pre-header bytes from input file");
|
||||||
|
if(memcmp(file_info.magic, elf_magic, sizeof(elf_magic)) != 0)
|
||||||
|
RETURN(LIBR_ERROR_WRONGFORMAT, "Invalid input file format: not an ELF binary");
|
||||||
|
|
||||||
|
/* Confirm processor (byte size) and packing (endian) */
|
||||||
|
if(!enum_valid(file_info.byte_size, ELFCLASS))
|
||||||
|
RETURN(LIBR_ERROR_WRONGFORMAT, "Invalid input file format: invalid byte size");
|
||||||
|
if(!enum_valid(file_info.endian, ELFDATA))
|
||||||
|
RETURN(LIBR_ERROR_WRONGFORMAT, "Invalid input file format: invalid endian type");
|
||||||
|
|
||||||
|
/* Get the file offset to the Section Header tables */
|
||||||
|
fseek(handle, HDROFF_SHOFF(file_info.byte_size), SEEK_SET);
|
||||||
|
if(!read_param(handle, &sh_offset, ELF_OFF(file_info.byte_size), file_info.endian))
|
||||||
|
RETURN(LIBR_ERROR_WRONGFORMAT, "Invalid input file format: failed to read section header offset");
|
||||||
|
/* Get the size of the Section Header tables */
|
||||||
|
fseek(handle, HDROFF_SHENTSIZE(file_info.byte_size), SEEK_SET);
|
||||||
|
if(!read_param(handle, &sh_size, ELF_HALF(file_info.byte_size), file_info.endian))
|
||||||
|
RETURN(LIBR_ERROR_WRONGFORMAT, "Invalid input file format: failed to read section header size");
|
||||||
|
/* Get the total number of sections */
|
||||||
|
fseek(handle, HDROFF_SHNUM(file_info.byte_size), SEEK_SET);
|
||||||
|
if(!read_param(handle, &total_sections, ELF_HALF(file_info.byte_size), file_info.endian))
|
||||||
|
RETURN(LIBR_ERROR_WRONGFORMAT, "Invalid input file format: failed to read total number of sections");
|
||||||
|
/* Get the ID of the "strings" section */
|
||||||
|
fseek(handle, HDROFF_SHSTRNDX(file_info.byte_size), SEEK_SET);
|
||||||
|
if(!read_param(handle, &strings_sec, ELF_HALF(file_info.byte_size), file_info.endian))
|
||||||
|
RETURN(LIBR_ERROR_WRONGFORMAT, "Invalid input file format: failed to read string section ID");
|
||||||
|
if(strings_sec >= total_sections)
|
||||||
|
RETURN(LIBR_ERROR_WRONGFORMAT, "Invalid input file format: invalid string section ID");
|
||||||
|
secdata = (libr_section *) malloc(sizeof(libr_section)*total_sections);
|
||||||
|
|
||||||
|
/* Load section information */
|
||||||
|
for(i=0; i<total_sections; i++)
|
||||||
|
{
|
||||||
|
long sec_start = sh_offset+sh_size*i;
|
||||||
|
|
||||||
|
/* Grab the offset in the string table to the name of the section */
|
||||||
|
fseek(handle, sec_start+SECOFF_NAME(file_info.byte_size), SEEK_SET);
|
||||||
|
if(!read_param(handle, &(secdata[i].name_offset), ELF_WORD(file_info.byte_size), file_info.endian))
|
||||||
|
RETURN(LIBR_ERROR_WRONGFORMAT, "Invalid input file format: failed to read section name offset");
|
||||||
|
/* Grab the offset to the data for the section */
|
||||||
|
fseek(handle, sec_start+SECOFF_OFFSET(file_info.byte_size), SEEK_SET);
|
||||||
|
if(!read_param(handle, &(secdata[i].data_offset), ELF_OFF(file_info.byte_size), file_info.endian))
|
||||||
|
RETURN(LIBR_ERROR_WRONGFORMAT, "Invalid input file format: failed to read section data offset");
|
||||||
|
/* Grab the size of the data for the section */
|
||||||
|
fseek(handle, sec_start+SECOFF_SIZE(file_info.byte_size), SEEK_SET);
|
||||||
|
if(!read_param(handle, &(secdata[i].size), ELF_XWORD(file_info.byte_size), file_info.endian))
|
||||||
|
RETURN(LIBR_ERROR_WRONGFORMAT, "Invalid input file format: failed to read section size");
|
||||||
|
}
|
||||||
|
/* Locate the name offset within the "strings" section and load the string */
|
||||||
|
for(i=0; i<total_sections; i++)
|
||||||
|
{
|
||||||
|
long stringsec_start = secdata[strings_sec].data_offset;
|
||||||
|
size_t n;
|
||||||
|
|
||||||
|
fseek(handle, stringsec_start+secdata[i].name_offset, SEEK_SET);
|
||||||
|
n = fread(secdata[i].name, 1, ELFSTRING_MAX-1, handle);
|
||||||
|
if(ferror(handle))
|
||||||
|
RETURN(LIBR_ERROR_WRONGFORMAT, "Invalid input file format: failed to read string");
|
||||||
|
secdata[i].name[n] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hold onto the important parameters */
|
||||||
|
file_handle->secdata = secdata;
|
||||||
|
file_handle->total_sections = total_sections;
|
||||||
|
file_handle->endian = file_info.endian;
|
||||||
|
file_handle->byte_size = file_info.byte_size;
|
||||||
|
file_handle->handle = handle;
|
||||||
|
file_handle->filename = filename;
|
||||||
|
file_handle->access = access;
|
||||||
|
RETURN_OK;
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
#ifndef __LIBRRO_H
|
||||||
|
#define __LIBRRO_H
|
||||||
|
|
||||||
|
/* For file handle support */
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/* For integer types with set bit-sizes */
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE: Packing the enum uses the smallest number of bytes
|
||||||
|
* possible to represent the value. This packing does not
|
||||||
|
* guarantee that a "short enum" will be 8 bits, however,
|
||||||
|
* for the small enumerations in the ELF specification this
|
||||||
|
* IS the case (no enum requires more than 8 bits).
|
||||||
|
*/
|
||||||
|
#define SHORT_ENUM __attribute__ ((__packed__))
|
||||||
|
|
||||||
|
/* Type of byte-packing (endian) */
|
||||||
|
typedef enum SHORT_ENUM {
|
||||||
|
ELFDATANONE, /* Invalid */
|
||||||
|
ELFDATA2LSB, /* Least Significant Byte First */
|
||||||
|
ELFDATA2MSB, /* Most Significant Byte First */
|
||||||
|
ELFDATAMAX, /* Invalid */
|
||||||
|
} eEncoding;
|
||||||
|
|
||||||
|
/* Type of target processor */
|
||||||
|
typedef enum SHORT_ENUM {
|
||||||
|
ELFCLASSNONE, /* Invalid */
|
||||||
|
ELFCLASS32, /* 32-bit Field Alignment */
|
||||||
|
ELFCLASS64, /* 64-bit Field Alignment */
|
||||||
|
ELFCLASSMAX, /* Invalid */
|
||||||
|
} eClass;
|
||||||
|
|
||||||
|
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||||
|
|
||||||
|
#define ELFSTRING_MAX 200
|
||||||
|
typedef struct _libr_section {
|
||||||
|
uint64_t size;
|
||||||
|
uint64_t data_offset;
|
||||||
|
uint32_t name_offset;
|
||||||
|
char name[ELFSTRING_MAX];
|
||||||
|
} libr_section;
|
||||||
|
|
||||||
|
typedef struct _libr_file {
|
||||||
|
FILE *handle;
|
||||||
|
char *filename;
|
||||||
|
eEncoding endian;
|
||||||
|
eClass byte_size;
|
||||||
|
libr_access_t access;
|
||||||
|
libr_section *secdata;
|
||||||
|
unsigned long total_sections;
|
||||||
|
} libr_file;
|
||||||
|
|
||||||
|
#endif /* DOXYGEN_SHOULD_SKIP_THIS */
|
||||||
|
|
||||||
|
/* for a clean internal API */
|
||||||
|
typedef void libr_data;
|
||||||
|
|
||||||
|
#define enum_valid(val, name) (val > name##NONE && val < name##MAX)
|
||||||
|
|
||||||
|
#endif /* __LIBRRO_H */
|
@ -0,0 +1,489 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008-2009 Erich Hoover
|
||||||
|
*
|
||||||
|
* libr - Add resources into ELF binaries
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* To provide feedback, report bugs, or otherwise contact me:
|
||||||
|
* ehoover at mines dot edu
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Include compile-time parameters */
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "libr.h"
|
||||||
|
#include "tempfiles.h"
|
||||||
|
|
||||||
|
/* Obtain file information */
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/* Compress files */
|
||||||
|
#include <zlib.h>
|
||||||
|
#include <math.h> /* for ceil */
|
||||||
|
|
||||||
|
/* Handle strings and variable arguments*/
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
/* For C99 number types */
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/* Handle status codes for multiple threads */
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#define SPEC_VERSION '1'
|
||||||
|
#define OFFSET_TYPE ((unsigned long) 4)
|
||||||
|
#define OFFSET_UNCOMPRESSED ((unsigned long) OFFSET_TYPE+sizeof(unsigned char))
|
||||||
|
#define OFFSET_UNCOMPRESSED_SIZE ((unsigned long) OFFSET_TYPE+sizeof(unsigned char))
|
||||||
|
#define OFFSET_COMPRESSED ((unsigned long) OFFSET_UNCOMPRESSED_SIZE+sizeof(uint32_t))
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
extern const char * __progname_full;
|
||||||
|
#define progpath() (char *) __progname_full
|
||||||
|
#endif
|
||||||
|
#define getself() ((char *) "/proc/self/exe")
|
||||||
|
|
||||||
|
pthread_key_t error_key;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Free the error status code/message structure
|
||||||
|
* (called on thread destruction or when a new code is set)
|
||||||
|
*/
|
||||||
|
void free_error_key(void *_m)
|
||||||
|
{
|
||||||
|
libr_intstatus *error = (libr_intstatus *) _m;
|
||||||
|
|
||||||
|
if(error != NULL)
|
||||||
|
{
|
||||||
|
/* Free the error structure */
|
||||||
|
if(error->message != NULL)
|
||||||
|
free(error->message);
|
||||||
|
free(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the error code and message for retrieval
|
||||||
|
*/
|
||||||
|
void libr_set_error(libr_intstatus error)
|
||||||
|
{
|
||||||
|
static int thread_key_initialized = false;
|
||||||
|
libr_intstatus *status = NULL;
|
||||||
|
|
||||||
|
if(!thread_key_initialized)
|
||||||
|
{
|
||||||
|
if(pthread_key_create(&error_key, free_error_key) != 0)
|
||||||
|
return; /* a serious pthread-related error occurred */
|
||||||
|
if(pthread_setspecific(error_key, NULL) != 0)
|
||||||
|
return; /* a serious pthread-related error occurred */
|
||||||
|
thread_key_initialized = true;
|
||||||
|
}
|
||||||
|
free_error_key(pthread_getspecific(error_key));
|
||||||
|
status = (libr_intstatus *) malloc(sizeof(libr_intstatus));
|
||||||
|
memcpy(status, &error, sizeof(libr_intstatus));
|
||||||
|
if(pthread_setspecific(error_key, (void *) status) != 0)
|
||||||
|
return; /* a serious pthread-related error occurred */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make an internal status passing structure, set the error code with this status
|
||||||
|
* if the status is not LIBR_OK.
|
||||||
|
*/
|
||||||
|
libr_intstatus make_status(const char *function, libr_status code, char *message, ...)
|
||||||
|
{
|
||||||
|
libr_intstatus status = {NULL, code, function};
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
if(message != NULL)
|
||||||
|
{
|
||||||
|
status.message = (char *) malloc(1024);
|
||||||
|
va_start(args, message);
|
||||||
|
vsnprintf(status.message, 1024, message, args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
libr_set_error(status);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure that the section is libr-compatible
|
||||||
|
*/
|
||||||
|
libr_intstatus section_ok(libr_section *scn, libr_data *data)
|
||||||
|
{
|
||||||
|
char required_header[5], test_header[4] = {'R', 'E', 'S', SPEC_VERSION};
|
||||||
|
void *ptr = data_pointer(scn, data);
|
||||||
|
size_t size = data_size(scn, data);
|
||||||
|
|
||||||
|
if(ptr == NULL || size < sizeof(required_header))
|
||||||
|
RETURN(LIBR_ERROR_NOTRESOURCE, "Not a valid libr-resource");
|
||||||
|
memcpy(required_header, ptr, sizeof(required_header));
|
||||||
|
if(strncmp(required_header, test_header, sizeof(test_header)) != 0)
|
||||||
|
RETURN(LIBR_ERROR_NOTRESOURCE, "Not a valid libr-resource");
|
||||||
|
RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove a resourcefrom the ELF binary handle
|
||||||
|
*/
|
||||||
|
EXPORT_FN int libr_clear(libr_file *file_handle, char *resource_name)
|
||||||
|
{
|
||||||
|
libr_data *data = NULL;
|
||||||
|
libr_section *scn = NULL;
|
||||||
|
|
||||||
|
/* Ensure valid inputs */
|
||||||
|
if(file_handle == NULL || resource_name == NULL)
|
||||||
|
PUBLIC_RETURN(LIBR_ERROR_INVALIDPARAMS, "Invalid parameters passed to function");
|
||||||
|
if(file_handle->access != LIBR_READ_WRITE)
|
||||||
|
PUBLIC_RETURN(LIBR_ERROR_NOPERM, "Open handle with LIBR_READ_WRITE access");
|
||||||
|
/* Find the section containing the icon */
|
||||||
|
if(find_section(file_handle, resource_name, &scn).status != LIBR_OK)
|
||||||
|
return false; /* error already set */
|
||||||
|
/* Get the section data (interested in header) */
|
||||||
|
if((data = get_data(file_handle, scn)) == NULL)
|
||||||
|
PUBLIC_RETURN(LIBR_ERROR_GETDATA, "Failed to obtain data of section");
|
||||||
|
/* Confirm that this resource is libr-compatible */
|
||||||
|
if(section_ok(scn, data).status != LIBR_OK)
|
||||||
|
return false; /* error already set */
|
||||||
|
/* Clear the data resource */
|
||||||
|
if(set_data(file_handle, scn, data, 0, NULL, 0).status != LIBR_OK)
|
||||||
|
return false; /* error already set */
|
||||||
|
/* Remove the section */
|
||||||
|
if(remove_section(file_handle, scn).status != LIBR_OK)
|
||||||
|
return false; /* error already set */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Close the specified ELF binary handle
|
||||||
|
*/
|
||||||
|
EXPORT_FN void libr_close(libr_file *file_handle)
|
||||||
|
{
|
||||||
|
unregister_handle_cleanup(file_handle);
|
||||||
|
libr_close_internal(file_handle);
|
||||||
|
}
|
||||||
|
/* Only called directly by cleanup routine, all other calls should be through libr_close */
|
||||||
|
void libr_close_internal(libr_file *file_handle)
|
||||||
|
{
|
||||||
|
write_output(file_handle);
|
||||||
|
free(file_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the last error message for the active thread
|
||||||
|
*/
|
||||||
|
EXPORT_FN char *libr_errmsg(void)
|
||||||
|
{
|
||||||
|
libr_intstatus *error = (libr_intstatus *) pthread_getspecific(error_key);
|
||||||
|
|
||||||
|
if(error == NULL)
|
||||||
|
return NULL;
|
||||||
|
return error->message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the last error code for the active thread (or LIBR_OK for no error)
|
||||||
|
*/
|
||||||
|
EXPORT_FN libr_status libr_errno(void)
|
||||||
|
{
|
||||||
|
libr_intstatus *error = (libr_intstatus *) pthread_getspecific(error_key);
|
||||||
|
|
||||||
|
if(error == NULL) /* Nothing has happened yet */
|
||||||
|
return LIBR_OK;
|
||||||
|
return error->status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the name of a libr-compatible resource
|
||||||
|
*/
|
||||||
|
EXPORT_FN char *libr_list(libr_file *file_handle, unsigned int resourceid)
|
||||||
|
{
|
||||||
|
libr_section *scn = NULL;
|
||||||
|
libr_data *data = NULL;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
while((scn = next_section(file_handle, scn)) != NULL)
|
||||||
|
{
|
||||||
|
/* Get the section data (interested in header) */
|
||||||
|
if((data = get_data(file_handle, scn)) == NULL)
|
||||||
|
return NULL;
|
||||||
|
if(section_ok(scn, data).status == LIBR_OK)
|
||||||
|
{
|
||||||
|
if(i == resourceid)
|
||||||
|
return strdup(section_name(file_handle, scn));
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate a buffer containing the data of a resource
|
||||||
|
*/
|
||||||
|
EXPORT_FN char *libr_malloc(libr_file *file_handle, char *resource_name, size_t *size)
|
||||||
|
{
|
||||||
|
char *buffer = NULL;
|
||||||
|
size_t size_local;
|
||||||
|
|
||||||
|
if(size == NULL)
|
||||||
|
size = &size_local;
|
||||||
|
if(!libr_size(file_handle, resource_name, size))
|
||||||
|
return NULL; /* error already set */
|
||||||
|
buffer = (char *) malloc(*size);
|
||||||
|
if(!libr_read(file_handle, resource_name, buffer))
|
||||||
|
{
|
||||||
|
free(buffer);
|
||||||
|
return NULL; /* error already set */
|
||||||
|
}
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Open the specified ELF binary (caller if filename is NULL)
|
||||||
|
*/
|
||||||
|
EXPORT_FN libr_file *libr_open(char *filename, libr_access_t access)
|
||||||
|
{
|
||||||
|
libr_file *file_handle = NULL;
|
||||||
|
static int initialized = false;
|
||||||
|
|
||||||
|
if(!initialized)
|
||||||
|
{
|
||||||
|
if(strncmp(zlibVersion(), ZLIB_VERSION, 1) != 0)
|
||||||
|
{
|
||||||
|
SET_ERROR(LIBR_ERROR_ZLIBINIT, "zlib library initialization failed");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
initialize_backend();
|
||||||
|
initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(filename == NULL)
|
||||||
|
filename = getself();
|
||||||
|
file_handle = (libr_file *) malloc(sizeof(libr_file));
|
||||||
|
memset(file_handle, 0, sizeof(libr_file));
|
||||||
|
if(open_handles(file_handle, filename, access).status != LIBR_OK)
|
||||||
|
{
|
||||||
|
/* failed to open file for processing, error already set */
|
||||||
|
free(file_handle);
|
||||||
|
file_handle = NULL;
|
||||||
|
}
|
||||||
|
/* Cleanup handles automatically when libr exits memory */
|
||||||
|
if(file_handle != NULL)
|
||||||
|
register_handle_cleanup(file_handle);
|
||||||
|
return file_handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read a resource from the specified ELF binary handle
|
||||||
|
*/
|
||||||
|
EXPORT_FN int libr_read(libr_file *file_handle, char *resource_name, char *buffer)
|
||||||
|
{
|
||||||
|
unsigned long uncompressed_size = 0, compressed_size = 0;
|
||||||
|
char *data_buffer = NULL;
|
||||||
|
libr_section *scn = NULL;
|
||||||
|
libr_data *data = NULL;
|
||||||
|
libr_type_t type;
|
||||||
|
|
||||||
|
/* Find the section containing the icon */
|
||||||
|
if(find_section(file_handle, resource_name, &scn).status != LIBR_OK)
|
||||||
|
return false; /* error already set */
|
||||||
|
/* Get the section data (interested in header) */
|
||||||
|
if((data = get_data(file_handle, scn)) == NULL)
|
||||||
|
PUBLIC_RETURN(LIBR_ERROR_GETDATA, "Failed to obtain data of section");
|
||||||
|
/* Confirm that this resource is libr-compatible */
|
||||||
|
if(section_ok(scn, data).status != LIBR_OK)
|
||||||
|
return false; /* error already set */
|
||||||
|
data_buffer = (char *) data_pointer(scn, data);
|
||||||
|
/* Get the size of the data resource */
|
||||||
|
type = (libr_type_t) data_buffer[OFFSET_TYPE];
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case LIBR_UNCOMPRESSED:
|
||||||
|
{ if(data_size(scn, data)-OFFSET_UNCOMPRESSED < 0)
|
||||||
|
PUBLIC_RETURN(LIBR_ERROR_SIZEMISMATCH, "Section's data size does not make sense");
|
||||||
|
uncompressed_size = data_size(scn, data)-OFFSET_UNCOMPRESSED;
|
||||||
|
memcpy(buffer, &data_buffer[OFFSET_UNCOMPRESSED], uncompressed_size);
|
||||||
|
} break;
|
||||||
|
case LIBR_COMPRESSED:
|
||||||
|
{
|
||||||
|
uint32_t size_temp;
|
||||||
|
|
||||||
|
memcpy(&size_temp, &data_buffer[OFFSET_UNCOMPRESSED_SIZE], sizeof(uint32_t));
|
||||||
|
uncompressed_size = size_temp;
|
||||||
|
compressed_size = data_size(scn, data)-OFFSET_COMPRESSED;
|
||||||
|
if(uncompress((unsigned char *)buffer, &uncompressed_size, (unsigned char *)&data_buffer[OFFSET_COMPRESSED], compressed_size) != Z_OK)
|
||||||
|
PUBLIC_RETURN(LIBR_ERROR_UNCOMPRESS, "Failed to uncompress resource data");
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
PUBLIC_RETURN(LIBR_ERROR_INVALIDTYPE, "Invalid data storage type specified");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Retrieve the number of libr-compatible resources
|
||||||
|
*/
|
||||||
|
EXPORT_FN unsigned int libr_resources(libr_file *file_handle)
|
||||||
|
{
|
||||||
|
libr_section *scn = NULL;
|
||||||
|
libr_data *data = NULL;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
while((scn = next_section(file_handle, scn)) != NULL)
|
||||||
|
{
|
||||||
|
if((data = get_data(file_handle, scn)) == NULL)
|
||||||
|
continue;
|
||||||
|
if(section_ok(scn, data).status == LIBR_OK)
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the size of a resource from the specified ELF binary handle
|
||||||
|
*/
|
||||||
|
EXPORT_FN int libr_size(libr_file *file_handle, char *resource_name, size_t *retsize)
|
||||||
|
{
|
||||||
|
char *data_buffer = NULL;
|
||||||
|
libr_section *scn = NULL;
|
||||||
|
libr_data *data = NULL;
|
||||||
|
unsigned long size = 0;
|
||||||
|
libr_type_t type;
|
||||||
|
|
||||||
|
/* Find the section containing the icon */
|
||||||
|
if(find_section(file_handle, resource_name, &scn).status != LIBR_OK)
|
||||||
|
return false; /* error already set */
|
||||||
|
/* Get the section data (interested in header) */
|
||||||
|
if((data = get_data(file_handle, scn)) == NULL)
|
||||||
|
PUBLIC_RETURN(LIBR_ERROR_GETDATA, "Failed to obtain data of section");
|
||||||
|
/* Confirm that this resource is libr-compatible */
|
||||||
|
if(section_ok(scn, data).status != LIBR_OK)
|
||||||
|
return false; /* error already set */
|
||||||
|
data_buffer = (char *) data_pointer(scn, data);
|
||||||
|
/* Get the size of the data resource */
|
||||||
|
type = (libr_type_t) data_buffer[OFFSET_TYPE];
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case LIBR_UNCOMPRESSED:
|
||||||
|
{
|
||||||
|
size_t full_size = data_size(scn, data);
|
||||||
|
|
||||||
|
if(full_size-OFFSET_UNCOMPRESSED < 0)
|
||||||
|
PUBLIC_RETURN(LIBR_ERROR_SIZEMISMATCH, "Section's data size does not make sense");
|
||||||
|
size = full_size - OFFSET_UNCOMPRESSED;
|
||||||
|
} break;
|
||||||
|
case LIBR_COMPRESSED:
|
||||||
|
{
|
||||||
|
memcpy(&size, &data_buffer[OFFSET_UNCOMPRESSED_SIZE], sizeof(uint32_t));
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
PUBLIC_RETURN(LIBR_ERROR_INVALIDTYPE, "Invalid data storage type specified");
|
||||||
|
}
|
||||||
|
*retsize = size;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write a resource to the specified ELF binary handle
|
||||||
|
*/
|
||||||
|
EXPORT_FN int libr_write(libr_file *file_handle, char *resource_name, char *buffer, size_t size, libr_type_t type, libr_overwrite_t overwrite)
|
||||||
|
{
|
||||||
|
char header[9] = {'R', 'E', 'S', SPEC_VERSION};
|
||||||
|
unsigned int header_size = 4;
|
||||||
|
libr_section *scn = NULL;
|
||||||
|
libr_data *data = NULL;
|
||||||
|
libr_intstatus ret;
|
||||||
|
|
||||||
|
/* Ensure valid inputs */
|
||||||
|
if(file_handle == NULL || resource_name == NULL || buffer == NULL)
|
||||||
|
PUBLIC_RETURN(LIBR_ERROR_INVALIDPARAMS, "Invalid parameters passed to function");
|
||||||
|
if(file_handle->access != LIBR_READ_WRITE)
|
||||||
|
PUBLIC_RETURN(LIBR_ERROR_NOPERM, "Open handle with LIBR_READ_WRITE access");
|
||||||
|
/* Get the section if it already exists */
|
||||||
|
ret = find_section(file_handle, resource_name, &scn);
|
||||||
|
if(ret.status == LIBR_OK)
|
||||||
|
{
|
||||||
|
/* If the section exists (and overwrite is not specified) then fail */
|
||||||
|
if(!overwrite)
|
||||||
|
PUBLIC_RETURN(LIBR_ERROR_OVERWRITE, "Section already exists, over-write not specified");
|
||||||
|
/* Grab the existing data section for overwriting */
|
||||||
|
if((data = get_data(file_handle, scn)) == NULL)
|
||||||
|
PUBLIC_RETURN(LIBR_ERROR_GETDATA, "Failed to obtain data of section");
|
||||||
|
}
|
||||||
|
else if(ret.status == LIBR_ERROR_NOSECTION)
|
||||||
|
{
|
||||||
|
/* Create a new section named "resource_name" */
|
||||||
|
if(add_section(file_handle, resource_name, &scn).status != LIBR_OK)
|
||||||
|
return false; /* error already set */
|
||||||
|
/* Create a data segment to store the compressed image */
|
||||||
|
if((data = new_data(file_handle, scn)) == NULL)
|
||||||
|
PUBLIC_RETURN(LIBR_ERROR_NEWDATA, "Failed to create data for section");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false; /* error already set */
|
||||||
|
|
||||||
|
header[header_size++] = (char) type;
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case LIBR_UNCOMPRESSED:
|
||||||
|
/* Do nothing, just stick the data in */
|
||||||
|
break;
|
||||||
|
case LIBR_COMPRESSED:
|
||||||
|
{
|
||||||
|
char *compressed_buffer = NULL, *uncompressed_buffer = buffer;
|
||||||
|
unsigned long compressed_size = 0, uncompressed_size = size;
|
||||||
|
uint32_t size_temp;
|
||||||
|
|
||||||
|
/* Store the uncompressed size to the header */
|
||||||
|
size_temp = uncompressed_size;
|
||||||
|
memcpy(&header[header_size], &size_temp, sizeof(uint32_t));
|
||||||
|
header_size += sizeof(uint32_t);
|
||||||
|
/* Compress the data for storage */
|
||||||
|
compressed_size = ceil((uncompressed_size+12)*1.1);
|
||||||
|
compressed_buffer = (char *) malloc(compressed_size);
|
||||||
|
if(compress((unsigned char *)compressed_buffer, &compressed_size, (unsigned char *)uncompressed_buffer, uncompressed_size) != Z_OK)
|
||||||
|
{
|
||||||
|
free(compressed_buffer);
|
||||||
|
PUBLIC_RETURN(LIBR_ERROR_COMPRESS, "Failed to compress resource data");
|
||||||
|
}
|
||||||
|
/* From here on treat the compressed buffer as the data */
|
||||||
|
buffer = compressed_buffer;
|
||||||
|
size = compressed_size;
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
PUBLIC_RETURN(LIBR_ERROR_INVALIDTYPE, "Invalid data storage type specified");
|
||||||
|
}
|
||||||
|
/* Store the resource header data */
|
||||||
|
if(set_data(file_handle, scn, data, 0, &header[0], header_size).status != LIBR_OK)
|
||||||
|
return false; /* error already set */
|
||||||
|
/* Create a data segment to store the post-header data
|
||||||
|
* NOTE: For existing files the data of the section is represented as a continuous stream
|
||||||
|
* (so calling elf_getdata now WILL NOT return the post-header data)
|
||||||
|
*/
|
||||||
|
if((data = new_data(file_handle, scn)) == NULL)
|
||||||
|
PUBLIC_RETURN(LIBR_ERROR_NEWDATA, "Failed to create data for section");
|
||||||
|
/* Store the actual user data to the section */
|
||||||
|
if(set_data(file_handle, scn, data, header_size, buffer, size).status != LIBR_OK)
|
||||||
|
return false; /* error already set */
|
||||||
|
/* Close compression resources */
|
||||||
|
if(type == LIBR_COMPRESSED)
|
||||||
|
free(buffer);
|
||||||
|
return true;
|
||||||
|
}
|
@ -0,0 +1,416 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008-2011 Erich Hoover
|
||||||
|
*
|
||||||
|
* libr - Add resources into ELF binaries
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* To provide feedback, report bugs, or otherwise contact me:
|
||||||
|
* ehoover at mines dot edu
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __LIBR_H
|
||||||
|
#define __LIBR_H
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#define DEPRECATED_FN __attribute__ ((deprecated))
|
||||||
|
#define ALIAS_FN(fn) __attribute__ ((weak, alias (#fn)))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup libr_status libr_status
|
||||||
|
* @brief Enumeration of possible libr status values.
|
||||||
|
* @{
|
||||||
|
* \#include <libr.h>
|
||||||
|
*/
|
||||||
|
/** Possible libr status values */
|
||||||
|
typedef enum {
|
||||||
|
LIBR_OK = 0, /**< Success */
|
||||||
|
LIBR_ERROR_GETEHDR = -1, /**< Failed to obtain ELF header: */
|
||||||
|
LIBR_ERROR_NOTABLE = -2, /**< No ELF string table */
|
||||||
|
LIBR_ERROR_TABLE = -3, /**< Failed to open string table: */
|
||||||
|
LIBR_ERROR_GETDATA = -4, /**< Failed to obtain data of section */
|
||||||
|
LIBR_ERROR_GETSHDR = -5, /**< Failed to obtain ELF section header: */
|
||||||
|
LIBR_ERROR_SIZEMISMATCH = -6, /**< Section's data size does not make sense */
|
||||||
|
LIBR_ERROR_UPDATE = -7, /**< Failed to perform dynamic update: */
|
||||||
|
LIBR_ERROR_NEWSECTION = -8, /**< Failed to create new section */
|
||||||
|
LIBR_ERROR_NEWDATA = -9, /**< Failed to create data for section */
|
||||||
|
LIBR_ERROR_REMOVESECTION = -10, /**< Failed to remove section: */
|
||||||
|
LIBR_ERROR_NOSECTION = -11, /**< ELF resource section not found */
|
||||||
|
LIBR_ERROR_STRPTR = -12, /**< Failed to obtain section string pointer: */
|
||||||
|
LIBR_ERROR_NOTRESOURCE = -13, /**< Not a valid libr-resource */
|
||||||
|
LIBR_ERROR_EXPANDSECTION = -14, /**< Failed to expand section */
|
||||||
|
LIBR_ERROR_WRONGFORMAT = -15, /**< Invalid input file format */
|
||||||
|
LIBR_ERROR_SETFLAGS = -16, /**< Failed to set flags for section */
|
||||||
|
LIBR_ERROR_NOPERM = -17, /**< Open handle with LIBR_READ_WRITE access */
|
||||||
|
LIBR_ERROR_NOSIZE = -18, /**< Failed to obtain file size */
|
||||||
|
LIBR_ERROR_SETFORMAT = -19, /**< Failed to set output file format to input file format */
|
||||||
|
LIBR_ERROR_SETARCH = -20, /**< Failed to set output file architecture to input file architecture */
|
||||||
|
LIBR_ERROR_OVERWRITE = -21, /**< Section already exists, over-write not specified */
|
||||||
|
LIBR_ERROR_COMPRESS = -22, /**< Failed to compress resource data */
|
||||||
|
LIBR_ERROR_INVALIDTYPE = -23, /**< Invalid data storage type specified */
|
||||||
|
LIBR_ERROR_MEMALLOC = -24, /**< Failed to allocate memory for data */
|
||||||
|
LIBR_ERROR_INVALIDPARAMS = -25, /**< Invalid parameters passed to function */
|
||||||
|
LIBR_ERROR_UNCOMPRESS = -26, /**< Failed to uncompress resource data */
|
||||||
|
LIBR_ERROR_ZLIBINIT = -27, /**< zlib library initialization failed */
|
||||||
|
LIBR_ERROR_OPENFAILED = -28, /**< Failed to open input file */
|
||||||
|
LIBR_ERROR_BEGINFAILED = -29, /**< Failed to open ELF file: */
|
||||||
|
LIBR_ERROR_WRITEPERM = -30, /**< No write permission for file */
|
||||||
|
LIBR_ERROR_UNSUPPORTED = -31, /**< The requested operation is not supported by the backend */
|
||||||
|
} libr_status;
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
LIBR_READ = 0,
|
||||||
|
LIBR_READ_WRITE = 1,
|
||||||
|
} libr_access_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
LIBR_UNCOMPRESSED = 0,
|
||||||
|
LIBR_COMPRESSED = 1
|
||||||
|
} libr_type_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
LIBR_NOOVERWRITE = 0,
|
||||||
|
LIBR_OVERWRITE = 1
|
||||||
|
} libr_overwrite_t;
|
||||||
|
|
||||||
|
#ifdef __LIBR_BUILD__
|
||||||
|
#include "libr-internal.h"
|
||||||
|
#if __LIBR_BACKEND_libbfd__
|
||||||
|
#include "libr-bfd.h"
|
||||||
|
#elif __LIBR_BACKEND_libelf__
|
||||||
|
#include "libr-elf.h"
|
||||||
|
#elif __LIBR_BACKEND_readonly__
|
||||||
|
#include "libr-ro.h"
|
||||||
|
#else /* LIBR_BACKEND */
|
||||||
|
#error "Unhandled backend"
|
||||||
|
#endif /* LIBR_BACKEND */
|
||||||
|
#include "libr-backends.h"
|
||||||
|
#else
|
||||||
|
struct _libr_file;
|
||||||
|
typedef struct _libr_file libr_file;
|
||||||
|
#endif /* __LIBR_BUILD__ */
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* libr Resource Management API
|
||||||
|
*************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @page libr_clear Remove a resource from an ELF executable.
|
||||||
|
* @section SYNOPSIS
|
||||||
|
* \#include <libr.h>
|
||||||
|
*
|
||||||
|
* <b>int libr_clear(libr_file *handle, char *resourcename);</b>
|
||||||
|
*
|
||||||
|
* @section DESCRIPTION
|
||||||
|
* Removes a libr-compatible resource from an ELF executable. The handle
|
||||||
|
* must be opened using <b>libr_open</b>(3) with either <b>LIBR_WRITE</b>
|
||||||
|
* or <b>LIBR_READ_WRITE</b> access in order to remove a resource.
|
||||||
|
*
|
||||||
|
* Please note that resource removal does not occur until the handle is
|
||||||
|
* closed using <b>libr_close</b>(3).
|
||||||
|
*
|
||||||
|
* @param handle A handle returned by <b>libr_open</b>(3).
|
||||||
|
* @param resourcename The name of the libr-compatible resource to remove.
|
||||||
|
*
|
||||||
|
* @section SA SEE ALSO
|
||||||
|
* <b>libr_open</b>(3), <b>libr_close</b>(3)
|
||||||
|
*
|
||||||
|
* @section AUTHOR
|
||||||
|
* Erich Hoover <ehoover@mines.edu>
|
||||||
|
*/
|
||||||
|
int libr_clear(libr_file *handle, char *resourcename);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @page libr_close Close a handle to an ELF executable.
|
||||||
|
* @section SYNOPSIS
|
||||||
|
* \#include <libr.h>
|
||||||
|
*
|
||||||
|
* <b>void libr_close(libr_file *handle);</b>
|
||||||
|
*
|
||||||
|
* @section DESCRIPTION
|
||||||
|
* Handles opened with <b>libr_open</b>(3) should be closed with
|
||||||
|
* <b>libr_close</b>() when they are no-longer needed by the calling
|
||||||
|
* application.
|
||||||
|
*
|
||||||
|
* @param handle The handle to close.
|
||||||
|
*
|
||||||
|
* @section SA SEE ALSO
|
||||||
|
* <b>libr_open</b>(3)
|
||||||
|
*
|
||||||
|
* @section AUTHOR
|
||||||
|
* Erich Hoover <ehoover@mines.edu>
|
||||||
|
*/
|
||||||
|
void libr_close(libr_file *handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @page libr_errmsg Return a detailed description of the last
|
||||||
|
* libr-related error.
|
||||||
|
* @section SYNOPSIS
|
||||||
|
* \#include <libr.h>
|
||||||
|
*
|
||||||
|
* <b>char *libr_errmsg(void);</b>
|
||||||
|
*
|
||||||
|
* @section DESCRIPTION
|
||||||
|
* Returns a detailed string describing the last error encountered by
|
||||||
|
* the libr resource library. The string is an internal error
|
||||||
|
* description, so it should not be freed.
|
||||||
|
*
|
||||||
|
* If no errors have been encountered then NULL is returned.
|
||||||
|
*
|
||||||
|
* @section SA SEE ALSO
|
||||||
|
* <b>libr_errno</b>(3)
|
||||||
|
*
|
||||||
|
* @section AUTHOR
|
||||||
|
* Erich Hoover <ehoover@mines.edu>
|
||||||
|
*/
|
||||||
|
char *libr_errmsg(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @page libr_errno Return a status code describing the last
|
||||||
|
* libr-related error.
|
||||||
|
* @section SYNOPSIS
|
||||||
|
* \#include <libr.h>
|
||||||
|
*
|
||||||
|
* <b>libr_status libr_errno(void);</b>
|
||||||
|
*
|
||||||
|
* @section DESCRIPTION
|
||||||
|
* Returns a code corresponding to the last error encountered by
|
||||||
|
* the libr resource library. For a detailed description of possible
|
||||||
|
* return values see <b>libr_status</b>(3).
|
||||||
|
*
|
||||||
|
* To get a user-readable string corresponding to the last error the
|
||||||
|
* <b>libr_errmsg</b>(3) function should be used instead.
|
||||||
|
*
|
||||||
|
* If no errors have been encountered then <b>LIBR_OK</b> is returned.
|
||||||
|
*
|
||||||
|
* @section SA SEE ALSO
|
||||||
|
* <b>libr_errmsg</b>(3)
|
||||||
|
*
|
||||||
|
* @section AUTHOR
|
||||||
|
* Erich Hoover <ehoover@mines.edu>
|
||||||
|
*/
|
||||||
|
libr_status libr_errno(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @page libr_list Obtain the name of a libr ELF resource (by index).
|
||||||
|
* @section SYNOPSIS
|
||||||
|
* \#include <libr.h>
|
||||||
|
*
|
||||||
|
* <b>char *libr_list(libr_file *file_handle, unsigned int resourceid);</b>
|
||||||
|
*
|
||||||
|
* @section DESCRIPTION
|
||||||
|
* Returns the name of a libr-compatible resource stored in an ELF binary
|
||||||
|
* corresponding to the given resource index. The index value ranges from
|
||||||
|
* 0 to the value returned by <b>libr_resources</b>(3), which returns the
|
||||||
|
* total number of libr-compatible resources stored in the ELF binary.
|
||||||
|
*
|
||||||
|
* @param handle A handle returned by <b>libr_open</b>(3).
|
||||||
|
* @param resourceid The index of the libr-compatible resource for which
|
||||||
|
* the name will be returned.
|
||||||
|
*
|
||||||
|
* @return Returns a string containing the name of the resource section. This
|
||||||
|
* string is allocated when the function is called, so it <i>must be
|
||||||
|
* unallocated</i> with a call to <b>free</b>(3) when it is no-longer
|
||||||
|
* needed. NULL is returned on failure.
|
||||||
|
*
|
||||||
|
* @section SA SEE ALSO
|
||||||
|
* <b>libr_open</b>(3), <b>free</b>(3)
|
||||||
|
*
|
||||||
|
* @section AUTHOR
|
||||||
|
* Erich Hoover <ehoover@mines.edu>
|
||||||
|
*/
|
||||||
|
char *libr_list(libr_file *file_handle, unsigned int resourceid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @page libr_malloc Obtain the data corresponding to a libr ELF resource.
|
||||||
|
* @section SYNOPSIS
|
||||||
|
* \#include <libr.h>
|
||||||
|
*
|
||||||
|
* <b>char *libr_malloc(libr_file *handle, char *resourcename, size_t *size);</b>
|
||||||
|
*
|
||||||
|
* @section DESCRIPTION
|
||||||
|
* Returns the contents of a libr-compatible resource stored in an ELF binary
|
||||||
|
* corresponding to the given resource name.
|
||||||
|
*
|
||||||
|
* @param handle A handle returned by <b>libr_open</b>(3).
|
||||||
|
* @param resourcename The name of the libr-compatible resource for which
|
||||||
|
* the data will be returned.
|
||||||
|
* @param size A pointer for storing the length of the data contained in the
|
||||||
|
* the resource. May be NULL.
|
||||||
|
*
|
||||||
|
* @return Returns NULL on failure, the pointer to a buffer containing the data
|
||||||
|
* for the resource on success. When the buffer is no-longer used it must
|
||||||
|
* be unallocated using a call to <b>free</b>(3).
|
||||||
|
*
|
||||||
|
* @section SA SEE ALSO
|
||||||
|
* <b>libr_open</b>(3), <b>free</b>(3)
|
||||||
|
*
|
||||||
|
* @section AUTHOR
|
||||||
|
* Erich Hoover <ehoover@mines.edu>
|
||||||
|
*/
|
||||||
|
char *libr_malloc(libr_file *handle, char *resourcename, size_t *size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @page libr_open Open an ELF executable file for resource management.
|
||||||
|
* @section SYNOPSIS
|
||||||
|
* \#include <libr.h>
|
||||||
|
*
|
||||||
|
* <b>libr_file *libr_open(char *filename, libr_access_t access);</b>
|
||||||
|
*
|
||||||
|
* @section DESCRIPTION
|
||||||
|
* <b>libr_open</b>() can be used on any ELF executable, however,
|
||||||
|
* <b>libr_open</b>() called with <b>LIBR_READ</b> access is only useful
|
||||||
|
* for executables that already contain libr-compatible stored resources.
|
||||||
|
*
|
||||||
|
* An application can easily access its own resources by passing NULL for
|
||||||
|
* the filename and requesting <b>LIBR_READ</b> access. For the obvious
|
||||||
|
* reason that an actively-open application cannot edit itself, the
|
||||||
|
* calling binary may only request <b>LIBR_READ</b> access.
|
||||||
|
*
|
||||||
|
* @param filename ELF executable to manage. Pass a NULL pointer as the
|
||||||
|
* filename in order to access the calling binary (<b>LIBR_READ</b>
|
||||||
|
* access only) @param access Requested access type (<b>LIBR_READ</b>,
|
||||||
|
* <b>LIBR_WRITE</b>, <b>LIBR_READ_WRITE</b>), the valid operations for
|
||||||
|
* the returned handle will be restricted based upon the requested access.
|
||||||
|
* @return Returns a libr file handle on success, NULL on failure. The
|
||||||
|
* handle should be freed with <b>libr_close</b>(3) when no-longer used.
|
||||||
|
*
|
||||||
|
* @section SA SEE ALSO
|
||||||
|
* <b>libr_close</b>(3)
|
||||||
|
*
|
||||||
|
* @section AUTHOR
|
||||||
|
* Erich Hoover <ehoover@mines.edu>
|
||||||
|
*/
|
||||||
|
libr_file *libr_open(char *filename, libr_access_t access);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @page libr_read Read out the contents of a libr ELF resource.
|
||||||
|
* @section SYNOPSIS
|
||||||
|
* \#include <libr.h>
|
||||||
|
*
|
||||||
|
* <b>int libr_read(libr_file *handle, char *resourcename, char *buffer);</b>
|
||||||
|
*
|
||||||
|
* @section WARNING
|
||||||
|
* This function does not allocate memory for the buffer, so the buffer must
|
||||||
|
* be large enough to fit the resource data. For this reason it is suggested
|
||||||
|
* that <b>libr_malloc</b>(3) be used in preference over this function.
|
||||||
|
*
|
||||||
|
* @section DESCRIPTION
|
||||||
|
* Reads the contents of a resource embedded in an ELF binary, the resource
|
||||||
|
* must be compatible with the libr specification.
|
||||||
|
*
|
||||||
|
* @param handle A handle returned by <b>libr_open</b>(3).
|
||||||
|
* @return Returns 1 on success, 0 on failure.
|
||||||
|
*
|
||||||
|
* @section SA SEE ALSO
|
||||||
|
* <b>libr_open</b>(3)
|
||||||
|
*
|
||||||
|
* @section AUTHOR
|
||||||
|
* Erich Hoover <ehoover@mines.edu>
|
||||||
|
*/
|
||||||
|
int libr_read(libr_file *handle, char *resourcename, char *buffer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @page libr_resources Returns the number of resources contained in
|
||||||
|
* the ELF binary.
|
||||||
|
* @section SYNOPSIS
|
||||||
|
* \#include <libr.h>
|
||||||
|
*
|
||||||
|
* <b>unsigned int libr_resources(libr_file *handle);</b>
|
||||||
|
*
|
||||||
|
* @section DESCRIPTION
|
||||||
|
* Returns the total number of libr-compatible resources contained
|
||||||
|
* in the ELF binary. Intended to be used with <b>libr_list</b>(3)
|
||||||
|
* to return the full list of resources contained in the binary.
|
||||||
|
*
|
||||||
|
* @param handle A handle returned by <b>libr_open</b>(3).
|
||||||
|
* @return The total number of libr resources in the binary.
|
||||||
|
*
|
||||||
|
* @section SA SEE ALSO
|
||||||
|
* <b>libr_open</b>(3), <b>libr_list</b>(3)
|
||||||
|
*
|
||||||
|
* @section AUTHOR
|
||||||
|
* Erich Hoover <ehoover@mines.edu>
|
||||||
|
*/
|
||||||
|
unsigned int libr_resources(libr_file *handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @page libr_size Returns the uncompressed size of a libr resource.
|
||||||
|
* @section SYNOPSIS
|
||||||
|
* \#include <libr.h>
|
||||||
|
*
|
||||||
|
* <b>int libr_size(libr_file *handle, char *resourcename, size_t *size);</b>
|
||||||
|
*
|
||||||
|
* @section DESCRIPTION
|
||||||
|
* Obtain the total number of bytes consumed by the uncompressed
|
||||||
|
* version of the specific libr-resource. Intended to be used with
|
||||||
|
* <b>libr_read</b>(3) in order to allocate a large enough buffer
|
||||||
|
* for the resource.
|
||||||
|
*
|
||||||
|
* @param handle A handle returned by <b>libr_open</b>(3).
|
||||||
|
* @param resourcename The name of the resource for which the
|
||||||
|
* size of the data section will be returned.
|
||||||
|
* @param size A pointer for storing the size of the data section.
|
||||||
|
* This pointer cannot be NULL.
|
||||||
|
* @return Returns 1 on success, 0 on failure.
|
||||||
|
*
|
||||||
|
* @section SA SEE ALSO
|
||||||
|
* <b>libr_open</b>(3), <b>libr_read</b>(3)
|
||||||
|
*
|
||||||
|
* @section AUTHOR
|
||||||
|
* Erich Hoover <ehoover@mines.edu>
|
||||||
|
*/
|
||||||
|
int libr_size(libr_file *handle, char *resourcename, size_t *size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @page libr_write Adds a libr resource to an ELF binary.
|
||||||
|
* @section SYNOPSIS
|
||||||
|
* \#include <libr.h>
|
||||||
|
*
|
||||||
|
* <b>int libr_write(libr_file *handle, char *resourcename, char *buffer, size_t size, libr_type_t type, libr_overwrite_t overwrite);</b>
|
||||||
|
*
|
||||||
|
* @section DESCRIPTION
|
||||||
|
* Adds a libr-compatible resource into the ELF binary. The handle
|
||||||
|
* must be opened using <b>libr_open</b>(3) with either <b>LIBR_WRITE</b>
|
||||||
|
* or <b>LIBR_READ_WRITE</b> access in order to add a resource.
|
||||||
|
*
|
||||||
|
* @param handle A handle returned by <b>libr_open</b>(3).
|
||||||
|
* @param resourcename The name of the resource to create.
|
||||||
|
* @param buffer A string containing the data of the resource.
|
||||||
|
* @param size The total size of the buffer.
|
||||||
|
* @param type The method which should be used for storing the
|
||||||
|
* data (either <b>LIBR_UNCOMPRESSED</b> or
|
||||||
|
* <b>LIBR_COMPRESSED</b>).
|
||||||
|
* @param overwrite Whether overwriting an existing resource
|
||||||
|
* should be permitted (either <b>LIBR_NOOVERWRITE</b> or
|
||||||
|
* <b>LIBR_OVERWRITE</b>).
|
||||||
|
* @return Returns 1 on success, 0 on failure.
|
||||||
|
*
|
||||||
|
* @section SA SEE ALSO
|
||||||
|
* <b>libr_open</b>(3)
|
||||||
|
*
|
||||||
|
* @section AUTHOR
|
||||||
|
* Erich Hoover <ehoover@mines.edu>
|
||||||
|
*/
|
||||||
|
int libr_write(libr_file *handle, char *resourcename, char *buffer, size_t size, libr_type_t type, libr_overwrite_t overwrite);
|
||||||
|
|
||||||
|
#endif /* __LIBR_H */
|
||||||
|
|
@ -0,0 +1,446 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010 Erich Hoover
|
||||||
|
*
|
||||||
|
* libr "one canvas" - Handle multiple icons stored in a single "one canvas"
|
||||||
|
* SVG document.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* To provide feedback, report bugs, or otherwise contact me:
|
||||||
|
* ehoover at mines dot edu
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#define FALSE 0
|
||||||
|
#define TRUE 1
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double width;
|
||||||
|
double height;
|
||||||
|
int icon_width;
|
||||||
|
int icon_height;
|
||||||
|
} IconSVG;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
STATUS_FINDSVG,
|
||||||
|
STATUS_FINDMETADATA,
|
||||||
|
STATUS_FINDPUBLISHER_START,
|
||||||
|
STATUS_FINDPUBLISHER_STOP,
|
||||||
|
STATUS_FINDHIDDEN,
|
||||||
|
STATUS_FINDBOUNDS,
|
||||||
|
STATUS_FAILED,
|
||||||
|
STATUS_DONE,
|
||||||
|
} eStatus;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
IconSVG **iconlist;
|
||||||
|
int iconlist_num;
|
||||||
|
eStatus status;
|
||||||
|
|
||||||
|
char *hidden_stop;
|
||||||
|
char *hidden_start;
|
||||||
|
char *publisher_stop;
|
||||||
|
char *publisher_start;
|
||||||
|
char *coordinate_stop;
|
||||||
|
char *coordinate_start;
|
||||||
|
} OneCanvasIconInfo;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find the start of the next XML tag (search for '<')
|
||||||
|
*/
|
||||||
|
static inline char *xml_nextTag(char *c)
|
||||||
|
{
|
||||||
|
c++;
|
||||||
|
if(c == NULL)
|
||||||
|
return NULL;
|
||||||
|
return strchr(c, '<');
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pull out the name/type of a tag.
|
||||||
|
*/
|
||||||
|
static inline char *xml_getTagName(char *c)
|
||||||
|
{
|
||||||
|
char *tag_end = NULL, *tag_space, *tag_close, *tag_feed, *tag_line;
|
||||||
|
static char tagname[20];
|
||||||
|
int tag_len;
|
||||||
|
|
||||||
|
if(++c == NULL)
|
||||||
|
return NULL;
|
||||||
|
tag_space = strchr(c, ' ');
|
||||||
|
tag_close = strchr(c, '>');
|
||||||
|
tag_feed = strchr(c, '\r');
|
||||||
|
tag_line = strchr(c, '\n');
|
||||||
|
if(tag_space)
|
||||||
|
tag_end = tag_space;
|
||||||
|
if(tag_close && tag_end > tag_close)
|
||||||
|
tag_end = tag_close;
|
||||||
|
if(tag_feed && tag_end > tag_feed)
|
||||||
|
tag_end = tag_feed;
|
||||||
|
if(tag_line && tag_end > tag_line)
|
||||||
|
tag_end = tag_line;
|
||||||
|
if(!tag_end)
|
||||||
|
return NULL;
|
||||||
|
tag_len = tag_end - c;
|
||||||
|
tag_len = tag_len > 19 ? 19 : tag_len;
|
||||||
|
strncpy(tagname, c, tag_len);
|
||||||
|
tagname[tag_len] = '\0';
|
||||||
|
return tagname;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find the position in the string corresponding to a particular named attribute.
|
||||||
|
*/
|
||||||
|
static inline char *xml_getTagAttributePtr(char *c, char *attrname)
|
||||||
|
{
|
||||||
|
char *end, *name;
|
||||||
|
int found;
|
||||||
|
|
||||||
|
if(++c == NULL)
|
||||||
|
return NULL;
|
||||||
|
end = strchr(c, '>');
|
||||||
|
while(c < end)
|
||||||
|
{
|
||||||
|
int name_len;
|
||||||
|
char *equal;
|
||||||
|
|
||||||
|
equal = c = strchr(c, '=');
|
||||||
|
if(c == NULL)
|
||||||
|
break;
|
||||||
|
c++;
|
||||||
|
name = equal;
|
||||||
|
while(name[0] != ' ' && name[0] != '\t' && name[0] != '\n')
|
||||||
|
name--;
|
||||||
|
name++; /* don't include the space */
|
||||||
|
name_len = equal-name;
|
||||||
|
if(name_len != strlen(attrname))
|
||||||
|
continue;
|
||||||
|
if(strncasecmp(attrname, name, name_len) == 0)
|
||||||
|
{
|
||||||
|
found = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!found)
|
||||||
|
return NULL;
|
||||||
|
return c-strlen(attrname)-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the value of an XML tag's named attribute.
|
||||||
|
*/
|
||||||
|
static inline char *xml_getTagAttribute(char *c, char *attrname)
|
||||||
|
{
|
||||||
|
char *data_end;
|
||||||
|
int data_len;
|
||||||
|
char *attr;
|
||||||
|
|
||||||
|
c = xml_getTagAttributePtr(c, attrname);
|
||||||
|
if(c == NULL)
|
||||||
|
return NULL;
|
||||||
|
c+=strlen(attrname); /* skip the name */
|
||||||
|
c+=2; /* skip the equals sign and the quote */
|
||||||
|
data_end = strchr(c, '"');
|
||||||
|
data_len = data_end - c;
|
||||||
|
attr = (char *) malloc(data_len+1);
|
||||||
|
strncpy(attr, c, data_len);
|
||||||
|
attr[data_len] = '\0';
|
||||||
|
return attr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find the value of an XML tag attribute and convert it to a number.
|
||||||
|
*/
|
||||||
|
static inline double xml_getTagAttributeFloat(char *c, char *attrname)
|
||||||
|
{
|
||||||
|
char *value = xml_getTagAttribute(c, attrname);
|
||||||
|
double ret;
|
||||||
|
|
||||||
|
if(!value)
|
||||||
|
return nan("nan");
|
||||||
|
sscanf(value, "%lf", &ret);
|
||||||
|
free(value);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Match the beginning an XML tag by "id" (preferred) or Inkscape's
|
||||||
|
* label (undesireable but acceptable).
|
||||||
|
*/
|
||||||
|
static inline char *xml_idMatchStart(char *stream_pos, char *layer_name)
|
||||||
|
{
|
||||||
|
char *id_acceptable = xml_getTagAttribute(stream_pos, "inkscape:label");
|
||||||
|
char *id_preferred = xml_getTagAttribute(stream_pos, "id");
|
||||||
|
|
||||||
|
if(id_preferred && strncasecmp(id_preferred, layer_name, strlen(layer_name)) == 0)
|
||||||
|
{
|
||||||
|
free(id_acceptable);
|
||||||
|
return id_preferred;
|
||||||
|
}
|
||||||
|
if(id_acceptable && strncasecmp(id_acceptable, layer_name, strlen(layer_name)) == 0)
|
||||||
|
{
|
||||||
|
free(id_preferred);
|
||||||
|
return id_acceptable;
|
||||||
|
}
|
||||||
|
free(id_acceptable);
|
||||||
|
free(id_preferred);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Match the entirety of an XML tag by "id" (preferred) or Inkscape's
|
||||||
|
* label (undesireable but acceptable).
|
||||||
|
*/
|
||||||
|
static inline int xml_idMatch(char *stream_pos, char *layer_name)
|
||||||
|
{
|
||||||
|
char *id_acceptable = xml_getTagAttribute(stream_pos, "inkscape:label");
|
||||||
|
char *id_preferred = xml_getTagAttribute(stream_pos, "id");
|
||||||
|
int ret = FALSE;
|
||||||
|
|
||||||
|
if((id_preferred && strcasecmp(id_preferred, layer_name) == 0)
|
||||||
|
|| (id_acceptable && strcasecmp(id_acceptable, layer_name) == 0))
|
||||||
|
ret = TRUE;
|
||||||
|
free(id_acceptable);
|
||||||
|
free(id_preferred);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Strip all the XML tags from a string and return only the data not
|
||||||
|
* contained within any tags.
|
||||||
|
*/
|
||||||
|
static inline char *xml_stripTags(char *data, int len)
|
||||||
|
{
|
||||||
|
char *ret = (char *) malloc(len+1);
|
||||||
|
char *tag_left, *tag_right;
|
||||||
|
|
||||||
|
memcpy(ret, data, len+1);
|
||||||
|
ret[len] = '\0';
|
||||||
|
while((tag_left = strchr(ret, '<')) != NULL)
|
||||||
|
{
|
||||||
|
tag_right = strchr(ret, '>');
|
||||||
|
memmove(tag_left, tag_right+1, strlen(ret)-(tag_right-ret));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the information for all of the icons within a "one-canvas"
|
||||||
|
* data stream.
|
||||||
|
*/
|
||||||
|
OneCanvasIconInfo onecanvas_geticons(char *stream)
|
||||||
|
{
|
||||||
|
eStatus status = STATUS_FINDSVG;
|
||||||
|
unsigned int stream_size = 0;
|
||||||
|
OneCanvasIconInfo info;
|
||||||
|
char *publisher = NULL;
|
||||||
|
char *stream_pos;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
memset(&info, 0, sizeof(info));
|
||||||
|
stream_pos = stream;
|
||||||
|
while(stream_pos)
|
||||||
|
{
|
||||||
|
char *name = xml_getTagName(stream_pos);
|
||||||
|
|
||||||
|
if(!name)
|
||||||
|
{
|
||||||
|
stream_pos = xml_nextTag(stream_pos);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
switch(status)
|
||||||
|
{
|
||||||
|
case STATUS_FINDSVG:
|
||||||
|
{
|
||||||
|
if(strcasecmp(name, "svg") == 0)
|
||||||
|
{
|
||||||
|
info.coordinate_start = xml_getTagAttributePtr(stream_pos, "x");
|
||||||
|
info.coordinate_stop = xml_getTagAttributePtr(stream_pos, "viewBox");
|
||||||
|
if(info.coordinate_start == NULL || info.coordinate_stop == NULL)
|
||||||
|
{
|
||||||
|
status = STATUS_FAILED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
info.coordinate_stop = strchr(info.coordinate_stop, '"')+1;
|
||||||
|
info.coordinate_stop = strchr(info.coordinate_stop, '"')+1;
|
||||||
|
status = STATUS_FINDMETADATA;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case STATUS_FINDMETADATA:
|
||||||
|
{
|
||||||
|
if(strcasecmp(name, "metadata") == 0)
|
||||||
|
{
|
||||||
|
status = STATUS_FINDPUBLISHER_START;
|
||||||
|
}
|
||||||
|
else if(strcasecmp(name, "/svg") == 0)
|
||||||
|
{
|
||||||
|
status = STATUS_FAILED;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case STATUS_FINDPUBLISHER_START:
|
||||||
|
{
|
||||||
|
if(strcasecmp(name, "dc:publisher") == 0)
|
||||||
|
{
|
||||||
|
status = STATUS_FINDPUBLISHER_STOP;
|
||||||
|
info.publisher_start = stream_pos + strlen("<dc:publisher>");
|
||||||
|
}
|
||||||
|
else if(strcasecmp(name, "/metadata") == 0)
|
||||||
|
{
|
||||||
|
status = STATUS_FAILED;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case STATUS_FINDPUBLISHER_STOP:
|
||||||
|
{
|
||||||
|
if(strcasecmp(name, "/dc:publisher") == 0)
|
||||||
|
{
|
||||||
|
info.publisher_stop = stream_pos;
|
||||||
|
publisher = xml_stripTags(info.publisher_start, info.publisher_stop-info.publisher_start);
|
||||||
|
if(strcasecmp(publisher, "one-canvas") == 0)
|
||||||
|
status = STATUS_FINDHIDDEN;
|
||||||
|
else
|
||||||
|
status = STATUS_FAILED;
|
||||||
|
}
|
||||||
|
else if(strcasecmp(name, "/metadata") == 0)
|
||||||
|
{
|
||||||
|
status = STATUS_FAILED;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case STATUS_FINDHIDDEN:
|
||||||
|
{
|
||||||
|
if(strcasecmp(name, "g") == 0)
|
||||||
|
{
|
||||||
|
if(xml_idMatch(stream_pos, "hidden"))
|
||||||
|
{
|
||||||
|
char *style_start;
|
||||||
|
|
||||||
|
info.hidden_start = stream_pos;
|
||||||
|
info.hidden_stop = info.hidden_start;
|
||||||
|
style_start = xml_getTagAttributePtr(stream_pos, "style");
|
||||||
|
if(style_start)
|
||||||
|
{
|
||||||
|
info.hidden_start = style_start;
|
||||||
|
info.hidden_stop = strchr(style_start, '"')+1;
|
||||||
|
info.hidden_stop = strchr(info.hidden_stop, '"')+1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
info.hidden_start += strlen("<g ");
|
||||||
|
info.hidden_stop += strlen("<g ");
|
||||||
|
}
|
||||||
|
status = STATUS_FINDBOUNDS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case STATUS_FINDBOUNDS:
|
||||||
|
{
|
||||||
|
if(strcasecmp(name, "rect") == 0)
|
||||||
|
{
|
||||||
|
char *layer_name = xml_idMatchStart(stream_pos, "iconlayer-");
|
||||||
|
|
||||||
|
if(layer_name != NULL)
|
||||||
|
{
|
||||||
|
IconSVG *icon = (IconSVG *) malloc(sizeof(IconSVG));
|
||||||
|
|
||||||
|
icon->x = xml_getTagAttributeFloat(stream_pos, "x");
|
||||||
|
icon->y = xml_getTagAttributeFloat(stream_pos, "y");
|
||||||
|
icon->width = xml_getTagAttributeFloat(stream_pos, "width");
|
||||||
|
icon->height = xml_getTagAttributeFloat(stream_pos, "height");
|
||||||
|
sscanf(layer_name, "iconlayer-%dx%d", &(icon->icon_width), &(icon->icon_height));
|
||||||
|
free(layer_name);
|
||||||
|
status = STATUS_FINDBOUNDS;
|
||||||
|
info.iconlist = (IconSVG **) realloc(info.iconlist, (info.iconlist_num+1)*sizeof(IconSVG *));
|
||||||
|
info.iconlist[info.iconlist_num] = icon;
|
||||||
|
info.iconlist_num++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(strcasecmp(name, "/g") == 0)
|
||||||
|
{
|
||||||
|
status = STATUS_DONE;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(status == STATUS_DONE || status == STATUS_FAILED)
|
||||||
|
break;
|
||||||
|
stream_pos = xml_nextTag(stream_pos);
|
||||||
|
}
|
||||||
|
free(publisher);
|
||||||
|
info.status = status;
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Obtain a single icon from the "one-canvas" stream corresponding
|
||||||
|
* to a particular icon size.
|
||||||
|
*/
|
||||||
|
char *onecanvas_geticon_bysize(char *icon_data, int requested_size)
|
||||||
|
{
|
||||||
|
OneCanvasIconInfo info = onecanvas_geticons(icon_data);
|
||||||
|
char *ret = NULL;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if(info.status == STATUS_DONE && info.iconlist_num > 0)
|
||||||
|
{
|
||||||
|
int closest_diff = abs(info.iconlist[0]->icon_width - requested_size);
|
||||||
|
int tocoord_length, topubl_length, tohidden_length;
|
||||||
|
int icon_id = 0;
|
||||||
|
IconSVG *icon;
|
||||||
|
int ret_max;
|
||||||
|
|
||||||
|
for(i=0;i<info.iconlist_num;i++)
|
||||||
|
{
|
||||||
|
int size_diff = abs(info.iconlist[i]->icon_width - requested_size);
|
||||||
|
|
||||||
|
if(size_diff < closest_diff)
|
||||||
|
{
|
||||||
|
closest_diff = size_diff;
|
||||||
|
icon_id = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
icon = info.iconlist[icon_id];
|
||||||
|
/* Note: 200 characters is a very generous over estimate for the data we add in */
|
||||||
|
ret_max = strlen(icon_data)+1+200;
|
||||||
|
ret = (char *) malloc(ret_max);
|
||||||
|
tocoord_length = info.coordinate_start-icon_data;
|
||||||
|
snprintf(ret, ret_max, "%.*s", tocoord_length, icon_data);
|
||||||
|
/* Output the coordinates of the icon */
|
||||||
|
snprintf(&ret[strlen(ret)], ret_max-strlen(ret), "\nx=\"0px\"\ny=\"0px\"\n");
|
||||||
|
snprintf(&ret[strlen(ret)], ret_max-strlen(ret), "width=\"%d\"\n", icon->icon_width);
|
||||||
|
snprintf(&ret[strlen(ret)], ret_max-strlen(ret), "height=\"%d\"\n", icon->icon_height);
|
||||||
|
snprintf(&ret[strlen(ret)], ret_max-strlen(ret), "viewBox=\"%lf %lf %lf %lf\"\n", icon->x, icon->y, icon->width, icon->height);
|
||||||
|
topubl_length = info.publisher_start-info.coordinate_stop;
|
||||||
|
snprintf(&ret[strlen(ret)], ret_max-strlen(ret), "%.*s", topubl_length, info.coordinate_stop);
|
||||||
|
/* Hide the "hidden" layer */
|
||||||
|
tohidden_length = info.hidden_start-info.publisher_stop;
|
||||||
|
snprintf(&ret[strlen(ret)], ret_max-strlen(ret), "%.*s", tohidden_length, info.publisher_stop);
|
||||||
|
snprintf(&ret[strlen(ret)], ret_max-strlen(ret), "\ndisplay=\"none\"\n");
|
||||||
|
/* Output the rest of the document */
|
||||||
|
snprintf(&ret[strlen(ret)], ret_max-strlen(ret), "%s", info.hidden_stop);
|
||||||
|
}
|
||||||
|
for(i=0;i<info.iconlist_num;i++)
|
||||||
|
free(info.iconlist[i]);
|
||||||
|
free(info.iconlist);
|
||||||
|
return ret;
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
#ifndef __ONECANVAS_H
|
||||||
|
#define __ONECANVAS_H
|
||||||
|
|
||||||
|
char *onecanvas_geticon_bysize(char *icon_data, int requested_size);
|
||||||
|
|
||||||
|
#endif /* __ONECANVAS_H */
|
@ -0,0 +1,317 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009 Erich Hoover
|
||||||
|
*
|
||||||
|
* libr temp files - Handle temporary files and handles that require cleanup
|
||||||
|
* when libr closes.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* To provide feedback, report bugs, or otherwise contact me:
|
||||||
|
* ehoover at mines dot edu
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "tempfiles.h"
|
||||||
|
|
||||||
|
/* For malloc/free and mkdtemp */
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* For string handling */
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/* For directory cleanup */
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
|
||||||
|
/* For directory creation */
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#ifndef FALSE
|
||||||
|
#define FALSE 0
|
||||||
|
#endif
|
||||||
|
#ifndef TRUE
|
||||||
|
#define TRUE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||||
|
|
||||||
|
/* Hold on to folder names for cleanup when libr is removed from memory */
|
||||||
|
typedef struct CLEANUPFOLDER {
|
||||||
|
char *folder;
|
||||||
|
struct CLEANUPFOLDER *next;
|
||||||
|
} CleanupFolder;
|
||||||
|
CleanupFolder *folders_to_remove = NULL;
|
||||||
|
|
||||||
|
/* Hold on to libr handles for cleanup when libr is removed from memory */
|
||||||
|
typedef struct CLEANUPHANDLE {
|
||||||
|
int internal; /* do not warn the user about cleaning this handle up */
|
||||||
|
libr_file *handle;
|
||||||
|
struct CLEANUPHANDLE *next;
|
||||||
|
} CleanupHandle;
|
||||||
|
CleanupHandle *handles_to_remove = NULL;
|
||||||
|
|
||||||
|
#endif /* DOXYGEN_SHOULD_SKIP_THIS */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Register a folder for cleanup when libr is removed from memory
|
||||||
|
*/
|
||||||
|
void register_folder_cleanup(char *temp_folder)
|
||||||
|
{
|
||||||
|
CleanupFolder *folder = malloc(sizeof(CleanupFolder));
|
||||||
|
|
||||||
|
folder->folder = strdup(temp_folder);
|
||||||
|
folder->next = NULL;
|
||||||
|
if(folders_to_remove != NULL)
|
||||||
|
{
|
||||||
|
CleanupFolder *f;
|
||||||
|
|
||||||
|
for(f = folders_to_remove; f->next != NULL; f = f->next) {}
|
||||||
|
f->next = folder;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
folders_to_remove = folder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Register a libr handle for cleanup when libr is removed from memory
|
||||||
|
*/
|
||||||
|
void register_handle_cleanup(libr_file *handle)
|
||||||
|
{
|
||||||
|
CleanupHandle *h = malloc(sizeof(CleanupHandle));
|
||||||
|
|
||||||
|
h->handle = handle;
|
||||||
|
h->internal = FALSE;
|
||||||
|
h->next = NULL;
|
||||||
|
if(handles_to_remove != NULL)
|
||||||
|
{
|
||||||
|
CleanupHandle *i;
|
||||||
|
|
||||||
|
for(i = handles_to_remove; i->next != NULL; i = i->next) {}
|
||||||
|
i->next = h;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
handles_to_remove = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove a libr handle from the cleanup list
|
||||||
|
*/
|
||||||
|
void unregister_handle_cleanup(libr_file *handle)
|
||||||
|
{
|
||||||
|
CleanupHandle *i, *last = NULL;
|
||||||
|
int found = FALSE;
|
||||||
|
|
||||||
|
if(handles_to_remove == NULL)
|
||||||
|
{
|
||||||
|
printf("Unregistering handle with no list of cleanup handles!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for(i = handles_to_remove; i != NULL; last = i, i = i->next)
|
||||||
|
{
|
||||||
|
if(i->handle == handle)
|
||||||
|
{
|
||||||
|
if(last == NULL)
|
||||||
|
handles_to_remove = i->next;
|
||||||
|
else
|
||||||
|
last->next = i->next;
|
||||||
|
free(i);
|
||||||
|
found = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!found)
|
||||||
|
printf("Could not find handle to remove from cleanup list!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Flag a handle as internal (do not warn about unsafe cleanup)
|
||||||
|
*/
|
||||||
|
void register_internal_handle(libr_file *handle)
|
||||||
|
{
|
||||||
|
int found = FALSE;
|
||||||
|
CleanupHandle *i;
|
||||||
|
|
||||||
|
if(handles_to_remove == NULL)
|
||||||
|
{
|
||||||
|
printf("No cleanup list!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for(i = handles_to_remove; i != NULL; i = i->next)
|
||||||
|
{
|
||||||
|
if(i->handle == handle)
|
||||||
|
{
|
||||||
|
i->internal = TRUE;
|
||||||
|
found = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!found)
|
||||||
|
printf("Could not find handle in cleanup list!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cleanup a temporary folder used to hack the inability to load resources from a buffer
|
||||||
|
*/
|
||||||
|
void cleanup_folder(char *temp_folder)
|
||||||
|
{
|
||||||
|
char *filepath = (char *) malloc(PATH_MAX);
|
||||||
|
DIR *dir = opendir(temp_folder);
|
||||||
|
struct dirent *file;
|
||||||
|
|
||||||
|
while((file = readdir(dir)) != NULL)
|
||||||
|
{
|
||||||
|
char *filename = file->d_name;
|
||||||
|
|
||||||
|
/* Do not delete "self" or "parent" directory entries */
|
||||||
|
if(!strcmp(filename, ".") || !strcmp(filename, ".."))
|
||||||
|
continue;
|
||||||
|
/* But delete anything else */
|
||||||
|
strcpy(filepath, temp_folder);
|
||||||
|
strcat(filepath, "/");
|
||||||
|
strcat(filepath, filename);
|
||||||
|
if(file->d_type == DT_DIR)
|
||||||
|
cleanup_folder(filepath);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(unlink(filepath))
|
||||||
|
printf("libr failed to cleanup '%s' in temporary folder: %m\n", filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(filepath);
|
||||||
|
closedir(dir);
|
||||||
|
if(rmdir(temp_folder) != 0)
|
||||||
|
printf("libr failed to remove temporary folder: %m\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Perform cleanup when libr is removed from memory
|
||||||
|
*/
|
||||||
|
void do_cleanup(void) __attribute__((destructor));
|
||||||
|
void do_cleanup(void)
|
||||||
|
{
|
||||||
|
CleanupFolder *f, *fnext;
|
||||||
|
CleanupHandle *h, *hnext;
|
||||||
|
|
||||||
|
/* Cleanup folders */
|
||||||
|
for(f = folders_to_remove; f != NULL; f = fnext)
|
||||||
|
{
|
||||||
|
folders_to_remove = NULL;
|
||||||
|
fnext = f->next;
|
||||||
|
cleanup_folder(f->folder);
|
||||||
|
free(f->folder);
|
||||||
|
free(f);
|
||||||
|
}
|
||||||
|
/* Cleanup handles */
|
||||||
|
for(h = handles_to_remove; h != NULL; h = hnext)
|
||||||
|
{
|
||||||
|
handles_to_remove = NULL;
|
||||||
|
hnext = h->next;
|
||||||
|
/* Unless the handle was created internally then warn the developer to cleanup their act */
|
||||||
|
if(!h->internal)
|
||||||
|
printf("Warning: Application did not cleanup resource handle: %p\n", h->handle);
|
||||||
|
libr_close_internal(h->handle);
|
||||||
|
free(h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Build all the directories required by a resource
|
||||||
|
* (and construct the output string)
|
||||||
|
*/
|
||||||
|
int make_valid_path(char *out_path, size_t maxpath, char *start_folder, char *resource_name)
|
||||||
|
{
|
||||||
|
char *a, *c = resource_name;
|
||||||
|
|
||||||
|
strcpy(out_path, start_folder);
|
||||||
|
while((a=strchr(c, '/')) != NULL)
|
||||||
|
{
|
||||||
|
strcat(out_path, "/");
|
||||||
|
strncat(out_path, c, (size_t) (a-c));
|
||||||
|
if(mkdir(out_path, S_IRUSR|S_IWUSR|S_IXUSR) != 0)
|
||||||
|
{
|
||||||
|
if(errno != EEXIST)
|
||||||
|
{
|
||||||
|
printf("failed to make directory: %s %m\n", out_path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c = a+1;
|
||||||
|
}
|
||||||
|
strcat(out_path, "/");
|
||||||
|
strcat(out_path, c);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extract all the resources from the ELF file for use by the resource loader
|
||||||
|
*/
|
||||||
|
char *libr_extract_resources(libr_file *handle)
|
||||||
|
{
|
||||||
|
char *temp_mask = strdup(LIBR_TEMPFILE);
|
||||||
|
char *temp_folder;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
temp_folder = mkdtemp(temp_mask);
|
||||||
|
if(temp_folder == NULL)
|
||||||
|
{
|
||||||
|
/* failed to extract ELF resources, could not create a temporary path */
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
/* If this library cannot dynamically load resources then pull out all the resources to a temporary directory */
|
||||||
|
for(i=0;i<libr_resources(handle);i++)
|
||||||
|
{
|
||||||
|
char *resource_name = libr_list(handle, i);
|
||||||
|
char *file_path[PATH_MAX];
|
||||||
|
size_t resource_size;
|
||||||
|
FILE *file_handle;
|
||||||
|
char *resource;
|
||||||
|
|
||||||
|
resource = libr_malloc(handle, resource_name, &resource_size);
|
||||||
|
if(!make_valid_path((char *)file_path, sizeof(file_path), temp_folder, resource_name))
|
||||||
|
{
|
||||||
|
/* failed to build the path required by a resource */
|
||||||
|
cleanup_folder(temp_folder);
|
||||||
|
temp_folder = NULL;
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
file_handle = fopen((const char *) file_path, "w");
|
||||||
|
if(file_handle == NULL)
|
||||||
|
{
|
||||||
|
/* failed to extract ELF resources, could not write to temporary path */
|
||||||
|
cleanup_folder(temp_folder);
|
||||||
|
temp_folder = NULL;
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
/* if the resource is empty then fwrite will fail */
|
||||||
|
if( (resource_size != 0) && (fwrite(resource, resource_size, 1, file_handle) != 1) )
|
||||||
|
{
|
||||||
|
/* failed to extract ELF resources, temporary path out of space? */
|
||||||
|
cleanup_folder(temp_folder);
|
||||||
|
temp_folder = NULL;
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
fclose(file_handle);
|
||||||
|
free(resource);
|
||||||
|
}
|
||||||
|
failed:
|
||||||
|
if(temp_folder != NULL)
|
||||||
|
temp_folder = strdup(temp_folder);
|
||||||
|
free(temp_mask);
|
||||||
|
return temp_folder;
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
#ifndef __TEMPFILES_H
|
||||||
|
#define __TEMPFILES_H
|
||||||
|
|
||||||
|
#include "libr.h"
|
||||||
|
|
||||||
|
void cleanup_folder(char *temp_folder);
|
||||||
|
void register_handle_cleanup(libr_file *handle);
|
||||||
|
void unregister_handle_cleanup(libr_file *handle);
|
||||||
|
void register_internal_handle(libr_file *handle);
|
||||||
|
void register_folder_cleanup(char *temp_folder);
|
||||||
|
char *libr_extract_resources(libr_file *handle);
|
||||||
|
|
||||||
|
#endif /* __TEMPFILES_H */
|
Loading…
Reference in new issue