1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
|
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* Copyright (c) 2023-2024 Brett Sheffield <bacs@librecast.net> */
#include "../src/config.h"
#define _XOPEN_SOURCE 700 /* for nftw() */
#include <ftw.h>
#include "test.h"
#include "testdata.h"
#include <assert.h>
#include <sys/types.h>
#include <unistd.h>
static char *rsrc, *rdst, *owd;
/* check mode, owner, group, times */
int statcmp_sb(const struct stat *ssb, const struct stat *dsb, const char *dst)
{
if ((ssb->st_mode & S_IFMT) == S_IFLNK) return 0; /* don't bother with symlinks */
test_assert(ssb->st_mode == dsb->st_mode, "st_mode: '%s' %o %o", dst, ssb->st_mode, dsb->st_mode);
test_assert(ssb->st_uid == dsb->st_uid, "st_uid: '%s'", dst);
test_assert(ssb->st_gid == dsb->st_gid, "st_gid: '%s'", dst);
if ((ssb->st_mode & S_IFMT) != S_IFDIR) {
/* check size, but not for directories */
test_assert(ssb->st_size == dsb->st_size, "st_size: '%s'", dst);
}
#ifndef HAVE_UTIMENSAT
/* without utimensat(), we only have microsecond precision */
ssb->st_mtim.tv_nsec /= 1000; ssb->st_mtim.tv_nsec *= 1000;
ssb->st_atim.tv_nsec /= 1000; ssb->st_atim.tv_nsec *= 1000;
#endif
/* No point testing atime unless the filesystem is mounted noatime */
/* test_assert(ssb.st_atim.tv_nsec == dsb.st_atim.tv_nsec, "st_atim: '%s'", dst); */
test_assert(ssb->st_mtim.tv_nsec == dsb->st_mtim.tv_nsec, "st_mtim: '%s'", dst);
return 0;
}
/* check mode, owner, group, times */
int statcmp(const char *src, const char *dst)
{
struct stat ssb, dsb;
int rc;
rc = stat(src, &ssb);
if (!test_assert(rc == 0, "stat '%s'", src)) return -1;
rc = stat(dst, &dsb);
if (!test_assert(rc == 0, "stat '%s'", dst)) return -1;
return statcmp_sb(&ssb, &dsb, dst);
}
static int verify_dst(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf)
{
(void) typeflag, (void) ftwbuf;
struct stat dsb;
int rc;
if (chdir(rdst) == -1) return -1;
rc = stat(fpath, &dsb);
if (!rc) rc = statcmp_sb(sb, &dsb, fpath);
if (chdir(rsrc) == -1) return -1;
return rc;
}
void test_verify_dirs(const char *src, const char *dst)
{
int n = 0, rc;
statcmp(src, dst);
owd = getcwd(NULL, 0);
assert(owd);
rsrc = realpath(src, NULL);
rdst = realpath(dst, NULL);
test_log("src: %s\n", src);
test_log("dst: %s\n", dst);
test_log("rsrc: %s\n", rsrc);
test_log("rdst: %s\n", rdst);
if (chdir(rsrc) == -1) goto err_free;
rc = nftw(".", &verify_dst, 32, 0);
if (!test_assert(rc == 0, "nftw() returned %i", rc)) goto err_free;
test_log("%i entries verified\n", n);
test_assert(test_status == TEST_OK, "source and destination trees match");
if (chdir(owd) == -1) perror("chdir");
err_free:
free(rsrc); free(rdst);
free(owd);
}
|