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
This diff is collapsed.
# 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
This diff is collapsed.
/*-
* 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
This diff is collapsed.
/*-
* 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.
This diff is collapsed.
/*-
* 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