mirror of
https://github.com/troglobit/libite.git
synced 2026-10-14 10:19:31 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
34097d33b6 | ||
|
|
311288eec9 | ||
|
|
63cf8867c5 | ||
|
|
ac7b4194cf | ||
|
|
e44aaa4fd5 | ||
|
|
97cb2cb87c | ||
|
|
837c3f23be | ||
|
|
4e9b5c13c1 | ||
|
|
d61b847e55 | ||
|
|
90fdcdeb39 | ||
|
|
e36ac8f462 |
No files matched your search
@@ -4,6 +4,19 @@ 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.5.3][] - 2023-04-08
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
- Refactor `copyfile()` unit test and verify number of bytes copied
|
||||||
|
- Add missing `rsync()` unit test to ensure proper function
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
- `rsync()` does not copy single files correctly
|
||||||
|
- `copyfile()` does not handle empty source files correctly (error)
|
||||||
|
- `copyfile()` does not properly create destination dir
|
||||||
|
|
||||||
|
|
||||||
[v2.5.2][] - 2022-04-17
|
[v2.5.2][] - 2022-04-17
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
AC_INIT(libite, 2.5.2, https://github.com/troglobit/libite/issues)
|
AC_INIT(libite, 2.5.3, https://github.com/troglobit/libite/issues)
|
||||||
AC_CONFIG_AUX_DIR(aux)
|
AC_CONFIG_AUX_DIR(aux)
|
||||||
AM_INIT_AUTOMAKE([1.11 foreign dist-xz])
|
AM_INIT_AUTOMAKE([1.11 foreign dist-xz])
|
||||||
AM_SILENT_RULES([yes])
|
AM_SILENT_RULES([yes])
|
||||||
|
|||||||
Vendored
+11
@@ -1,3 +1,14 @@
|
|||||||
|
libite (2.5.3) stable; urgency=medium
|
||||||
|
|
||||||
|
* rsync() does not copy single files correctly
|
||||||
|
* copyfile() does not handle empty source files correctly (error)
|
||||||
|
* copyfile() does not properly create destination dir
|
||||||
|
* Add printf format attribute hint to all vararg functions
|
||||||
|
* Fix fisdir() segfault on GNU/Hurd
|
||||||
|
* Fix touch() on Debian/kFreeBSD, use creat() instad of mknod()
|
||||||
|
|
||||||
|
-- Joachim Wiberg <troglobit@gmail.com> Sat, 08 Apr 2023 07:04:00 +0200
|
||||||
|
|
||||||
libite (2.5.1) stable; urgency=medium
|
libite (2.5.1) stable; urgency=medium
|
||||||
|
|
||||||
* Use dh_link(1) to install `/usr/include/lite -> libite/`.
|
* Use dh_link(1) to install `/usr/include/lite -> libite/`.
|
||||||
|
|||||||
+20
-5
@@ -38,6 +38,7 @@ static int adjust_target(const char *src, char **dst)
|
|||||||
{
|
{
|
||||||
int isdir = 0;
|
int isdir = 0;
|
||||||
|
|
||||||
|
retry:
|
||||||
if (fisdir(*dst)) {
|
if (fisdir(*dst)) {
|
||||||
int slash = 0;
|
int slash = 0;
|
||||||
char *tmp, *ptr = strrchr(src, '/');
|
char *tmp, *ptr = strrchr(src, '/');
|
||||||
@@ -58,16 +59,25 @@ static int adjust_target(const char *src, char **dst)
|
|||||||
|
|
||||||
sprintf(tmp, "%s%s%s", *dst, slash ? "" : "/", ptr);
|
sprintf(tmp, "%s%s%s", *dst, slash ? "" : "/", ptr);
|
||||||
*dst = tmp;
|
*dst = tmp;
|
||||||
|
} else {
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
if (stat(*dst, &st) && fisslashdir(*dst)) {
|
||||||
|
makedir(*dst, 0755);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return isdir;
|
return isdir;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Actual copy loop, used by both copyfile() and fcopyfile()
|
/*
|
||||||
* breaks loop on error and EOF */
|
* Actual copy loop, used by both copyfile() and fcopyfile() breaks loop
|
||||||
|
* on error and EOF
|
||||||
|
*/
|
||||||
static ssize_t do_copy(int in, int out, size_t num, char *buffer, size_t len)
|
static ssize_t do_copy(int in, int out, size_t num, char *buffer, size_t len)
|
||||||
{
|
{
|
||||||
ssize_t ret = 0, size = 0;
|
ssize_t ret = 0, size = -1;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
size_t count = num > len ? len : num;
|
size_t count = num > len ? len : num;
|
||||||
@@ -76,11 +86,16 @@ static ssize_t do_copy(int in, int out, size_t num, char *buffer, size_t len)
|
|||||||
if (ret <= 0) {
|
if (ret <= 0) {
|
||||||
if (ret == -1 && EINTR == errno)
|
if (ret == -1 && EINTR == errno)
|
||||||
continue;
|
continue;
|
||||||
|
if (ret == 0 && size == -1)
|
||||||
|
size = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret > 0)
|
if (ret > 0) {
|
||||||
|
if (size == -1)
|
||||||
|
size = 0;
|
||||||
size += write(out, buffer, ret);
|
size += write(out, buffer, ret);
|
||||||
|
}
|
||||||
num -= count;
|
num -= count;
|
||||||
} while (num > 0);
|
} while (num > 0);
|
||||||
|
|
||||||
@@ -194,7 +209,7 @@ ssize_t copyfile(const char *src, const char *dst, int len, int opt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
size = do_copy(in, out, num, buffer, BUFSIZ);
|
size = do_copy(in, out, num, buffer, BUFSIZ);
|
||||||
if (!size && errno)
|
if (size < 0)
|
||||||
saved_errno = errno;
|
saved_errno = errno;
|
||||||
else if (keep_mtim)
|
else if (keep_mtim)
|
||||||
set_mtime(in, out);
|
set_mtime(in, out);
|
||||||
|
|||||||
+5
-3
@@ -77,7 +77,9 @@ int rsync(char *src, char *dst, int opt, int (*filter)(const char *file))
|
|||||||
char **files; /* Array of file names. */
|
char **files; /* Array of file names. */
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
if (!fisdir(dst))
|
errno = 0;
|
||||||
|
|
||||||
|
if (stat(dst, &st) && fisslashdir(dst))
|
||||||
makedir(dst, 0755);
|
makedir(dst, 0755);
|
||||||
|
|
||||||
if (!fisdir(src)) {
|
if (!fisdir(src)) {
|
||||||
@@ -85,9 +87,9 @@ int rsync(char *src, char *dst, int opt, int (*filter)(const char *file))
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (copy(src, dst, keep_mtim))
|
if (copy(src, dst, keep_mtim))
|
||||||
result++;
|
return 1;
|
||||||
|
|
||||||
return errno;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy dir as well? */
|
/* Copy dir as well? */
|
||||||
|
|||||||
+124
-48
@@ -2,54 +2,130 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include "check.h"
|
#include "check.h"
|
||||||
|
|
||||||
|
#define ERR(fmt, args...) { printf(fmt ": %s\n", ##args, strerror(errno)); rc = 1; }
|
||||||
|
#define ERRX(fmt, args...) { printf(fmt "\n", ##args); rc = 1; }
|
||||||
|
|
||||||
|
static char *files[] = {
|
||||||
|
"/etc/passwd", "/tmp/mypwd", "/tmp/mypwd",
|
||||||
|
"/etc/passwd", "/tmp/", "/tmp/passwd",
|
||||||
|
"/etc/passwd", "/tmp", "/tmp/passwd",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static int one_sz(const char *src, const char *dst, int sz)
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
ssize_t len;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
len = copyfile(src, dst, sz, 0);
|
||||||
|
if (!len) {
|
||||||
|
ERR("failed copying any bytes from %s", src);
|
||||||
|
} else {
|
||||||
|
if (stat(dst, &st))
|
||||||
|
ERR("copied but cannot find destination %s", dst);
|
||||||
|
|
||||||
|
if (st.st_size != sz)
|
||||||
|
ERR("file only %ld bytes, expected %d", st.st_size, sz);
|
||||||
|
|
||||||
|
if (len != st.st_size)
|
||||||
|
ERRX("copied expected data %d, but copyfile() says %ld", sz, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _sz()
|
||||||
|
{
|
||||||
|
const int sz = 32768;
|
||||||
|
|
||||||
|
return test(one_sz("/dev/zero", "/tmp/zeroes", sz), "copyfile(/dev/zero, %d)", sz);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fcopyfile_one(const char *src, const char *dst, const char *expected)
|
||||||
|
{
|
||||||
|
FILE *from, *to;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
from = fopen(src, "r");
|
||||||
|
to = fopen(dst, "w");
|
||||||
|
|
||||||
|
rc = fcopyfile(from, to);
|
||||||
|
|
||||||
|
if (from)
|
||||||
|
fclose(from);
|
||||||
|
if (to)
|
||||||
|
fclose(to);
|
||||||
|
|
||||||
|
if (rc) {
|
||||||
|
if (!src || !dst)
|
||||||
|
rc = 0; /* expected */
|
||||||
|
else if (fisdir(dst))
|
||||||
|
rc = 0; /* expected */
|
||||||
|
} else {
|
||||||
|
if (fexist(expected)) {
|
||||||
|
if (systemf("diff -q %s %s", src, expected))
|
||||||
|
rc = 1;
|
||||||
|
} else
|
||||||
|
ERR("cannot find %s", expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
erase(expected);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _fcopyfile()
|
||||||
|
{
|
||||||
|
int i, rc = 0;
|
||||||
|
|
||||||
|
for (i = 0; files[i]; i += 3) {
|
||||||
|
char *src = files[i];
|
||||||
|
char *dst = files[i + 1];
|
||||||
|
char *res = files[i + 2];
|
||||||
|
|
||||||
|
rc += test(fcopyfile_one(src, dst, res), "fcopyfile(%s, %s)", src, dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* only checks success, correct file size verified by _sz() */
|
||||||
|
static int copyfile_one(const char *src, const char *dst, const char *expected)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = copyfile(src, dst, 0, 0);
|
||||||
|
if (!rc)
|
||||||
|
rc = 1;
|
||||||
|
else if (!fexist(expected))
|
||||||
|
rc = 1;
|
||||||
|
else
|
||||||
|
rc = 0;
|
||||||
|
|
||||||
|
erase(expected);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _copyfile()
|
||||||
|
{
|
||||||
|
int i, rc = 0;
|
||||||
|
|
||||||
|
for (i = 0; files[i]; i += 3) {
|
||||||
|
char *src = files[i];
|
||||||
|
char *dst = files[i + 1];
|
||||||
|
char *res = files[i + 2];
|
||||||
|
|
||||||
|
rc += test(copyfile_one(src, dst, res), "copyfile(%s, %s)", src, dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
int i = 0;
|
return _fcopyfile() ||
|
||||||
char *files[] = {
|
_copyfile() ||
|
||||||
"/etc/passwd", "/tmp/mypwd", "/tmp/mypwd",
|
_sz();
|
||||||
"/etc/passwd", "/tmp/", "/tmp/passwd",
|
|
||||||
"/etc/passwd", "/tmp", "/tmp/passwd",
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
FILE *src, *dst;
|
|
||||||
|
|
||||||
printf("=>Start testing fcopyfile()\n");
|
|
||||||
while (files[i]) {
|
|
||||||
printf("fcopyfile(%s, %s)\t", files[i], files[i + 1]);
|
|
||||||
src = fopen(files[i], "r");
|
|
||||||
dst = fopen(files[i + 1], "w");
|
|
||||||
if (fcopyfile(src, dst)) {
|
|
||||||
if (!fisdir(files[i + 1]))
|
|
||||||
err(1, "Failed fcopyfile(%s, %s)", files[i], files[i + 1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (src)
|
|
||||||
fclose(src);
|
|
||||||
if (dst)
|
|
||||||
fclose(dst);
|
|
||||||
|
|
||||||
if (fexist(files[i + 2]))
|
|
||||||
printf("OK => %s", files[i + 2]);
|
|
||||||
printf("\n");
|
|
||||||
|
|
||||||
erase(files[i + 2]);
|
|
||||||
i += 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\n=>Start testing copyfile()\n");
|
|
||||||
i = 0;
|
|
||||||
while (files[i]) {
|
|
||||||
printf("copyfile(%s, %s)\t", files[i], files[i + 1]);
|
|
||||||
if (!copyfile(files[i], files[i + 1], 0, 0))
|
|
||||||
err(1, "Failed copyfile(%s, %s)", files[i], files[i + 1]);
|
|
||||||
|
|
||||||
if (fexist(files[i + 2]))
|
|
||||||
printf("OK => %s", files[i + 2]);
|
|
||||||
printf("\n");
|
|
||||||
|
|
||||||
erase(files[i + 2]);
|
|
||||||
i += 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
+65
-35
@@ -48,52 +48,82 @@ void setup_test(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void check_tree(char *heading, char *dir)
|
int check_dir_to_dir(void)
|
||||||
{
|
{
|
||||||
if (verbose) {
|
int rc = 0;
|
||||||
if (heading)
|
|
||||||
puts(heading);
|
rc += rsync(SRC, DST, LITE_FOPT_KEEP_MTIME, NULL);
|
||||||
|
rc += systemf("diff -rq %s %s", SRC, DST);
|
||||||
|
systemf("rm -rf %s/*", DST);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int check_file_to_file(void)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
touch(SRC "foo.txt");
|
||||||
|
PRINT("SRC ==========================\n");
|
||||||
|
if (verbose) system("ls -l " SRC);
|
||||||
|
rc += rsync(SRC "foo.txt", DST "foo.txt", LITE_FOPT_KEEP_MTIME, NULL);
|
||||||
|
if (!fexist(DST "foo.txt") || fisdir(DST "foo.txt")) {
|
||||||
|
PRINT("No dst file or it's a directory\n");
|
||||||
|
rc++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX: Fixme, add code to list tree, nftw() possibly
|
PRINT("DST ==========================\n");
|
||||||
|
if (verbose) system("ls -l " DST);
|
||||||
|
systemf("rm -rf %s %s/*", SRC "foo.txt" , DST);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int check_file_to_dir(void)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
touch(SRC "foo.txt");
|
||||||
|
PRINT("SRC ==========================\n");
|
||||||
|
if (verbose) system("ls -l " SRC);
|
||||||
|
rc += rsync(SRC "foo.txt", DST, LITE_FOPT_KEEP_MTIME, NULL);
|
||||||
|
if (!fexist(DST "foo.txt") || fisdir(DST "foo.txt"))
|
||||||
|
rc++;
|
||||||
|
PRINT("DST ==========================\n");
|
||||||
|
if (verbose) system("ls -l " DST);
|
||||||
|
systemf("rm -rf %s %s/*", SRC "foo.txt" , DST);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int check_file_to_nodir(void)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
touch(SRC "foo.txt");
|
||||||
|
PRINT("SRC ==========================\n");
|
||||||
|
if (verbose) system("ls -l " SRC);
|
||||||
|
system("rm -rf " DST);
|
||||||
|
rc += rsync(SRC "foo.txt", DST, LITE_FOPT_KEEP_MTIME, NULL);
|
||||||
|
if (!fexist(DST "foo.txt") || fisdir(DST "foo.txt"))
|
||||||
|
rc++;
|
||||||
|
PRINT("DST ==========================\n");
|
||||||
|
if (verbose) system("ls -l " DST);
|
||||||
|
systemf("rm -rf %s %s/*", SRC "foo.txt" , DST);
|
||||||
|
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int run_test(void)
|
int run_test(void)
|
||||||
{
|
{
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
|
||||||
#if 0
|
|
||||||
setup_test();
|
setup_test();
|
||||||
check_tree("Before:", BASE);
|
|
||||||
|
|
||||||
result += rsync(SRC, DST, 0, NULL);
|
result += test(check_dir_to_dir(), "Verifying src/ -> dst/");
|
||||||
check_tree("After:", BASE);
|
result += test(check_file_to_file(), "Verifying src/foo.txt -> dst/foo.txt");
|
||||||
cleanup_test();
|
result += test(check_file_to_dir(), "Verifying src/foo.txt -> dst/");
|
||||||
#endif
|
result += test(check_file_to_nodir(),"Verifying src/foo.txt -> dst/ (non-existing target dir)");
|
||||||
|
|
||||||
setup_test();
|
|
||||||
sleep(1);
|
|
||||||
result += rsync(BASE "src", DST, LITE_FOPT_KEEP_MTIME, NULL);
|
|
||||||
check_tree("Only partial rsync of src <-- No slash!", BASE);
|
|
||||||
#if 0
|
|
||||||
cleanup_test();
|
|
||||||
setup_test();
|
|
||||||
result += rsync(BASE "src/sub1", BASE "dst", 0, NULL);
|
|
||||||
check_tree("Only partial rsync of src/sub1 <-- No slashes!!", BASE);
|
|
||||||
|
|
||||||
cleanup_test();
|
|
||||||
setup_test();
|
|
||||||
result += rsync(BASE "src/sub1/", DST, 0, NULL);
|
|
||||||
check_tree("Only partial rsync of src/sub1/", BASE);
|
|
||||||
|
|
||||||
cleanup_test();
|
|
||||||
setup_test();
|
|
||||||
result += rsync(BASE "src/sub1", DST, 0, NULL);
|
|
||||||
check_tree("Only partial rsync of src/sub1 <-- No slash!", BASE);
|
|
||||||
|
|
||||||
result += rsync("/etc", "/var/tmp", 0, NULL);
|
|
||||||
check_tree("Real life test:", "/var/tmp");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user