Commit a83c59af authored by Nils Goroll's avatar Nils Goroll

initial

parents
# Matches ALL Makefile and Makefile.in occurrences
Makefile
Makefile.in
stamp-h1
# ...
.deps/
.libs/
*.o
*.lo
*.la
*~
# Various auto-tools artifacts
/aclocal.m4
/autom4te.cache/
/compile
/config.guess
/config.h
/config.h.in
/config.h.in~
/config.log
/config.status
/config.sub
/configure
/configure.lineno
/depcomp
/install-sh
/libtool
/ltmain.sh
/m4/libtool.m4
/m4/ltoptions.m4
/m4/ltsugar.m4
/m4/ltversion.m4
/m4/lt~obsolete.m4
/missing
/varnishapi.pc
TAGS
cscope.*out
# built files
/src/liblongpath.3
/src/longpath.html
/src/longpath_test
/src/longpath_unsafe_test
/src/include/longpath/longpath_config.h
./configure --enable-developer-warnings --enable-debugging-symbols --prefix=/tmp/longpath
liblongpath: wrapper library for long paths exceeding PATH_MAX
Copyright (c) 2013 UPLEX Nils Goroll Systemoptimierung.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the
distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = src
EXTRA_DIST = LICENSE README.rst autogen.sh
MAINTAINERCLEANFILES = $(dist_man_MANS)
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.8: http://docutils.sourceforge.net/" />
<title>liblongpath</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 6387 2010-08-13 12:23:41Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
overflow: hidden;
}
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left, .figure.align-left, object.align-left {
clear: left ;
float: left ;
margin-right: 1em }
img.align-right, .figure.align-right, object.align-right {
clear: right ;
float: right ;
margin-left: 1em }
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left }
.align-center {
clear: both ;
text-align: center }
.align-right {
text-align: right }
/* reset inner alignment in figures */
div.align-right {
text-align: left }
/* div.align-center * { */
/* text-align: left } */
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font: inherit }
pre.literal-block, pre.doctest-block {
margin-left: 2em ;
margin-right: 2em }
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document" id="liblongpath">
<h1 class="title">liblongpath</h1>
<h2 class="subtitle" id="a-wrapper-library-for-handling-very-long-path-names">A wrapper library for handling very long path names</h2>
<div class="section" id="description">
<h1>DESCRIPTION</h1>
<p><em>liblongpath</em> provides, where possible, transparent wrapper functions
of well-known system i/o functions for handling path names longer than
<tt class="docutils literal">PATH_MAX</tt> - overcoming a practical limitation of these functions at
the expense of additional memory consumption and higher system call
overhead for long paths.</p>
<p>The wrapper functions check the length of path arguments and, if they
exceed <tt class="docutils literal">PATH_MAX</tt>, open intermediate directories on the path. A
semantic equivalent of the wrapped function is then executed with the
last relative path element. In most cases, an <tt class="docutils literal">*at</tt> variant of the
wrapped function is used (e.g. <tt class="docutils literal">openat</tt> for
<tt class="docutils literal">open</tt>). Alternatively, some wrapper functions use <tt class="docutils literal">f*</tt> variants
of the wrapped function on a newly opened file descriptor
(e.g. <tt class="docutils literal">fdopendir</tt> for <tt class="docutils literal">opendir</tt>).</p>
</div>
<div class="section" id="installation">
<h1>INSTALLATION</h1>
<p>GNU autotools are used, the standard installation process should work</p>
<pre class="literal-block">
./configure [options]
make
make install
</pre>
</div>
<div class="section" id="usage">
<h1>USAGE</h1>
<p>See <tt class="docutils literal">liblongpath(3)</tt> man page or <tt class="docutils literal">src/liblongpath.rst</tt></p>
</div>
<div class="section" id="support-this-project">
<h1>SUPPORT THIS PROJECT!</h1>
<p>If <em>liblongpath</em> is helpful to you, please support our work. Any
donations are welcome to Paypal account <tt class="docutils literal">nils.goroll at uplex dot
de</tt>.</p>
<p>Please contact me via email if you need an invoice or would like to
donate via bank transfer. At any rate, we promise to properly tax all
donations.</p>
<div class="section" id="commercial-support">
<h2>COMMERCIAL SUPPORT</h2>
<p>If you require commercial support for <em>liblongpath</em> or are interested
in future development, please contact <tt class="docutils literal">info at uplex dot de</tt>.</p>
</div>
</div>
<div class="section" id="license">
<h1>LICENSE</h1>
<p>This document is licensed under the same license as <em>liblongpath</em>
itself. See the distribution's <tt class="docutils literal">LICENSE</tt> file for details</p>
</div>
<div class="section" id="copyright">
<h1>COPYRIGHT</h1>
<p>Copyright (c) 2013 UPLEX Nils Goroll Systemoptimierung.
All rights reserved.</p>
</div>
</div>
</body>
</html>
===========
liblongpath
===========
---------------------------------------------------
A wrapper library for handling very long path names
---------------------------------------------------
DESCRIPTION
===========
*liblongpath* provides, where possible, transparent wrapper functions
of well-known system i/o functions for handling path names longer than
``PATH_MAX`` - overcoming a practical limitation of these functions at
the expense of additional memory consumption and higher system call
overhead for long paths.
The wrapper functions check the length of path arguments and, if they
exceed ``PATH_MAX``, open intermediate directories on the path. A
semantic equivalent of the wrapped function is then executed with the
last relative path element. In most cases, an ``*at`` variant of the
wrapped function is used (e.g. ``openat`` for
``open``). Alternatively, some wrapper functions use ``f*`` variants
of the wrapped function on a newly opened file descriptor
(e.g. ``fdopendir`` for ``opendir``).
INSTALLATION
============
GNU autotools are used, the standard installation process should work
::
./configure [options]
make
make install
USAGE
=====
See ``liblongpath(3)`` man page or ``src/liblongpath.rst``
SUPPORT THIS PROJECT!
=====================
If *liblongpath* is helpful to you, please support our work. Any
donations are welcome to Paypal account ``nils.goroll at uplex dot
de``.
Please contact me via email if you need an invoice or would like to
donate via bank transfer. At any rate, we promise to properly tax all
donations.
COMMERCIAL SUPPORT
------------------
If you require commercial support for *liblongpath* or are interested
in future development, please contact ``info at uplex dot de``.
LICENSE
=======
This document is licensed under the same license as *liblongpath*
itself. See the distribution's ``LICENSE`` file for details
COPYRIGHT
=========
Copyright (c) 2013 UPLEX Nils Goroll Systemoptimierung.
All rights reserved.
#!/bin/sh
#
# $Id$
#
warn() {
echo "WARNING: $@" 1>&2
}
case `uname -s` in
Darwin)
LIBTOOLIZE=glibtoolize
;;
FreeBSD)
LIBTOOLIZE=libtoolize
;;
Linux)
LIBTOOLIZE=libtoolize
;;
SunOS)
LIBTOOLIZE=libtoolize
;;
*)
warn "unrecognized platform:" `uname -s`
LIBTOOLIZE=libtoolize
esac
automake_version=`automake --version | tr ' ' '\n' | egrep '^[0-9]\.[0-9a-z.-]+'`
if [ -z "$automake_version" ] ; then
warn "unable to determine automake version"
else
case $automake_version in
0.*|1.[0-8]|1.[0-8][.-]*)
warn "automake ($automake_version) detected; 1.9 or newer recommended"
;;
*)
;;
esac
fi
set -ex
aclocal -I m4
$LIBTOOLIZE --copy --force
autoheader
automake --add-missing --copy --foreign
autoconf
AC_PREREQ(2.63)
AC_COPYRIGHT([Copyright (c) 2013 UPLEX - Nils Goroll Systemoptimierung])
AC_REVISION([$Id$])
AC_INIT([liblongpath],[master],[nils.goroll@uplex.de])
AC_CONFIG_SRCDIR([src/longpath.c])
AC_CANONICAL_TARGET
AC_LANG(C)
AM_INIT_AUTOMAKE
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4])
AC_USE_SYSTEM_EXTENSIONS
AC_PROG_CC
AC_PROG_CC_STDC
if test "x$ac_cv_prog_cc_c99" = xno; then
AC_MSG_ERROR([Could not find a C99 compatible compiler])
fi
AC_PROG_CPP
AX_PTHREAD(,[AC_MSG_ERROR([Could not configure pthreads support])])
AC_PROG_INSTALL
AC_PROG_LIBTOOL
AC_PROG_MAKE_SET
# Check for rst utilities
AC_CHECK_PROGS(RST2MAN, [rst2man rst2man.py], "no")
if test "x$RST2MAN" = "xno"; then
AC_MSG_WARN([rst2man not found - not building man pages])
fi
AM_CONDITIONAL(HAVE_RST2MAN, [test "x$RST2MAN" != "xno"])
# Checks for header files.
##AC_HEADER_STDC
AC_CHECK_HEADERS_ONCE(
sys/stdlib.h
sys/types.h
sys/stat.h
fcntl.h
assert.h
string.h
limits.h
errno.h
unistd.h
stdio.h
stdlib.h
sys/varargs.h
stdarg.h
dirent.h
sys/mkdev.h
)
## functions we currently require.
AC_CHECK_FUNC([openat], [], [
echo "this library requires (most) *at system calls";
exit -1])
AC_CHECK_FUNC([renameat], [], [
echo "this library requires (most) *at system calls";
exit -1])
AC_CHECK_FUNC([fchmod], [], [
echo "fchmod required";
exit -1])
AC_CHECK_FUNC([fchdir], [], [
echo "fchdir required";
exit -1])
AC_CHECK_FUNC([fdopendir], [], [
echo "fdopendir required";
exit -1])
## functions we currently require, but for which we probably could
## have more fallback code
## for example using f* functions, opening the fd ourselves
## (as long as we have openat)
AC_CHECK_FUNC([fchownat], [], [
echo "this library requires (most) *at functions";
exit -1])
AC_CHECK_FUNC([fstatat], [], [
echo "this library requires (most) *at functions";
exit -1])
AC_CHECK_FUNC([mktemp], [], [
echo "this library requires (most) *at functions";
exit -1])
AC_CHECK_FUNC([utimensat], [], [
echo "this library requires (most) *at functions";
exit -1])
## functions for which we have (some) fallback code
AC_CHECK_FUNCS_ONCE(
linkat
unlinkat
symlinkat
readlinkat
mknodat
mkfifoat
mkdirat
attropen
fgetxattr
fsetxattr
)
## not yet checked
# This corresponds to FreeBSD's WARNS level 6
DEVELOPER_CFLAGS="-Wall -Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wshadow -Wcast-align -Wunused-parameter -Wchar-subscripts -Winline -Wnested-externs -Wredundant-decls -Wformat"
# Additional flags for GCC 4
EXTRA_DEVELOPER_CFLAGS="-Wextra -Wno-missing-field-initializers -Wno-sign-compare"
# --enable-developer-warnings
AC_ARG_ENABLE(developer-warnings,
AS_HELP_STRING([--enable-developer-warnings],[enable strict warnings (default is NO)]),
CFLAGS="${CFLAGS} ${DEVELOPER_CFLAGS}")
# --enable-debugging-symbols
AC_ARG_ENABLE(debugging-symbols,
AS_HELP_STRING([--enable-debugging-symbols],[enable debugging symbols (default is NO)]),
CFLAGS="${CFLAGS} -O0 -g -fno-inline")
# --enable-diagnostics
AC_ARG_ENABLE(diagnostics,
AS_HELP_STRING([--enable-diagnostics],[enable run-time diagnostics (default is NO)]),
CFLAGS="${CFLAGS} -DDIAGNOSTICS")
# --enable-extra-developer-warnings
AC_ARG_ENABLE(extra-developer-warnings,
AS_HELP_STRING([--enable-extra-developer-warnings],[enable even stricter warnings (default is NO)]),
[],
[enable_extra_developer_warnings=no])
if test "x$enable_stack_protector" != "xno"; then
save_CFLAGS="$CFLAGS"
CFLAGS="${CFLAGS} ${EXTRA_DEVELOPER_CFLAGS}"
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([],[],[])],
[],
[AC_MSG_WARN([All of ${EXTRA_DEVELOPER_CFLAGS} not supported, disabling])
CFLAGS="$save_CFLAGS"])
fi
# --enable-stack-protector
AC_ARG_ENABLE(stack-protector,
AS_HELP_STRING([--enable-stack-protector],[enable stack protector (default is NO)]),
[],
[enable_stack_protector=no])
if test "x$enable_stack_protector" != "xno"; then
save_CFLAGS="$CFLAGS"
CFLAGS="${CFLAGS} -fstack-protector-all"
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([],[],[])],
[],
[AC_MSG_WARN([-fstack-protector not supported, disabling])
CFLAGS="$save_CFLAGS"])
fi
# --enable-tests
AC_ARG_ENABLE(tests,
AS_HELP_STRING([--enable-tests],[build test programs (default is NO)]))
AM_CONDITIONAL([ENABLE_TESTS], [test x$enable_tests = xyes])
# --enable-werror
AC_ARG_ENABLE(werror,
AS_HELP_STRING([--enable-werror],[use -Werror (default is NO)]),
CFLAGS="${CFLAGS} -Werror")
AC_CONFIG_FILES([
Makefile
src/Makefile
src/include/Makefile
])
AC_OUTPUT
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_pthread.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
#
# DESCRIPTION
#
# This macro figures out how to build C programs using POSIX threads. It
# sets the PTHREAD_LIBS output variable to the threads library and linker
# flags, and the PTHREAD_CFLAGS output variable to any special C compiler
# flags that are needed. (The user can also force certain compiler
# flags/libs to be tested by setting these environment variables.)
#
# Also sets PTHREAD_CC to any special C compiler that is needed for
# multi-threaded programs (defaults to the value of CC otherwise). (This
# is necessary on AIX to use the special cc_r compiler alias.)
#
# NOTE: You are assumed to not only compile your program with these flags,
# but also link it with them as well. e.g. you should link with
# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
#
# If you are only building threads programs, you may wish to use these
# variables in your default LIBS, CFLAGS, and CC:
#
# LIBS="$PTHREAD_LIBS $LIBS"
# CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
# CC="$PTHREAD_CC"
#
# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
# has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name
# (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
#
# ACTION-IF-FOUND is a list of shell commands to run if a threads library
# is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it
# is not found. If ACTION-IF-FOUND is not specified, the default action
# will define HAVE_PTHREAD.
#
# Please let the authors know if this macro fails on any platform, or if
# you have any other suggestions or comments. This macro was based on work
# by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help
# from M. Frigo), as well as ac_pthread and hb_pthread macros posted by
# Alejandro Forero Cuervo to the autoconf macro repository. We are also
# grateful for the helpful feedback of numerous users.
#
# LICENSE
#
# Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation, either version 3 of the License, or (at your
# option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
#
# As a special exception, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
# scripts that are the output of Autoconf when processing the Macro. You
# need not follow the terms of the GNU General Public License when using
# or distributing such scripts, even though portions of the text of the
# Macro appear in them. The GNU General Public License (GPL) does govern
# all other use of the material that constitutes the Autoconf Macro.
#
# This special exception to the GPL applies to versions of the Autoconf
# Macro released by the Autoconf Archive. When you make and distribute a
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
#serial 7
AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
AC_DEFUN([AX_PTHREAD], [
AC_REQUIRE([AC_CANONICAL_HOST])
AC_LANG_SAVE
AC_LANG_C
ax_pthread_ok=no
# We used to check for pthread.h first, but this fails if pthread.h
# requires special compiler flags (e.g. on True64 or Sequent).
# It gets checked for in the link test anyway.
# First of all, check if the user has set any of the PTHREAD_LIBS,
# etcetera environment variables, and if threads linking works using
# them:
if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
save_LIBS="$LIBS"
LIBS="$PTHREAD_LIBS $LIBS"
AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
AC_TRY_LINK_FUNC(pthread_join, ax_pthread_ok=yes)
AC_MSG_RESULT($ax_pthread_ok)
if test x"$ax_pthread_ok" = xno; then
PTHREAD_LIBS=""
PTHREAD_CFLAGS=""
fi
LIBS="$save_LIBS"
CFLAGS="$save_CFLAGS"
fi
# We must check for the threads library under a number of different
# names; the ordering is very important because some systems
# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
# libraries is broken (non-POSIX).
# Create a list of thread flags to try. Items starting with a "-" are
# C compiler flags, and other items are library names, except for "none"
# which indicates that we try without any flags at all, and "pthread-config"
# which is a program returning the flags for the Pth emulation library.
ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
# The ordering *is* (sometimes) important. Some notes on the
# individual items follow:
# pthreads: AIX (must check this before -lpthread)
# none: in case threads are in libc; should be tried before -Kthread and
# other compiler flags to prevent continual compiler warnings
# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
# -pthreads: Solaris/gcc
# -mthreads: Mingw32/gcc, Lynx/gcc
# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
# doesn't hurt to check since this sometimes defines pthreads too;
# also defines -D_REENTRANT)
# ... -mt is also the pthreads flag for HP/aCC
# pthread: Linux, etcetera
# --thread-safe: KAI C++
# pthread-config: use pthread-config program (for GNU Pth library)
case "${host_cpu}-${host_os}" in
*solaris*)
# On Solaris (at least, for some versions), libc contains stubbed
# (non-functional) versions of the pthreads routines, so link-based
# tests will erroneously succeed. (We need to link with -pthreads/-mt/
# -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
# a function called by this macro, so we could check for that, but
# who knows whether they'll stub that too in a future libc.) So,
# we'll just look for -pthreads and -lpthread first:
ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags"
;;
*-darwin*)
acx_pthread_flags="-pthread $acx_pthread_flags"
;;
esac
if test x"$ax_pthread_ok" = xno; then
for flag in $ax_pthread_flags; do
case $flag in
none)
AC_MSG_CHECKING([whether pthreads work without any flags])
;;
-*)
AC_MSG_CHECKING([whether pthreads work with $flag])
PTHREAD_CFLAGS="$flag"
;;
pthread-config)
AC_CHECK_PROG(ax_pthread_config, pthread-config, yes, no)
if test x"$ax_pthread_config" = xno; then continue; fi
PTHREAD_CFLAGS="`pthread-config --cflags`"
PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
;;
*)
AC_MSG_CHECKING([for the pthreads library -l$flag])
PTHREAD_LIBS="-l$flag"
;;
esac
save_LIBS="$LIBS"
save_CFLAGS="$CFLAGS"
LIBS="$PTHREAD_LIBS $LIBS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
# Check for various functions. We must include pthread.h,
# since some functions may be macros. (On the Sequent, we
# need a special flag -Kthread to make this header compile.)
# We check for pthread_join because it is in -lpthread on IRIX
# while pthread_create is in libc. We check for pthread_attr_init
# due to DEC craziness with -lpthreads. We check for
# pthread_cleanup_push because it is one of the few pthread
# functions on Solaris that doesn't have a non-functional libc stub.
# We try pthread_create on general principles.
AC_TRY_LINK([#include <pthread.h>
static void routine(void* a) {a=0;}
static void* start_routine(void* a) {return a;}],
[pthread_t th; pthread_attr_t attr;
pthread_join(th, 0);
pthread_attr_init(&attr);
pthread_cleanup_push(routine, 0);
pthread_create(&th,0,start_routine,0);
pthread_cleanup_pop(0); ],
[ax_pthread_ok=yes])
LIBS="$save_LIBS"
CFLAGS="$save_CFLAGS"
AC_MSG_RESULT($ax_pthread_ok)
if test "x$ax_pthread_ok" = xyes; then
break;
fi
PTHREAD_LIBS=""
PTHREAD_CFLAGS=""
done
fi
# Various other checks:
if test "x$ax_pthread_ok" = xyes; then
save_LIBS="$LIBS"
LIBS="$PTHREAD_LIBS $LIBS"
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
# Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
AC_MSG_CHECKING([for joinable pthread attribute])
attr_name=unknown
for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
AC_TRY_LINK([#include <pthread.h>], [int attr=$attr; return attr;],
[attr_name=$attr; break])
done
AC_MSG_RESULT($attr_name)
if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name,
[Define to necessary symbol if this constant
uses a non-standard name on your system.])
fi
AC_MSG_CHECKING([if more special flags are required for pthreads])
flag=no
case "${host_cpu}-${host_os}" in
*-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";;
*solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";;
esac
AC_MSG_RESULT(${flag})
if test "x$flag" != xno; then
PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
fi
LIBS="$save_LIBS"
CFLAGS="$save_CFLAGS"
# More AIX lossage: must compile with xlc_r or cc_r
if test x"$GCC" != xyes; then
AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC})
else
PTHREAD_CC=$CC
fi
else
PTHREAD_CC="$CC"
fi
AC_SUBST(PTHREAD_LIBS)
AC_SUBST(PTHREAD_CFLAGS)
AC_SUBST(PTHREAD_CC)
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
if test x"$ax_pthread_ok" = xyes; then
ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])
:
else
ax_pthread_ok=no
$2
fi
AC_LANG_RESTORE
])dnl AX_PTHREAD
# ld-version-script.m4 serial 3
dnl Copyright (C) 2008-2013 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
dnl From Simon Josefsson
# FIXME: The test below returns a false positive for mingw
# cross-compiles, 'local:' statements does not reduce number of
# exported symbols in a DLL. Use --disable-ld-version-script to work
# around the problem.
# gl_LD_VERSION_SCRIPT
# --------------------
# Check if LD supports linker scripts, and define automake conditional
# HAVE_LD_VERSION_SCRIPT if so.
AC_DEFUN([gl_LD_VERSION_SCRIPT],
[
AC_ARG_ENABLE([ld-version-script],
AS_HELP_STRING([--enable-ld-version-script],
[enable linker version script (default is enabled when possible)]),
[have_ld_version_script=$enableval], [])
if test -z "$have_ld_version_script"; then
AC_MSG_CHECKING([if LD -Wl,--version-script works])
save_LDFLAGS="$LDFLAGS"
LDFLAGS="$LDFLAGS -Wl,--version-script=conftest.map"
cat > conftest.map <<EOF
foo
EOF
AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])],
[accepts_syntax_errors=yes], [accepts_syntax_errors=no])
if test "$accepts_syntax_errors" = no; then
cat > conftest.map <<EOF
VERS_1 {
global: sym;
};
VERS_2 {
global: sym;
} VERS_1;
EOF
AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])],
[have_ld_version_script=yes], [have_ld_version_script=no])
else
have_ld_version_script=no
fi
rm -f conftest.map
LDFLAGS="$save_LDFLAGS"
AC_MSG_RESULT($have_ld_version_script)
fi
AM_CONDITIONAL(HAVE_LD_VERSION_SCRIPT, test "$have_ld_version_script" = "yes")
])
SUBDIRS = include
AM_CPPFLAGS = -Iinclude
CLEANFILES = cscope.in.out cscope.out cscope.po.out
EXTRA_DIST = LICENSE autogen.sh varnishapi.pc.in
DISTCHECK_CONFIGURE_FLAGS = \
--enable-developer-warnings \
--enable-debugging-symbols \
--enable-dependency-tracking \
--enable-diagnostics \
--enable-extra-developer-warnings \
--enable-tests \
--enable-werror
AM_LDFLAGS = $(AM_LT_LDFLAGS)
lib_LTLIBRARIES = liblongpath.la liblongpath_unsafe.la
liblongpath_includes = \
include/longpath/longpath.h \
include/longpath/longpath_config.h
liblongpath_la_CFLAGS = $(AM_CFLAGS) $(PTHREAD_CFLAGS)
liblongpath_la_LDFLAGS = $(AM_LDFLAGS) $(PTHREAD_LDLAGS) \
-export-dynamic -avoid-version -shared
liblongpath_la_SOURCES = \
$(liblongpath_includes) \
longpath.c
liblongpath_unsafe_la_CFLAGS = $(AM_CFLAGS) -DUSE_CHDIR_FALLBACK
liblongpath_unsafe_la_LDFLAGS = $(AM_LDFLAGS) \
-export-dynamic -avoid-version -shared
liblongpath_unsafe_la_SOURCES = $(liblongpath_la_SOURCES)
## TEST - XXX make a proper test directory etc
bin_PROGRAMS = longpath_test longpath_unsafe_test
longpath_test_SOURCES = \
$(liblongpath_includes) \
test.c
longpath_test_CFLAGS = $(AM_CFLAGS) -DTEST
longpath_test_LDADD = liblongpath.la
longpath_unsafe_test_SOURCES = $(longpath_test_SOURCES)
longpath_unsafe_test_CFLAGS = $(AM_CFLAGS) -DTEST -DUSE_CHDIR_FALLBACK
longpath_unsafe_test_LDADD = liblongpath_unsafe.la
cscope:
-rm -f cscope*
find . -name '*.[hcS]' > cscope.files
cscope -b
.PHONY: cscope
dist_man_MANS = liblongpath.3
liblongpath.3: liblongpath.rst
if HAVE_RST2MAN
${RST2MAN} $? $@
else
@echo "========================================"
@echo "You need rst2man installed to make dist"
@echo "========================================"
@false
endif
nobase_dist_include_HEADERS = \
longpath/longpath_redefine_post.h \
longpath/longpath_redefine_defs.h \
longpath/longpath_redefine_impl.h \
longpath/longpath_redefine_pre.h \
longpath/longpath.h \
longpath/longpath_config.h
longpath/longpath_config.h: ../../config.h
echo '/* THIS FILE IS AUTO-GENERATED, DO NOT EDIT */' \
>longpath/longpath_config.h
egrep '^#define HAVE_' ../../config.h \
| sed -e 's: [^ ]*$$::' -e 's:^#define:#undef:' \
>>longpath/longpath_config.h
egrep '^#define HAVE_' ../../config.h \
>>longpath/longpath_config.h
CLEANFILES = longpath/longpath_config.h
\ No newline at end of file
/*-
* Copyright (c) 2013 UPLEX Nils Goroll Systemoptimierung
* All rights reserved
*
* Author: Nils Goroll <nils.goroll@uplex.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
/*
* structure taken from OpenSolaris fcntl.h
*/
#ifndef _LONGPATH_H
#define _LONGPATH_H
#include "longpath_config.h"
/*
* XXX HACK: This prevents the solaris includes to win the redefine_extname race
* -- is there a better way ?
*/
#if defined(_LONGPATH_REDEFINE_PRE_H) && defined(__PRAGMA_REDEFINE_EXTNAME)
#define __PRAGMA_REDEFINE_EXTNAME_SAVE
#undef __PRAGMA_REDEFINE_EXTNAME
#endif
// XXX conditional includes incomplete
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
// mktemp
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#include <utime.h> // utimbuf
// stdlib stuff
#include <dirent.h>
#ifdef __PRAGMA_REDEFINE_EXTNAME_SAVE
#undef __PRAGMA_REDEFINE_EXTNAME_SAVE
#define __PRAGMA_REDEFINE_EXTNAME
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifdef DEBUG_LF
#ifdef _FILE_OFFSET_BITS
# if (_FILE_OFFSET_BITS == 64)
# warning _FILE_OFFSET_BITS == 64
# elif (_FILE_OFFSET_BITS == 32)
# warning _FILE_OFFSET_BITS == 32
# else
# warning _FILE_OFFSET_BITS other value
# endif
#else
#warning _FILE_OFFSET_BITS UN_defined
#endif
#ifdef _LARGEFILE64_SOURCE
#warning _LARGEFILE64_SOURCE defined
#else
#warning _LARGEFILE64_SOURCE UN_defined
#endif
#ifdef _LARGEFILE_SOURCE
#warning _LARGEFILE_SOURCE defined
#else
#warning _LARGEFILE_SOURCE UN_defined
#endif
#ifdef _LP64
#warning _LP64 defined
#else
#warning _LP64 UN_defined
#endif
#endif /* DEBUG_LF */
/* from solaris sys/feature_tests.h */
#if defined(_LP64)
#ifndef _FILE_OFFSET_BITS
#define _FILE_OFFSET_BITS 64
#endif
#if _FILE_OFFSET_BITS - 0 != 64
#error "invalid _FILE_OFFSET_BITS value specified"
#endif
#else /* _LP64 */
#ifndef _FILE_OFFSET_BITS
#define _FILE_OFFSET_BITS 32
#endif
#if _FILE_OFFSET_BITS - 0 != 32 && _FILE_OFFSET_BITS - 0 != 64
#error "invalid _FILE_OFFSET_BITS value specified"
#endif
#endif /* _LP64 */
/* large file compilation environment setup */
/* func -> func64 */
#if !defined(_LP64) && _FILE_OFFSET_BITS == 64
#ifdef __PRAGMA_REDEFINE_EXTNAME
#pragma redefine_extname openl openl64
#pragma redefine_extname creatl creatl64
#pragma redefine_extname statl statl64
#if defined(__EXTENSIONS__) || !defined(__XOPEN_OR_POSIX) || \
defined(_ATFILE_SOURCE)
#pragma redefine_extname openatl openatl64
#ifdef HAVE_ATTROPEN
#pragma redefine_extname attropenl attropenl64
#endif
#pragma redefine_extname fstatatl fstatatl64
#endif /* defined(__EXTENSIONS__) || !defined(__XOPEN_OR_POSIX) ... */
#if !defined(__XOPEN_OR_POSIX) || defined(_XPG_2) || defined(__EXTENSIONS__)
#pragma redefine_extname lstatl lstatl64
#endif
#pragma redefine_extname mkstempl mkstempl64
#pragma redefine_extname mkstempsl mkstempsl64
#if defined(_GNU_SOURCE)
#pragma redefine_extname mkostempl mkostempl64
#pragma redefine_extname mkostempsl mkostempsl64
#endif
#else /* __PRAGMA_REDEFINE_EXTNAME */
#define openl openl64
#define creatl creatl64
#define statl statl64
#if defined(__EXTENSIONS__) || !defined(__XOPEN_OR_POSIX) || \
defined(_ATFILE_SOURCE)
#define openatl openatl64
#ifdef HAVE_ATTROPEN
#define attropenl attropenl64
#endif
#define fstatatl fstatatl64
#endif /* defined(__EXTENSIONS__) || !defined(__XOPEN_OR_POSIX) ... */
#if !defined(__XOPEN_OR_POSIX) || defined(_XPG_2) || defined(__EXTENSIONS__)
#define lstatl lstatl64
#endif
#define mkstempl mkstempl64
#define mkstempsl mkstempsl64
#if defined(_GNU_SOURCE)
#define mkostempl mkostempl64
#define mkostempsl mkostempsl64
#endif
#endif /* __PRAGMA_REDEFINE_EXTNAME */
#endif /* !_LP64 && _FILE_OFFSET_BITS == 64 */
/* func64 -> func */
#if defined(_LP64) && defined(_LARGEFILE64_SOURCE)
#ifdef __PRAGMA_REDEFINE_EXTNAME
#pragma redefine_extname openl64 openl
#pragma redefine_extname creatl64 creatl
#pragma redefine_extname statl64 statl
#if defined(__EXTENSIONS__) || !defined(__XOPEN_OR_POSIX) || \
defined(_ATFILE_SOURCE)
#pragma redefine_extname openatl64 openatl
#ifdef HAVE_ATTROPEN
#pragma redefine_extname attropenl64 attropenl
#endif
#pragma redefine_extname fstatatl64 fstatatl
#endif /* defined(__EXTENSIONS__) || !defined(__XOPEN_OR_POSIX) ... */
#if !defined(__XOPEN_OR_POSIX) || defined(_XPG_2) || defined(__EXTENSIONS__)
#pragma redefine_extname lstatl64 lstatl
#endif
#pragma redefine_extname mkstempl64 mkstempl
#pragma redefine_extname mkstempsl64 mkstempsl
#if defined(_GNU_SOURCE)
#pragma redefine_extname mkostempl64 mkostempl
#pragma redefine_extname mkostempsl64 mkostempsl
#endif
#else /* __PRAGMA_REDEFINE_EXTNAME */
#define openl64 openl
#define creatl64 creatl
#define statl64 statl
#if defined(__EXTENSIONS__) || !defined(__XOPEN_OR_POSIX) || \
defined(_ATFILE_SOURCE)
#define openatl64 openatl
#ifdef HAVE_ATTROPEN
#define attropenl64 attropenl
#endif
#define fstatatl64 fstatatl
#endif /* defined(__EXTENSIONS__) || !defined(__XOPEN_OR_POSIX) ... */
#if !defined(__XOPEN_OR_POSIX) || defined(_XPG_2) || defined(__EXTENSIONS__)
#define lstatl64 lstatl
#endif
#define mkstempl64 mkstempl
#define mkstempsl64 mkstempsl
#if defined(_GNU_SOURCE)
#define mkostempl64 mkostempl
#define mkostempsl64 mkostempsl
#endif
#endif /* __PRAGMA_REDEFINE_EXTNAME */
#endif /* _LP64 && _LARGEFILE64_SOURCE */
#if defined(__STDC__)
extern int openl(const char *, int, ...);
extern int creatl(const char *, mode_t);
extern int statl(const char *, struct stat *);
extern int linkl(const char *, const char *);
extern int unlinkl(const char *);
extern int chownl(const char *, uid_t , gid_t);
extern int chmodl(const char *, mode_t);
extern int mknodl(const char *, mode_t , dev_t);
extern int mkfifol(const char *, mode_t);
extern int rmdirl(const char *);
extern int mkdirl(const char *, mode_t);
extern int renamel(const char *, const char *);
extern int utimesl(const char *, const struct timeval *);
extern int lutimesl(const char *, const struct timeval *);
extern int utimel(const char *, const struct utimbuf *);
/* at funcs */
#if defined(__EXTENSIONS__) || !defined(__XOPEN_OR_POSIX) || \
defined(_ATFILE_SOURCE)
extern int openatl(int , const char *, int , mode_t);
#ifdef HAVE_ATTROPEN
extern int attropenl(const char *, const char *, int , ...);
#endif
extern int fstatatl(int, const char *, struct stat *, int);
#if defined(HAVE_LINKAT)
extern int linkatl(int , const char *, int , const char *, int);
#endif
extern int unlinkatl(int , const char *, int);
#if defined(HAVE_SYMLINKAT)
extern int symlinkatl(const char *, int , const char *);
#endif
#if defined(HAVE_READLINKAT)
extern int readlinkatl(int , const char *, char *, size_t);
#endif
extern int fchownatl(int , const char *, uid_t , gid_t , int);
#if defined(HAVE_MKNODAT)
extern int mknodatl(int , const char *, mode_t , dev_t);
#endif
#if defined(HAVE_MKFIFOAT)
extern int mkfifoatl(int , const char *, mode_t);
#endif
extern int rmdiratl(int , const char *);
#if defined(HAVE_MKDIRAT)
extern int mkdiratl(int , const char *, mode_t);
#endif
extern int renameatl(int , const char *, int , const char *);
#endif
/* times at */
#if defined(__EXTENSIONS__) || \
(!defined(_STRICT_STDC) && !defined(__XOPEN_OR_POSIX))
/* || defined(_XPG7) */
extern int futimesatl(int , const char *, const struct timeval *);
extern int utimensatl(int, const char *, const struct timespec *, int);
#endif
/* lstat */
#if !defined(__XOPEN_OR_POSIX) || defined(_XPG_2) || defined(__EXTENSIONS__)
extern int lstatl(const char *, struct stat *);
extern int symlinkl(const char *, const char *);
extern int readlinkl(const char *, char *, size_t);
extern int lchownl(const char *, uid_t , gid_t);
#endif
/* mkstemp */
extern char *mktempl(char *);
extern char *mkdtempl(char *);
extern int mkstempl(char *);
extern int mkstempsl(char *, int);
/* mkstemp GNU */
#if defined(_GNU_SOURCE)
extern int mkostempl(char *, int);
extern int mkostempsl(char *, int , int);
#endif
DIR *opendirl(const char *);
/* linux */
#ifdef HAVE_FGETXATTR
extern ssize_t getxattrl(const char *, const char *, void *, size_t);
extern ssize_t lgetxattrl(const char *, const char *, void *, size_t);
extern int setxattrl(const char *, const char *, const void *, size_t, int);
extern int lsetxattrl(const char *, const char *, const void *, size_t, int);
#endif
/* 64 */
#if defined(_LARGEFILE64_SOURCE) && !((_FILE_OFFSET_BITS == 64) && \
!defined(__PRAGMA_REDEFINE_EXTNAME))
extern int openl64(const char *, int , ...);
extern int creatl64(const char *, mode_t);
extern int statl64(const char *, struct stat64 *);
/* 64 at funcs */
#if defined(__EXTENSIONS__) || !defined(__XOPEN_OR_POSIX) || \
defined(_ATFILE_SOURCE)
extern int openatl64(int , const char *, int , mode_t);
#ifdef HAVE_ATTROPEN
extern int attropenl64(const char *, const char *, int , ...);
#endif
extern int fstatatl64(int , const char *, struct stat64 *, int);
#endif
/* 64 lstat */
#if !defined(__XOPEN_OR_POSIX) || defined(_XPG_2) || defined(__EXTENSIONS__)
extern int lstatl64(const char *, struct stat64 *);
#endif
/* 64 mkstemp*/
extern int mkstempl64(char *);
extern int mkstempsl64(char *, int);
/* 64 mkstemp GNU*/
#if defined(_GNU_SOURCE)
extern int mkostempl64(char *, int);
extern int mkostempsl64(char *, int , int);
#endif
#endif /* 64 */
#else /* defined(__STDC__) */
extern int openl();
extern int creatl();
extern int statl();
extern int linkl();
extern int unlinkl();
extern int chownl();
extern int chmodl();
extern int mknodl();
extern int mkfifol();
extern int rmdirl();
extern int mkdirl();
extern int renamel();
extern int utimesl();
extern int lutimesl();
extern int utimel();
/* at funcs */
#if defined(__EXTENSIONS__) || !defined(__XOPEN_OR_POSIX) || \
defined(_ATFILE_SOURCE)
extern int openatl();
#ifdef HAVE_ATTROPEN
extern int attropenl();
#endif
extern int fstatatl();
#if defined(HAVE_LINKAT)
extern int linkatl();
#endif
extern int unlinkatl();
#if defined(HAVE_SYMLINKAT)
extern int symlinkatl();
#endif
#if defined(HAVE_READLINKAT)
extern int readlinkatl();
#endif
extern int fchownatl();
#if defined(HAVE_MKNODAT)
extern int mknodatl();
#endif
#if defined(HAVE_MKFIFOAT)
extern int mkfifoatl();
#endif
extern int rmdiratl();
#if defined(HAVE_MKDIRAT)
extern int mkdiratl();
#endif
extern int renameatl();
#endif
/* times at */
#if defined(__EXTENSIONS__) || \
(!defined(_STRICT_STDC) && !defined(__XOPEN_OR_POSIX))
/* || defined(_XPG7) */
extern int futimesatl();
extern int utimensatl();
#endif
/* lstat */
#if !defined(__XOPEN_OR_POSIX) || defined(_XPG_2) || defined(__EXTENSIONS__)
extern int lstatl();
extern int symlinkl();
extern int readlinkl();
extern int lchownl();
#endif
/* mkstemp */
extern char *mktempl();
extern char *mkdtempl();
extern int mkstempl();
extern int mkstempsl();
/* mkstemp GNU */
#if defined(_GNU_SOURCE)
extern int mkostempl();
extern int mkostempsl();
#endif
DIR *opendirl();
#ifdef HAVE_FGETXATTR
extern ssize_t getxattrl();
extern ssize_t lgetxattrl();
extern int setxattrl();
extern int lsetxattrl();
#endif
/* 64 */
#if defined(_LARGEFILE64_SOURCE) && !((_FILE_OFFSET_BITS == 64) && \
!defined(__PRAGMA_REDEFINE_EXTNAME))
extern int openl64();
extern int creatl64();
extern int statl64();
/* 64 at funcs */
#if defined(__EXTENSIONS__) || !defined(__XOPEN_OR_POSIX) || \
defined(_ATFILE_SOURCE)
extern int openatl64();
#ifdef HAVE_ATTROPEN
extern int attropenl64();
#endif
extern int fstatatl64();
#endif
/* 64 lstat */
#if !defined(__XOPEN_OR_POSIX) || defined(_XPG_2) || defined(__EXTENSIONS__)
extern int lstatl64();
#endif
/* 64 mkstemp*/
extern int mkstempl64();
extern int mkstempsl64();
/* 64 mkstemp GNU*/
#if defined(_GNU_SOURCE)
extern int mkostempl64();
extern int mkostempsl64();
#endif
#endif /* 64 */
#endif /* defined(__STDC__) */
#endif /* _LONGPATH_H */
/*-
* Copyright (c) 2013 UPLEX Nils Goroll Systemoptimierung
* All rights reserved
*
* Author: Nils Goroll <nils.goroll@uplex.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
/*
* what are sensible default which don't cost too much ram / stack space for
* allocations based on these defines?
*/
#ifdef PATH_MAX
#undef PATH_MAX
#endif
#define PATH_MAX (4*4096)
#ifdef MAXPATHLEN
#undef MAXPATHLEN
#define MAXPATHLEN PATH_MAX
#endif
/*-
* Copyright (c) 2013 UPLEX Nils Goroll Systemoptimierung
* All rights reserved
*
* Author: Nils Goroll <nils.goroll@uplex.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#ifdef _LONGPATH_REDEFINE_IMPL_H
#error "longpath_redefine_impl.h included twice"
#else
#define _LONGPATH_REDEFINE_IMPL_H
#if ((! defined(_LONGPATH_REDEFINE_PRE_H)) && (! defined(_LONGPATH_REDEFINE_POST_H)))
#error "longpath_redefine_impl.h should not be included directly"
#endif
#include "longpath_config.h"
/*
* __PRAGMA_REDEFINE_EXTNAME : _first_ redefinition wins (see gcc/c-pragma.c)
*
* otherwise: _last_ redefinition wins
*
* so longpath_redefine_pre and _post include this dependend upon __PRAGMA_REDEFINE_EXTNAME
*/
/* func -> func64 */
#if !defined(_LP64) && (_FILE_OFFSET_BITS == 64)
#ifdef __PRAGMA_REDEFINE_EXTNAME
#pragma redefine_extname open openl64
#pragma redefine_extname creat creatl64
#pragma redefine_extname stat statl64
#if defined(__EXTENSIONS__) || !defined(__XOPEN_OR_POSIX) || \
defined(_ATFILE_SOURCE)
#pragma redefine_extname openat openatl64
#ifdef HAVE_ATTROPEN
#pragma redefine_extname attropen attropenl64
#endif
#pragma redefine_extname fstatat fstatatl64
#endif /* defined(__EXTENSIONS__) || !defined(__XOPEN_OR_POSIX) ... */
#if !defined(__XOPEN_OR_POSIX) || defined(_XPG_2) || defined(__EXTENSIONS__)
#pragma redefine_extname lstat lstatl64
#endif
#pragma redefine_extname mkstemp mkstempl64
#pragma redefine_extname mkstemps mkstempsl64
#if defined(_GNU_SOURCE)
#pragma redefine_extname mkostemp mkostempl64
#pragma redefine_extname mkostemps mkostempsl64
#endif
#else /* __PRAGMA_REDEFINE_EXTNAME */
#define open openl64
#define creat creatl64
#define stat(p,b) statl64(p,b)
#if defined(__EXTENSIONS__) || !defined(__XOPEN_OR_POSIX) || \
defined(_ATFILE_SOURCE)
#define openat openatl64
#ifdef HAVE_ATTROPEN
#define attropen attropenl64
#endif
#define fstatat fstatatl64
#endif /* defined(__EXTENSIONS__) || !defined(__XOPEN_OR_POSIX) ... */
#if !defined(__XOPEN_OR_POSIX) || defined(_XPG_2) || defined(__EXTENSIONS__)
#define lstat lstatl64
#endif
#define mkstemp mkstempl64
#define mkstemps mkstempsl64
#if defined(_GNU_SOURCE)
#define mkostemp mkostempl64
#define mkostemps mkostempsl64
#endif
#endif /* __PRAGMA_REDEFINE_EXTNAME */
#else /* _LP64 && _FILE_OFFSET_BITS == 64 */
#ifdef __PRAGMA_REDEFINE_EXTNAME
#pragma redefine_extname open openl
#pragma redefine_extname creat creatl
#pragma redefine_extname stat statl
#if defined(__EXTENSIONS__) || !defined(__XOPEN_OR_POSIX) || \
defined(_ATFILE_SOURCE)
#pragma redefine_extname openat openatl
#ifdef HAVE_ATTROPEN
#pragma redefine_extname attropen attropenl
#endif
#pragma redefine_extname fstatat fstatatl
#endif /* defined(__EXTENSIONS__) || !defined(__XOPEN_OR_POSIX) ... */
#if !defined(__XOPEN_OR_POSIX) || defined(_XPG_2) || defined(__EXTENSIONS__)
#pragma redefine_extname lstat lstatl
#endif
#pragma redefine_extname mkstemp mkstempl
#pragma redefine_extname mkstemps mkstempsl
#if defined(_GNU_SOURCE)
#pragma redefine_extname mkostemp mkostempl
#pragma redefine_extname mkostemps mkostempsl
#endif
#else /* __PRAGMA_REDEFINE_EXTNAME */
#define open openl
#define creat creatl
#define stat(p, b) statl(p, b)
#if defined(__EXTENSIONS__) || !defined(__XOPEN_OR_POSIX) || \
defined(_ATFILE_SOURCE)
#define openat openatl
#ifdef HAVE_ATTROPEN
#define attropen attropenl
#endif
#define fstatat fstatatl
#endif /* defined(__EXTENSIONS__) || !defined(__XOPEN_OR_POSIX) ... */
#if !defined(__XOPEN_OR_POSIX) || defined(_XPG_2) || defined(__EXTENSIONS__)
#define lstat lstatl
#endif
#define mkstemp mkstempl
#define mkstemps mkstempsl
#if defined(_GNU_SOURCE)
#define mkostemp mkostempl
#define mkostemps mkostempsl
#endif
#endif /* __PRAGMA_REDEFINE_EXTNAME */
#endif /* _LP64 && _FILE_OFFSET_BITS == 64 */
/* func64 -> func */
#if defined(_LP64) && defined(_LARGEFILE64_SOURCE)
#ifdef __PRAGMA_REDEFINE_EXTNAME
#pragma redefine_extname open64 openl
#pragma redefine_extname creat64 creatl
#pragma redefine_extname stat64 statl
#if defined(__EXTENSIONS__) || !defined(__XOPEN_OR_POSIX) || \
defined(_ATFILE_SOURCE)
#pragma redefine_extname openat64 openatl
#ifdef HAVE_ATTROPEN
#pragma redefine_extname attropen64 attropenl
#endif
#pragma redefine_extname fstatat64 fstatatl
#endif /* defined(__EXTENSIONS__) || !defined(__XOPEN_OR_POSIX) ... */
#if !defined(__XOPEN_OR_POSIX) || defined(_XPG_2) || defined(__EXTENSIONS__)
#pragma redefine_extname lstat64 lstatl
#endif
#pragma redefine_extname mkstemp64 mkstempl
#pragma redefine_extname mkstemps64 mkstempsl
#if defined(_GNU_SOURCE)
#pragma redefine_extname mkostemp64 mkostempl
#pragma redefine_extname mkostemps64 mkostempsl
#endif
#else /* __PRAGMA_REDEFINE_EXTNAME */
#define open64 openl
#define creat64 creatl
#define stat64 statl
#if defined(__EXTENSIONS__) || !defined(__XOPEN_OR_POSIX) || \
defined(_ATFILE_SOURCE)
#define openat64 openatl
#ifdef HAVE_ATTROPEN
#define attropen64 attropenl
#endif
#define fstatat64 fstatatl
#endif /* defined(__EXTENSIONS__) || !defined(__XOPEN_OR_POSIX) ... */
#if !defined(__XOPEN_OR_POSIX) || defined(_XPG_2) || defined(__EXTENSIONS__)
#define lstat64 lstatl
#endif
#define mkstemp64 mkstempl
#define mkstemps64 mkstempsl
#if defined(_GNU_SOURCE)
#define mkostemp64 mkostempl
#define mkostemps64 mkostempsl
#endif
#endif /* __PRAGMA_REDEFINE_EXTNAME */
#endif /* _LP64 && _LARGEFILE64_SOURCE */
/* func- > funcl redefinitions for all which have not been done above */
#ifdef __PRAGMA_REDEFINE_EXTNAME
#pragma redefine_extname link linkl
#pragma redefine_extname unlink unlinkl
#pragma redefine_extname chown chownl
#pragma redefine_extname chmod chmodl
#pragma redefine_extname mknod mknodl
#pragma redefine_extname mkfifo mkfifol
#pragma redefine_extname rmdir rmdirl
#pragma redefine_extname mkdir mkdirl
#pragma redefine_extname rename renamel
#pragma redefine_extname utimes utimesl
#pragma redefine_extname lutimes lutimesl
#pragma redefine_extname utime utimel
/* at funcs */
#if defined(__EXTENSIONS__) || !defined(__XOPEN_OR_POSIX) || \
defined(_ATFILE_SOURCE)
#if defined(HAVE_LINKAT)
#pragma redefine_extname linkat linkatl
#endif
#pragma redefine_extname unlinkat unlinkatl
#if defined(HAVE_SYMLINKAT)
#pragma redefine_extname symlinkat symlinkatl
#endif
#if defined(HAVE_READLINKAT)
#pragma redefine_extname readlinkat readlinkatl
#endif
#pragma redefine_extname fchownat fchownatl
#if defined(HAVE_MKNODAT)
#pragma redefine_extname mknodat mknodatl
#endif
#if defined(HAVE_MKFIFOAT)
#pragma redefine_extname mkfifoat mkfifoatl
#endif
#pragma redefine_extname rmdirat rmdiratl
#if defined(HAVE_MKDIRAT)
#pragma redefine_extname mkdirat mkdiratl
#endif
#pragma redefine_extname renameat renameatl
#endif
/* times at */
#if defined(__EXTENSIONS__) || \
(!defined(_STRICT_STDC) && !defined(__XOPEN_OR_POSIX))
/* || defined(_XPG7) */
#pragma redefine_extname futimesat futimesatl
#pragma redefine_extname utimensat utimensatl
#endif
/* lstat */
#if !defined(__XOPEN_OR_POSIX) || defined(_XPG_2) || defined(__EXTENSIONS__)
#pragma redefine_extname symlink symlinkl
#pragma redefine_extname readlink readlinkl
#pragma redefine_extname lchown lchownl
#endif
/* mkstemp */
#pragma redefine_extname mktemp mktempl
#pragma redefine_extname mkdtemp mkdtempl
/* stdlib */
#pragma redefine_extname opendir opendirl
/* linux */
#ifdef HAVE_FGETXATTR
#pragma redefine_extname getxattr getxattrl
#pragma redefine_extname lgetxattr lgetxattrl
#pragma redefine_extname setxattr setxattrl
#pragma redefine_extname lsetxattr lsetxattrl
#endif
/* 64 */
#if !defined(_LP64)
#pragma redefine_extname open64 openl64
#pragma redefine_extname creat64 creatl64
#pragma redefine_extname stat64 statl64
/* 64 at funcs */
#if defined(__EXTENSIONS__) || !defined(__XOPEN_OR_POSIX) || \
defined(_ATFILE_SOURCE)
#pragma redefine_extname openat64 openatl64
#ifdef HAVE_ATTROPEN
#pragma redefine_extname attropen64 attropenl64
#endif
#pragma redefine_extname fstatat64 fstatatl64
#endif
/* 64 lstat */
#if !defined(__XOPEN_OR_POSIX) || defined(_XPG_2) || defined(__EXTENSIONS__)
#pragma redefine_extname lstat64 lstatl64
#endif
/* 64 mkstemp*/
#pragma redefine_extname mkstemp64 mkstempl64
#pragma redefine_extname mkstemps64 mkstempsl64
/* 64 mkstemp GNU*/
#if defined(_GNU_SOURCE)
#pragma redefine_extname mkostemp64 mkostempl64
#pragma redefine_extname mkostemps64 mkostempsl64
#endif
#endif /* _LP64_ */
#else /* __PRAGMA_REDEFINE_EXTNAME */
#define link linkl
#define unlink unlinkl
#define chown chownl
#define chmod chmodl
#define mknod mknodl
#define mkfifo mkfifol
#define rmdir rmdirl
#define mkdir mkdirl
#define rename renamel
#define utimes utimesl
#define lutimes lutimesl
#define utime utimel
/* at funcs */
#if defined(__EXTENSIONS__) || !defined(__XOPEN_OR_POSIX) || \
defined(_ATFILE_SOURCE)
#if defined(HAVE_LINKAT)
#define linkat linkatl
#endif
#define unlinkat unlinkatl
#if defined(HAVE_SYMLINKAT)
#define symlinkat symlinkatl
#endif
#if defined(HAVE_READLINKAT)
#define readlinkat readlinkatl
#endif
#define fchownat fchownatl
#if defined(HAVE_MKNODAT)
#define mknodat mknodatl
#endif
#if defined(HAVE_MKFIFOAT)
#define mkfifoat mkfifoatl
#endif
#define rmdirat rmdiratl
#if defined(HAVE_MKDIRAT)
#define mkdirat mkdiratl
#endif
#define renameat renameatl
#endif
/* times at */
#if defined(__EXTENSIONS__) || \
(!defined(_STRICT_STDC) && !defined(__XOPEN_OR_POSIX))
/* || defined(_XPG7) */
#define futimesat futimesatl
#define utimensat utimensatl
#endif
/* lstat */
#if !defined(__XOPEN_OR_POSIX) || defined(_XPG_2) || defined(__EXTENSIONS__)
#define symlink symlinkl
#define readlink readlinkl
#define lchown lchownl
#endif
/* mkstemp */
#define mktemp mktempl
#define mkdtemp mkdtempl
/* stdlib */
#define opendir opendirl
/* linux */
#ifdef HAVE_FGETXATTR
#define getxattr getxattrl
#define lgetxattr lgetxattrl
#define setxattr setxattrl
#define lsetxattr lsetxattrl
#endif
/* 64 */
#if !defined(_LP64)
#define open64 openl64
#define creat64 creatl64
#define stat64 statl64
/* 64 at funcs */
#if defined(__EXTENSIONS__) || !defined(__XOPEN_OR_POSIX) || \
defined(_ATFILE_SOURCE)
#define openat64 openatl64
#ifdef HAVE_ATTROPEN
#define attropen64 attropenl64
#endif
#define fstatat64 fstatatl64
#endif
/* 64 lstat */
#if !defined(__XOPEN_OR_POSIX) || defined(_XPG_2) || defined(__EXTENSIONS__)
#define lstat64 lstatl64
#endif
/* 64 mkstemp*/
#define mkstemp64 mkstempl64
#define mkstemps64 mkstempsl64
/* 64 mkstemp GNU*/
#if defined(_GNU_SOURCE)
#define mkostemp64 mkostempl64
#define mkostemps64 mkostempsl64
#endif
#endif /* _LP64_ */
#endif /* __PRAGMA_REDEFINE_EXTNAME */
#include "longpath.h"
#endif /* _LONGPATH_REDEFINE_IMPL_H */
/*-
* Copyright (c) 2013 UPLEX Nils Goroll Systemoptimierung
* All rights reserved
*
* Author: Nils Goroll <nils.goroll@uplex.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#ifndef _LONGPATH_REDEFINE_POST_H
#define _LONGPATH_REDEFINE_POST_H
#ifndef _LONGPATH_REDEFINE_PRE_H
#error "longpath_redefine_pre.h must be included before any system headers"
#endif
#ifndef __PRAGMA_REDEFINE_EXTNAME
// #ifdef __PRAGMA_REDEFINE_EXTNAME
#include "longpath_redefine_impl.h"
#endif
#include "longpath_redefine_defs.h"
#endif /* _LONGPATH_REDEFINE_POST_H */
/*-
* Copyright (c) 2013 UPLEX Nils Goroll Systemoptimierung
* All rights reserved
*
* Author: Nils Goroll <nils.goroll@uplex.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#ifndef _LONGPATH_REDEFINE_PRE_H
#define _LONGPATH_REDEFINE_PRE_H
#ifdef _FCNTL_H
#error "longpath_redefine_pre.h must be included before any system headers"
#endif
#ifdef __PRAGMA_REDEFINE_EXTNAME
// #ifndef __PRAGMA_REDEFINE_EXTNAME
#include "longpath_redefine_impl.h"
#endif
#include "longpath_redefine_defs.h"
#endif /* _LONGPATH_REDEFINE_PRE_H */
===========
liblongpath
===========
---------------------------------------------------
A wrapper library for handling very long path names
---------------------------------------------------
:Author: Nils Goroll
:Date: 2013-08-19
:Version: 0.1
:Manual section: 3
SYNOPSIS
========
::
CC [ flag... ] file... -llongpath [ library... ]
or
::
CC [ flag... ] file... -llongpath_unsafe [ library... ]
source:
::
#include <longpath/longpath.h>
int openl(const char *path, int oflag, /* mode_t mode */);
int openatl(int filedes, const char *path, int oflag, mode_t mode);
int creatl(const char *path, mode_t mode);
int linkatl(int fd1, const char *p1, int fd2, const char *p2, int flags);
int linkl(const char *p1, const char *p2);
int unlinkatl(int fd, const char *p, int flags);
int unlinkl(const char *p);
int symlinkatl(const char *dest, int filedes, const char *path);
int symlinkl(const char *dest, const char *path);
int readlinkatl(int fd, const char *name, char *buf, size_t count);
int readlinkl(const char *name, char *buf, size_t count);
int fchownatl(int fd, const char *name, uid_t uid, gid_t gid, int flags);
int chownl(const char *name, uid_t uid, gid_t gid);
int lchownl(const char *name, uid_t uid, gid_t gid);
int chmodl(const char *path, mode_t mode);
int mknodatl(int fd, const char *name, mode_t mode, dev_t dev);
int mknodl(const char *name, mode_t mode, dev_t dev);
int mkfifoatl(int fd, const char *name, mode_t mode);
int mkfifol(const char *name, mode_t mode);
int fstatatl(int fd, const char *name, struct stat *sb, int flags);
int statl(const char *name, struct stat *sb);
int lstatl(const char *name, struct stat *sb);
int rmdiratl(int fd, const char *name);
int rmdirl(const char *name);
int mkdiratl(int fd, const char *name, mode_t mode);
int mkdirl(const char *name, mode_t mode);
int renameatl(int fd1, const char *p1, int fd2, const char *p2);
int renamel(const char *p1, const char *p2);
char *mktempl(char *template);
char *mkdtempl(char *template);
int mkstempl(char *template);
int mkstempsl(char *template, int slen);
int mkostempl(char *template, int flags);
int mkostempsl(char *template, int slen, int flags);
int utimensatl(int fd, const char *path, const struct timespec times[2], int flag);
int futimesatl(int filedes, const char *path, const struct timeval tv[2]);
int utimesl(const char *path, const struct timeval tv[2]);
int lutimesl(const char *path, const struct timeval tv[2]);
DIR *opendirl(const char *dirname);
platform dependent
------------------
::
int attropenl(const char *path, const char *apath, int oflag, /* mode_t mode */);
ssize_t getxattrl(const char *path, const char *name, void *value, size_t size);
ssize_t lgetxattrl(const char *path, const char *name, void *value, size_t size);
int setxattrl(const char *path, const char *name, const void *value, size_t size, int flags);
int lsetxattrl(const char *path, const char *name, const void *value, size_t size, int flags);
lf64 transitional
-----------------
::
openl64
openatl64
creatl64
attropenl64
fstatatl64
statl64
lstatl64
mkstempl64
mkstempsl64
mkostempl64
mkostempsl64
SYNOPSIS: Compile-time redefinition
===================================
source file using i/o functions
-------------------------------
::
#include <longpath/longpath_redefine_pre.h>
#include <stat.h>
/* ... system includes ... */
#include <fcntl.h>
#include <longpath/longpath_redefine_post.h>
source file using ``PATH_MAX`` / ``MAXPATHLEN``
-----------------------------------------------
::
#include <longpath/longpath_redefine_defs.h>
DESCRIPTION
===========
*liblongpath* provides, where possible, transparent wrapper functions
of well-known system i/o functions for handling path names longer than
``PATH_MAX`` - overcoming a practical limitation of these functions at
the expense of additional memory consumption and higher system call
overhead for long paths.
The wrapper functions check the length of path arguments and, if they
exceed ``PATH_MAX``, open intermediate directories on the path. A
semantic equivalent of the wrapped function is then executed with the
last relative path element. In most cases, an ``*at`` variant of the
wrapped function is used (e.g. ``openat`` for
``open``). Alternatively, some wrapper functions use ``f*`` variants
of the wrapped function on a newly opened file descriptor
(e.g. ``fdopendir`` for ``opendir``).
NAMING
------
All *liblongpath* functions match the names of their wrapped
equivalents with the letter ``l`` appended.
lf64 variants
-------------
transitional interfaces for 64-bit file offsets are
implemented. ``longpath.h`` implements mappings as per values of
* ``_FILE_OFFSET_BITS``
* ``_LARGEFILE64_SOURCE``
* ``_LARGEFILE_SOURCE``
PLATFORM SPECIFICS
------------------
Not all functions are available on all platforms. As a general rule,
if a wrapped function is not available, *liblongpath* probably cannot
implement it.
If no ``*at`` variant of a wrapped function is available,
*liblongpath* wrappes the original function, which reduces its'
capabilities (see section on *liblongpath_unsafe* below).
THREAD SAFETY
-------------
*liblongpath* is thread safe if the wrapped functions are on the
respective platform.
*liblongpath_unsafe*
--------------------
If ``*at`` variants of wrapped functions are missing on a platform,
*liblongpath_unsafe* may provide a working implementation at the expense
of thread safety: Instead of opening intermediate directories,
*liblongpath_unsafe* may change the current working directory and call
the wrapped function on a short remaining relative path.
Despite the name (which is intended as a motivation to read the
documentation), *liblongpath_unsafe* is considered safe for single
threaded applications.
RETURN VALUES
=============
All *liblongpath* functions return the same values as their wrapped
equivalents, usually ``-1`` or a ``NULL`` pointer for errors.
ERRORS
======
All *liblongpath* functions should set the same ``errno`` values as their
wrapped equivalents, but ``errno`` values can differ slightly.
COMPILE-TIME REDEFINITION
=========================
To facilitate use of *liblongpath* as a plug-in replacement, header
files are provided which redefine the wrapped function names to their
respective wrapper functions.
Such wrapping is error-prone because it highly depends on
implementation details of system include files and the application
using the wrapper, so it should be considered as an intermediate
solution only.
rules for redefinition includes
-------------------------------
for source files referencing any wrapped function
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* ``longpath/longpath_redefine_pre.h`` should be included before any
other system includes, but after ``#define`` s which could be
relevant for the wrapper behavior, in particular those controlling
``lf64`` behavior (see above).
* ``longpath/longpath_redefine_post.h`` should be included after all
other system includes
for source files using ``PATH_MAX`` / ``MAXPATHLEN``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
source files using ``PATH_MAX`` or ``MAXPATHLEN`` may include
``longpath/longpath_redefine_defs.h`` to have these macros redefined
to significantly larger values (16KB currently).
*liblongpath* itself does not impose any limit on the maximum path
length. As long as the kernel supports the respective directory
nesting level and resources allow, applications may use arbitrarily
long path names with *liblongpath*.
PERFORMANCE AND RESOURCE CONSUMPTION
====================================
As a rule of thumb, for each wrapped function call, *liblongpath*
imposes overhead in the orders of magnitude of:
* One ``strlen()`` call for each path
If the path is longer than ``PATH_MAX``:
* Stack space of ``PATH_MAX`` bytes
* One additional file descriptor for each path
* For each path segment with a length not exceeding ``PATH_MAX``:
* One ``open()`` and one ``close()`` call
* One ``memcpy()`` operation
* One ``strlen()`` call if assertions are enabled (compiled without ``-DNDEBUG``)
Applications recompiled with a redefined, longer ``PATH_MAX`` may require
considerably more stack space and/or heap memory.
LIMITATIONS
===========
* The ``PATH_MAX`` limit does not necessarily apply to all file systems -
the actual limit would need to be determined using pathconf. No such
check is currently implemented, *liblongpath* assumes that relative
paths with a length of up to ``PATH_MAX`` bytes (including the
terminating null byte) can be handled by wrapped functions on all
paths.
* *liblongpath* implements only minimal additional logic. Returned error
codes do not necessarily match applicable standards.
MISSING FUNCTIONS
=================
The following functions are known to be missing in the current
implementation:
* ``stdio.h`` functions
* ``fopen()``
* ``freopen()``
* ``libgen.h`` functions
* ``copylist()``
* file tree walkers
* ``ftw()``
* ``nftw()``
* Solaris ACLs (posix draft ACLs, ZFS and NFSv4 ACLS)
* ``acl()``
LICENSE
=======
This document is licensed under the same license as *liblongpath*
itself. See the distribution's ``LICENSE`` file for details
COPYRIGHT
=========
Copyright (c) 2013 UPLEX Nils Goroll Systemoptimierung.
All rights reserved.
/*-
* wrapper library for long paths exceeding PATH_MAX
*
* Copyright (c) 2013 UPLEX Nils Goroll Systemoptimierung
* All rights reserved
*
* Author: Nils Goroll <nils.goroll@uplex.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* == IMPLEMENTATION NOTES ==
*
* UNIMPLEMENTED
* - ftw, nftw
* - copylist
* - stdio.h stuff: fopen, freopen
* - acl
* - Check for O_SEARCH ?
*
* TODO
* - use pathconf instead of fixed MAX_PATH
* - cache intermediate fds
* - cache getpath results
*
* Notes on lf64:
* for the intermediate filedescriptors, we always use openat64 unless _LP64 we
* can do so because we never hand out these fds - Xatl/Xatl2 always close them
*
* the lib gets compiled with _FILE_OFFSET_BITS==32 for 32 bit builds so we can
* provide both variants. longpath.h will provide the appropriate redefinitions
* depending on our consumer
*
* Notes on PATH_MAX:
* Ref: http://pubs.opengroup.org/onlinepubs/009695399/basedefs/limits.h.html
* Maximum number of bytes in a pathname, including the terminating null character.
*
*/
#include "../config.h"
#define _ATFILE_SOURCE
#if defined(_LP64)
#define _FILE_OFFSET_BITS 64
#define six4(x) x
#else
#define _FILE_OFFSET_BITS 32
#define six4(x) x ## 64
#endif
//// no use to undef these - solaris sys/feature_tests.h sets to 1
//#undef _LARGEFILE_SOURCE
//#undef _LARGEFILE64_SOURCE
#include <longpath/longpath.h>
#ifdef HAVE_ASSERT_H
#include <assert.h>
#else
#define assert(EX) ((void)0)
#endif
// XXX conditional includes incomplete
// string functions
#if defined(HAVE_STRING_H)
#include <string.h>
#endif
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_STDIO_H
#include <stdio.h>
#endif
// varargs for open
#if defined(HAVE_SYS_VARARGS_H)
#include <sys/varargs.h>
#elif defined(HAVE_STDARG_H)
#include <stdarg.h>
#endif
// opendir
#ifdef HAVE_DIRENT_H
#include <dirent.h>
#endif
// linux xattr
#ifdef HAVE_FGETXATTR
#include <sys/xattr.h>
#endif
/*
* close an intermediate file descriptor, restoring errno if necessary
*/
static inline void
close_ifd(int ifd) {
const int s = errno;
assert(ifd >= 0);
assert(ifd != (int)AT_FDCWD);
if (close(ifd) == -1)
errno = s;
}
#ifdef USE_CHDIR_FALLBACK
/*
* define NEED_CHDIR when using these
*/
static inline void restore_cwd(int *fd);
static int chdir_im(const char *path, const char **remaining, int limit);
#define Xl(funcn, path, ...) \
int r; \
int ocwd = open(".", O_RDONLY|O_NDELAY|O_LARGEFILE); \
const char *remaining; \
\
if (ocwd == -1) \
return -1; \
\
if (chdir_im(path, &remaining, 0) == -1) { \
restore_cwd(&ocwd); \
return -1; \
} \
\
path += (remaining - path); \
\
r = funcn(path, ##__VA_ARGS__); \
\
restore_cwd(&ocwd); \
return r
#endif /* USE_CHDIR_FALLBACK */
/*
* oatl_im = open at long intermediate
*
* for a path longer than PATH_MAX, open intermediate directories and return an
* fd to the last directory component required for colling *at functions on the
* remaining path component
*
* filedes can be AT_FDCWD
* openatl_interm will not close filedes
*
* return:
*
* -1 for errors, errno will be set
* filedes if path is NULL or shorter than PATH_MAX
* otherwise new open filedescriptor
*
* The caller must close the returned fd unless it is equal to filedes
*/
static int
oatl_im(int filedes, const char *path, const char **remaining) {
char interm[PATH_MAX];
const char *p, *sl;
size_t l;
int fd;
/*
* work with functions on NULL paths like fchownat
* - at any rate we can leave error handling with the system function
*/
if (path == NULL) {
*remaining = NULL;
return filedes;
}
l = strlen(path);
if (l < PATH_MAX) {
*remaining = path;
return filedes;
}
p = path;
fd = filedes;
while (l >= PATH_MAX) {
int nfd;
assert(l == strlen(p));
/* find last slash for strlen(component) < PATH_MAX */
sl = p + PATH_MAX - 1;
while (sl > p) {
if (*sl == '/')
goto found;
sl--;
}
errno = ENAMETOOLONG;
goto err;
found:
assert((sl - p) < PATH_MAX);
strncpy(interm, p, (sl - p));
interm[sl - p] = '\0';
nfd = six4(openat)(fd, interm,
O_RDONLY|O_NDELAY|O_LARGEFILE, 0);
if (nfd == -1)
goto err;
if (fd != filedes)
close_ifd(fd);
fd = nfd;
l -= (sl - p) + 1;
p = sl + 1;
}
assert(fd != filedes);
*remaining = p;
return fd;
err:
if (fd != filedes)
close_ifd(fd);
return -1;
}
// long path *at function
#define Xatl(funcn, filedes, path, ...) \
int __ifd, __fd; \
const char *__rest; \
\
__ifd = oatl_im(filedes, path, &__rest); \
\
if (__ifd == -1) \
return -1; \
\
__fd = funcn(__ifd, __rest, ##__VA_ARGS__); \
\
if (__ifd != filedes) \
close_ifd(__ifd); \
\
return __fd
// long path *at function with two paths
#define Xatl2(funcn, fd1, p1, fd2, p2, ...) \
int __ifd1, __ifd2, __fd; \
const char *__rest1; \
const char *__rest2; \
\
__ifd1 = oatl_im(fd1, p1, &__rest1); \
if (__ifd1 == -1) \
return -1; \
\
__ifd2 = oatl_im(fd2, p2, &__rest2); \
if (__ifd2 == -1) { \
__fd = -1; \
goto close_ifd1; \
} \
\
__fd = funcn(__ifd1, __rest1, __ifd2, __rest2, ##__VA_ARGS__); \
\
if (__ifd2 != fd2) \
close_ifd(__ifd2); \
\
close_ifd1: \
if (__ifd1 != fd1) \
close_ifd(__ifd1); \
\
return __fd
// long path f* function - make mode an argument?
#define Xfl(path, flags, err, r, funcn, ...) \
int __ifd; \
\
__ifd = openatl(AT_FDCWD, (path), \
O_RDONLY|O_NDELAY|O_LARGEFILE, (flags)); \
\
if (__ifd == -1) \
return (err); \
\
r = funcn(__ifd, ##__VA_ARGS__); \
\
close_ifd(__ifd)
/* OPEN */
int
openatl(int filedes, const char *path, int oflag, mode_t mode) {
Xatl(openat, filedes, path, oflag, mode);
}
#if !defined(_LP64)
int
openatl64(int filedes, const char *path, int oflag, mode_t mode) {
Xatl(openat64, filedes, path, oflag, mode);
}
#endif
#define Openl(bits) \
mode_t mode = 0; \
if (oflag & O_CREAT) { \
va_list arg; \
va_start(arg, oflag); \
mode = va_arg(arg, mode_t); \
va_end(arg); \
} \
\
return openatl ## bits (AT_FDCWD, path, oflag, mode)
int
openl(const char *path, int oflag, ...) {
Openl(/*32*/);
}
#if !defined(_LP64)
int
openl64(const char *path, int oflag, ...) {
Openl(64);
}
#endif
/* CREAT */
int
creatl(const char *path, mode_t mode) {
return openatl(AT_FDCWD, path, O_WRONLY|O_CREAT|O_TRUNC , mode);
}
#if !defined(_LP64)
int
creatl64(const char *path, mode_t mode) {
return openatl64(AT_FDCWD, path, O_WRONLY|O_CREAT|O_TRUNC , mode);
}
#endif
/* ATTROPEN */
/* Solaris specific ? */
#ifdef HAVE_ATTROPEN
#define Attropenl(bits) \
int fd, afd; \
va_list ap; \
\
fd = openl ## bits (path, O_RDONLY|O_NONBLOCK); \
if (fd == -1) \
return -1; \
\
va_start(ap, oflag); \
afd = openatl ## bits (fd, apath, oflag|O_XATTR, \
va_arg(ap, mode_t)); \
va_end(ap); \
\
close_ifd(fd); \
return afd
int
attropenl(const char *path, const char *apath, int oflag, ...) {
Attropenl(/*32*/);
}
#if !defined(_LP64)
int
attropenl64(const char *path, const char *apath, int oflag, ...) {
Attropenl(64);
}
#endif
#endif /* HAVE_ATTROPEN */
/* GETXATTR / LGETXATTR */
/* untested */
#ifdef HAVE_FGETXATTR
#ifndef HAVE_FSETXATTR
#error Assuming fsetxattr to exist when fgetxattr exists
#endif
ssize_t
getxattrl(const char *path, const char *name, void *value, size_t size) {
ssize_t r;
Xfl(path, 0, -1,
r, fgetxattr, name, value, size);
return r;
}
ssize_t
lgetxattrl(const char *path, const char *name, void *value, size_t size) {
ssize_t r;
Xfl(path, AT_SYMLINK_NOFOLLOW, -1,
r, fgetxattr, name, value, size);
return r;
}
int
setxattrl(const char *path, const char *name, const void *value, size_t size, int flags) {
int r;
Xfl(path, 0, -1,
r, fsetxattr, name, value, size, flags);
return r;
}
int
lsetxattrl(const char *path, const char *name, const void *value, size_t size, int flags) {
int r;
Xfl(path, AT_SYMLINK_NOFOLLOW, -1,
r, fsetxattr, name, value, size, flags);
return r;
}
#endif /* HAVE_FGETXATTR */
/* LINK */
#ifdef HAVE_LINKAT
int
linkatl(int fd1, const char *p1, int fd2, const char *p2, int flags) {
Xatl2(linkat, fd1, p1, fd2, p2, flags);
}
int
linkl(const char *p1, const char *p2) {
return linkatl(AT_FDCWD, p1, AT_FDCWD, p2, 0);
}
#else /* HAVE_LINKAT */
#ifndef USE_CHDIR_FALLBACK
#warning linkat missing - link* calls on long paths may fail
int
linkl(const char *p1, const char *p2) {
return link(p1, p2);
}
#else /* USE_CHDIR_FALLBACK */
#warning linkat missing - link* calls on long paths may fail (trying prefix match)
static int
strprefixlen(const char *s1, const char *s2) {
int i = 0;
while((*s1 != '\0') && (*s1 == *s2)) {
s1++; s2++; i++;
}
return i;
}
int
linkl(const char *p1, const char *p2) {
int l = strprefixlen(p1, p2);
if (l > 0) {
int r;
int ocwd = open(".", O_RDONLY|O_NDELAY|O_LARGEFILE);
const char *remaining;
if (ocwd == -1)
return -1;
if (chdir_im(p1, &remaining, l) == -1) {
restore_cwd(&ocwd);
return -1;
}
l = remaining - p1;
p1 += l;
p2 += l;
r = link(p1, p2);
restore_cwd(&ocwd);
return r;
}
return link(p1, p2);
}
#endif /* USE_CHDIR_FALLBACK */
#endif /* HAVE_LINKAT */
/** UNLINK **/
int
unlinkatl(int fd, const char *p, int flags) {
Xatl(unlinkat, fd, p, flags);
}
int
unlinkl(const char *p) {
return unlinkatl(AT_FDCWD, p, 0);
}
/** SYMLINK **/
#ifdef HAVE_SYMLINKAT
/* slightly differnt signature - damn */
int
symlinkatl(const char *dest, int filedes, const char *path) {
int ifd, r;
const char *rest;
ifd = oatl_im(filedes, path, &rest);
if (ifd == -1)
return -1;
r = symlinkat(dest, ifd, rest);
if (ifd != filedes)
close_ifd(ifd);
return r;
}
int
symlinkl(const char *dest, const char *path) {
return symlinkatl(dest, AT_FDCWD, path);
}
#else /* HAVE_SYMLINKAT */
#ifndef USE_CHDIR_FALLBACK
#warning symlinkat missing - symlink* calls on long paths may fail
int
symlinkl(const char *dest, const char *path) {
return symlink(dest, path);
}
#else /* USE_CHDIR_FALLBACK */
int
symlinkl(const char *dest, const char *path) {
int r;
int ocwd = open(".", O_RDONLY|O_NDELAY|O_LARGEFILE);
const char *remaining;
if (ocwd == -1)
return -1;
if (chdir_im(path, &remaining, 0) == -1) {
restore_cwd(&ocwd);
return -1;
}
path += (remaining - path);
r = symlink(dest, path);
restore_cwd(&ocwd);
return r;
}
#endif /* USE_CHDIR_FALLBACK */
#endif /* HAVE_SYMLINKAT */
/** READLINK **/
#ifdef HAVE_READLINKAT
int
readlinkatl(int fd, const char *name, char *buf, size_t count) {
Xatl(readlinkat, fd, name, buf, count);
}
int
readlinkl(const char *name, char *buf, size_t count) {
return readlinkatl(AT_FDCWD, name, buf, count);
}
#else /* HAVE_READLINKAT */
#ifndef USE_CHDIR_FALLBACK
#warning readlinkat missing - link* calls on long paths may fail
int
readlinkl(const char *name, char *buf, size_t count) {
return readlink(name, buf, count);
}
#else /* USE_CHDIR_FALLBACK */
#undef NEED_CHDIR
#define NEED_CHDIR
int
readlinkl(const char *name, char *buf, size_t count) {
Xl(readlink, name, buf, count);
}
#endif /* USE_CHDIR_FALLBACK */
#endif /* HAVE_READLINKAT */
/** CHOWN **/
int
fchownatl(int fd, const char *name, uid_t uid, gid_t gid, int flags) {
Xatl(fchownat, fd, name, uid, gid, flags);
}
int
chownl(const char *name, uid_t uid, gid_t gid) {
return fchownatl(AT_FDCWD, name, uid, gid, 0);
}
int
lchownl(const char *name, uid_t uid, gid_t gid) {
return fchownatl(AT_FDCWD, name, uid, gid, AT_SYMLINK_NOFOLLOW);
}
/** CHMOD **/
int
chmodl(const char *path, mode_t mode) {
int fd;
Xfl(path, 0, -1,
fd, fchmod, mode);
return fd;
}
/* MKNOD */
#ifdef HAVE_MKNODAT
int
mknodatl(int fd, const char *name, mode_t mode, dev_t dev) {
Xatl(mknodat, fd, name, mode, dev);
}
int
mknodl(const char *name, mode_t mode, dev_t dev) {
return mknodatl(AT_FDCWD, name, mode, dev);
}
#else /* HAVE_MKNODAT */
#ifndef USE_CHDIR_FALLBACK
#warning mknodat missing - link* calls on long paths may fail
int
mknodl(const char *name, mode_t mode, dev_t dev) {
return mknod(name, mode, dev);
}
#else /* USE_CHDIR_FALLBACK */
#undef NEED_CHDIR
#define NEED_CHDIR
int
mknodl(const char *name, mode_t mode, dev_t dev) {
Xl(mknod, name, mode, dev);
}
#endif /* USE_CHDIR_FALLBACK */
#endif /* HAVE_MKNODAT */
/* MKFIFO */
#ifdef HAVE_MKFIFOAT
int
mkfifoatl(int fd, const char *name, mode_t mode) {
Xatl(mkfifoat, fd, name, mode);
}
int
mkfifol(const char *name, mode_t mode) {
return mkfifoatl(AT_FDCWD, name, mode);
}
#else /* HAVE_MKFIFOAT */
#ifndef USE_CHDIR_FALLBACK
#warning mkfifoat missing - link* calls on long paths may fail
int
mkfifol(const char *name, mode_t mode) {
return mkfifo(name, mode);
}
#else /* USE_CHDIR_FALLBACK */
#undef NEED_CHDIR
#define NEED_CHDIR
int
mkfifol(const char *name, mode_t mode) {
Xl(mkfifo, name, mode);
}
#endif /* USE_CHDIR_FALLBACK */
#endif /* HAVE_MKFIFOAT */
/* STAT */
int
fstatatl(int fd, const char *name, struct stat *sb, int flags) {
Xatl(fstatat, fd, name, sb, flags);
}
int
statl(const char *name, struct stat *sb) {
return fstatatl(AT_FDCWD, name, sb, 0);
}
int
lstatl(const char *name, struct stat *sb) {
return fstatatl(AT_FDCWD, name, sb, AT_SYMLINK_NOFOLLOW);
}
#if !defined(_LP64)
int
fstatatl64(int fd, const char *name, struct stat64 *sb, int flags) {
Xatl(fstatat64, fd, name, sb, flags);
}
int
statl64(const char *name, struct stat64 *sb) {
return fstatatl64(AT_FDCWD, name, sb, 0);
}
int
lstatl64(const char *name, struct stat64 *sb) {
return fstatatl64(AT_FDCWD, name, sb, AT_SYMLINK_NOFOLLOW);
}
#endif
/* RMDIR */
int
rmdiratl(int fd, const char *name) {
return unlinkatl(fd, name, AT_REMOVEDIR);
}
int
rmdirl(const char *name) {
return rmdiratl(AT_FDCWD, name);
}
/* MKDIR */
#ifdef HAVE_MKDIRAT
int
mkdiratl(int fd, const char *name, mode_t mode) {
Xatl(mkdirat, fd, name, mode);
}
int
mkdirl(const char *name, mode_t mode) {
return mkdiratl(AT_FDCWD, name, mode);
}
#else /* HAVE_MKDIRAT */
#ifndef USE_CHDIR_FALLBACK
#warning mkdirat missing - link* calls on long paths may fail
int
mkdirl(const char *name, mode_t mode) {
return mkdir(name, mode);
}
#else /* USE_CHDIR_FALLBACK */
#undef NEED_CHDIR
#define NEED_CHDIR
int
mkdirl(const char *name, mode_t mode) {
Xl(mkdir, name, mode);
}
#endif /* USE_CHDIR_FALLBACK */
#endif /* HAVE_MKDIRAT */
/* RENAME */
int
renameatl(int fd1, const char *p1, int fd2, const char *p2) {
Xatl2(renameat, fd1, p1, fd2, p2);
}
int
renamel(const char *p1, const char *p2) {
return renameatl(AT_FDCWD, p1, AT_FDCWD, p2);
}
/*
* MK*TEMP*
*
* there is no mk*tempat, so we need to implement it outselves
*/
/*
* common code for all the mk*temp* - structure taken from glibc, which is
* Copyright (C) 1991-2001, 2006, 2007, 2009 Free Software Foundation, Inc.
*/
enum temp_kind {
T_NOCREATE,
T_FILE,
T_DIR
#if !defined(_LP64)
,T_FILE64
#endif
};
/*
* return val:
* -1 or valid fd
*
* AT_FDCWD is returned to signal success for T_DIR and T_NOCREATE
*/
static inline int
_mkxtempl(char *template, int slen, int flags, enum temp_kind kind) {
size_t len;
int ifd, fd;
char *rest;
char *save, *r, *spos;
struct six4(stat) tstat;
if (slen < 0 || template == NULL || *template == '\0') {
errno = EINVAL;
return -1;
}
len = strlen(template);
spos = NULL;
save = NULL;
/* check input */
{
char *end, *tmp;
end = &template[len - 1];
/* no trailing slashes */
if (*end == '/') {
errno = EINVAL;
return -1;
}
tmp = end;
while (--tmp >= template) {
if (*tmp == '/') {
/*
* if we have a slash, the suffix must be within
* the last path element
*/
if (slen >= (end - tmp)) {
errno = EINVAL;
return -1;
}
}
}
tmp = end - slen;
if (*tmp == 'X')
spos = tmp + 1;
}
ifd = oatl_im(AT_FDCWD, template, (const char **)&rest);
if (ifd == -1)
return -1;
// save = strdupa(rest);
save = malloc(strlen(rest) + 1);
if (! save) {
errno = ENOMEM;
goto err;
}
strcpy(save, rest);
do {
/*
* XXX: as we don't have mktempat, mktemp will check the wrong
* directory for long paths. this does not really matter because
* we check for exclusive createion / existance afterwards, but
* is less efficient.
*/
if (spos) {
char s = *spos;
/* temp. trim of the suffix for mktemp */
*spos = '\0';
r = mktemp(rest);
*spos = s;
if (*r == '\0')
goto err;
}
switch (kind) {
case T_DIR:
{
#ifdef HAVE_MKDIRAT
if (mkdirat(ifd, rest, 0700) == 0) {
fd = AT_FDCWD;
goto out;
}
#else /* HAVE_MKDIRAT */
#ifndef USE_CHDIR_FALLBACK
#warning mkdirat missing - mkdtemp* calls on long paths may fail
if (mkdtemp(template)) {
fd = AT_FDCWD;
goto out;
}
goto err;
#else /* USE_CHDIR_FALLBACK */
if (ifd == AT_FDCWD) {
if (mkdir(rest, 0700) == 0) {
fd = AT_FDCWD;
goto out;
}
} else {
int ocwd;
ocwd = open(".", O_RDONLY|O_NDELAY|O_LARGEFILE);
if (ocwd == -1)
goto err;
if (fchdir(ifd) == -1)
goto err;
if (mkdir(rest, 0700) == 0) {
restore_cwd(&ocwd);
fd = AT_FDCWD;
goto out;
}
restore_cwd(&ocwd);
}
#endif /* USE_CHDIR_FALLBACK */
#endif /* HAVE_MKDIRAT */
break; /* retry */
}
case T_FILE:
fd = openat(ifd, rest, O_CREAT|O_EXCL|O_RDWR|flags, 0600);
if (fd != -1)
goto out;
break; /* retry */
#if !defined(_LP64)
case T_FILE64:
fd = openat64(ifd, rest, O_CREAT|O_EXCL|O_RDWR|flags, 0600);
if (fd != -1)
goto out;
break; /* retry */
#endif
case T_NOCREATE:
{
int serrno = errno;
if (six4(fstatatl)(ifd, rest, &tstat, AT_SYMLINK_NOFOLLOW) == -1) {
if (errno != ENOENT)
goto err;
assert(errno == ENOENT);
errno = serrno;
fd = AT_FDCWD;
goto out;
}
break; /* retry */
}
default:
assert(! "invalid kind in _mkxtempl");
}
if ((! spos) || (errno != EEXIST))
goto err;
(void) strcpy(rest, save);
} while (1);
assert (! "NOTREACHED");
err:
fd = -1;
out:
if (save)
free(save);
if (ifd != (int)AT_FDCWD)
close_ifd(ifd);
return fd;
}
/*
* Quote solaris man page:
* The mkdtemp() function can set errno to the same values as
* mkdir(2).
* so we don't need to save errno
*/
char *
mktempl(char *template) {
int serrno = errno;
if (_mkxtempl(template, 0, 0, T_NOCREATE) == -1)
return NULL;
errno = serrno;
return template;
}
char *
mkdtempl(char *template) {
if (_mkxtempl(template, 0, 0, T_DIR) == -1)
return NULL;
return template;
}
int
mkstempl(char *template) {
return _mkxtempl(template, 0, 0, T_FILE);
}
int
mkstempsl(char *template, int slen) {
return _mkxtempl(template, slen, 0, T_FILE);
}
int
mkostempl(char *template, int flags) {
return _mkxtempl(template, 0, flags, T_FILE);
}
int
mkostempsl(char *template, int slen, int flags) {
return _mkxtempl(template, slen, flags, T_FILE);
}
#if !defined(_LP64)
int
mkstempl64(char *template) {
return _mkxtempl(template, 0, 0, T_FILE64);
}
int
mkstempsl64(char *template, int slen) {
return _mkxtempl(template, slen, 0, T_FILE64);
}
int
mkostempl64(char *template, int flags) {
return _mkxtempl(template, 0, flags, T_FILE64);
}
int
mkostempsl64(char *template, int slen, int flags) {
return _mkxtempl(template, slen, flags, T_FILE64);
}
#endif
/* UTIMES */
/*
* (f)utimesat is special and strange, so map them all to utimensat, which is
* the new syscall anyway
*/
/*
* http://pubs.opengroup.org/onlinepubs/9699919799/functions/futimens.html#tag_16_181
*
* tv_nsec UTIME_NOW : same as NULL tv
* tv_nsec UTIME_OMIT: don't set
*/
int
utimensatl(int fd, const char *path, const struct timespec times[2], int flag) {
Xatl(utimensat, fd, path, times, flag);
}
static inline void
tv2ts(struct timespec **tsp, const struct timeval tv[2]) {
if (tv == NULL) {
*tsp = NULL;
} else {
struct timespec *ts = *tsp;
assert(ts);
ts[0].tv_sec = tv[0].tv_sec;
ts[0].tv_nsec = tv[0].tv_usec * 1000;
ts[1].tv_sec = tv[1].tv_sec;
ts[1].tv_nsec = tv[1].tv_usec * 1000;
}
}
/*
* futimesat is special
* - if PATH is NULL, update is applied to the fd
* - if PATH is relative, PATH is relative to fd
*
* but because utimensatl does not handle PATH == NULL, we need
* to pass to futimens
*
*/
int
futimesatl(int filedes, const char *path, const struct timeval tv[2]) {
struct timespec ts[2];
struct timespec *tsp = ts;
tv2ts(&tsp, tv);
if (path == NULL)
return futimens(filedes, tsp);
return utimensatl(filedes, path, tsp, 0);
}
int
utimesl(const char *path, const struct timeval tv[2]) {
struct timespec ts[2];
struct timespec *tsp = ts;
tv2ts(&tsp, tv);
return utimensatl(AT_FDCWD, path, tsp, 0);
}
int
lutimesl(const char *path, const struct timeval tv[2]) {
struct timespec ts[2];
struct timespec *tsp = ts;
tv2ts(&tsp, tv);
return utimensatl(AT_FDCWD, path, tsp, AT_SYMLINK_NOFOLLOW);
}
int
utimel(const char *path, const struct utimbuf *times) {
if (times) {
struct timespec ts[2];
ts[0].tv_sec = times->actime;
ts[0].tv_nsec = 0;
ts[1].tv_sec = times->modtime;
ts[1].tv_nsec = 0;
return utimensatl(AT_FDCWD, path, ts, 0);
}
return utimensatl(AT_FDCWD, path, NULL, 0);
}
/* OPENDIR */
DIR *
opendirl(const char *dirname) {
DIR *r;
int fd;
/* almost identical to Xfl, but we must not close the fd */
fd = openatl(AT_FDCWD, dirname, O_RDONLY|O_NDELAY|O_LARGEFILE, 0);
if (fd == -1)
return NULL;
return fdopendir(fd);
}
#ifdef NEED_CHDIR
/*
* this function will always try to chdir even if path is shorter than PATH_MAX
* so it can be used on a common prefix of two paths
*/
static int
chdir_im(const char *path, const char **remaining, int limit) {
char interm[PATH_MAX];
const char *p, *sl;
size_t l;
/*
* work with functions on NULL paths like fchownat
* - at any rate we can leave error handling with the system function
*/
if (path == NULL) {
*remaining = NULL;
return 0;
}
l = strlen(path);
if ((limit > 0) && (l > limit))
l = limit;
p = path;
do {
/* find last slash within limit */
sl = p + ((l < PATH_MAX) ? l : (PATH_MAX - 1));
while (sl > p) {
if (*sl == '/')
goto found;
sl--;
}
goto out;
found:
assert((sl - p) < PATH_MAX);
strncpy(interm, p, (sl - p));
interm[sl - p] = '\0';
if (chdir(interm) == -1)
goto err;
l -= (sl - p) + 1;
p = sl + 1;
} while (1);
out:
*remaining = p;
return 0;
err:
return -1;
}
static inline void
restore_cwd(int *fd) {
assert(*fd >= 0);
assert(*fd != (int)AT_FDCWD);
if (fchdir(*fd) == -1) {
/*
* XXX: This really must not happen, we have
* changed the processes' state and can't
* restore it. Any better ideas?
*/
assert(! "liblongpath restore_cwd");
perror("liblongpath restore_cwd");
exit(1);
}
close_ifd(*fd);
*fd = -1;
}
#else /* NEED_CHDIR */
static int chdir_im(const char *path, const char **remaining, int limit) {
assert(! "not used");
(void)path;
(void)remaining;
(void)limit;
return -1;
}
static inline void restore_cwd(int *fd) {
assert(! "not used");
(void)fd;
}
void *_dummy1 = chdir_im;
void *_dummy2 = restore_cwd;
#endif /* NEED_CHDIR */
/*-
* test code for wrapper library for long paths exceeding PATH_MAX
*
* Copyright (c) 2013 UPLEX Nils Goroll Systemoptimierung
* All rights reserved
*
* Author: Nils Goroll <nils.goroll@uplex.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* use this tool with some long path files
*
mkdir /tmp/test
cd /tmp/test
for i in {,1,2,3}{0..9} ; do
p=`printf "%0255d" $i`;
mkdir $p && cd $p;
echo REALLYLONGPATHTEST >file.$i
date >>file.$i
done
cd /
find /tmp/test -name file\*
test:
./a.out $(find /tmp/test -name file\*)
*/
// for mko*temp*
#define _GNU_SOURCE
#include <longpath/longpath.h>
#include <stdlib.h>
#include <alloca.h>
#ifdef HAVE_SYS_MKDEV_H
#include <sys/mkdev.h>
#else
// linux has makedev in sys/types.h but wants this define
#undef _BSD_SOURCE
#define _BSD_SOURCE
#endif
#include <sys/types.h>
#include <assert.h>
// XXX conditional includes incomplete
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_STDIO_H
#include <stdio.h>
#endif
// open
#ifdef HAVE_SYS_VARARGS_H
#include <sys/varargs.h>
#endif
// opendir
#ifdef HAVE_DIRENT_H
#include <dirent.h>
#endif
// linux
#ifndef S_IAMB
#define S_IAMB (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)
#endif
#define _ok(badval, funcn, ...) if (funcn(__VA_ARGS__) == (badval)) { \
perror(#funcn); \
assert(! #funcn); \
}
#define ok(funcn, ...) _ok(-1 , funcn, __VA_ARGS__)
#define ok_ptr(funcn, ...) _ok(NULL, funcn, __VA_ARGS__)
#define _nok(badval, e, funcn, ...) if (funcn(__VA_ARGS__) != (badval)) { \
assert(! "should fail: " #funcn); \
} else if (errno != e) { \
perror(#funcn " bad errno"); \
assert(! "expected " #e); \
}
#define nok(e, funcn, ...) _nok(-1 , e, funcn, __VA_ARGS__)
#define nok_ptr(e, funcn, ...) _nok(NULL, e, funcn, __VA_ARGS__)
#define canskip(p, funcn, ...) if (p) { \
funcn(__VA_ARGS__); \
} else { \
fprintf(stderr, "warn: can't test %s at line %d\n", \
#funcn, __LINE__); \
}
#define check(funcn, v) if((v) == -1) { \
perror(#funcn); \
assert(! #funcn); \
}
#define otherpath(argc, argv, i) ( \
((i + 1) < argc) ? argv[i + 1] \
: ((i > 1) ? argv[i - 1] : NULL))
#undef strdupa
#define strdupa(s) \
strcpy(alloca(strlen(s) + 1), s)
static char *
_strconcata(char *spc, const char *s1, const char *s2) {
char *r = spc;
assert (r);
strcpy(r, s1);
strcat(r, s2);
assert (r);
return r;
}
static char *
_strconcata3(char *spc, const char *s1, const char *s2, const char *s3) {
char *r = spc;
assert (r);
strcpy(r, s1);
strcat(r, s2);
strcat(r, s3);
assert (r);
return r;
}
#define strconcata(s1, s2) \
_strconcata(alloca(strlen(s1) + strlen(s2) + 1), s1, s2)
#define strconcata3(s1, s2, s3) \
_strconcata3(alloca(strlen(s1) + strlen(s2) + strlen(s3) + 1), s1, s2, s3)
static void
test_file(const char *path, const char *path2) {
const char *linkpath;
struct stat tstat;
int n;
const int sz = 1024;
char buf[sz];
linkpath = strconcata(path2 ? path2 : path, ".link");
assert(linkpath);
assert(*linkpath);
/* TEST linkl */
ok(linkl, path, linkpath);
/* TEST unlinkl */
ok(unlinkl, linkpath);
/* TEST symlinkl */
ok(symlinkl, strrchr(path, '/') + 1, linkpath);
/* TEST readlinkl */
n = readlinkl(linkpath, buf, sz);
check(readlinkl, n);
buf[n] = '\0';
printf("readlink out: %s\n", buf);
/* TEST lchownl */
ok(lchownl, path, 2, 3);
/* TEST lstatl */
ok(lstatl, path, &tstat);
assert(tstat.st_uid == 2);
assert(tstat.st_gid == 3);
ok(unlinkl, linkpath);
/* TEST renamel (file) */
ok(renamel, path, linkpath);
ok(renamel, linkpath, path);
}
static void
test_dir(const char *path, const char *path2) {
char *dp1, *dp2;
const char *cdp1, *cdp2;
cdp1 = dp1 = strconcata(path, ".dirpath_1_XXXXXX");
cdp2 = dp2 = strconcata(path2 ? path2 : path, ".dirpath_2_XXXXXX");
/* TEST mkdirl */
ok(mkdirl, cdp1, 0700);
#if 0
/* neg test dir unlink */
nok(EINVAL, unlinkl, cdp1);
#endif
/* TEST renamel (dir) */
ok(renamel, cdp1, cdp2);
ok(renamel, cdp2, cdp1);
/* TEST rmdirl */
ok(rmdirl, cdp1);
cdp1 = cdp2 = NULL;
/* TEST mkdtempl */
ok_ptr(mkdtempl, dp1);
assert(dp1[strlen(dp1) - 1] != 'X');
nok_ptr(EEXIST, mkdtempl, dp1);
ok(rmdirl, dp1);
}
static void
test_mktempl(const char *path) {
char *c1, *c2;
int fd;
c1 = strconcata(path, ".mktempl_XXXXXX");
c2 = strdupa(c1);
/* TEST mktempl */
ok_ptr(mktempl, c1);
assert(strcmp(c1, c2));
fd = openl(c1, O_CREAT|O_EXCL|O_RDWR, 0600);
check(openl, fd);
ok_ptr(mktempl, c2);
assert(strcmp(c1, c2));
ok(close, fd);
ok(unlinkl, c1);
}
#define t_mkXstempXl(fname, ...) \
static void \
test_ ## fname(const char *path, const char *templsuff) { \
char *c1, *c2; \
int fd; \
struct stat tstat; \
\
c1 = strconcata3(path, "." #fname "_XXXXXX", templsuff); \
c2 = strdupa(c1); \
\
fd = fname(c1, ##__VA_ARGS__); \
check(fname, fd); \
assert(strcmp(c1, c2)); \
ok(lstatl, c1, &tstat); \
ok(close, fd); \
\
fd = fname(c2, ##__VA_ARGS__); \
check(fname, fd); \
assert(strcmp(c1, c2)); \
ok(lstatl, c2, &tstat); \
ok(close, fd); \
\
ok(unlinkl, c1); \
ok(unlinkl, c2); \
}
t_mkXstempXl(mkstempl)
t_mkXstempXl(mkstempsl, strlen(templsuff))
t_mkXstempXl(mkostempl, O_SYNC)
t_mkXstempXl(mkostempsl, strlen(templsuff), O_SYNC)
static void
test_mkXstempXl(const char *path) {
/* TEST mkstempl */
/* TEST mkstempsl */
/* TEST mkostempl */
/* TEST mkostempsl */
test_mkstempl(path, "");
test_mkstempsl(path, "suffix123");
test_mkostempl(path, "");
test_mkostempsl(path, "suffix123");
}
static void
test_mkfifol(const char *path) {
char *c1;
struct stat tstat;
c1 = strconcata(path, ".fifo");
ok(mkfifol, c1, 0700);
ok(lstatl, c1, &tstat);
assert(tstat.st_mode & S_IFIFO);
ok(unlinkl, c1);
}
static void
test_mknodl(const char *path) {
#ifdef SKIP_TEST_MKNOD
(void)path;
#else
char *c1;
struct stat tstat;
c1 = strconcata(path, ".nod");
ok(mknodl, c1, 0700|S_IFCHR, makedev(37, 0));
ok(lstatl, c1, &tstat);
assert(tstat.st_mode & S_IFCHR);
ok(unlinkl, c1);
#endif
}
#define tv_eq(a, b) \
((a.tv_sec == b.tv_sec) && (a.tv_nsec == b.tv_nsec))
int
main(int argc, char *argv[]) {
int fd;
struct stat tstat, tostat;
int i, n;
char *path, *otherpath;
const int sz = 1024;
char buf[sz];
if (argc < 2)
return (EINVAL);
for (i = 1; i < argc; i++) {
path = argv[i];
otherpath = otherpath(argc, argv, i);
printf("length path, otherpath:\t%8zu\t%8zu\n", strlen(path), strlen(otherpath));
#if 0
printf("path: %s\n", path);
printf("otherpath: %s\n", otherpath);
#endif
/* TEST openl */
errno = 0;
fd = openl(path, O_RDONLY, 0);
check(openl, fd);
// no result ouput
ok(fstat, fd, &tstat);
// print the first bytes up to sz size
// ignore any errors
while ((n = read(fd, buf, sz)) != -1) {
if (write(1, buf, n) != n)
break;
if (n < sz)
break;
}
ok(close, fd);
/* TEST statl */
ok(statl, path, &tostat);
/* TEST chownl */
ok(chownl, path, 2, 3);
/* TEST chmodl */
ok(chmodl, path, 0452);
ok(statl, path, &tstat);
assert(tstat.st_uid == 2);
assert(tstat.st_gid == 3);
assert((tstat.st_mode & S_IAMB) == 0452);
/* TEST utimesl */
ok(utimesl, path, NULL);
ok(statl, path, &tstat);
assert(! tv_eq(tstat.st_atim, tostat.st_atim));
assert(! tv_eq(tstat.st_mtim, tostat.st_mtim));
/* XXX HERE */
/* TEST utimel */
ok(utimel, path, NULL);
/* chown back */
ok(chownl, path, tostat.st_uid, tostat.st_gid);
/* chmod back */
ok(chmodl, path, tostat.st_mode & S_IAMB);
/* check everything back ? */
ok(statl, path, &tstat);
assert(tstat.st_uid == tostat.st_uid);
assert(tstat.st_gid == tostat.st_gid);
assert(tstat.st_mode == tostat.st_mode);
test_file(path, otherpath);
test_dir(path, otherpath);
test_mktempl(path);
test_mkXstempXl(path);
test_mknodl(path);
test_mkfifol(path);
}
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment