Compare commits

..
113 Commits
Author SHA1 Message Date
Joachim Nilsson 7172f487d5 Bump version for v1.9.0 GA release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-07-02 19:18:55 +02:00
Joachim Nilsson 4c0967405d Bump ABI version, removed UNUSED() added which(), fixed touch()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-07-02 19:18:55 +02:00
Joachim Nilsson fd65af31db Update HACKING document, mostly wrt library versioning
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-07-02 19:18:55 +02:00
Joachim Nilsson e55976d137 Update ChangeLog for v1.9 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-07-02 19:18:55 +02:00
Joachim Nilsson 1b1ffb33f1 Bump version to v1.9 due to new functionality, which()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-07-02 16:51:21 +02:00
Joachim Nilsson d018a5215f which.c: C implementation of UNIX which(1)
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-07-02 16:50:58 +02:00
Joachim Nilsson 0d70c116d7 Update .gitignore files
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-07-02 16:33:00 +02:00
Joachim Nilsson 32c774deef tree(): Refactor, flatten tree
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-07-02 16:32:04 +02:00
Joachim Nilsson 441d5f58d7 Add simple ocular unit test for printheader()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-06-30 20:28:31 +02:00
Joachim Nilsson 2a59289d53 conio.h: Add top-like heading macro, printheader()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-06-30 20:27:59 +02:00
Joachim Nilsson f89c3c88de Clear build warnings for unit tests
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-06-30 17:43:11 +02:00
Joachim Nilsson 705b402344 Remove UNUSED() macro, just use -Wno-unused instead
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-06-30 17:36:10 +02:00
Joachim Nilsson fe82ab953c Fix non-writable tempfile(), "rw" --> "w+", found by Westermo
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-06-18 18:18:08 +02:00
Joachim Nilsson 6ec2a31042 Update tempfile() unit test to detect failed write + read
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-06-18 18:14:39 +02:00
Joachim Nilsson 9f5e852084 Bump version in preparation for 1.8.4 bug-fix release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-05-20 09:29:26 +02:00
Joachim Nilsson 628c5597b9 Fix issue #6: touch does not update mtime if file exists
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-05-19 17:50:44 +02:00
Joachim Nilsson b7b635a3f4 Add unit test for touch to replicate issue #6
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-05-19 17:50:22 +02:00
Joachim Nilsson dd53c3ae9e Minor refactor of unit tests
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-05-19 17:50:07 +02:00
Joachim Nilsson 16a30a293c Add support for make package to build .deb files
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-03-12 17:43:53 +01:00
Joachim Nilsson 325fcbe149 lite.h: Add whitespace to compat macros, for readability
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-03-12 17:43:31 +01:00
Joachim Nilsson cbb1604ea0 New release for .deb package, 1.8.3-1
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-01-08 15:22:42 +01:00
Joachim Nilsson 8587971fb9 Update ChangeLog and bump version for v1.8.3 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-01-08 15:17:17 +01:00
Joachim Nilsson 6545ac8fd4 Bump ABI revision 3:0:0 --> 3:1:0
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-01-08 15:16:36 +01:00
Joachim Nilsson 9105e8d3d8 Update pidfile() documentation
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-01-08 15:16:00 +01:00
Joachim Nilsson 3555af6a6a Update ChangeLog and bump version for upcoming v1.8.3 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-01-07 13:58:59 +01:00
Joachim Nilsson 42715eab8a ChangeLog: Add missing link to v1.8.2 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-01-07 13:57:57 +01:00
Joachim Nilsson 497d58dbf0 ChangeLog: Minor Markdown fixes
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-01-07 13:57:21 +01:00
Joachim Nilsson 9ab70ebbcd Build all unit tests static, for easier debugging
- Add -static to LDFLAGS
- Remove CFLAGS override, respect input from configure script

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-01-07 13:00:08 +01:00
Joachim Nilsson bad363883d Fix leaky makepath() unit test
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-01-07 12:59:27 +01:00
Joachim Nilsson 7f3215b3e6 Update pidfile unit test to cover new use-case
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-01-07 12:59:02 +01:00
Joachim Nilsson 729cc5307f pidfile: Add support for absolute path
The OpenBSD version of pidfile() makes sure to place all PID files in
the same, canonical, location: _PATH_VARRUN.  On Linux, however, some
disitributions prefer to place PID files in a sub-directory under the
canonical location: _PATH_VARRUN + __progname/ ...

This patch adds support for creating PID files in any location. If the
PID file name argument starts with a '/', the function assumes the rest
of the string is the full PATH to the PID file.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-01-07 12:55:26 +01:00
Joachim Nilsson 66290d132f pidfile: Re-create file on consequetive calls if it doesn't exist
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-01-07 08:15:49 +01:00
Joachim Nilsson 59f7a78441 pidfile: Always initialize global variables
Always initialize global variables, even though they cannot be used in
current code paths without being initialized at runtime.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-01-07 08:15:42 +01:00
Joachim Nilsson b716776863 tests/pidfile: Cleanup test files from /tmp
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-01-07 06:53:21 +01:00
Joachim Nilsson 018ecaca15 debian/source/format: Change to native mode to allow building from GIT
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-01-07 04:10:21 +01:00
Joachim Nilsson a293c37777 debian/: Support for building .deb packages
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-11-29 08:32:06 +01:00
Joachim Nilsson a4937a93e2 Add reminder about umask()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-10-02 12:13:43 +02:00
Joachim Nilsson 94d547c9ec Unit test: fix search path for library header
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-09-05 00:19:52 +02:00
Joachim Nilsson 68cf8b6576 Update ChangeLog and bump version for v1.8.2 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-09-05 00:13:03 +02:00
Joachim Nilsson b6a55fcc46 Add err.h include to tests
lite.h no longer includes err.h it has to be included in each test.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-09-05 00:07:24 +02:00
Joachim Nilsson 5f29ef6413 Convert touch() et al to inline functions
The touch(), makedir(), makefifo(), and erase() macros print warnings to
stderr, which mess up the logging in Finit.  This patch refactors these
macros into inline functions and in the process removes the warn() use.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-09-04 23:58:32 +02:00
Joachim Nilsson 627c47caff Bump version for v1.8.2 devel
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-08-22 01:33:12 +02:00
Joachim Nilsson 7c2ed556b9 Replace \e GNUism w/ ISO \033 for escape sequences
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-08-22 01:31:49 +02:00
Joachim Nilsson 6dec4e3858 Extend lfile test with fstab parser
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-08-02 00:29:52 +02:00
Joachim Nilsson dff92356b3 Remove sys/cdefs.h include, does not exist in musl libc
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-07-19 15:39:57 +02:00
Joachim Nilsson 883c90112d Update modification date
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-07-04 12:46:44 +02:00
Joachim Nilsson a2c8dddaad Free pidfile_path atexit()
To prevent warnings from tools like Valgrind, or handle issues
with RAM leaks on non-MMU systems like uClinux, we must free
the memory allocated by pidfile().

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-07-04 12:42:22 +02:00
Joachim Nilsson 14f547b638 Add ldconfig to build instructions, thanks rooth!
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-30 18:53:59 +02:00
Joachim Nilsson 6f2a03bba7 Update ChangeLog & bump version for v1.8.1 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-25 12:50:21 +02:00
Joachim Nilsson cdfffa312b Update ChangeLog for upcoming v1.8.1 fix release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-08 07:18:30 +02:00
Joachim Nilsson 50cb72018f pidfile: Portability fix, utimensat() in sys/time.h
For building libite on NetBSD, and probably other BSD's as well.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-08 06:25:02 +02:00
Joachim Nilsson e8a3117158 fparseln: Portability fix _DIAGASSERT()
Only define _DIAGASSERT() if it's not already defined.
For building libite on NetBSD.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-08 06:23:34 +02:00
Joachim Nilsson 7cf2a3786c Bump version and ABI for v1.8.0 release
- Change from v1.7.1 to v1.8.0 due to amount of changes
  including ABI bump
- Update ChangeLog
- Bump library ABI version due to change in API semantics

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 19:05:26 +02:00
Joachim Nilsson 1c1d5c94e3 Clarify ABI versioning and encourage more unit tests
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 19:00:14 +02:00
Joachim Nilsson 23703c75da tests/dir.c: Remove nested checker function
Move nested check function is_startup_config() outside main().

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 18:15:47 +02:00
Joachim Nilsson efae15416c Bump version to -rc1, many changes since last release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 18:11:03 +02:00
Joachim Nilsson 661b4b4d0b Remove last remnants of old build/unit test framework
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 18:09:59 +02:00
Joachim Nilsson 682b662bd5 Add unit test for chomp()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 18:09:29 +02:00
Joachim Nilsson 75d4edb424 check.h: Add stdlib.h for exit()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 18:08:54 +02:00
Joachim Nilsson 141d4f6936 Add unit test for copyfile()/fcopyfile()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 17:59:52 +02:00
Joachim Nilsson 63aa6c5d07 Add unit test for dir()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 17:56:13 +02:00
Joachim Nilsson 1d698418c7 dir(): Do not assert(), return -1 and errno
The dir() function, although useless compared to glob(), called assert()
and perror() instead of returning an error code.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 17:56:13 +02:00
Joachim Nilsson 92d81280a9 Add unit test for fexist()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 17:45:19 +02:00
Joachim Nilsson 267465f3d2 Add unit test for fisdir()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 17:42:31 +02:00
Joachim Nilsson c22a6e64d9 Add unit test for progress bars
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 17:39:31 +02:00
Joachim Nilsson 16ae343df2 Add missing progress bar API's
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 17:39:31 +02:00
Joachim Nilsson 6e558e98f0 Add unit test for rsync
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 17:28:41 +02:00
Joachim Nilsson 69291d3e74 Add unit test for fsendfile()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 17:20:58 +02:00
Joachim Nilsson 6fdffeb355 fsendfile(): Change return type size_t --> ssize_t
Most send/recv/read/write API's return -1 on error and today use the
agreed upon type ssize_t for this purpose.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 17:19:54 +02:00
Joachim Nilsson b2f6721813 Clarify LITE file API in README
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 17:12:42 +02:00
Joachim Nilsson 3c350b8862 Add unit test for LITE file API
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 17:11:22 +02:00
Joachim Nilsson 5b786ce221 Add unit test for tempfile()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 17:07:14 +02:00
Joachim Nilsson 86b883e2af strdupa.h: Unify header guards with other headers
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 15:32:35 +02:00
Joachim Nilsson 2d6e8850a2 Add unit test for tree
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 15:32:35 +02:00
Joachim Nilsson d8cb477861 Ignore *.log and *.trs files in unit test dir
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 15:31:24 +02:00
Joachim Nilsson 27644677dd Clean *.trs and *.log files from unit test dir
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 15:31:24 +02:00
Joachim Nilsson 3588c9b01f Rename unit tests, drop _func suffix
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 15:31:24 +02:00
Joachim Nilsson ca3ea5ae92 Add unit test for mkpath() and makepath() funcs
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 15:31:23 +02:00
Joachim Nilsson 188d968f89 Remove previous pidfilefn() unit test makefile
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 15:03:56 +02:00
Joachim Nilsson 8e2c58501c Build all unit tests with -W -Wall -Wextra
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 14:02:36 +02:00
Joachim Nilsson 1da317ce1e Add missing signal.h include
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 14:02:27 +02:00
Joachim Nilsson fe39284d50 Travis-CI: Verify installation and run unit tests
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 12:42:33 +02:00
Joachim Nilsson c3c23b9aef Update ChangeLog for upcoming v1.7.1 fix release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 12:39:50 +02:00
Joachim Nilsson d45f2bad5b Update pidfile() description with hidden features
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 12:35:01 +02:00
Joachim Nilsson 61fb7aeca2 New unit test framework, first test pidfile funcs
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 12:30:35 +02:00
Joachim Nilsson dedcaf92d5 Minor style fix, to keep with pidfile.c style
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 12:16:14 +02:00
Joachim Nilsson c009c49a92 Expose __pidfile_path to override _PATH_VARRUN
This patch makes it possible to override the default pidfile() path used
for PID files, _PATH_VARRUN, with a custom path, e.g. _PATH_TMP.

This change does not affect the ABI of pidfile()

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 12:14:26 +02:00
Joachim Nilsson 12f619a320 Fix minor build error in new strndupa() header
Wrong path to local strnlen.h file.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 11:04:17 +02:00
Joachim Nilsson c1b3b76ea3 Update ChangeLog and bump version for v1.7.0 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-05 00:36:43 +02:00
Joachim Nilsson 8108b8ec14 Add HACKING.md for release policy ABI versioning etc.
Most of the text shamelessly stolen from the libConfuse project :)

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-04 19:01:18 +02:00
Joachim Nilsson 0e2d365eb9 Update ChangeLog with fixes and new features
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-04 18:56:07 +02:00
Joachim Nilsson 8b499aa9cd Add compat strnlen() implementation for non-GLIBC systems
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-04 18:51:25 +02:00
Joachim Nilsson f4fa44fe60 Add strndupa.h to distribution and update README
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-04 15:13:16 +02:00
Joachim Nilsson be08bcd09d strndupa.h: #error if building with non-GCC on non-GNU systems
At the moment only GCC is supported on non-GNU systems, unfortunately.
GNU systems usually have GLIBC, or another library with strndupa().
This strndupa() implementation requires GCC for the builtin alloca API.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-04 15:12:02 +02:00
Joachim Nilsson 1495a3f858 Add compat strndupa() implementation from libnostd
This patch adds compat support, to *BSD and other UNIX, for the GLIBC
strndupa() function.  The implementation is taken from libnostd written
by William Ahern.

http://www.25thandclement.com/~william/projects/libnostd.html

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-04 15:07:17 +02:00
Joachim Nilsson 5eb816b4c0 Update ChangeLog and README with new strdupa()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-03 23:12:50 +02:00
Valery Frolov 456c58d52d Add new headers, for strdupa(), to distribution
Signed-off-by: Valery Frolov <fvgenn@gmail.com>
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-03 23:08:08 +02:00
Joachim Nilsson 59869b876e strdupa.h: #error if building with non-GCC on non-GNU systems
At the moment only GCC is supported on non-GNU systems, unfortunately.
GNU systems usually have GLIBC, or another library with strdupa().  This
strdupa() implementation requires GCC for the builtin alloca API.

Followup to pull-request #4

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-02 19:51:43 +02:00
Joachim Nilsson 113c3487bd Add info on building directly from GIT
Followup to pullrequest #4

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-02 19:44:49 +02:00
Joachim Nilsson de73e268d3 Merge branch 'abs0-master'
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-05-30 22:32:43 +02:00
Joachim Nilsson b57c257f09 Cleanup of old shared rules.mk file, now only used by unit tests.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-05-30 22:31:59 +02:00
Joachim Nilsson 94d42b3df7 Add compat strdupa() implementation from libnostd
This patch adds compat support, to *BSD and other UNIX, for GLIBC
strdupa() function, used in mkpath().  The implementation is taken
from http://www.25thandclement.com/~william/projects/libnostd.html
by William Ahern.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-05-30 22:29:30 +02:00
Joachim Nilsson 94ad65a121 Factor out string functions to lite/strlite.h
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-05-30 22:27:41 +02:00
David Brownlee f3f6947604 Handle old Linux/(G)LIBC and UNIX systems the same
Linux systems pre Linux 3.11, and UNIX do not have the O_TMPFILE flag,
so let's treat them the same, by wrapping tmpfile().

Signed-off-by: David Brownlee <abs@absd.org>
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-05-30 21:05:21 +02:00
Joachim Nilsson 613d397161 Fix mkpath() to handle relative dirs
After input from both StackOverflow and Valery Frolov.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-05-23 09:15:50 +02:00
Joachim Nilsson 7df1b75fa0 Bump version for v1.6.0 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-05-13 07:22:25 +02:00
Joachim Nilsson 9b1b7ca4cf ChangeLog: Fix Markdown links in v1.6.0 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-05-13 07:21:45 +02:00
Joachim Nilsson 1e064b8b4d Update ChangeLog for v1.6.0 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-05-12 21:13:10 +02:00
Joachim Nilsson 18dde87f0a Add NetBSD fparseln(3) v1.10
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-05-09 19:14:05 +02:00
Joachim Nilsson fcb38c9cc5 Constify fisdir() argument
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-05-09 19:10:05 +02:00
Joachim Nilsson ab69ae8374 Add OpenBSD reallocarray(3) v1.2
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-05-09 00:37:05 +02:00
Joachim Nilsson 95f7a91a8a Bump version for v1.6.0 release cycle
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-05-09 00:33:16 +02:00
Joachim Nilsson aab5a1145c Remove Emacs version-control handling
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-05-07 22:35:49 +02:00
77 changed files with 2207 additions and 1057 deletions

No files matched your search

+1
View File
@@ -22,3 +22,4 @@ aclocal.m4
ar-lib
autom4te.cache
libite*
test-driver
+8 -7
View File
@@ -1,10 +1,8 @@
# Travis CI integration -- https://travis-ci.org/troglobit/libuev
# Travis CI integration -- https://travis-ci.org/troglobit/libite
# Defaults to GNU GCC and autotools: ./configure && make && make test
language: c
# Some of the autotests may use sudo, so use non-dockerized build atm.
# http://stackoverflow.com/questions/26299552/travis-sudo-is-disabled
#sudo: true
# Use docker for quicker builds, it now allows https://docs.travis-ci.com/user/apt/
sudo: false
# Test build with both GCC and Clang (LLVM)
@@ -12,8 +10,11 @@ compiler:
- gcc
- clang
# - make test
script:
- ./autogen.sh
- ./configure --disable-silent-rules
- make -j5 clean all
- ./configure --prefix=/tmp --disable-silent-rules
- make clean
- make -j5
- make install-strip
- ls -lR /tmp
- make check
+99 -1
View File
@@ -4,6 +4,95 @@ Change Log
All notable changes to the project are documented in this file.
[v1.9.0][] - 2017-07-02
-----------------------
### Changes
- Add `which()`, a C implementation of UNIX which(1)
- Add `printheader()`, prints a top-like table heading for client tools
- Remove `UNUSED()` macro, recommended to disable GCC warning instead
### Fixes
- Fix issue #6: `touch()` does not update mtime if file exists
- Fix non-writable `tempfile()`, now with proper unit test
[v1.8.3][] - 2017-01-08
-----------------------
### Changes
- Support absolute path in `pidfile()`. Needed by, e.g. Inadyn
- Add initial `debian/` packaging
- Update README with note on remembering to set `umask()`
### Fixes
- In use-cases when `pidfile()` is called consecutively, e.g. on
`SIGHUP`, recreate PID file if it no longer exists
[v1.8.2][] - 2016-09-05
-----------------------
### Changes
- Updated build instructions in README.
- Converted `touch()`, `makedir()`, `makefifo()`, and `erase()` from
macros to inline functions. Also removed implicit logging to stderr
on error.
### Fixes
- Fix small memory leak in `pidfile()` ... at exit.
- Fixes for building on musl libc
[v1.8.1][] - 2016-06-25
-----------------------
### Fixes
- `fparseln()`, portability fix for NetBSD
- `pidfile()`, portability fix for NetBSD and OpenBSD
[v1.8.0][] - 2016-06-06
-----------------------
### Changes
- Change return type of `fsendfile()` from `size_t` to `ssize_t`
- Change `dir()` semantics: do not assert and always return error
without calling `perror()` or similar.
- The OpenBSD `pidfile()` function's prefix path `_PATH_VARRUN`
can now be overridden by setting the hidden `__pidfile_path`
variable. E.g., to `_PATH_TMP`. Make sure read the docs!
- Add new unit test framework `make check`.
### Fixes
- Fix bad path in new `strndupa()` header file.
- Add missing progress bar API's to `lite.h`
[v1.7.0][] - 2016-06-05
-----------------------
### Changes
- Add support for GNU `strdupa()`, for [Inadyn][] on NetBSD.
- Add support for GNU `strndupa()` and `strnlen()`
### Fixes
- Fix `mkpath()` to handle creating relative directories.
[v1.6.0][] - 2016-05-13
-----------------------
### Changes
- Add support for NetBSD `fparaseln()` for the benefit of [Mg][]
- Add support for OpenBSD `reallocarray()` for the benefit of [Mg][]
- Constify `fisdir()` argument
[v1.5.1][] - 2016-04-17
-----------------------
@@ -155,7 +244,14 @@ problems this may cause!
Initial extraction of frog DNA from [Finit][]. See [README][] for API details.
[UNRELEASED]: https://github.com/troglobit/libite/compare/v1.5.1...HEAD
[UNRELEASED]: https://github.com/troglobit/libite/compare/v1.9.0...HEAD
[v1.9.0]: https://github.com/troglobit/libite/compare/v1.8.3...v1.9.0
[v1.8.3]: https://github.com/troglobit/libite/compare/v1.8.2...v1.8.3
[v1.8.2]: https://github.com/troglobit/libite/compare/v1.8.1...v1.8.2
[v1.8.1]: https://github.com/troglobit/libite/compare/v1.8.0...v1.8.1
[v1.8.0]: https://github.com/troglobit/libite/compare/v1.7.0...v1.8.0
[v1.7.0]: https://github.com/troglobit/libite/compare/v1.6.0...v1.7.0
[v1.6.0]: https://github.com/troglobit/libite/compare/v1.5.1...v1.6.0
[v1.5.1]: https://github.com/troglobit/libite/compare/v1.5.0...v1.5.1
[v1.5.0]: https://github.com/troglobit/libite/compare/v1.4.4...v1.5.0
[v1.4.4]: https://github.com/troglobit/libite/compare/v1.4.3...v1.4.4
@@ -169,6 +265,8 @@ Initial extraction of frog DNA from [Finit][]. See [README][] for API details.
[v1.1.0]: https://github.com/troglobit/libite/compare/v1.0.0...v1.1.0
[v1.0.0]: https://github.com/troglobit/libite/compare/TAIL...v1.0.0
[Finit]: https://github.com/troglobit/finit/
[Inadyn]: https://github.com/troglobit/inadyn/
[Mg]: https://github.com/troglobit/mg
[README]: https://github.com/troglobit/libite/blob/v1.0.0/README.md
<!--
+104
View File
@@ -0,0 +1,104 @@
Maintenance and Release Checklist
=================================
Maintenance
-----------
* Encourage contributors to write tests, in particular for new features
* Run tests regularly, use Travis-CI to do this automatically
* Leverage GitHub issues for milestone planning
* Reference issues from GitHub pull requests to alert issue subscribers
* Bump library ABI version just before release!
Release Checklist
-----------------
* Update ChangeLog, follow http://keepachangelog.com/ loosely
- Inform users in a plain language of changes and bug fixes
- Do *not* copy-paste GIT commit logs!
- Order entrys according to importance, most relevant first
* Run unit tests: `make check`
* Do we need to bump the ABI version? (Probably, see below)
* Tag
* Push last commit(s) *and* tags to GitHub
* Make release
make distclean
./autogen.sh
./configure
make release
* Create new release in GitHub releases page
* Copy and paste ChangeLog entry, check any stale links!
* Upload release tarball and MD5 files
Library Versioning
------------------
Libite (-lite) relies on GNU Libtool for building the library. For a
user of the library it is important to maintain a clear ABI versioning
scheme. This is not the same as the library version, but rather the
library "compatibility level".
The ABI version is specified in `src/Makefile.am` and looks like this:
libite_la_LDFLAGS = -version-info 0:0:0
\ \ `-- age
\ `--- revision
`---- current
It must be updated according to the [GNU Libtool recommendations][1]:
1. Start with version information of `0:0:0` for each libtool library.
2. Update the version information only immediately before a public
release of your software. More frequent updates are unnecessary, and
only guarantee that the current interface number gets larger faster.
3. If the library *source code has changed at all* since the last update,
then increment revision (`c:r:a` becomes `c:r+1:a`).
4. If any *interfaces have been added, removed, or changed* since the
last update, increment current, and set revision to 0.
5. If any *interfaces have been added* since the last public release,
then increment age.
6. If any *interfaces have been removed or changed* since the last
public release, then set age to 0.
The libtool ABI versioning logic is very confusing but works if you just
disable your brain and follow the rules, one by one.
**Example #1:** a new function has been added, none of the existing ones
have changed. The initial version is 1:0:0, we follow the rules above to
the letter: increase revision, increase current and set revision to zero,
and finally increase age. This, rather confusingly, gives us 2:0:1 which
libtool then translates to `libconfuse.so.1.1.0`.
**Example #2:** some existing functions are changed, they now return an
`int` instead of `void`. The initial version is 0:0:0, and we follow the
rules again: increment revision, increment current and set revision to
zero, set age to zero. This gives us 1:0:0, which is then translated to
`libconfuse.so.1.0.0`.
### Note
Usually, non-developers have no interest in running development versions
(releases are frequent enough), and developers are expected to know how
to juggle versions. In such an ideal world, it is good enough to bump
the library version just prior to a release, point 2.
However, if releases are few and far between, distributors may start to
use snapshots. When a distributor uses a snapshot, the distributor has
to handle the library version manually. Things can get ugly when the
distributor has released an intermediate version with a bumped library
version, and when the official release is bumped to that version, the
distributor will then have to bump the library version for the official
release, and it can be confusing if someone reports bugs on versions
that you didn't even know existed.
The problem with bumping the version with every change is that if your
interface is not finished, the version number might run away, and it
looks pretty bad if a library is at version 262. It kind of tells the
user that the library interface is volatile, which is not good for
business.
[1]: https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
+31 -25
View File
@@ -2,49 +2,55 @@ ACLOCAL_AMFLAGS = -I m4
lib_LTLIBRARIES = libite.la
pkgincludedir = $(includedir)/lite
pkginclude_HEADERS = lite.h queue.h conio.h tree.h
libite_la_SOURCES = chomp.c copyfile.c dir.c fexist.c fisdir.c fmode.c fsendfile.c \
ifconfig.c lfile.c makepath.c pidfile.c pidfilefn.c progress.c \
rsync.c strlcpy.c strlcat.c strtonum.c tempfile.c tree.c
pkginclude_HEADERS = lite.h queue.h conio.h tree.h strlite.h strdupa.h strndupa.h strnlen.h
libite_la_SOURCES = chomp.c copyfile.c dir.c fexist.c fisdir.c fmode.c fparseln.c \
fsendfile.c ifconfig.c lfile.c makepath.c pidfile.c pidfilefn.c \
progress.c reallocarray.c rsync.c strlcpy.c strlcat.c strtonum.c \
tempfile.c tree.c which.c
libite_la_CPPFLAGS = -D_GNU_SOURCE
libite_la_CFLAGS = -W -Wall -Wextra
libite_la_LDFLAGS = $(AM_LDFLAGS) -version-info 2:2:0
libite_la_LDFLAGS = $(AM_LDFLAGS) -version-info 4:0:0
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libite.pc
doc_DATA = README.md LICENSE
EXTRA_DIST = README.md LICENSE ChangeLog.md
SUBDIRS = tests
## Generate .deb package
package:
@dpkg-buildpackage -uc -us -B
## Generate MD5 checksum file
MD5 = md5sum
md5-dist:
@for file in $(DIST_ARCHIVES); do \
$(MD5) $$file > $$file.md5; \
@for file in $(DIST_ARCHIVES); do \
$(MD5) $$file > $$file.md5; \
done
## Check if tagged in git
release-hook:
if [ ! `git tag | grep $(PACKAGE_VERSION)` ]; then \
echo; \
printf "\e[1m\e[41mCannot find release tag $(PACKAGE_VERSION)\e[0m\n"; \
printf "\e[1m\e[5mDo release anyway?\e[0m "; read yorn; \
if [ "$$yorn" != "y" -a "$$yorn" != "Y" ]; then \
printf "OK, aborting release.\n"; \
exit 1; \
fi; \
echo; \
else \
echo; \
printf "\e[1m\e[42mFound GIT release tag $(PACKAGE_VERSION)\e[0m\n"; \
printf "\e[1m\e[44m>>Remember to push tags!\e[0m\n"; \
echo; \
if [ ! `git tag | grep $(PACKAGE_VERSION)` ]; then \
echo; \
printf "\033[1m\033[41mCannot find release tag $(PACKAGE_VERSION)\033[0m\n"; \
printf "\033[1m\033[5mDo release anyway?\033[0m "; read yorn; \
if [ "$$yorn" != "y" -a "$$yorn" != "Y" ]; then \
printf "OK, aborting release.\n"; \
exit 1; \
fi; \
echo; \
else \
echo; \
printf "\033[1m\033[42mFound GIT release tag $(PACKAGE_VERSION)\033[0m\n"; \
printf "\033[1m\033[44m>>Remember to push tags!\033[0m\n"; \
echo; \
fi
## Target to run when building a release
release: dist release-hook md5-dist
@for file in $(DIST_ARCHIVES); do \
printf "$$file \tDistribution tarball\n"; \
printf "$$file.md5\t"; cat $$file.md5 | cut -f1 -d' '; \
mv $$file* ../; \
@for file in $(DIST_ARCHIVES); do \
printf "$$file \tDistribution tarball\n"; \
printf "$$file.md5\t"; cat $$file.md5 | cut -f1 -d' '; \
mv $$file* ../; \
done
+76 -26
View File
@@ -70,6 +70,14 @@ and in your `Makefile.am`:
proggy_LDADD = $(lite_LIBS)
Important Note
--------------
When using functions like `mkpath()`, `makepath()`, and `makefifo()`,
make sure your `umask()` is correct so you do not accidentally create
files and directories accessible to other users than intended.
Helper Macros
-------------
@@ -135,10 +143,6 @@ Helper Macros
Returns the number of elements in an array. From the great book, The
Practice of Programming, by Kernighan and Pike.
- `UNUSED(var)`
Shorter and more readable version of `var __attribute__ ((unused))`
Generic Functions
-----------------
@@ -155,7 +159,8 @@ Generic Functions
Wrapper for `scandir()` with optional filter. Returns a list of
names: files and directories that must be freed after use. See
the unit test at the bottom for an example.
the unit test for an example, or take a look at `glob(3)`, it's
probably what you want anyway.
- `fcopyfile(src, dst)`
@@ -187,8 +192,8 @@ Generic Functions
- `lfopen(file, sep)`, `lfclose(lf)`
API for parsing UNIX style configuration files like `/etc/protocols`
and `/etc/services`.
LITE file API for parsing UNIX style configuration files like
`/etc/protocols` and `/etc/services`.
- `lftok(lf)`
@@ -222,11 +227,13 @@ Generic Functions
with the `dst` name. On successful operation the source is removed
and the function returns POSIX OK (0).
- `pidfile(basename)`
- `pidfile(name)`
Create a daemon PID file in `_PATH_VARRUN` using either `basename` or,
if `basename` is `NULL`, `__progname`. The resulting file name is
available to the user as a read-only pointer:
Create a daemon PID file using either the `name` as a full path, if
`name` starts with `/`, or in `_PATH_VARRUN` using `name` as the
basename of the application. If `name` is `NULL`, then `__progname`
is used as the basename. The resulting file name is available to the
user as a read-only pointer:
extern char *__pidfile_name;
@@ -237,14 +244,14 @@ Generic Functions
The PID file is removed when the program exits, using an `atexit()`
handler. However, depending on how the program terminates the file
may still exist even though the program is no longer running. This
is only a problem for clients.
may still exist even though the program is no longer running.
Calling this function multiple times updates the mtime of the file.
Only one `atexit()` handler is created, regardless of the amount of
times the function is called.
times the function is called. If the file is removed, subsequent
calls to this function will recreate the file.
See below for link to OpenBSD man page.
See below for a link to OpenBSD man page.
- `pidfile_read(pidfile)`
@@ -281,20 +288,57 @@ Generic Functions
optional listing of file and directory permissions if `show_perms` is
set. The `path` argument should be a directory.
- `which(cmd)`
OpenBSD Functions
-----------------
C implementation of UNIX which(1). Returns a malloc'ed string with the
full path to `cmd` on success, otherwise `NULL`.
The following are popular OpenBSD functions and highly useful macros.
GNU Functions
-------------
The following are useful GNU functions, that do not exist on *BSD, and
some other platforms.
- `strdupa(str)`
http://man7.org/linux/man-pages/man3/strdupa.3.html
- `strndupa(str)`
http://man7.org/linux/man-pages/man3/strndupa.3.html
- `strnlen(str, lim)`
http://man7.org/linux/man-pages/man3/strnlen.3.html
OpenBSD/NetBSD/FreeBSD Functions
--------------------------------
The following are popular functions and highly useful macros from the
*BSD world of UNIX that are sadly missing on Linux.
- `fparseln(fp, *len, *lineno, delim, flags)`
http://man.openbsd.org/OpenBSD-current/man3/fparseln.3
- `pidfile(basename)`
http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man3/pidfile.3
**Note:** this version of `pidfile()` has been extended to handle it
being called multiple times, and also to export the path to the PID
file `__pidfile_name`, similar to `__progname`. See previous section
for details.
**Note:** the version of `pidfile()` in -lite has been extended to
handle it being called multiple times, i.e. to not create multiple
`atexit()` handlers, and also to export a few internal paths:
- `__pidfile_path`: prefix path, default `_PATH_VARRUN`. Notice the
trailing slash requirement if you want to override it!
- `__pidfile_name`: full path to PID file , similar to `__progname`.
See previous section for details.
- `reallocarray(ptr, nmemb, size)`
http://man.openbsd.org/OpenBSD-current/man3/reallocarray.3
- `strlcpy(dst, src, len)`
@@ -322,13 +366,19 @@ The following are popular OpenBSD functions and highly useful macros.
Build & Install
---------------
The library is built for and developed on GNU/Linux systems as a light
weight utility library. Libite (LITE) employs the de facto standard GNU
configure and build system:
This library was initially built for and developed on GNU/Linux systems
as a light weight utility library, these days NetBSD should also work.
Libite (LITE) employs the de facto standard GNU configure and build
system:
./configure
make -j5
make install-strip
sudo make install-strip
sudo ldconfig
**Note:** When checking code from GitHub, use <kbd>./autogen.sh</kbd> to
generate a `configure` script. It is a generated file and otherwise only
included in released tarballs.
TODO
-11
View File
@@ -45,19 +45,8 @@ char *chomp(char *str)
return str;
}
#ifdef UNITTEST
#include <stdio.h>
int main(void)
{
int i; char t[][16] = { "hej\ndej", "Slime\n\n\\n", "Tripple\n\n\n", "" };
for (i = 0; t[i][0]; i++) printf("[%02d]: '%s'\n", i, chomp(t[i])); return 0;
}
#endif
/**
* Local Variables:
* compile-command: "make V=1 -f chomp.mk"
* version-control: t
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
-4
View File
@@ -1,4 +0,0 @@
OBJS =
TARGET = chomp.test clean
include rules.mk
+2 -2
View File
@@ -1,10 +1,10 @@
AC_INIT(libite, 1.5.1, https://github.com/troglobit/libite/issues)
AC_INIT(libite, 1.9.0, https://github.com/troglobit/libite/issues)
AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz])
AM_SILENT_RULES([yes])
AC_CONFIG_SRCDIR(lite.h)
AM_CONFIG_HEADER(config.h)
AC_CONFIG_FILES([Makefile libite.pc])
AC_CONFIG_FILES([Makefile tests/Makefile libite.pc])
AC_CONFIG_MACRO_DIR([m4])
AC_PROG_CC
+16 -9
View File
@@ -48,34 +48,41 @@
#define LIGHTCYAN 0x16
#define WHITE 0x17
#ifndef SCREEN_WIDTH
#define SCREEN_WIDTH 80 /* Override as #define SCREEN_WIDTH tty_width() */
#endif
/* Esc[2JEsc[1;1H - Clear screen and move cursor to 1,1 (upper left) pos. */
#define clrscr() fputs ("\e[2J\e[1;1H", stdout)
#define clrscr() fputs ("\033[2J\033[1;1H", stdout)
/* Esc[K - Erases from the current cursor position to the end of the current line. */
#define clreol() fputs ("\e[K", stdout)
#define clreol() fputs ("\033[K", stdout)
/* Esc[2K - Erases the entire current line. */
#define delline() fputs ("\e[2K", stdout)
#define delline() fputs ("\033[2K", stdout)
/* Esc[Line;ColumnH - Moves the cursor to the specified position (coordinates) */
#define gotoxy(x,y) printf("\e[%d;%dH", y, x)
#define gotoxy(x,y) printf("\033[%d;%dH", y, x)
/* Esc[?25l (lower case L) - Hide Cursor */
#define hidecursor() fputs ("\e[?25l", stdout)
#define hidecursor() fputs ("\033[?25l", stdout)
/* Esc[?25h (lower case H) - Show Cursor */
#define showcursor() fputs ("\e[?25h", stdout)
#define showcursor() fputs ("\033[?25h", stdout)
/* Esc[Value;...;Valuem - Set Graphics Mode */
#define __set_gm(attr,color,val) \
if (!color) \
printf("\e[%dm", attr); \
printf("\033[%dm", attr); \
else \
printf("\e[%d;%dm", color & 0x10 ? 1 : 0, (color & 0xF) + val)
printf("\033[%d;%dm", color & 0x10 ? 1 : 0, (color & 0xF) + val)
#define textattr(attr) __set_gm(attr, 0, 0)
#define textcolor(color) __set_gm(RESETATTR, color, 30)
#define textbackground(color) __set_gm(RESETATTR, color, 40)
#define printheader(fp, line, nl) \
fprintf(fp ?: stdout, "%s\033[7m%s%*s\033[0m\n", nl ? "\n" : "",\
line, SCREEN_WIDTH - (int)strlen(line), "")
#endif /* CONIO_H_ */
/**
* Local Variables:
* version-control: t
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
-62
View File
@@ -23,13 +23,9 @@
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include "lite.h"
/* Tests if dst is a directory, if so, reallocates dst and appends src filename returning 1 */
static int adjust_target(char *src, char **dst)
{
@@ -256,66 +252,8 @@ int fcopyfile(FILE *src, FILE *dst)
return 0;
}
#ifdef UNITTEST
#include <err.h>
int main(void)
{
int i = 0;
char *files[] = {
"/etc/passwd", "/tmp/mypwd", "/tmp/mypwd",
"/etc/passwd", "/tmp/", "/tmp/passwd",
"/etc/passwd", "/tmp", "/tmp/passwd",
NULL
};
FILE *src, *dst;
printf("=>Start testing fcopyfile()\n");
while (files[i]) {
printf("fcopyfile(%s, %s)\t", files[i], files[i + 1]);
src = fopen(files[i], "r");
dst = fopen(files[i + 1], "w");
if (fcopyfile(src, dst)) {
if (!fisdir(files[i + 1]))
err(1, "Failed fcopyfile(%s, %s)", files[i], files[i + 1]);
}
if (src)
fclose(src);
if (dst)
fclose(dst);
if (fexist(files[i + 2]))
printf("OK => %s", files[i + 2]);
printf("\n");
erase(files[i + 2]);
i += 3;
}
printf("\n=>Start testing copyfile()\n");
i = 0;
while (files[i]) {
printf("copyfile(%s, %s)\t", files[i], files[i + 1]);
if (!copyfile(files[i], files[i + 1], 0, 0))
err(1, "Failed copyfile(%s, %s)", files[i], files[i + 1]);
if (fexist(files[i + 2]))
printf("OK => %s", files[i + 2]);
printf("\n");
erase(files[i + 2]);
i += 3;
}
return 0;
}
#endif /* UNITTEST */
/**
* Local Variables:
* compile-command: "make V=1 -f copyfile.mk"
* version-control: t
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
-4
View File
@@ -1,4 +0,0 @@
OBJS = fisdir.o fexist.o fmode.o
TARGET = $(OBJS) copyfile.test clean
include rules.mk
+8
View File
@@ -0,0 +1,8 @@
tmp/*
libuev/*
libuev*
autoreconf*
debhelper*
files
!*.dirs
!*.install
+11
View File
@@ -0,0 +1,11 @@
libite (1.8.3-1) unstable; urgency=low
* New upstream reelase.
-- Joachim Nilsson <troglobit@gmail.com> Sun, 08 Jan 2017 15:22:26 +0100
libite (1.8.2-1) unstable; urgency=low
* Initial release.
-- Joachim Nilsson <troglobit@gmail.com> Tue, 29 Nov 2016 08:23:35 +0100
+1
View File
@@ -0,0 +1 @@
config.log
+1
View File
@@ -0,0 +1 @@
9
+51
View File
@@ -0,0 +1,51 @@
Source: libite
Priority: optional
Maintainer: Joachim Nilsson <troglobit@gmail.com>
Build-Depends: dpkg-dev (>= 1.14.9), debhelper (>= 9), dh-autoreconf
Standards-Version: 3.9.6
Section: libs
Homepage: https://github.com/troglobit/libite/
Vcs-Git: https://github.com/troglobit/libite.git
Vcs-Browser: https://github.com/troglobit/libite/
Package: libite-dev
Priority: extra
Section: libdevel
Architecture: any
Depends: ${misc:Depends}, libite (= ${binary:Version})
Description: static library, header files, and docs for libite
Static library, header files, and documentation for libite.
.
Libite is a lightweight library of frog DNA. It can be used to fill the
gaps in any dinosaur project. It holds useful functions and macros
developed by both Finit and the OpenBSD project. Most notably the
string functions: strlcpy(3), strlcat(3) and the highly useful *BSD
sys/queue.h and sys/tree.h API's.
.
Libite is the frog DNA missing in GNU libc. However, -lite does not aim
to become another GLIB! One noticeable gap in GLIBC is the missing
_SAFE macros in the BSD sys/queue.h API — highly recommended when
traversing lists to delete/free nodes.
.
The code is open sourced under a mix of the MIT/X11 license, the ISC
license used by OpenBSD, and BSD licenses, all of them are extremely
liberal and can be used freely in proprietary software if needed.
Package: libite
Architecture: any
Depends: ${misc:Depends}, ${shlibs:Depends}
Description: That missing frog DNA you've been looking for. MIT/X11/ISC/BSD License.
Libite is a lightweight library of frog DNA. It can be used to fill the
gaps in any dinosaur project. It holds useful functions and macros
developed by both Finit and the OpenBSD project. Most notably the
string functions: strlcpy(3), strlcat(3) and the highly useful *BSD
sys/queue.h and sys/tree.h API's.
.
Libite is the frog DNA missing in GNU libc. However, -lite does not aim
to become another GLIB! One noticeable gap in GLIBC is the missing
_SAFE macros in the BSD sys/queue.h API — highly recommended when
traversing lists to delete/free nodes.
.
The code is open sourced under a mix of the MIT/X11 license, the ISC
license used by OpenBSD, and BSD licenses, all of them are extremely
liberal and can be used freely in proprietary software if needed.
+84
View File
@@ -0,0 +1,84 @@
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Source: https.//github.com/troglobit/libite/
Files: *
Copyright:
2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
2008-2016 Joachim Nilsson <troglobit@gmail.com>
License: MIT
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Files: chomp.c
Copyright: 2014-2015 Joachim Nilsson <troglobit@gmail.com>
License: ISC
Files: conio.h
Copyright: 2009-2013 Joachim Nilsson <troglobit@gmail.com>
License: ISC
Files: dir.c
Copyright: 2008-2016 Joachim Nilsson <troglobit@gmail.com>
License: ISC
Files: lfile.c
Copyright: 2015-2016 Joachim Nilsson <troglobit@gmail.com>
License: ISC
Files: pidfile.c
Copyright: 1999 The NetBSD Foundation, Inc.
License: BSD-2-clause
Files: queue.h
Copyright: 1991, 1993 The Regents of the University of California.
License: BSD-3-clause
Files: reallocarray.c
Copyright: 2008 Otto Moerbeek <otto@drijf.net>
License: ISC
Files: rsync.c
Copyright: 2011, 2012 Joachim Nilsson <troglobit@gmail.com>
License: ISC
Files: strdupa.h strndupa.h
Copyright: 2009 William Ahern
License: MIT
Files: strlcat.c strlcpy.c
Copyright: 998, 2015 Todd C. Miller <Todd.Miller@courtesan.com>
License: MIT
Files: strnlen.c
Copyright: 2016 Joachim Nilsson <troglobit@gmail.com>
License: ISC
Files: strtonum.c
Copyright: 2004 Ted Unangst and Todd Miller
License: ISC
Files: tempfile.c
Copyright: 2015-2016 Joachim Nilsson <troglobit@gmail.com>
License: ISC
Files: tree.c
Copyright: 2015 Joachim Nilsson <troglobit@gmail.com>
License: ISC
Files: tests/*.c
License: public-domain
Vendored
+1
View File
@@ -0,0 +1 @@
README.md
+2
View File
@@ -0,0 +1,2 @@
usr/lib
usr/include
+4
View File
@@ -0,0 +1,4 @@
usr/include/lite/*.h
usr/lib/*/lib*.a
usr/lib/*/lib*.so
usr/lib/*/pkgconfig/lib*.pc
+1
View File
@@ -0,0 +1 @@
usr/lib
+1
View File
@@ -0,0 +1 @@
usr/lib/*/lib*.so.*
Vendored Executable
+8
View File
@@ -0,0 +1,8 @@
#!/usr/bin/make -f
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
%:
dh $@ --with autoreconf
+1
View File
@@ -0,0 +1 @@
3.0 (native)
+13 -110
View File
@@ -1,6 +1,6 @@
/* Functions for operating on files in directories.
*
* Copyright (c) 2008-2014 Joachim Nilsson <troglobit@gmail.com>
* Copyright (c) 2008-2016 Joachim Nilsson <troglobit@gmail.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -15,14 +15,14 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <assert.h>
#include <errno.h>
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static const char *matcher_type = NULL;
static int (*matcher_filter) (const char *file) = NULL;
static int matcher(const struct dirent *entry)
{
char *pos = strrchr(entry->d_name, '.');
@@ -72,7 +72,8 @@ static int matcher(const struct dirent *entry)
* would be returned as "config0".
*
* Returns:
* Number of files in @list, zero if no matching files of @type.
* Number of files in @list, zero if no matching files of @type, or
* non-zero on error with @errno set.
*/
int dir(const char *dir, const char *type, int (*filter) (const char *file), char ***list, int strip)
{
@@ -80,7 +81,10 @@ int dir(const char *dir, const char *type, int (*filter) (const char *file), cha
char **files;
struct dirent **namelist;
assert(list);
if (!list) {
errno = EINVAL;
return -1;
}
if (!dir)
/* Assuming current directory */
@@ -92,9 +96,10 @@ int dir(const char *dir, const char *type, int (*filter) (const char *file), cha
matcher_type = type;
matcher_filter = filter;
n = scandir(dir, &namelist, matcher, alphasort);
if (n < 0) {
perror("scandir");
} else if (n > 0) {
if (n < 0)
return -1;
if (n > 0) {
files = (char **)malloc(n * sizeof(char *));
for (i = 0; i < n; i++) {
if (files) {
@@ -119,110 +124,8 @@ int dir(const char *dir, const char *type, int (*filter) (const char *file), cha
return num;
}
#ifdef UNITTEST
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "lite.h"
#define DIR_TYPE_IMAGE ".img"
#define DIR_TYPE_SYSLOG ""
#define DIR_TYPE_CONFIG ".cfg"
#define STARTUP_CONFIG "startup-config.cfg"
int simulate_files(int creat)
{
int i;
char *files[] =
{ "config0.cfg", "config1.cfg", "config2.cfg", "config3.cfg",
"rr109.img", "rx100.img", "rx107.img", "rm957.img", "messages"
};
for (i = 0; i < NELEMS(files); i++) {
if (creat)
touch(files[i]);
else
erase(files[i]);
}
if (creat)
symlink("config2.cfg", STARTUP_CONFIG);
else
erase(STARTUP_CONFIG);
return 0;
}
static int cfg_dir_filter(const char *file)
{
/* Skip the STARTUP_CONFIG file, it is a symbolic link to the
* current startup configuration. */
return ! !strcmp(file, STARTUP_CONFIG);
}
int main(int argc, char *argv[])
{
int i, num;
char *type = DIR_TYPE_CONFIG;
char **files;
int once = 1;
int is_startup_config(const char *entry) {
static char file[80];
if (once) {
int len = readlink(STARTUP_CONFIG, file, sizeof(file));
if (len == -1)
return 0;
file[len] = 0;
once = 0; /* Only once per call to dir() */
}
//printf ("Comparing link %s with entry %s\n", file, entry);
return !strcmp(file, entry);
}
simulate_files(1);
if (argc >= 2) {
if (!strcasecmp("CONFIG", argv[1])) {
type = DIR_TYPE_CONFIG;
system("ls -l *" DIR_TYPE_CONFIG);
}
if (!strcasecmp("IMAGE", argv[1])) {
type = DIR_TYPE_IMAGE;
system("ls -l *" DIR_TYPE_IMAGE);
}
if (!strcasecmp("SYSLOG", argv[1])) {
type = DIR_TYPE_SYSLOG;
system("ls -l *");
}
}
num = dir(NULL, type, cfg_dir_filter, &files, 0);
if (num) {
for (i = 0; i < num; i++) {
printf("%s", files[i]);
if (is_startup_config(files[i]))
printf(" --> startup-config");
printf("\n");
free(files[i]);
}
free(files);
}
simulate_files(0);
return 0;
}
#endif /* UNITTEST */
/**
* Local Variables:
* compile-command: "make V=1 -f dir.mk"
* version-control: t
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
-4
View File
@@ -1,4 +0,0 @@
OBJS =
TARGET = dir.test clean
include rules.mk
-29
View File
@@ -44,37 +44,8 @@ int fexist(char *file)
return 1;
}
#ifdef UNITTEST
#include "lite.h"
int main(void)
{
int i = 0;
struct { char *file; int exist; } arr[] = {
{ "/etc/passwd", 1 },
{ "/etc/kalle", 0 },
{ "/sbin/init", 1 },
{ "/dev/null", 1 },
{ NULL, 0 },
};
FILE *src, *dst;
for (i = 0; i < NELEMS(arr); i++) {
if (fexist(arr[i].file) != arr[i].exist)
err(1, "Failed fexist(%s)", arr[i].file ?: "NULL");
else
printf("File %-11s %-14s => OK!\n", arr[i].file ?: "NULL",
arr[i].exist ? "does exist" : "does not exist");
}
return 0;
}
#endif /* UNITTEST */
/**
* Local Variables:
* compile-command: "make V=1 -f fexist.mk"
* version-control: t
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
-4
View File
@@ -1,4 +0,0 @@
OBJS =
TARGET = fexist.test clean
include rules.mk
+1 -32
View File
@@ -21,7 +21,6 @@
* THE SOFTWARE.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
@@ -32,7 +31,7 @@
* Returns:
* %TRUE(1) if the file exists and is a directory, otherwise %FALSE(0).
*/
int fisdir(char *file)
int fisdir(const char *file)
{
struct stat sb;
@@ -42,38 +41,8 @@ int fisdir(char *file)
return 0;
}
#ifdef UNITTEST
#include "lite.h"
int main(void)
{
int i = 0;
struct { char *file; int exist; } arr[] = {
{ "/etc/passwd", 0 },
{ "/etc/", 1 },
{ "/sbin/init", 0 },
{ "/dev/null", 0 },
{ "/dev/", 1 },
{ NULL, 0 },
};
FILE *src, *dst;
for (i = 0; i < NELEMS(arr); i++) {
if (fisdir(arr[i].file) != arr[i].exist)
err(1, "Failed fisdir(%s)", arr[i].file ?: "NULL");
else
printf("fisdir() %-11s %-18s => OK!\n", arr[i].file ?: "NULL",
arr[i].exist ? "is a directory" : "is NOT a directory");
}
return 0;
}
#endif /* UNITTEST */
/**
* Local Variables:
* compile-command: "make V=1 -f fisdir.mk"
* version-control: t
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
-4
View File
@@ -1,4 +0,0 @@
OBJS =
TARGET = fisdir.test clean
include rules.mk
-1
View File
@@ -50,7 +50,6 @@ mode_t fmode(char *file)
/**
* Local Variables:
* version-control: t
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
+199
View File
@@ -0,0 +1,199 @@
/* $NetBSD: fparseln.c,v 1.10 2009/10/21 01:07:45 snj Exp $ */
/*
* Copyright (c) 1997 Christos Zoulas. 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 ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR 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.
*/
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "lite.h"
#ifndef _DIAGASSERT
#define _DIAGASSERT(t)
#endif
static int isescaped(const char *, const char *, int);
/* isescaped():
* Return true if the character in *p that belongs to a string
* that starts in *sp, is escaped by the escape character esc.
*/
static int
isescaped(const char *sp, const char *p, int esc)
{
const char *cp;
size_t ne;
_DIAGASSERT(sp != NULL);
_DIAGASSERT(p != NULL);
/* No escape character */
if (esc == '\0')
return 0;
/* Count the number of escape characters that precede ours */
for (ne = 0, cp = p; --cp >= sp && *cp == esc; ne++)
continue;
/* Return true if odd number of escape characters */
return (ne & 1) != 0;
}
/* fparseln():
* Read a line from a file parsing continuations ending in \
* and eliminating trailing newlines, or comments starting with
* the comment char.
*/
char *
fparseln(FILE *fp, size_t *size, size_t *lineno, const char str[3], int flags)
{
static const char dstr[3] = { '\\', '\\', '#' };
ssize_t s;
size_t len, ptrlen;
char *buf;
char *ptr, *cp;
int cnt;
char esc, con, nl, com;
_DIAGASSERT(fp != NULL);
len = 0;
buf = NULL;
ptrlen = 0;
ptr = NULL;
cnt = 1;
if (str == NULL)
str = dstr;
esc = str[0];
con = str[1];
com = str[2];
/*
* XXX: it would be cool to be able to specify the newline character,
* getdelim(3) does let us, but supporting it would diverge from BSDs.
*/
nl = '\n';
flockfile(fp);
while (cnt) {
cnt = 0;
if (lineno)
(*lineno)++;
s = getline(&ptr, &ptrlen, fp);
if (s < 0)
break;
if (s && com) { /* Check and eliminate comments */
for (cp = ptr; cp < ptr + s; cp++)
if (*cp == com && !isescaped(ptr, cp, esc)) {
s = cp - ptr;
cnt = s == 0 && buf == NULL;
break;
}
}
if (s && nl) { /* Check and eliminate newlines */
cp = &ptr[s - 1];
if (*cp == nl)
s--; /* forget newline */
}
if (s && con) { /* Check and eliminate continuations */
cp = &ptr[s - 1];
if (*cp == con && !isescaped(ptr, cp, esc)) {
s--; /* forget continuation char */
cnt = 1;
}
}
if (s == 0) {
/*
* nothing to add, skip realloc except in case
* we need a minimal buf to return an empty line
*/
if (cnt || buf != NULL)
continue;
}
if ((cp = realloc(buf, len + s + 1)) == NULL) {
funlockfile(fp);
free(buf);
free(ptr);
return NULL;
}
buf = cp;
(void) memcpy(buf + len, ptr, s);
len += s;
buf[len] = '\0';
}
funlockfile(fp);
free(ptr);
if ((flags & FPARSELN_UNESCALL) != 0 && esc && buf != NULL &&
strchr(buf, esc) != NULL) {
ptr = cp = buf;
while (cp[0] != '\0') {
int skipesc;
while (cp[0] != '\0' && cp[0] != esc)
*ptr++ = *cp++;
if (cp[0] == '\0' || cp[1] == '\0')
break;
skipesc = 0;
if (cp[1] == com)
skipesc += (flags & FPARSELN_UNESCCOMM);
if (cp[1] == con)
skipesc += (flags & FPARSELN_UNESCCONT);
if (cp[1] == esc)
skipesc += (flags & FPARSELN_UNESCESC);
if (cp[1] != com && cp[1] != con && cp[1] != esc)
skipesc = (flags & FPARSELN_UNESCREST);
if (skipesc)
cp++;
else
*ptr++ = *cp++;
*ptr++ = *cp++;
}
*ptr = '\0';
len = strlen(buf);
}
if (size)
*size = len;
return buf;
}
+4 -38
View File
@@ -41,10 +41,11 @@
* The number of bytes copied. If an error is detected -1 is returned
* and @errno will be set accordingly.
*/
size_t fsendfile(FILE *src, FILE *dst, size_t len)
ssize_t fsendfile(FILE *src, FILE *dst, size_t len)
{
char *buf;
size_t blk = BUFSIZ, num = 0, tot = 0;
size_t tot = 0;
ssize_t blk = BUFSIZ, num = 0;
if (!src) {
errno = EINVAL;
@@ -73,46 +74,11 @@ size_t fsendfile(FILE *src, FILE *dst, size_t len)
free(buf);
return (num == (size_t)-1) ? (size_t)-1 : tot;
return (num == -1) ? -1 : (ssize_t)tot;
}
#ifdef UNITTEST
#include <err.h>
#include <unistd.h>
int main(void)
{
int i = 0;
char *files[] = {
"/etc/passwd", "/tmp/tok",
"/etc/passwd", "/tmp/passwd",
"/etc/passwd", "/tmp/passwd",
NULL
};
FILE *src, *dst;
while (files[i]) {
src = fopen(files[i], "r");
dst = fopen(files[i + 1], "w");
printf("fsendfile(%s, %s, 512)\t", files[i], files[i + 1]);
if (-1 == fsendfile(src, dst, 512))
err(1, "Failed fsendfile(%s, %s)", files[i], files[i + 1]);
if (!access(files[i + 1], F_OK))
printf("OK => %s\n", files[i + 1]);
remove(files[i + 1]);
i += 2;
}
return 0;
}
#endif /* UNITTEST */
/**
* Local Variables:
* compile-command: "make V=1 -f fsendfile.mk"
* version-control: t
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
-4
View File
@@ -1,4 +0,0 @@
OBJS =
TARGET = fsendfile.test clean
include rules.mk
-1
View File
@@ -85,7 +85,6 @@ int ifconfig(char *ifname, char *addr, char *mask, int up)
/**
* Local Variables:
* version-control: t
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
+1 -41
View File
@@ -1,6 +1,6 @@
/* Parse UNIX /etc configuration files like /etc/protocols and /etc/services
*
* Copyright (c) 2015 Joachim Nilsson <troglobit@gmail.com>
* Copyright (c) 2015-2016 Joachim Nilsson <troglobit@gmail.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -187,48 +187,8 @@ int fgetint(char *file, char *sep, char *key)
return val;
}
#ifdef UNITTEST
int main(void)
{
int val;
lfile_t lf;
val = fgetint("/etc/protocols", " \n\t", "udp");
if (val == -1) {
perror("Failed locating 'udp' protocol");
return 1;
}
printf("udp has proto %d\n", val);
val = fgetint("/etc/services", " /\n\t", "ftp");
if (val == -1) {
perror("Failed locating 'ftp' service");
return 1;
}
printf("ftp is inet port %d\n", val);
val = fgetint("/etc/group", "x:\n", "utmp");
if (val == -1) {
perror("Failed locating group 'utmp'");
return 1;
}
printf("utmp is gid %d\n", val);
val = fgetint("/etc/passwd", "x:\n", "nobody");
if (val == -1) {
perror("Failed locating user 'nobody'");
return 1;
}
printf("nobody is uid %d\n", val);
return 0;
}
#endif
/**
* Local Variables:
* compile-command: "make V=1 -f lfile.mk"
* version-control: t
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
-4
View File
@@ -1,4 +0,0 @@
OBJS =
TARGET = lfile.test clean
include rules.mk
+55 -85
View File
@@ -25,28 +25,38 @@
#ifndef LITE_H_
#define LITE_H_
#include <err.h>
#include <errno.h>
#include <stdio.h>
#include <stdint.h> /* uint8_t, uint16_t, uint32_t, INT32_MAX, etc. */
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/param.h> /* MAX(), isset(), setbit(), TRUE, FALSE, et consortes. :-) */
#include <unistd.h>
#include "strlite.h"
/*
* fparseln() specific operation flags.
*/
#define FPARSELN_UNESCESC 0x01
#define FPARSELN_UNESCCONT 0x02
#define FPARSELN_UNESCCOMM 0x04
#define FPARSELN_UNESCREST 0x08
#define FPARSELN_UNESCALL 0x0f
typedef struct lfile lfile_t;
char *chomp (char *str);
char *fparseln (FILE *, size_t *, size_t *, const char[3], int);
int fexist (char *file);
int fisdir (char *file);
int fisdir (const char *file);
mode_t fmode (char *file);
FILE *tempfile (void);
ssize_t copyfile (char *src, char *dst, int len, int sym);
int movefile (char *src, char *dst);
int fcopyfile (FILE *src, FILE *dst);
size_t fsendfile (FILE *src, FILE *dst, size_t len);
ssize_t fsendfile (FILE *src, FILE *dst, size_t len);
int ifconfig (char *ifname, char *addr, char *mask, int up);
@@ -61,37 +71,60 @@ int mkpath (char *dir, mode_t mode);
int makepath (char *dir);
int dir (const char *dir, const char *type, int (*filter) (const char *file), char ***list, int strip);
int rsync (char *src, char *dst, int delete, int (*filter) (const char *file));
int rsync (char *src, char *dst, int delete, int (*filter) (const char *file));
int pidfile (const char *basename);
int pidfile_signal(const char *pidfile, int signal);
pid_t pidfile_read (const char *pidfile);
pid_t pidfile_poll (const char *pidfile);
#ifndef strlcpy
size_t strlcpy (char *dst, const char *src, size_t siz);
#endif
#ifndef strlcat
size_t strlcat (char *dst, const char *src, size_t siz);
#endif
#ifndef strtonum
long long strtonum (const char *numstr, long long minval, long long maxval, const char **errstrp);
#endif
void *reallocarray(void *optr, size_t nmemb, size_t size);
int tree(char *path, int show_perms);
int tree(char *path, int show_perms);
void progress (int percent, int max_width);
void progress_simple(int percent);
char *which (const char *cmd);
#ifndef touch
# define touch(x) do { if (mknod((x), S_IFREG|0644, 0) && errno != EEXIST) warn("Failed creating %s", x); } while (0)
#include <sys/stat.h> /* utimensat() */
#include <sys/time.h> /* utimensat() on *BSD */
static inline int touch(const char *path)
{
if (mknod((path), S_IFREG|0644, 0)) {
if (errno == EEXIST)
return utimensat(0, path, NULL, 0);
return -1;
}
return 0;
}
#endif
#ifndef makedir
# define makedir(x, p) do { if (mkdir(x, p) && errno != EEXIST) warn("Failed creating directory %s", x); } while (0)
static inline int makedir(const char *path, mode_t mode)
{
if (mkdir(path, mode) && errno != EEXIST)
return -1;
return 0;
}
#endif
#ifndef makefifo
# define makefifo(x, p) do { if (mkfifo(x, p) && errno != EEXIST) warn("Failed creating FIFO %s", x); } while (0)
static inline int makefifo(const char *path, mode_t mode)
{
if (mkfifo(path, mode) && errno != EEXIST)
return -1;
return 0;
}
#endif
#ifndef erase
# define erase(x) do { if (remove(x) && errno != ENOENT) warn("Failed removing %s", x); } while (0)
static inline int erase(const char *path)
{
if (remove(path) && errno != ENOENT)
return -1;
return 0;
}
#endif
#ifndef chardev
# define chardev(x,m,maj,min) mknod((x), S_IFCHR|(m), makedev((maj),(min)))
#endif
@@ -125,11 +158,6 @@ int tree(char *path, int show_perms);
#define NELEMS(array) (sizeof(array) / sizeof(array[0]))
#endif
/* Mark a function variable as unused, useful for generic callbacks */
#ifndef UNUSED
#define UNUSED(x) UNUSED_ ## x __attribute__ ((unused))
#endif
/* Does directory end with a slash? */
static inline int fisslashdir(char *dir)
{
@@ -142,73 +170,15 @@ static inline int fisslashdir(char *dir)
return 0;
}
/* Convert string to natural number (0-2147483647), returns -1 on error. */
static inline int atonum(const char *str)
{
int val = -1;
const char *errstr;
if (str) {
val = strtonum(str, 0, INT32_MAX, &errstr);
if (errstr)
return -1;
}
return val;
}
/* Validate string, non NULL and not zero length */
static inline int string_valid(const char *s)
{
return s && strlen(s);
}
/* Relaxed comparison, e.g., sys_string_match("small", "smaller") => TRUE */
static inline int string_match(const char *a, const char *b)
{
size_t min = MIN(strlen(a), strlen(b));
return !strncasecmp(a, b, min);
}
/* Strict comparison, e.g., sys_string_match("small", "smaller") => FALSE */
static inline int string_compare (const char *a, const char *b)
{
return strlen(a) == strlen(b) && !strcmp(a, b);
}
/* Strict comparison, like sys_string_compare(), but case insensitive,
* e.g., sys_string_match("small", "SmAlL") => TRUE
*/
static inline int string_case_compare (const char *a, const char *b)
{
return strlen (a) == strlen (b) && !strcasecmp (a, b);
}
#define min(a,b) \
({ \
__typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a < _b ? _a : _b; \
})
#define max(a,b) \
({ \
__typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a > _b ? _a : _b; \
})
/* Compat */
#define copy_filep(src,dst) fcopyfile(src,dst)
#define pidfile_read_pid(file) pifile_read(file)
#define signal_pidfile(file,signo) pidfile_signal(file,signo)
#define copy_filep(src, dst) fcopyfile(src, dst)
#define pidfile_read_pid(file) pifile_read(file)
#define signal_pidfile(file, signo) pidfile_signal(file, signo)
#endif /* LITE_H_ */
/**
* Local Variables:
* version-control: t
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
+13 -68
View File
@@ -1,6 +1,6 @@
/* mkpath() -- Create all components leading up to a given directory
*
* Copyright (c) 2013 Joachim Nilsson <troglobit@gmail.com>
* Copyright (c) 2013-2016 Joachim Nilsson <troglobit@gmail.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -17,20 +17,28 @@
#include <errno.h>
#include <libgen.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "lite.h"
/**
* mkpath - Like makepath() but takes a mode_t argument
* @dir: Directory to created, relative or absolute
* @mode: A &mode_t mode to create @dir with
*
* Returns:
* POSIX OK(0) on success, otherwise -1 with @errno set.
*/
int mkpath(char *dir, mode_t mode)
{
struct stat sb;
if (!dir) {
errno = EINVAL;
return 1;
}
if (strlen(dir) == 1 && dir[0] == '/')
if (!stat(dir, &sb))
return 0;
mkpath(dirname(strdupa(dir)), mode);
@@ -53,71 +61,8 @@ int makepath(char *dir)
return mkpath(dir, 0777);
}
/********************************* UNIT TESTS ************************************/
#ifdef UNITTEST
#include "lite.h"
int checkpath(char *dir)
{
char tmp[256];
struct stat sb;
snprintf(tmp, sizeof(tmp), "ls -ld %s", dir);
if (system(tmp))
perror("system");
if (!stat(dir, &sb) && S_ISDIR(sb.st_mode))
return 0;
errno = ENOTDIR;
return 1;
}
int test_makepath(char *dir)
{
int ret = makepath(dir);
if (!ret)
ret = checkpath(dir);
if (ret)
perror("Failed");
return ret;
}
int main(void)
{
int i, ret = 0;
char *list[] = {
"/tmp/tok/",
"/tmp/tok2",
"/tmp/ab",
"/tmp/b",
"/tmp/a/",
"/tmp/a/b",
"/tmp/a/c/",
NULL
};
for (i = 0; list[i]; i++)
rmdir(list[i]);
printf("Testing makepath() ...\n");
for (i = 0; list[i] && !ret; i++)
ret = test_makepath(list[i]);
printf("\nCleaning up ...\n");
for (i = 0; list[i]; i++)
rmdir(list[i]);
return ret;
}
#endif /* UNITTEST */
/**
* Local Variables:
* compile-command: "make V=1 -f makepath.mk"
* version-control: t
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
-4
View File
@@ -1,4 +0,0 @@
OBJS =
TARGET = makepath.test clean
include rules.mk
+18 -10
View File
@@ -1,4 +1,4 @@
/* Updated by troglobit for libite/finit/uftpd projects 2016/03/19 */
/* Updated by troglobit for libite/finit/uftpd projects 2016/07/04 */
/* $OpenBSD: pidfile.c,v 1.11 2015/06/03 02:24:36 millert Exp $ */
/* $NetBSD: pidfile.c,v 1.4 2001/02/19 22:43:42 cgd Exp $ */
@@ -32,6 +32,7 @@
*/
#include <sys/stat.h> /* utimensat() */
#include <sys/time.h> /* utimensat() on *BSD */
#include <sys/types.h>
#include <errno.h>
#include <paths.h>
@@ -41,10 +42,11 @@
#ifndef pidfile
static char *pidfile_path = NULL;
static pid_t pidfile_pid;
static pid_t pidfile_pid = 0;
static void pidfile_cleanup(void);
const char *__pidfile_path = _PATH_VARRUN; /* Note: includes trailing slash '/' */
const char *__pidfile_name = NULL;
extern char *__progname;
@@ -63,9 +65,9 @@ pidfile(const char *basename)
atexit_already = 0;
if (pidfile_path != NULL) {
if (pid == pidfile_pid) {
if (!access(pidfile_path, R_OK) && pid == pidfile_pid) {
utimensat(0, pidfile_path, NULL, 0);
return 0;
return (0);
}
free(pidfile_path);
pidfile_path = NULL;
@@ -73,9 +75,13 @@ pidfile(const char *basename)
atexit_already = 1;
}
/* _PATH_VARRUN includes trailing / */
if (asprintf(&pidfile_path, "%s%s.pid", _PATH_VARRUN, basename) == -1)
return (-1);
if (basename[0] != '/') {
if (asprintf(&pidfile_path, "%s%s.pid", __pidfile_path, basename) == -1)
return (-1);
} else {
if (asprintf(&pidfile_path, "%s", basename) == -1)
return (-1);
}
if ((f = fopen(pidfile_path, "w")) == NULL) {
save_errno = errno;
@@ -95,6 +101,7 @@ pidfile(const char *basename)
return (-1);
}
(void) fclose(f);
__pidfile_name = pidfile_path;
/*
* LITE extension, no need to set up another atexit() handler
@@ -113,7 +120,6 @@ pidfile(const char *basename)
errno = save_errno;
return (-1);
}
__pidfile_name = pidfile_path;
return (0);
}
@@ -121,8 +127,10 @@ pidfile(const char *basename)
static void
pidfile_cleanup(void)
{
if (pidfile_path != NULL && pidfile_pid == getpid())
if (pidfile_path != NULL && pidfile_pid == getpid()) {
(void) unlink(pidfile_path);
free(pidfile_path);
pidfile_path = NULL;
}
}
#endif
-126
View File
@@ -21,7 +21,6 @@
#include <signal.h>
#include <unistd.h>
extern char *__pidfile_name;
extern char *chomp(char *str);
/**
@@ -118,131 +117,6 @@ int pidfile_signal(const char *pidfile, int signal)
return 0;
}
/********************************* UNIT TESTS ************************************/
#ifdef UNITTEST
#include <paths.h>
#include <stdarg.h>
#include <time.h>
#include "lite.h"
extern char *__progname;
static char PIDFILE[42];
static int verbose = 0;
static struct stat before, after;
static int test(int result, const char *fmt, ...)
{
char buf[80];
size_t len;
va_list ap;
const char success[] = " \e[1m[ OK ]\e[0m\n";
const char failure[] = " \e[7m[FAIL]\e[0m\n";
const char dots[] = " .....................................................................";
va_start(ap, fmt);
len = vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
write(STDERR_FILENO, buf, len);
write(STDERR_FILENO, dots, 60 - len); /* pad with dots. */
if (!result)
write(STDERR_FILENO, success, strlen(success));
else
write(STDERR_FILENO, failure, strlen(failure));
return result;
}
static inline int timespec_newer(const struct timespec *a, const struct timespec *b)
{
if (a->tv_sec != b->tv_sec)
return a->tv_sec > b->tv_sec;
return a->tv_nsec > b->tv_nsec;
}
char *timespec2str(struct timespec *ts, char *buf, size_t len)
{
size_t ret, pos;
struct tm t;
memset(buf, 0, len);
tzset();
if (localtime_r(&(ts->tv_sec), &t) == NULL)
return buf;
ret = strftime(buf, len, "%F %T", &t);
if (ret == 0)
return buf;
len -= ret - 1;
pos = strlen(buf);
len -= pos;
snprintf(&buf[pos], len, ".%09ld", ts->tv_nsec);
return buf;
}
static void sigterm_handler(int UNUSED(signo))
{
if (verbose)
printf("Exiting ...\n");
}
static void sigalrm_handler(int UNUSED(signo))
{
pidfile(NULL);
if (!fexist(PIDFILE))
err(1, "failed creating %s", PIDFILE);
stat(PIDFILE, &before);
}
static int mtime()
{
int ret;
char buf[80];
/* Must sleep a while here otherwise we execute too fast => no mtime change :-( */
usleep(10000);
if (verbose)
printf("Calling pidfile() again to update mtime ...\n");
pidfile(NULL);
stat(PIDFILE, &after);
ret = timespec_newer(&after.st_mtim, &before.st_mtim);
if (verbose) {
printf("Before: %s\n", timespec2str(&before.st_mtim, buf, sizeof(buf)));
printf("After : %s\n", timespec2str(&after.st_mtim, buf, sizeof(buf)));
}
return !ret;
}
int main(int argc, char *argv[])
{
if (argc > 1 && !strcmp(argv[1], "-v"))
verbose = 1;
snprintf(PIDFILE, sizeof(PIDFILE), "%s%s.pid", _PATH_VARRUN, __progname);
signal(SIGTERM, sigterm_handler);
signal(SIGALRM, sigalrm_handler);
alarm(1);
return test(pidfile_poll(PIDFILE) != getpid(), "Testing pidfile_poll()")
|| test(strcmp(__pidfile_name, PIDFILE), "Testing __pidfile_name vs guessed PID filename")
|| test(mtime(), "Testing mtime update of followup pidfile() call")
|| test(pidfile_signal(PIDFILE, SIGTERM), "Testing signalling ourselves")
;
return 0;
}
#endif /* UNITTEST */
/**
* Local Variables:
* compile-command: "make V=1 -f pidfilefn.mk"
-6
View File
@@ -1,6 +0,0 @@
CFLAGS = -W -Wall -Wextra -Werror
OBJS = pidfile.o chomp.o fexist.o
ASROOT = 1
TARGET = clean $(OBJS) pidfilefn.test
include rules.mk
-53
View File
@@ -114,61 +114,8 @@ void progress_simple(int percent)
}
}
#ifdef UNITTEST
#include <stdlib.h> /* atexit() */
#include <unistd.h> /* usleep() */
#define MAX_WIDTH 80
#define msleep(msec) usleep(msec * 1000)
static void bye(void)
{
showcursor();
}
static void testit(int fn, int percent)
{
if (fn)
progress(percent, MAX_WIDTH);
else
progress_simple(percent);
}
static void test(int fn)
{
int i, percent, block = 0, num = 85;
while (block < num) {
percent = block * 100 / num;
for (i = 0; i < 10; i++) {
testit(fn, percent);
msleep(5);
}
block++;
msleep(10);
}
testit(fn, 100);
}
int main(void)
{
atexit(bye);
hidecursor();
printf("\nAdvanced:\n");
test(1);
printf("\nSimple:\n");
test(0);
printf("\n");
return 0;
}
#endif /* UNITTEST */
/**
* Local Variables:
* compile-command: "make V=1 -f progress.mk"
* version-control: t
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
-4
View File
@@ -1,4 +0,0 @@
OBJS =
TARGET = progress.test clean
include rules.mk
+38
View File
@@ -0,0 +1,38 @@
/* $OpenBSD: reallocarray.c,v 1.2 2014/12/08 03:45:00 bcook Exp $ */
/*
* Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <errno.h>
#include <stdint.h>
#include <stdlib.h>
/*
* This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
* if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
*/
#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
void *
reallocarray(void *optr, size_t nmemb, size_t size)
{
if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
nmemb > 0 && SIZE_MAX / nmemb < size) {
errno = ENOMEM;
return NULL;
}
return realloc(optr, size * nmemb);
}
-112
View File
@@ -193,120 +193,8 @@ static int prune(char *dst, char **new_files, int new_num)
return result;
}
#ifdef UNITTEST
#define BASE "/tmp/.unittest/"
#define SRC BASE "src/"
#define DST BASE "dst/"
static int verbose = 0;
static char *files[] = {
SRC "sub1/1.tst",
SRC "sub1/2.tst",
SRC "sub1/3.tst",
SRC "sub2/4.tst",
SRC "sub2/5.tst",
SRC "sub2/6.tst",
SRC "sub3/7.tst",
SRC "sub3/8.tst",
SRC "sub3/9.tst",
NULL
};
void cleanup_test(void)
{
system("rm -rf " BASE);
}
void setup_test(void)
{
int i;
char cmd[256];
mode_t dir_modes[] = { 755, 700 };
mode_t file_modes[] = { 644, 600 };
cleanup_test();
mkdir(BASE, 0755);
mkdir(SRC, 0755);
mkdir(DST, 0755);
for (i = 0; files[i]; i++) {
snprintf(cmd, sizeof(cmd), "mkdir -m %d -p `dirname %s`",
dir_modes[i % 2], files[i]);
system(cmd);
snprintf(cmd, sizeof(cmd), "touch %s; chmod %d %s", files[i],
file_modes[i % 2], files[i]);
system(cmd);
}
}
static void check_tree(char *heading, char *dir)
{
if (verbose) {
char cmd[128];
if (heading)
puts(heading);
tree(dir, 1);
}
}
int run_test(void)
{
int result = 0;
#if 0
setup_test();
check_tree("Before:", BASE);
result += rsync(SRC, DST, 0, NULL);
check_tree("After:", BASE);
cleanup_test();
#endif
setup_test();
result += rsync(BASE "src", DST, 0, NULL);
check_tree("Only partial rsync of src <-- No slash!", BASE);
#if 0
cleanup_test();
setup_test();
result += rsync(BASE "src/sub1", BASE "dst", 0, NULL);
check_tree("Only partial rsync of src/sub1 <-- No slashes!!", BASE);
cleanup_test();
setup_test();
result += rsync(BASE "src/sub1/", DST, 0, NULL);
check_tree("Only partial rsync of src/sub1/", BASE);
cleanup_test();
setup_test();
result += rsync(BASE "src/sub1", DST, 0, NULL);
check_tree("Only partial rsync of src/sub1 <-- No slash!", BASE);
result += rsync("/etc", "/var/tmp", 0, NULL);
check_tree("Real life test:", "/var/tmp");
#endif
return result;
}
int main(int argc, char *argv[])
{
if (argc > 1)
verbose = !strncmp("-v", argv[1], 2);
atexit(cleanup_test);
return run_test();
}
#endif /* UNITTEST */
/**
* Local Variables:
* compile-command: "make V=1 -f rsync.mk"
* version-control: t
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
-4
View File
@@ -1,4 +0,0 @@
OBJS = dir.o copyfile.o fexist.o fisdir.o fmode.o tree.o
TARGET = clean $(OBJS) rsync.test
include rules.mk
-68
View File
@@ -1,68 +0,0 @@
.PHONY: all clean distclean
# Figure out root of library, unless used as submodule
ROOTDIR ?= $(shell pwd)
CC ?= $(CROSS)gcc
AR ?= $(CROSS)ar
STRIP ?= $(CROSS)strip
INSTALL := install --backup=off
STRIPINST := $(INSTALL) -s --strip-program=$(CROSS)strip -m 0755
CFLAGS += -g -O0
CPPFLAGS += -D_GNU_SOURCE
ARFLAGS = crus
# Default to silent build, use V=1 to get verbose mode.
ifeq ($V,1)
Q =
PRINT = @true
REDIRECT =
MAKEFLAGS =
VERBOSE = -v
else
Q = @
PRINT = @printf
REDIRECT = >/dev/null
MAKEFLAGS = --no-print-directory --silent
VERBOSE =
endif
# Some tests may need to be run as root, e.g. pidfile()
ifeq ($(ASROOT), 1)
SUDO = sudo -n
else
SUDO =
endif
# Default install paths
prefix ?= /usr/local
libdir ?= $(prefix)/lib
datadir ?= $(prefix)/share/doc/$(LIBNAME)
incdir ?= $(prefix)/include
# Pretty printing and GCC -M for auto dep files
%.o: %.c
$(PRINT) " CC $(subst $(ROOTDIR)/,,$(shell pwd)/)$@\n"
$(Q)$(CC) $(CFLAGS) $(CPPFLAGS) -c -MMD -MP -o $@ $<
%: %.o
$(PRINT) " LINK $(subst $(ROOTDIR)/,,$(shell pwd)/)$@\n"
$(Q)$(CC) $(CFLAGS) $(LDFLAGS) -Wl,-Map,$@.map -o $@ $^ $(LDLIBS$(LDLIBS-$(@)))
.PHONY: %.test
%.test: %.c
$(PRINT) " TEST $(subst $(ROOTDIR)/,,$(shell pwd)/)$(@:.test=)\n"
$(Q)$(CC) $(CFLAGS) $(CPPFLAGS) -g -o $@ -DUNITTEST $< $(OBJS)
$(Q)$(RM) $(OBJS)
$(Q)$(SUDO) ./$@ $(VERBOSE) $(REDIRECT)
# Default build rules for both main and unit test makefiles
all:: $(TARGET)
clean::
-$(Q)$(RM) $(OBJS) $(DEPS) $(TARGET) $(SOLIB) $(STATICLIB)
distclean::
-$(Q)$(RM) $(JUNK) unittest *.o *.a *.so* *.unittest *.test
+52
View File
@@ -0,0 +1,52 @@
/* ==========================================================================
* strdupa.h - Re-implementation of glibc strdupa.
* --------------------------------------------------------------------------
* Copyright (c) 2009 William Ahern
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
* ==========================================================================
*/
#ifndef LITE_STRDUPA_H
#define LITE_STRDUPA_H
#if !defined(HAVE_STRDUPA)
#if defined(strdupa)
#define HAVE_STRDUPA 1
#endif
#endif
#if !HAVE_STRDUPA
#if defined(__GNUC__)
#include <stddef.h> /* size_t */
#include <string.h> /* memcpy(3) strlen(3) */
#define strdupa(src) (__extension__ ({ \
size_t len_ = strlen(src); \
char *dst_ = __builtin_alloca(len_ + 1); \
dst_[len_] = '\0'; \
(char *)memcpy(dst_, src, len_); \
}))
#else /* If not GCC, e.g. Clang */
#error strdupa() may use an unsupported GNU C API, please forward any fix to maintainer, cheers!
#endif /* __GNUC__ */
#endif /* !HAVE_STRDUPA */
#endif /* LITE_STRDUPA_H */
+100
View File
@@ -0,0 +1,100 @@
/* Collection of frog DNA
*
* Copyright (c) 2008-2016 Joachim Nilsson <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef LITE_STRING_H_
#define LITE_STRING_H_
#include <string.h>
#include "strdupa.h"
#include "strndupa.h"
#include "strnlen.h"
#ifndef strlcpy
size_t strlcpy (char *dst, const char *src, size_t siz);
#endif
#ifndef strlcat
size_t strlcat (char *dst, const char *src, size_t siz);
#endif
#ifndef strtonum
long long strtonum (const char *numstr, long long minval, long long maxval, const char **errstrp);
#endif
/* Convert string to natural number (0-2147483647), returns -1 on error. */
static inline int atonum(const char *str)
{
int val = -1;
const char *errstr;
if (str) {
val = strtonum(str, 0, INT32_MAX, &errstr);
if (errstr)
return -1;
}
return val;
}
/* Validate string, non NULL and not zero length */
static inline int string_valid(const char *s)
{
return s && strlen(s);
}
/* Relaxed comparison, e.g., sys_string_match("small", "smaller") => TRUE */
static inline int string_match(const char *a, const char *b)
{
size_t min = MIN(strlen(a), strlen(b));
return !strncasecmp(a, b, min);
}
/* Strict comparison, e.g., sys_string_match("small", "smaller") => FALSE */
static inline int string_compare(const char *a, const char *b)
{
return strlen(a) == strlen(b) && !strcmp(a, b);
}
/* Strict comparison, like sys_string_compare(), but case insensitive,
* e.g., sys_string_match("small", "SmAlL") => TRUE
*/
static inline int string_case_compare(const char *a, const char *b)
{
return strlen (a) == strlen (b) && !strcasecmp (a, b);
}
#define min(a,b) \
({ \
__typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a < _b ? _a : _b; \
})
#define max(a,b) \
({ \
__typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a > _b ? _a : _b; \
})
#endif /* LITE_STRING_H_ */
+53
View File
@@ -0,0 +1,53 @@
/* ==========================================================================
* strndupa.h - Re-implementation of glibc strndupa.
* --------------------------------------------------------------------------
* Copyright (c) 2009 William Ahern
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
* ==========================================================================
*/
#ifndef LITE_STRNDUPA_H_
#define LITE_STRNDUPA_H_
#if !defined(HAVE_STRNDUPA)
#if defined(strndupa)
#define HAVE_STRNDUPA 1
#endif
#endif
#if !HAVE_STRNDUPA
#if defined(__GNUC__)
#include <stddef.h> /* size_t */
#include <string.h> /* memcpy(3) */
#include "strnlen.h"
#define strndupa(src, lim) (__extension__ ({ \
size_t len_ = strnlen(src, lim); \
char *dst_ = __builtin_alloca(len_ + 1); \
dst_[len_] = '\0'; \
(char *)memcpy(dst_, src, len_); \
}))
#else /* If not GCC, e.g. Clang */
+#error strndupa() may use an unsupported GNU C API, please forward any fix to maintainer, cheers!
#endif /* __GNUC__ */
#endif /* !HAVE_STRNDUPA */
#endif /* GNU_STRING_STRNDUPA_H */
+43
View File
@@ -0,0 +1,43 @@
/* strnlen.h - Re-implementation of GLIBC strnlen()
*
* Copyright (c) 2016 Joachim Nilsson <troglobit@gmail.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef LITE_STRNLEN_H_
#define LITE_STRNLEN_H_
#if !defined(HAVE_STRNLEN)
#if defined(strnlen)
#define HAVE_STRNLEN 1
#endif
#endif
#if !HAVE_STRNLEN
#include <stddef.h> /* size_t */
#define strnlen(str, lim) xstrnlen(str, lim)
static inline size_t xstrnlen(const char *str, size_t lim)
{
size_t i = 0;
while (str[i] && i < lim)
i++;
return i;
}
#endif
#endif /* LITE_STRNLEN_H_ */
+4 -23
View File
@@ -1,6 +1,6 @@
/* A secure tmpfile() replacement.
*
* Copyright (c) 2015 Joachim Nilsson <troglobit@gmail.com>
* Copyright (c) 2015-2016 Joachim Nilsson <troglobit@gmail.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -17,17 +17,9 @@
#include <paths.h>
#include <fcntl.h> /* O_TMPFILE requires -D_GNU_SOURCE */
#include <linux/version.h>
#include <stdlib.h> /* mkstemp() */
#include <stdio.h> /* fdopen() */
#include <sys/stat.h> /* umask() */
#ifndef O_TMPFILE /* Too old GLIBC or kernel */
#warning O_TMPFILE missing on your system, tempfile() may not work!
#define __O_TMPFILE 020000000
#define O_TMPFILE (__O_TMPFILE | O_DIRECTORY) /* Define and let it fail at runtime */
#endif
/**
* tempfile - A secure tmpfile() replacement
*
@@ -43,7 +35,7 @@
*/
FILE *tempfile(void)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0)
#ifdef O_TMPFILE /* Only on Linux, with fairly recent (G)LIBC */
int fd;
mode_t oldmask;
@@ -53,25 +45,14 @@ FILE *tempfile(void)
if (-1 == fd)
return NULL;
return fdopen(fd, "rw");
return fdopen(fd, "w+");
#else
#warning Too old kernel, reverting to wrap unsafe tmpfile() ...
return tmpfile();
return tmpfile(); /* Fallback on older GLIBC/Linux and actual UNIX systems */
#endif
}
#ifdef UNITTEST
int main(void)
{
FILE *fp = tempfile(); system("ls -lrt "
_PATH_TMP " | tail -10"); return fclose(fp);
}
#endif
/**
* Local Variables:
* compile-command: "make V=1 -f tempfile.mk"
* version-control: t
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
-4
View File
@@ -1,4 +0,0 @@
OBJS =
TARGET = tempfile.test clean
include rules.mk
+17
View File
@@ -0,0 +1,17 @@
*.log
*.trs
chomp
copyfile
dir
fexist
fisdir
fsendfile
lfile
makepath
pidfile
progress
rsync
tempfile
touch
tree
which
+27
View File
@@ -0,0 +1,27 @@
EXTRA_DIST = check.h
CLEANFILES = *~ *.trs *.log
TESTS =
TESTS += chomp
TESTS += copyfile
TESTS += dir
TESTS += fexist
TESTS += fisdir
TESTS += fsendfile
TESTS += lfile
TESTS += makepath
TESTS += pidfile
TESTS += touch
TESTS += progress
TESTS += rsync
TESTS += tempfile
TESTS += tree
TESTS += which
check_PROGRAMS = $(TESTS)
# Ignore warnings about unused result, in e.g. write()
CFLAGS += -Wno-unused-result
CPPFLAGS += -D_GNU_SOURCE
LDADD = -L../ ../libite.la
LDFLAGS += -static
+81
View File
@@ -0,0 +1,81 @@
#ifndef LITE_TESTS_CHECK_H_
#define LITE_TESTS_CHECK_H_
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "../conio.h"
#include "../lite.h"
#define PRINT(args...) if (verbose) printf(args)
#define fail_unless(test) \
do { \
if (!(test)) { \
fprintf(stderr, \
"----------------------------------------------\n" \
"%s:%d: test FAILED:\nFailed test: %s\n" \
"----------------------------------------------\n", \
__FILE__, __LINE__, #test); \
exit(1); \
} \
} while (0)
static inline int test(int result, const char *fmt, ...)
{
char buf[80];
size_t len;
va_list ap;
const char success[] = " \033[1m[ OK ]\033[0m\n";
const char failure[] = " \033[7m[FAIL]\033[0m\n";
const char dots[] = " .....................................................................";
va_start(ap, fmt);
len = vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
write(STDERR_FILENO, buf, len);
write(STDERR_FILENO, dots, 60 - len); /* pad with dots. */
if (!result)
write(STDERR_FILENO, success, strlen(success));
else
write(STDERR_FILENO, failure, strlen(failure));
return result;
}
static inline int timespec_newer(const struct timespec *a, const struct timespec *b)
{
if (a->tv_sec != b->tv_sec)
return a->tv_sec > b->tv_sec;
return a->tv_nsec > b->tv_nsec;
}
static inline char *timespec2str(struct timespec *ts, char *buf, size_t len)
{
size_t ret, pos;
struct tm t;
memset(buf, 0, len);
tzset();
if (localtime_r(&(ts->tv_sec), &t) == NULL)
return buf;
ret = strftime(buf, len, "%F %T", &t);
if (ret == 0)
return buf;
len -= ret - 1;
pos = strlen(buf);
len -= pos;
snprintf(&buf[pos], len, ".%09ld", ts->tv_nsec);
return buf;
}
#endif /* LITE_TESTS_CHECK_H_ */
+24
View File
@@ -0,0 +1,24 @@
#include "check.h"
int main(void)
{
size_t i;
char t[][16] = {
"hej\ndej",
"Slime\n\n\\n",
"Tripple\n\n\n"
};
for (i = 0; i < NELEMS(t); i++) {
char *str = t[i];
size_t len;
chomp(str);
len = strlen(str);
printf("[%02zd]: '%s'\n", i, str);
fail_unless(str[len] != '\n');
}
return 0;
}
+55
View File
@@ -0,0 +1,55 @@
#include <err.h>
#include <errno.h>
#include "check.h"
int main(void)
{
int i = 0;
char *files[] = {
"/etc/passwd", "/tmp/mypwd", "/tmp/mypwd",
"/etc/passwd", "/tmp/", "/tmp/passwd",
"/etc/passwd", "/tmp", "/tmp/passwd",
NULL
};
FILE *src, *dst;
printf("=>Start testing fcopyfile()\n");
while (files[i]) {
printf("fcopyfile(%s, %s)\t", files[i], files[i + 1]);
src = fopen(files[i], "r");
dst = fopen(files[i + 1], "w");
if (fcopyfile(src, dst)) {
if (!fisdir(files[i + 1]))
err(1, "Failed fcopyfile(%s, %s)", files[i], files[i + 1]);
}
if (src)
fclose(src);
if (dst)
fclose(dst);
if (fexist(files[i + 2]))
printf("OK => %s", files[i + 2]);
printf("\n");
erase(files[i + 2]);
i += 3;
}
printf("\n=>Start testing copyfile()\n");
i = 0;
while (files[i]) {
printf("copyfile(%s, %s)\t", files[i], files[i + 1]);
if (!copyfile(files[i], files[i + 1], 0, 0))
err(1, "Failed copyfile(%s, %s)", files[i], files[i + 1]);
if (fexist(files[i + 2]))
printf("OK => %s", files[i + 2]);
printf("\n");
erase(files[i + 2]);
i += 3;
}
return 0;
}
+99
View File
@@ -0,0 +1,99 @@
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/stat.h>
#include "check.h"
#define DIR_TYPE_IMAGE ".img"
#define DIR_TYPE_SYSLOG ""
#define DIR_TYPE_CONFIG ".cfg"
#define STARTUP_CONFIG "startup-config.cfg"
int simulate_files(int creat)
{
size_t i;
char *files[] =
{ "config0.cfg", "config1.cfg", "config2.cfg", "config3.cfg",
"rr109.img", "rx100.img", "rx107.img", "rm957.img", "messages"
};
for (i = 0; i < NELEMS(files); i++) {
if (creat)
touch(files[i]);
else
erase(files[i]);
}
if (creat)
symlink("config2.cfg", STARTUP_CONFIG);
else
erase(STARTUP_CONFIG);
return 0;
}
static int cfg_dir_filter(const char *file)
{
/* Skip the STARTUP_CONFIG file, it is a symbolic link to the
* current startup configuration. */
return ! !strcmp(file, STARTUP_CONFIG);
}
static int is_startup_config(const char *entry)
{
static int once = 1;
static char file[80];
if (once) {
int len = readlink(STARTUP_CONFIG, file, sizeof(file));
if (len == -1)
return 0;
file[len] = 0;
once = 0; /* Only once per call to dir() */
}
//printf ("Comparing link %s with entry %s\n", file, entry);
return !strcmp(file, entry);
}
int main(int argc, char *argv[])
{
int i, num;
char *type = DIR_TYPE_CONFIG;
char **files;
simulate_files(1);
if (argc >= 2) {
if (!strcasecmp("CONFIG", argv[1])) {
type = DIR_TYPE_CONFIG;
system("ls -l *" DIR_TYPE_CONFIG);
}
if (!strcasecmp("IMAGE", argv[1])) {
type = DIR_TYPE_IMAGE;
system("ls -l *" DIR_TYPE_IMAGE);
}
if (!strcasecmp("SYSLOG", argv[1])) {
type = DIR_TYPE_SYSLOG;
system("ls -l *");
}
}
num = dir(NULL, type, cfg_dir_filter, &files, 0);
if (num) {
for (i = 0; i < num; i++) {
printf("%s", files[i]);
if (is_startup_config(files[i]))
printf(" --> startup-config");
printf("\n");
free(files[i]);
}
free(files);
}
simulate_files(0);
return 0;
}
+24
View File
@@ -0,0 +1,24 @@
#include <err.h>
#include "check.h"
int main(void)
{
size_t i = 0;
struct { char *file; int exist; } arr[] = {
{ "/etc/passwd", 1 },
{ "/etc/kalle", 0 },
{ "/sbin/init", 1 },
{ "/dev/null", 1 },
{ NULL, 0 },
};
for (i = 0; i < NELEMS(arr); i++) {
if (fexist(arr[i].file) != arr[i].exist)
err(1, "Failed fexist(%s)", arr[i].file ?: "NULL");
else
printf("File %-11s %-14s => OK!\n", arr[i].file ?: "NULL",
arr[i].exist ? "does exist" : "does not exist");
}
return 0;
}
+25
View File
@@ -0,0 +1,25 @@
#include <err.h>
#include "check.h"
int main(void)
{
size_t i = 0;
struct { char *file; int exist; } arr[] = {
{ "/etc/passwd", 0 },
{ "/etc/", 1 },
{ "/sbin/init", 0 },
{ "/dev/null", 0 },
{ "/dev/", 1 },
{ NULL, 0 },
};
for (i = 0; i < NELEMS(arr); i++) {
if (fisdir(arr[i].file) != arr[i].exist)
err(1, "Failed fisdir(%s)", arr[i].file ?: "NULL");
else
printf("fisdir() %-11s %-18s => OK!\n", arr[i].file ?: "NULL",
arr[i].exist ? "is a directory" : "is NOT a directory");
}
return 0;
}
+31
View File
@@ -0,0 +1,31 @@
#include <err.h>
#include <unistd.h>
#include "check.h"
int main(void)
{
int i = 0;
char *files[] = {
"/etc/passwd", "/tmp/tok",
"/etc/passwd", "/tmp/passwd",
"/etc/passwd", "/tmp/passwd",
NULL
};
FILE *src, *dst;
while (files[i]) {
src = fopen(files[i], "r");
dst = fopen(files[i + 1], "w");
printf("fsendfile(%s, %s, 512)\t", files[i], files[i + 1]);
if (-1 == fsendfile(src, dst, 512))
err(1, "Failed fsendfile(%s, %s)", files[i], files[i + 1]);
if (!access(files[i + 1], F_OK))
printf("OK => %s\n", files[i + 1]);
remove(files[i + 1]);
i += 2;
}
return 0;
}
+74
View File
@@ -0,0 +1,74 @@
#include <stdio.h>
#include "check.h"
#define FSTAB "/etc/fstab"
static int fstab(void)
{
int field = 1;
char *token;
lfile_t *lf;
lf = lfopen(FSTAB, " \t\n");
if (!lf) {
perror("Failed opening " FSTAB);
return 1;
}
printheader(NULL, "FILE SYSTEM MOUNT OPTIONS D P", 0);
while ((token = lftok(lf))) {
if (field == 1)
printf("%-41s ", token);
if (field == 2)
printf("%-9s ", token);
if (field == 4)
printf("%-17s ", token);
if (field == 5)
printf("%d ", atoi(token));
if (field == 6) {
field = 0;
printf("%d\n", atoi(token));
}
field++;
}
lfclose(lf);
return 0;
}
int main(void)
{
int val;
val = fgetint("/etc/protocols", " \n\t", "udp");
if (val == -1) {
perror("Failed locating 'udp' protocol");
return 1;
}
printf("udp has proto %d\n", val);
val = fgetint("/etc/services", " /\n\t", "ftp");
if (val == -1) {
perror("Failed locating 'ftp' service");
return 1;
}
printf("ftp is inet port %d\n", val);
val = fgetint("/etc/group", "x:\n", "utmp");
if (val == -1) {
perror("Failed locating group 'utmp'");
return 1;
}
printf("utmp is gid %d\n", val);
val = fgetint("/etc/passwd", "x:\n", "nobody");
if (val == -1) {
perror("Failed locating user 'nobody'");
return 1;
}
printf("nobody is uid %d\n", val);
return fstab();
}
+67
View File
@@ -0,0 +1,67 @@
#include <errno.h>
#include <errno.h>
#include <libgen.h>
#include <stdlib.h>
#include "check.h"
int checkpath(char *dir)
{
char tmp[256];
struct stat sb;
snprintf(tmp, sizeof(tmp), "ls -ld %s", dir);
if (system(tmp))
perror("system");
if (!stat(dir, &sb) && S_ISDIR(sb.st_mode))
return 0;
errno = ENOTDIR;
return 1;
}
int test_makepath(char *dir)
{
int ret = makepath(dir);
if (!ret)
ret = checkpath(dir);
if (ret)
perror("Failed");
return ret;
}
int main(void)
{
int i, ret = 0;
char *list[] = {
"/tmp/libite-test/tok/",
"/tmp/libite-test/tok2",
"/tmp/libite-test/ab",
"/tmp/libite-test/b",
"/tmp/libite-test/a/",
"/tmp/libite-test/a/b",
"/tmp/libite-test/a/c/",
NULL
};
printf("Testing makepath() ...\n");
mkdir("/tmp/libite-test", 0755);
for (i = 0; list[i] && !ret; i++)
ret |= test_makepath(list[i]);
printf("\nCleaning up ...\n");
system("rm -rf /tmp/libite-test");
return ret;
}
/**
* Local Variables:
* indent-tabs-mode: t
* c-file-style: "linux"
* compile-command: "make makepath && ./makepath"
* End:
*/
+129
View File
@@ -0,0 +1,129 @@
#include <err.h>
#include <paths.h>
#include <signal.h>
#include <stdarg.h>
#include <time.h>
#include "check.h"
extern char *__pidfile_name;
extern char *__pidfile_path;
static char *ident;
static char *pidfile_arg;
static char PIDFILE[42];
static int verbose = 0;
static struct stat before, after;
static void sigterm_handler(int signo)
{
PRINT("Exiting ...\n");
remove(PIDFILE);
}
static void sigalrm_handler(int signo)
{
PRINT("Calling pidfile(%s)\n", pidfile_arg ?: "NULL");
if (pidfile(pidfile_arg))
err(1, "failed creating1 %s", pidfile_arg);
if (!fexist(PIDFILE))
err(1, "failed creating2 %s, created %s", PIDFILE, __pidfile_name);
stat(PIDFILE, &before);
}
static int mtime()
{
int ret;
char buf[80];
/* Must sleep a while here otherwise we execute too fast => no mtime change :-( */
usleep(10000);
PRINT("Calling pidfile() again to update mtime ...\n");
if (pidfile(pidfile_arg))
err(1, "failed creating3 %s", pidfile_arg);
stat(PIDFILE, &after);
ret = timespec_newer(&after.st_mtim, &before.st_mtim);
PRINT("Before: %s\n", timespec2str(&before.st_mtim, buf, sizeof(buf)));
PRINT("After : %s\n", timespec2str(&after.st_mtim, buf, sizeof(buf)));
return !ret;
}
int test_pidfile(char *arg0)
{
/* pidfile() argument */
pidfile_arg = arg0;
/* Expected PID file name */
if (!arg0)
snprintf(PIDFILE, sizeof(PIDFILE), "%s%s.pid", __pidfile_path, ident);
else if (arg0[0] != '/')
snprintf(PIDFILE, sizeof(PIDFILE), "%s%s.pid", __pidfile_path, arg0);
else
snprintf(PIDFILE, sizeof(PIDFILE), "%s", arg0);
PRINT("Verifying pidfile(%s) ... PID: %d\n", PIDFILE, getpid());
/* Remove any lingering files from previous test runs */
remove(PIDFILE);
signal(SIGTERM, sigterm_handler);
signal(SIGALRM, sigalrm_handler);
/* For signalling test */
alarm(1);
return test(pidfile_poll(PIDFILE) != getpid(), "Testing pidfile_poll()")
|| test(strcmp(__pidfile_name, PIDFILE), "Testing __pidfile_name vs guessed PID filename")
|| test(mtime(), "Testing mtime update of followup pidfile() call")
|| test(pidfile_signal(PIDFILE, SIGTERM), "Testing signalling ourselves")
;
}
static char *progname(char *arg0)
{
char *nm;
nm = strrchr(arg0, '/');
if (nm)
nm++;
else
nm = arg0;
return nm;
}
int main(int argc, char *argv[])
{
int ret = 0;
size_t i;
char *pidfiles[] = {
NULL,
"pidfile_test1",
"/var/tmp/pidfile_test2.pid",
};
if (argc > 1 && !strcmp(argv[1], "-v"))
verbose = 1;
/* Override default _PATH_VARRUN in pidfile() */
__pidfile_path = _PATH_TMP;
/* Find __progname, not all C libraries support this */
ident = progname(argv[0]);
for (i = 0; i < NELEMS(pidfiles); i++)
ret += test_pidfile(pidfiles[i]);
return ret;
}
/**
* Local Variables:
* indent-tabs-mode: t
* c-file-style: "linux"
* compile-command: "make pidfile && ./pidfile -v"
* End:
*/
+51
View File
@@ -0,0 +1,51 @@
#include <stdlib.h> /* atexit() */
#include <unistd.h> /* usleep() */
#include "check.h"
#include "../conio.h"
#define MAX_WIDTH 80
#define msleep(msec) usleep(msec * 1000)
static void bye(void)
{
showcursor();
}
static void testit(int fn, int percent)
{
if (fn)
progress(percent, MAX_WIDTH);
else
progress_simple(percent);
}
static void run_test(int fn)
{
int i, percent, block = 0, num = 85;
while (block < num) {
percent = block * 100 / num;
for (i = 0; i < 10; i++) {
testit(fn, percent);
msleep(1);
}
block++;
msleep(1);
}
testit(fn, 100);
}
int main(void)
{
atexit(bye);
hidecursor();
printf("\nAdvanced:\n");
run_test(1);
printf("\nSimple:\n");
run_test(0);
printf("\n");
return 0;
}
+108
View File
@@ -0,0 +1,108 @@
#include <stdlib.h>
#include "check.h"
#define BASE "/tmp/.unittest/"
#define SRC BASE "src/"
#define DST BASE "dst/"
static int verbose = 0;
static char *files[] = {
SRC "sub1/1.tst",
SRC "sub1/2.tst",
SRC "sub1/3.tst",
SRC "sub2/4.tst",
SRC "sub2/5.tst",
SRC "sub2/6.tst",
SRC "sub3/7.tst",
SRC "sub3/8.tst",
SRC "sub3/9.tst",
NULL
};
void cleanup_test(void)
{
system("rm -rf " BASE);
}
void setup_test(void)
{
int i;
char cmd[256];
mode_t dir_modes[] = { 755, 700 };
mode_t file_modes[] = { 644, 600 };
cleanup_test();
mkdir(BASE, 0755);
mkdir(SRC, 0755);
mkdir(DST, 0755);
for (i = 0; files[i]; i++) {
snprintf(cmd, sizeof(cmd), "mkdir -m %d -p `dirname %s`",
dir_modes[i % 2], files[i]);
system(cmd);
snprintf(cmd, sizeof(cmd), "touch %s; chmod %d %s", files[i],
file_modes[i % 2], files[i]);
system(cmd);
}
}
static void check_tree(char *heading, char *dir)
{
if (verbose) {
if (heading)
puts(heading);
tree(dir, 1);
}
}
int run_test(void)
{
int result = 0;
#if 0
setup_test();
check_tree("Before:", BASE);
result += rsync(SRC, DST, 0, NULL);
check_tree("After:", BASE);
cleanup_test();
#endif
setup_test();
result += rsync(BASE "src", DST, 0, NULL);
check_tree("Only partial rsync of src <-- No slash!", BASE);
#if 0
cleanup_test();
setup_test();
result += rsync(BASE "src/sub1", BASE "dst", 0, NULL);
check_tree("Only partial rsync of src/sub1 <-- No slashes!!", BASE);
cleanup_test();
setup_test();
result += rsync(BASE "src/sub1/", DST, 0, NULL);
check_tree("Only partial rsync of src/sub1/", BASE);
cleanup_test();
setup_test();
result += rsync(BASE "src/sub1", DST, 0, NULL);
check_tree("Only partial rsync of src/sub1 <-- No slash!", BASE);
result += rsync("/etc", "/var/tmp", 0, NULL);
check_tree("Real life test:", "/var/tmp");
#endif
return result;
}
int main(int argc, char *argv[])
{
if (argc > 1)
verbose = !strncmp("-v", argv[1], 2);
atexit(cleanup_test);
return run_test();
}
+36
View File
@@ -0,0 +1,36 @@
#include <fcntl.h> /* O_TMPFILE requires -D_GNU_SOURCE */
#include <paths.h>
#include <stdio.h>
#include <stdlib.h>
#include "check.h"
#ifndef O_TMPFILE
#warning O_TMPFILE is missing, either too old GLIBC, Linux, or non-Linux system
#endif
#define READBACK "Reality is frequently inaccurate.\n"
int main(void)
{
int ret;
FILE *fp;
char buf[80] = "";
printf("Before tempfile():\n");
ret = system("ls -lrt " _PATH_TMP " | tail -3");
fp = tempfile();
fail_unless(fp != NULL);
ret = fputs(READBACK, fp);
rewind(fp);
if (fgets(buf, sizeof(buf), fp))
fprintf(stderr, "\nRead-back from tempfile: %s", buf);
fail_unless(!strcmp(buf, READBACK));
printf("\nAfter tempfile(), should be same list:\n");
ret = system("ls -lrt " _PATH_TMP " | tail -3");
return fclose(fp);
}
+61
View File
@@ -0,0 +1,61 @@
#include <err.h>
#include <paths.h>
#include <signal.h>
#include <stdarg.h>
#include <time.h>
#include "check.h"
int verbose = 0;
static int mtime(char *file)
{
int ret;
char buf[80];
struct stat before, after;
PRINT("Calling touch() to create file ...\n");
touch(file);
stat(file, &before);
/* Must sleep a while here otherwise we execute too fast => no mtime change :-( */
usleep(10000);
PRINT("Calling touch() again to update mtime ...\n");
if (touch(file)) {
erase(file);
err(1, "Failed creating %s", file);
}
stat(file, &after);
ret = timespec_newer(&after.st_mtim, &before.st_mtim);
PRINT("Before: %s\n", timespec2str(&before.st_mtim, buf, sizeof(buf)));
PRINT("After : %s\n", timespec2str(&after.st_mtim, buf, sizeof(buf)));
return !ret;
}
int main(int argc, char *argv[])
{
int fd;
char file[42] = "/tmp/touch_test.XXXXXX";
if (argc > 1 && !strcmp(argv[1], "-v"))
verbose = 1;
fd = mkstemp(file);
if (fd < 0)
err(1, "Failed creating tempfile, %s", file);
close(fd);
return mtime(file);
}
/**
* Local Variables:
* indent-tabs-mode: t
* c-file-style: "linux"
* compile-command: "make pidfile && ./pidfile -v"
* End:
*/
+19
View File
@@ -0,0 +1,19 @@
#include "check.h"
int main(void)
{
int result = 0;
size_t i;
struct { char *path; int fail; } arr[] = {
{ "/etc/passwd", -1 },
{ "/dev", 0 },
{ "/sbin", 0 },
};
for (i = 0; i < NELEMS(arr); i++) {
if (tree(arr[i].path, 1) != arr[i].fail)
result++;
}
return result;
}
+47
View File
@@ -0,0 +1,47 @@
#include "check.h"
struct tc {
char *cmd;
int exp;
int res;
};
int main(void)
{
int result = 0;
size_t i;
struct tc test[] = {
{ "ls", 1 },
{ "free", 1 },
{ "modinfo", 1 },
{ "useradd", 1 },
{ "/etc/passwd", 0 },
{ NULL, 0 }
};
for (i = 0; test[i].cmd; i++) {
char *path;
path = which(test[i].cmd);
if (!path) {
test[i].res = 0;
fprintf(stderr, "%20s : Not hot dog\n", test[i].cmd);
} else {
test[i].res = 1;
fprintf(stderr, "%20s : hot dog --> %s\n", test[i].cmd, path);
free(path);
}
}
for (i = 0; test[i].cmd; i++)
result += test[i].exp != test[i].res;
return result;
}
/**
* Local Variables:
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/
+38 -63
View File
@@ -59,56 +59,54 @@ static void get_perms(struct stat *st, char *buf, size_t len)
static int descend(char *path, int show_perms, char *pfx)
{
int result = 0;
int i, n, result = 0;
struct stat st;
struct dirent **namelist = NULL;
if (-1 == lstat(path, &st))
return 1;
if ((st.st_mode & S_IFMT) == S_IFDIR) {
int i, n;
struct dirent **namelist = NULL;
if ((st.st_mode & S_IFMT) != S_IFDIR) {
errno = ENOTDIR;
return -1;
}
n = scandir(path, &namelist, filter, alphasort);
if (n) {
for (i = 0; i < n; i++) {
char t = ' ', p[14] = "", s[256] = "";
char buf[256];
char dir[80];
n = scandir(path, &namelist, filter, alphasort);
if (n) {
for (i = 0; i < n; i++) {
char t = ' ', p[14] = "", s[256] = "";
char buf[256];
char dir[80];
if (i + 1 == n) {
printf("%s `- ", pfx);
snprintf(dir, sizeof(dir), "%s ", pfx);
} else {
printf("%s|-- ", pfx);
snprintf(dir, sizeof(dir), "%s| ", pfx);
}
snprintf(buf, sizeof(buf), "%s/%s", path, namelist[i]->d_name);
if (!lstat(buf, &st)) {
if (show_perms)
get_perms(&st, p, sizeof(p));
if ((st.st_mode & S_IFMT) == S_IFDIR)
t = '/';
if (S_ISLNK(st.st_mode)) {
snprintf(s, sizeof(s), "-> ");
if (-1 == readlink(buf, &s[3], sizeof(s) - 3))
s[0] = 0;
}
}
printf("%s%s%c%s\n", p, namelist[i]->d_name, t, s);
if (t == '/')
result += descend(buf, show_perms, dir);
free(namelist[i]);
if (i + 1 == n) {
printf("%s `- ", pfx);
snprintf(dir, sizeof(dir), "%s ", pfx);
} else {
printf("%s|-- ", pfx);
snprintf(dir, sizeof(dir), "%s| ", pfx);
}
free(namelist);
snprintf(buf, sizeof(buf), "%s/%s", path, namelist[i]->d_name);
if (!lstat(buf, &st)) {
if (show_perms)
get_perms(&st, p, sizeof(p));
if ((st.st_mode & S_IFMT) == S_IFDIR)
t = '/';
if (S_ISLNK(st.st_mode)) {
snprintf(s, sizeof(s), "-> ");
if (-1 == readlink(buf, &s[3], sizeof(s) - 3))
s[0] = 0;
}
}
printf("%s%s%c%s\n", p, namelist[i]->d_name, t, s);
if (t == '/')
result += descend(buf, show_perms, dir);
free(namelist[i]);
}
} else {
errno = ENOTDIR;
result = -1;
free(namelist);
}
return result;
@@ -120,31 +118,8 @@ int tree(char *path, int show_perms)
return descend(path, show_perms, "");
}
#ifdef UNITTEST
#include "lite.h"
int main(void)
{
int i, result = 0;
struct { char *path; int fail; } arr[] = {
{ "/etc/passwd", -1 },
{ "/dev", 0 },
{ "/sbin", 0 },
};
for (i = 0; i < NELEMS(arr); i++) {
if (tree(arr[i].path, 1) != arr[i].fail)
result++;
}
return result;
}
#endif
/**
* Local Variables:
* compile-command: "make V=1 -f tree.mk"
* version-control: t
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
-4
View File
@@ -1,4 +0,0 @@
OBJS =
TARGET = clean $(OBJS) tree.test
include rules.mk
+89
View File
@@ -0,0 +1,89 @@
/* C implementation of UNIX which(1)
*
* Copyright (c) 2017 Joachim Nilsson <troglobit@gmail.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <errno.h>
#include <stdio.h> /* snprintf() */
#include <stdlib.h> /* realloc(), free() */
#include <string.h> /* strtok_r() */
#include <unistd.h> /* access() */
/*
* Like which(1), returns a malloc'ed path to cmd on success, or NULL
*/
char *which(const char *cmd)
{
size_t pathlen = 0;
char *ptr, *tok, *env, *path = NULL;
if (!cmd) {
errno = EINVAL;
return NULL;
}
if (cmd[0] == '/') {
path = strdup(cmd);
if (!access(path, X_OK))
return path;
if (path)
free(path);
return NULL;
}
ptr = getenv("PATH");
if (!ptr)
return NULL;
env = strdup(ptr);
if (!env)
return NULL;
tok = strtok_r(env, ":", &ptr);
while (tok) {
size_t len = strlen(tok) + strlen(cmd) + 2;
if (pathlen < len) {
path = realloc(path, len);
if (!path) {
free(env);
return NULL;
}
pathlen = len;
}
snprintf(path, pathlen, "%s/%s", tok, cmd);
if (!access(path, X_OK)) {
free(env);
return path;
}
tok = strtok_r(NULL, ":", &ptr);
}
if (path)
free(path);
free(env);
return NULL;
}
/**
* Local Variables:
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/