Compare commits

...
67 Commits
Author SHA1 Message Date
Joachim Nilsson 02d9d9f8c1 Update ChangeLog and bump version for v2.0.2 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-05-10 19:13:56 +02:00
Joachim Nilsson 9f92a9d572 Fix #12: Add missing includes for INT32_MAX and MIN()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-05-10 19:06:07 +02:00
Joachim Nilsson f0e3ed3342 Add basic unit test for strlite.h
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-05-10 19:05:48 +02:00
Joachim Nilsson 34f23a77f8 Missing defines for LLONG_MAX and LLONG_MIN
Some systems may not yet have defined LLONG_MAX and LLONG_MIN in
limits.h, in particular older GLIBC installs are affected.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-02-28 10:43:08 +01:00
Joachim Nilsson 261cf3a01b debian/changelog; Update for new upstream release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-22 12:12:34 +01:00
Joachim Nilsson 2c9c13bd07 Update ChangeLog for v2.0.1
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-22 12:08:05 +01:00
Joachim Nilsson 59ce0c0dc4 Minor ABI bump, changes to lite.h, const + fixed up touch()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-22 12:08:05 +01:00
Joachim Nilsson a603208da9 Redo 60406c3, this is a bug-fix release only: 2.1.0-pre --> 2.0.1
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-22 12:08:05 +01:00
Joachim Nilsson eaac01871b Simplify introduction, and tone it down a bit ...
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-22 12:08:05 +01:00
Joachim Nilsson 8cefa12675 Remove Emacs hinting
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-22 12:08:05 +01:00
Joachim Nilsson 5893010074 Move TODO items to TODO.md
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-22 12:08:05 +01:00
Joachim Nilsson d84bcb3847 copyfile(),movefile(): constify
A `const` string is a declaration to the user of an API that the
implementation does not touch the contents.

We do some `(char *)` casting in this patch, but the resulting
code still does not touch the contents of the original pointer.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-22 11:34:46 +01:00
Joachim Nilsson a9a3a2dda1 constify
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-22 11:34:24 +01:00
Joachim Nilsson 20af39300c ifconfig(): constify
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-22 11:33:55 +01:00
Joachim Nilsson 7b612cda83 lfile: constify
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-22 11:33:37 +01:00
Joachim Nilsson 60406c33f6 Bump version, -pre, for v2.1.0 release cycle
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-22 10:57:37 +01:00
Joachim Nilsson 1d21b11802 lftok(): Refactor, collapse and simplify a bit
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-22 10:56:54 +01:00
Joachim Nilsson a3badc85f8 Fix FTBFS, add missing fcntl.h header for AT_FDCWD
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-21 17:15:39 +01:00
Joachim Nilsson ac936448f5 Only define min() and max() macros if not already defined
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-21 14:19:45 +01:00
Joachim Nilsson 3a26ab28b2 Fix #11: Allow relative paths to touch()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-21 14:17:43 +01:00
Joachim Nilsson 123108fbf9 Fix #10: Supply a default PATH for test
Set a default PATH matching the root user's defaults.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-07 23:09:19 +01:00
Joachim Nilsson 3545d63d2e Fix #9: Use /usr/bin/which, not /bin/which, for unit test.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-07 22:15:40 +01:00
Joachim Nilsson 3e921d72e5 conio.h: Add initscr() declaration after relocation to conio.c
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-22 15:39:16 +01:00
Joachim Nilsson 1c9c038c06 Update copyfile() and rsync() API descriptions, new option flags
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-22 14:18:27 +01:00
Joachim Nilsson e5b79443b8 Bump version for v2.0.0 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-22 14:01:44 +01:00
Joachim Nilsson 589465f48b Update ChangeLog for v2.0.0 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-22 14:01:44 +01:00
Joachim Nilsson 1f745ff9a0 Add head-up to users about changes in v2.0 early in text
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-22 13:58:01 +01:00
Joachim Nilsson 71a0c53029 Bump ABI version, major changes in this release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-22 13:57:44 +01:00
Joachim Nilsson 6608d2e8c9 Remove tree() from libite, moved to troglobit/toolbox.git instead
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-22 13:49:05 +01:00
Joachim Nilsson 62334c80fd Remove fmode() from libite, it's safer to use stat() instead
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-22 12:51:49 +01:00
Joachim Nilsson 626d5456f7 copyfile(): Reduce dependency and simplify, already called stat()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-22 12:49:49 +01:00
Joachim Nilsson e3dff8e5be Reorder source files, sort of alphabetically
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-22 12:46:39 +01:00
Joachim Nilsson bbb951dc23 conio.h: Move initscr() function to conio.c
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-22 10:28:07 +01:00
Joachim Nilsson 94800e7d5c Use distcheck in release target, verifies generated tarball is buildable
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-22 09:04:28 +01:00
Joachim Nilsson 3442d8e12b Update unit test suite with new path to library and header files
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-22 09:03:54 +01:00
Joachim Nilsson 75f57283bd Don't guess where conio.h is, rely on check.h instead
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-22 09:02:51 +01:00
Joachim Nilsson daf41d326b Relocate source files to an src/ sub directory
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-22 09:02:21 +01:00
Joachim Nilsson 3179be4348 Update ChangeLog, hint at future v2.0
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-21 23:57:31 +01:00
Joachim Nilsson 56530a8c78 Ignore global indexing files
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-20 18:37:59 +01:00
Joachim Nilsson abd6e3abd6 Update rsync() unit test slightly, does not verify MTIME yet ...
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-20 17:32:31 +01:00
Joachim Nilsson b078a8676f rsync(): Refactor @delete argument into an @opt to keep mtime
This patch changes the @delete rsync() argument to @opt.  The first bit
is reserved for %LITE_FOPT_RSYNC_DELETE, for backwards compatibility.

A new %LITE_FOPT_KEEP_MTIME option is also added.  If set the mtime of
the @src file is set on @dst, both directories and regular files are
fully supported.  However, if the base @dst directory does not exist,
and rsync() has to create it, its mtime will be the time of the last
file copied into it.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-20 17:29:39 +01:00
Joachim Nilsson c2b92a38ef copyfile(): Refactor @sym argument into an @opt to keep mtime
This patch changes the @sym copyfile() argument to @opt.  The first bit
is reserved for %LITE_FOPT_COPYFILE_SYM, for backwards compatibility.

A new %LITE_FOPT_KEEP_MTIME option is also added.  If set the mtime of
the @src file is set on @dst.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-20 17:24:08 +01:00
Joachim Nilsson 98b2e9d426 debian/changelog: New upstream release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-19 22:43:03 +01:00
Joachim Nilsson 96d3e5dd8b Bump version for v1.9.4 release cycle (-pre)
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-16 21:31:33 +01:00
Joachim Nilsson ff626acb73 Update ChangeLog for upcoming v1.9.4
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-16 21:31:20 +01:00
Joachim Nilsson ba3f7c89fb Update makepath() unit test
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-10-31 21:08:21 +01:00
Joachim Nilsson 714ea88cc9 makepath(): Update doc, recommend mkpath() over this function
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-10-31 21:08:21 +01:00
Joachim Nilsson add4d5d325 Fix #8: constify mkpath() and makepath()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-10-31 21:08:21 +01:00
Joachim Nilsson be6f276557 Fix #7: inconsistent return value in mkpath()
When the required `dir` argument is missing `mkpath()` inconsistently
returns 1 instead of -1.  Found by @jesponde

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-10-31 00:33:19 +01:00
Joachim Nilsson 6daebf4ea4 Bump version for v1.9.3 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-10-24 15:56:30 +02:00
Joachim Nilsson 4d6e3e060e Update ChangeLog(s) for v1.9.3
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-10-24 15:56:17 +02:00
Joachim Nilsson 86eef8e38d tree(): Increase internal buffer size, result may be truncated
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-10-24 08:42:55 +02:00
Joachim Nilsson d5d3dafc78 Slight ABI bump due to changes in initscr()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-10-24 08:38:10 +02:00
Joachim Nilsson 2534c398ea initscr(): Use stdout, not stderr, just like other conio.h macros
A program's stderr may have been redirected by the operator.  We want to
query the size of stdout, even though it is buffered, so add fflush() to
handle that.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-10-24 08:33:02 +02:00
Joachim Nilsson 3691044007 conio.h: initscr() requires termios.h as well
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-10-24 08:32:30 +02:00
Joachim Nilsson 6770dad0cc conio.h: Minor, whitespace only
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-10-24 08:32:18 +02:00
Joachim Nilsson ef0db5e766 initscr(): Check if stdin and stdout are TTYs first
Programs that may be called in the background or with the stdin/stdout
redirected are not proper TTYs and we should not try to perform any
tricks on them.  This patch checks isatty() and returns standard term
sizes as a fallback.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-10-24 08:31:43 +02:00
Joachim Nilsson 485463c70e Update tree() test, use /usr/sbin instead of /sbin
Seems Debian finally went through with their move to symlink /bin and
/sbin to /usr/bin and /usr/sbin, respectively.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-09-30 11:13:23 +02:00
Joachim Nilsson 4b77eb1423 Update ChangeLog diff URLs
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-09-22 16:27:08 +02:00
Joachim Nilsson 0b54dc6015 Update Debian packaging, v1.9.2-1
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-08-15 08:15:30 +02:00
Joachim Nilsson 9d6df87d0d Update ChangeLog and bump version for v1.9.2 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-07-09 15:52:29 +02:00
Joachim Nilsson 5b2eee6aff conio.h: Minor refactor, cleanup
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-07-09 15:46:49 +02:00
Joachim Nilsson 6904f6e0fe conio.h: Add initscr(), probes terminal rows + cols
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-07-07 13:19:53 +02:00
Joachim Nilsson 877ba02d13 conio.h: Revert 018e607, fails unit tests
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-07-07 13:19:23 +02:00
Joachim Nilsson 25dfded835 conio.h: Update copyright years
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-07-07 12:51:43 +02:00
Joachim Nilsson 1323a88e94 conio.h: Convert printheader() to static inline function
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-07-07 12:51:25 +02:00
Joachim Nilsson 018e607290 conio.h: Use stderr instead of stdout because it's non-buffered
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-07-07 11:58:48 +02:00
48 changed files with 498 additions and 390 deletions

No files matched your search

+4
View File
@@ -6,6 +6,10 @@
*.a *.a
.deps .deps
.libs .libs
ID
GPATH
GRTAGS
GTAGS
tmp/ tmp/
compile compile
config.* config.*
+78 -7
View File
@@ -4,6 +4,78 @@ Change Log
All notable changes to the project are documented in this file. All notable changes to the project are documented in this file.
[v2.0.2][] - 2018-05-10
-----------------------
### Fixes
- Fix issue #12, missing includes in `strlite.h` for standalone use
- FTBFS `strtonum.c` on older systems w/o `LLONG_MAX` and `LLONG_MIN`
[v2.0.1][] - 2017-12-22
-----------------------
### Changes
- Add missing `initscr()` declaration, regression in [v2.0.0][]
- Add `#ifdef` guards around `min()` and `max()` macros
- Add `const` to `char *` args in multiple API:s:
- `fexist()`
- `fgetint()`
- `fisslashdir()`
- `copyfile()`
- `movefile()`
- `ifconfig()`
- `lfopen()`
- `lfgetkey()`
- `lfgetint()`
### Fixes
- Fix #9, uncommon location of `which` command in unit test
- Fix #10, supply unit test with a default `$PATH`
- Fix #11, `touch()` command cannot handle relative paths when updating
the mtime of an existing file
[v2.0.0][] - 2017-11-22
-----------------------
### Changes
- Remove `tree()`, moved to toolbox.git instead
- Remove `fmode()`, please use `stat()` instead, it's safer
- Add support for keeping mtime in `copy()` and `rsync()`
- Move source files to an `src/` sub-directory
- Move `initscr()` from `conio.h` to `conio.c`
- Update docs, recommend `mkpath()` over `makepath()`
- Bump ABI version, major changes to library
### Fixes
- Fix #7, inconsistent return value in `mkpath()` and `makepath()`
- Fix #8, constify `mkpath()` and `makepath()`
[v1.9.3][] - 2017-10-24
-----------------------
### Changes
- `initscr()`, use stdout, not stderr, like the rest of the
`conio.h` macros. Also, stderr may be redirected by user
- `tree()`, update unit test, use standard directries
### Fixes
- `initscr()`, verify that both stdin and stdout are real TTYs
before messing up output or blocking on input for the user
- `tree()`, increase internal buffer slightly, output may be
truncated otherwise. Found by GCC 7.2
[v1.9.2][] - 2017-07-09
-----------------------
### Changes
- Add `initscr()` function to query screen size
- Convert `printheader()` to a static inline function
[v1.9.1][] - 2017-07-03 [v1.9.1][] - 2017-07-03
----------------------- -----------------------
@@ -252,7 +324,12 @@ problems this may cause!
Initial extraction of frog DNA from [Finit][]. See [README][] for API details. Initial extraction of frog DNA from [Finit][]. See [README][] for API details.
[UNRELEASED]: https://github.com/troglobit/libite/compare/v1.9.1...HEAD [UNRELEASED]: https://github.com/troglobit/libite/compare/v2.0.2...HEAD
[v2.0.2]: https://github.com/troglobit/libite/compare/v2.0.1...v2.0.2
[v2.0.1]: https://github.com/troglobit/libite/compare/v2.0.0...v2.0.1
[v2.0.0]: https://github.com/troglobit/libite/compare/v1.9.3...v2.0.0
[v1.9.3]: https://github.com/troglobit/libite/compare/v1.9.2...v1.9.3
[v1.9.2]: https://github.com/troglobit/libite/compare/v1.9.1...v1.9.2
[v1.9.1]: https://github.com/troglobit/libite/compare/v1.9.0...v1.9.1 [v1.9.1]: https://github.com/troglobit/libite/compare/v1.9.0...v1.9.1
[v1.9.0]: https://github.com/troglobit/libite/compare/v1.8.3...v1.9.0 [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.3]: https://github.com/troglobit/libite/compare/v1.8.2...v1.8.3
@@ -277,9 +354,3 @@ Initial extraction of frog DNA from [Finit][]. See [README][] for API details.
[Inadyn]: https://github.com/troglobit/inadyn/ [Inadyn]: https://github.com/troglobit/inadyn/
[Mg]: https://github.com/troglobit/mg [Mg]: https://github.com/troglobit/mg
[README]: https://github.com/troglobit/libite/blob/v1.0.0/README.md [README]: https://github.com/troglobit/libite/blob/v1.0.0/README.md
<!--
-- Local Variables:
-- mode: markdown
-- End:
-->
+4 -16
View File
@@ -1,22 +1,10 @@
ACLOCAL_AMFLAGS = -I m4 ACLOCAL_AMFLAGS = -I m4
lib_LTLIBRARIES = libite.la
pkgincludedir = $(includedir)/lite
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 4:0:0
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libite.pc
doc_DATA = README.md LICENSE doc_DATA = README.md LICENSE
EXTRA_DIST = README.md LICENSE ChangeLog.md EXTRA_DIST = README.md LICENSE ChangeLog.md
SUBDIRS = tests pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libite.pc
SUBDIRS = src tests
## Generate .deb package ## Generate .deb package
package: package:
@@ -48,7 +36,7 @@ release-hook:
fi fi
## Target to run when building a release ## Target to run when building a release
release: dist release-hook md5-dist release: distcheck release-hook md5-dist
@for file in $(DIST_ARCHIVES); do \ @for file in $(DIST_ARCHIVES); do \
printf "$$file \tDistribution tarball\n"; \ printf "$$file \tDistribution tarball\n"; \
printf "$$file.md5\t"; cat $$file.md5 | cut -f1 -d' '; \ printf "$$file.md5\t"; cat $$file.md5 | cut -f1 -d' '; \
+32 -42
View File
@@ -15,27 +15,24 @@ Table of Contents
* [TODO](#todo) * [TODO](#todo)
> **NOTE:** Incompatible changes in v2.0 compared to v1.x!
Introduction Introduction
------------ ------------
Libite is a lightweight library of *frog DNA*. It can be used to fill Libite is a lightweight library of *frog DNA* that can be used to fill
the gaps in any dinosaur project. It holds useful functions and macros the gaps in any dinosaur project. It holds useful functions and macros
developed by both [Finit][1] and the [OpenBSD][2] project. Most notably developed by both [Finit][1] and the [OpenBSD][2] project. Most notably
the string functions: [strlcpy(3)][3], [strlcat(3)][3] and the highly the string functions: [strlcpy(3)][3], [strlcat(3)][3] and the highly
useful *BSD [sys/queue.h][4] and [sys/tree.h][7] API's. useful *BSD [sys/queue.h][4] and [sys/tree.h][7] API's.
Libite is the frog DNA missing in GNU libc. However, -lite does not aim Libite holds many of the missing pieces in GNU libc, although -lite does
to become another [GLIB][5]! One noticeable gap in GLIBC is the missing not aim to become another [GLIB][5]. One noticeable gap in GLIBC is the
`_SAFE` macros in the BSD `sys/queue.h` API &mdash; highly recommended `_SAFE` macros available in the BSD `sys/queue.h` API &mdash; highly
when traversing lists to delete/free nodes. recommended when traversing lists to delete/free nodes.
The code is open sourced under a mix of the [MIT/X11 license][MIT], the The code is open sourced under a mix of permissive Open Source licenses:
[ISC license][ISC] used by OpenBSD, and [BSD licenses][BSD], all of them [MIT/X11 license][MIT], [ISC license][ISC], and [BSD licenses][BSD].
are extremely liberal and can be used freely in proprietary software if
needed.
For an introduction to why Libite happened, and how you can use it, see
[this blog post][6].
Using -lite Using -lite
@@ -151,9 +148,18 @@ Generic Functions
Perl like chomp function, chop off last char if newline. Perl like chomp function, chop off last char if newline.
- `copyfile(src, dst, len, symlink)` - `copyfile(src, dst, len, opt)`
Like the shell `cp(1)` and `dd(1),` can also create symlinks. Like the shell `cp(1)` and `dd(1),`, can also copy symlinks and
preserve the mtime of the source file. The opt argument can be
a mask of:
- `LITE_FOPT_COPYFILE_SYM (0x01)`
- `LITE_FOPT_KEEP_MTIME (0x02)`
In releases prior to v2.0 the opt argument was called `symlink`.
The APIs are 100% compatible if the value `1` was used to enable
the symlink option.
- `dir(dir, ext, filter, list, strip)` - `dir(dir, ext, filter, list, strip)`
@@ -175,10 +181,6 @@ Generic Functions
Check for the existence of a directory, returns True(1) or False(0). Check for the existence of a directory, returns True(1) or False(0).
- `fmode(file)`
Returns the `mode_t` bits of a file or directory.
- `fsendfile(src, dst, len)` - `fsendfile(src, dst, len)`
Copy data between file streams, very similar to `fcopyfile()`, but Copy data between file streams, very similar to `fcopyfile()`, but
@@ -268,10 +270,19 @@ Generic Functions
Called multiple times with the same percentage value cause spinner to Called multiple times with the same percentage value cause spinner to
spin. spin.
- `rsync(src, dst, delete, *filter())` - `rsync(src, dst, opt, *filter())`
Very simple `rsync()` to copy files files and directories Very simple `rsync()` to copy files and directories recursively. It
recursively. supports pruning files from the destination tree that do not exist in
the source tree and preserving the mtime of the source files. The opt
argument can be a mask of:
- `LITE_FOPT_RSYNC_DELETE (0x01)`
- `LITE_FOPT_KEEP_MTIME (0x02)`
In releases prior to v2.0 the argument controlling pruning was called
`delete`, it is now called `opt`. The APIs are 100% compatible if the
value `1` was used.
- `tempfile()` - `tempfile()`
@@ -282,12 +293,6 @@ Generic Functions
**Note:** Requires Linux v3.11, or later, will fall back to the old **Note:** Requires Linux v3.11, or later, will fall back to the old
and unsafe `tmpfile()` on older systems. and unsafe `tmpfile()` on older systems.
- `tree(path, show_perms)`
Very simple `/bin/tree` replacement. Draw ASCII tree of `path`, with
optional listing of file and directory permissions if `show_perms` is
set. The `path` argument should be a directory.
- `which(cmd)`, `whichp(cmd)` - `which(cmd)`, `whichp(cmd)`
C implementation of UNIX which(1). Returns a malloc'ed string with the C implementation of UNIX which(1). Returns a malloc'ed string with the
@@ -373,8 +378,6 @@ Build & Install
This library was initially built for and developed on GNU/Linux systems This library was initially built for and developed on GNU/Linux systems
as a light weight utility library, these days NetBSD should also work. 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 ./configure
make -j5 make -j5
@@ -386,27 +389,14 @@ generate a `configure` script. It is a generated file and otherwise only
included in released tarballs. included in released tarballs.
TODO
----
- Improve documentation, possibly use kdoc or gdoc2 to generate docs from API.
- Continuously, update OpenBSD functions/macros.
[1]: https://github.com/troglobit/finit [1]: https://github.com/troglobit/finit
[2]: http://www.openbsd.org/ [2]: http://www.openbsd.org/
[3]: http://www.openbsd.org/cgi-bin/man.cgi?query=strlcpy [3]: http://www.openbsd.org/cgi-bin/man.cgi?query=strlcpy
[4]: http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man3/LIST_EMPTY.3 [4]: http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man3/LIST_EMPTY.3
[5]: https://developer.gnome.org/glib/ [5]: https://developer.gnome.org/glib/
[6]: http://troglobit.com/blog/2015/07/02/howto-using-lite-with-a-git-based-application/
[7]: http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man3/SPLAY_FOREACH.3 [7]: http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man3/SPLAY_FOREACH.3
[MIT]: https://en.wikipedia.org/wiki/MIT_License [MIT]: https://en.wikipedia.org/wiki/MIT_License
[ISC]: https://en.wikipedia.org/wiki/ISC_license [ISC]: https://en.wikipedia.org/wiki/ISC_license
[BSD]: https://en.wikipedia.org/wiki/BSD_licenses [BSD]: https://en.wikipedia.org/wiki/BSD_licenses
[Travis]: https://travis-ci.org/troglobit/libite [Travis]: https://travis-ci.org/troglobit/libite
[Travis Status]: https://travis-ci.org/troglobit/libite.png?branch=master [Travis Status]: https://travis-ci.org/troglobit/libite.png?branch=master
<!--
-- Local Variables:
-- mode: markdown
-- End:
-->
+2 -1
View File
@@ -1,7 +1,8 @@
TODO ... in no particular order TODO ... in no particular order
=============================== ===============================
* Improve documentation, possibly use kdoc or gdoc2 to generate docs from API
* Continuously, update OpenBSD functions/macros
* Investigate adding FreeBSD pidfile_open() et al * Investigate adding FreeBSD pidfile_open() et al
* Investigate FreeBSD libutil library, could be useful for porting between unices * Investigate FreeBSD libutil library, could be useful for porting between unices
+3 -3
View File
@@ -1,10 +1,10 @@
AC_INIT(libite, 1.9.1, https://github.com/troglobit/libite/issues) AC_INIT(libite, 2.0.2, https://github.com/troglobit/libite/issues)
AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz]) AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz])
AM_SILENT_RULES([yes]) AM_SILENT_RULES([yes])
AC_CONFIG_SRCDIR(lite.h) AC_CONFIG_SRCDIR(src/lite.h)
AM_CONFIG_HEADER(config.h) AM_CONFIG_HEADER(config.h)
AC_CONFIG_FILES([Makefile tests/Makefile libite.pc]) AC_CONFIG_FILES([Makefile src/Makefile tests/Makefile libite.pc])
AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_MACRO_DIR([m4])
AC_PROG_CC AC_PROG_CC
+41
View File
@@ -1,3 +1,44 @@
libite (2.0.2) unstable; urgency=medium
* Fix issues with using `strlite.h` standalone
* Fix build issue with `strtonum.c` older GLIBC
-- Joachim Nilsson <troglobit@gmail.com> Thu, 10 May 2018 19:12:57 +0200
libite (2.0.1-1) unstable; urgency=medium
* New upstream release, v2.0.1, fixes to:
- touch(), cannot handle relative paths when updating mtime
- unit test for which()
- add missing initscr() declaration in conio.h
- ifdef guards around min()/max() macros
-- Joachim Nilsson <troglobit@gmail.com> Fri, 22 Dec 2017 12:11:41 +0100
libite (2.0.0-1) unstable; urgency=low
* New upstream release, v2.0.0, fixes to:
- makepath(), mkpath()
* Changes to
- rsync(), API changes
- copyfile(), API changes
- tree(), removed from library
- fmode(), removed from library
-- Joachim Nilsson <troglobit@gmail.com> Sun, 19 Nov 2017 22:42:51 +0100
libite (1.9.3-1) unstable; urgency=low
* New upstream release, v1.9.3, fixes to conio.h, initscr() and tree().
-- Joachim Nilsson <troglobit@gmail.com> Tue, 24 Oct 2017 08:49:54 +0200
libite (1.9.2-1) unstable; urgency=low
* New upstream reelase, v1.9.2, see upstream ChangeLog for details.
-- Joachim Nilsson <troglobit@gmail.com> Tue, 15 Aug 2017 08:15:14 +0200
libite (1.9.1-1) unstable; urgency=low libite (1.9.1-1) unstable; urgency=low
* New upstream reelase, v1.9.1. * New upstream reelase, v1.9.1.
-56
View File
@@ -1,56 +0,0 @@
/* File mode bit operations
*
* Copyright (c) 2008 Claudio Matsuoka <http://helllabs.org/finit/>
*
* 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.
*/
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
/**
* fmode - Return a file's mode bits.
* @file: File to look for, with full path.
*
* Returns:
* The mode bits or zero when @file does not exist and errno set to %ENOENT.
*/
mode_t fmode(char *file)
{
struct stat sb;
if (!file) {
errno = EINVAL;
return 0;
}
if (!stat(file, &sb))
return sb.st_mode;
return 0;
}
/**
* Local Variables:
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/
+24
View File
@@ -0,0 +1,24 @@
lib_LTLIBRARIES = libite.la
libite_la_CPPFLAGS = -D_GNU_SOURCE
libite_la_CFLAGS = -W -Wall -Wextra
libite_la_LDFLAGS = $(AM_LDFLAGS) -version-info 5:1:0
libite_la_SOURCES = chomp.c copyfile.c \
conio.c conio.h \
dir.c \
fexist.c fisdir.c \
fparseln.c fsendfile.c \
ifconfig.c lfile.c \
makepath.c progress.c \
pidfile.c pidfilefn.c \
reallocarray.c rsync.c \
strlcpy.c strlcat.c strtonum.c \
strdupa.h strndupa.h strnlen.h \
tempfile.c which.c \
lite.h strlite.h \
queue.h tree.h
## Distribute these header files in the <lite/...> name space
pkgincludedir = $(includedir)/lite
pkginclude_HEADERS = lite.h queue.h conio.h tree.h strlite.h strdupa.h strndupa.h strnlen.h
View File
File renamed without changes.
+83
View File
@@ -0,0 +1,83 @@
/* A conio.h like implementation for VTANSI displays.
*
* Copyright (c) 2009-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 <poll.h>
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
void initscr(int *row, int *col)
{
if (!row || !col)
return;
#if defined(TCSANOW) && defined(POLLIN)
struct termios tc, saved;
struct pollfd fd = { STDIN_FILENO, POLLIN, 0 };
if (!isatty(STDIN_FILENO) || !isatty(STDOUT_FILENO)) {
*row = 24;
*col = 80;
return;
}
/* Disable echo to terminal while probing */
tcgetattr(STDOUT_FILENO, &tc);
saved = tc;
tc.c_cflag |= (CLOCAL | CREAD);
tc.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
tcsetattr(STDOUT_FILENO, TCSANOW, &tc);
/*
* Save cursor pos+attr
* Diable top+bottom margins
* Set cursor at the far bottom,right pos
* Query term for resulting pos
*/
fprintf(stdout, "\e7" "\e[r" "\e[999;999H" "\e[6n");
fflush(stdout);
/*
* Wait here for terminal to echo back \e[row,lineR ...
*/
if (poll(&fd, 1, 300) <= 0 || scanf("\e[%d;%dR", row, col) != 2) {
*row = 24;
*col = 80;
}
/*
* Restore above saved cursor pos+attr
*/
fprintf(stdout, "\e8");
fflush(stdout);
/* Restore terminal */
tcsetattr(STDOUT_FILENO, TCSANOW, &saved);
return;
#else
*row = 24;
*col = 80;
#endif
}
/**
* Local Variables:
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/
+23 -16
View File
@@ -1,6 +1,6 @@
/* A conio.h like implementation for VTANSI displays. /* A conio.h like implementation for VTANSI displays.
* *
* Copyright (c) 2009-2013 Joachim Nilsson <troglobit@gmail.com> * Copyright (c) 2009-2017 Joachim Nilsson <troglobit@gmail.com>
* *
* Permission to use, copy, modify, and/or distribute this software for any * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@@ -49,35 +49,42 @@
#define WHITE 0x17 #define WHITE 0x17
#ifndef SCREEN_WIDTH #ifndef SCREEN_WIDTH
#define SCREEN_WIDTH 80 /* Override as #define SCREEN_WIDTH tty_width() */ #define SCREEN_WIDTH 80 /* Override using, e.g. #define SCREEN_WIDTH tty_width() */
#endif #endif
/* Esc[2JEsc[1;1H - Clear screen and move cursor to 1,1 (upper left) pos. */ /* Esc[2JEsc[1;1H - Clear screen and move cursor to 1,1 (upper left) pos. */
#define clrscr() fputs ("\033[2J\033[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. */ /* Esc[K - Erases from the current cursor position to the end of the current line. */
#define clreol() fputs ("\033[K", stdout) #define clreol() fputs("\033[K", stdout)
/* Esc[2K - Erases the entire current line. */ /* Esc[2K - Erases the entire current line. */
#define delline() fputs ("\033[2K", stdout) #define delline() fputs("\033[2K", stdout)
/* Esc[Line;ColumnH - Moves the cursor to the specified position (coordinates) */ /* Esc[Line;ColumnH - Moves the cursor to the specified position (coordinates) */
#define gotoxy(x,y) printf("\033[%d;%dH", y, x) #define gotoxy(x,y) fprintf(stdout, "\033[%d;%dH", y, x)
/* Esc[?25l (lower case L) - Hide Cursor */ /* Esc[?25l (lower case L) - Hide Cursor */
#define hidecursor() fputs ("\033[?25l", stdout) #define hidecursor() fputs("\033[?25l", stdout)
/* Esc[?25h (lower case H) - Show Cursor */ /* Esc[?25h (lower case H) - Show Cursor */
#define showcursor() fputs ("\033[?25h", stdout) #define showcursor() fputs("\033[?25h", stdout)
/* Esc[Value;...;Valuem - Set Graphics Mode */ /* Esc[Value;...;Valuem - Set Graphics Mode (attr, color, val) */
#define __set_gm(attr,color,val) \ #define __set_gm(a,c,v) \
if (!color) \ if (!c) \
printf("\033[%dm", attr); \ fprintf(stdout, "\033[%dm", a); \
else \ else \
printf("\033[%d;%dm", color & 0x10 ? 1 : 0, (color & 0xF) + val) fprintf(stdout, "\033[%d;%dm", c & 0x10 ? 1 : 0, (c & 0xF) + v)
#define textattr(attr) __set_gm(attr, 0, 0) #define textattr(attr) __set_gm(attr, 0, 0)
#define textcolor(color) __set_gm(RESETATTR, color, 30) #define textcolor(color) __set_gm(RESETATTR, color, 30)
#define textbackground(color) __set_gm(RESETATTR, color, 40) #define textbackground(color) __set_gm(RESETATTR, color, 40)
#define printheader(fp, line, nl) \ void initscr(int *row, int *col);
fprintf(fp ?: stdout, "%s\033[7m%s%*s\033[0m\n", nl ? "\n" : "",\
line, SCREEN_WIDTH - (int)strlen(line), "") /* Print table heading @line to @fp, with optional leading newline */
static inline void printheader(FILE *fp, const char *line, int nl)
{
fprintf(fp ?: stdout,
"%s\033[7m%s%*s\033[0m\n",
nl ? "\n" : "",
line, SCREEN_WIDTH - (int)strlen(line), "");
}
#endif /* CONIO_H_ */ #endif /* CONIO_H_ */
+37 -14
View File
@@ -27,7 +27,7 @@
#include "lite.h" #include "lite.h"
/* Tests if dst is a directory, if so, reallocates dst and appends src filename returning 1 */ /* Tests if dst is a directory, if so, reallocates dst and appends src filename returning 1 */
static int adjust_target(char *src, char **dst) static int adjust_target(const char *src, char **dst)
{ {
int isdir = 0; int isdir = 0;
@@ -36,7 +36,7 @@ static int adjust_target(char *src, char **dst)
char *tmp, *ptr = strrchr(src, '/'); char *tmp, *ptr = strrchr(src, '/');
if (!ptr) if (!ptr)
ptr = src; ptr = (char *)src;
else else
ptr++; ptr++;
@@ -80,26 +80,46 @@ static ssize_t do_copy(int in, int out, size_t num, char *buffer, size_t len)
return size; return size;
} }
static void set_mtime(int in, int out)
{
struct stat st;
struct timespec tv[2];
fstat(in, &st);
tv[0] = st.st_atim;
tv[1] = st.st_mtim;
futimens(out, tv);
}
/** /**
* copyfile - Copy a file to another. * copyfile - Copy a file to another.
* @src: Full path name to source file. * @src: Full path name to source file.
* @dst: Full path name to target file. * @dst: Full path name to target file.
* @len: Number of bytes to copy, zero (0) for entire file. * @len: Number of bytes to copy, zero (0) for entire file.
* @sym: Should symlinks be recreated (1) or followed (0) * @opt: An option mask of %LITE_FOPT_COPYFILE_SYM, %LITE_FOPT_KEEP_MTIME
* *
* This is a C implementation of the command line cp(1) utility. It is one * This is a C implementation of the command line cp(1) utility. It is one
* of the classic missing links in the UNIX C library. This version is from * of the classic missing links in the UNIX C library. This version is from
* the finit project, http://helllabs.org/finit/, which is a reimplementation * the finit project, http://helllabs.org/finit/, which is a reimplementation
* of fastinit for the Asus EeePC. * of fastinit for the Asus EeePC.
* *
* The @opt field replaces the @sym argument in previous releases and
* works as follows. To maintain backwards compatibility with @sym
* the %LITE_FOPT_COPYFILE_SYM maintains a value of 1:
*
* %LITE_FOPT_COPYFILE_SYM: Recreate symlink or follow to copy target
* %LITE_FOPT_KEEP_MTIME: Preserve modification time
*
* Returns: * Returns:
* The number of bytes copied, zero may be error (check errno!), but it * The number of bytes copied, zero may be error (check errno!), but it
* may also indicate that @src was empty. If @src is a directory @errno * may also indicate that @src was empty. If @src is a directory @errno
* will be set to %EISDIR since copyfile() is not recursive. * will be set to %EISDIR since copyfile() is not recursive.
*/ */
ssize_t copyfile(char *src, char *dst, int len, int sym) ssize_t copyfile(const char *src, const char *dst, int len, int opt)
{ {
char *buffer; char *buffer, *dest = (char *)dst;
int sym = (opt & LITE_FOPT_COPYFILE_SYM) != 0;
int keep_mtim = (opt & LITE_FOPT_KEEP_MTIME) != 0;
int in, out, isdir = 0, saved_errno = 0; int in, out, isdir = 0, saved_errno = 0;
size_t num; size_t num;
ssize_t size = 0; ssize_t size = 0;
@@ -117,7 +137,7 @@ ssize_t copyfile(char *src, char *dst, int len, int sym)
} }
/* Check if target is a directory, then append src filename. */ /* Check if target is a directory, then append src filename. */
isdir = adjust_target(src, &dst); isdir = adjust_target(src, &dest);
/* Check if the source file is a symlink ... */ /* Check if the source file is a symlink ... */
if (stat(src, &st)) { if (stat(src, &st)) {
@@ -134,7 +154,7 @@ ssize_t copyfile(char *src, char *dst, int len, int sym)
size = -1; size = -1;
} else { } else {
buffer[size] = 0; buffer[size] = 0;
size = !symlink(buffer, dst); size = !symlink(buffer, dest);
} }
} }
@@ -155,7 +175,7 @@ ssize_t copyfile(char *src, char *dst, int len, int sym)
goto exit; goto exit;
} }
out = open(dst, O_WRONLY | O_CREAT | O_TRUNC, fmode(src)); out = open(dest, O_WRONLY | O_CREAT | O_TRUNC, st.st_mode);
if (out < 0) { if (out < 0) {
close(in); close(in);
saved_errno = errno; saved_errno = errno;
@@ -165,6 +185,8 @@ ssize_t copyfile(char *src, char *dst, int len, int sym)
size = do_copy(in, out, num, buffer, BUFSIZ); size = do_copy(in, out, num, buffer, BUFSIZ);
if (!size && errno) if (!size && errno)
saved_errno = errno; saved_errno = errno;
else if (keep_mtim)
set_mtime(in, out);
close(out); close(out);
close(in); close(in);
@@ -172,7 +194,7 @@ ssize_t copyfile(char *src, char *dst, int len, int sym)
exit: exit:
free(buffer); free(buffer);
if (isdir) if (isdir)
free(dst); free(dest);
errno = saved_errno; errno = saved_errno;
return size; return size;
@@ -194,17 +216,18 @@ exit:
* Returns: * Returns:
* POSIX OK(0), or non-zero with errno set. * POSIX OK(0), or non-zero with errno set.
*/ */
int movefile(char *src, char *dst) int movefile(const char *src, const char *dst)
{ {
char *dest = (char *)dst;
int isdir, result = 0; int isdir, result = 0;
/* Check if target is a directory, then append the src base filename. */ /* Check if target is a directory, then append the src base filename. */
isdir = adjust_target(src, &dst); isdir = adjust_target(src, &dest);
if (rename(src, dst)) { if (rename(src, dest)) {
if (errno == EXDEV) { if (errno == EXDEV) {
errno = 0; errno = 0;
copyfile(src, dst, 0, 1); copyfile(src, dest, 0, 1);
if (errno) if (errno)
result = 1; result = 1;
else else
@@ -215,7 +238,7 @@ int movefile(char *src, char *dst)
} }
if (isdir) if (isdir)
free(dst); free(dest);
return result; return result;
} }
View File
File renamed without changes.
+1 -1
View File
@@ -31,7 +31,7 @@
* Returns: * Returns:
* %TRUE(1) if the file exists, otherwise %FALSE(0). * %TRUE(1) if the file exists, otherwise %FALSE(0).
*/ */
int fexist(char *file) int fexist(const char *file)
{ {
if (!file) { if (!file) {
errno = EINVAL; errno = EINVAL;
View File
File renamed without changes.
View File
File renamed without changes.
View File
File renamed without changes.
+1 -1
View File
@@ -43,7 +43,7 @@ extern size_t strlcpy(char *dst, const char *src, size_t siz);
* Returns: * Returns:
* POSIX OK(0) on success, or non-zero on error. * POSIX OK(0) on success, or non-zero on error.
*/ */
int ifconfig(char *ifname, char *addr, char *mask, int up) int ifconfig(const char *ifname, const char *addr, const char *mask, int up)
{ {
int sd, ret = -1; int sd, ret = -1;
struct ifreq ifr; struct ifreq ifr;
+15 -17
View File
@@ -24,7 +24,8 @@
typedef struct lfile { typedef struct lfile {
FILE *fp; FILE *fp;
char buf[256]; char buf[256];
char *sep, *save; char *save;
const char *sep;
} lfile_t; } lfile_t;
/** /**
@@ -35,7 +36,7 @@ typedef struct lfile {
* Returns: * Returns:
* Pointer to a &lftile_t parser context, or %NULL on error. * Pointer to a &lftile_t parser context, or %NULL on error.
*/ */
lfile_t *lfopen(char *file, char *sep) lfile_t *lfopen(const char *file, const char *sep)
{ {
lfile_t *lf; lfile_t *lf;
@@ -92,23 +93,20 @@ char *lftok(lfile_t *lf)
} }
token = strtok_r(NULL, lf->sep, &lf->save); token = strtok_r(NULL, lf->sep, &lf->save);
if (!token) { if (token)
while (fgets(lf->buf, sizeof(lf->buf), lf->fp)) { return token;
if (lf->buf[0] == '#')
continue;
token = strtok_r(lf->buf, lf->sep, &lf->save); while (fgets(lf->buf, sizeof(lf->buf), lf->fp)) {
if (!token) if (lf->buf[0] == '#')
continue; continue;
token = strtok_r(lf->buf, lf->sep, &lf->save);
if (token)
return token; return token;
}
errno = ENOENT;
return NULL;
} }
return token; errno = ENOENT;
return NULL;
} }
/** /**
@@ -125,7 +123,7 @@ char *lftok(lfile_t *lf)
* Returns: * Returns:
* The value to @key, or %NULL if not found. * The value to @key, or %NULL if not found.
*/ */
char *lfgetkey(lfile_t *lf, char *key) char *lfgetkey(lfile_t *lf, const char *key)
{ {
char *token; char *token;
@@ -151,7 +149,7 @@ char *lfgetkey(lfile_t *lf, char *key)
* Returns: * Returns:
* The positive integer value for @key, or -1 if not found. * The positive integer value for @key, or -1 if not found.
*/ */
int lfgetint(lfile_t *lf, char *key) int lfgetint(lfile_t *lf, const char *key)
{ {
char *token = lfgetkey(lf, key); char *token = lfgetkey(lf, key);
@@ -173,7 +171,7 @@ int lfgetint(lfile_t *lf, char *key)
* Returns: * Returns:
* The positive integer value for @key, or -1 if not found. * The positive integer value for @key, or -1 if not found.
*/ */
int fgetint(char *file, char *sep, char *key) int fgetint(const char *file, const char *sep, const char *key)
{ {
int val = -1; int val = -1;
lfile_t *lf; lfile_t *lf;
+21 -16
View File
@@ -26,6 +26,7 @@
#define LITE_H_ #define LITE_H_
#include <errno.h> #include <errno.h>
#include <fcntl.h> /* Definition of AT_* constants for utimensat() */
#include <stdio.h> #include <stdio.h>
#include <stdint.h> /* uint8_t, uint16_t, uint32_t, INT32_MAX, etc. */ #include <stdint.h> /* uint8_t, uint16_t, uint32_t, INT32_MAX, etc. */
#include <sys/stat.h> #include <sys/stat.h>
@@ -43,35 +44,41 @@
#define FPARSELN_UNESCREST 0x08 #define FPARSELN_UNESCREST 0x08
#define FPARSELN_UNESCALL 0x0f #define FPARSELN_UNESCALL 0x0f
/*
* copyfile() and rsync() option flags
*/
#define LITE_FOPT_RSYNC_DELETE 0x01
#define LITE_FOPT_COPYFILE_SYM 0x01
#define LITE_FOPT_KEEP_MTIME 0x02
typedef struct lfile lfile_t; typedef struct lfile lfile_t;
char *chomp (char *str); char *chomp (char *str);
char *fparseln (FILE *, size_t *, size_t *, const char[3], int); char *fparseln (FILE *, size_t *, size_t *, const char[3], int);
int fexist (char *file); int fexist (const char *file);
int fisdir (const char *file); int fisdir (const char *file);
mode_t fmode (char *file);
FILE *tempfile (void); FILE *tempfile (void);
ssize_t copyfile (char *src, char *dst, int len, int sym); ssize_t copyfile (const char *src, const char *dst, int len, int opt);
int movefile (char *src, char *dst); int movefile (const char *src, const char *dst);
int fcopyfile (FILE *src, FILE *dst); int fcopyfile (FILE *src, FILE *dst);
ssize_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); int ifconfig (const char *ifname, const char *addr, const char *mask, int up);
lfile_t*lfopen (char *file, char *sep); lfile_t*lfopen (const char *file, const char *sep);
void lfclose (lfile_t *lf); void lfclose (lfile_t *lf);
char *lftok (lfile_t *lf); char *lftok (lfile_t *lf);
char *lfgetkey (lfile_t *lf, char *key); char *lfgetkey (lfile_t *lf, const char *key);
int lfgetint (lfile_t *lf, char *key); int lfgetint (lfile_t *lf, const char *key);
int fgetint (char *file, char *sep, char *key); int fgetint (const char *file, const char *sep, const char *key);
int mkpath (char *dir, mode_t mode); int mkpath (const char *dir, mode_t mode);
int makepath (char *dir); int makepath (const char *dir);
int dir (const char *dir, const char *type, int (*filter) (const char *file), char ***list, int strip); 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 opt, int (*filter) (const char *file));
int pidfile (const char *basename); int pidfile (const char *basename);
int pidfile_signal(const char *pidfile, int signal); int pidfile_signal(const char *pidfile, int signal);
@@ -80,8 +87,6 @@ pid_t pidfile_poll (const char *pidfile);
void *reallocarray(void *optr, size_t nmemb, size_t size); void *reallocarray(void *optr, size_t nmemb, size_t size);
int tree(char *path, int show_perms);
void progress (int percent, int max_width); void progress (int percent, int max_width);
void progress_simple(int percent); void progress_simple(int percent);
@@ -95,7 +100,7 @@ static inline int touch(const char *path)
{ {
if (mknod((path), S_IFREG|0644, 0)) { if (mknod((path), S_IFREG|0644, 0)) {
if (errno == EEXIST) if (errno == EEXIST)
return utimensat(0, path, NULL, 0); return utimensat(AT_FDCWD, path, NULL, 0);
return -1; return -1;
} }
return 0; return 0;
@@ -160,7 +165,7 @@ static inline int erase(const char *path)
#endif #endif
/* Does directory end with a slash? */ /* Does directory end with a slash? */
static inline int fisslashdir(char *dir) static inline int fisslashdir(const char *dir)
{ {
if (!dir) if (!dir)
return 0; return 0;
+8 -3
View File
@@ -29,13 +29,13 @@
* Returns: * Returns:
* POSIX OK(0) on success, otherwise -1 with @errno set. * POSIX OK(0) on success, otherwise -1 with @errno set.
*/ */
int mkpath(char *dir, mode_t mode) int mkpath(const char *dir, mode_t mode)
{ {
struct stat sb; struct stat sb;
if (!dir) { if (!dir) {
errno = EINVAL; errno = EINVAL;
return 1; return -1;
} }
if (!stat(dir, &sb)) if (!stat(dir, &sb))
@@ -50,13 +50,18 @@ int mkpath(char *dir, mode_t mode)
* makepath - Create all components of the specified directory. * makepath - Create all components of the specified directory.
* @dir: Directory to create. * @dir: Directory to create.
* *
* Comment:
* It is recommended to use mkpath() over this function since it has
* the @mode argument while this function instead default ot 0777,
* which in most cases is insecure.
*
* Returns: * Returns:
* POSIX OK (0) on success, otherwise -1 and errno set appropriately. * POSIX OK (0) on success, otherwise -1 and errno set appropriately.
* This function returns EINVAL on bad argument, or ENOMEM when it * This function returns EINVAL on bad argument, or ENOMEM when it
* fails allocating temporary memory. For other error codes see the * fails allocating temporary memory. For other error codes see the
* mkdir() syscall description. * mkdir() syscall description.
*/ */
int makepath(char *dir) int makepath(const char *dir)
{ {
return mkpath(dir, 0777); return mkpath(dir, 0777);
} }
View File
File renamed without changes.
View File
File renamed without changes.
View File
File renamed without changes.
View File
File renamed without changes.
File renamed without changes.
+54 -20
View File
@@ -16,6 +16,7 @@
*/ */
#include <errno.h> #include <errno.h>
#include <fcntl.h> /* AT_* macros */
#include <stdlib.h> /* NULL, free() */ #include <stdlib.h> /* NULL, free() */
#include <string.h> /* strlen() */ #include <string.h> /* strlen() */
#include <strings.h> /* rindex() */ #include <strings.h> /* rindex() */
@@ -26,16 +27,17 @@
#include "lite.h" #include "lite.h"
static int copy(char *src, char *dst); static int copy(char *src, char *dst, int opt);
static int mdir(char *buf, size_t buf_len, char *dir, char *name, mode_t mode); static int mdir(char *buf, size_t buf_len, char *dir, char *name, struct stat *st);
static int prune(char *dst, char **new_files, int new_num); static int prune(char *dst, char **new_files, int new_num);
static int set_mtime(char *fn, struct stat *st);
/** /**
* rsync - Synchronize contents and optionally remove non-existing backups * rsync - Synchronize contents and optionally remove non-existing backups
* @src: Source directory * @src: Source directory
* @dst: Destination directory * @dst: Destination directory
* @delete: Prune files from @dst that no longer exist in @src. * @opt: An option mask of %LITE_FOPT_RSYNC_DELETE, %LITE_FOPT_KEEP_MTIME
* @filter: Optional filtering function for source directory. * @filter: Optional filtering function for source directory.
* *
* This is a miniature implementation of the famous rsync for local use only. * This is a miniature implementation of the famous rsync for local use only.
@@ -44,19 +46,29 @@ static int prune(char *dst, char **new_files, int new_num);
* files removed from src since last backup are pruned from the destination * files removed from src since last backup are pruned from the destination
* (backup) directory. * (backup) directory.
* *
* The filter callback, @filter, if provided, is used to determine what files to * The @opt parameter to rsync() is an option mask for the most common
* include from the source directory when backing up. If a file is to be skipped * rsync(1) options. Previously this argument was called @delete and
* the callback should simply return zero. * to maintain backwards compatibility the value 1 is reserved:
*
* %LITE_FOPT_RSYNC_DELETE: Prune files from @dst that no longer exist in @src.
* %LITE_FOPT_KEEP_MTIME: Preserve modification time
*
* The filter callback, @filter, if provided, is used to determine what
* files to include from the source directory when backing up. If a
* file is to be skipped the callback should simply return zero.
* *
* Returns: * Returns:
* POSIX OK(0), or non-zero with @errno set on error. * POSIX OK(0), or non-zero with @errno set on error.
*/ */
int rsync(char *src, char *dst, int delete, int (*filter) (const char *file)) int rsync(char *src, char *dst, int opt, int (*filter)(const char *file))
{ {
char source[256]; char source[256];
char dest[256]; char dest[256];
int i = 0, num = 0, result = 0; int delete = (opt & LITE_FOPT_RSYNC_DELETE) != 0;
int keep_mtim = (opt & LITE_FOPT_KEEP_MTIME);
int i = 0, num = 0, result = 0, do_mtim = 0;
char **files; /* Array of file names. */ char **files; /* Array of file names. */
struct stat st;
if (!fisdir(dst)) if (!fisdir(dst))
makedir(dst, 0755); makedir(dst, 0755);
@@ -65,7 +77,7 @@ int rsync(char *src, char *dst, int delete, int (*filter) (const char *file))
if (!fexist(src)) if (!fexist(src))
return 1; return 1;
if (copy(src, dst)) if (copy(src, dst, keep_mtim))
result++; result++;
return errno; return errno;
@@ -80,9 +92,13 @@ int rsync(char *src, char *dst, int delete, int (*filter) (const char *file))
else else
ptr++; ptr++;
if (mdir(dest, sizeof(dest), dst, ptr, fmode(src))) if (stat(src, &st))
return 1;
if (mdir(dest, sizeof(dest), dst, ptr, &st))
return 1; return 1;
dst = dest; dst = dest;
do_mtim = keep_mtim;
} }
num = dir(src, "", filter, &files, 0); num = dir(src, "", filter, &files, 0);
@@ -91,21 +107,31 @@ int rsync(char *src, char *dst, int delete, int (*filter) (const char *file))
snprintf(source, sizeof(source), "%s%s%s", src, fisslashdir(src) ? "" : "/", files[i]); snprintf(source, sizeof(source), "%s%s%s", src, fisslashdir(src) ? "" : "/", files[i]);
if (fisdir(source)) { if (fisdir(source)) {
char dst2[256]; char dst2[256];
struct stat st;
strcat(source, "/"); strcat(source, "/");
if (mdir (dst2, sizeof(dst2), dst, files[i], fmode(source))) { if (stat(source, &st))
return 1;
if (mdir(dst2, sizeof(dst2), dst, files[i], &st)) {
result++; result++;
continue; continue;
} }
rsync(source, dst2, delete, filter); rsync(source, dst2, opt, filter);
if (keep_mtim)
set_mtime(dst2, &st);
continue; /* Next file/dir in @src to copy... */ continue; /* Next file/dir in @src to copy... */
} }
if (copy(source, dst)) if (copy(source, dst, keep_mtim))
result++; result++;
} }
if (do_mtim)
set_mtime(dest, &st);
/* We ignore any errors from the pruning, that phase albeit useful is only /* We ignore any errors from the pruning, that phase albeit useful is only
* cosmetic. --Jocke 2011-03-24 */ * cosmetic. --Jocke 2011-03-24 */
if (delete) if (delete)
@@ -120,11 +146,9 @@ int rsync(char *src, char *dst, int delete, int (*filter) (const char *file))
return result; return result;
} }
static int copy(char *src, char *dst) static int copy(char *src, char *dst, int opt)
{ {
errno = 0; copyfile(src, dst, 0, opt | LITE_FOPT_COPYFILE_SYM);
copyfile(src, dst, 0, 1);
if (errno) { if (errno) {
if (errno != EEXIST) if (errno != EEXIST)
return 1; return 1;
@@ -136,10 +160,10 @@ static int copy(char *src, char *dst)
} }
/* Creates dir/name @mode ... skipping / if dir already ends so. */ /* Creates dir/name @mode ... skipping / if dir already ends so. */
static int mdir(char *buf, size_t buf_len, char *dir, char *name, mode_t mode) static int mdir(char *buf, size_t buf_len, char *dir, char *name, struct stat *st)
{ {
snprintf(buf, buf_len, "%s%s%s/", dir, fisslashdir(dir) ? "" : "/", name); snprintf(buf, buf_len, "%s%s%s", dir, fisslashdir(dir) ? "" : "/", name);
if (mkdir(buf, mode)) { if (mkdir(buf, st->st_mode)) {
if (EEXIST != errno) if (EEXIST != errno)
return 1; return 1;
@@ -193,6 +217,16 @@ static int prune(char *dst, char **new_files, int new_num)
return result; return result;
} }
static int set_mtime(char *fn, struct stat *st)
{
struct timespec tv[2];
tv[0] = st->st_atim;
tv[1] = st->st_mtim;
return utimensat(AT_FDCWD, fn, tv, AT_SYMLINK_NOFOLLOW);
}
/** /**
* Local Variables: * Local Variables:
* indent-tabs-mode: t * indent-tabs-mode: t
View File
File renamed without changes.
View File
File renamed without changes.
View File
File renamed without changes.
+20 -15
View File
@@ -24,11 +24,31 @@
#ifndef LITE_STRING_H_ #ifndef LITE_STRING_H_
#define LITE_STRING_H_ #define LITE_STRING_H_
#include <stdint.h> /* uint8_t, uint16_t, uint32_t, INT32_MAX, etc. */
#include <string.h> #include <string.h>
#include <sys/param.h> /* MAX(), isset(), setbit(), TRUE, FALSE, et consortes. :-) */
#include "strdupa.h" #include "strdupa.h"
#include "strndupa.h" #include "strndupa.h"
#include "strnlen.h" #include "strnlen.h"
#ifndef min
#define min(a,b) \
({ \
__typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a < _b ? _a : _b; \
})
#endif
#ifndef max
#define max(a,b) \
({ \
__typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a > _b ? _a : _b; \
})
#endif
#ifndef strlcpy #ifndef strlcpy
size_t strlcpy (char *dst, const char *src, size_t siz); size_t strlcpy (char *dst, const char *src, size_t siz);
#endif #endif
@@ -82,19 +102,4 @@ static inline int string_case_compare(const char *a, const char *b)
return strlen (a) == strlen (b) && !strcasecmp (a, 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_ */ #endif /* LITE_STRING_H_ */
View File
File renamed without changes.
View File
File renamed without changes.
+9
View File
@@ -26,6 +26,15 @@
#define TOOSMALL 2 #define TOOSMALL 2
#define TOOLARGE 3 #define TOOLARGE 3
#ifndef LLONG_MAX
# define LLONG_MAX 0x7fffffffffffffffLL
#endif
#ifndef LLONG_MIN
# define LLONG_MIN (-0x7fffffffffffffffLL - 1)
#endif
long long long long
strtonum(const char *numstr, long long minval, long long maxval, strtonum(const char *numstr, long long minval, long long maxval,
const char **errstrp) const char **errstrp)
View File
File renamed without changes.
View File
File renamed without changes.
View File
File renamed without changes.
+1
View File
@@ -11,6 +11,7 @@ makepath
pidfile pidfile
progress progress
rsync rsync
str
tempfile tempfile
touch touch
tree tree
+2 -2
View File
@@ -11,11 +11,11 @@ TESTS += fsendfile
TESTS += lfile TESTS += lfile
TESTS += makepath TESTS += makepath
TESTS += pidfile TESTS += pidfile
TESTS += str
TESTS += touch TESTS += touch
TESTS += progress TESTS += progress
TESTS += rsync TESTS += rsync
TESTS += tempfile TESTS += tempfile
TESTS += tree
TESTS += which TESTS += which
check_PROGRAMS = $(TESTS) check_PROGRAMS = $(TESTS)
@@ -23,5 +23,5 @@ check_PROGRAMS = $(TESTS)
# Ignore warnings about unused result, in e.g. write() # Ignore warnings about unused result, in e.g. write()
CFLAGS += -Wno-unused-result CFLAGS += -Wno-unused-result
CPPFLAGS += -D_GNU_SOURCE CPPFLAGS += -D_GNU_SOURCE
LDADD = -L../ ../libite.la LDADD = -L../src/ ../src/libite.la
LDFLAGS += -static LDFLAGS += -static
+2 -2
View File
@@ -6,8 +6,8 @@
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include "../conio.h" #include "../src/conio.h"
#include "../lite.h" #include "../src/lite.h"
#define PRINT(args...) if (verbose) printf(args) #define PRINT(args...) if (verbose) printf(args)
+2 -2
View File
@@ -4,7 +4,7 @@
#include <stdlib.h> #include <stdlib.h>
#include "check.h" #include "check.h"
int checkpath(char *dir) int checkpath(const char *dir)
{ {
char tmp[256]; char tmp[256];
struct stat sb; struct stat sb;
@@ -20,7 +20,7 @@ int checkpath(char *dir)
return 1; return 1;
} }
int test_makepath(char *dir) int test_makepath(const char *dir)
{ {
int ret = makepath(dir); int ret = makepath(dir);
-1
View File
@@ -2,7 +2,6 @@
#include <unistd.h> /* usleep() */ #include <unistd.h> /* usleep() */
#include "check.h" #include "check.h"
#include "../conio.h"
#define MAX_WIDTH 80 #define MAX_WIDTH 80
#define msleep(msec) usleep(msec * 1000) #define msleep(msec) usleep(msec * 1000)
+4 -3
View File
@@ -53,9 +53,9 @@ static void check_tree(char *heading, char *dir)
if (verbose) { if (verbose) {
if (heading) if (heading)
puts(heading); puts(heading);
tree(dir, 1);
} }
// XXX: Fixme, add code to list tree, nftw() possibly
} }
int run_test(void) int run_test(void)
@@ -72,7 +72,8 @@ int run_test(void)
#endif #endif
setup_test(); setup_test();
result += rsync(BASE "src", DST, 0, NULL); sleep(1);
result += rsync(BASE "src", DST, LITE_FOPT_KEEP_MTIME, NULL);
check_tree("Only partial rsync of src <-- No slash!", BASE); check_tree("Only partial rsync of src <-- No slash!", BASE);
#if 0 #if 0
cleanup_test(); cleanup_test();
+19
View File
@@ -0,0 +1,19 @@
#include "../src/strlite.h"
int main(void)
{
int val;
val = atonum("42");
if (val != 42)
return 1;
if (!string_match("eth1", "eth1234"))
return 1;
if (string_compare("eth1", "eth1234"))
return 1;
return 0;
}
-19
View File
@@ -1,19 +0,0 @@
#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;
}
+8 -7
View File
@@ -11,16 +11,17 @@ int main(void)
int result = 0; int result = 0;
size_t i; size_t i;
struct tc test[] = { struct tc test[] = {
{ "ls", 1 }, { "ls", 1 },
{ "free", 1 }, { "free", 1 },
{ "modinfo", 1 }, { "modinfo", 1 },
{ "useradd", 1 }, { "useradd", 1 },
{ "/bin/which", 1 }, { "/usr/bin/which", 1 },
{ "/bin/ps aux", 1 }, { "/bin/ps aux", 1 },
{ "/etc/passwd", 0 }, { "/etc/passwd", 0 },
{ NULL, 0 } { NULL, 0 }
}; };
setenv("PATH", "/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin", 1);
for (i = 0; test[i].cmd; i++) { for (i = 0; test[i].cmd; i++) {
char *path; char *path;
-126
View File
@@ -1,126 +0,0 @@
/* Simple /bin/tree replacement
*
* Copyright (c) 2015 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 <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
static int all = 0;
static int filter(const struct dirent *entry)
{
/* Skip current dir ".", and prev dir "..", from list of files */
if ((1 == strlen(entry->d_name) && entry->d_name[0] == '.') ||
(2 == strlen(entry->d_name) && !strcmp(entry->d_name, "..")))
return 0;
if (!all && entry->d_name[0] == '.')
return 0;
return 1;
}
static void get_perms(struct stat *st, char *buf, size_t len)
{
mode_t m = st->st_mode;
snprintf(buf, len, "[%c%c%c%c%c%c%c%c%c%c] ",
S_ISCHR(m) ? 'c' : S_ISBLK(m) ? 'b' : S_ISFIFO(m) ? 'p' : S_ISLNK(m) ? 'l' : S_ISSOCK(m) ? 's' : '-',
(m & S_IRUSR) ? 'r' : '-',
(m & S_IWUSR) ? 'w' : '-',
(m & S_ISUID ) ? 's' : (m & S_IXUSR) ? 'x' : '-',
(m & S_IRGRP) ? 'r' : '-',
(m & S_IWGRP) ? 'w' : '-',
(m & S_ISGID) ? 's' : (m & S_IXGRP) ? 'x' : '-',
(m & S_IROTH) ? 'r' : '-',
(m & S_IWOTH) ? 'w' : '-',
(m & S_IXOTH) ? 'x' : '-'
);
}
static int descend(char *path, int show_perms, char *pfx)
{
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) {
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];
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]);
}
free(namelist);
}
return result;
}
int tree(char *path, int show_perms)
{
printf("[%s]\n", path);
return descend(path, show_perms, "");
}
/**
* Local Variables:
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/