Skip to content

Commit

Permalink
Merge pull request #16 from mariux64/next
Browse files Browse the repository at this point in the history
Fixes a NULL pointer dereference when the first incarnation of a file with multiple hardlinks ist not created, e.g. because of `--rduce`. Minor new features and code cleanup.
  • Loading branch information
donald authored Dec 15, 2022
2 parents 14bd1ac + bb3613f commit 055fdc2
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 36 deletions.
27 changes: 27 additions & 0 deletions README.local-glib
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
To install with static glib (e.g. when system glib is to old):
==============================================================
git clone https://github.com/GNOME/glib.git glib_src
git -C glib_src checkout 2.70.5
mkdir glib_build
meson setup glib_build glib_src --buildtype release -Ddefault_library=static
cd glib_build
ninja build

patch -p1 Makefile <<'EOF'
diff --git a/Makefile b/Makefile
index 921b373..7a0bd0c 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
CFLAGS += -O3
CFLAGS += -g -Wall -Wextra -Werror
-CFLAGS += $(shell pkg-config --cflags glib-2.0)
-LDLIBS += $(shell pkg-config --libs glib-2.0)
+CFLAGS += -Iglib_src -Iglib_src/glib -Iglib_build/glib
+LDLIBS += -Lglib_build/glib -lglib-2.0 -lpthread -lpcre

cmirror: cmirror.c

EOF
make

66 changes: 30 additions & 36 deletions cmirror.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
#include <ctype.h>
#include <getopt.h>

// https://www.manpagez.com/html/glib/glib-2.56.0/glib-Double-ended-Queues.php
// http://owww.molgen.mpg.de/~buczek/glib-doc/

#include <glib.h>
Expand Down Expand Up @@ -61,7 +60,7 @@ static G_NORETURN G_GNUC_PRINTF(1, 2) void die(const char *restrict fmt, ...) {

static GRegex *compile_pattern(char *pattern) {
GError *error = NULL;
GRegex *regex = g_regex_new(pattern, 0, 0, &error);;
GRegex *regex = g_regex_new(pattern, 0, 0, &error);
if (!regex)
die("%s\n", error->message);
return regex;
Expand Down Expand Up @@ -112,9 +111,8 @@ static gboolean fn_unescape_cb(const GMatchInfo *match_info, GString *result, g

static char *fn_unescape(char *fn) {
static GRegex *regex = NULL;
if (!regex) {
if (!regex)
regex = compile_pattern("\\\\x([0-9a-f]{0,2})");
}
GError *error;
char *ret = g_regex_replace_eval(regex, fn, -1, 0, 0, fn_unescape_cb, NULL, &error);
if (!ret)
Expand Down Expand Up @@ -285,7 +283,7 @@ static int reduce;
static int force_status;
static int bandwidth;
static int allowremotefs;
static char *ssh_opt;
static char **ssh_opts;
static int cksum;
static int opt_nice;
static int unix_socket;
Expand Down Expand Up @@ -318,17 +316,6 @@ static void fileop_mknod(char *path, char type, dev_t rdev) {
die("%s: %m\n", path);
}

static void fileop_chown(uid_t uid, gid_t gid, char *path) {
if (slave_unprivileged)
return;
if (fileop_debug)
warn("fileop: chown %d:%d %s\n", uid, gid, path);
if (fileop_noop)
return;
if (lchown(path, uid, gid) == -1)
die("%s: %m\n", path);
}

static void fileop_chmod(mode_t perm, char *path) {
if (fileop_debug)
warn("fileop: chmod 0%03o %s\n", perm, path);
Expand Down Expand Up @@ -465,10 +452,10 @@ static void fileop_ln_or_cp(char *from, char *to) {
}

static void check_perm(FileInfo *is, FileInfo *want) {
if (is->uid != want->uid || is->gid != want ->gid ){
if (!quiet && !slave_unprivileged)
if (!slave_unprivileged && (is->uid != want->uid || is->gid != want->gid) ) {
if (!quiet)
warn("chown %d:%d %s\n", want->uid, want->gid, is->name);
fileop_chown(want->uid, want->gid, is->name);
fileop_lchown(want->uid, want->gid, is->name);
}
if (want->perm != is->perm) {
if (!quiet)
Expand All @@ -481,7 +468,8 @@ static void make_dir(char *path, mode_t perm, uid_t uid, gid_t gid) {
if (!quiet)
warn("mkdir %s owner %d:%d mode 0%03o\n", path, uid, gid, perm);
fileop_mkdir(path);
fileop_chown(uid, gid, path);
if (!slave_unprivileged)
fileop_lchown(uid, gid, path);
fileop_chmod(perm, path);
}

Expand All @@ -505,11 +493,10 @@ static void add_clean_dir(char *dir) {
const char *entry;
while ( (entry = g_dir_read_name(d)) ) {
char *path = g_strdup_printf("%s/%s", dir, entry);
if (is_excepted(path)) {
if (is_excepted(path))
free(path);
} else {
else
g_hash_table_insert(CLEAN, path, path);
}
}
g_dir_close(d);
}
Expand All @@ -527,7 +514,7 @@ static void out_of_the_way(FileInfo *fi) {
static int is_local_fs(char *fs) {
static GRegex *local_fs_regex;
if (!local_fs_regex)
local_fs_regex = compile_pattern("^(advfs|ufs|ext\\d+|reiserfs|xfs|fuseblk|vfat|efs|tmpfs|btrfs)$");
local_fs_regex = compile_pattern("^(advfs|ufs|ext\\d+|reiserfs|xfs|fuseblk|vfat|efs|tmpfs|btrfs|ecryptfs)$");
return g_regex_match(local_fs_regex, fs, 0, 0);
}

Expand Down Expand Up @@ -778,9 +765,11 @@ static void slave(char *slave_path) {
g_autofree char *hardlink = fn_unescape(word[7]);
g_autoptr(FileInfo) fi_src = fileinfo_lstat(hardlink);
if (!fi_src) {
// source removed, i/o error, --reduce or logic error. We could
// request the file here, but the above cases don't seem to
// ustify this.
warn("%s: hardlink source %s: %m\n", filename, hardlink);
}
if (!fi_is || fi_is->dev != fi_src->dev || fi_is->ino != fi_src->ino) {
} else if (!fi_is || fi_is->dev != fi_src->dev || fi_is->ino != fi_src->ino) {
if (fi_is)
out_of_the_way(fi_is);
if (!quiet)
Expand Down Expand Up @@ -816,7 +805,7 @@ static void slave(char *slave_path) {
close(fd);
}
if (!slave_unprivileged) {
fileop_chown(fi_want->uid, fi_want->gid, tmpfile);
fileop_lchown(fi_want->uid, fi_want->gid, tmpfile);
fileop_chmod(fi_want->perm, tmpfile);
}
if (fi_is && fi_is->type == 'D')
Expand Down Expand Up @@ -846,7 +835,8 @@ static void slave(char *slave_path) {
if (!quiet)
warn("ln -s %s %s\n", fi_want->target, filename);
fileop_symlink(fi_want->target, filename);
fileop_lchown(fi_want->uid, fi_want->gid, filename);
if (!slave_unprivileged)
fileop_lchown(fi_want->uid, fi_want->gid, filename);
fileop_lmtime(fi_want->mtime, filename);
} else {
if (!slave_unprivileged && (fi_is->uid != fi_want->uid || fi_is->gid != fi_want->gid)) {
Expand All @@ -867,7 +857,8 @@ static void slave(char *slave_path) {
if (!quiet)
warn("mknod %s P\n", filename);
fileop_mknod(filename, fi_want->type, 0);
fileop_chown(fi_want->uid, fi_want->gid, filename);
if (!slave_unprivileged)
fileop_lchown(fi_want->uid, fi_want->gid, filename);
fileop_chmod(fi_want->perm, filename);
}
} else if (fi_want->type== 'S') {
Expand All @@ -879,7 +870,8 @@ static void slave(char *slave_path) {
if (!quiet)
warn("mknod %s %c\n", filename, fi_want->type);
fileop_mknod(filename, fi_want->type, fi_want->rdev);
fileop_chown(fi_want->uid, fi_want->gid, filename);
if (!slave_unprivileged)
fileop_lchown(fi_want->uid, fi_want->gid, filename);
fileop_chmod(fi_want->perm, filename);
} else {
check_perm(fi_is, fi_want);
Expand Down Expand Up @@ -1101,7 +1093,6 @@ static void master(char *master_path, char *target) {
g_ptr_array_add (EXCEPTS, "./.tags");
g_ptr_array_add (EXCEPTS, "./.PMIRROR_ENABLED");
g_ptr_array_add (EXCEPTS, "./.PMIRROR_STATUS");
g_ptr_array_add (EXCEPTS, "./.PMIRROR_HISTORY");
if (excepts) {
for (char **p = excepts; *p; p++) {
g_ptr_array_add (EXCEPTS, *p);
Expand Down Expand Up @@ -1211,7 +1202,9 @@ static void master(char *master_path, char *target) {
char *s = g_strdup_printf("%s:%s", unix_socket_name, unix_socket_name);
g_ptr_array_add(args, s);
}
if (ssh_opt) g_ptr_array_add(args, ssh_opt);
if (ssh_opts)
for (char **p = ssh_opts ; *p ; p++)
g_ptr_array_add(args, *p);
g_ptr_array_add(args, slave);
g_ptr_array_add(args, "/usr/bin/cmirror");
g_ptr_array_add(args, "--slave");
Expand Down Expand Up @@ -1450,7 +1443,6 @@ static void master(char *master_path, char *target) {
}
}


int main(int argc, char **argv) {

char *argv0 = argv[0];
Expand All @@ -1464,6 +1456,7 @@ int main(int argc, char **argv) {
}

g_autoptr(GStrvBuilder) excepts_builder = g_strv_builder_new();
g_autoptr(GStrvBuilder) ssh_opts_builder = g_strv_builder_new();
while (1) {
int opt = getopt_long(argc, argv, "", options, NULL);
if (opt == -1)
Expand All @@ -1475,9 +1468,9 @@ int main(int argc, char **argv) {
else if (opt == 101)
identity_file = g_strdup(optarg);
else if (opt == 102)
g_strv_builder_add(excepts_builder, g_strdup(optarg));
g_strv_builder_add(excepts_builder, optarg);
else if (opt == 103)
ssh_opt = g_strdup(optarg);
g_strv_builder_add(ssh_opts_builder, optarg);
else if (opt == 104)
unix_socket_name = g_strdup(optarg);
else if (opt == '?')
Expand All @@ -1486,6 +1479,7 @@ int main(int argc, char **argv) {
die("internal error: getopt returned %d\n", opt);
}
excepts = g_strv_builder_end(excepts_builder);
ssh_opts = g_strv_builder_end(ssh_opts_builder);
argv = &argv[optind];
argc -= optind;

Expand All @@ -1496,7 +1490,7 @@ int main(int argc, char **argv) {

if (opt_nice) {
g_autofree char *cmd = g_strdup_printf("ionice -c idle -p %d", getpid());
system(cmd);
int __attribute__((unused)) status = system(cmd);
}

if (slave_mode) {
Expand Down

0 comments on commit 055fdc2

Please sign in to comment.