Compare commits

...
46 Commits
Author SHA1 Message Date
Joachim Nilsson 12ed342d55 Bump version for v1.2.0 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-11-23 00:32:56 +01:00
Joachim Nilsson 23badc990d lfile: Improve unittest/example with /etc/group + passwd
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-10-26 00:50:18 +01:00
Joachim Nilsson ca53e097c3 lfile: Initialize strtok_r() save pointer
Must initialize the save pointer in the parser context, otherwise
strtok_r() will fail on statically built embedded targets.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-10-26 00:16:36 +01:00
Joachim Nilsson a7b5c240c1 Add UNIX lfile_t parser API to lite.h
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-10-25 23:25:17 +01:00
Joachim Nilsson c4eb5cb124 Add simple parser for UNIX configuration files.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-10-25 22:50:10 +01:00
Joachim Nilsson db08b20f23 Make sure we don't inherit LDFLAGS from environment.
To pass custom LDFLAGS to libite, use EXTRA_LDFLAGS.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-10-22 18:35:35 +02:00
Joachim Nilsson 8779f54125 Do not allow VERSION to be overloaded by build system.
When integrating libite as a component in another piece of software,
that build system may set VERSION as an environment variable.  We do
not want that version to be set as the version of libite.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-10-03 09:13:37 +02:00
Joachim Nilsson bd9a618ea3 Bump version for v1.1.1 patch release.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-09-27 00:59:54 +02:00
Joachim Nilsson 3f89fafe24 Fix macro definitions for compat APIs
Seems cpp is a bit uptight about spaces.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-09-27 00:56:20 +02:00
Joachim Nilsson ebec48d671 Silence annoying warnings from GNU ar
In (very) modern versions of binutils, for instance v2.25.1 shipped in
Ubuntu 15.10, ar complains about the VERY common `crus` argument.  This
patch silences this noise:

    $ make -j5
      ARCHIVE libite.a
    ar: `u' modifier ignored since `D' is the default (see `U')

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-09-27 00:55:26 +02:00
Joachim Nilsson 4d6c32f81a Bump version to v1.1.0 and drop default optimization.
User of library will likely want to have better control over the default
optimization level.  Either way, defaulting to -Os is a lot more "risky"
than, say -O2.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-09-16 17:25:43 +02:00
Joachim Nilsson 25c725c240 Bump SONAME to libite.so.2 so for upcoming Finit v2.0
We need to lock down the ABI and do a new release on behalf of
Finit.  Finit will have support for using an externally built
libite and libuev, so Finit must lock down to a known ABI.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-09-16 17:23:49 +02:00
Joachim Nilsson 039a92b292 progress.c: Merge in latest changes from troglobit/toolbox@d845e67
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-24 23:52:26 +02:00
Joachim Nilsson 5ae5bfb767 Bump version to indicate new feature status, v1.1.0-beta1
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-23 19:37:08 +02:00
Joachim Nilsson a00e765789 Update README with info on progress() and tree()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-23 19:36:21 +02:00
Joachim Nilsson aff5812c46 Minor whitespace fixes, use Linux KNF
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-23 13:15:18 +02:00
Joachim Nilsson 3809b109c6 Add autotest for progress()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-23 13:11:20 +02:00
Joachim Nilsson 1909dd475c progress(): Very simple ASCII progress bar from troglobit/toolbox@f98c5d0
This patch adds a very simple progress bar I wrote once.  It's revision
f98c5d0 from https://github.com/troglobit/toolbox

Also included in this patch is conio.h, a neat little set of macros for
manipulating your terminal using ANSI escape seequences.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-23 13:07:03 +02:00
Joachim Nilsson a157fe4162 tree: Minor cleanup, also does not need sudo for tests.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-23 05:23:54 +02:00
Joachim Nilsson 42b6a03317 rsync.test: Use homegrown tree, instead of out-of-tree tree ...
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-23 05:19:11 +02:00
Joachim Nilsson 1f1e88a640 New function: tree(), simple /bin/tree replacement.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-23 05:12:38 +02:00
Joachim Nilsson bb67fb749d rsync.c: Refactor unit tests to work on Travis as well.
Travis does not have `/bin/tree` installed, and since we do not
output intermediate results from `make test`, there is no need
to call `/bin/tree` unless `-v` is supplied to the test.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-23 02:33:33 +02:00
Joachim Nilsson 3e337c7078 rules.mk: When V=1 is used, add -v to autotests.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-23 02:32:29 +02:00
Joachim Nilsson 407e954f02 tempfile(): Handle kernels older than 3.11 by wrapping tmpfile()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-23 02:17:45 +02:00
Joachim Nilsson 8978cb9bff Try sudo: true for sake of tests, skip Docker for now.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-23 01:39:08 +02:00
Joachim Nilsson 9c90ec56a6 Attempt to activate autotests in Travis-CI.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-23 01:33:24 +02:00
Joachim Nilsson 44e787c966 Add generic support for running tests as root.
By setting `ASROOT=1` in a unit test makefile a test will now run as
root, using `sudo -n`.

This patch allows us to simplify the pidfilefn() test.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-23 01:30:29 +02:00
Joachim Nilsson e8ff38ad6a Add autotest for fisdir()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-22 23:26:41 +02:00
Joachim Nilsson 1138822d19 Add autotest for fexist()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-22 23:22:38 +02:00
Joachim Nilsson de8f2b087c Add autotest for tempfile()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-22 23:08:22 +02:00
Joachim Nilsson 87d6fe822c Make sure to start the makepath() tests clean.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-22 23:07:56 +02:00
Joachim Nilsson 57c49bfe0c Add autotest for mkpath() and makepath()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-22 23:01:15 +02:00
Joachim Nilsson b59249714b Add autotest for fsendfile()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-22 22:49:48 +02:00
Joachim Nilsson 36da3aa35e Add autotest for dir
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-22 22:46:42 +02:00
Joachim Nilsson ab2b0f00fa Add autotest for pidfilefn et al.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-22 22:41:34 +02:00
Joachim Nilsson bd69aad13a Add autotest for copyfile et al.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-22 22:22:14 +02:00
Joachim Nilsson ebe2ad4a4c Add autotest for chomp
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-22 22:08:25 +02:00
Joachim Nilsson 2ea2357b62 Lay foundation for unit test build framework.
GNU Make double colon rules, rule ;-)

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-22 21:59:52 +02:00
Joachim Nilsson b7a8042c87 Add Travis-CI status icon
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-22 16:11:31 +02:00
Joachim Nilsson 7d1423b5b1 Add dockerized Travis-CI autobuilder support.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-22 16:09:54 +02:00
Joachim Nilsson 117ec58a90 Add some very useful helper macros: NELEMS() and bitops.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-21 09:42:43 +02:00
Joachim Nilsson a4cbc7a10e pidfile.c: Upgrade to OpenBSD r1.11, asprintf() fixes.
Do not assume that asprintf() clears the pointer on failure, which
   is non-portable.  Also add missing asprintf() return value checks.
   Signed-off-by: millert@
   Signed-off-by: deraadt@ guenther@ doug@

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-07-22 11:53:44 +02:00
Joachim Nilsson 3eb1fbb31d lite.h: Minor coding style cleanup.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-07-22 11:52:41 +02:00
Joachim Nilsson f5355ecf7b lite.h: Convert from error.h to the more BSD friendly err.h
OpenBSD, and possibly the other BSD's, do not have error.h so we replace
it with err.h, which exists almost everywhere.

This means the macros in lite.h that used error() now instead use
warn(),  with the same semantics as before.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-07-18 15:36:06 +02:00
Joachim Nilsson 61b1b5b457 Add support for 'make distdir' used by GNU configure and build.
This patch adds support for being called with "make distdir" from a GNU
configure and build based project.  This was a requirement to get the
Inadyn v1.99.14 release out.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-07-14 17:26:32 +02:00
Joachim Nilsson 83f83466b5 Fix indentation of description to some API's.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-07-12 13:13:21 +02:00
33 changed files with 1071 additions and 152 deletions

No files matched your search

+11
View File
@@ -0,0 +1,11 @@
# Travis CI integration -- https://travis-ci.org/troglobit/libuev
# 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
script:
- make
- make test
+24 -42
View File
@@ -19,67 +19,51 @@
# 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.
.PHONY: all install clean
# Figure out root of library, unless used as submodule
ROOTDIR ?= $(shell pwd)
.PHONY: install test
#VERSION = $(shell git tag -l | tail -1)
VERSION ?= 1.0.0
VERSION = 1.2.0
NAME = libite
PKG = $(NAME)-$(VERSION)
ARCHIVE = $(PKG).tar.xz
CC ?= $(CROSS)gcc
AR ?= $(CROSS)ar
STRIP ?= $(CROSS)strip
INSTALL := install --backup=off
STRIPINST := $(INSTALL) -s --strip-program=$(CROSS)strip -m 0755
CFLAGS += -fPIC
CFLAGS += -Os
CPPFLAGS += -D_GNU_SOURCE
CPPFLAGS += -W -Wall
ARFLAGS = crus
# Default to silent build, use V=1 to get verbose mode.
ifeq ($V,1)
Q =
PRINT = @true
MAKEFLAGS =
else
Q = @
PRINT = @printf
MAKEFLAGS = --no-print-directory --silent
endif
LDFLAGS = $(EXTRA_LDFLAGS)
DISTFILES = README LICENSE
HEADERS = lite.h
OBJS := chomp.o copyfile.o dir.o fexist.o fisdir.o fmode.o fsendfile.o
OBJS += ifconfig.o makepath.o pidfile.o pidfilefn.o rsync.o
OBJS += strlcpy.o strlcat.o strtonum.o tempfile.o
OBJS += ifconfig.o lfile.o makepath.o pidfile.o pidfilefn.o progress.o
OBJS += rsync.o strlcpy.o strlcat.o strtonum.o tempfile.o tree.o
DEPS := $(OBJS:.o=.d)
JUNK = *~ *.bak *.map .*.d *.d DEADJOE semantic.cache *.gdb *.elf core core.*
VER = 1
VER = 2
LIBNAME = $(NAME)
SOLIB = $(LIBNAME).so.$(VER)
SYMLIB = $(LIBNAME).so
STATICLIB = $(LIBNAME).a
TARGET = $(STATICLIB) $(SOLIB)
# Default install paths
prefix ?= /usr/local
libdir ?= $(prefix)/lib
datadir ?= $(prefix)/share/doc/$(LIBNAME)
incdir ?= $(prefix)/include
# This magic trick looks like a comment, but works on BSD PMake
#include <rules.mk>
include rules.mk
# Build rules
all: $(TARGET)
test: clean
$(MAKE) -f chomp.mk
$(MAKE) -f copyfile.mk
$(MAKE) -f dir.mk
$(MAKE) -f fexist.mk
$(MAKE) -f fisdir.mk
$(MAKE) -f fsendfile.mk
$(MAKE) -f lfile.mk
$(MAKE) -f makepath.mk
$(MAKE) -f pidfilefn.mk
$(MAKE) -f progress.mk
$(MAKE) -f rsync.mk
$(MAKE) -f tempfile.mk
$(MAKE) -f tree.mk
$(OBJS): Makefile
@@ -89,7 +73,7 @@ $(SOLIB): Makefile $(OBJS)
$(STATICLIB): Makefile $(OBJS)
$(Q)$(PRINT) " ARCHIVE $@\n"
$(Q)$(AR) $(ARFLAGS) $@ $(OBJS)
$(Q)$(AR) $(ARFLAGS) $@ $(OBJS) 2>/dev/null
install-exec: all
$(PRINT) " INSTALL $(DESTDIR)$(libdir)/$(SOLIB)\n"
@@ -130,11 +114,9 @@ strip: $(TARGET)
check: clean
$(Q)scan-build $(MAKE) all
clean:
-$(Q)$(RM) $(OBJS) $(DEPS) $(TARGET) $(SOLIB) $(STATICLIB)
distclean:
-$(Q)$(RM) $(JUNK) unittest *.o *.a *.so* *.unittest
# When called from GNU configure and build system
distdir:
@git archive --format=tar HEAD | (cd $(distdir); tar xf -)
dist:
$(Q)echo "Building .xz tarball of $(PKG) in parent dir..."
+72 -6
View File
@@ -1,5 +1,6 @@
-lite | Frog DNA, basically
===========================
[![Travis Status][]][Travis]
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
@@ -31,11 +32,11 @@ Helper Macros
- `blkdev(dev)`
Create block device
Create block device
- `chardev(dev)`
Create character device
Create character device
- `erase(path)`
@@ -55,11 +56,36 @@ Create character device
- `S_ISEXEC(mode_t m)`
Mysteriously missing from GLIBC
Mysteriously missing from GLIBC
- `ISCLR(word,bit)`
Is bit in (integer) word cleared?
- `ISSET(word,bit)`
Is bit in (integer) word set?
- `ISOTHER(word,bit)`
Is any other bits, except bit, in (integer) word set?
- `SETBIT(word,bit)`
Set bit in (integer) word.
- `CLRBIT(word,bit)`
Clear bit in (integer) word.
- `NELEMS(array)`
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))`
Shorter and more readable version of `var __attribute__ ((unused))`
Generic Functions
@@ -107,6 +133,29 @@ Generic Functions
Basic ifconfig like operations on an interface. Only supports IPv4
adresses. Note that mask is not CIDR notation.
- `lfopen(file, sep)`, `lfclose(lf)`
API for parsing UNIX style configuration files like `/etc/protocols`
and `/etc/services`.
- `lftok(lf)`
Read tokens, delimeted by `sep`, from file opened with `lfopen()`.
- `lfgetkey(lf, key)`
Find `key` in file opened with `lfopen()`, return value/argument.
- `lfgetint(lf, key)`
Wrapper for `lfgetkey()`, returns positive integer value to `key`,
or `-1` if `key` is not found.
- `fgetint(file, sep, key)`
Wrapper for `lfopen()`, `lfgetint()`, and `lfclose()`. Useful for
when only reading a single `key` from a file.
- `makepath(dir)`
Create all components of the specified directory.
@@ -147,6 +196,13 @@ Generic Functions
Send signal to PID found in pid file created by `pidfile()`.
- `progress(percent, max_width)`
Simple ASCII progress bar with a spinner. Start it with `percent=0`
and set the `max_width=chars` to indicate width of the progress bar.
Called multiple times with the same percentage value cause spinner to
spin.
- `rsync(src, dst, delete, *filter())`
Very simple `rsync()` to copy files files and directories
@@ -156,7 +212,16 @@ Generic Functions
Secure replacement for `tmpfile()`. Creates an invisible temporary
file in `/tmp` that is removed when the returned `FILE` pointer is
closed. **Note:** Requires Linux v3.11, or later.
closed.
**Note:** Requires Linux v3.11, or later, will fall back to the old
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.
OpenBSD Functions
@@ -200,7 +265,8 @@ TODO
[MIT]: https://en.wikipedia.org/wiki/MIT_License
[ISC]: https://en.wikipedia.org/wiki/ISC_license
[BSD]: https://en.wikipedia.org/wiki/BSD_licenses
[Travis]: https://travis-ci.org/troglobit/libite
[Travis Status]: https://travis-ci.org/troglobit/libite.png?branch=master
<!--
-- Local Variables:
+2 -2
View File
@@ -50,13 +50,13 @@ char *chomp(char *str)
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("'%s'\n", chomp(t[i])); return 0;
for (i = 0; t[i][0]; i++) printf("[%02d]: '%s'\n", i, chomp(t[i])); return 0;
}
#endif
/**
* Local Variables:
* compile-command: "gcc -DUNITTEST -o chompy chomp.c && ./chompy"
* compile-command: "make V=1 -f chomp.mk"
* version-control: t
* indent-tabs-mode: t
* c-file-style: "linux"
+4
View File
@@ -0,0 +1,4 @@
OBJS =
TARGET = chomp.test clean
include rules.mk
+82
View File
@@ -0,0 +1,82 @@
/* A conio.h like implementation for VTANSI displays.
*
* Copyright (c) 2009-2013 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 CONIO_H_
#define CONIO_H_
#include <stdio.h>
/* Attributes */
#define RESETATTR 0
#define BRIGHT 1
#define DIM 2
#define UNDERSCORE 4
#define BLINK 5 /* May not work on all displays. */
#define REVERSE 7
#define HIDDEN 8
/* Colors for text and background */
#define BLACK 0x0
#define RED 0x1
#define GREEN 0x2
#define BROWN 0x3
#define BLUE 0x4
#define MAGENTA 0x5
#define CYAN 0x6
#define LIGHTGREY 0x7
#define DARKGREY 0x10
#define LIGHTRED 0x11
#define LIGHTGREEN 0x12
#define YELLOW 0x13
#define LIGHTBLUE 0x14
#define LIGHTMAGENTA 0x15
#define LIGHTCYAN 0x16
#define WHITE 0x17
/* Esc[2JEsc[1;1H - Clear screen and move cursor to 1,1 (upper left) pos. */
#define clrscr() fputs ("\e[2J\e[1;1H", stdout)
/* Esc[K - Erases from the current cursor position to the end of the current line. */
#define clreol() fputs ("\e[K", stdout)
/* Esc[2K - Erases the entire current line. */
#define delline() fputs ("\e[2K", stdout)
/* Esc[Line;ColumnH - Moves the cursor to the specified position (coordinates) */
#define gotoxy(x,y) printf("\e[%d;%dH", y, x)
/* Esc[?25l (lower case L) - Hide Cursor */
#define hidecursor() fputs ("\e[?25l", stdout)
/* Esc[?25h (lower case H) - Show Cursor */
#define showcursor() fputs ("\e[?25h", stdout)
/* Esc[Value;...;Valuem - Set Graphics Mode */
#define __set_gm(attr,color,val) \
if (!color) \
printf("\e[%dm", attr); \
else \
printf("\e[%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)
#endif /* CONIO_H_ */
/**
* Local Variables:
* version-control: t
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/
+16 -11
View File
@@ -261,6 +261,8 @@ int fcopyfile(FILE *src, FILE *dst)
}
#ifdef UNITTEST
#include <err.h>
int main(void)
{
int i = 0;
@@ -272,14 +274,15 @@ int main(void)
};
FILE *src, *dst;
fprintf(stderr, "\n=>Start testing copy_filep()\n");
printf("=>Start testing fcopyfile()\n");
while (files[i]) {
fprintf(stderr, "fcopyfile(%s, %s)\t", files[i],
files[i + 1]);
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))
perror("Failed");
if (fcopyfile(src, dst)) {
if (!fisdir(files[i + 1]))
err(1, "Failed fcopyfile(%s, %s)", files[i], files[i + 1]);
}
if (src)
fclose(src);
@@ -287,21 +290,23 @@ int main(void)
fclose(dst);
if (fexist(files[i + 2]))
fprintf(stderr, "OK => %s\n", files[i + 2]);
printf("OK => %s", files[i + 2]);
printf("\n");
erase(files[i + 2]);
i += 3;
}
printf("\n\n=>Start testing copyfile()\n");
printf("\n=>Start testing copyfile()\n");
i = 0;
while (files[i]) {
fprintf(stderr, "copyfile(%s, %s)\t", files[i], files[i + 1]);
printf("copyfile(%s, %s)\t", files[i], files[i + 1]);
if (!copyfile(files[i], files[i + 1], 0, 0))
perror("Failed");
err(1, "Failed copyfile(%s, %s)", files[i], files[i + 1]);
if (fexist(files[i + 2]))
fprintf(stderr, "OK => %s\n", files[i + 2]);
printf("OK => %s", files[i + 2]);
printf("\n");
erase(files[i + 2]);
i += 3;
@@ -313,7 +318,7 @@ int main(void)
/**
* Local Variables:
* compile-command: "gcc -g -o coppy -DUNITTEST copyfile.c fisdir.c fexist.c fmode.c && ./coppy"
* compile-command: "make V=1 -f copyfile.mk"
* version-control: t
* indent-tabs-mode: t
* c-file-style: "linux"
+4
View File
@@ -0,0 +1,4 @@
OBJS = fisdir.o fexist.o fmode.o
TARGET = $(OBJS) copyfile.test clean
include rules.mk
+4 -4
View File
@@ -123,7 +123,7 @@ int dir(const char *dir, const char *type, int (*filter) (const char *file), cha
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "otn/c.h"
#include "lite.h"
#define DIR_TYPE_IMAGE ".img"
#define DIR_TYPE_SYSLOG ""
@@ -138,7 +138,7 @@ int simulate_files(int creat)
"rr109.img", "rx100.img", "rx107.img", "rm957.img", "messages"
};
for (i = 0; i < ARRAY_ELEMENTS(files); i++) {
for (i = 0; i < NELEMS(files); i++) {
if (creat)
touch(files[i]);
else
@@ -217,11 +217,11 @@ int main(int argc, char *argv[])
return 0;
}
#endif /* UNITTEST */
#endif /* UNITTEST */
/**
* Local Variables:
* compile-command: "gcc -g -DUNITTEST -o unittest dir.c"
* compile-command: "make V=1 -f dir.mk"
* version-control: t
* indent-tabs-mode: t
* c-file-style: "linux"
+4
View File
@@ -0,0 +1,4 @@
OBJS =
TARGET = dir.test clean
include rules.mk
+28
View File
@@ -44,8 +44,36 @@ 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"
+4
View File
@@ -0,0 +1,4 @@
OBJS =
TARGET = fexist.test clean
include rules.mk
+29
View File
@@ -42,8 +42,37 @@ 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"
+4
View File
@@ -0,0 +1,4 @@
OBJS =
TARGET = fisdir.test clean
include rules.mk
+5 -4
View File
@@ -77,6 +77,7 @@ size_t fsendfile(FILE *src, FILE *dst, size_t len)
}
#ifdef UNITTEST
#include <err.h>
#include <unistd.h>
int main(void)
@@ -93,12 +94,12 @@ int main(void)
while (files[i]) {
src = fopen(files[i], "r");
dst = fopen(files[i + 1], "w");
fprintf(stderr, "fsendfile(%s, %s, 512)\t", files[i], files[i + 1]);
printf("fsendfile(%s, %s, 512)\t", files[i], files[i + 1]);
if (-1 == fsendfile(src, dst, 512))
perror("Failed");
err(1, "Failed fsendfile(%s, %s)", files[i], files[i + 1]);
if (!access(files[i + 1], F_OK))
fprintf(stderr, "OK => %s\n", files[i + 1]);
printf("OK => %s\n", files[i + 1]);
remove(files[i + 1]);
i += 2;
@@ -110,7 +111,7 @@ int main(void)
/**
* Local Variables:
* compile-command: "gcc -g -o sendy -DUNITTEST fsendfile.c && ./sendy"
* compile-command: "make V=1 -f fsendfile.mk"
* version-control: t
* indent-tabs-mode: t
* c-file-style: "linux"
+4
View File
@@ -0,0 +1,4 @@
OBJS =
TARGET = fsendfile.test clean
include rules.mk
+235
View File
@@ -0,0 +1,235 @@
/* Parse UNIX /etc configuration files like /etc/protocols and /etc/services
*
* 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 <stdio.h> /* FILE */
#include <stdlib.h> /* atoi() */
#include <string.h> /* strlen(), strncmp(), strtok_r() */
#include <sys/param.h> /* MAX() */
typedef struct lfile {
FILE *fp;
char buf[256];
char *sep, *save;
} lfile_t;
/**
* lfopen - Open file and return parsing context
* @file: File to parse
* @sep: Separator(s) to use in lftok()
*
* Returns:
* Pointer to a &lftile_t parser context, or %NULL on error.
*/
lfile_t *lfopen(char *file, char *sep)
{
lfile_t *lf;
if (!file || !sep) {
errno = EINVAL;
return NULL;
}
/* Use calloc for clearing buf on behalf of lftok() */
lf = calloc(sizeof(*lf), sizeof(char));
if (lf) {
lf->fp = fopen(file, "r");
lf->sep = sep;
lf->save = lf->buf;
if (!lf->fp) {
free(lf);
return NULL;
}
}
return lf;
}
/**
* lfclose - Close a parser context
* @lf: Pointer to &lfile_t context from lfopen()
*/
void lfclose(lfile_t *lf)
{
if (!lf)
return;
if (lf->fp)
fclose(lf->fp);
free(lf);
}
/**
* lftok - Get next token in file
* @lf: Pointer to &lfile_t context from lfopen()
*
* Returns:
* Next token, read from file previously opened with lfopen(),
* or %NULL if EOF.
*/
char *lftok(lfile_t *lf)
{
char *token;
if (!lf || !lf->fp || !lf->sep) {
errno = EINVAL;
return NULL;
}
token = strtok_r(NULL, lf->sep, &lf->save);
if (!token) {
while (fgets(lf->buf, sizeof(lf->buf), lf->fp)) {
if (lf->buf[0] == '#')
continue;
token = strtok_r(lf->buf, lf->sep, &lf->save);
if (!token)
continue;
return token;
}
errno = ENOENT;
return NULL;
}
return token;
}
/**
* lfgetkey - Find key in file
* @lf: Pointer to &lfile_t context from lfopen()
* @key: Key to look for
*
* Locate @key from the current position in the file parser context
* returned from lfopen(). Please note, the search for @key does not
* start from the beginning of the file, it searches from the current
* position. To restart search from the beginning use rewind() on the
* lf->fp.
*
* Returns:
* The value to @key, or %NULL if not found.
*/
char *lfgetkey(lfile_t *lf, char *key)
{
char *token;
while ((token = lftok(lf))) {
if (token[0] == '#')
continue;
if (!strncmp(token, key, MAX(strlen(token), strlen(key))))
return lftok(lf);
}
return NULL;
}
/**
* lfgetint - Same as lfgetkey() but returns an integer
* @lf: Pointer to &lfile_t context from lfopen()
* @key: Key to look for
*
* This function is the same as lfgetkey() but returns the positive
* integer value for the matching @key, if found.
*
* Returns:
* The positive integer value for @key, or -1 if not found.
*/
int lfgetint(lfile_t *lf, char *key)
{
char *token = lfgetkey(lf, key);
if (token)
return atoi(token);
return -1;
}
/**
* fgetint - Find the integer value for key in a file
* @file: File to search for @key
* @sep: Separator for tokens in @file
* @key: Key to look for in @file
*
* This is a convenience wrapper for lfopen(), lfgetint(), and
* lfclose().
*
* Returns:
* The positive integer value for @key, or -1 if not found.
*/
int fgetint(char *file, char *sep, char *key)
{
int val = -1;
lfile_t *lf;
lf = lfopen(file, sep);
if (lf) {
val = lfgetint(lf, key);
lfclose(lf);
}
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
@@ -0,0 +1,4 @@
OBJS =
TARGET = lfile.test clean
include rules.mk
+50 -14
View File
@@ -25,7 +25,7 @@
#ifndef FINIT_LITE_H_
#define FINIT_LITE_H_
#include <error.h>
#include <err.h>
#include <stdio.h>
#include <stdint.h> /* uint8_t, uint16_t, uint32_t, INT32_MAX, etc. */
#include <string.h>
@@ -34,6 +34,8 @@
#include <sys/param.h> /* MAX(), isset(), setbit(), TRUE, FALSE, et consortes. :-) */
#include <unistd.h>
typedef struct lfile lfile_t;
char *chomp (char *str);
int fexist (char *file);
@@ -48,6 +50,13 @@ size_t fsendfile (FILE *src, FILE *dst, size_t len);
int ifconfig (char *ifname, char *addr, char *mask, int up);
lfile_t*lfopen (char *file, char *sep);
void lfclose (lfile_t *lf);
char *lftok (lfile_t *lf);
char *lfgetkey (lfile_t *lf, char *key);
int lfgetint (lfile_t *lf, char *key);
int fgetint (char *file, char *sep, char *key);
int mkpath (char *dir, mode_t mode);
int makepath (char *dir);
@@ -69,17 +78,19 @@ size_t strlcat (char *dst, const char *src, size_t siz);
long long strtonum (const char *numstr, long long minval, long long maxval, const char **errstrp);
#endif
int tree(char *path, int show_perms);
#ifndef touch
# define touch(x) do { if (mknod((x), S_IFREG|0644, 0) && errno != EEXIST) error(0, errno, "Failed creating %s", x); } while (0)
# define touch(x) do { if (mknod((x), S_IFREG|0644, 0) && errno != EEXIST) warn("Failed creating %s", x); } while (0)
#endif
#ifndef makedir
# define makedir(x, p) do { if (mkdir(x, p) && errno != EEXIST) error(0, errno, "Failed creating directory %s", x); } while (0)
# define makedir(x, p) do { if (mkdir(x, p) && errno != EEXIST) warn("Failed creating directory %s", x); } while (0)
#endif
#ifndef makefifo
# define makefifo(x, p) do { if (mkfifo(x, p) && errno != EEXIST) error(0, errno, "Failed creating FIFO %s", x); } while (0)
# define makefifo(x, p) do { if (mkfifo(x, p) && errno != EEXIST) warn("Failed creating FIFO %s", x); } while (0)
#endif
#ifndef erase
# define erase(x) do { if (remove(x) && errno != ENOENT) error(0, errno, "Failed removing %s", x); } while (0)
# define erase(x) do { if (remove(x) && errno != ENOENT) warn("Failed removing %s", x); } while (0)
#endif
#ifndef chardev
# define chardev(x,m,maj,min) mknod((x), S_IFCHR|(m), makedev((maj),(min)))
@@ -87,9 +98,34 @@ long long strtonum (const char *numstr, long long minval, long long maxval, cons
#ifndef blkdev
# define blkdev(x,m,maj,min) mknod((x), S_IFBLK|(m), makedev((maj),(min)))
#endif
#ifndef S_ISEXEC
# define S_ISEXEC(m) (((m) & S_IXUSR) == S_IXUSR)
#endif
/* Unline isset(), setbit() et al, these work with integers/shorts/longwords/etc. */
#ifndef ISCLR
#define ISCLR(word,bit) ((word & (1 << (bit)) ? 0 : 1))
#endif
#ifndef ISSET
#define ISSET(word,bit) ((word & (1 << (bit)) ? 1 : 0))
#endif
#ifndef ISOTHER
#define ISOTHER(word,bit) ((word & ~(1 << (bit)) ? 1 : 0)) /* Is any other bit set? */
#endif
#ifndef SETBIT
#define SETBIT(word,bit) (word |= (1 << (bit)))
#endif
#ifndef CLRBIT
#define CLRBIT(word,bit) (word &= ~(1 << (bit)))
#endif
/* From The Practice of Programming, by Kernighan and Pike */
#ifndef NELEMS
#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
@@ -118,23 +154,23 @@ static inline int atonum(const char *str)
}
/* Validate string, non NULL and not zero length */
static inline int string_valid (const char *s)
static inline int string_valid(const char *s)
{
return s && strlen (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)
static inline int string_match(const char *a, const char *b)
{
size_t min = MIN(strlen (a), strlen (b));
size_t min = MIN(strlen(a), strlen(b));
return !strncasecmp (a, b, min);
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);
return strlen(a) == strlen(b) && !strcmp(a, b);
}
/* Strict comparison, like sys_string_compare(), but case insensitive,
@@ -146,9 +182,9 @@ static inline int string_case_compare (const char *a, const char *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 /* FINIT_LITE_H_ */
+9 -5
View File
@@ -55,7 +55,7 @@ int makepath(char *dir)
/********************************* UNIT TESTS ************************************/
#ifdef UNITTEST
#include <stdio.h>
#include "lite.h"
int checkpath(char *dir)
{
@@ -63,7 +63,8 @@ int checkpath(char *dir)
struct stat sb;
snprintf(tmp, sizeof(tmp), "ls -ld %s", dir);
system(tmp);
if (system(tmp))
perror("system");
if (!stat(dir, &sb) && S_ISDIR(sb.st_mode))
return 0;
@@ -98,11 +99,14 @@ int main(void)
NULL
};
fprintf(stderr, "Testing makepath() ...\n");
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]);
fprintf(stderr, "\nCleaning up ...\n");
printf("\nCleaning up ...\n");
for (i = 0; list[i]; i++)
rmdir(list[i]);
@@ -112,7 +116,7 @@ int main(void)
/**
* Local Variables:
* compile-command: "gcc -g -o unittest -D_GNU_SOURCE -DUNITTEST makepath.c && ./unittest"
* compile-command: "make V=1 -f makepath.mk"
* version-control: t
* indent-tabs-mode: t
* c-file-style: "linux"
+4
View File
@@ -0,0 +1,4 @@
OBJS =
TARGET = makepath.test clean
include rules.mk
+3 -4
View File
@@ -1,4 +1,4 @@
/* $OpenBSD: pidfile.c,v 1.10 2014/06/30 00:26:22 deraadt Exp $ */
/* $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 $ */
/*-
@@ -47,7 +47,7 @@ extern char *__progname;
int
pidfile(const char *basename)
{
int save_errno, result;
int save_errno;
pid_t pid;
FILE *f;
@@ -60,8 +60,7 @@ pidfile(const char *basename)
}
/* _PATH_VARRUN includes trailing / */
result = asprintf(&pidfile_path, "%s%s.pid", _PATH_VARRUN, basename);
if (result == -1 || pidfile_path == NULL)
if (asprintf(&pidfile_path, "%s%s.pid", _PATH_VARRUN, basename) == -1)
return (-1);
if ((f = fopen(pidfile_path, "w")) == NULL) {
+21 -14
View File
@@ -119,38 +119,45 @@ int pidfile_signal(const char *pidfile, int signal)
/********************************* UNIT TESTS ************************************/
#ifdef UTEST_PIDFN
#define PIDFILE "/var/run/unittest.pid"
#ifdef UNITTEST
#include <paths.h>
#include "lite.h"
extern char *__progname;
static char PIDFILE[42];
static void sigterm_handler(int signo)
{
fprintf(stderr, "Exiting ...\n");
printf("Exiting ...\n");
}
static void sigalrm_handler(int signo)
{
fprintf(stderr, "Testing pidfile() ...\n");
printf("Testing pidfile() ...\n");
pidfile(NULL);
if (!fexist(PIDFILE))
err(1, "pidfile() failed creating %s", PIDFILE);
}
int main(void)
{
snprintf(PIDFILE, sizeof(PIDFILE), "%s%s.pid", _PATH_VARRUN, __progname);
signal(SIGTERM, sigterm_handler);
signal(SIGALRM, sigalrm_handler);
alarm(3);
alarm(1);
fprintf(stderr, "Testing pidfile_poll() ...\n");
printf("Testing pidfile_poll() ...\n");
if (!pidfile_poll(PIDFILE))
fprintf(stderr, "Timed out!\n");
printf("Timed out!\n");
else
fprintf(stderr, "We got signal!\n");
printf("We got signal!\n");
system("ls -ld " PIDFILE);
printf("Reading pid file, should be %d ...\n", getpid());
printf("=> %d\n", pidfile_read(PIDFILE));
fprintf(stderr, "Reading pid file, should be %d ...\n", getpid());
fprintf(stderr, "=> %d\n", pidfile_read(PIDFILE));
fprintf(stderr, "Signalling ourselves ...\n");
printf("Signalling ourselves ...\n");
return pidfile_signal(PIDFILE, SIGTERM);
}
@@ -158,7 +165,7 @@ int main(void)
/**
* Local Variables:
* compile-command: "gcc -g -o unittest -DUTEST_PIDFN pidfile.c chomp.c pidfilefn.c && ./unittest"
* compile-command: "make V=1 -f pidfilefn.mk"
* version-control: t
* indent-tabs-mode: t
* c-file-style: "linux"
+5
View File
@@ -0,0 +1,5 @@
OBJS = pidfile.o chomp.o fexist.o
ASROOT = 1
TARGET = clean $(OBJS) pidfilefn.test
include rules.mk
+175
View File
@@ -0,0 +1,175 @@
/* Simple termios based progress bar
*
* Copyright (c) 2012-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 <limits.h> /* INT_MAX */
#include <stdio.h>
#include <string.h>
#include "conio.h"
#define SPINNER_THROB ".oOo"
#define SPINNER_PULSAR ".oO°Oo."
#define SPINNER_ARROW "v<^>"
#define SPINNER_STAR ".oO@*"
#define SPINNER_DEFAULT "|/-\\"
static char spinner(char *style)
{
size_t num;
static unsigned int i = 0;
if (!style)
style = SPINNER_DEFAULT;
num = strlen(style);
return style[i++ % num]; /* % Number of states in style */
}
/**
* progress - Advanced ASCII progress bar with spinner
* @percent: Start first call with this set to 0, end with 100
* @max_width: Max width of progress bar, in total characters.
*
* This function draws an advanced ASCII progressbar at the current
* line. It always start from the first column.
*
* The progress bar will hide the cursor if started with @percent 0 and
* show it again at the end, when called with @percent 100.
*
* While being called with the same percentage the spinner will spin,
* to show the user the process hasn't frozen.
*
* If the output TTY cannot interpret control characters, like \r, it is
* advised to instead used the progress_simple() function.
*/
void progress(int percent, int max_width)
{
int i, bar;
/* Adjust for progress bar overhead */
max_width -= 10;
if (0 == percent)
hidecursor();
fprintf(stderr, "\r%3d%% %c [", percent, spinner(NULL));
bar = percent * max_width / 100;
for (i = 0; i < max_width; i++) {
if (i > bar)
fputc(' ', stderr);
else if (i == bar)
fputc('>', stderr);
else
fputc('=', stderr);
}
fprintf(stderr, "]");
if (100 == percent) {
showcursor();
fputc('\n', stderr);
}
}
void progress_simple(int percent)
{
static int last = 1;
int ratio, numout;
if (!percent && last) {
last = 0;
fputs("0% 25% 50% 75% 100%\n"
"|---------+---------+---------+---------|\n"
"|", stderr);
return;
}
ratio = 40 * percent / 100;
numout = ratio - last;
if (ratio <= last)
return;
last = ratio;
while (numout--) {
if (ratio != 40 || numout)
putc('=', stderr);
else
putc('|', stderr);
}
}
#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
@@ -0,0 +1,4 @@
OBJS =
TARGET = progress.test clean
include rules.mk
+36 -24
View File
@@ -198,7 +198,8 @@ static int prune(char *dst, char **new_files, int new_num)
#define SRC BASE "src/"
#define DST BASE "dst/"
char *files[] = {
static int verbose = 0;
static char *files[] = {
SRC "sub1/1.tst",
SRC "sub1/2.tst",
SRC "sub1/3.tst",
@@ -240,51 +241,62 @@ void setup_test(void)
}
}
int run_test()
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();
puts("Before:");
system("tree -np " BASE);
check_tree("Before:", BASE);
rsync(SRC, DST, 0, NULL);
puts("After:");
system("tree -np " BASE);
result += rsync(SRC, DST, 0, NULL);
check_tree("After:", BASE);
cleanup_test();
#endif
setup_test();
rsync(BASE "src", DST, 0, NULL);
puts("Only partial rsync of src <-- No slash!");
system("tree -np " BASE);
result += rsync(BASE "src", DST, 0, NULL);
check_tree("Only partial rsync of src <-- No slash!", BASE);
#if 0
cleanup_test();
setup_test();
rsync(BASE "src/sub1", BASE "dst", 0, NULL);
puts("Only partial rsync of src/sub1 <-- No slashes!!");
system("tree -np " BASE);
result += rsync(BASE "src/sub1", BASE "dst", 0, NULL);
check_tree("Only partial rsync of src/sub1 <-- No slashes!!", BASE);
cleanup_test();
setup_test();
rsync(BASE "src/sub1/", DST, 0, NULL);
puts("Only partial rsync of src/sub1/");
system("tree -np " BASE);
result += rsync(BASE "src/sub1/", DST, 0, NULL);
check_tree("Only partial rsync of src/sub1/", BASE);
cleanup_test();
setup_test();
rsync(BASE "src/sub1", DST, 0, NULL);
puts("Only partial rsync of src/sub1 <-- No slash!");
system("tree -np " BASE);
result += rsync(BASE "src/sub1", DST, 0, NULL);
check_tree("Only partial rsync of src/sub1 <-- No slash!", BASE);
rsync("/etc", "/var/tmp", 0, NULL);
puts("Real life test:");
system("tree -np /var/tmp");
result += rsync("/etc", "/var/tmp", 0, NULL);
check_tree("Real life test:", "/var/tmp");
#endif
return 0;
return result;
}
int main(int argc, char *argv[])
{
if (argc > 1)
verbose = !strncmp("-v", argv[1], 2);
atexit(cleanup_test);
return run_test();
@@ -293,7 +305,7 @@ int main(int argc, char *argv[])
/**
* Local Variables:
* compile-command: "make -f rsync.mk"
* compile-command: "make V=1 -f rsync.mk"
* version-control: t
* indent-tabs-mode: t
* c-file-style: "linux"
+3 -21
View File
@@ -1,22 +1,4 @@
# Unittest makefile for rsync.c
.PHONY: clean
SRC = rsync.c
OBJS = dir.o copyfile.o fexist.o fisdir.o fmode.o
UNIT = rsync.unittest
#CPPFLAGS = -DDEBUG -I../../.. -I../../include
all: build run
clean:
@rm -f $(OBJS) $(UNIT)
# This rule also forces a cleanup of built objects to not leave any object files
# lingering in the tree to interfere with cross builds.
build: clean $(OBJS)
$(CC) $(CFLAGS) $(CPPFLAGS) -o $(UNIT) -DUNITTEST $(SRC) $(OBJS)
@rm -f $(OBJS)
run:
@./$(UNIT)
OBJS = dir.o copyfile.o fexist.o fisdir.o fmode.o tree.o
TARGET = clean $(OBJS) rsync.test
include rules.mk
+59
View File
@@ -1,3 +1,45 @@
.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
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"
@@ -7,3 +49,20 @@
$(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
+7 -1
View File
@@ -17,6 +17,7 @@
#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() */
@@ -41,6 +42,7 @@
*/
FILE *tempfile(void)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0)
int fd;
mode_t oldmask;
@@ -51,6 +53,10 @@ FILE *tempfile(void)
return NULL;
return fdopen(fd, "rw");
#else
#warning Too old kernel, reverting to wrap unsafe tmpfile() ...
return tmpfile();
#endif
}
#ifdef UNITTEST
@@ -63,7 +69,7 @@ int main(void)
/**
* Local Variables:
* compile-command: "gcc -D_GNU_SOURCE -DUNITTEST -o tempy tempfile.c && ./tempy"
* compile-command: "make V=1 -f tempfile.mk"
* version-control: t
* indent-tabs-mode: t
* c-file-style: "linux"
+4
View File
@@ -0,0 +1,4 @@
OBJS =
TARGET = tempfile.test clean
include rules.mk
+151
View File
@@ -0,0 +1,151 @@
/* 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 result = 0;
struct stat st;
if (-1 == lstat(path, &st))
return 1;
if ((st.st_mode & S_IFMT) == S_IFDIR) {
int i, n;
struct dirent **namelist = NULL;
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);
}
} else {
errno = ENOTDIR;
result = -1;
}
return result;
}
int tree(char *path, int show_perms)
{
printf("[%s]\n", path);
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
@@ -0,0 +1,4 @@
OBJS =
TARGET = clean $(OBJS) tree.test
include rules.mk