From 178a61384887dfac9a5ff6219995969ba582dd0b Mon Sep 17 00:00:00 2001 From: Donald Buczek Date: Sat, 10 Sep 2022 11:58:37 +0200 Subject: [PATCH 01/13] Ignore system("ionice") failure more explicitly Newer versions of glibc set the function attribute `warn_unused_result` on `system()`. We want to ignore a failure in the call with `ionice`, because its best-efford anyway. Unfortunately, the intuitive `(void)system(...)` doesn't work with gcc. --- cmirror.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmirror.c b/cmirror.c index 987d3e4..2e121c0 100644 --- a/cmirror.c +++ b/cmirror.c @@ -1496,7 +1496,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) { From a88862762a6e02f031914d7e512226f1d49a4265 Mon Sep 17 00:00:00 2001 From: Donald Buczek Date: Sat, 10 Sep 2022 12:14:22 +0200 Subject: [PATCH 02/13] Do not try to lchown new links when slave is unprivileged --- cmirror.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmirror.c b/cmirror.c index 2e121c0..0befcd5 100644 --- a/cmirror.c +++ b/cmirror.c @@ -846,7 +846,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)) { From 0ab3a32dd81f920ed3b8367bde8f91c17a656547 Mon Sep 17 00:00:00 2001 From: Donald Buczek Date: Sat, 10 Sep 2022 14:19:05 +0200 Subject: [PATCH 03/13] Let caller of fileop_chown check for !slave_unprivileged --- cmirror.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/cmirror.c b/cmirror.c index 0befcd5..cc626cb 100644 --- a/cmirror.c +++ b/cmirror.c @@ -319,8 +319,6 @@ static void fileop_mknod(char *path, char type, dev_t rdev) { } 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) @@ -465,8 +463,8 @@ 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); } @@ -481,7 +479,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_chown(uid, gid, path); fileop_chmod(perm, path); } @@ -868,7 +867,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_chown(fi_want->uid, fi_want->gid, filename); fileop_chmod(fi_want->perm, filename); } } else if (fi_want->type== 'S') { @@ -880,7 +880,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_chown(fi_want->uid, fi_want->gid, filename); fileop_chmod(fi_want->perm, filename); } else { check_perm(fi_is, fi_want); From a05560e71219a100739c43a3478b6c0d91562950 Mon Sep 17 00:00:00 2001 From: Donald Buczek Date: Sat, 10 Sep 2022 14:22:11 +0200 Subject: [PATCH 04/13] Remove fileop_chown After the last commit, fileop_chown and fileop_lchown are the same. Remove fileop_chown and use fileop_lchown everywhere. --- cmirror.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/cmirror.c b/cmirror.c index cc626cb..64466a1 100644 --- a/cmirror.c +++ b/cmirror.c @@ -318,15 +318,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 (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); @@ -466,7 +457,7 @@ static void check_perm(FileInfo *is, FileInfo *want) { 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) @@ -480,7 +471,7 @@ static void make_dir(char *path, mode_t perm, uid_t uid, gid_t gid) { warn("mkdir %s owner %d:%d mode 0%03o\n", path, uid, gid, perm); fileop_mkdir(path); if (!slave_unprivileged) - fileop_chown(uid, gid, path); + fileop_lchown(uid, gid, path); fileop_chmod(perm, path); } @@ -815,7 +806,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') @@ -868,7 +859,7 @@ static void slave(char *slave_path) { warn("mknod %s P\n", filename); fileop_mknod(filename, fi_want->type, 0); if (!slave_unprivileged) - fileop_chown(fi_want->uid, fi_want->gid, filename); + fileop_lchown(fi_want->uid, fi_want->gid, filename); fileop_chmod(fi_want->perm, filename); } } else if (fi_want->type== 'S') { @@ -881,7 +872,7 @@ static void slave(char *slave_path) { warn("mknod %s %c\n", filename, fi_want->type); fileop_mknod(filename, fi_want->type, fi_want->rdev); if (!slave_unprivileged) - fileop_chown(fi_want->uid, fi_want->gid, filename); + fileop_lchown(fi_want->uid, fi_want->gid, filename); fileop_chmod(fi_want->perm, filename); } else { check_perm(fi_is, fi_want); From c7f39833beb6457d872d9bb6906d7784b2d64df0 Mon Sep 17 00:00:00 2001 From: Donald Buczek Date: Sat, 10 Sep 2022 14:36:42 +0200 Subject: [PATCH 05/13] Add README.local-glib --- README.local-glib | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 README.local-glib diff --git a/README.local-glib b/README.local-glib new file mode 100644 index 0000000..13813fc --- /dev/null +++ b/README.local-glib @@ -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 + From 5686998421a8ad54b4e58125938ceb6deafc3a53 Mon Sep 17 00:00:00 2001 From: Donald Buczek Date: Fri, 23 Sep 2022 09:54:55 +0200 Subject: [PATCH 06/13] Add "ecryptfs" as local filesystem My notebook uses ecryptfs and this surely is a local filesystem. --- cmirror.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmirror.c b/cmirror.c index 64466a1..5354c07 100644 --- a/cmirror.c +++ b/cmirror.c @@ -517,7 +517,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); } From b42b2da89c7c37a2d7ba6b8c16ef68661be1534d Mon Sep 17 00:00:00 2001 From: Donald Buczek Date: Sat, 24 Sep 2022 11:59:30 +0200 Subject: [PATCH 07/13] Allow multiple --ssh-opt in command line --ssh-opt is much more powerfull if it can be specified multiple times. So allow that. --- cmirror.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/cmirror.c b/cmirror.c index 5354c07..2e404da 100644 --- a/cmirror.c +++ b/cmirror.c @@ -285,7 +285,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; @@ -1204,7 +1204,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"); @@ -1457,6 +1459,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) @@ -1470,7 +1473,7 @@ int main(int argc, char **argv) { else if (opt == 102) g_strv_builder_add(excepts_builder, g_strdup(optarg)); else if (opt == 103) - ssh_opt = g_strdup(optarg); + g_strv_builder_add(ssh_opts_builder, g_strdup(optarg)); else if (opt == 104) unix_socket_name = g_strdup(optarg); else if (opt == '?') @@ -1479,6 +1482,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; From 19bc12d8fb653421a0066861cbde6f3c0cf65c85 Mon Sep 17 00:00:00 2001 From: Donald Buczek Date: Sat, 24 Sep 2022 16:24:53 +0200 Subject: [PATCH 08/13] Don't dup strings from argv We don't free the string vectors `excepts` and `ssh_opts` or the strings they containt, so we can use the strings from argv directly. --- cmirror.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmirror.c b/cmirror.c index 2e404da..4c3e457 100644 --- a/cmirror.c +++ b/cmirror.c @@ -1471,9 +1471,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) - g_strv_builder_add(ssh_opts_builder, g_strdup(optarg)); + g_strv_builder_add(ssh_opts_builder, optarg); else if (opt == 104) unix_socket_name = g_strdup(optarg); else if (opt == '?') From 4c637811c00ef0fea4d7bb70a8fd1f34e7d10262 Mon Sep 17 00:00:00 2001 From: Donald Buczek Date: Tue, 27 Sep 2022 08:32:17 +0200 Subject: [PATCH 09/13] Cosmetics --- cmirror.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/cmirror.c b/cmirror.c index 4c3e457..709e37a 100644 --- a/cmirror.c +++ b/cmirror.c @@ -112,9 +112,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) @@ -495,11 +494,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); } @@ -1445,7 +1443,6 @@ static void master(char *master_path, char *target) { } } - int main(int argc, char **argv) { char *argv0 = argv[0]; From d345a505911044470c8d1f8de4b33a95291867a0 Mon Sep 17 00:00:00 2001 From: Donald Buczek Date: Mon, 26 Sep 2022 07:01:49 +0200 Subject: [PATCH 10/13] Remove strange doc reference --- cmirror.c | 1 - 1 file changed, 1 deletion(-) diff --git a/cmirror.c b/cmirror.c index 709e37a..7594397 100644 --- a/cmirror.c +++ b/cmirror.c @@ -26,7 +26,6 @@ #include #include -// https://www.manpagez.com/html/glib/glib-2.56.0/glib-Double-ended-Queues.php // http://owww.molgen.mpg.de/~buczek/glib-doc/ #include From c29c7f637efa02f5d3c5f0fcc5d1d95081a33ef5 Mon Sep 17 00:00:00 2001 From: Donald Buczek Date: Mon, 26 Sep 2022 07:02:20 +0200 Subject: [PATCH 11/13] Remove doubled semicolon --- cmirror.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmirror.c b/cmirror.c index 7594397..3a7f3db 100644 --- a/cmirror.c +++ b/cmirror.c @@ -60,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; From 281b34a0ea80e360bac915b28ab3f8d8eb34e7d4 Mon Sep 17 00:00:00 2001 From: Donald Buczek Date: Mon, 26 Sep 2022 07:23:24 +0200 Subject: [PATCH 12/13] Remove .PMIRROR_HISTORY exclude I don't remember, what his was for, so remove it. --- cmirror.c | 1 - 1 file changed, 1 deletion(-) diff --git a/cmirror.c b/cmirror.c index 3a7f3db..967235d 100644 --- a/cmirror.c +++ b/cmirror.c @@ -1091,7 +1091,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); From bb3613fe0b2c2cc72c0faaab15848b29f30305ee Mon Sep 17 00:00:00 2001 From: Donald Buczek Date: Wed, 14 Dec 2022 23:47:05 +0100 Subject: [PATCH 13/13] Don't crash if hardlink source is missing --- cmirror.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cmirror.c b/cmirror.c index 967235d..c625d05 100644 --- a/cmirror.c +++ b/cmirror.c @@ -765,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)