diff --git a/backport-build-To-adjust-the-directory-structure.patch b/backport-build-To-adjust-the-directory-structure.patch new file mode 100644 index 0000000..2cd9a28 --- /dev/null +++ b/backport-build-To-adjust-the-directory-structure.patch @@ -0,0 +1,613 @@ +From 3c91ed36496fa7cab722cdc3646781c873242034 Mon Sep 17 00:00:00 2001 +From: overweight +Date: Wed, 5 Jul 2023 10:53:20 +0800 +Subject: [PATCH] build: To adjust the directory structure + +--- + Cargo.toml | 12 ++++++++---- + core/{lib => libsysmaster}/error.rs | 0 + core/{lib => libsysmaster}/exec/base.rs | 0 + core/{lib => libsysmaster}/exec/cmd.rs | 0 + core/{lib => libsysmaster}/exec/mod.rs | 0 + core/{lib => libsysmaster}/lib.rs | 0 + core/{lib => libsysmaster}/rel/api.rs | 0 + core/{lib => libsysmaster}/rel/base.rs | 0 + core/{lib => libsysmaster}/rel/enable.rs | 0 + core/{lib => libsysmaster}/rel/history.rs | 0 + core/{lib => libsysmaster}/rel/last.rs | 0 + core/{lib => libsysmaster}/rel/mod.rs | 0 + core/{lib => libsysmaster}/rel/pending.rs | 0 + core/{lib => libsysmaster}/rel/station.rs | 0 + core/{lib => libsysmaster}/serialize.rs | 0 + core/{lib => libsysmaster}/unit/base.rs | 0 + core/{lib => libsysmaster}/unit/deps.rs | 0 + core/{lib => libsysmaster}/unit/kill.rs | 0 + core/{lib => libsysmaster}/unit/mod.rs | 0 + core/{lib => libsysmaster}/unit/state.rs | 0 + core/{lib => libsysmaster}/unit/umif.rs | 0 + core/{lib => libsysmaster}/utils/fd.rs | 0 + core/{lib => libsysmaster}/utils/mod.rs | 0 + {exts/sctl/src => core/sctl}/main.rs | 0 + core/{bin => sysmaster}/job/alloc.rs | 0 + core/{bin => sysmaster}/job/entry.rs | 0 + core/{bin => sysmaster}/job/junit.rs | 0 + core/{bin => sysmaster}/job/manager.rs | 0 + core/{bin => sysmaster}/job/mod.rs | 0 + core/{bin => sysmaster}/job/notify.rs | 0 + core/{bin => sysmaster}/job/rentry.rs | 0 + core/{bin => sysmaster}/job/stat.rs | 0 + core/{bin => sysmaster}/job/table.rs | 0 + core/{bin => sysmaster}/job/transaction.rs | 0 + core/{bin => sysmaster}/keep_alive/mod.rs | 0 + core/{bin => sysmaster}/main.rs | 0 + core/{bin => sysmaster}/manager/alive_timer.rs | 0 + core/{bin => sysmaster}/manager/commands.rs | 0 + core/{bin => sysmaster}/manager/config.rs | 0 + core/{bin => sysmaster}/manager/mod.rs | 0 + core/{bin => sysmaster}/manager/pre_install.rs | 0 + core/{bin => sysmaster}/manager/rentry.rs | 0 + core/{bin => sysmaster}/manager/signals.rs | 0 + core/{bin => sysmaster}/mount/mod.rs | 0 + core/{bin => sysmaster}/mount/setup.rs | 0 + core/{bin => sysmaster}/plugin/mod.rs | 0 + core/{bin => sysmaster}/unit/base/load.rs | 0 + core/{bin => sysmaster}/unit/base/mod.rs | 0 + core/{bin => sysmaster}/unit/base/relation.rs | 0 + core/{bin => sysmaster}/unit/base/relation_atom.rs | 0 + core/{bin => sysmaster}/unit/data/dep_conf.rs | 0 + core/{bin => sysmaster}/unit/data/mod.rs | 0 + core/{bin => sysmaster}/unit/data/state.rs | 0 + core/{bin => sysmaster}/unit/data/table.rs | 0 + core/{bin => sysmaster}/unit/datastore/child.rs | 0 + core/{bin => sysmaster}/unit/datastore/deps.rs | 0 + core/{bin => sysmaster}/unit/datastore/mod.rs | 0 + core/{bin => sysmaster}/unit/datastore/sets.rs | 0 + core/{bin => sysmaster}/unit/entry/base.rs | 0 + core/{bin => sysmaster}/unit/entry/cgroup.rs | 0 + core/{bin => sysmaster}/unit/entry/child.rs | 0 + core/{bin => sysmaster}/unit/entry/condition.rs | 0 + core/{bin => sysmaster}/unit/entry/config.rs | 0 + core/{bin => sysmaster}/unit/entry/load.rs | 0 + core/{bin => sysmaster}/unit/entry/mod.rs | 0 + core/{bin => sysmaster}/unit/entry/ratelimit.rs | 0 + core/{bin => sysmaster}/unit/entry/uentry.rs | 0 + core/{bin => sysmaster}/unit/entry/unitx.rs | 0 + core/{bin => sysmaster}/unit/execute/mod.rs | 0 + core/{bin => sysmaster}/unit/execute/spawn.rs | 0 + core/{bin => sysmaster}/unit/manager.rs | 0 + core/{bin => sysmaster}/unit/mod.rs | 0 + core/{bin => sysmaster}/unit/notify.rs | 0 + core/{bin => sysmaster}/unit/rentry.rs | 0 + core/{bin => sysmaster}/unit/runtime.rs | 0 + core/{bin => sysmaster}/unit/sigchld.rs | 0 + core/{bin => sysmaster}/unit/test/mod.rs | 0 + core/{bin => sysmaster}/unit/uload.rs | 0 + core/{bin => sysmaster}/unit/util/mod.rs | 0 + core/{bin => sysmaster}/unit/util/unit_file.rs | 0 + core/{bin => sysmaster}/utils/mod.rs | 0 + core/{bin => sysmaster}/utils/table.rs | 0 + exts/sctl/Cargo.toml | 13 ------------- + {exts/init => init}/Cargo.toml | 2 +- + {exts/init => init}/src/main.rs | 0 + {exts/init => init}/src/runtime/comm.rs | 0 + {exts/init => init}/src/runtime/epoll.rs | 0 + {exts/init => init}/src/runtime/mod.rs | 0 + {exts/init => init}/src/runtime/param.rs | 0 + {exts/init => init}/src/runtime/signals.rs | 0 + {exts/init => init}/src/runtime/timer.rs | 0 + 91 files changed, 9 insertions(+), 18 deletions(-) + rename core/{lib => libsysmaster}/error.rs (100%) + rename core/{lib => libsysmaster}/exec/base.rs (100%) + rename core/{lib => libsysmaster}/exec/cmd.rs (100%) + rename core/{lib => libsysmaster}/exec/mod.rs (100%) + rename core/{lib => libsysmaster}/lib.rs (100%) + rename core/{lib => libsysmaster}/rel/api.rs (100%) + rename core/{lib => libsysmaster}/rel/base.rs (100%) + rename core/{lib => libsysmaster}/rel/enable.rs (100%) + rename core/{lib => libsysmaster}/rel/history.rs (100%) + rename core/{lib => libsysmaster}/rel/last.rs (100%) + rename core/{lib => libsysmaster}/rel/mod.rs (100%) + rename core/{lib => libsysmaster}/rel/pending.rs (100%) + rename core/{lib => libsysmaster}/rel/station.rs (100%) + rename core/{lib => libsysmaster}/serialize.rs (100%) + rename core/{lib => libsysmaster}/unit/base.rs (100%) + rename core/{lib => libsysmaster}/unit/deps.rs (100%) + rename core/{lib => libsysmaster}/unit/kill.rs (100%) + rename core/{lib => libsysmaster}/unit/mod.rs (100%) + rename core/{lib => libsysmaster}/unit/state.rs (100%) + rename core/{lib => libsysmaster}/unit/umif.rs (100%) + rename core/{lib => libsysmaster}/utils/fd.rs (100%) + rename core/{lib => libsysmaster}/utils/mod.rs (100%) + rename {exts/sctl/src => core/sctl}/main.rs (100%) + rename core/{bin => sysmaster}/job/alloc.rs (100%) + rename core/{bin => sysmaster}/job/entry.rs (100%) + rename core/{bin => sysmaster}/job/junit.rs (100%) + rename core/{bin => sysmaster}/job/manager.rs (100%) + rename core/{bin => sysmaster}/job/mod.rs (100%) + rename core/{bin => sysmaster}/job/notify.rs (100%) + rename core/{bin => sysmaster}/job/rentry.rs (100%) + rename core/{bin => sysmaster}/job/stat.rs (100%) + rename core/{bin => sysmaster}/job/table.rs (100%) + rename core/{bin => sysmaster}/job/transaction.rs (100%) + rename core/{bin => sysmaster}/keep_alive/mod.rs (100%) + rename core/{bin => sysmaster}/main.rs (100%) + rename core/{bin => sysmaster}/manager/alive_timer.rs (100%) + rename core/{bin => sysmaster}/manager/commands.rs (100%) + rename core/{bin => sysmaster}/manager/config.rs (100%) + rename core/{bin => sysmaster}/manager/mod.rs (100%) + rename core/{bin => sysmaster}/manager/pre_install.rs (100%) + rename core/{bin => sysmaster}/manager/rentry.rs (100%) + rename core/{bin => sysmaster}/manager/signals.rs (100%) + rename core/{bin => sysmaster}/mount/mod.rs (100%) + rename core/{bin => sysmaster}/mount/setup.rs (100%) + rename core/{bin => sysmaster}/plugin/mod.rs (100%) + rename core/{bin => sysmaster}/unit/base/load.rs (100%) + rename core/{bin => sysmaster}/unit/base/mod.rs (100%) + rename core/{bin => sysmaster}/unit/base/relation.rs (100%) + rename core/{bin => sysmaster}/unit/base/relation_atom.rs (100%) + rename core/{bin => sysmaster}/unit/data/dep_conf.rs (100%) + rename core/{bin => sysmaster}/unit/data/mod.rs (100%) + rename core/{bin => sysmaster}/unit/data/state.rs (100%) + rename core/{bin => sysmaster}/unit/data/table.rs (100%) + rename core/{bin => sysmaster}/unit/datastore/child.rs (100%) + rename core/{bin => sysmaster}/unit/datastore/deps.rs (100%) + rename core/{bin => sysmaster}/unit/datastore/mod.rs (100%) + rename core/{bin => sysmaster}/unit/datastore/sets.rs (100%) + rename core/{bin => sysmaster}/unit/entry/base.rs (100%) + rename core/{bin => sysmaster}/unit/entry/cgroup.rs (100%) + rename core/{bin => sysmaster}/unit/entry/child.rs (100%) + rename core/{bin => sysmaster}/unit/entry/condition.rs (100%) + rename core/{bin => sysmaster}/unit/entry/config.rs (100%) + rename core/{bin => sysmaster}/unit/entry/load.rs (100%) + rename core/{bin => sysmaster}/unit/entry/mod.rs (100%) + rename core/{bin => sysmaster}/unit/entry/ratelimit.rs (100%) + rename core/{bin => sysmaster}/unit/entry/uentry.rs (100%) + rename core/{bin => sysmaster}/unit/entry/unitx.rs (100%) + rename core/{bin => sysmaster}/unit/execute/mod.rs (100%) + rename core/{bin => sysmaster}/unit/execute/spawn.rs (100%) + rename core/{bin => sysmaster}/unit/manager.rs (100%) + rename core/{bin => sysmaster}/unit/mod.rs (100%) + rename core/{bin => sysmaster}/unit/notify.rs (100%) + rename core/{bin => sysmaster}/unit/rentry.rs (100%) + rename core/{bin => sysmaster}/unit/runtime.rs (100%) + rename core/{bin => sysmaster}/unit/sigchld.rs (100%) + rename core/{bin => sysmaster}/unit/test/mod.rs (100%) + rename core/{bin => sysmaster}/unit/uload.rs (100%) + rename core/{bin => sysmaster}/unit/util/mod.rs (100%) + rename core/{bin => sysmaster}/unit/util/unit_file.rs (100%) + rename core/{bin => sysmaster}/utils/mod.rs (100%) + rename core/{bin => sysmaster}/utils/table.rs (100%) + delete mode 100644 exts/sctl/Cargo.toml + rename {exts/init => init}/Cargo.toml (81%) + rename {exts/init => init}/src/main.rs (100%) + rename {exts/init => init}/src/runtime/comm.rs (100%) + rename {exts/init => init}/src/runtime/epoll.rs (100%) + rename {exts/init => init}/src/runtime/mod.rs (100%) + rename {exts/init => init}/src/runtime/param.rs (100%) + rename {exts/init => init}/src/runtime/signals.rs (100%) + rename {exts/init => init}/src/runtime/timer.rs (100%) + +diff --git a/Cargo.toml b/Cargo.toml +index 089e7ab..f97be77 100644 +--- a/Cargo.toml ++++ b/Cargo.toml +@@ -7,12 +7,16 @@ build = "build.rs" + + [lib] + name = "sysmaster" +-path = "core/lib/lib.rs" ++path = "core/libsysmaster/lib.rs" + + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + [[bin]] + name = "sysmaster" +-path = "core/bin/main.rs" ++path = "core/sysmaster/main.rs" ++ ++[[bin]] ++name = "sctl" ++path = "core/sctl/main.rs" + + [dev-dependencies.libtests] + path = "libs/libtests" +@@ -111,9 +111,9 @@ overflow-checks = false + + [workspace] + members = [ ++ # sysmaster-init ++ "init", + # external binaries +- "exts/init", +- "exts/sctl", + "exts/hostname_setup", + #internal libraries crates + "libs/cmdproto", +diff --git a/core/lib/error.rs b/core/libsysmaster/error.rs +similarity index 100% +rename from core/lib/error.rs +rename to core/libsysmaster/error.rs +diff --git a/core/lib/exec/base.rs b/core/libsysmaster/exec/base.rs +similarity index 100% +rename from core/lib/exec/base.rs +rename to core/libsysmaster/exec/base.rs +diff --git a/core/lib/exec/cmd.rs b/core/libsysmaster/exec/cmd.rs +similarity index 100% +rename from core/lib/exec/cmd.rs +rename to core/libsysmaster/exec/cmd.rs +diff --git a/core/lib/exec/mod.rs b/core/libsysmaster/exec/mod.rs +similarity index 100% +rename from core/lib/exec/mod.rs +rename to core/libsysmaster/exec/mod.rs +diff --git a/core/lib/lib.rs b/core/libsysmaster/lib.rs +similarity index 100% +rename from core/lib/lib.rs +rename to core/libsysmaster/lib.rs +diff --git a/core/lib/rel/api.rs b/core/libsysmaster/rel/api.rs +similarity index 100% +rename from core/lib/rel/api.rs +rename to core/libsysmaster/rel/api.rs +diff --git a/core/lib/rel/base.rs b/core/libsysmaster/rel/base.rs +similarity index 100% +rename from core/lib/rel/base.rs +rename to core/libsysmaster/rel/base.rs +diff --git a/core/lib/rel/enable.rs b/core/libsysmaster/rel/enable.rs +similarity index 100% +rename from core/lib/rel/enable.rs +rename to core/libsysmaster/rel/enable.rs +diff --git a/core/lib/rel/history.rs b/core/libsysmaster/rel/history.rs +similarity index 100% +rename from core/lib/rel/history.rs +rename to core/libsysmaster/rel/history.rs +diff --git a/core/lib/rel/last.rs b/core/libsysmaster/rel/last.rs +similarity index 100% +rename from core/lib/rel/last.rs +rename to core/libsysmaster/rel/last.rs +diff --git a/core/lib/rel/mod.rs b/core/libsysmaster/rel/mod.rs +similarity index 100% +rename from core/lib/rel/mod.rs +rename to core/libsysmaster/rel/mod.rs +diff --git a/core/lib/rel/pending.rs b/core/libsysmaster/rel/pending.rs +similarity index 100% +rename from core/lib/rel/pending.rs +rename to core/libsysmaster/rel/pending.rs +diff --git a/core/lib/rel/station.rs b/core/libsysmaster/rel/station.rs +similarity index 100% +rename from core/lib/rel/station.rs +rename to core/libsysmaster/rel/station.rs +diff --git a/core/lib/serialize.rs b/core/libsysmaster/serialize.rs +similarity index 100% +rename from core/lib/serialize.rs +rename to core/libsysmaster/serialize.rs +diff --git a/core/lib/unit/base.rs b/core/libsysmaster/unit/base.rs +similarity index 100% +rename from core/lib/unit/base.rs +rename to core/libsysmaster/unit/base.rs +diff --git a/core/lib/unit/deps.rs b/core/libsysmaster/unit/deps.rs +similarity index 100% +rename from core/lib/unit/deps.rs +rename to core/libsysmaster/unit/deps.rs +diff --git a/core/lib/unit/kill.rs b/core/libsysmaster/unit/kill.rs +similarity index 100% +rename from core/lib/unit/kill.rs +rename to core/libsysmaster/unit/kill.rs +diff --git a/core/lib/unit/mod.rs b/core/libsysmaster/unit/mod.rs +similarity index 100% +rename from core/lib/unit/mod.rs +rename to core/libsysmaster/unit/mod.rs +diff --git a/core/lib/unit/state.rs b/core/libsysmaster/unit/state.rs +similarity index 100% +rename from core/lib/unit/state.rs +rename to core/libsysmaster/unit/state.rs +diff --git a/core/lib/unit/umif.rs b/core/libsysmaster/unit/umif.rs +similarity index 100% +rename from core/lib/unit/umif.rs +rename to core/libsysmaster/unit/umif.rs +diff --git a/core/lib/utils/fd.rs b/core/libsysmaster/utils/fd.rs +similarity index 100% +rename from core/lib/utils/fd.rs +rename to core/libsysmaster/utils/fd.rs +diff --git a/core/lib/utils/mod.rs b/core/libsysmaster/utils/mod.rs +similarity index 100% +rename from core/lib/utils/mod.rs +rename to core/libsysmaster/utils/mod.rs +diff --git a/exts/sctl/src/main.rs b/core/sctl/main.rs +similarity index 100% +rename from exts/sctl/src/main.rs +rename to core/sctl/main.rs +diff --git a/core/bin/job/alloc.rs b/core/sysmaster/job/alloc.rs +similarity index 100% +rename from core/bin/job/alloc.rs +rename to core/sysmaster/job/alloc.rs +diff --git a/core/bin/job/entry.rs b/core/sysmaster/job/entry.rs +similarity index 100% +rename from core/bin/job/entry.rs +rename to core/sysmaster/job/entry.rs +diff --git a/core/bin/job/junit.rs b/core/sysmaster/job/junit.rs +similarity index 100% +rename from core/bin/job/junit.rs +rename to core/sysmaster/job/junit.rs +diff --git a/core/bin/job/manager.rs b/core/sysmaster/job/manager.rs +similarity index 100% +rename from core/bin/job/manager.rs +rename to core/sysmaster/job/manager.rs +diff --git a/core/bin/job/mod.rs b/core/sysmaster/job/mod.rs +similarity index 100% +rename from core/bin/job/mod.rs +rename to core/sysmaster/job/mod.rs +diff --git a/core/bin/job/notify.rs b/core/sysmaster/job/notify.rs +similarity index 100% +rename from core/bin/job/notify.rs +rename to core/sysmaster/job/notify.rs +diff --git a/core/bin/job/rentry.rs b/core/sysmaster/job/rentry.rs +similarity index 100% +rename from core/bin/job/rentry.rs +rename to core/sysmaster/job/rentry.rs +diff --git a/core/bin/job/stat.rs b/core/sysmaster/job/stat.rs +similarity index 100% +rename from core/bin/job/stat.rs +rename to core/sysmaster/job/stat.rs +diff --git a/core/bin/job/table.rs b/core/sysmaster/job/table.rs +similarity index 100% +rename from core/bin/job/table.rs +rename to core/sysmaster/job/table.rs +diff --git a/core/bin/job/transaction.rs b/core/sysmaster/job/transaction.rs +similarity index 100% +rename from core/bin/job/transaction.rs +rename to core/sysmaster/job/transaction.rs +diff --git a/core/bin/keep_alive/mod.rs b/core/sysmaster/keep_alive/mod.rs +similarity index 100% +rename from core/bin/keep_alive/mod.rs +rename to core/sysmaster/keep_alive/mod.rs +diff --git a/core/bin/main.rs b/core/sysmaster/main.rs +similarity index 100% +rename from core/bin/main.rs +rename to core/sysmaster/main.rs +diff --git a/core/bin/manager/alive_timer.rs b/core/sysmaster/manager/alive_timer.rs +similarity index 100% +rename from core/bin/manager/alive_timer.rs +rename to core/sysmaster/manager/alive_timer.rs +diff --git a/core/bin/manager/commands.rs b/core/sysmaster/manager/commands.rs +similarity index 100% +rename from core/bin/manager/commands.rs +rename to core/sysmaster/manager/commands.rs +diff --git a/core/bin/manager/config.rs b/core/sysmaster/manager/config.rs +similarity index 100% +rename from core/bin/manager/config.rs +rename to core/sysmaster/manager/config.rs +diff --git a/core/bin/manager/mod.rs b/core/sysmaster/manager/mod.rs +similarity index 100% +rename from core/bin/manager/mod.rs +rename to core/sysmaster/manager/mod.rs +diff --git a/core/bin/manager/pre_install.rs b/core/sysmaster/manager/pre_install.rs +similarity index 100% +rename from core/bin/manager/pre_install.rs +rename to core/sysmaster/manager/pre_install.rs +diff --git a/core/bin/manager/rentry.rs b/core/sysmaster/manager/rentry.rs +similarity index 100% +rename from core/bin/manager/rentry.rs +rename to core/sysmaster/manager/rentry.rs +diff --git a/core/bin/manager/signals.rs b/core/sysmaster/manager/signals.rs +similarity index 100% +rename from core/bin/manager/signals.rs +rename to core/sysmaster/manager/signals.rs +diff --git a/core/bin/mount/mod.rs b/core/sysmaster/mount/mod.rs +similarity index 100% +rename from core/bin/mount/mod.rs +rename to core/sysmaster/mount/mod.rs +diff --git a/core/bin/mount/setup.rs b/core/sysmaster/mount/setup.rs +similarity index 100% +rename from core/bin/mount/setup.rs +rename to core/sysmaster/mount/setup.rs +diff --git a/core/bin/plugin/mod.rs b/core/sysmaster/plugin/mod.rs +similarity index 100% +rename from core/bin/plugin/mod.rs +rename to core/sysmaster/plugin/mod.rs +diff --git a/core/bin/unit/base/load.rs b/core/sysmaster/unit/base/load.rs +similarity index 100% +rename from core/bin/unit/base/load.rs +rename to core/sysmaster/unit/base/load.rs +diff --git a/core/bin/unit/base/mod.rs b/core/sysmaster/unit/base/mod.rs +similarity index 100% +rename from core/bin/unit/base/mod.rs +rename to core/sysmaster/unit/base/mod.rs +diff --git a/core/bin/unit/base/relation.rs b/core/sysmaster/unit/base/relation.rs +similarity index 100% +rename from core/bin/unit/base/relation.rs +rename to core/sysmaster/unit/base/relation.rs +diff --git a/core/bin/unit/base/relation_atom.rs b/core/sysmaster/unit/base/relation_atom.rs +similarity index 100% +rename from core/bin/unit/base/relation_atom.rs +rename to core/sysmaster/unit/base/relation_atom.rs +diff --git a/core/bin/unit/data/dep_conf.rs b/core/sysmaster/unit/data/dep_conf.rs +similarity index 100% +rename from core/bin/unit/data/dep_conf.rs +rename to core/sysmaster/unit/data/dep_conf.rs +diff --git a/core/bin/unit/data/mod.rs b/core/sysmaster/unit/data/mod.rs +similarity index 100% +rename from core/bin/unit/data/mod.rs +rename to core/sysmaster/unit/data/mod.rs +diff --git a/core/bin/unit/data/state.rs b/core/sysmaster/unit/data/state.rs +similarity index 100% +rename from core/bin/unit/data/state.rs +rename to core/sysmaster/unit/data/state.rs +diff --git a/core/bin/unit/data/table.rs b/core/sysmaster/unit/data/table.rs +similarity index 100% +rename from core/bin/unit/data/table.rs +rename to core/sysmaster/unit/data/table.rs +diff --git a/core/bin/unit/datastore/child.rs b/core/sysmaster/unit/datastore/child.rs +similarity index 100% +rename from core/bin/unit/datastore/child.rs +rename to core/sysmaster/unit/datastore/child.rs +diff --git a/core/bin/unit/datastore/deps.rs b/core/sysmaster/unit/datastore/deps.rs +similarity index 100% +rename from core/bin/unit/datastore/deps.rs +rename to core/sysmaster/unit/datastore/deps.rs +diff --git a/core/bin/unit/datastore/mod.rs b/core/sysmaster/unit/datastore/mod.rs +similarity index 100% +rename from core/bin/unit/datastore/mod.rs +rename to core/sysmaster/unit/datastore/mod.rs +diff --git a/core/bin/unit/datastore/sets.rs b/core/sysmaster/unit/datastore/sets.rs +similarity index 100% +rename from core/bin/unit/datastore/sets.rs +rename to core/sysmaster/unit/datastore/sets.rs +diff --git a/core/bin/unit/entry/base.rs b/core/sysmaster/unit/entry/base.rs +similarity index 100% +rename from core/bin/unit/entry/base.rs +rename to core/sysmaster/unit/entry/base.rs +diff --git a/core/bin/unit/entry/cgroup.rs b/core/sysmaster/unit/entry/cgroup.rs +similarity index 100% +rename from core/bin/unit/entry/cgroup.rs +rename to core/sysmaster/unit/entry/cgroup.rs +diff --git a/core/bin/unit/entry/child.rs b/core/sysmaster/unit/entry/child.rs +similarity index 100% +rename from core/bin/unit/entry/child.rs +rename to core/sysmaster/unit/entry/child.rs +diff --git a/core/bin/unit/entry/condition.rs b/core/sysmaster/unit/entry/condition.rs +similarity index 100% +rename from core/bin/unit/entry/condition.rs +rename to core/sysmaster/unit/entry/condition.rs +diff --git a/core/bin/unit/entry/config.rs b/core/sysmaster/unit/entry/config.rs +similarity index 100% +rename from core/bin/unit/entry/config.rs +rename to core/sysmaster/unit/entry/config.rs +diff --git a/core/bin/unit/entry/load.rs b/core/sysmaster/unit/entry/load.rs +similarity index 100% +rename from core/bin/unit/entry/load.rs +rename to core/sysmaster/unit/entry/load.rs +diff --git a/core/bin/unit/entry/mod.rs b/core/sysmaster/unit/entry/mod.rs +similarity index 100% +rename from core/bin/unit/entry/mod.rs +rename to core/sysmaster/unit/entry/mod.rs +diff --git a/core/bin/unit/entry/ratelimit.rs b/core/sysmaster/unit/entry/ratelimit.rs +similarity index 100% +rename from core/bin/unit/entry/ratelimit.rs +rename to core/sysmaster/unit/entry/ratelimit.rs +diff --git a/core/bin/unit/entry/uentry.rs b/core/sysmaster/unit/entry/uentry.rs +similarity index 100% +rename from core/bin/unit/entry/uentry.rs +rename to core/sysmaster/unit/entry/uentry.rs +diff --git a/core/bin/unit/entry/unitx.rs b/core/sysmaster/unit/entry/unitx.rs +similarity index 100% +rename from core/bin/unit/entry/unitx.rs +rename to core/sysmaster/unit/entry/unitx.rs +diff --git a/core/bin/unit/execute/mod.rs b/core/sysmaster/unit/execute/mod.rs +similarity index 100% +rename from core/bin/unit/execute/mod.rs +rename to core/sysmaster/unit/execute/mod.rs +diff --git a/core/bin/unit/execute/spawn.rs b/core/sysmaster/unit/execute/spawn.rs +similarity index 100% +rename from core/bin/unit/execute/spawn.rs +rename to core/sysmaster/unit/execute/spawn.rs +diff --git a/core/bin/unit/manager.rs b/core/sysmaster/unit/manager.rs +similarity index 100% +rename from core/bin/unit/manager.rs +rename to core/sysmaster/unit/manager.rs +diff --git a/core/bin/unit/mod.rs b/core/sysmaster/unit/mod.rs +similarity index 100% +rename from core/bin/unit/mod.rs +rename to core/sysmaster/unit/mod.rs +diff --git a/core/bin/unit/notify.rs b/core/sysmaster/unit/notify.rs +similarity index 100% +rename from core/bin/unit/notify.rs +rename to core/sysmaster/unit/notify.rs +diff --git a/core/bin/unit/rentry.rs b/core/sysmaster/unit/rentry.rs +similarity index 100% +rename from core/bin/unit/rentry.rs +rename to core/sysmaster/unit/rentry.rs +diff --git a/core/bin/unit/runtime.rs b/core/sysmaster/unit/runtime.rs +similarity index 100% +rename from core/bin/unit/runtime.rs +rename to core/sysmaster/unit/runtime.rs +diff --git a/core/bin/unit/sigchld.rs b/core/sysmaster/unit/sigchld.rs +similarity index 100% +rename from core/bin/unit/sigchld.rs +rename to core/sysmaster/unit/sigchld.rs +diff --git a/core/bin/unit/test/mod.rs b/core/sysmaster/unit/test/mod.rs +similarity index 100% +rename from core/bin/unit/test/mod.rs +rename to core/sysmaster/unit/test/mod.rs +diff --git a/core/bin/unit/uload.rs b/core/sysmaster/unit/uload.rs +similarity index 100% +rename from core/bin/unit/uload.rs +rename to core/sysmaster/unit/uload.rs +diff --git a/core/bin/unit/util/mod.rs b/core/sysmaster/unit/util/mod.rs +similarity index 100% +rename from core/bin/unit/util/mod.rs +rename to core/sysmaster/unit/util/mod.rs +diff --git a/core/bin/unit/util/unit_file.rs b/core/sysmaster/unit/util/unit_file.rs +similarity index 100% +rename from core/bin/unit/util/unit_file.rs +rename to core/sysmaster/unit/util/unit_file.rs +diff --git a/core/bin/utils/mod.rs b/core/sysmaster/utils/mod.rs +similarity index 100% +rename from core/bin/utils/mod.rs +rename to core/sysmaster/utils/mod.rs +diff --git a/core/bin/utils/table.rs b/core/sysmaster/utils/table.rs +similarity index 100% +rename from core/bin/utils/table.rs +rename to core/sysmaster/utils/table.rs +diff --git a/exts/sctl/Cargo.toml b/exts/sctl/Cargo.toml +deleted file mode 100644 +index 21c00c7..0000000 +--- a/exts/sctl/Cargo.toml ++++ /dev/null +@@ -1,13 +0,0 @@ +-[package] +-name = "sctl" +-version = "0.2.4" +-edition = "2021" +- +-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +- +-[dependencies] +-clap = { version = "3.1.8", features = ["derive"] } +-cmdproto = { path = "../../libs/cmdproto" } +-basic = { path = "../../libs/basic" } +-nix = "0.24" +-constants = { path = "../../libs/constants" } +diff --git a/exts/init/Cargo.toml b/init/Cargo.toml +similarity index 81% +rename from exts/init/Cargo.toml +rename to init/Cargo.toml +index f72b52a..6dcfb61 100644 +--- a/exts/init/Cargo.toml ++++ b/init/Cargo.toml +@@ -6,6 +6,6 @@ edition = "2021" + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + [dependencies] +-constants = { path = "../../libs/constants" } ++constants = { path = "../libs/constants" } + libc = "0.2.*" + nix = "0.24" +diff --git a/exts/init/src/main.rs b/init/src/main.rs +similarity index 100% +rename from exts/init/src/main.rs +rename to init/src/main.rs +diff --git a/exts/init/src/runtime/comm.rs b/init/src/runtime/comm.rs +similarity index 100% +rename from exts/init/src/runtime/comm.rs +rename to init/src/runtime/comm.rs +diff --git a/exts/init/src/runtime/epoll.rs b/init/src/runtime/epoll.rs +similarity index 100% +rename from exts/init/src/runtime/epoll.rs +rename to init/src/runtime/epoll.rs +diff --git a/exts/init/src/runtime/mod.rs b/init/src/runtime/mod.rs +similarity index 100% +rename from exts/init/src/runtime/mod.rs +rename to init/src/runtime/mod.rs +diff --git a/exts/init/src/runtime/param.rs b/init/src/runtime/param.rs +similarity index 100% +rename from exts/init/src/runtime/param.rs +rename to init/src/runtime/param.rs +diff --git a/exts/init/src/runtime/signals.rs b/init/src/runtime/signals.rs +similarity index 100% +rename from exts/init/src/runtime/signals.rs +rename to init/src/runtime/signals.rs +diff --git a/exts/init/src/runtime/timer.rs b/init/src/runtime/timer.rs +similarity index 100% +rename from exts/init/src/runtime/timer.rs +rename to init/src/runtime/timer.rs +-- +2.33.0 + diff --git a/backport-build-update-version-to-0.2.4.patch b/backport-build-update-version-to-0.2.4.patch new file mode 100644 index 0000000..c567196 --- /dev/null +++ b/backport-build-update-version-to-0.2.4.patch @@ -0,0 +1,198 @@ +From af5f8417e595d7155b343efdbc63d6c337102058 Mon Sep 17 00:00:00 2001 +From: overweight +Date: Wed, 5 Jul 2023 10:51:21 +0800 +Subject: [PATCH] build: update version to 0.2.4 + +--- + Cargo.toml | 2 +- + coms/service/Cargo.toml | 2 +- + coms/target/Cargo.toml | 2 +- + exts/hostname_setup/Cargo.toml | 4 ++-- + exts/init/Cargo.toml | 4 ++-- + exts/sctl/Cargo.toml | 4 ++-- + libs/basic/Cargo.toml | 2 +- + libs/cgroup/Cargo.toml | 2 +- + libs/constants/Cargo.toml | 2 +- + libs/event/Cargo.toml | 2 +- + libs/libtests/Cargo.toml | 2 +- + libs/macros/Cargo.toml | 2 +- + libs/watchdog/Cargo.toml | 2 +- + 23 files changed, 28 insertions(+), 28 deletions(-) + +diff --git a/Cargo.toml b/Cargo.toml +index 89efa33..089e7ab 100644 +--- a/Cargo.toml ++++ b/Cargo.toml +@@ -1,6 +1,6 @@ + [package] + name = "sysmaster" +-version = "0.2.2" ++version = "0.2.4" + authors = ["sysmaster"] + edition = "2021" + build = "build.rs" +diff --git a/coms/service/Cargo.toml b/coms/service/Cargo.toml +index e87706e..0f37cf8 100644 +--- a/coms/service/Cargo.toml ++++ b/coms/service/Cargo.toml +@@ -1,6 +1,6 @@ + [package] + name = "service" +-version = "0.1.0" ++version = "0.2.4" + edition = "2021" + + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +diff --git a/coms/target/Cargo.toml b/coms/target/Cargo.toml +index 69d8bda..7223879 100644 +--- a/coms/target/Cargo.toml ++++ b/coms/target/Cargo.toml +@@ -1,6 +1,6 @@ + [package] + name = "target" +-version = "0.1.0" ++version = "0.2.4" + edition = "2021" + + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +diff --git a/exts/hostname_setup/Cargo.toml b/exts/hostname_setup/Cargo.toml +index b2cbdcf..0758da6 100644 +--- a/exts/hostname_setup/Cargo.toml ++++ b/exts/hostname_setup/Cargo.toml +@@ -1,11 +1,11 @@ + [package] + name = "hostname_setup" +-version = "0.1.0" ++version = "0.2.4" + edition = "2021" + + [dependencies] + nix = "0.24" + log = "0.4" + libc = "0.2.*" +-constants = { version = "0.1.0", path = "../../libs/constants" } ++constants = { path = "../../libs/constants" } + basic = { path = "../../libs/basic" } +diff --git a/exts/init/Cargo.toml b/exts/init/Cargo.toml +index e351b61..f72b52a 100644 +--- a/exts/init/Cargo.toml ++++ b/exts/init/Cargo.toml +@@ -1,11 +1,11 @@ + [package] + name = "init" +-version = "0.1.0" ++version = "0.2.4" + edition = "2021" + + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + [dependencies] +-constants = { version = "0.1.0", path = "../../libs/constants" } ++constants = { path = "../../libs/constants" } + libc = "0.2.*" + nix = "0.24" +diff --git a/exts/sctl/Cargo.toml b/exts/sctl/Cargo.toml +index b0c0bfc..21c00c7 100644 +--- a/exts/sctl/Cargo.toml ++++ b/exts/sctl/Cargo.toml +@@ -1,6 +1,6 @@ + [package] + name = "sctl" +-version = "0.1.0" ++version = "0.2.4" + edition = "2021" + + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +@@ -10,4 +10,4 @@ clap = { version = "3.1.8", features = ["derive"] } + cmdproto = { path = "../../libs/cmdproto" } + basic = { path = "../../libs/basic" } + nix = "0.24" +-constants = { version = "0.1.0", path = "../../libs/constants" } ++constants = { path = "../../libs/constants" } +diff --git a/libs/basic/Cargo.toml b/libs/basic/Cargo.toml +index c18991a..3d2c9cc 100644 +--- a/libs/basic/Cargo.toml ++++ b/libs/basic/Cargo.toml +@@ -1,6 +1,6 @@ + [package] + name = "basic" +-version = "0.1.0" ++version = "0.2.4" + authors = ["overweight "] + edition = "2021" + +diff --git a/libs/cgroup/Cargo.toml b/libs/cgroup/Cargo.toml +index c7d17d2..f772c80 100644 +--- a/libs/cgroup/Cargo.toml ++++ b/libs/cgroup/Cargo.toml +@@ -1,6 +1,6 @@ + [package] + name = "cgroup" +-version = "0.1.0" ++version = "0.2.4" + edition = "2021" + + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +diff --git a/libs/constants/Cargo.toml b/libs/constants/Cargo.toml +index 06d8173..f0552de 100644 +--- a/libs/constants/Cargo.toml ++++ b/libs/constants/Cargo.toml +@@ -1,6 +1,6 @@ + [package] + name = "constants" +-version = "0.1.0" ++version = "0.2.4" + edition = "2021" + + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +diff --git a/libs/event/Cargo.toml b/libs/event/Cargo.toml +index 21dad06..8cd9398 100644 +--- a/libs/event/Cargo.toml ++++ b/libs/event/Cargo.toml +@@ -1,6 +1,6 @@ + [package] + name = "event" +-version = "0.1.0" ++version = "0.2.4" + authors = ["overweight "] + edition = "2021" + +diff --git a/libs/libtests/Cargo.toml b/libs/libtests/Cargo.toml +index 0d80f5b..b14166c 100644 +--- a/libs/libtests/Cargo.toml ++++ b/libs/libtests/Cargo.toml +@@ -1,6 +1,6 @@ + [package] + name = "libtests" +-version = "0.1.0" ++version = "0.2.4" + edition = "2021" + + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +diff --git a/libs/macros/Cargo.toml b/libs/macros/Cargo.toml +index 955b94c..e7d178a 100644 +--- a/libs/macros/Cargo.toml ++++ b/libs/macros/Cargo.toml +@@ -1,6 +1,6 @@ + [package] + name = "macros" +-version = "0.1.0" ++version = "0.2.4" + edition = "2021" + + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +diff --git a/libs/watchdog/Cargo.toml b/libs/watchdog/Cargo.toml +index 5583d9a..458b55d 100644 +--- a/libs/watchdog/Cargo.toml ++++ b/libs/watchdog/Cargo.toml +@@ -1,6 +1,6 @@ + [package] + name = "watchdog" +-version = "0.1.0" ++version = "0.2.4" + edition = "2021" + + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +-- +2.33.0 + diff --git a/backport-feature-add-LogFileSize-and-LogFileNumber.patch b/backport-feature-add-LogFileSize-and-LogFileNumber.patch new file mode 100644 index 0000000..901fe8f --- /dev/null +++ b/backport-feature-add-LogFileSize-and-LogFileNumber.patch @@ -0,0 +1,118 @@ +From 4c86ef5908d10a9d6c29c80d39c993fbce0ab99c Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Sun, 25 Jun 2023 14:54:03 +0800 +Subject: [PATCH] feature: add LogFileSize and LogFileNumber + +--- + core/bin/main.rs | 9 +++------ + core/bin/manager/config.rs | 6 ++++++ + core/bin/unit/manager.rs | 16 ++++++++++++++++ + core/lib/unit/umif.rs | 10 ++++++++++ + 5 files changed, 59 insertions(+), 8 deletions(-) + +diff --git a/core/bin/main.rs b/core/bin/main.rs +index 7f163c7..b75ef0b 100644 +--- a/core/bin/main.rs ++++ b/core/bin/main.rs +@@ -82,16 +82,13 @@ fn main() -> Result<()> { + let args = Args::parse(); + + let manager_config = Rc::new(ManagerConfig::new(None)); +- let log_file = if manager_config.LogFile.is_empty() { +- None +- } else { +- Some(manager_config.LogFile.as_str()) +- }; + logger::init_log( + "sysmaster", + manager_config.LogLevel, + &manager_config.LogTarget, +- log_file, ++ &manager_config.LogFile, ++ manager_config.LogFileSize, ++ manager_config.LogFileNumber, + ); + log::info!("sysmaster running in system mode."); + +diff --git a/core/bin/manager/config.rs b/core/bin/manager/config.rs +index 8b7aaab..fc4c028 100644 +--- a/core/bin/manager/config.rs ++++ b/core/bin/manager/config.rs +@@ -30,6 +30,10 @@ pub struct ManagerConfig { + pub LogTarget: String, + #[config(default = "")] + pub LogFile: String, ++ #[config(default = 10240)] ++ pub LogFileSize: u32, ++ #[config(default = 10)] ++ pub LogFileNumber: u32, + + #[config(default = 1048576)] // RELI_HISTORY_MAPSIZE_DEFAULT + pub DbSize: usize, +@@ -55,6 +59,8 @@ impl Default for ManagerConfig { + LogLevel: log::LevelFilter::Debug, + LogTarget: "console".to_string(), + LogFile: String::new(), ++ LogFileSize: 10240, ++ LogFileNumber: 10, + DbSize: RELI_HISTORY_MAPSIZE_DEFAULT, + } + } +diff --git a/core/bin/unit/manager.rs b/core/bin/unit/manager.rs +index 99366fa..492f3f4 100644 +--- a/core/bin/unit/manager.rs ++++ b/core/bin/unit/manager.rs +@@ -475,6 +475,14 @@ impl UmIf for UnitManager { + self.get_log_target() + } + ++ fn get_log_file_size(&self) -> u32 { ++ self.get_log_file_size() ++ } ++ ++ fn get_log_file_number(&self) -> u32 { ++ self.get_log_file_number() ++ } ++ + /// set the service's socket fd + fn service_set_socket_fd(&self, service_name: &str, fd: i32) { + let service = match self.units_get(service_name) { +@@ -1130,6 +1138,14 @@ impl UnitManager { + fn get_log_target(&self) -> &str { + &self.manager_config.LogTarget + } ++ ++ fn get_log_file_size(&self) -> u32 { ++ self.manager_config.LogFileSize ++ } ++ ++ fn get_log_file_number(&self) -> u32 { ++ self.manager_config.LogFileNumber ++ } + } + + impl ReStation for UnitManager { +diff --git a/core/lib/unit/umif.rs b/core/lib/unit/umif.rs +index 049013d..c41c211 100644 +--- a/core/lib/unit/umif.rs ++++ b/core/lib/unit/umif.rs +@@ -195,6 +195,16 @@ pub trait UmIf { + "" + } + ++ /// get the log file size ++ fn get_log_file_size(&self) -> u32 { ++ 0 ++ } ++ ++ /// get the log file number ++ fn get_log_file_number(&self) -> u32 { ++ 0 ++ } ++ + /// get the log target config + fn get_log_target(&self) -> &str { + "" +-- +2.33.0 + diff --git a/backport-feature-devmaster-support-update-device-database-and.patch b/backport-feature-devmaster-support-update-device-database-and.patch new file mode 100644 index 0000000..4c19a10 --- /dev/null +++ b/backport-feature-devmaster-support-update-device-database-and.patch @@ -0,0 +1,138 @@ +From d570a9c740fec2c89f006c83f0cd46cec5e547a8 Mon Sep 17 00:00:00 2001 +From: chenjiayi +Date: Mon, 3 Jul 2023 01:03:39 +0800 +Subject: [PATCH] feature(devmaster): support update device database and tags + +Besides, move the loop device interfaces to libdevice as some test +cases in libdevice need to use loop device. +--- + libs/basic/src/fs_util.rs | 88 +++++- + 9 files changed, 542 insertions(+), 128 deletions(-) + delete mode 100644 exts/devmaster/src/lib/utils/loop_device.rs + +diff --git a/libs/basic/src/fs_util.rs b/libs/basic/src/fs_util.rs +index 8a8f276..413008b 100644 +--- a/libs/basic/src/fs_util.rs ++++ b/libs/basic/src/fs_util.rs +@@ -15,7 +15,7 @@ + use crate::{error::*, format_proc_fd_path}; + use libc::{fchownat, mode_t, timespec, AT_EMPTY_PATH, S_IFLNK, S_IFMT}; + use nix::{ +- fcntl::{readlink, renameat, OFlag}, ++ fcntl::{open, readlink, renameat, OFlag}, + sys::stat::{fstat, Mode}, + unistd::{unlinkat, Gid, Uid, UnlinkatFlags}, + }; +@@ -23,7 +23,7 @@ use pathdiff::diff_paths; + use rand::Rng; + use std::{ + ffi::CString, +- fs::{remove_dir, File}, ++ fs::{create_dir_all, remove_dir, File}, + io::ErrorKind, + os::unix::prelude::{AsRawFd, FromRawFd, PermissionsExt, RawFd}, + path::Path, +@@ -245,13 +245,70 @@ pub fn remove_dir_until(path: &str, stop: &str) -> Result<()> { + Ok(()) + } + ++/// create and open a temporary file ++pub fn open_temporary(path: &str) -> Result<(File, String)> { ++ let tmp_file = format!("{}.{}", path, rand::thread_rng().gen::()); ++ ++ let f = open( ++ tmp_file.as_str(), ++ OFlag::O_CLOEXEC | OFlag::O_NOCTTY | OFlag::O_RDWR | OFlag::O_CREAT | OFlag::O_EXCL, ++ Mode::from_bits(0o644).unwrap(), ++ ) ++ .context(NixSnafu)?; ++ ++ let file = unsafe { File::from_raw_fd(f) }; ++ ++ Ok((file, tmp_file)) ++} ++ ++/// Create a new file based on absolute path. ++pub fn touch_file( ++ path: &str, ++ parents: bool, ++ mode: Option, ++ uid: Option, ++ gid: Option, ++) -> Result { ++ let p = Path::new(path); ++ ++ if parents && p.parent().is_some() { ++ let _ = create_dir_all(p.parent().unwrap()); ++ } ++ ++ let fd = match open( ++ p, ++ OFlag::O_PATH | OFlag::O_CLOEXEC | OFlag::O_NOFOLLOW, ++ Mode::empty(), ++ ) { ++ Ok(n) => n, ++ Err(e) => { ++ if e != nix::Error::ENOENT { ++ return Err(Error::Nix { source: e }); ++ } ++ ++ open( ++ p, ++ OFlag::O_WRONLY | OFlag::O_CREAT | OFlag::O_EXCL | OFlag::O_CLOEXEC, ++ mode.map(|v| Mode::from_bits(v).unwrap_or(Mode::empty())) ++ .unwrap_or(Mode::empty()), ++ ) ++ .context(NixSnafu)? ++ } ++ }; ++ ++ /* The returned value should be explicitly declared, otherwise the file will be closed at once */ ++ let _f = unsafe { File::from_raw_fd(fd) }; ++ ++ fchmod_and_chown(fd, path, mode, uid, gid) ++} ++ + #[cfg(test)] + mod tests { + use super::*; + use crate::fs_util::symlink; +- use nix::unistd::{self}; ++ use nix::unistd::{self, unlink}; + use std::{ +- fs::{create_dir_all, File}, ++ fs::{create_dir_all, remove_file, File}, + os::unix::prelude::MetadataExt, + time::SystemTime, + }; +@@ -369,4 +426,27 @@ mod tests { + assert!(!Path::new("/tmp/test_remove_dir_until_2/test2").exists()); + assert!(Path::new("/tmp/test_remove_dir_until_2/test_file").exists()); + } ++ ++ #[test] ++ fn test_open_temporary() { ++ let (file, name) = open_temporary("test_open_temporary").unwrap(); ++ let p = Path::new(&name); ++ println!("{:?}", p.canonicalize().unwrap()); ++ drop(file); ++ remove_file(name).unwrap(); ++ } ++ ++ #[test] ++ fn test_touch_file() { ++ let _ = unlink("/tmp/test_touch_file/f1"); ++ touch_file("/tmp/test_touch_file/f1", true, Some(0o444), None, None).unwrap(); ++ let p = Path::new("/tmp/test_touch_file/f1"); ++ assert!(p.exists()); ++ let md = p.metadata().unwrap(); ++ assert_eq!(md.mode() & 0o777, 0o444); ++ touch_file("/tmp/test_touch_file/f1", true, Some(0o666), None, None).unwrap(); ++ let md = p.metadata().unwrap(); ++ assert_eq!(md.mode() & 0o777, 0o666); ++ let _ = unlink("/tmp/test_touch_file/f1"); ++ } + } +-- +2.33.0 + diff --git a/backport-feature-libbasic-add-more-error-information.patch b/backport-feature-libbasic-add-more-error-information.patch new file mode 100644 index 0000000..698364b --- /dev/null +++ b/backport-feature-libbasic-add-more-error-information.patch @@ -0,0 +1,38 @@ +From 8bdb2720d1d3a16624b441c5c0c93269e1feb6a2 Mon Sep 17 00:00:00 2001 +From: chenjiayi +Date: Wed, 21 Jun 2023 21:30:08 +0800 +Subject: [PATCH] feature(libbasic): add more error information + +Print error source information in addition. +--- + libs/basic/src/error.rs | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/libs/basic/src/error.rs b/libs/basic/src/error.rs +index 373ee57..2730883 100644 +--- a/libs/basic/src/error.rs ++++ b/libs/basic/src/error.rs +@@ -32,16 +32,16 @@ pub enum Error { + errno: i32, + }, + +- #[snafu(display("Io"))] ++ #[snafu(display("Io: {}", source))] + Io { source: std::io::Error }, + +- #[snafu(display("Errno"))] ++ #[snafu(display("Errno: {}", source))] + Nix { source: nix::Error }, + +- #[snafu(display("Var"))] ++ #[snafu(display("Var: {}", source))] + Var { source: std::env::VarError }, + +- #[snafu(display("procfs"))] ++ #[snafu(display("procfs: {}", source))] + Proc { source: procfs::ProcError }, + + #[snafu(display("Error parsing from string: {}", source))] +-- +2.33.0 + diff --git a/backport-feature-libbasic-add-opendirat.patch b/backport-feature-libbasic-add-opendirat.patch new file mode 100644 index 0000000..c020d6e --- /dev/null +++ b/backport-feature-libbasic-add-opendirat.patch @@ -0,0 +1,86 @@ +From 0b9863bfcb3148247986ead64683bd9add2502fa Mon Sep 17 00:00:00 2001 +From: chenjiayi +Date: Wed, 21 Jun 2023 21:29:27 +0800 +Subject: [PATCH] feature(libbasic): add opendirat + +opendirat is used to open a directory with the directory fd. +--- + libs/basic/src/fd_util.rs | 46 +++++++++++++++++++++++++++++++++++---- + 1 file changed, 42 insertions(+), 4 deletions(-) + +diff --git a/libs/basic/src/fd_util.rs b/libs/basic/src/fd_util.rs +index b397472..0d41966 100644 +--- a/libs/basic/src/fd_util.rs ++++ b/libs/basic/src/fd_util.rs +@@ -14,9 +14,9 @@ + use crate::error::*; + use nix::{ + errno::Errno, +- fcntl::{FcntlArg, FdFlag, OFlag}, ++ fcntl::{openat, FcntlArg, FdFlag, OFlag}, + ioctl_read, +- sys::stat::SFlag, ++ sys::stat::{Mode, SFlag}, + }; + + /// check if the given stat.st_mode is regular file +@@ -157,11 +157,33 @@ pub fn fd_get_diskseq(fd: i32) -> Result { + Ok(diskseq) + } + ++/// open the directory at fd ++pub fn opendirat(dirfd: i32, flags: OFlag) -> Result { ++ let nfd = openat( ++ dirfd, ++ ".", ++ OFlag::O_RDONLY | OFlag::O_NONBLOCK | OFlag::O_DIRECTORY | OFlag::O_CLOEXEC | flags, ++ Mode::empty(), ++ ) ++ .context(NixSnafu)?; ++ ++ nix::dir::Dir::from_fd(nfd).context(NixSnafu) ++} ++ + #[cfg(test)] + mod tests { + use crate::fd_util::{stat_is_char, stat_is_reg}; +- use nix::sys::stat::fstat; +- use std::{fs::File, os::unix::prelude::AsRawFd, path::Path}; ++ use nix::{ ++ fcntl::{open, OFlag}, ++ sys::stat::{fstat, Mode}, ++ }; ++ use std::{ ++ fs::{remove_dir_all, File}, ++ os::unix::prelude::AsRawFd, ++ path::Path, ++ }; ++ ++ use super::opendirat; + + #[test] + fn test_stats() { +@@ -185,4 +207,20 @@ mod tests { + let st = fstat(fd_non_char_file.as_raw_fd()).unwrap(); + assert!(!stat_is_char(st.st_mode)); + } ++ ++ #[test] ++ fn test_opendirat() { ++ std::fs::create_dir_all("/tmp/test_opendirat").unwrap(); ++ File::create("/tmp/test_opendirat/entry0").unwrap(); ++ File::create("/tmp/test_opendirat/entry1").unwrap(); ++ ++ let dirfd = open("/tmp/test_opendirat", OFlag::O_DIRECTORY, Mode::empty()).unwrap(); ++ let mut dir = opendirat(dirfd, OFlag::O_NOFOLLOW).unwrap(); ++ ++ for e in dir.iter() { ++ let _ = e.unwrap(); ++ } ++ ++ remove_dir_all("/tmp/test_opendirat").unwrap(); ++ } + } +-- +2.33.0 + diff --git a/backport-feature-libbasic-add-path_simplify.patch b/backport-feature-libbasic-add-path_simplify.patch new file mode 100644 index 0000000..5f95b1b --- /dev/null +++ b/backport-feature-libbasic-add-path_simplify.patch @@ -0,0 +1,76 @@ +From 292dfedd1d02b2ac4a926a5e32658562a92bd9be Mon Sep 17 00:00:00 2001 +From: chenjiayi +Date: Wed, 21 Jun 2023 21:25:56 +0800 +Subject: [PATCH] feature(libbasic): add path_simplify + +path_simplify is used to remove redundant inner and trailing slashes +and unnecessary dots in path. +--- + libs/basic/src/path_util.rs | 44 ++++++++++++++++++++++++++++++++++++- + 1 file changed, 43 insertions(+), 1 deletion(-) + +diff --git a/libs/basic/src/path_util.rs b/libs/basic/src/path_util.rs +index 4ac9de9..7391615 100644 +--- a/libs/basic/src/path_util.rs ++++ b/libs/basic/src/path_util.rs +@@ -21,9 +21,44 @@ pub fn path_equal(a: &str, b: &str) -> bool { + p_a == p_b + } + ++/// Remove redundant inner and trailing slashes and unnecessary dots to simplify path. ++/// e.g., //foo//.//bar/ becomes /foo/bar ++/// .//foo//.//bar/ becomes foo/bar ++pub fn path_simplify(s: &str) -> String { ++ let mut ret = String::new(); ++ ++ let mut pre = ""; ++ ++ for com in s.split('/') { ++ match com { ++ "" => { ++ if ret.is_empty() && pre.is_empty() { ++ ret.push('/'); ++ } ++ } ++ "." => { ++ if pre.is_empty() { ++ pre = "."; ++ } ++ } ++ _ => { ++ ret.push_str(com); ++ ret.push('/'); ++ pre = com; ++ } ++ } ++ } ++ /* drop the trailing slash */ ++ if ret.ends_with('/') { ++ let _ = ret.pop(); ++ } ++ ++ ret ++} ++ + #[cfg(test)] + mod tests { +- use crate::path_util::path_equal; ++ use super::*; + + #[test] + fn test_path_equal() { +@@ -35,4 +70,11 @@ mod tests { + assert!(path_equal("/x/././y", "/x/y/./.")); + assert!(!path_equal("/etc", "/var")); + } ++ ++ #[test] ++ fn test_path_simplify() { ++ assert_eq!(path_simplify("//foo//.//bar/"), "/foo/bar"); ++ assert_eq!(path_simplify(".//foo//.//bar/"), "foo/bar"); ++ assert_eq!(path_simplify("foo//.//bar/"), "foo/bar"); ++ } + } +-- +2.33.0 + diff --git a/backport-feature-libbasic-add-remove_dir_until.patch b/backport-feature-libbasic-add-remove_dir_until.patch new file mode 100644 index 0000000..0a58ff0 --- /dev/null +++ b/backport-feature-libbasic-add-remove_dir_until.patch @@ -0,0 +1,106 @@ +From d9fdd267027d6bf3b8265c18279a7f50c2b62081 Mon Sep 17 00:00:00 2001 +From: chenjiayi +Date: Wed, 21 Jun 2023 21:27:38 +0800 +Subject: [PATCH] feature(libbasic): add remove_dir_until + +remove_dir_until is used to recursively remove parent directories +which contains nothing until specific directory. +--- + libs/basic/src/fs_util.rs | 64 +++++++++++++++++++++++++++++++++++++-- + 1 file changed, 62 insertions(+), 2 deletions(-) + +diff --git a/libs/basic/src/fs_util.rs b/libs/basic/src/fs_util.rs +index 63c43ca..5f34e9a 100644 +--- a/libs/basic/src/fs_util.rs ++++ b/libs/basic/src/fs_util.rs +@@ -20,7 +20,7 @@ use nix::{ + unistd::{Gid, Uid}, + }; + use pathdiff::diff_paths; +-use std::{os::unix::prelude::PermissionsExt, path::Path}; ++use std::{fs::remove_dir, io::ErrorKind, os::unix::prelude::PermissionsExt, path::Path}; + + /// open the parent directory of path + pub fn open_parent(path: &Path, flags: OFlag, mode: Mode) -> Result { +@@ -164,12 +164,55 @@ pub fn futimens_opath(fd: i32, ts: Option<[timespec; 2]>) -> Result<()> { + } + } + ++/// recursively remove parent directories until specific directory ++pub fn remove_dir_until(path: &str, stop: &str) -> Result<()> { ++ let path = Path::new(path); ++ ++ let mut dir = if path.is_dir() { ++ Path::new(path) ++ } else { ++ match path.parent() { ++ Some(p) => p, ++ None => { ++ return Ok(()); ++ } ++ } ++ }; ++ ++ loop { ++ if let Err(e) = remove_dir(dir) { ++ match e.kind() { ++ ErrorKind::NotFound => break, ++ _ => { ++ return Err(Error::Io { source: e }); ++ } ++ } ++ } ++ ++ match dir.parent() { ++ Some(p) => { ++ if p.ends_with(stop) { ++ break; ++ } ++ dir = p; ++ } ++ None => break, ++ }; ++ } ++ ++ Ok(()) ++} ++ + #[cfg(test)] + mod tests { + use super::*; + use crate::fs_util::symlink; + use nix::unistd::{self}; +- use std::{fs::File, os::unix::prelude::MetadataExt, time::SystemTime}; ++ use std::{ ++ fs::{create_dir_all, File}, ++ os::unix::prelude::MetadataExt, ++ time::SystemTime, ++ }; + + #[test] + fn test_symlink() { +@@ -267,4 +310,21 @@ mod tests { + + std::fs::remove_file("/tmp/test_futimens_opath").unwrap(); + } ++ ++ #[test] ++ fn test_remove_dir_until() { ++ create_dir_all("/tmp/test_remove_dir_until_1/test1").unwrap(); ++ assert!(Path::new("/tmp/test_remove_dir_until_1/test1").exists()); ++ remove_dir_until("/tmp/test_remove_dir_until_1/test1", "/tmp").unwrap(); ++ assert!(!Path::new("/tmp/test_remove_dir_until_1/test1").exists()); ++ assert!(!Path::new("/tmp/test_remove_dir_until_1").exists()); ++ ++ create_dir_all("/tmp/test_remove_dir_until_2/test2").unwrap(); ++ File::create("/tmp/test_remove_dir_until_2/test_file").unwrap(); ++ assert!(Path::new("/tmp/test_remove_dir_until_2/test2").exists()); ++ assert!(Path::new("/tmp/test_remove_dir_until_2/test_file").exists()); ++ assert!(remove_dir_until("/tmp/test_remove_dir_until_2/test2", "/tmp").is_err()); ++ assert!(!Path::new("/tmp/test_remove_dir_until_2/test2").exists()); ++ assert!(Path::new("/tmp/test_remove_dir_until_2/test_file").exists()); ++ } + } +-- +2.33.0 + diff --git a/backport-feature-support-hostname-setup.patch b/backport-feature-support-hostname-setup.patch new file mode 100644 index 0000000..1d72fa3 --- /dev/null +++ b/backport-feature-support-hostname-setup.patch @@ -0,0 +1,426 @@ +From d854bdec0aa318fb1db33c96a7f2e52976452bc4 Mon Sep 17 00:00:00 2001 +From: zhangyao2022 +Date: Tue, 20 Jun 2023 17:26:52 +0800 +Subject: [PATCH] feature: support hostname setup + +--- + Cargo.toml | 1 + + exts/hostname_setup/Cargo.toml | 11 ++ + exts/hostname_setup/src/main.rs | 235 +++++++++++++++++++++++ + install.sh | 1 + + libs/basic/src/lib.rs | 1 + + libs/basic/src/os_release.rs | 109 +++++++++++ + 9 files changed, 368 insertions(+), 1 deletion(-) + create mode 100644 exts/hostname_setup/Cargo.toml + create mode 100644 exts/hostname_setup/src/main.rs + create mode 100644 libs/basic/src/os_release.rs + +diff --git a/Cargo.toml b/Cargo.toml +index b96ec26..a375070 100644 +--- a/Cargo.toml ++++ b/Cargo.toml +@@ -120,6 +120,7 @@ members = [ + # external binaries + "exts/init", + "exts/sctl", ++ "exts/hostname_setup", + #internal libraries crates + "libs/cmdproto", + #external libraries crates +diff --git a/exts/hostname_setup/Cargo.toml b/exts/hostname_setup/Cargo.toml +new file mode 100644 +index 0000000..b2cbdcf +--- /dev/null ++++ b/exts/hostname_setup/Cargo.toml +@@ -0,0 +1,11 @@ ++[package] ++name = "hostname_setup" ++version = "0.1.0" ++edition = "2021" ++ ++[dependencies] ++nix = "0.24" ++log = "0.4" ++libc = "0.2.*" ++constants = { version = "0.1.0", path = "../../libs/constants" } ++basic = { path = "../../libs/basic" } +diff --git a/exts/hostname_setup/src/main.rs b/exts/hostname_setup/src/main.rs +new file mode 100644 +index 0000000..4dc5a1b +--- /dev/null ++++ b/exts/hostname_setup/src/main.rs +@@ -0,0 +1,235 @@ ++// Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. ++// ++// sysMaster is licensed under Mulan PSL v2. ++// You can use this software according to the terms and conditions of the Mulan ++// PSL v2. ++// You may obtain a copy of Mulan PSL v2 at: ++// http://license.coscl.org.cn/MulanPSL2 ++// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY ++// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ++// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. ++// See the Mulan PSL v2 for more details. ++ ++//! hostname setup ++ ++use basic::logger; ++use basic::os_release; ++use basic::proc_cmdline; ++use nix::Result; ++use std::fmt; ++use std::fmt::Display; ++ ++const SYSTEMD_HOSTNAME_KEY: &str = "systemd.hostname"; ++const SYSMASTER_HOSTNAME_KEY: &str = "sysmaster.hostname"; ++const DEFAULT_HOSTNAME: &str = "localhost"; ++ ++#[derive(Debug)] ++struct Hostname { ++ hostname: String, ++} ++ ++impl Hostname { ++ fn from_string(str_hostname: &str) -> Option { ++ let hostname = Hostname::new(str_hostname.trim()); ++ if hostname.valid() { ++ Some(hostname) ++ } else { ++ None ++ } ++ } ++ ++ fn from_cmdline() -> Option { ++ let systemd_hostname = match proc_cmdline::cmdline_get_value(SYSTEMD_HOSTNAME_KEY) { ++ Err(e) => { ++ log::warn!( ++ "Failed to get proc cmdline by key {}: {}", ++ SYSTEMD_HOSTNAME_KEY, ++ e ++ ); ++ None ++ } ++ Ok(hostname) => hostname, ++ }; ++ ++ systemd_hostname.map_or_else( ++ || match proc_cmdline::cmdline_get_value(SYSMASTER_HOSTNAME_KEY) { ++ Err(e) => { ++ log::warn!( ++ "Failed to get proc cmdline by key {}: {}", ++ SYSMASTER_HOSTNAME_KEY, ++ e ++ ); ++ None ++ } ++ Ok(hostname) => hostname.and_then(|hostname| Hostname::from_string(&hostname)), ++ }, ++ |hostname| Hostname::from_string(&hostname), ++ ) ++ } ++ ++ fn from_etc_hostname() -> Option { ++ match std::fs::read_to_string("/etc/hostname") { ++ Err(e) => { ++ log::warn!("Failed to get /etc/hostname: {}", e); ++ None ++ } ++ Ok(hostname) => Hostname::from_string(&hostname), ++ } ++ } ++ ++ fn new(hostname: &str) -> Self { ++ Hostname { ++ hostname: hostname.trim().to_string(), ++ } ++ } ++ ++ fn valid(&self) -> bool { ++ if self.hostname.is_empty() { ++ return false; ++ } ++ ++ if self.hostname.len() > 64 { ++ return false; ++ } ++ ++ let mut dot = true; ++ let mut hyphen = true; ++ ++ for c in self.hostname.chars() { ++ if c == '.' { ++ if dot || hyphen { ++ return false; ++ } ++ dot = true; ++ hyphen = false; ++ } else if c == '-' { ++ if dot { ++ return false; ++ } ++ dot = false; ++ hyphen = true; ++ } else { ++ if !c.is_ascii_alphanumeric() { ++ return false; ++ } ++ dot = false; ++ hyphen = false; ++ } ++ } ++ ++ if dot { ++ return false; ++ } ++ ++ if hyphen { ++ return false; ++ } ++ true ++ } ++ ++ fn setup(hostname: &Self) -> Result<()> { ++ if !hostname.valid() { ++ return Err(nix::errno::Errno::EINVAL); ++ } ++ ++ let local_hostname = Hostname::local_hostname()?; ++ if local_hostname.eq(hostname) { ++ log::info!("Hostname has already been set: {hostname}."); ++ return Ok(()); ++ } ++ nix::unistd::sethostname(&hostname.hostname) ++ } ++ ++ fn local_hostname() -> Result { ++ match nix::sys::utsname::uname() { ++ Err(e) => { ++ log::warn!("Failed to get uname: {}", e); ++ Err(e) ++ } ++ Ok(uts_name) => Ok(uts_name ++ .nodename() ++ .to_str() ++ .map_or(Hostname::new(""), Hostname::new)), ++ } ++ } ++ ++ fn hostname_is_set() -> bool { ++ Hostname::local_hostname().map_or(false, |hostname| hostname != Hostname::new("(none)")) ++ } ++} ++ ++impl PartialEq for Hostname { ++ fn eq(&self, other: &Self) -> bool { ++ self.hostname.eq(&other.hostname) ++ } ++} ++ ++impl Display for Hostname { ++ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { ++ write!(f, "{}", self.hostname) ++ } ++} ++ ++impl Default for Hostname { ++ fn default() -> Self { ++ if let Ok(Some(str)) = os_release::get_os_release("DEFAULT_HOSTNAME") { ++ return Hostname::from_string(&str).unwrap_or_else(|| Hostname::new(DEFAULT_HOSTNAME)); ++ } ++ Hostname::new(DEFAULT_HOSTNAME) ++ } ++} ++ ++fn main() { ++ logger::init_log_to_console("hostname-setup", log::LevelFilter::Info); ++ let mut op_hostname = Hostname::from_cmdline(); ++ if op_hostname.is_none() { ++ op_hostname = Hostname::from_etc_hostname(); ++ } ++ ++ if op_hostname.is_none() && Hostname::hostname_is_set() { ++ log::info!("Hostname has already been set, skipping."); ++ return; ++ } ++ ++ let hostname = op_hostname.unwrap_or_default(); ++ ++ log::info!("Hostname set to: {}.", hostname); ++ if let Err(e) = Hostname::setup(&hostname) { ++ log::error!("Failed to set hostname: {}.", e); ++ std::process::exit(e as i32); ++ } ++ std::process::exit(0); ++} ++ ++#[cfg(test)] ++mod test { ++ use crate::Hostname; ++ ++ #[test] ++ fn test_hostname_valid() { ++ assert!(Hostname::new("foobar").valid()); ++ assert!(Hostname::new("foobar.com").valid()); ++ assert!(!Hostname::new("foobar.com.").valid()); ++ assert!(Hostname::new("fooBAR").valid()); ++ assert!(Hostname::new("fooBAR.com").valid()); ++ assert!(!Hostname::new("fooBAR.").valid()); ++ assert!(!Hostname::new("fooBAR.com.").valid()); ++ assert!(!Hostname::new("fööbar").valid()); ++ assert!(!Hostname::new("").valid()); ++ assert!(!Hostname::new(".").valid()); ++ assert!(!Hostname::new("..").valid()); ++ assert!(!Hostname::new("foobar.").valid()); ++ assert!(!Hostname::new(".foobar").valid()); ++ assert!(!Hostname::new("foo..bar").valid()); ++ assert!(!Hostname::new("foo.bar..").valid()); ++ assert!(!Hostname::new("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx").valid()); ++ assert!(!Hostname::new( ++ "au-xph5-rvgrdsb5hcxc-47et3a5vvkrc-server-wyoz4elpdpe3.openstack.local" ++ ) ++ .valid()); ++ assert!(Hostname::new("local--host.localdomain").valid()); ++ assert!(!Hostname::new("localhost-.localdomain").valid()); ++ assert!(!Hostname::new("localhost.-localdomain").valid()); ++ assert!(Hostname::new("localhost.localdomain").valid()); ++ } ++} +diff --git a/install.sh b/install.sh +index eb1b43e..675c543 100644 +--- a/install.sh ++++ b/install.sh +@@ -14,6 +14,7 @@ install -Dm0755 -t ${install_dir} ${target_dir}/fstab || exit 1 + install -Dm0755 -t ${install_dir} ${target_dir}/sysmonitor || exit 1 + install -Dm0755 -t ${install_dir} ${target_dir}/random_seed || exit 1 + install -Dm0755 -t ${install_dir} ${target_dir}/rc-local-generator || exit 1 ++install -Dm0755 -t ${install_dir} ${target_dir}/hostname_setup || exit 1 + + strip ${target_dir}/lib*.so + +diff --git a/libs/basic/src/lib.rs b/libs/basic/src/lib.rs +index 8678b58..db80efb 100644 +--- a/libs/basic/src/lib.rs ++++ b/libs/basic/src/lib.rs +@@ -44,3 +44,4 @@ pub mod user_group_util; + pub mod uuid; + pub mod virtualize; + pub use error::*; ++pub mod os_release; +diff --git a/libs/basic/src/os_release.rs b/libs/basic/src/os_release.rs +new file mode 100644 +index 0000000..26e291d +--- /dev/null ++++ b/libs/basic/src/os_release.rs +@@ -0,0 +1,109 @@ ++// Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. ++// ++// sysMaster is licensed under Mulan PSL v2. ++// You can use this software according to the terms and conditions of the Mulan ++// PSL v2. ++// You may obtain a copy of Mulan PSL v2 at: ++// http://license.coscl.org.cn/MulanPSL2 ++// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY ++// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ++// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. ++// See the Mulan PSL v2 for more details. ++ ++//! Parse info about /etc/os-release ++use std::{ ++ fs::File, ++ io::{BufRead, BufReader}, ++}; ++ ++use crate::error::*; ++ ++/// get value by key in /etc/os-release ++pub fn get_os_release(key: &str) -> Result> { ++ let reader = BufReader::new(File::open("/etc/os-release").context(IoSnafu)?); ++ for line in reader.lines().map(std::result::Result::unwrap_or_default) { ++ match parse_line(key, &line) { ++ Some(value) => return Ok(Some(value.to_string())), ++ None => continue, ++ } ++ } ++ Ok(None) ++} ++ ++fn parse_line<'a>(key: &str, line: &'a str) -> Option<&'a str> { ++ if let Some(pos) = line.chars().position(|c| c == '=') { ++ let line_key = line[..pos].trim(); ++ if key == line_key { ++ let s = trim_quotes(line[pos + 1..].trim()); ++ if !s.is_empty() { ++ return Some(s); ++ } ++ } ++ None ++ } else { ++ None ++ } ++} ++ ++fn trim_quotes(str: &str) -> &str { ++ if ["\"", "'"] ++ .iter() ++ .any(|s| str.starts_with(s) && str.ends_with(s)) ++ { ++ str[1..str.len() - 1].trim() ++ } else { ++ str.trim() ++ } ++} ++ ++#[cfg(test)] ++mod test { ++ use super::*; ++ ++ #[test] ++ fn test_trim_quotes() { ++ let str1 = "\"aaaaa\""; ++ assert_eq!(&str1[1..str1.len() - 1], trim_quotes(str1)); ++ ++ let str2 = "'aaaaa'"; ++ assert_eq!(&str2[1..str2.len() - 1], trim_quotes(str2)); ++ ++ let str3 = "\"aaaaa"; ++ assert_eq!(str3, trim_quotes(str3)); ++ ++ let str4 = "'aaaaa"; ++ assert_eq!(str4, trim_quotes(str4)); ++ } ++ ++ #[test] ++ fn test_parse_line() { ++ let line = "ID=\"openEuler\""; ++ assert_eq!(parse_line("ID", line), Some("openEuler")); ++ assert_eq!(parse_line("NONE", line), None); ++ ++ let line = "ID='openEuler'"; ++ assert_eq!(parse_line("ID", line), Some("openEuler")); ++ assert_eq!(parse_line("NONE", line), None); ++ ++ let line = "IDopenEuler"; ++ assert_eq!(parse_line("ID", line), None); ++ ++ let line = "ID="; ++ assert_eq!(parse_line("ID", line), None); ++ ++ let line = "ID=\"openEuler \""; ++ assert_eq!(parse_line("ID", line), Some("openEuler")); ++ ++ let line = "ID=\"openEuler \""; ++ assert_eq!(parse_line("ID", line), Some("openEuler")); ++ ++ let line = "ID=\"openEuler\" "; ++ assert_eq!(parse_line("ID", line), Some("openEuler")); ++ ++ let line = "ID=openEuler"; ++ assert_eq!(parse_line("ID", line), Some("openEuler")); ++ ++ let line = "ID=openEuler "; ++ assert_eq!(parse_line("ID", line), Some("openEuler")); ++ } ++} +-- +2.33.0 + diff --git a/backport-feature-use-LogFileSize-and-LogFileNumber-to-rotate-.patch b/backport-feature-use-LogFileSize-and-LogFileNumber-to-rotate-.patch new file mode 100644 index 0000000..55e22da --- /dev/null +++ b/backport-feature-use-LogFileSize-and-LogFileNumber-to-rotate-.patch @@ -0,0 +1,309 @@ +From 8b9ac4b0954529df5c343317ee5223307224303c Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Sun, 25 Jun 2023 15:00:41 +0800 +Subject: [PATCH] feature: use LogFileSize and LogFileNumber to rotate the log + and make __um_obj_create() accept LogFileSize/LogFileNumber + +--- + core/bin/plugin/mod.rs | 61 ++++++++++++++++------------ + core/bin/unit/manager.rs | 25 ++++++++---- + core/lib/unit/umif.rs | 6 ++- + libs/basic/src/logger.rs | 88 +++++++++++++++++++++++++++++++--------- + 4 files changed, 125 insertions(+), 55 deletions(-) + +diff --git a/core/bin/plugin/mod.rs b/core/bin/plugin/mod.rs +index 9b19336..a8f6f24 100644 +--- a/core/bin/plugin/mod.rs ++++ b/core/bin/plugin/mod.rs +@@ -475,33 +475,44 @@ impl Plugin { + unit_type: UnitType, + target: &str, + file: &str, ++ file_size: u32, ++ file_number: u32, + ) -> Result> { +- match self.get_lib(unit_type) { +- Ok(dy_lib) => { +- #[allow(clippy::type_complexity)] +- let sym: Result< +- Symbol< +- fn(level: LevelFilter, target: &str, file: &str) -> *mut dyn UnitManagerObj, +- >, +- > = unsafe { +- dy_lib +- .lib +- .get(b"__um_obj_create") +- .map_err(|e| Error::PluginLoad { msg: e.to_string() }) +- }; +- if let Ok(fun) = sym { +- let boxed_raw = fun(log::max_level(), target, file); +- Ok(unsafe { Box::from_raw(boxed_raw) }) +- } else { +- Err(Error::PluginLoad { +- msg: format!("The library of {:?} is {:?}", unit_type, sym.err()), +- }) +- } ++ let dy_lib = match self.get_lib(unit_type) { ++ Err(_) => { ++ return Err(Error::PluginLoad { ++ msg: format!("create um, the {unit_type:?} plugin is not exist"), ++ }); + } +- Err(_) => Err(Error::PluginLoad { +- msg: format!("create um, the {unit_type:?} plugin is not exist"), +- }), +- } ++ Ok(v) => v, ++ }; ++ ++ type FnType = fn( ++ level: LevelFilter, ++ target: &str, ++ file: &str, ++ file_size: u32, ++ file_number: u32, ++ ) -> *mut dyn UnitManagerObj; ++ ++ #[allow(clippy::type_complexity)] ++ let sym: Result> = unsafe { ++ dy_lib ++ .lib ++ .get(b"__um_obj_create") ++ .map_err(|e| Error::PluginLoad { msg: e.to_string() }) ++ }; ++ let fun = match sym { ++ Err(_) => { ++ return Err(Error::PluginLoad { ++ msg: format!("The library of {:?} is {:?}", unit_type, sym.err()), ++ }) ++ } ++ Ok(v) => v, ++ }; ++ ++ let boxed_raw = fun(log::max_level(), target, file, file_size, file_number); ++ Ok(unsafe { Box::from_raw(boxed_raw) }) + } + + fn get_lib(&self, unit_type: UnitType) -> Result> { +diff --git a/core/bin/unit/manager.rs b/core/bin/unit/manager.rs +index 492f3f4..f548817 100644 +--- a/core/bin/unit/manager.rs ++++ b/core/bin/unit/manager.rs +@@ -1408,15 +1408,24 @@ mod unit_submanager { + + fn new_sub(&self, unit_type: UnitType) -> Option> { + let um = self.um(); +- let target = um.get_log_target(); +- let file = um.get_log_file(); +- let ret = Plugin::get_instance().create_um_obj(unit_type, target, file); +- if ret.is_err() { +- log::info!("create um_obj is not found, type {:?}!", unit_type); +- return None; +- } ++ log::info!( ++ "Creating UnitManagerObj for {:?} by __um_obj_create()", ++ unit_type ++ ); ++ let sub = match Plugin::get_instance().create_um_obj( ++ unit_type, ++ um.get_log_target(), ++ um.get_log_file(), ++ um.get_log_file_size(), ++ um.get_log_file_number(), ++ ) { ++ Err(_) => { ++ log::info!("__um_obj_create() of {:?} is not found", unit_type); ++ return None; ++ } ++ Ok(v) => v, ++ }; + +- let sub = ret.unwrap(); + let reli = um.reliability(); + sub.attach_um(um); + sub.attach_reli(reli); +diff --git a/core/lib/unit/umif.rs b/core/lib/unit/umif.rs +index c41c211..a000a3d 100644 +--- a/core/lib/unit/umif.rs ++++ b/core/lib/unit/umif.rs +@@ -250,9 +250,11 @@ macro_rules! declure_umobj_plugin { + pub fn __um_obj_create( + level: LevelFilter, + target: &str, +- file: &str, ++ file_path: &str, ++ file_size: u32, ++ file_number: u32, + ) -> *mut dyn $crate::unit::UnitManagerObj { +- logger::init_log_for_subum($name, level, target, file); ++ logger::init_log_for_subum($name, level, target, file_path, file_size, file_number); + let construcotr: fn() -> $unit_type = $constructor; + let obj = construcotr(); + let boxed: Box = Box::new(obj); +diff --git a/libs/basic/src/logger.rs b/libs/basic/src/logger.rs +index 2f24d25..0bc15bb 100644 +--- a/libs/basic/src/logger.rs ++++ b/libs/basic/src/logger.rs +@@ -15,7 +15,12 @@ use log::{LevelFilter, Log}; + use log4rs::{ + append::{ + console::{ConsoleAppender, Target}, +- file::FileAppender, ++ rolling_file::{ ++ policy::compound::{ ++ roll::fixed_window::FixedWindowRoller, trigger::size::SizeTrigger, CompoundPolicy, ++ }, ++ RollingFileAppender, ++ }, + Append, + }, + config::{Appender, Config, Logger, Root}, +@@ -78,13 +83,20 @@ impl log::Log for SysLogger { + fn flush(&self) {} + } + +-fn append_log(app_name: &str, level: LevelFilter, target: &str, file_path: Option<&str>) { ++fn append_log( ++ app_name: &str, ++ level: LevelFilter, ++ target: &str, ++ file_path: &str, ++ file_size: u32, ++ file_number: u32, ++) { + if target == "syslog" { + let _ = log::set_boxed_logger(Box::new(SysLogger)); + log::set_max_level(level); + return; + } +- let config = build_log_config(app_name, level, target, file_path); ++ let config = build_log_config(app_name, level, target, file_path, file_size, file_number); + let logger = log4rs::Logger::new(config); + log::set_max_level(level); + let _ = log::set_boxed_logger(Box::new(LogPlugin(logger))); +@@ -99,12 +111,18 @@ fn append_log(app_name: &str, level: LevelFilter, target: &str, file_path: Optio + /// target: log target + /// + /// file_path: file path if the target is set to file +-pub fn init_log_for_subum(app_name: &str, level: LevelFilter, target: &str, file: &str) { +- let file = if file.is_empty() { None } else { Some(file) }; ++pub fn init_log_for_subum( ++ app_name: &str, ++ level: LevelFilter, ++ target: &str, ++ file_path: &str, ++ file_size: u32, ++ file_number: u32, ++) { + /* We should avoid calling init_log here, or we will get many "attempted + * to set a logger after the logging system was already initialized" error + * message. */ +- append_log(app_name, level, target, file); ++ append_log(app_name, level, target, file_path, file_size, file_number); + } + + /// Init and set the log target to console +@@ -113,7 +131,7 @@ pub fn init_log_for_subum(app_name: &str, level: LevelFilter, target: &str, file + /// + /// level: maximum log level + pub fn init_log_to_console(app_name: &str, level: LevelFilter) { +- init_log(app_name, level, "console", None); ++ init_log(app_name, level, "console", "", 0, 0); + } + + /// Init and set the log target to file +@@ -123,8 +141,14 @@ pub fn init_log_to_console(app_name: &str, level: LevelFilter) { + /// level: maximum log level + /// + /// file_path: log to which file +-pub fn init_log_to_file(app_name: &str, level: LevelFilter, file_path: &str) { +- init_log(app_name, level, "file", Some(file_path)); ++pub fn init_log_to_file( ++ app_name: &str, ++ level: LevelFilter, ++ file_path: &str, ++ file_size: u32, ++ file_number: u32, ++) { ++ init_log(app_name, level, "file", file_path, file_size, file_number); + } + + /// Init and set the logger +@@ -136,13 +160,20 @@ pub fn init_log_to_file(app_name: &str, level: LevelFilter, file_path: &str) { + /// target: log target + /// + /// file_path: file path if the target is set to file +-pub fn init_log(app_name: &str, level: LevelFilter, target: &str, file_path: Option<&str>) { ++pub fn init_log( ++ app_name: &str, ++ level: LevelFilter, ++ target: &str, ++ file_path: &str, ++ file_size: u32, ++ file_number: u32, ++) { + if target == "syslog" { + let _ = log::set_boxed_logger(Box::new(SysLogger)); + log::set_max_level(level); + return; + } +- let config = build_log_config(app_name, level, target, file_path); ++ let config = build_log_config(app_name, level, target, file_path, file_size, file_number); + let r = log4rs::init_config(config); + if let Err(e) = r { + println!("{e}"); +@@ -153,12 +184,18 @@ fn build_log_config( + app_name: &str, + level: LevelFilter, + target: &str, +- file: Option<&str>, ++ file_path: &str, ++ file_size: u32, ++ file_number: u32, + ) -> Config { + let mut target = target; + /* If the file is configured to None, use console forcely. */ +- if file.is_none() && target == "file" { +- println!("LogTarget is configured to `file`, but LogFile is not configured, changing the LogTarget to `console`"); ++ if (file_path.is_empty() || file_size == 0 || file_number == 0) && target == "file" { ++ println!( ++ "LogTarget is configured to `file`, but configuration is invalid, changing the \ ++ LogTarget to `console`, file: {file_path}, file_size: {file_size}, file_number: \ ++ {file_number}" ++ ); + target = "console"; + } + let encoder = Box::new(PatternEncoder::new(LOG_PATTERN)); +@@ -169,12 +206,23 @@ fn build_log_config( + .target(Target::Stdout) + .build(), + ), +- "file" => Box::new( +- FileAppender::builder() +- .encoder(encoder) +- .build(file.unwrap()) +- .unwrap(), +- ), ++ "file" => { ++ let pattern = file_path.to_string() + &".{}"; ++ let policy = Box::new(CompoundPolicy::new( ++ Box::new(SizeTrigger::new(file_size as u64 * 1024)), ++ Box::new( ++ FixedWindowRoller::builder() ++ .build(&pattern, file_number) ++ .unwrap(), ++ ), ++ )); ++ Box::new( ++ RollingFileAppender::builder() ++ .encoder(encoder) ++ .build(file_path, policy) ++ .unwrap(), ++ ) ++ } + _ => Box::new( + ConsoleAppender::builder() + .encoder(encoder) +-- +2.33.0 + diff --git a/backport-feature-use-our-own-file-logger.patch b/backport-feature-use-our-own-file-logger.patch new file mode 100644 index 0000000..8a899b7 --- /dev/null +++ b/backport-feature-use-our-own-file-logger.patch @@ -0,0 +1,283 @@ +From f70fcf7c4389ee9eb81f62e8b763e095ed50aea9 Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Tue, 27 Jun 2023 20:15:04 +0800 +Subject: [PATCH] feature: use our own file logger + +This implements a simple file logger which supports log rorating. we set +the log file mode to 600 forcely +--- + libs/basic/Cargo.toml | 1 + + libs/basic/src/logger.rs | 203 ++++++++++++++++++++++++++++++++++++++- + 2 files changed, 202 insertions(+), 2 deletions(-) + +diff --git a/libs/basic/Cargo.toml b/libs/basic/Cargo.toml +index 7557d37..6ee7162 100644 +--- a/libs/basic/Cargo.toml ++++ b/libs/basic/Cargo.toml +@@ -21,6 +21,7 @@ lazy_static = "1.4.0" + bitflags = "1.3.2" + pkg-config = "0.3" + rand = "0.4.6" ++time = {version = "=0.3.10", features = ["formatting", "macros"] } + + [dev-dependencies] + libtests = { path = "../libtests" } +diff --git a/libs/basic/src/logger.rs b/libs/basic/src/logger.rs +index 56def43..3bf579b 100644 +--- a/libs/basic/src/logger.rs ++++ b/libs/basic/src/logger.rs +@@ -11,6 +11,14 @@ + // See the Mulan PSL v2 for more details. + + //! ++use std::{ ++ fs::{File, OpenOptions}, ++ io::Write, ++ os::unix::prelude::OpenOptionsExt, ++ path::{Path, PathBuf}, ++ sync::Mutex, ++}; ++ + use log::{LevelFilter, Log}; + use log4rs::{ + append::{ +@@ -27,6 +35,7 @@ use log4rs::{ + encode::pattern::PatternEncoder, + }; + use nix::libc; ++use time::UtcOffset; + + /// sysmaster log parttern: + /// +@@ -83,6 +92,174 @@ impl log::Log for SysLogger { + fn flush(&self) {} + } + ++struct FileLogger { ++ level: log::Level, ++ file_path: PathBuf, ++ #[allow(dead_code)] ++ file_mode: u32, ++ file_number: u32, ++ max_size: u32, ++ file: Mutex, ++} ++ ++impl log::Log for FileLogger { ++ fn enabled(&self, metadata: &log::Metadata) -> bool { ++ metadata.level() <= self.level ++ } ++ ++ fn log(&self, record: &log::Record) { ++ if !self.enabled(record.metadata()) { ++ return; ++ } ++ let current_size: u32; ++ { ++ let mut file = self.file.lock().unwrap(); ++ self.write( ++ &mut file, ++ record.module_path().unwrap(), ++ record.args().to_string(), ++ ); ++ current_size = file.metadata().unwrap().len() as u32; ++ /* file is automatically unlocked. */ ++ } ++ if current_size > self.max_size { ++ self.rotate(); ++ let file = self.file.lock().unwrap(); ++ let _ = file.set_len(0); ++ } ++ } ++ ++ fn flush(&self) { ++ let mut file = self.file.lock().unwrap(); ++ let _ = file.flush(); ++ } ++} ++ ++impl FileLogger { ++ fn file_open(file_path: &PathBuf, file_mode: u32) -> File { ++ OpenOptions::new() ++ .write(true) ++ .create(true) ++ .append(true) ++ .mode(file_mode) ++ .open(file_path) ++ .unwrap() ++ } ++ ++ fn mv_file_in_dir(src: &str, dst: Option<&str>, dir: &Path) { ++ let src = dir.join(src); ++ if dst.is_none() { ++ let _ = std::fs::remove_file(src); ++ return; ++ } ++ let dst = dir.join(dst.unwrap()); ++ let _ = std::fs::rename(src, dst); ++ } ++ ++ fn cp_file_in_dir(src: &str, dst: &str, dir: &Path) { ++ let src = dir.join(src); ++ let dst = dir.join(dst); ++ let _ = std::fs::copy(src, dst); ++ } ++ ++ fn new( ++ level: log::Level, ++ file_path: PathBuf, ++ file_mode: u32, ++ max_size: u32, ++ file_number: u32, ++ ) -> Self { ++ let file = Self::file_open(&file_path, file_mode); ++ Self { ++ level, ++ file_path, ++ file_mode, ++ file_number, ++ max_size: max_size * 1024, ++ file: Mutex::new(file), ++ } ++ } ++ ++ fn write(&self, file: &mut File, module: &str, msg: String) { ++ let now = time::OffsetDateTime::now_utc().to_offset(UtcOffset::UTC); ++ let format = ++ time::macros::format_description!("[year]-[month]-[day] [hour]:[minute]:[second]"); ++ let now = now.format(&format).unwrap(); ++ ++ /* 1. Write time */ ++ if let Err(e) = file.write(format!("{now} ").as_bytes()) { ++ println!("Failed to log time message: {e}"); ++ return; ++ } ++ ++ /* 2. Write module */ ++ if let Err(e) = file.write((module.to_string() + " ").as_bytes()) { ++ println!("Failed to log module message: {e}"); ++ return; ++ } ++ ++ /* 3. Write message */ ++ if let Err(e) = file.write((msg + "\n").as_bytes()) { ++ println!("Failed to log message: {e}"); ++ return; ++ } ++ } ++ ++ fn rotate(&self) { ++ let dir = self.file_path.parent().unwrap(); ++ let file_name = self ++ .file_path ++ .file_name() ++ .unwrap() ++ .to_string_lossy() ++ .to_string(); ++ let file_name_dot = String::from(&file_name) + "."; ++ let mut num_list: Vec = Vec::new(); ++ ++ for de in dir.read_dir().unwrap() { ++ let de = match de { ++ Err(_) => continue, ++ Ok(v) => v, ++ }; ++ if !de.file_type().unwrap().is_file() { ++ continue; ++ } ++ let de_file_name = de.file_name().to_string_lossy().to_string(); ++ let rotated_num = de_file_name.trim_start_matches(&file_name_dot); ++ let rotated_num = match rotated_num.parse::() { ++ Err(_) => { ++ continue; ++ } ++ Ok(v) => v, ++ }; ++ num_list.push(rotated_num); ++ } ++ ++ num_list.sort(); ++ ++ /* 1. delete surplus rotated file */ ++ /* We only keep (file_number - 1) rotated files, because we will generate a new one later. */ ++ let file_number = self.file_number as usize; ++ for i in file_number - 1..num_list.len() { ++ let src = String::from(&file_name_dot) + &num_list[i].to_string(); ++ Self::mv_file_in_dir(&src, None, dir); ++ } ++ ++ let end = std::cmp::min(num_list.len(), file_number); ++ /* 2. {sysmaster.log.1, sysmaster.log.2, ...} => {sysmaster.log.2, sysmaster.log.3, ...} */ ++ for i in (0..end).rev() { ++ let src = String::from(&file_name_dot) + &num_list[i].to_string(); ++ let dst = String::from(&file_name_dot) + &(num_list[i] + 1).to_string(); ++ Self::mv_file_in_dir(&src, Some(&dst), dir); ++ } ++ ++ /* 3. **copy** sysmaster.log => sysmaster.log.1 */ ++ let src = String::from(&file_name); ++ let dst = String::from(&file_name_dot) + "1"; ++ Self::cp_file_in_dir(&src, &dst, dir); ++ } ++} ++ + fn append_log( + app_name: &str, + level: LevelFilter, +@@ -96,6 +273,17 @@ fn append_log( + log::set_max_level(level); + return; + } ++ if target == "file" { ++ log::set_max_level(level); ++ let _ = log::set_boxed_logger(Box::new(FileLogger::new( ++ log::Level::Debug, ++ PathBuf::from(file_path), ++ 0o600, ++ file_size, ++ file_number, ++ ))); ++ return; ++ } + let config = build_log_config(app_name, level, target, file_path, file_size, file_number); + let logger = log4rs::Logger::new(config); + log::set_max_level(level); +@@ -173,6 +361,17 @@ pub fn init_log( + log::set_max_level(level); + return; + } ++ if target == "file" { ++ let _ = log::set_boxed_logger(Box::new(FileLogger::new( ++ log::Level::Debug, ++ PathBuf::from(&file_path), ++ 0o600, ++ file_size, ++ file_number, ++ ))); ++ log::set_max_level(level); ++ return; ++ } + let config = build_log_config(app_name, level, target, file_path, file_size, file_number); + let r = log4rs::init_config(config); + if let Err(e) = r { +@@ -190,7 +389,7 @@ fn build_log_config( + ) -> Config { + let mut target = target; + /* If the file is configured to None, use console forcely. */ +- if (file_path.is_empty() || file_size == 0 || file_number == 0) && target == "file" { ++ if (file_path.is_empty() || file_size == 0 || file_number == 0) && target == "rolling_file" { + println!( + "LogTarget is configured to `file`, but configuration is invalid, changing the \ + LogTarget to `console`, file: {file_path}, file_size: {file_size}, file_number: \ +@@ -206,7 +405,7 @@ fn build_log_config( + .target(Target::Stdout) + .build(), + ), +- "file" => { ++ "rolling_file" => { + let pattern = file_path.to_string() + ".{}"; + let policy = Box::new(CompoundPolicy::new( + Box::new(SizeTrigger::new(file_size as u64 * 1024)), +-- +2.33.0 + diff --git a/backport-fix-add-default-system.toml.patch b/backport-fix-add-default-system.toml.patch new file mode 100644 index 0000000..374cf19 --- /dev/null +++ b/backport-fix-add-default-system.toml.patch @@ -0,0 +1,24 @@ +From 1782a2b961e7a68960a37ef9a7b0140f20fad72e Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Wed, 28 Jun 2023 16:47:54 +0800 +Subject: [PATCH] fix: add default system.toml + +--- + units/system.toml | 5 +++++ + 1 file changed, 5 insertions(+) + create mode 100644 units/system.toml + +diff --git a/units/system.toml b/units/system.toml +new file mode 100644 +index 0000000..539a119 +--- /dev/null ++++ b/units/system.toml +@@ -0,0 +1,5 @@ ++LogLevel="info" ++LogTarget="syslog" ++LogFile="/var/log/sysmaster/sysmaster.log" ++LogFileSize=10240 ++LogFileNumber=10 +-- +2.33.0 + diff --git a/backport-fix-add-two-helper-function-to-check-if-the-path-nam.patch b/backport-fix-add-two-helper-function-to-check-if-the-path-nam.patch new file mode 100644 index 0000000..c617a4f --- /dev/null +++ b/backport-fix-add-two-helper-function-to-check-if-the-path-nam.patch @@ -0,0 +1,134 @@ +From be5bf4f1e2a8a61e6277e0a568cd3d0be058f0ae Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Mon, 24 Jul 2023 11:47:53 +0800 +Subject: [PATCH] fix: add two helper function to check if the path name is + safe, and path length is valid + +--- + libs/basic/src/path_util.rs | 98 +++++++++++++++++++++++++++++++++++++ + 1 file changed, 98 insertions(+) + +diff --git a/libs/basic/src/path_util.rs b/libs/basic/src/path_util.rs +index 7391615..58f8e49 100644 +--- a/libs/basic/src/path_util.rs ++++ b/libs/basic/src/path_util.rs +@@ -14,6 +14,12 @@ + //! + use std::path::Path; + ++/// The maximum length of a linux path ++pub const PATH_LENGTH_MAX: usize = 4096; ++ ++/// The maximum length of a linux file name ++pub const FILE_LENGTH_MAX: usize = 255; ++ + /// return true if the path of a and b equaled. + pub fn path_equal(a: &str, b: &str) -> bool { + let p_a = Path::new(a); +@@ -21,6 +27,58 @@ pub fn path_equal(a: &str, b: &str) -> bool { + p_a == p_b + } + ++/// check if the path name contains unsafe character ++/// ++/// return true if it doesn't contain unsafe character ++pub fn path_name_is_safe(s: &str) -> bool { ++ if s.is_empty() { ++ return false; ++ } ++ for c in s.chars() { ++ if c > 0 as char && c < ' ' { ++ return false; ++ } ++ if (c as char).is_ascii_control() { ++ return false; ++ } ++ } ++ true ++} ++ ++/// check if the path length is valid ++pub fn path_length_is_valid(s: &str) -> bool { ++ if s.is_empty() { ++ return false; ++ } ++ if s.len() > PATH_LENGTH_MAX { ++ return false; ++ } ++ let mut de_len = 0; ++ let mut last_c = '/'; ++ for c in s.chars() { ++ match c { ++ '/' => { ++ de_len = 0; ++ } ++ '.' => { ++ if last_c == '/' { ++ de_len = 1; ++ } else { ++ de_len += 1; ++ } ++ } ++ _ => { ++ de_len += 1; ++ } ++ } ++ if de_len > FILE_LENGTH_MAX { ++ return false; ++ } ++ last_c = c; ++ } ++ true ++} ++ + /// Remove redundant inner and trailing slashes and unnecessary dots to simplify path. + /// e.g., //foo//.//bar/ becomes /foo/bar + /// .//foo//.//bar/ becomes foo/bar +@@ -77,4 +135,44 @@ mod tests { + assert_eq!(path_simplify(".//foo//.//bar/"), "foo/bar"); + assert_eq!(path_simplify("foo//.//bar/"), "foo/bar"); + } ++ ++ #[test] ++ fn test_path_name_is_safe() { ++ assert!(!path_name_is_safe("")); ++ assert!(path_name_is_safe("/abc")); ++ assert!(!path_name_is_safe("/abc\x7f/a")); ++ assert!(!path_name_is_safe("/abc\x1f/a")); ++ assert!(!path_name_is_safe("/\x0a/a")); ++ } ++ ++ #[test] ++ fn test_path_length_is_valid() { ++ assert!(!path_length_is_valid("")); ++ ++ let path = "/a/".to_string() + &String::from_iter(vec!['1'; 255]); ++ assert!(path_length_is_valid(&path)); ++ ++ let path = "/a/".to_string() + &String::from_iter(vec!['1'; 256]); ++ assert!(!path_length_is_valid(&path)); ++ ++ let path = "/a/".to_string() + &String::from_iter(vec!['/'; 256]); ++ assert!(path_length_is_valid(&path)); ++ ++ let path = "/a/".to_string() + &String::from_iter(vec!['.'; 255]); ++ assert!(path_length_is_valid(&path)); ++ ++ let mut path = "".to_string(); ++ for _ in 0..40 { ++ path += "/"; ++ path += &String::from_iter(vec!['1'; 100]); ++ } ++ assert!(path_length_is_valid(&path)); ++ ++ let mut path = "".to_string(); ++ for _ in 0..41 { ++ path += "/"; ++ path += &String::from_iter(vec!['1'; 100]); ++ } ++ assert!(!path_length_is_valid(&path)); ++ } + } +-- +2.33.0 + diff --git a/backport-fix-add-two-helper-macroes-to-help-us-log-message-ou.patch b/backport-fix-add-two-helper-macroes-to-help-us-log-message-ou.patch new file mode 100644 index 0000000..ae4ee61 --- /dev/null +++ b/backport-fix-add-two-helper-macroes-to-help-us-log-message-ou.patch @@ -0,0 +1,49 @@ +From e9ce7c44f15a6e03df5d5c4837f8b4d86841cd1f Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Wed, 5 Jul 2023 16:42:08 +0800 +Subject: [PATCH] fix: add two helper macroes to help us log message out when + we operate a file or directory easily + +--- + libs/basic/src/fs_util.rs | 25 +++++++++++++++++++++++++ + 1 file changed, 25 insertions(+) + +diff --git a/libs/basic/src/fs_util.rs b/libs/basic/src/fs_util.rs +index ec814e2..3aa93e9 100644 +--- a/libs/basic/src/fs_util.rs ++++ b/libs/basic/src/fs_util.rs +@@ -310,6 +310,31 @@ pub fn touch_file( + fchmod_and_chown(fd, path, mode, uid, gid) + } + ++/// do some operations and log message out, returns Io error when fail ++#[macro_export] ++macro_rules! do_entry_or_return_io_error { ++ ($function:expr, $entry:ident, $action:literal) => { ++ match $function(&$entry) { ++ Err(e) => { ++ log::error!("Failed to {} {:?}: {e}", $action, $entry); ++ return Err(e).context(IoSnafu); ++ } ++ Ok(_) => log::debug!("{} {:?} succeeded", $action, $entry), ++ } ++ }; ++} ++ ++/// do some operations and log message out, skip the error ++#[macro_export] ++macro_rules! do_entry_log { ++ ($function:expr, $entry:ident, $action:literal) => { ++ match $function(&$entry) { ++ Err(e) => log::error!("Failed to {} {:?}: {e}", $action, $entry), ++ Ok(_) => log::debug!("{} {:?} succeeded", $action, $entry), ++ } ++ }; ++} ++ + #[cfg(test)] + mod tests { + use super::*; +-- +2.33.0 + diff --git a/backport-fix-adjust-the-mode-of-internal-generated-files.patch b/backport-fix-adjust-the-mode-of-internal-generated-files.patch new file mode 100644 index 0000000..940bef6 --- /dev/null +++ b/backport-fix-adjust-the-mode-of-internal-generated-files.patch @@ -0,0 +1,288 @@ +From bb5273fb5e381cc9f655cec8ca1c77faebc3a40b Mon Sep 17 00:00:00 2001 +From: xuxiaozhou1 +Date: Fri, 30 Jun 2023 14:29:08 +0800 +Subject: [PATCH] fix: adjust the mode of internal generated files + +--- + core/libsysmaster/rel/api.rs | 25 ++++++++++++++++++++----- + core/libsysmaster/rel/base.rs | 9 +++++++++ + core/libsysmaster/rel/history.rs | 11 ++++++++++- + core/sysmaster/unit/notify.rs | 10 +++++++++- + core/sysmaster/unit/util/unit_file.rs | 4 ++-- + init/src/runtime/comm.rs | 16 ++++++++++++++-- + libs/basic/src/path_lookup.rs | 18 +++++++++++------- + tests/common/util_lib.sh | 6 +++--- + 8 files changed, 104 insertions(+), 45 deletions(-) + +diff --git a/core/libsysmaster/rel/api.rs b/core/libsysmaster/rel/api.rs +index fb482b8..94f9015 100644 +--- a/core/libsysmaster/rel/api.rs ++++ b/core/libsysmaster/rel/api.rs +@@ -21,6 +21,7 @@ use super::{ + use crate::{error::*, rel::base}; + use basic::do_entry_or_return_io_error; + use heed::Database; ++use nix::sys::stat::{self, Mode}; + use std::{ + fs::{self, File}, + path::Path, +@@ -396,17 +397,31 @@ fn reli_prepare() -> Result { + base::reli_dir_prepare()?; // again + let dir_string = base::reli_dir_get().unwrap(); + ++ // prepare ++ /* create '/run/sysmaster/reliability/sub_dir' or 'xxx/reliability/sub_dir' with mode 700 */ ++ let old_mask = stat::umask(Mode::from_bits_truncate(!0o700)); ++ let ret = reli_do_prepare(&dir_string); ++ let _ = stat::umask(old_mask); ++ if let Err(e) = ret { ++ log::error!("reliability prepare failed: dir{:?}, {}", dir_string, e); ++ return Err(e); ++ } ++ ++ Ok(dir_string) ++} ++ ++fn reli_do_prepare(dir_string: &str) -> Result<()> { + // enable +- enable::prepare(&dir_string)?; ++ enable::prepare(dir_string)?; + + // last +- last::prepare(&dir_string)?; ++ last::prepare(dir_string)?; + + // history +- history::prepare(&dir_string)?; ++ history::prepare(dir_string)?; + + // pending +- pending::prepare(&dir_string)?; ++ pending::prepare(dir_string)?; + +- Ok(dir_string) ++ Ok(()) + } +diff --git a/core/libsysmaster/rel/base.rs b/core/libsysmaster/rel/base.rs +index 7137e13..65307e0 100644 +--- a/core/libsysmaster/rel/base.rs ++++ b/core/libsysmaster/rel/base.rs +@@ -15,6 +15,7 @@ use crate::error::*; + use heed::types::SerdeBincode; + use heed::Database; + use heed::{Env, RoTxn, RwTxn}; ++use nix::sys::stat::{self, Mode}; + use serde::de::DeserializeOwned; + use serde::Serialize; + use std::cell::RefCell; +@@ -305,6 +306,14 @@ pub fn reli_dir_get() -> Result { + /// 2. OUT_DIR/../reliability/: make CI happy, which is target/debug/reliability/ or target/release/reliability/ usually. + /// 3. PROCESS_RELI_PATH: the path customized. + pub fn reli_dir_prepare() -> Result<()> { ++ // create '/run/sysmaster/reliability' or 'xxx/reliability' with mode 700 ++ let old_mask = stat::umask(Mode::from_bits_truncate(!0o700)); ++ let ret = reli_dir_prepare_body(); ++ let _ = stat::umask(old_mask); ++ ret ++} ++ ++fn reli_dir_prepare_body() -> Result<()> { + // // /run/sysmaster/reliability/ + let ret_run = reli_dir_prepare_run(); + if ret_run.is_ok() { +diff --git a/core/libsysmaster/rel/history.rs b/core/libsysmaster/rel/history.rs +index fc31623..c301f38 100644 +--- a/core/libsysmaster/rel/history.rs ++++ b/core/libsysmaster/rel/history.rs +@@ -14,6 +14,7 @@ use super::base::{ReDbRoTxn, ReDbRwTxn, ReDbTable}; + use crate::error::*; + use basic::{do_entry_log, do_entry_or_return_io_error}; + use heed::{CompactionOption, Env, EnvOpenOptions}; ++use nix::sys::stat::{self, Mode}; + use std::cell::RefCell; + use std::collections::HashMap; + use std::fmt; +@@ -120,6 +121,14 @@ impl ReliHistory { + } + + pub(super) fn compact(&self) -> Result<()> { ++ // action with mode 700, excluding group and other users ++ let old_mask = stat::umask(Mode::from_bits_truncate(!0o700)); ++ let ret = self.compact_body(); ++ let _ = stat::umask(old_mask); ++ ret ++ } ++ ++ fn compact_body(&self) -> Result<()> { + // a -> b or b -> a + // prepare next + let history = history_path_get(&self.hdir); +@@ -189,7 +198,7 @@ pub fn prepare(dir_str: &str) -> Result<()> { + + let b = history.join(RELI_HISTORY_B_DIR); + if !b.exists() { +- do_entry_or_return_io_error!(fs::create_dir_all, a, "create"); ++ do_entry_or_return_io_error!(fs::create_dir_all, b, "create"); + } + + Ok(()) +diff --git a/core/sysmaster/unit/notify.rs b/core/sysmaster/unit/notify.rs +index d23a725..4f92b63 100644 +--- a/core/sysmaster/unit/notify.rs ++++ b/core/sysmaster/unit/notify.rs +@@ -21,6 +21,7 @@ use nix::errno::Errno; + use nix::sys::socket::{ + self, sockopt, AddressFamily, MsgFlags, RecvMsg, SockFlag, SockType, UnixAddr, UnixCredentials, + }; ++use nix::sys::stat::{self, Mode}; + use nix::unistd::Pid; + use std::{ + cell::RefCell, collections::HashMap, fs, io::IoSliceMut, os::unix::prelude::RawFd, +@@ -171,7 +172,14 @@ impl Notify { + log::warn!("unlink path failed: {:?}, error: {}", sock_path, e); + } + +- socket::bind(fd, &unix_addr)?; ++ // create '/run/sysmaster/notify' with mode 666 ++ let old_mask = stat::umask(Mode::from_bits_truncate(!0o666)); ++ let ret = socket::bind(fd, &unix_addr); ++ let _ = stat::umask(old_mask); ++ if let Err(e) = ret { ++ log::error!("Failed to bind socket {:?}: {}", sock_path, e); ++ return Err(e); ++ } + socket::setsockopt(fd, sockopt::PassCred, &true)?; + + log::debug!("set event fd is: {}", fd); +diff --git a/core/sysmaster/unit/util/unit_file.rs b/core/sysmaster/unit/util/unit_file.rs +index eb9404b..4f7078f 100644 +--- a/core/sysmaster/unit/util/unit_file.rs ++++ b/core/sysmaster/unit/util/unit_file.rs +@@ -105,7 +105,7 @@ impl UnitFileData { + if fs::metadata(path).is_err() { + return None; + } +- /* {/etc/sysmaster, /usr/lib/sysmaster}/foo.service.d */ ++ /* {/etc/sysmaster/system, /usr/lib/sysmaster/system}/foo.service.d */ + let pathd_str = format!("{path}/{name}.d"); + let dir = Path::new(&pathd_str); + if dir.is_dir() { +@@ -121,7 +121,7 @@ impl UnitFileData { + res.push(fragment); + } + } +- /* {/etc/sysmater, /usr/lib/sysmaster}/foo.service */ ++ /* {/etc/sysmater/system, /usr/lib/sysmaster/system}/foo.service */ + let config_path = Path::new(path).join(name); + if !config_path.exists() { + return None; +diff --git a/init/src/runtime/comm.rs b/init/src/runtime/comm.rs +index 92d52bc..c285ad7 100644 +--- a/init/src/runtime/comm.rs ++++ b/init/src/runtime/comm.rs +@@ -16,6 +16,7 @@ use nix::errno::Errno; + use nix::sys::epoll::EpollEvent; + use nix::sys::inotify::{AddWatchFlags, InitFlags, Inotify, WatchDescriptor}; + use nix::sys::socket::{self, AddressFamily, SockFlag, SockType, UnixAddr}; ++use nix::sys::stat::{self, Mode}; + use nix::unistd; + use std::os::unix::io::AsRawFd; + use std::os::unix::prelude::RawFd; +@@ -281,12 +282,16 @@ fn create_listen_fd(epoll: &Rc) -> Result<(i32, Inotify, WatchDescriptor) + None, + )?; + ++ // create '/run/sysmaster' with mode 755 + let sock_path = PathBuf::from(INIT_SOCKET); + let path = match sock_path.as_path().parent() { + None => return Err(Errno::EINVAL), + Some(v) => v, + }; +- if let Err(e) = fs::create_dir_all(path) { ++ let old_mask = stat::umask(Mode::from_bits_truncate(!0o755)); ++ let ret = fs::create_dir_all(path); ++ let _ = stat::umask(old_mask); ++ if let Err(e) = ret { + eprintln!("Failed to create directory {path:?}: {e}"); + return Err(Errno::from_i32( + e.raw_os_error().unwrap_or(Errno::EINVAL as i32), +@@ -297,8 +302,15 @@ fn create_listen_fd(epoll: &Rc) -> Result<(i32, Inotify, WatchDescriptor) + eprintln!("Failed to unlink path:{:?}, error:{}", sock_path, e); + } + ++ // create '/run/sysmaster/init' with mode 600 + let addr = UnixAddr::new(&sock_path)?; +- socket::bind(listen_fd, &addr)?; ++ let old_mask = stat::umask(Mode::from_bits_truncate(!0o600)); ++ let ret = socket::bind(listen_fd, &addr); ++ let _ = stat::umask(old_mask); ++ if let Err(e) = ret { ++ eprintln!("Failed to bind socket {sock_path:?}: {e}"); ++ return Err(e); ++ } + socket::listen(listen_fd, LISTEN_BACKLOG)?; + + let inotify = Inotify::init(InitFlags::all())?; +diff --git a/libs/basic/src/path_lookup.rs b/libs/basic/src/path_lookup.rs +index 4c9797d..e3ab1f2 100644 +--- a/libs/basic/src/path_lookup.rs ++++ b/libs/basic/src/path_lookup.rs +@@ -13,11 +13,11 @@ + //! the management of the unit file lookup path + + /// unit lookup path in /etc +-pub const ETC_SYSTEM_PATH: &str = "/etc/sysmaster"; ++pub const ETC_SYSTEM_PATH: &str = "/etc/sysmaster/system"; + /// unit lookup path in /run +-pub const RUN_SYSTEM_PATH: &str = "/run/sysmaster"; ++pub const RUN_SYSTEM_PATH: &str = "/run/sysmaster/system"; + /// unit lookup path in /usr/lib +-pub const LIB_SYSTEM_PATH: &str = "/usr/lib/sysmaster"; ++pub const LIB_SYSTEM_PATH: &str = "/usr/lib/sysmaster/system"; + + /// struct LookupPaths + #[derive(Debug, Clone)] +@@ -85,15 +85,19 @@ mod tests { + lp.init_lookup_paths(); + assert_eq!( + lp.search_path, +- vec!["/usr/lib/sysmaster", "/run/sysmaster", "/etc/sysmaster"] ++ vec![ ++ "/usr/lib/sysmaster/system", ++ "/run/sysmaster/system", ++ "/etc/sysmaster/system" ++ ] + ); + assert_eq!( + lp.preset_path, + vec![ +- "/etc/sysmaster/system-preset", +- "/usr/lib/sysmaster/system-preset" ++ "/etc/sysmaster/system/system-preset", ++ "/usr/lib/sysmaster/system/system-preset" + ] + ); +- assert_eq!(lp.persistent_path, "/etc/sysmaster") ++ assert_eq!(lp.persistent_path, "/etc/sysmaster/system") + } + } +diff --git a/tests/common/util_lib.sh b/tests/common/util_lib.sh +index 1878016..18de448 100644 +--- a/tests/common/util_lib.sh ++++ b/tests/common/util_lib.sh +@@ -1,9 +1,9 @@ + #!/usr/bin/env bash + + export EXPECT_FAIL=0 +-export SYSMST_LIB_PATH='/usr/lib/sysmaster' +-export SYSMST_ETC_PATH='/etc/sysmaster' +-export SYSMST_RUN_PATH='/run/sysmaster' ++export SYSMST_LIB_PATH='/usr/lib/sysmaster/system' ++export SYSMST_ETC_PATH='/etc/sysmaster/system' ++export SYSMST_RUN_PATH='/run/sysmaster/system' + export SYSMST_LOG='/opt/sysmaster.log' + export RELIAB_SWITCH_PATH='/run/sysmaster/reliability' + export RELIAB_SWITCH='switch.debug' +-- +2.33.0 + diff --git a/backport-fix-avoid-calling-init_lookup_paths-in-testcase.patch b/backport-fix-avoid-calling-init_lookup_paths-in-testcase.patch new file mode 100644 index 0000000..dd023a4 --- /dev/null +++ b/backport-fix-avoid-calling-init_lookup_paths-in-testcase.patch @@ -0,0 +1,102 @@ +From cf4539ac602c1bcf7dc1bf1664cba60118ccd576 Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Fri, 30 Jun 2023 10:57:34 +0800 +Subject: [PATCH] fix: avoid calling init_lookup_paths in testcase + +We know where our testcases are, so just push the directory into our search_path +--- + core/bin/manager/pre_install.rs | 14 ++++++++++++-- + core/bin/unit/entry/uentry.rs | 7 ++++++- + core/bin/unit/manager.rs | 7 ++++++- + core/bin/unit/test/mod.rs | 7 ++++++- + 4 files changed, 30 insertions(+), 5 deletions(-) + +diff --git a/core/bin/manager/pre_install.rs b/core/bin/manager/pre_install.rs +index 7762ecb..88150c0 100644 +--- a/core/bin/manager/pre_install.rs ++++ b/core/bin/manager/pre_install.rs +@@ -796,7 +796,12 @@ mod test { + #[test] + fn test_read_presets() { + let mut l_path = LookupPaths::new(); +- l_path.init_lookup_paths(); ++ let test_preset_dir = libtests::get_project_root() ++ .unwrap() ++ .join("tests/presets") ++ .to_string_lossy() ++ .to_string(); ++ l_path.preset_path.push(test_preset_dir); + let lookup_path = Rc::new(l_path); + + let install = Install::new(PresetMode::Enable, lookup_path); +@@ -815,7 +820,12 @@ mod test { + #[test] + fn test_preset_all() { + let mut l_path = LookupPaths::new(); +- l_path.init_lookup_paths(); ++ let test_preset_dir = libtests::get_project_root() ++ .unwrap() ++ .join("tests/presets") ++ .to_string_lossy() ++ .to_string(); ++ l_path.preset_path.push(test_preset_dir); + let lookup_path = Rc::new(l_path); + let install = Install::new(PresetMode::Enable, lookup_path); + assert!(install.preset_all().is_ok()); +diff --git a/core/bin/unit/entry/uentry.rs b/core/bin/unit/entry/uentry.rs +index 45f0e57..d2f5369 100644 +--- a/core/bin/unit/entry/uentry.rs ++++ b/core/bin/unit/entry/uentry.rs +@@ -783,7 +783,12 @@ mod tests { + let rentry = Rc::new(UnitRe::new(&reli)); + + let mut l_path = LookupPaths::new(); +- l_path.init_lookup_paths(); ++ let test_units_dir = libtests::get_project_root() ++ .unwrap() ++ .join("tests/test_units/") ++ .to_string_lossy() ++ .to_string(); ++ l_path.search_path.push(test_units_dir); + let lookup_path = Rc::new(l_path); + let unit_file = UnitFile::new(&lookup_path); + +diff --git a/core/bin/unit/manager.rs b/core/bin/unit/manager.rs +index 73fb593..0a3549f 100644 +--- a/core/bin/unit/manager.rs ++++ b/core/bin/unit/manager.rs +@@ -1403,7 +1403,12 @@ mod tests { + fn init_dm_for_test() -> (Rc, Rc, Rc) { + logger::init_log_to_console("manager test", log::LevelFilter::Trace); + let mut l_path = LookupPaths::new(); +- l_path.init_lookup_paths(); ++ let test_units_dir = libtests::get_project_root() ++ .unwrap() ++ .join("tests/test_units/") ++ .to_string_lossy() ++ .to_string(); ++ l_path.search_path.push(test_units_dir); + let lookup_path = Rc::new(l_path); + + let event = Rc::new(Events::new().unwrap()); +diff --git a/core/bin/unit/test/mod.rs b/core/bin/unit/test/mod.rs +index 8f2d120..2138ab6 100644 +--- a/core/bin/unit/test/mod.rs ++++ b/core/bin/unit/test/mod.rs +@@ -32,7 +32,12 @@ pub(crate) mod test_utils { + name: &str, + ) -> Rc { + let mut l_path = LookupPaths::new(); +- l_path.init_lookup_paths(); ++ let test_units_dir = libtests::get_project_root() ++ .unwrap() ++ .join("tests/test_units/") ++ .to_string_lossy() ++ .to_string(); ++ l_path.search_path.push(test_units_dir); + let lookup_path = Rc::new(l_path); + + let file = Rc::new(UnitFile::new(&lookup_path)); +-- +2.33.0 + diff --git a/backport-fix-call-clear_last_frame-before-early-return.patch b/backport-fix-call-clear_last_frame-before-early-return.patch new file mode 100644 index 0000000..cf01172 --- /dev/null +++ b/backport-fix-call-clear_last_frame-before-early-return.patch @@ -0,0 +1,87 @@ +From 2546fa929d682c61e179eac0a67e6d0da59ebd8a Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Fri, 7 Jul 2023 14:36:58 +0800 +Subject: [PATCH] fix: call clear_last_frame before early return + +This makes sure 'frame' is released +--- + core/sysmaster/manager/commands.rs | 46 ++++++++++++++++++------------ + 1 file changed, 28 insertions(+), 18 deletions(-) + +diff --git a/core/sysmaster/manager/commands.rs b/core/sysmaster/manager/commands.rs +index 6e1da40..ad3e97f 100644 +--- a/core/sysmaster/manager/commands.rs ++++ b/core/sysmaster/manager/commands.rs +@@ -31,7 +31,10 @@ pub(super) struct Commands { + socket_fd: i32, + } + +-impl Commands { ++impl Commands ++where ++ T: ExecuterAction, ++{ + pub(super) fn new(relir: &Rc, comm_action: T) -> Self { + /* The socket is used to communicate with sctl, panic if any of the following steps fail. */ + let sctl_socket_path = Path::new(SCTL_SOCKET); +@@ -65,22 +68,8 @@ impl Commands { + socket_fd, + } + } +-} + +-impl Source for Commands +-where +- T: ExecuterAction, +-{ +- fn event_type(&self) -> EventType { +- EventType::Io +- } +- +- fn epoll_event(&self) -> u32 { +- (libc::EPOLLIN) as u32 +- } +- +- fn dispatch(&self, _e: &Events) -> i32 { +- self.reli.set_last_frame1(ReliLastFrame::CmdOp as u32); ++ pub fn dispatch_commands(&self) -> i32 { + let client = match socket::accept(self.socket_fd) { + Err(e) => { + log::error!("Failed to accept connection: {}, ignoring.", e); +@@ -104,10 +93,31 @@ where + Err(e) => log::error!("Commands failed: {:?}", e), + } + basic::fd_util::close(client); +- self.reli.clear_last_frame(); +- + 0 + } ++} ++ ++impl Source for Commands ++where ++ T: ExecuterAction, ++{ ++ fn event_type(&self) -> EventType { ++ EventType::Io ++ } ++ ++ fn epoll_event(&self) -> u32 { ++ (libc::EPOLLIN) as u32 ++ } ++ ++ fn dispatch(&self, _e: &Events) -> i32 { ++ self.reli.set_last_frame1(ReliLastFrame::CmdOp as u32); ++ /* NOTE: we must call clear_last_frame before return. If we don't do this, the allocated ++ * vector "frame" in reli.set_frame will be leaked, and become larger and larger until ++ * triggers a panic. */ ++ let ret = self.dispatch_commands(); ++ self.reli.clear_last_frame(); ++ ret ++ } + + fn token(&self) -> u64 { + let data: u64 = unsafe { std::mem::transmute(self) }; +-- +2.33.0 + diff --git a/backport-fix-check-if-the-message-is-truncated.patch b/backport-fix-check-if-the-message-is-truncated.patch new file mode 100644 index 0000000..984bb17 --- /dev/null +++ b/backport-fix-check-if-the-message-is-truncated.patch @@ -0,0 +1,42 @@ +From 403e74d159d0937e5e0f5c67a59483b8fce41890 Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Fri, 14 Jul 2023 15:47:15 +0800 +Subject: [PATCH] fix: check if the message is truncated + +--- + core/sysmaster/unit/notify.rs | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/core/sysmaster/unit/notify.rs b/core/sysmaster/unit/notify.rs +index f35ed91..4f3cc15 100644 +--- a/core/sysmaster/unit/notify.rs ++++ b/core/sysmaster/unit/notify.rs +@@ -224,6 +224,12 @@ impl Notify { + let msgs = socket::recvmsg::<()>(self.rawfd(), &mut iov, Some(&mut space), flags) + .context(NixSnafu)?; + ++ if msgs.flags.contains(MsgFlags::MSG_CTRUNC) { ++ return Err(Error::Nix { ++ source: nix::Error::EXFULL, ++ }); ++ } ++ + // check: peek == pop + let (received_cred, received_fds) = notify_trans_recvmsg(&msgs); + if get_pid_from_cred(&received_cred) != pid { +@@ -279,6 +285,12 @@ fn notify_peek_pid(fd: RawFd, flags: MsgFlags) -> Result { + let msgs = + socket::recvmsg::<()>(fd, &mut iov, Some(&mut space), peek_flags).context(NixSnafu)?; + ++ if msgs.flags.contains(MsgFlags::MSG_CTRUNC) { ++ return Err(Error::Nix { ++ source: nix::Error::EXFULL, ++ }); ++ } ++ + // get message information + let (received_cred, received_fds) = notify_trans_recvmsg(&msgs); + for fd in received_fds.iter() { +-- +2.33.0 + diff --git a/backport-fix-check-if-the-words-is-empty-before-using-it.patch b/backport-fix-check-if-the-words-is-empty-before-using-it.patch new file mode 100644 index 0000000..14ddf1a --- /dev/null +++ b/backport-fix-check-if-the-words-is-empty-before-using-it.patch @@ -0,0 +1,26 @@ +From 9a1154cb9c038921d118f576c691c823ca32995d Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Fri, 14 Jul 2023 15:46:21 +0800 +Subject: [PATCH] fix: check if the words is empty before using it + +--- + core/sysmaster/unit/rentry.rs | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/core/sysmaster/unit/rentry.rs b/core/sysmaster/unit/rentry.rs +index 312347e..5d7360c 100644 +--- a/core/sysmaster/unit/rentry.rs ++++ b/core/sysmaster/unit/rentry.rs +@@ -30,6 +30,9 @@ use sysmaster::unit::{UnitRelations, UnitType}; + + pub(crate) fn unit_name_to_type(unit_name: &str) -> UnitType { + let words: Vec<&str> = unit_name.split('.').collect(); ++ if words.is_empty() { ++ return UnitType::UnitTypeInvalid; ++ } + UnitType::from_str(words[words.len() - 1]).unwrap_or(UnitType::UnitTypeInvalid) + } + +-- +2.33.0 + diff --git a/backport-fix-devmaster-deal-with-fd-leak.patch b/backport-fix-devmaster-deal-with-fd-leak.patch new file mode 100644 index 0000000..ed1d3e2 --- /dev/null +++ b/backport-fix-devmaster-deal-with-fd-leak.patch @@ -0,0 +1,248 @@ +From ae19e57d309303b4f8e16ea26dbe6c6c7fd04f7d Mon Sep 17 00:00:00 2001 +From: chenjiayi +Date: Tue, 27 Jun 2023 13:57:20 +0800 +Subject: [PATCH] fix(devmaster): deal with fd leak + +RawFd will not be automatically closed when it is dropped. Use std::fs::File +or nix::dir::Dir to take the RawFd when opening the file or directory, which +can automatically close the RawFd when the variable is dropped. + +Also rename the fd type from i32 to RawFd to better declare the file descriptor +type. +--- + core/bin/mount/setup.rs | 9 +- + libs/basic/src/fd_util.rs | 18 ++-- + libs/basic/src/fs_util.rs | 28 +++--- + libs/basic/src/mount_util.rs | 4 +- + 8 files changed, 146 insertions(+), 107 deletions(-) + +diff --git a/core/bin/mount/setup.rs b/core/bin/mount/setup.rs +index 6a13626..e7ca9df 100644 +--- a/core/bin/mount/setup.rs ++++ b/core/bin/mount/setup.rs +@@ -23,6 +23,7 @@ use nix::{ + sys::stat::Mode, + unistd::AccessFlags, + }; ++use std::os::unix::prelude::AsRawFd; + use std::{ + collections::HashMap, + fs, +@@ -361,7 +362,7 @@ impl MountPoint { + // symlink + + let path = Path::new(&self.target); +- let ret = fs_util::open_parent( ++ let file = fs_util::open_parent( + path, + OFlag::O_PATH | OFlag::O_CLOEXEC, + Mode::from_bits(0).unwrap(), +@@ -369,7 +370,11 @@ impl MountPoint { + + let last_file_name = path.file_name().unwrap_or_default(); + +- let ret = mount_util::mount_point_fd_valid(ret, last_file_name.to_str().unwrap(), flags)?; ++ let ret = mount_util::mount_point_fd_valid( ++ file.as_raw_fd(), ++ last_file_name.to_str().unwrap(), ++ flags, ++ )?; + + Ok(ret) + } +diff --git a/libs/basic/src/fd_util.rs b/libs/basic/src/fd_util.rs +index 0d41966..210c830 100644 +--- a/libs/basic/src/fd_util.rs ++++ b/libs/basic/src/fd_util.rs +@@ -18,6 +18,8 @@ use nix::{ + ioctl_read, + sys::stat::{Mode, SFlag}, + }; ++use std::os::unix::prelude::FromRawFd; ++use std::{fs::File, os::unix::prelude::RawFd}; + + /// check if the given stat.st_mode is regular file + pub fn stat_is_reg(st_mode: u32) -> bool { +@@ -30,7 +32,7 @@ pub fn stat_is_char(st_mode: u32) -> bool { + } + + /// +-pub fn fd_nonblock(fd: i32, nonblock: bool) -> Result<()> { ++pub fn fd_nonblock(fd: RawFd, nonblock: bool) -> Result<()> { + assert!(fd >= 0); + + let flags = nix::fcntl::fcntl(fd, FcntlArg::F_GETFL).context(NixSnafu)?; +@@ -51,7 +53,7 @@ pub fn fd_nonblock(fd: i32, nonblock: bool) -> Result<()> { + } + + /// +-pub fn fd_cloexec(fd: i32, cloexec: bool) -> Result<()> { ++pub fn fd_cloexec(fd: RawFd, cloexec: bool) -> Result<()> { + assert!(fd >= 0); + + let flags = nix::fcntl::fcntl(fd, FcntlArg::F_GETFD).context(NixSnafu)?; +@@ -69,7 +71,7 @@ pub fn fd_cloexec(fd: i32, cloexec: bool) -> Result<()> { + } + + /// +-pub fn fd_is_cloexec(fd: i32) -> bool { ++pub fn fd_is_cloexec(fd: RawFd) -> bool { + assert!(fd >= 0); + + let flags = nix::fcntl::fcntl(fd, FcntlArg::F_GETFD).unwrap_or(0); +@@ -78,7 +80,7 @@ pub fn fd_is_cloexec(fd: i32) -> bool { + } + + /// +-pub fn close(fd: i32) { ++pub fn close(fd: RawFd) { + if let Err(e) = nix::unistd::close(fd) { + log::warn!("close fd {} failed, errno: {}", fd, e); + } +@@ -90,12 +92,12 @@ pub fn close(fd: i32) { + /// this function can not work on sockets, as they can not be opened + /// + /// note that this function implicitly reset the read index to zero +-pub fn fd_reopen(fd: i32, oflags: OFlag) -> Result { ++pub fn fd_reopen(fd: RawFd, oflags: OFlag) -> Result { + if oflags.intersects(OFlag::O_DIRECTORY) { + let new_fd = nix::fcntl::openat(fd, ".", oflags, nix::sys::stat::Mode::empty()) + .map_err(|e| Error::Nix { source: e })?; + +- return Ok(new_fd); ++ return Ok(unsafe { File::from_raw_fd(new_fd) }); + } + + match nix::fcntl::open( +@@ -103,7 +105,7 @@ pub fn fd_reopen(fd: i32, oflags: OFlag) -> Result { + oflags, + nix::sys::stat::Mode::empty(), + ) { +- Ok(n) => Ok(n), ++ Ok(n) => Ok(unsafe { File::from_raw_fd(n) }), + Err(e) => { + if e != Errno::ENOENT { + return Err(Error::Nix { source: e }); +@@ -137,7 +139,7 @@ ioctl_read!( + ); + + /// get the diskseq according to fd +-pub fn fd_get_diskseq(fd: i32) -> Result { ++pub fn fd_get_diskseq(fd: RawFd) -> Result { + let mut diskseq: u64 = 0; + let ptr: *mut u64 = &mut diskseq; + unsafe { +diff --git a/libs/basic/src/fs_util.rs b/libs/basic/src/fs_util.rs +index 3f72658..8a8f276 100644 +--- a/libs/basic/src/fs_util.rs ++++ b/libs/basic/src/fs_util.rs +@@ -22,16 +22,20 @@ use nix::{ + use pathdiff::diff_paths; + use rand::Rng; + use std::{ +- ffi::CString, fs::remove_dir, io::ErrorKind, os::unix::prelude::PermissionsExt, path::Path, ++ ffi::CString, ++ fs::{remove_dir, File}, ++ io::ErrorKind, ++ os::unix::prelude::{AsRawFd, FromRawFd, PermissionsExt, RawFd}, ++ path::Path, + }; + + /// open the parent directory of path +-pub fn open_parent(path: &Path, flags: OFlag, mode: Mode) -> Result { ++pub fn open_parent(path: &Path, flags: OFlag, mode: Mode) -> Result { + let parent = path.parent().ok_or(Error::Nix { + source: nix::errno::Errno::EINVAL, + })?; + +- nix::fcntl::open(parent, flags, mode).context(NixSnafu) ++ Ok(unsafe { File::from_raw_fd(nix::fcntl::open(parent, flags, mode).context(NixSnafu)?) }) + } + + /// create symlink link_name -> target +@@ -39,7 +43,7 @@ pub fn symlink(target: &str, link: &str, relative: bool) -> Result<()> { + let link_path = Path::new(&link); + let target_path = Path::new(&target); + +- let (target_path, dirfd) = if relative { ++ let (target_path, dir) = if relative { + let link_path_parent = link_path.parent().ok_or(Error::NotExisted { + what: format!("{}'s parent", link_path.to_string_lossy()), + })?; +@@ -51,19 +55,19 @@ pub fn symlink(target: &str, link: &str, relative: bool) -> Result<()> { + Mode::from_bits(0).unwrap(), + ) + .context(NixSnafu)?; +- (rel_path, Some(fd)) ++ (rel_path, Some(unsafe { File::from_raw_fd(fd) })) + } else { + (target_path.to_path_buf(), None) + }; + + let mut rng = rand::thread_rng(); +- + let tmp_to = format!("{}.{}", link, rng.gen::()); ++ let raw_fd = dir.map(|f| f.as_raw_fd()); + +- nix::unistd::symlinkat(target_path.as_path(), dirfd, tmp_to.as_str()).context(NixSnafu)?; ++ nix::unistd::symlinkat(target_path.as_path(), raw_fd, tmp_to.as_str()).context(NixSnafu)?; + +- if let Err(e) = renameat(dirfd, tmp_to.as_str(), dirfd, link_path) { +- let _ = unlinkat(dirfd, tmp_to.as_str(), UnlinkatFlags::NoRemoveDir); ++ if let Err(e) = renameat(raw_fd, tmp_to.as_str(), raw_fd, link_path) { ++ let _ = unlinkat(raw_fd, tmp_to.as_str(), UnlinkatFlags::NoRemoveDir); + return Err(Error::Nix { source: e }); + } + +@@ -71,7 +75,7 @@ pub fn symlink(target: &str, link: &str, relative: bool) -> Result<()> { + } + + /// chmod based on fd opened with O_PATH +-pub fn fchmod_opath(fd: i32, mode: mode_t) -> Result<()> { ++pub fn fchmod_opath(fd: RawFd, mode: mode_t) -> Result<()> { + let fd_path = format_proc_fd_path!(fd); + + let mut perms = std::fs::metadata(&fd_path).context(IoSnafu)?.permissions(); +@@ -91,7 +95,7 @@ pub fn chmod(path: &str, mode: mode_t) -> Result<()> { + /// the access mode is above the old mode under old owner or the new + /// mode under new owner. + pub fn fchmod_and_chown( +- fd: i32, ++ fd: RawFd, + path: &str, + mode: Option, + uid: Option, +@@ -151,7 +155,7 @@ pub fn fchmod_and_chown( + } + + /// Update the timestamp of a file with fd. If 'ts' is not provided, use the current timestamp by default. +-pub fn futimens_opath(fd: i32, ts: Option<[timespec; 2]>) -> Result<()> { ++pub fn futimens_opath(fd: RawFd, ts: Option<[timespec; 2]>) -> Result<()> { + let fd_path = format_proc_fd_path!(fd); + let c_string = + CString::new(fd_path.clone()).map_err(|e| crate::Error::NulError { source: e })?; +diff --git a/libs/basic/src/mount_util.rs b/libs/basic/src/mount_util.rs +index 3b041d3..72a11d3 100644 +--- a/libs/basic/src/mount_util.rs ++++ b/libs/basic/src/mount_util.rs +@@ -11,6 +11,8 @@ + // See the Mulan PSL v2 for more details. + + //! ++use std::os::unix::prelude::RawFd; ++ + use crate::error::*; + use nix::{ + fcntl::AtFlags, +@@ -18,7 +20,7 @@ use nix::{ + }; + + /// +-pub fn mount_point_fd_valid(fd: i32, file_name: &str, flags: AtFlags) -> Result { ++pub fn mount_point_fd_valid(fd: RawFd, file_name: &str, flags: AtFlags) -> Result { + assert!(fd >= 0); + + let flags = if flags.contains(AtFlags::AT_SYMLINK_FOLLOW) { +-- +2.33.0 + diff --git a/backport-fix-downgrade-the-time-crate-from-0.3.x-to-0.1.45.patch b/backport-fix-downgrade-the-time-crate-from-0.3.x-to-0.1.45.patch new file mode 100644 index 0000000..2d5162f --- /dev/null +++ b/backport-fix-downgrade-the-time-crate-from-0.3.x-to-0.1.45.patch @@ -0,0 +1,69 @@ +From d50fcced7eea0ceabf74191d3de4d08420120a3a Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Mon, 24 Jul 2023 19:12:16 +0800 +Subject: [PATCH] fix: downgrade the time crate from 0.3.x to 0.1.45 + +--- + libs/basic/Cargo.toml | 2 +- + libs/basic/src/logger.rs | 23 +++++++++++------------ + 2 files changed, 12 insertions(+), 13 deletions(-) + +diff --git a/libs/basic/Cargo.toml b/libs/basic/Cargo.toml +index 29f97a3..d0dd4fb 100644 +--- a/libs/basic/Cargo.toml ++++ b/libs/basic/Cargo.toml +@@ -21,7 +21,7 @@ lazy_static = "1.4.0" + bitflags = "1.3.2" + pkg-config = "0.3" + rand = "0.4.6" +-time = {version = "=0.3.5", features = ["formatting", "macros", "local-offset"] } ++time = "=0.1.45" + constants = { path = "../constants"} + + [dev-dependencies] +diff --git a/libs/basic/src/logger.rs b/libs/basic/src/logger.rs +index ae12c36..9f96316 100644 +--- a/libs/basic/src/logger.rs ++++ b/libs/basic/src/logger.rs +@@ -36,7 +36,6 @@ use log4rs::{ + encode::pattern::PatternEncoder, + }; + use nix::libc; +-use time::macros::offset; + + use crate::Error; + +@@ -69,19 +68,19 @@ impl log::Log for LogPlugin { + } + + fn write_msg_common(writer: &mut impl Write, module: &str, msg: String) { +- let now = match time::OffsetDateTime::now_local() { +- Ok(v) => v, +- Err(_) => time::OffsetDateTime::now_utc().to_offset(offset!(+8)), +- }; +- +- let format = time::macros::format_description!("[year]-[month]-[day] [hour]:[minute]:[second]"); +- let now = match now.format(&format) { +- Err(_) => "[unknown time]".to_string(), +- Ok(v) => v, +- }; ++ let now = time::now(); ++ let now_str = format!( ++ "{:0>4}-{:0>2}-{:0>2} {:0>2}:{:0>2}:{:0>2} ", ++ now.tm_year + 1900, /* tm_year is years since 1900 */ ++ now.tm_mon + 1, /* tm_mon is months since Jan: [0, 11] */ ++ now.tm_mday, ++ now.tm_hour, ++ now.tm_min, ++ now.tm_sec ++ ); + + /* 1. Write time */ +- if let Err(e) = writer.write(format!("{now} ").as_bytes()) { ++ if let Err(e) = writer.write(now_str.as_bytes()) { + println!("Failed to log time message: {e}"); + return; + } +-- +2.33.0 + diff --git a/backport-fix-fix-the-type-error-of-test_get_service_type.patch b/backport-fix-fix-the-type-error-of-test_get_service_type.patch new file mode 100644 index 0000000..03bc732 --- /dev/null +++ b/backport-fix-fix-the-type-error-of-test_get_service_type.patch @@ -0,0 +1,34 @@ +From 2d3c357ab61bbe2b6b5cb24ccb964105a250d5b7 Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Thu, 20 Jul 2023 14:22:04 +0800 +Subject: [PATCH] fix: fix the type error of test_get_service_type() + +--- + coms/service/src/config.rs | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/coms/service/src/config.rs b/coms/service/src/config.rs +index ec2ebf4..5205351 100644 +--- a/coms/service/src/config.rs ++++ b/coms/service/src/config.rs +@@ -199,6 +199,7 @@ impl ServiceConfigData { + mod tests { + use crate::comm::ServiceUnitComm; + use crate::config::ServiceConfig; ++ use crate::rentry::ServiceType; + use libtests::get_project_root; + use std::rc::Rc; + +@@ -228,7 +229,7 @@ mod tests { + let comm = Rc::new(ServiceUnitComm::new()); + let config = ServiceConfig::new(&comm); + +- let result = config.load(paths, false); +- assert_eq!(config.service_type(), b"Simple") ++ assert!(config.load(paths, false).is_ok()); ++ assert_eq!(config.service_type(), ServiceType::Simple) + } + } +-- +2.33.0 + diff --git a/backport-fix-ignore-auto-generated-toml-file-in-tests-test_un.patch b/backport-fix-ignore-auto-generated-toml-file-in-tests-test_un.patch new file mode 100644 index 0000000..66209de --- /dev/null +++ b/backport-fix-ignore-auto-generated-toml-file-in-tests-test_un.patch @@ -0,0 +1,21 @@ +From d1eb397bbf6760569c3043119c6a6cb733ad301f Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Fri, 30 Jun 2023 10:52:55 +0800 +Subject: [PATCH] fix: ignore auto generated toml file in tests/test_units + +--- + .gitignore | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/.gitignore b/.gitignore +index 2408785..e8437ea 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -4,3 +4,4 @@ Cargo.lock + tests/**/*.log + /site + libs/blkid_rs/src/libblkid.rs ++tests/test_units/*.toml +-- +2.33.0 + diff --git a/backport-fix-init-does-not-enter-the-freeze-during-normal-run.patch b/backport-fix-init-does-not-enter-the-freeze-during-normal-run.patch new file mode 100644 index 0000000..12f4957 --- /dev/null +++ b/backport-fix-init-does-not-enter-the-freeze-during-normal-run.patch @@ -0,0 +1,775 @@ +From 2c6d13f3fac35b901b39a851eea2662ae6d02bf1 Mon Sep 17 00:00:00 2001 +From: huyubiao +Date: Thu, 29 Jun 2023 21:40:53 +0800 +Subject: [PATCH] fix: init does not enter the freeze during normal running + +--- + core/bin/unit/notify.rs | 4 +- + exts/init/src/main.rs | 21 ++-- + exts/init/src/runtime/comm.rs | 163 ++++++++++++++++++++----------- + exts/init/src/runtime/epoll.rs | 14 ++- + exts/init/src/runtime/mod.rs | 51 ++++------ + exts/init/src/runtime/signals.rs | 95 ++++++++---------- + exts/init/src/runtime/timer.rs | 58 ++++++++--- + libs/constants/src/lib.rs | 3 + + 8 files changed, 226 insertions(+), 183 deletions(-) + +diff --git a/core/bin/unit/notify.rs b/core/bin/unit/notify.rs +index f824725..d23a725 100644 +--- a/core/bin/unit/notify.rs ++++ b/core/bin/unit/notify.rs +@@ -109,7 +109,7 @@ impl NotifyManager { + } + } + +-const NOTIFY_INVALID_FD: i32 = -1; ++use constants::INVALID_FD; + const NOTIFY_INVALID_PID: libc::pid_t = -1; + + struct Notify { +@@ -135,7 +135,7 @@ impl Notify { + rentry: Rc::clone(rentryr), + db: Rc::clone(dbr), + config: Rc::clone(configr), +- fd: RefCell::new(NOTIFY_INVALID_FD), ++ fd: RefCell::new(INVALID_FD), + } + } + +diff --git a/exts/init/src/main.rs b/exts/init/src/main.rs +index 587077e..fbd77b9 100644 +--- a/exts/init/src/main.rs ++++ b/exts/init/src/main.rs +@@ -23,21 +23,14 @@ fn main() { + // Run: Monitor the sysmaster's liveliness and acceptance of message. + // Unrecover: On-site problem collection or recreate new sysmaster. + match RunTime::new(cmd) { +- Ok(mut run_time) => { +- loop { +- let state = run_time.state(); +- let ret = match state { +- InitState::Reexec => run_time.reexec(), +- InitState::Run => run_time.run(), +- InitState::Unrecover => run_time.unrecover(), +- }; +- if let Err(err) = ret { +- eprintln!("Failed to {:?}:{:?} ", state, err); +- break; +- } ++ Ok(mut run_time) => loop { ++ let state = run_time.state(); ++ match state { ++ InitState::Reexec => run_time.reexec(), ++ InitState::Run => run_time.run(), ++ InitState::Unrecover => run_time.unrecover(), + } +- run_time.clear(); +- } ++ }, + Err(err) => eprintln!( + "Failed to new init, it may be necessary to run it as root :{:?}", + err +diff --git a/exts/init/src/runtime/comm.rs b/exts/init/src/runtime/comm.rs +index 1a0d0ca..8f71511 100644 +--- a/exts/init/src/runtime/comm.rs ++++ b/exts/init/src/runtime/comm.rs +@@ -14,18 +14,18 @@ use super::epoll::Epoll; + use super::timer::Timer; + use nix::errno::Errno; + use nix::sys::epoll::EpollEvent; ++use nix::sys::inotify::{AddWatchFlags, InitFlags, Inotify, WatchDescriptor}; + use nix::sys::socket::{self, AddressFamily, SockFlag, SockType, UnixAddr}; + use nix::unistd; ++use std::os::unix::io::AsRawFd; + use std::os::unix::prelude::RawFd; + use std::rc::Rc; +-use std::str; +-use std::{fs, path::PathBuf}; ++use std::{fs, path::PathBuf, str}; + + const LISTEN_BACKLOG: usize = 10; +-const INVALID_FD: i32 = -1; + const ACCEPT_COUNT: i32 = 3; + const BUF_SIZE: usize = 16; //The communication string length is fixed to 16 characters. +-use constants::{ALIVE, INIT_SOCKET}; ++use constants::{ALIVE, INIT_SOCKET, INVALID_FD}; + + pub struct Comm { + epoll: Rc, +@@ -33,6 +33,8 @@ pub struct Comm { + connect_fd: RawFd, + online_fd: RawFd, // Specsify either listen_fd or connect_fd. + timer: Timer, ++ inotify: Inotify, ++ wd: WatchDescriptor, + } + + #[derive(PartialEq, Eq)] +@@ -47,28 +49,7 @@ impl Comm { + pub fn new(epoll: &Rc, time_wait: i64, time_cnt: i64) -> Result { + let timer = Timer::new(epoll, time_wait, time_cnt)?; + +- let sock_path = PathBuf::from(INIT_SOCKET); +- let listen_fd = socket::socket( +- AddressFamily::Unix, +- SockType::Stream, +- SockFlag::SOCK_CLOEXEC, +- None, +- )?; +- +- let parent_path = sock_path.as_path().parent(); +- match parent_path { +- Some(path) => fs::create_dir_all(path) +- .map_err(|e| Errno::from_i32(e.raw_os_error().unwrap_or(Errno::EINVAL as i32)))?, +- None => return Err(Errno::EINVAL), +- } +- +- if let Err(e) = unistd::unlink(&sock_path) { +- eprintln!("Failed to unlink path:{:?}, error:{}", sock_path, e); +- } +- +- let addr = UnixAddr::new(&sock_path)?; +- socket::bind(listen_fd, &addr)?; +- socket::listen(listen_fd, LISTEN_BACKLOG)?; ++ let (listen_fd, inotify, wd) = create_listen_fd(epoll)?; + + let mut comm = Comm { + epoll: epoll.clone(), +@@ -76,51 +57,50 @@ impl Comm { + connect_fd: INVALID_FD, + online_fd: INVALID_FD, + timer, ++ inotify, ++ wd, + }; + + comm.set_online_fd(comm.listen_fd)?; +- + Ok(comm) + } + + pub fn is_fd(&self, fd: RawFd) -> bool { +- if fd == self.online_fd || fd == self.timer.fd() { +- return true; +- } +- false ++ fd == self.online_fd || fd == self.timer.fd() || fd == self.inotify.as_raw_fd() + } + +- pub fn proc(&mut self, event: EpollEvent) -> Result { ++ pub fn proc(&mut self, event: EpollEvent) -> CommType { + if self.timer.fd() as u64 == event.data() { +- if self.timer.is_time_out(event)? { +- return Ok(CommType::PipTMOUT); ++ if self.timer.is_time_out(event) { ++ return CommType::PipTMOUT; + } +- return Ok(CommType::Succeed); ++ return CommType::Succeed; ++ } ++ ++ if self.inotify.as_raw_fd() as u64 == event.data() { ++ // Dont self.inotify.read_events(), because if recover fails, event can be retrieved to recover again. ++ return self.recover(); ++ } ++ ++ // When the program runs normally, listen_fd will not be closed, ++ // but connect_fd will be closed during listening. ++ if self.listen_fd as u64 == event.data() && self.epoll.is_err(event) { ++ return self.recover(); + } + +- // When online_fd fails, ensure that connect_fd is closed, and then execute again after timeout. + if self.online_fd as u64 == event.data() { + match self.online_fd { +- x if x == self.listen_fd => return self.listen_proc(event), ++ x if x == self.listen_fd => return self.listen_proc(), + x if x == self.connect_fd => return self.connect_proc(event), + _ => {} + } + } +- Ok(CommType::Succeed) ++ CommType::Succeed + } + + pub fn finish(&mut self) { + _ = self.set_online_fd(self.listen_fd); +- } +- +- pub fn clear(&mut self) { +- self.epoll.safe_close(self.listen_fd); +- self.listen_fd = INVALID_FD; +- +- self.epoll.safe_close(self.connect_fd); +- self.connect_fd = INVALID_FD; +- +- self.timer.clear(); ++ self.timer.reset(); + } + + fn connect(&mut self) -> Result<(), Errno> { +@@ -223,21 +203,18 @@ impl Comm { + Ok(()) + } + +- fn listen_proc(&mut self, event: EpollEvent) -> Result { +- if self.epoll.is_err(event) { +- return Err(Errno::EINVAL); +- } ++ fn listen_proc(&mut self) -> CommType { + if self.connect().is_err() { +- return Ok(CommType::PipOFF); ++ return CommType::PipOFF; + } + self.timer.reset(); +- Ok(CommType::PipON) ++ CommType::PipON + } + +- fn connect_proc(&mut self, event: EpollEvent) -> Result { ++ fn connect_proc(&mut self, event: EpollEvent) -> CommType { + if self.epoll.is_err(event) { + _ = self.set_online_fd(self.listen_fd); +- return Ok(CommType::PipOFF); ++ return CommType::PipOFF; + } + match self.recv_msg() { + Ok(buf) => { +@@ -252,6 +229,78 @@ impl Comm { + unistd::sleep(1); + } + } +- Ok(CommType::Succeed) ++ CommType::Succeed + } ++ ++ fn recover(&mut self) -> CommType { ++ match create_listen_fd(&self.epoll) { ++ Ok((listen_fd, inotify, wd)) => { ++ self.epoll.safe_close(self.listen_fd); ++ self.epoll.safe_close(self.inotify.as_raw_fd()); ++ self.listen_fd = listen_fd; ++ self.inotify = inotify; ++ self.wd = wd; ++ eprintln!("comm recover"); ++ if self.online_fd == self.connect_fd { ++ // The socket file(INIT_SOCKET) cannot be used when connecting, ++ // so recreate the socket file(INIT_SOCKET) and return success. ++ return CommType::Succeed; ++ } else { ++ // If init is in the listening state, ++ // the sysmaster cannot be connected through the old socket file(INIT_SOCKET) at this time, ++ // we must recreate the socket file and then reexec the sysmaster. ++ return CommType::PipTMOUT; ++ } ++ } ++ Err(e) => { ++ eprintln!("Failed to create_listen_fd:{:?}", e); ++ } ++ } ++ CommType::Succeed ++ } ++} ++ ++impl Drop for Comm { ++ fn drop(&mut self) { ++ self.epoll.safe_close(self.listen_fd); ++ self.listen_fd = INVALID_FD; ++ ++ self.epoll.safe_close(self.connect_fd); ++ self.connect_fd = INVALID_FD; ++ ++ let _ = self.inotify.rm_watch(self.wd); ++ self.epoll.safe_close(self.inotify.as_raw_fd()); ++ } ++} ++ ++fn create_listen_fd(epoll: &Rc) -> Result<(i32, Inotify, WatchDescriptor), Errno> { ++ let listen_fd = socket::socket( ++ AddressFamily::Unix, ++ SockType::Stream, ++ SockFlag::SOCK_CLOEXEC, ++ None, ++ )?; ++ ++ let sock_path = PathBuf::from(INIT_SOCKET); ++ let parent_path = sock_path.as_path().parent(); ++ match parent_path { ++ Some(path) => fs::create_dir_all(path) ++ .map_err(|e| Errno::from_i32(e.raw_os_error().unwrap_or(Errno::EINVAL as i32)))?, ++ None => return Err(Errno::EINVAL), ++ } ++ ++ if let Err(e) = unistd::unlink(&sock_path) { ++ eprintln!("Failed to unlink path:{:?}, error:{}", sock_path, e); ++ } ++ ++ let addr = UnixAddr::new(&sock_path)?; ++ socket::bind(listen_fd, &addr)?; ++ socket::listen(listen_fd, LISTEN_BACKLOG)?; ++ ++ let inotify = Inotify::init(InitFlags::all())?; ++ ++ let wd = inotify.add_watch(INIT_SOCKET, AddWatchFlags::IN_ALL_EVENTS)?; ++ ++ epoll.register(inotify.as_raw_fd())?; ++ Ok((listen_fd, inotify, wd)) + } +diff --git a/exts/init/src/runtime/epoll.rs b/exts/init/src/runtime/epoll.rs +index ad7475f..6c21bbc 100644 +--- a/exts/init/src/runtime/epoll.rs ++++ b/exts/init/src/runtime/epoll.rs +@@ -10,6 +10,7 @@ + // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + // See the Mulan PSL v2 for more details. + ++use constants::INVALID_FD; + use nix::errno::Errno; + use nix::sys::epoll::{self, EpollEvent, EpollFlags, EpollOp}; + use nix::unistd; +@@ -21,7 +22,7 @@ pub struct Epoll { + + impl Epoll { + pub(crate) fn new() -> Result { +- let epoll_fd = epoll::epoll_create1(epoll::EpollCreateFlags::empty())?; ++ let epoll_fd = epoll::epoll_create1(epoll::EpollCreateFlags::EPOLL_CLOEXEC)?; + Ok(Epoll { epoll_fd }) + } + +@@ -61,10 +62,6 @@ impl Epoll { + false + } + +- pub(crate) fn clear(&self) { +- self.safe_close(self.epoll_fd); +- } +- + pub(crate) fn safe_close(&self, fd: RawFd) { + if fd <= 0 { + return; +@@ -75,3 +72,10 @@ impl Epoll { + }; + } + } ++ ++impl Drop for Epoll { ++ fn drop(&mut self) { ++ self.safe_close(self.epoll_fd); ++ self.epoll_fd = INVALID_FD; ++ } ++} +diff --git a/exts/init/src/runtime/mod.rs b/exts/init/src/runtime/mod.rs +index d11d8f2..e81a513 100644 +--- a/exts/init/src/runtime/mod.rs ++++ b/exts/init/src/runtime/mod.rs +@@ -81,7 +81,7 @@ impl RunTime { + self.state + } + +- pub fn reexec(&mut self) -> Result<(), Errno> { ++ pub fn reexec(&mut self) { + if self.need_reexec { + self.reexec_manager(); + } +@@ -89,43 +89,33 @@ impl RunTime { + let event = self.epoll.wait_one(); + let fd = event.data() as RawFd; + match fd { +- _x if self.comm.is_fd(fd) => self.reexec_comm_dispatch(event)?, +- _x if self.signals.is_fd(fd) => self.reexec_signal_dispatch(event)?, ++ _x if self.comm.is_fd(fd) => self.reexec_comm_dispatch(event), ++ _x if self.signals.is_fd(fd) => self.reexec_signal_dispatch(event), + _ => self.epoll.safe_close(fd), + } +- Ok(()) + } + +- pub fn run(&mut self) -> Result<(), Errno> { ++ pub fn run(&mut self) { + let event = self.epoll.wait_one(); + let fd = event.data() as RawFd; + match fd { +- _x if self.comm.is_fd(fd) => self.run_comm_dispatch(event)?, +- _x if self.signals.is_fd(fd) => self.run_signal_dispatch(event)?, ++ _x if self.comm.is_fd(fd) => self.run_comm_dispatch(event), ++ _x if self.signals.is_fd(fd) => self.run_signal_dispatch(event), + _ => self.epoll.safe_close(fd), + } +- Ok(()) + } + +- pub fn unrecover(&mut self) -> Result<(), Errno> { ++ pub fn unrecover(&mut self) { + let event = self.epoll.wait_one(); + let fd = event.data() as RawFd; + match fd { + _x if self.comm.is_fd(fd) => self.unrecover_comm_dispatch(event), +- _x if self.signals.is_fd(fd) => self.unrecover_signal_dispatch(event)?, ++ _x if self.signals.is_fd(fd) => self.unrecover_signal_dispatch(event), + _ => self.epoll.safe_close(fd), + } +- Ok(()) +- } +- +- pub fn clear(&mut self) { +- self.comm.clear(); +- self.signals.clear(); +- self.epoll.clear(); + } + + pub fn reexec_self(&mut self) { +- self.clear(); + let mut args = Vec::new(); + let mut init_path = CString::new("/usr/bin/init").unwrap(); + if let Some(str) = std::env::args().next() { +@@ -154,17 +144,16 @@ impl RunTime { + unsafe { libc::kill(self.sysmaster_pid.into(), libc::SIGABRT) }; + } + +- fn reexec_comm_dispatch(&mut self, event: EpollEvent) -> Result<(), Errno> { +- match self.comm.proc(event)? { ++ fn reexec_comm_dispatch(&mut self, event: EpollEvent) { ++ match self.comm.proc(event) { + CommType::PipON => self.state = InitState::Run, + CommType::PipTMOUT => self.need_reexec = true, + _ => {} + } +- Ok(()) + } + +- fn run_comm_dispatch(&mut self, event: EpollEvent) -> Result<(), Errno> { +- match self.comm.proc(event)? { ++ fn run_comm_dispatch(&mut self, event: EpollEvent) { ++ match self.comm.proc(event) { + CommType::PipOFF => self.state = InitState::Reexec, + CommType::PipTMOUT => { + self.state = InitState::Reexec; +@@ -172,15 +161,14 @@ impl RunTime { + } + _ => {} + } +- Ok(()) + } + + fn unrecover_comm_dispatch(&mut self, event: EpollEvent) { + _ = self.comm.proc(event); + } + +- fn reexec_signal_dispatch(&mut self, event: EpollEvent) -> Result<(), Errno> { +- if let Some(siginfo) = self.signals.read(event)? { ++ fn reexec_signal_dispatch(&mut self, event: EpollEvent) { ++ if let Some(siginfo) = self.signals.read(event) { + match siginfo { + _x if self.signals.is_zombie(siginfo) => self.do_recycle(), + _x if self.signals.is_restart(siginfo) => self.do_reexec(), +@@ -188,11 +176,10 @@ impl RunTime { + _ => {} + } + } +- Ok(()) + } + +- fn run_signal_dispatch(&mut self, event: EpollEvent) -> Result<(), Errno> { +- if let Some(siginfo) = self.signals.read(event)? { ++ fn run_signal_dispatch(&mut self, event: EpollEvent) { ++ if let Some(siginfo) = self.signals.read(event) { + match siginfo { + _x if self.signals.is_zombie(siginfo) => self.do_recycle(), + _x if self.signals.is_restart(siginfo) => self.do_reexec(), +@@ -200,11 +187,10 @@ impl RunTime { + _ => {} + } + } +- Ok(()) + } + +- fn unrecover_signal_dispatch(&mut self, event: EpollEvent) -> Result<(), Errno> { +- if let Some(siginfo) = self.signals.read(event)? { ++ fn unrecover_signal_dispatch(&mut self, event: EpollEvent) { ++ if let Some(siginfo) = self.signals.read(event) { + match siginfo { + _x if self.signals.is_zombie(siginfo) => { + self.signals.recycle_zombie(); +@@ -216,7 +202,6 @@ impl RunTime { + _ => {} + } + } +- Ok(()) + } + + fn change_to_unrecover(&mut self) { +diff --git a/exts/init/src/runtime/signals.rs b/exts/init/src/runtime/signals.rs +index 1c3059c..327ff3e 100644 +--- a/exts/init/src/runtime/signals.rs ++++ b/exts/init/src/runtime/signals.rs +@@ -13,7 +13,8 @@ + use super::epoll::Epoll; + use nix::errno::Errno; + use nix::sys::epoll::EpollEvent; +-use nix::sys::signal::{SigmaskHow, Signal}; ++use nix::sys::signal::{self, SigSet, SigmaskHow, Signal}; ++use nix::sys::signalfd::{self, SfdFlags}; + use nix::sys::wait::{self, Id, WaitPidFlag, WaitStatus}; + use nix::unistd; + use std::mem; +@@ -21,42 +22,12 @@ use std::ops::Neg; + use std::os::unix::io::RawFd; + use std::rc::Rc; + ++use constants::INVALID_FD; + use constants::{SIG_RESTART_MANAGER_OFFSET, SIG_RUN_UNRECOVER_OFFSET, SIG_SWITCH_ROOT_OFFSET}; +-const INVALID_FD: i32 = -1; +- +-pub(crate) struct SigSet { +- sigset: libc::sigset_t, +-} +- +-impl SigSet { +- /// Initialize to include nothing. +- pub fn empty() -> SigSet { +- let mut sigset = mem::MaybeUninit::zeroed(); +- let _ = unsafe { libc::sigemptyset(sigset.as_mut_ptr()) }; +- +- unsafe { +- SigSet { +- sigset: sigset.assume_init(), +- } +- } +- } +- +- /// Add the specified signal to the set. +- pub fn add(&mut self, signal: libc::c_int) { +- unsafe { +- libc::sigaddset( +- &mut self.sigset as *mut libc::sigset_t, +- signal as libc::c_int, +- ) +- }; +- } +-} + + pub struct Signals { + epoll: Rc, +- signal_fd: RawFd, +- set: SigSet, +- oldset: SigSet, ++ pub signal_fd: RawFd, + signals: Vec, + zombie_signal: i32, + restart_signal: i32, +@@ -71,8 +42,6 @@ impl Signals { + Signals { + epoll: epoll.clone(), + signal_fd: INVALID_FD, +- set: SigSet::empty(), +- oldset: SigSet::empty(), + signals, + zombie_signal: libc::SIGCHLD, + unrecover_signal: libc::SIGRTMIN() + SIG_RUN_UNRECOVER_OFFSET, +@@ -101,29 +70,25 @@ impl Signals { + } + + pub fn create_signals_epoll(&mut self) -> Result<(), Errno> { +- self.reset_sigset(); ++ self.signal_fd = self.reset_sigset()?; + self.epoll.register(self.signal_fd)?; + Ok(()) + } + +- pub fn reset_sigset(&mut self) { ++ pub fn reset_sigset(&mut self) -> Result { ++ let mut sigset = SigSet::empty(); + for sig in self.signals.clone() { +- self.set.add(sig); +- } +- +- unsafe { +- libc::pthread_sigmask(libc::SIG_BLOCK, &self.set.sigset, &mut self.oldset.sigset); +- self.signal_fd = libc::signalfd( +- -1, +- &mut self.set.sigset as *const libc::sigset_t, +- libc::SFD_NONBLOCK, +- ); ++ let signum: Signal = unsafe { std::mem::transmute(sig) }; ++ sigset.add(signum); + } ++ let mut oldset = SigSet::empty(); ++ signal::pthread_sigmask(SigmaskHow::SIG_BLOCK, Some(&sigset), Some(&mut oldset))?; ++ signalfd::signalfd(-1, &sigset, SfdFlags::SFD_CLOEXEC | SfdFlags::SFD_NONBLOCK) + } + +- pub fn read(&mut self, event: EpollEvent) -> Result, Errno> { ++ pub fn read(&mut self, event: EpollEvent) -> Option { + if self.epoll.is_err(event) { +- return Err(Errno::EIO); ++ return self.recover(); + } + let mut buffer = mem::MaybeUninit::::zeroed(); + +@@ -139,14 +104,14 @@ impl Signals { + match res { + x if x == size as isize => { + let info = unsafe { buffer.assume_init() }; +- Ok(Some(info)) ++ Some(info) + } +- x if x >= 0 => Ok(None), ++ x if x >= 0 => None, + x => { + let err = Errno::from_i32(x.neg() as i32); + eprintln!("read_signals failed err:{:?}", err); + unistd::sleep(1); +- Ok(None) ++ None + } + } + } +@@ -191,13 +156,31 @@ impl Signals { + } + + pub fn is_fd(&self, fd: RawFd) -> bool { +- if fd == self.signal_fd { +- return true; ++ fd == self.signal_fd ++ } ++ ++ fn recover(&mut self) -> Option { ++ match self.reset_sigset() { ++ Ok(signal_fd) => match self.epoll.register(signal_fd) { ++ Ok(_) => { ++ self.epoll.safe_close(self.signal_fd); ++ self.signal_fd = signal_fd; ++ eprintln!("signals recover"); ++ } ++ Err(e) => { ++ eprintln!("Failed to register signal_fd:{:?}", e); ++ } ++ }, ++ Err(e) => { ++ eprintln!("Failed to create_signals_epoll:{:?}", e); ++ } + } +- false ++ None + } ++} + +- pub fn clear(&mut self) { ++impl Drop for Signals { ++ fn drop(&mut self) { + self.epoll.safe_close(self.signal_fd); + self.signal_fd = INVALID_FD; + if let Err(e) = nix::sys::signal::pthread_sigmask( +diff --git a/exts/init/src/runtime/timer.rs b/exts/init/src/runtime/timer.rs +index f7b5f30..54fcc62 100644 +--- a/exts/init/src/runtime/timer.rs ++++ b/exts/init/src/runtime/timer.rs +@@ -24,25 +24,18 @@ pub struct Timer { + epoll: Rc, + timer: TimerFd, + current_cnt: i64, ++ time_wait: i64, + time_cnt: i64, + } + + impl Timer { + pub fn new(epoll: &Rc, time_wait: i64, time_cnt: i64) -> Result { +- let timer = TimerFd::new( +- ClockId::CLOCK_REALTIME, +- TimerFlags::TFD_NONBLOCK | TimerFlags::TFD_CLOEXEC, +- )?; +- timer.set( +- Expiration::Interval(TimeSpec::seconds(time_wait)), +- TimerSetTimeFlags::empty(), +- )?; +- +- epoll.register(timer.as_raw_fd())?; ++ let timer = create_timer(epoll, time_wait)?; + Ok(Timer { + epoll: epoll.clone(), + timer, + current_cnt: 0, ++ time_wait, + time_cnt, + }) + } +@@ -56,18 +49,18 @@ impl Timer { + } + + #[allow(clippy::wrong_self_convention)] +- pub fn is_time_out(&mut self, event: EpollEvent) -> Result { ++ pub fn is_time_out(&mut self, event: EpollEvent) -> bool { + if self.epoll.is_err(event) { +- return Err(Errno::EIO); ++ return self.recover(); + } + self.flush(); + self.current_cnt += 1; + if self.time_cnt <= self.current_cnt { + eprintln!("time out!"); + self.reset(); +- return Ok(true); ++ return true; + } +- Ok(false) ++ false + } + + // reset timer. +@@ -79,7 +72,40 @@ impl Timer { + self.timer.as_raw_fd() + } + +- pub fn clear(&mut self) { +- self.epoll.safe_close(self.timer.as_raw_fd()); ++ fn recover(&mut self) -> bool { ++ match create_timer(&self.epoll, self.time_wait) { ++ Ok(timer) => { ++ // After successfully creating a new timer, recycle the old timer so that ++ // if create_timer fails, event can be retrieved to create_timer again. ++ // timer have drop, no need to manually close timer. ++ self.timer = timer; ++ eprintln!("timer recover"); ++ } ++ Err(e) => { ++ eprintln!("Failed to create_timer:{:?}", e); ++ } ++ } ++ // Here we believe that the system has encountered an exception, set it to timeout ++ true ++ } ++} ++ ++impl Drop for Timer { ++ fn drop(&mut self) { ++ // self.timer does not need to drop, because TimerFd have drop. + } + } ++ ++fn create_timer(epoll: &Rc, time_wait: i64) -> Result { ++ let timer = TimerFd::new( ++ ClockId::CLOCK_REALTIME, ++ TimerFlags::TFD_NONBLOCK | TimerFlags::TFD_CLOEXEC, ++ )?; ++ timer.set( ++ Expiration::Interval(TimeSpec::seconds(time_wait)), ++ TimerSetTimeFlags::empty(), ++ )?; ++ ++ epoll.register(timer.as_raw_fd())?; ++ Ok(timer) ++} +diff --git a/libs/constants/src/lib.rs b/libs/constants/src/lib.rs +index 6005067..1f84b40 100644 +--- a/libs/constants/src/lib.rs ++++ b/libs/constants/src/lib.rs +@@ -29,3 +29,6 @@ pub const SCTL_SOCKET: &str = "/run/sysmaster/sctl"; + + /// Default log file path when LogTarget is configured to "file" + pub const LOG_FILE_PATH: &str = "/var/log/sysmaster/sysmaster.log"; ++ ++/// invalid fd ++pub const INVALID_FD: i32 = -1; +-- +2.33.0 + diff --git a/backport-fix-init-recyle-zombie-process-normally-corrects-doc.patch b/backport-fix-init-recyle-zombie-process-normally-corrects-doc.patch new file mode 100644 index 0000000..adcf1d9 --- /dev/null +++ b/backport-fix-init-recyle-zombie-process-normally-corrects-doc.patch @@ -0,0 +1,49 @@ +From 11b48132ed907faa586220da9aafffa3b3e246ce Mon Sep 17 00:00:00 2001 +From: huyubiao +Date: Fri, 7 Jul 2023 16:08:27 +0800 +Subject: [PATCH] fix: init recyle zombie process normally, corrects document + writing errors + +--- + init/src/runtime/mod.rs | 12 ++++++------ + init/src/runtime/signals.rs | 18 +++++++++--------- + 4 files changed, 17 insertions(+), 17 deletions(-) + +diff --git a/init/src/runtime/signals.rs b/init/src/runtime/signals.rs +index 327ff3e..1226e99 100644 +--- a/init/src/runtime/signals.rs ++++ b/init/src/runtime/signals.rs +@@ -81,8 +81,7 @@ impl Signals { + let signum: Signal = unsafe { std::mem::transmute(sig) }; + sigset.add(signum); + } +- let mut oldset = SigSet::empty(); +- signal::pthread_sigmask(SigmaskHow::SIG_BLOCK, Some(&sigset), Some(&mut oldset))?; ++ signal::pthread_sigmask(SigmaskHow::SIG_BLOCK, Some(&sigset), None)?; + signalfd::signalfd(-1, &sigset, SfdFlags::SFD_CLOEXEC | SfdFlags::SFD_NONBLOCK) + } + +@@ -183,12 +182,13 @@ impl Drop for Signals { + fn drop(&mut self) { + self.epoll.safe_close(self.signal_fd); + self.signal_fd = INVALID_FD; +- if let Err(e) = nix::sys::signal::pthread_sigmask( +- SigmaskHow::SIG_SETMASK, +- Some(&nix::sys::signal::SigSet::empty()), +- None, +- ) { +- eprintln!("reset pthread_sigmask failed: {e}"); +- } ++ reset_signal_mask(); ++ } ++} ++ ++pub fn reset_signal_mask() { ++ let set = SigSet::empty(); ++ if let Err(e) = signal::pthread_sigmask(SigmaskHow::SIG_SETMASK, Some(&set), None) { ++ eprintln!("reset signal mask failed: {e}"); + } + } +-- +2.33.0 + diff --git a/backport-fix-init-uses-SIGABRT-to-reexec-sysmaster-increase-s.patch b/backport-fix-init-uses-SIGABRT-to-reexec-sysmaster-increase-s.patch new file mode 100644 index 0000000..ed8be57 --- /dev/null +++ b/backport-fix-init-uses-SIGABRT-to-reexec-sysmaster-increase-s.patch @@ -0,0 +1,285 @@ +From 5c9eb30727331780e01cd34293801efd38aa787d Mon Sep 17 00:00:00 2001 +From: huyubiao +Date: Fri, 16 Jun 2023 15:32:28 +0800 +Subject: [PATCH] fix: init uses SIGABRT to reexec sysmaster, increase signal + permissions + +--- + core/bin/main.rs | 46 ++++++++++++++++---------------- + core/bin/manager/mod.rs | 9 ++++++- + exts/init/Cargo.toml | 1 - + exts/init/src/runtime/mod.rs | 33 +++++++++-------------- + exts/init/src/runtime/signals.rs | 19 +++++++------ + libs/constants/src/lib.rs | 2 -- + 7 files changed, 60 insertions(+), 62 deletions(-) + +diff --git a/core/bin/main.rs b/core/bin/main.rs +index 0239ce9..7f163c7 100644 +--- a/core/bin/main.rs ++++ b/core/bin/main.rs +@@ -39,7 +39,7 @@ use crate::mount::setup; + use basic::logger::{self}; + use basic::process_util; + use clap::Parser; +-use libc::{c_int, getppid, prctl, PR_SET_CHILD_SUBREAPER}; ++use libc::{c_int, getpid, getppid, prctl, PR_SET_CHILD_SUBREAPER}; + use log::{self}; + use manager::signals::EVENT_SIGNALS; + use nix::sys::resource::{self, Resource}; +@@ -52,7 +52,6 @@ use std::rc::Rc; + use sysmaster::error::*; + use sysmaster::rel; + +-use constants::SIG_MANAGER_REEXEC_OFFSET; + use constants::SIG_SWITCH_ROOT_OFFSET; + + /// parse program arguments +@@ -106,21 +105,17 @@ fn main() -> Result<()> { + setup::mount_setup()?; + + rel::reli_dir_prepare()?; +- let switch = rel::reli_debug_get_switch(); +- log::info!("sysmaster initialize with switch: {}.", switch); ++ let self_recovery_enable = rel::reli_debug_get_switch(); ++ log::info!("sysmaster self_recovery_enable: {}.", self_recovery_enable); + +- initialize_runtime(switch)?; ++ initialize_runtime(self_recovery_enable)?; + + let manager = Manager::new(Mode::System, Action::Run, manager_config); + +- // enable clear, mutex with install_crash_handler +- if !switch { +- if !args.deserialize { +- manager.debug_clear_restore(); +- log::info!("debug: clear data restored."); +- } +- // if switch is false unregister init's reexec signal. +- register_reexec_signal(false); ++ // enable clear ++ if !self_recovery_enable && !args.deserialize { ++ manager.debug_clear_restore(); ++ log::info!("debug: clear data restored."); + } + + manager.setup_cgroup()?; +@@ -144,10 +139,13 @@ fn main() -> Result<()> { + Ok(()) + } + +-fn initialize_runtime(switch: bool) -> Result<()> { +- if switch { ++fn initialize_runtime(self_recovery_enable: bool) -> Result<()> { ++ if self_recovery_enable { + install_crash_handler(); + log::info!("install crash handler."); ++ } else { ++ // if self_recovery_enable is false unregister init's reexec signal. ++ register_reexec_signal(false); + } + + #[cfg(feature = "linux")] +@@ -222,7 +220,7 @@ fn install_crash_handler() { + Signal::SIGABRT, + Signal::SIGSYS, + ]; +- let handler = SigHandler::Handler(crash); ++ let handler = SigHandler::SigAction(crash); + let flags = SaFlags::SA_NODEFER; + let action = SigAction::new(handler, flags, SigSet::empty()); + for &signal in signals.iter() { +@@ -232,11 +230,14 @@ fn install_crash_handler() { + } + } + +-extern "C" fn crash(signo: c_int) { +- let _signal = Signal::try_from(signo).unwrap(); // debug +- +- let args: Vec = env::args().collect(); +- do_reexecute(&args, false); ++extern "C" fn crash(signo: c_int, siginfo: *mut libc::siginfo_t, _con: *mut libc::c_void) { ++ let signal = Signal::try_from(signo).unwrap(); // debug ++ if (signal == Signal::SIGABRT && unsafe { (*siginfo).si_pid() == getppid() }) ++ || unsafe { (*siginfo).si_pid() == getpid() } ++ { ++ let args: Vec = env::args().collect(); ++ do_reexecute(&args, false); ++ } + } + + fn execarg_build_default() -> (String, Vec) { +@@ -265,8 +266,7 @@ extern "C" fn crash_none(_signo: c_int, _siginfo: *mut libc::siginfo_t, _con: *m + } + + fn register_reexec_signal(enable: bool) { +- let manager_signal: signal::Signal = +- unsafe { std::mem::transmute(libc::SIGRTMIN() + SIG_MANAGER_REEXEC_OFFSET) }; ++ let manager_signal: Signal = Signal::SIGABRT; + let handler = match enable { + true => SigHandler::SigAction(crash_reexec), + false => SigHandler::SigAction(crash_none), +diff --git a/core/bin/manager/mod.rs b/core/bin/manager/mod.rs +index e972cc7..7bd16e0 100644 +--- a/core/bin/manager/mod.rs ++++ b/core/bin/manager/mod.rs +@@ -59,6 +59,12 @@ impl SignalMgr { + SignalMgr { um: Rc::clone(&um) } + } + fn reexec(&self) -> Result { ++ self.um.set_state(State::ReExecute); ++ Ok(1) ++ } ++ ++ fn reload(&self) -> Result { ++ self.um.set_state(State::ReLoad); + Ok(1) + } + } +@@ -70,7 +76,8 @@ impl SignalDispatcher for SignalMgr { + return Ok(1); + } + match signal.ssi_signo as libc::c_int { +- libc::SIGHUP | libc::SIGTERM => self.reexec(), ++ libc::SIGHUP => self.reload(), ++ libc::SIGTERM => self.reexec(), + libc::SIGCHLD => Ok(self.um.child_sigchld_enable(true)), + /* Kernel will send SIGINT to PID1 when users press ctrl-alt-del, + * init should forward SIGINT to sysmaster. */ +diff --git a/exts/init/Cargo.toml b/exts/init/Cargo.toml +index e3c0198..e351b61 100644 +--- a/exts/init/Cargo.toml ++++ b/exts/init/Cargo.toml +@@ -9,4 +9,3 @@ edition = "2021" + constants = { version = "0.1.0", path = "../../libs/constants" } + libc = "0.2.*" + nix = "0.24" +-signal-hook-registry = "1.4.0" +diff --git a/exts/init/src/runtime/mod.rs b/exts/init/src/runtime/mod.rs +index e37ff01..d11d8f2 100644 +--- a/exts/init/src/runtime/mod.rs ++++ b/exts/init/src/runtime/mod.rs +@@ -33,7 +33,6 @@ use std::rc::Rc; + + use constants::SIG_SWITCH_ROOT_OFFSET; + const INVALID_PID: i32 = -1; +-const MANAGER_SIG_OFFSET: i32 = 7; + const SYSMASTER_PATH: &str = "/usr/lib/sysmaster/sysmaster"; + + #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd)] +@@ -152,12 +151,7 @@ impl RunTime { + + self.comm.finish(); + +- unsafe { +- libc::kill( +- self.sysmaster_pid.into(), +- libc::SIGRTMIN() + MANAGER_SIG_OFFSET, +- ) +- }; ++ unsafe { libc::kill(self.sysmaster_pid.into(), libc::SIGABRT) }; + } + + fn reexec_comm_dispatch(&mut self, event: EpollEvent) -> Result<(), Errno> { +@@ -187,11 +181,10 @@ impl RunTime { + + fn reexec_signal_dispatch(&mut self, event: EpollEvent) -> Result<(), Errno> { + if let Some(siginfo) = self.signals.read(event)? { +- let signo = siginfo.ssi_signo as i32; +- match signo { +- _x if self.signals.is_zombie(signo) => self.do_recycle(), +- _x if self.signals.is_restart(signo) => self.do_reexec(), +- _x if self.signals.is_unrecover(signo) => self.change_to_unrecover(), ++ match siginfo { ++ _x if self.signals.is_zombie(siginfo) => self.do_recycle(), ++ _x if self.signals.is_restart(siginfo) => self.do_reexec(), ++ _x if self.signals.is_unrecover(siginfo) => self.change_to_unrecover(), + _ => {} + } + } +@@ -200,11 +193,10 @@ impl RunTime { + + fn run_signal_dispatch(&mut self, event: EpollEvent) -> Result<(), Errno> { + if let Some(siginfo) = self.signals.read(event)? { +- let signo = siginfo.ssi_signo as i32; +- match signo { +- _x if self.signals.is_zombie(signo) => self.do_recycle(), +- _x if self.signals.is_restart(signo) => self.do_reexec(), +- _x if self.signals.is_switch_root(signo) => self.send_switch_root_signal(), ++ match siginfo { ++ _x if self.signals.is_zombie(siginfo) => self.do_recycle(), ++ _x if self.signals.is_restart(siginfo) => self.do_reexec(), ++ _x if self.signals.is_switch_root(siginfo) => self.send_switch_root_signal(), + _ => {} + } + } +@@ -213,15 +205,14 @@ impl RunTime { + + fn unrecover_signal_dispatch(&mut self, event: EpollEvent) -> Result<(), Errno> { + if let Some(siginfo) = self.signals.read(event)? { +- let signo = siginfo.ssi_signo as i32; +- match signo { +- _x if self.signals.is_zombie(signo) => { ++ match siginfo { ++ _x if self.signals.is_zombie(siginfo) => { + self.signals.recycle_zombie(); + if self.is_sysmaster(siginfo.ssi_pid as i32) && self.switching { + self.reexec_self() + } + } +- _x if self.signals.is_restart(signo) => self.do_recreate(), ++ _x if self.signals.is_restart(siginfo) => self.do_recreate(), + _ => {} + } + } +diff --git a/exts/init/src/runtime/signals.rs b/exts/init/src/runtime/signals.rs +index eee088c..1c3059c 100644 +--- a/exts/init/src/runtime/signals.rs ++++ b/exts/init/src/runtime/signals.rs +@@ -81,20 +81,23 @@ impl Signals { + } + } + +- pub fn is_zombie(&self, signo: i32) -> bool { +- self.zombie_signal == signo ++ pub fn is_zombie(&self, siginfo: libc::signalfd_siginfo) -> bool { ++ self.zombie_signal as u32 == siginfo.ssi_signo + } + +- pub fn is_restart(&self, signo: i32) -> bool { +- self.restart_signal == signo ++ pub fn is_restart(&self, siginfo: libc::signalfd_siginfo) -> bool { ++ self.restart_signal as u32 == siginfo.ssi_signo + } + +- pub fn is_unrecover(&self, signo: i32) -> bool { +- self.unrecover_signal == signo ++ pub fn is_unrecover(&self, siginfo: libc::signalfd_siginfo) -> bool { ++ if 0 == siginfo.ssi_uid { ++ return self.unrecover_signal as u32 == siginfo.ssi_signo; ++ } ++ false + } + +- pub fn is_switch_root(&self, signo: i32) -> bool { +- self.switch_root_signal == signo ++ pub fn is_switch_root(&self, siginfo: libc::signalfd_siginfo) -> bool { ++ self.switch_root_signal as u32 == siginfo.ssi_signo + } + + pub fn create_signals_epoll(&mut self) -> Result<(), Errno> { +diff --git a/libs/constants/src/lib.rs b/libs/constants/src/lib.rs +index 7c918aa..b1db27c 100644 +--- a/libs/constants/src/lib.rs ++++ b/libs/constants/src/lib.rs +@@ -12,8 +12,6 @@ + + //! Common used constants by init, sysmaster and other extensions. + +-/// Signal used to reexecute sysmaster, SIGRTMIN+7 +-pub const SIG_MANAGER_REEXEC_OFFSET: i32 = 7; + /// Signal used run unrecover, SIGRTMIN+8 + pub const SIG_RUN_UNRECOVER_OFFSET: i32 = 8; + /// Signal used to restart the manager, SIGRTMIN+9 +-- +2.33.0 + diff --git a/backport-fix-integer-overflow.patch b/backport-fix-integer-overflow.patch new file mode 100644 index 0000000..f472dbe --- /dev/null +++ b/backport-fix-integer-overflow.patch @@ -0,0 +1,261 @@ +From 9414249d740f90dfe5b65a922835306a78a1ad9f Mon Sep 17 00:00:00 2001 +From: huyubiao +Date: Tue, 18 Jul 2023 02:22:51 +0800 +Subject: [PATCH] fix: integer overflow + +--- + coms/service/Cargo.toml | 1 + + coms/service/src/config.rs | 15 +++++++++++++++ + coms/service/src/mng.rs | 10 +++++----- + coms/service/src/rentry.rs | 4 ++-- + coms/service/src/spawn.rs | 2 +- + coms/service/src/unit.rs | 6 ------ + core/sysmaster/mount/setup.rs | 1 - + libs/basic/src/time_util.rs | 3 --- + libs/constants/src/lib.rs | 9 +++++++++ + libs/event/Cargo.toml | 1 + + libs/event/src/timer.rs | 20 +++++--------------- + 11 files changed, 39 insertions(+), 33 deletions(-) + +diff --git a/coms/service/Cargo.toml b/coms/service/Cargo.toml +index 0f37cf8..27cedda 100644 +--- a/coms/service/Cargo.toml ++++ b/coms/service/Cargo.toml +@@ -10,6 +10,7 @@ crate-type = ["dylib"] + name = "service" + + [dependencies] ++constants = { path = "../../libs/constants" } + basic = { path = "../../libs/basic" } + macros = { path = "../../libs/macros" } + cgroup = { path = "../../libs/cgroup" } +diff --git a/coms/service/src/config.rs b/coms/service/src/config.rs +index aa62b00..e61340b 100644 +--- a/coms/service/src/config.rs ++++ b/coms/service/src/config.rs +@@ -14,6 +14,7 @@ + use super::comm::ServiceUnitComm; + use super::rentry::{NotifyAccess, SectionService, ServiceCommand, ServiceType}; + use confique::{Config, FileFormat, Partial}; ++use constants::{USEC_INFINITY, USEC_PER_SEC}; + use std::cell::RefCell; + use std::collections::{HashMap, VecDeque}; + use std::path::PathBuf; +@@ -86,6 +87,7 @@ impl ServiceConfig { + } + Ok(v) => v, + }; ++ self.data.borrow_mut().verify(); + + if update { + self.db_update(); +@@ -178,6 +180,19 @@ impl ServiceConfigData { + pub(self) fn set_timeout_stop(&mut self, time_out: u64) { + self.Service.set_timeout_stop(time_out); + } ++ ++ pub(self) fn verify(&mut self) { ++ if self.Service.WatchdogSec >= USEC_INFINITY / USEC_PER_SEC { ++ self.Service.WatchdogSec = 0; ++ } else { ++ self.Service.WatchdogSec *= USEC_PER_SEC; ++ } ++ if self.Service.RestartSec >= USEC_INFINITY / USEC_PER_SEC { ++ self.Service.RestartSec = USEC_PER_SEC; ++ } else { ++ self.Service.RestartSec *= USEC_PER_SEC; ++ } ++ } + } + + #[cfg(test)] +diff --git a/coms/service/src/mng.rs b/coms/service/src/mng.rs +index b44a0dd..e5fbeb8 100644 +--- a/coms/service/src/mng.rs ++++ b/coms/service/src/mng.rs +@@ -1228,9 +1228,9 @@ impl ServiceMng { + } + + fn restart_watchdog(&self) { +- self.monitor.borrow_mut().set_original_watchdog( +- self.config.config_data().borrow().Service.WatchdogSec * 1000000, +- ); ++ self.monitor ++ .borrow_mut() ++ .set_original_watchdog(self.config.config_data().borrow().Service.WatchdogSec); + let watchdog_usec = self.monitor.borrow().watchdog_usec(); + if watchdog_usec == 0 || watchdog_usec == u64::MAX { + self.stop_watchdog(); +@@ -2570,7 +2570,7 @@ mod tests { + assert!(rt.armd_watchdog()); + assert_eq!( + rt.watchdog().time(), +- config.config_data().borrow().Service.WatchdogSec * 1000000 ++ config.config_data().borrow().Service.WatchdogSec + ); + } + +@@ -2589,7 +2589,7 @@ mod tests { + assert!(rt.armd_watchdog()); + assert_eq!( + rt.watchdog().time(), +- config.config_data().borrow().Service.WatchdogSec * 1000000 ++ config.config_data().borrow().Service.WatchdogSec + ); + + messages.remove("WATCHDOG"); +diff --git a/coms/service/src/rentry.rs b/coms/service/src/rentry.rs +index 7099e01..87c92b2 100644 +--- a/coms/service/src/rentry.rs ++++ b/coms/service/src/rentry.rs +@@ -32,7 +32,7 @@ use sysmaster::serialize::DeserializeWith; + use sysmaster::unit::KillMode; + + use basic::special::EXEC_RUNTIME_PREFIX; +-use basic::time_util::USEC_PER_SEC; ++use constants::USEC_PER_SEC; + + struct ServiceReDb(ReDb); + +@@ -290,7 +290,7 @@ pub(super) struct SectionService { + #[config(deserialize_with = ExitStatusSet::deserialize_with)] + #[config(default = "")] + pub RestartPreventExitStatus: ExitStatusSet, +- #[config(default = 100000)] ++ #[config(default = 1)] + pub RestartSec: u64, + #[config(deserialize_with = Vec::::deserialize_with)] + #[config(default = "")] +diff --git a/coms/service/src/spawn.rs b/coms/service/src/spawn.rs +index 2ff9e92..9b895aa 100644 +--- a/coms/service/src/spawn.rs ++++ b/coms/service/src/spawn.rs +@@ -171,7 +171,7 @@ impl ServiceSpawn { + } + + fn watchdog_timer(&self) -> u64 { +- self.config.config_data().borrow().Service.WatchdogSec * 1000000 ++ self.config.config_data().borrow().Service.WatchdogSec + } + + pub(super) fn set_socket_fd(&self, fd: i32) { +diff --git a/coms/service/src/unit.rs b/coms/service/src/unit.rs +index 4bb235e..ac2e05b 100644 +--- a/coms/service/src/unit.rs ++++ b/coms/service/src/unit.rs +@@ -405,11 +405,5 @@ impl ServiceUnit { + } + } + +-/*impl Default for ServiceUnit { +- fn default() -> Self { +- ServiceUnit::new() +- } +-}*/ +- + use sysmaster::declare_unitobj_plugin_with_param; + declare_unitobj_plugin_with_param!(ServiceUnit, ServiceUnit::new); +diff --git a/core/sysmaster/mount/setup.rs b/core/sysmaster/mount/setup.rs +index e7ca9df..850a2b2 100644 +--- a/core/sysmaster/mount/setup.rs ++++ b/core/sysmaster/mount/setup.rs +@@ -32,7 +32,6 @@ use std::{ + use sysmaster::error::*; + + const EARLY_MOUNT_NUM: u8 = 3; +-// const CGROUP_ROOT: &str = "/sys/fs/cgroup/"; + + type Callback = fn() -> bool; + +diff --git a/libs/basic/src/time_util.rs b/libs/basic/src/time_util.rs +index 45a12af..a6eb5cb 100644 +--- a/libs/basic/src/time_util.rs ++++ b/libs/basic/src/time_util.rs +@@ -15,9 +15,6 @@ use std::time::SystemTime; + + const USEC_INFINITY: u128 = u128::MAX; + +-/// usec per sec +-pub const USEC_PER_SEC: u64 = 1000000; +- + /// + pub fn timespec_load(systime: SystemTime) -> u128 { + match systime.duration_since(SystemTime::UNIX_EPOCH) { +diff --git a/libs/constants/src/lib.rs b/libs/constants/src/lib.rs +index 46a3a50..3be5723 100644 +--- a/libs/constants/src/lib.rs ++++ b/libs/constants/src/lib.rs +@@ -35,3 +35,12 @@ pub const INIT_PARA_PATH: &str = "/run/sysmaster/init_para"; + + /// invalid fd + pub const INVALID_FD: i32 = -1; ++ ++/// USec per Sec ++pub const USEC_PER_SEC: u64 = 1000000; ++/// NSec per USec ++pub const NSEC_PER_USEC: u64 = 1000; ++/// NSec per Sec ++pub const NSEC_PER_SEC: u64 = 1000000000; ++/// USec infinity ++pub const USEC_INFINITY: u64 = u64::MAX; +diff --git a/libs/event/Cargo.toml b/libs/event/Cargo.toml +index 8cd9398..55a5cb4 100644 +--- a/libs/event/Cargo.toml ++++ b/libs/event/Cargo.toml +@@ -7,6 +7,7 @@ edition = "2021" + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + [dependencies] ++constants = { path = "../constants" } + libc = { version = "0.2" } + nix = { version = "0.24" } + snafu = { version = "0.7" } +diff --git a/libs/event/src/timer.rs b/libs/event/src/timer.rs +index a94025b..9a0cb3d 100644 +--- a/libs/event/src/timer.rs ++++ b/libs/event/src/timer.rs +@@ -19,11 +19,7 @@ use std::{ + }; + + use crate::{EventType, Source}; +- +-use std::u64::MAX as USEC_INFINITY; +-const USEC_PER_SEC: u64 = 1000000; +-const NSEC_PER_USEC: u64 = 1000; +-const NSEC_PER_SEC: u64 = 1000000000; ++use constants::{NSEC_PER_SEC, NSEC_PER_USEC, USEC_INFINITY, USEC_PER_SEC}; + + #[derive(Debug, Clone, Copy)] + pub(crate) struct Timestamp { +@@ -137,16 +133,11 @@ impl Timer { + pub fn push(&mut self, source: Rc) { + // calc the time + let mut next = source.time_relative(); +- if next != u64::MAX { +- next += self.timerid(&source.event_type()); +- } else { ++ let now = self.timerid(&source.event_type()); ++ if next > USEC_INFINITY - now { + next = source.time(); +- } +- +- if next == u64::MAX { +- panic!( +- "You need to implement time() or time_relative(), and cannot be set to u64::MAX" +- ); ++ } else { ++ next += now; + } + + let cd = ClockData::new(source.clone(), next); +@@ -165,7 +156,6 @@ impl Timer { + + pub fn pop(&mut self, et: &EventType) -> Option> { + let next = self.timerid(et); +- // self.now(); + match self.timer_set.get_mut(et) { + Some(timer) => { + if timer.data.is_empty() { +-- +2.33.0 + diff --git a/backport-fix-isolate-debugging-code-through-configuration-pre.patch b/backport-fix-isolate-debugging-code-through-configuration-pre.patch new file mode 100644 index 0000000..91ca83c --- /dev/null +++ b/backport-fix-isolate-debugging-code-through-configuration-pre.patch @@ -0,0 +1,462 @@ +From d36bb9fa9a0322f475f6039948bba6ea8e106d74 Mon Sep 17 00:00:00 2001 +From: xuxiaozhou1 +Date: Sun, 2 Jul 2023 17:32:25 +0800 +Subject: [PATCH] fix: isolate debugging code through configuration predicate + 'debug' + +--- + build.rs | 8 +++ + core/libsysmaster/rel/api.rs | 106 ++++++++------------------------- + core/libsysmaster/rel/base.rs | 40 +++++++++++-- + core/libsysmaster/rel/debug.rs | 106 +++++++++++++++++++++++++++++++++ + core/libsysmaster/rel/mod.rs | 6 +- + 5 files changed, 178 insertions(+), 88 deletions(-) + create mode 100644 core/libsysmaster/rel/debug.rs + +diff --git a/build.rs b/build.rs +index 05296f5..15c2a21 100644 +--- a/build.rs ++++ b/build.rs +@@ -14,6 +14,8 @@ + // if use env out_dir need add build.rs + use std::{env, process::Command}; + ++const RELEASE: &str = "release"; ++ + macro_rules! warn { + ($message:expr) => { + println!("cargo:warning={}", $message); +@@ -45,4 +47,10 @@ fn main() { + println!("cargo:rerun-if-changed=build.sh"); + println!("cargo:rerun-if-changed=build.rs"); + // println!("cargo:rerun-if-changed=config.service"); ++ ++ // turn on "debug" for non-release build ++ let profile = env::var("PROFILE").unwrap(); ++ if profile != RELEASE { ++ println!("cargo:rustc-cfg=debug"); ++ } + } +diff --git a/core/libsysmaster/rel/api.rs b/core/libsysmaster/rel/api.rs +index 94f9015..ad7743a 100644 +--- a/core/libsysmaster/rel/api.rs ++++ b/core/libsysmaster/rel/api.rs +@@ -10,6 +10,8 @@ + // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + // See the Mulan PSL v2 for more details. + ++#[cfg(debug)] ++use super::debug::{self, ReliDebug}; + use super::{ + enable::{self, ReliEnable}, + history::{self, ReliHistory}, +@@ -19,24 +21,9 @@ use super::{ + ReDbTable, ReStation, ReStationKind, + }; + use crate::{error::*, rel::base}; +-use basic::do_entry_or_return_io_error; + use heed::Database; + use nix::sys::stat::{self, Mode}; +-use std::{ +- fs::{self, File}, +- path::Path, +- rc::Rc, +- thread, +- time::Duration, +-}; +- +-const RELI_DEBUG_SWITCH_FILE: &str = "switch.debug"; +-const RELI_DEBUG_CLEAR_FILE: &str = "clear.debug"; +-const RELI_DEBUG_CFIRST_FILE: &str = "clear_first.debug"; +-const RELI_DEBUG_ENABLE_FILE: &str = "enable.debug"; +-const RELI_DEBUG_PANIC_FILE: &str = "panic.debug"; +-const RELI_DEBUG_PFIRST_FILE: &str = "panic_first.debug"; +-const RELI_DEBUG_SLEEP_FILE: &str = "sleep.debug"; ++use std::rc::Rc; + + /// the configuration of reliability instance + pub struct ReliConf { +@@ -76,8 +63,11 @@ impl Default for ReliConf { + /// reliability instance + #[derive(Debug)] + pub struct Reliability { ++ // debug ++ #[cfg(debug)] ++ debug: ReliDebug, ++ + // control data +- dir_string: String, + enable: ReliEnable, + + // output data +@@ -102,7 +92,8 @@ impl Reliability { + pub fn new(conf: &ReliConf) -> Reliability { + let dir_s = reli_prepare().expect("reliability prepare"); + let reli = Reliability { +- dir_string: dir_s.clone(), ++ #[cfg(debug)] ++ debug: ReliDebug::new(&dir_s), + enable: ReliEnable::new(&dir_s), + last: ReliLast::new(&dir_s), + history: ReliHistory::new(&dir_s, conf.map_size, conf.max_dbs), +@@ -250,8 +241,8 @@ impl Reliability { + + /// do the debug action: enable the recover process + pub fn debug_enable(&self) { +- let enable = Path::new(&self.dir_string).join(RELI_DEBUG_ENABLE_FILE); +- if enable.exists() { ++ #[cfg(debug)] ++ if self.debug.enable() { + log::info!("reliability debug: enable data..."); + self.set_enable(true); + } +@@ -259,53 +250,25 @@ impl Reliability { + + /// do the debug action: clear data excluding enable + pub fn debug_clear(&self) { +- let clear = Path::new(&self.dir_string).join(RELI_DEBUG_CLEAR_FILE); +- if clear.exists() { +- log::info!("reliability debug: clear data..."); +- let cfirst = Path::new(&self.dir_string).join(RELI_DEBUG_CFIRST_FILE); +- if cfirst.exists() { +- // do nothing +- log::info!("reliability debug_clear: non-first time, do nothing."); +- } else { +- log::info!("reliability debug_clear: first time, try clear."); +- File::create(&cfirst).unwrap(); +- log::debug!("Successfully created {cfirst:?}"); +- log::info!("reliability debug_clear: first time, clear ..."); +- +- // clear data excluding enable +- let enable = self.enable(); +- self.data_clear(); +- self.set_enable(enable); +- } ++ #[cfg(debug)] ++ if self.debug.clear() { ++ // clear data excluding enable ++ let enable = self.enable(); ++ self.data_clear(); ++ self.set_enable(enable); + } + } + + /// do the debug action: panic + pub fn debug_panic(&self) { +- let panic = Path::new(&self.dir_string).join(RELI_DEBUG_PANIC_FILE); +- if panic.exists() { +- log::info!("reliability debug: panic..."); +- let pfirst = Path::new(&self.dir_string).join(RELI_DEBUG_PFIRST_FILE); +- if pfirst.exists() { +- // do nothing +- log::info!("reliability debug_panic: non-first time, do nothing."); +- } else { +- log::info!("reliability debug_panic: first time, try panic."); +- File::create(&pfirst).unwrap(); +- log::debug!("Successfully created {pfirst:?}"); +- log::info!("reliability debug_panic: first time, panic ..."); +- panic!("first debug_panic."); +- } +- } ++ #[cfg(debug)] ++ self.debug.panic(); + } + + /// do the debug action: sleep + pub fn debug_sleep(&self) { +- let sleep = Path::new(&self.dir_string).join(RELI_DEBUG_SLEEP_FILE); +- if sleep.exists() { +- log::info!("reliability debug: sleep..."); +- thread::sleep(Duration::from_secs(3600)); +- } ++ #[cfg(debug)] ++ self.debug.sleep(); + } + + fn input_rebuild(&self) { +@@ -365,31 +328,12 @@ impl Reliability { + } + } + +-/// do the debug action: enable or disable switch flag. effective after restart. +-#[allow(dead_code)] +-pub fn reli_debug_enable_switch(enable: bool) -> Result<()> { +- log::info!("reliability debug: enable[{}] switch.", enable); +- +- let dir_string = base::reli_dir_get().unwrap(); +- let switch = Path::new(&dir_string).join(RELI_DEBUG_SWITCH_FILE); +- // touch switch.debug if enable +- if enable && !switch.exists() { +- do_entry_or_return_io_error!(File::create, switch, "create"); +- } +- // remove switch.debug if disable +- if !enable && switch.exists() { +- do_entry_or_return_io_error!(fs::remove_file, switch, "remove"); +- } +- +- Ok(()) +-} +- + /// get the debug flag of switch + pub fn reli_debug_get_switch() -> bool { +- let dir_string = base::reli_dir_get().expect("guaranteed by caller."); +- let switch = Path::new(&dir_string).join(RELI_DEBUG_SWITCH_FILE); +- log::info!("reliability debug: get switch file: {:?}.", switch); +- switch.exists() ++ #[cfg(debug)] ++ return debug::switch(); ++ #[cfg(not(debug))] ++ return true; + } + + fn reli_prepare() -> Result { +diff --git a/core/libsysmaster/rel/base.rs b/core/libsysmaster/rel/base.rs +index 65307e0..bcc8a21 100644 +--- a/core/libsysmaster/rel/base.rs ++++ b/core/libsysmaster/rel/base.rs +@@ -20,10 +20,12 @@ use serde::de::DeserializeOwned; + use serde::Serialize; + use std::cell::RefCell; + use std::collections::{HashMap, HashSet}; ++#[cfg(debug)] ++use std::env; + use std::fmt::Debug; ++use std::fs; + use std::hash::Hash; + use std::path::Path; +-use std::{env, fs}; + + /// the reliability database + /// K & V that can be deserialized without borrowing any data from the deserializer. +@@ -275,7 +277,21 @@ pub trait ReDbTable { + + const RELI_PATH_DIR: &str = "/run/sysmaster/reliability"; + ++/// get the directory for reliability. + pub fn reli_dir_get() -> Result { ++ #[cfg(debug)] ++ return reli_dir_get_debug(); ++ #[cfg(not(debug))] ++ return reli_dir_get_release(); ++} ++ ++#[cfg(not(debug))] ++fn reli_dir_get_release() -> Result { ++ return reli_dir_get_run(); ++} ++ ++#[cfg(debug)] ++fn reli_dir_get_debug() -> Result { + // /run/sysmaster/reliability/ + let ret_run = reli_dir_get_run(); + if ret_run.is_ok() { +@@ -303,17 +319,26 @@ pub fn reli_dir_get() -> Result { + /// prepare the directory for reliability. + /// the reliability path is prepared and searched according to the following priority, from high to low: + /// 1. /run/sysmaster/reliability/: the real running directory. +-/// 2. OUT_DIR/../reliability/: make CI happy, which is target/debug/reliability/ or target/release/reliability/ usually. +-/// 3. PROCESS_RELI_PATH: the path customized. ++/// 2. [debug-only]OUT_DIR/../reliability/: make CI happy, which is target/debug/reliability/ or target/release/reliability/ usually. ++/// 3. [debug-only]ROCESS_RELI_PATH: the path customized. + pub fn reli_dir_prepare() -> Result<()> { + // create '/run/sysmaster/reliability' or 'xxx/reliability' with mode 700 + let old_mask = stat::umask(Mode::from_bits_truncate(!0o700)); +- let ret = reli_dir_prepare_body(); ++ #[cfg(debug)] ++ let ret = reli_dir_prepare_debug(); ++ #[cfg(not(debug))] ++ let ret = reli_dir_prepare_release(); + let _ = stat::umask(old_mask); + ret + } + +-fn reli_dir_prepare_body() -> Result<()> { ++#[cfg(not(debug))] ++fn reli_dir_prepare_release() -> Result<()> { ++ return reli_dir_prepare_run(); ++} ++ ++#[cfg(debug)] ++fn reli_dir_prepare_debug() -> Result<()> { + // // /run/sysmaster/reliability/ + let ret_run = reli_dir_prepare_run(); + if ret_run.is_ok() { +@@ -373,6 +398,7 @@ fn reli_dir_get_run() -> Result { + } + } + ++#[cfg(debug)] + fn reli_dir_prepare_out() -> Result<()> { + let dir_string = out_dir_string_get(); + if let Some(d_str) = dir_string { +@@ -390,6 +416,7 @@ fn reli_dir_prepare_out() -> Result<()> { + }) + } + ++#[cfg(debug)] + fn reli_dir_get_out() -> Result { + let dir_string = out_dir_string_get(); + if let Some(d_str) = dir_string { +@@ -405,6 +432,7 @@ fn reli_dir_get_out() -> Result { + }) + } + ++#[cfg(debug)] + fn reli_dir_prepare_customize() -> Result<()> { + let dir_string = env::var("PROCESS_LIB_LOAD_PATH").ok(); + if let Some(d_str) = dir_string { +@@ -425,6 +453,7 @@ fn reli_dir_prepare_customize() -> Result<()> { + }) + } + ++#[cfg(debug)] + fn reli_dir_get_customize() -> Result { + let dir_string = env::var("PROCESS_LIB_LOAD_PATH").ok(); + if let Some(d_str) = dir_string { +@@ -443,6 +472,7 @@ fn reli_dir_get_customize() -> Result { + }) + } + ++#[cfg(debug)] + fn out_dir_string_get() -> Option { + let run = env::var("OUT_DIR").ok(); + let compile: Option = option_env!("OUT_DIR").map(String::from); +diff --git a/core/libsysmaster/rel/debug.rs b/core/libsysmaster/rel/debug.rs +new file mode 100644 +index 0000000..fff3463 +--- /dev/null ++++ b/core/libsysmaster/rel/debug.rs +@@ -0,0 +1,106 @@ ++use super::base::{self}; ++use crate::error::*; ++use basic::do_entry_or_return_io_error; ++use std::fs::{self, File}; ++use std::path::Path; ++use std::thread; ++use std::time::Duration; ++ ++const RELI_DEBUG_SWITCH_FILE: &str = "switch.debug"; ++const RELI_DEBUG_CLEAR_FILE: &str = "clear.debug"; ++const RELI_DEBUG_CFIRST_FILE: &str = "clear_first.debug"; ++const RELI_DEBUG_ENABLE_FILE: &str = "enable.debug"; ++const RELI_DEBUG_PANIC_FILE: &str = "panic.debug"; ++const RELI_DEBUG_PFIRST_FILE: &str = "panic_first.debug"; ++const RELI_DEBUG_SLEEP_FILE: &str = "sleep.debug"; ++ ++#[derive(Debug)] ++pub(crate) struct ReliDebug { ++ hdir: String, // home-directory ++} ++ ++impl ReliDebug { ++ pub(crate) fn new(dir_str: &str) -> ReliDebug { ++ ReliDebug { ++ hdir: String::from(dir_str), ++ } ++ } ++ ++ pub(crate) fn enable(&self) -> bool { ++ let enable = Path::new(&self.hdir).join(RELI_DEBUG_ENABLE_FILE); ++ enable.exists() ++ } ++ ++ pub(crate) fn clear(&self) -> bool { ++ let clear = Path::new(&self.hdir).join(RELI_DEBUG_CLEAR_FILE); ++ if clear.exists() { ++ let cfirst = Path::new(&self.hdir).join(RELI_DEBUG_CFIRST_FILE); ++ if cfirst.exists() { ++ // do nothing ++ log::info!("reliability debug_clear: non-first time, do nothing."); ++ false ++ } else { ++ File::create(&cfirst).unwrap(); ++ log::debug!("Successfully created {cfirst:?}"); ++ ++ // clear data ++ log::info!("reliability debug_clear: first time, clear ..."); ++ true ++ } ++ } else { ++ false ++ } ++ } ++ ++ pub(crate) fn panic(&self) { ++ let panic = Path::new(&self.hdir).join(RELI_DEBUG_PANIC_FILE); ++ if panic.exists() { ++ let pfirst = Path::new(&self.hdir).join(RELI_DEBUG_PFIRST_FILE); ++ if pfirst.exists() { ++ // do nothing ++ log::info!("reliability debug_panic: non-first time, do nothing."); ++ } else { ++ File::create(&pfirst).unwrap(); ++ log::debug!("Successfully created {pfirst:?}"); ++ ++ // panic ++ log::info!("reliability debug_panic: first time, panic ..."); ++ panic!("first debug_panic."); ++ } ++ } ++ } ++ ++ pub(crate) fn sleep(&self) { ++ let sleep = Path::new(&self.hdir).join(RELI_DEBUG_SLEEP_FILE); ++ if sleep.exists() { ++ log::info!("reliability debug: sleep..."); ++ thread::sleep(Duration::from_secs(3600)); ++ } ++ } ++} ++ ++#[allow(dead_code)] ++pub(crate) fn enable_switch(enable: bool) -> Result<()> { ++ // do the debug action: enable or disable switch flag. effective after restart. ++ log::info!("reliability debug: enable[{}] switch.", enable); ++ ++ let dir_string = base::reli_dir_get().unwrap(); ++ let switch = Path::new(&dir_string).join(RELI_DEBUG_SWITCH_FILE); ++ // touch switch.debug if enable ++ if enable && !switch.exists() { ++ do_entry_or_return_io_error!(File::create, switch, "create"); ++ } ++ // remove switch.debug if disable ++ if !enable && switch.exists() { ++ do_entry_or_return_io_error!(fs::remove_file, switch, "remove"); ++ } ++ ++ Ok(()) ++} ++ ++pub(crate) fn switch() -> bool { ++ let dir_string = base::reli_dir_get().expect("guaranteed by caller."); ++ let switch = Path::new(&dir_string).join(RELI_DEBUG_SWITCH_FILE); ++ log::info!("reliability debug: get switch file: {:?}.", switch); ++ switch.exists() ++} +diff --git a/core/libsysmaster/rel/mod.rs b/core/libsysmaster/rel/mod.rs +index 07470e4..2ae515a 100644 +--- a/core/libsysmaster/rel/mod.rs ++++ b/core/libsysmaster/rel/mod.rs +@@ -11,15 +11,17 @@ + // See the Mulan PSL v2 for more details. + + //! reliability module +-pub use api::{reli_debug_enable_switch, reli_debug_get_switch, ReliConf, Reliability}; ++pub use api::{reli_debug_get_switch, ReliConf, Reliability}; + pub use base::{reli_dir_prepare, ReDb, ReDbRoTxn, ReDbRwTxn, ReDbTable}; + use serde::{Deserialize, Serialize}; + pub use station::{ReStation, ReStationKind}; + use std::convert::TryFrom; + +-// dependency: base -> {enable | last | history | pending | station} -> api ++// dependency: base -> {enable | last | history | pending | station} -> debug -> api + mod api; + mod base; ++#[cfg(debug)] ++mod debug; + mod enable; + mod history; + mod last; +-- +2.33.0 + diff --git a/backport-fix-libbasic-create-relative-symlink-in-right-way.patch b/backport-fix-libbasic-create-relative-symlink-in-right-way.patch new file mode 100644 index 0000000..3ca9949 --- /dev/null +++ b/backport-fix-libbasic-create-relative-symlink-in-right-way.patch @@ -0,0 +1,96 @@ +From e4e5ecb66154ee71dde02120287aaf26a24577d1 Mon Sep 17 00:00:00 2001 +From: chenjiayi +Date: Tue, 20 Jun 2023 02:50:36 +0800 +Subject: [PATCH] fix(libbasic): create relative symlink in right way + +When creating relative symlink, 'symlinkat' should take the directory +fd as input, but previously the 'symlink' function tried to open the +symlink that hasn't been created. The unit test case for 'symlink' just +consider the usage on creating non-relative symlink, thus it didn't +find the bug when creating relative symlink. +--- + libs/basic/src/fs_util.rs | 39 ++++++++++++++++++++++----------------- + 1 file changed, 22 insertions(+), 17 deletions(-) + +diff --git a/libs/basic/src/fs_util.rs b/libs/basic/src/fs_util.rs +index e7cbfb9..63c43ca 100644 +--- a/libs/basic/src/fs_util.rs ++++ b/libs/basic/src/fs_util.rs +@@ -42,17 +42,18 @@ pub fn symlink(target: &str, link: &str, relative: bool) -> Result<()> { + })?; + + let rel_path = diff_paths(target_path, link_path_parent).unwrap(); +- let fd = nix::fcntl::open(&rel_path, OFlag::O_DIRECT, Mode::from_bits(0).unwrap()) +- .context(NixSnafu)?; ++ let fd = nix::fcntl::open( ++ link_path_parent, ++ OFlag::O_DIRECTORY | OFlag::O_CLOEXEC | OFlag::O_NOFOLLOW, ++ Mode::from_bits(0).unwrap(), ++ ) ++ .context(NixSnafu)?; + (rel_path, Some(fd)) + } else { + (target_path.to_path_buf(), None) + }; + +- nix::unistd::symlinkat(target_path.as_path(), fd, link_path).map_err(|e| { +- log::debug!("Failed to create symlink: {} -> {}", link, target); +- Error::Nix { source: e } +- }) ++ nix::unistd::symlinkat(target_path.as_path(), fd, link_path).context(NixSnafu) + } + + /// chmod based on fd opened with O_PATH +@@ -61,18 +62,14 @@ pub fn fchmod_opath(fd: i32, mode: mode_t) -> Result<()> { + + let mut perms = std::fs::metadata(&fd_path).context(IoSnafu)?.permissions(); + perms.set_mode(mode); +- std::fs::set_permissions(&fd_path, perms).context(IoSnafu)?; +- +- Ok(()) ++ std::fs::set_permissions(&fd_path, perms).context(IoSnafu) + } + + /// chmod based on path + pub fn chmod(path: &str, mode: mode_t) -> Result<()> { + let mut perms = std::fs::metadata(path).context(IoSnafu)?.permissions(); + perms.set_mode(mode); +- std::fs::set_permissions(path, perms).context(IoSnafu)?; +- +- Ok(()) ++ std::fs::set_permissions(path, perms).context(IoSnafu) + } + + /// Safely chmod and chown based on a file description. If ownership +@@ -183,15 +180,23 @@ mod tests { + return; + } + +- let ret = symlink("/dev/null", "/tmp/test_link_name_39285b", false); +- assert!(ret.is_ok()); ++ symlink("/dev/null", "/tmp/test_link_name_39285b", false).unwrap(); + +- let ret = unistd::unlinkat( ++ unistd::unlinkat( + None, + link_name_path.to_str().unwrap(), + unistd::UnlinkatFlags::NoRemoveDir, +- ); +- assert!(ret.is_ok()); ++ ) ++ .unwrap(); ++ ++ symlink("/dev/null", "/tmp/test_link_name_39285c", true).unwrap(); ++ ++ unistd::unlinkat( ++ None, ++ "/tmp/test_link_name_39285c", ++ unistd::UnlinkatFlags::NoRemoveDir, ++ ) ++ .unwrap(); + } + + /// test changing the mode of a file by file descriptor with O_PATH +-- +2.33.0 + diff --git a/backport-fix-libbasic-create-symlink-atomically.patch b/backport-fix-libbasic-create-symlink-atomically.patch new file mode 100644 index 0000000..938af69 --- /dev/null +++ b/backport-fix-libbasic-create-symlink-atomically.patch @@ -0,0 +1,77 @@ +From 58774990868761750874fc8c21af0ccabefb1e53 Mon Sep 17 00:00:00 2001 +From: chenjiayi +Date: Wed, 21 Jun 2023 23:43:12 +0800 +Subject: [PATCH] fix(libbasic): create symlink atomically + +Create a temporary symlink and rename it into the final symlink. +If there exists a symlink with the same name already, the symlink +will be overrided. If any error occurs, the original symlink will +be reserved. +--- + libs/basic/Cargo.toml | 1 + + libs/basic/src/fs_util.rs | 20 ++++++++++++++++---- + 2 files changed, 17 insertions(+), 4 deletions(-) + +diff --git a/libs/basic/Cargo.toml b/libs/basic/Cargo.toml +index 64fbfba..7557d37 100644 +--- a/libs/basic/Cargo.toml ++++ b/libs/basic/Cargo.toml +@@ -20,6 +20,7 @@ caps = "0.5.5" + lazy_static = "1.4.0" + bitflags = "1.3.2" + pkg-config = "0.3" ++rand = "0.4.6" + + [dev-dependencies] + libtests = { path = "../libtests" } +diff --git a/libs/basic/src/fs_util.rs b/libs/basic/src/fs_util.rs +index 5f34e9a..6a6378d 100644 +--- a/libs/basic/src/fs_util.rs ++++ b/libs/basic/src/fs_util.rs +@@ -15,11 +15,12 @@ + use crate::{error::*, format_proc_fd_path}; + use libc::{fchownat, mode_t, timespec, AT_EMPTY_PATH, S_IFLNK, S_IFMT}; + use nix::{ +- fcntl::OFlag, ++ fcntl::{renameat, OFlag}, + sys::stat::{fstat, Mode}, +- unistd::{Gid, Uid}, ++ unistd::{unlinkat, Gid, Uid, UnlinkatFlags}, + }; + use pathdiff::diff_paths; ++use rand::Rng; + use std::{fs::remove_dir, io::ErrorKind, os::unix::prelude::PermissionsExt, path::Path}; + + /// open the parent directory of path +@@ -36,7 +37,7 @@ pub fn symlink(target: &str, link: &str, relative: bool) -> Result<()> { + let link_path = Path::new(&link); + let target_path = Path::new(&target); + +- let (target_path, fd) = if relative { ++ let (target_path, dirfd) = if relative { + let link_path_parent = link_path.parent().ok_or(Error::NotExisted { + what: format!("{}'s parent", link_path.to_string_lossy()), + })?; +@@ -53,7 +54,18 @@ pub fn symlink(target: &str, link: &str, relative: bool) -> Result<()> { + (target_path.to_path_buf(), None) + }; + +- nix::unistd::symlinkat(target_path.as_path(), fd, link_path).context(NixSnafu) ++ let mut rng = rand::thread_rng(); ++ ++ let tmp_to = format!("{}.{}", link, rng.gen::()); ++ ++ nix::unistd::symlinkat(target_path.as_path(), dirfd, tmp_to.as_str()).context(NixSnafu)?; ++ ++ if let Err(e) = renameat(dirfd, tmp_to.as_str(), dirfd, link_path) { ++ let _ = unlinkat(dirfd, tmp_to.as_str(), UnlinkatFlags::NoRemoveDir); ++ return Err(Error::Nix { source: e }); ++ } ++ ++ Ok(()) + } + + /// chmod based on fd opened with O_PATH +-- +2.33.0 + diff --git a/backport-fix-libbasic-try-to-follow-the-fd-path-to-make-the-u.patch b/backport-fix-libbasic-try-to-follow-the-fd-path-to-make-the-u.patch new file mode 100644 index 0000000..3f6ac2f --- /dev/null +++ b/backport-fix-libbasic-try-to-follow-the-fd-path-to-make-the-u.patch @@ -0,0 +1,152 @@ +From 11b505249041b6368eaac0b5699c455599a9565a Mon Sep 17 00:00:00 2001 +From: chenjiayi +Date: Tue, 27 Jun 2023 05:01:37 +0800 +Subject: [PATCH] fix(libbasic): try to follow the fd path to make the + utimensat work + +In devmaster threads, utimensat will fail with errno of ENOENT, which means +the file path does not exist, if the fd path is used. The fd path is a symlink to +the opened real file. It is weired because the fd path really exists but utimesat +can not find it. To avoid the failure, we have no choice but to follow the fd path +symlink to the real file, and update the timestamp directly on it. +--- + libs/basic/src/error.rs | 7 +++- + libs/basic/src/fs_util.rs | 78 ++++++++++++++++++++++++++------------- + 2 files changed, 57 insertions(+), 28 deletions(-) + +diff --git a/libs/basic/src/error.rs b/libs/basic/src/error.rs +index 2730883..cfa89f8 100644 +--- a/libs/basic/src/error.rs ++++ b/libs/basic/src/error.rs +@@ -44,6 +44,9 @@ pub enum Error { + #[snafu(display("procfs: {}", source))] + Proc { source: procfs::ProcError }, + ++ #[snafu(display("NulError: '{}'", source))] ++ NulError { source: std::ffi::NulError }, ++ + #[snafu(display("Error parsing from string: {}", source))] + Parse { + source: Box, +@@ -52,13 +55,13 @@ pub enum Error { + #[snafu(display("Invalid naming scheme string: {}", what))] + ParseNamingScheme { what: String }, + +- #[snafu(display("Not exist): '{}'.", what))] ++ #[snafu(display("Not exist: '{}'.", what))] + NotExisted { what: String }, + + #[snafu(display("Invalid: '{}'.", what))] + Invalid { what: String }, + +- #[snafu(display("OtherError): '{}'.", msg))] ++ #[snafu(display("OtherError: '{}'.", msg))] + Other { msg: String }, + } + +diff --git a/libs/basic/src/fs_util.rs b/libs/basic/src/fs_util.rs +index 6a6378d..3f72658 100644 +--- a/libs/basic/src/fs_util.rs ++++ b/libs/basic/src/fs_util.rs +@@ -15,13 +15,15 @@ + use crate::{error::*, format_proc_fd_path}; + use libc::{fchownat, mode_t, timespec, AT_EMPTY_PATH, S_IFLNK, S_IFMT}; + use nix::{ +- fcntl::{renameat, OFlag}, ++ fcntl::{readlink, renameat, OFlag}, + sys::stat::{fstat, Mode}, + unistd::{unlinkat, Gid, Uid, UnlinkatFlags}, + }; + use pathdiff::diff_paths; + use rand::Rng; +-use std::{fs::remove_dir, io::ErrorKind, os::unix::prelude::PermissionsExt, path::Path}; ++use std::{ ++ ffi::CString, fs::remove_dir, io::ErrorKind, os::unix::prelude::PermissionsExt, path::Path, ++}; + + /// open the parent directory of path + pub fn open_parent(path: &Path, flags: OFlag, mode: Mode) -> Result { +@@ -148,32 +150,56 @@ pub fn fchmod_and_chown( + Ok(do_chown || do_chmod) + } + +-/// if ts are not provided, use the current timestamp by default. ++/// Update the timestamp of a file with fd. If 'ts' is not provided, use the current timestamp by default. + pub fn futimens_opath(fd: i32, ts: Option<[timespec; 2]>) -> Result<()> { +- let r = unsafe { +- libc::utimensat( +- libc::AT_FDCWD, +- format_proc_fd_path!(fd).as_ptr() as *const libc::c_char, +- &ts.unwrap_or([ +- timespec { +- tv_sec: 0, +- tv_nsec: libc::UTIME_NOW, +- }, +- timespec { +- tv_sec: 0, +- tv_nsec: libc::UTIME_NOW, +- }, +- ])[0], +- 0, +- ) +- }; +- if r < 0 { +- Err(Error::Nix { +- source: nix::Error::from_i32(std::io::Error::last_os_error().raw_os_error().unwrap()), +- }) +- } else { +- Ok(()) ++ let fd_path = format_proc_fd_path!(fd); ++ let c_string = ++ CString::new(fd_path.clone()).map_err(|e| crate::Error::NulError { source: e })?; ++ let times = ts.unwrap_or([ ++ timespec { ++ tv_sec: 0, ++ tv_nsec: libc::UTIME_NOW, ++ }, ++ timespec { ++ tv_sec: 0, ++ tv_nsec: libc::UTIME_NOW, ++ }, ++ ])[0]; ++ ++ if unsafe { libc::utimensat(libc::AT_FDCWD, c_string.as_ptr(), ×, 0) } < 0 { ++ let errno = nix::Error::from_i32( ++ std::io::Error::last_os_error() ++ .raw_os_error() ++ .unwrap_or_default(), ++ ); ++ ++ if errno == nix::Error::ENOENT { ++ /* ++ * In devmaster threads, utimensat will fail with errno of ENOENT, which means ++ * the file path does not exist, if the fd path is used. The fd path is a symlink to ++ * the opened real file. It is weird because the fd path really exists but utimesat ++ * can not find it. To avoid the failure, we try to follow the fd path symlink to the ++ * real file and update the timestamp directly on it. ++ */ ++ let target = readlink(fd_path.as_str()).unwrap(); ++ let c_string = target ++ .to_str() ++ .ok_or(Error::Nix { source: errno }) ++ .map(|s| unsafe { libc::strdup(s.as_ptr() as *const libc::c_char) })?; ++ ++ if unsafe { libc::utimensat(libc::AT_FDCWD, c_string, ×, 0) } < 0 { ++ return Err(Error::Nix { ++ source: nix::Error::from_i32( ++ std::io::Error::last_os_error().raw_os_error().unwrap(), ++ ), ++ }); ++ } ++ } else { ++ return Err(Error::Nix { source: errno }); ++ } + } ++ ++ Ok(()) + } + + /// recursively remove parent directories until specific directory +-- +2.33.0 + diff --git a/backport-fix-log-message-before-and-after-reaping-zombie-proc.patch b/backport-fix-log-message-before-and-after-reaping-zombie-proc.patch new file mode 100644 index 0000000..0030116 --- /dev/null +++ b/backport-fix-log-message-before-and-after-reaping-zombie-proc.patch @@ -0,0 +1,39 @@ +From 213633478307d6178b5ce85b27350d63174651e7 Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Wed, 5 Jul 2023 09:31:43 +0800 +Subject: [PATCH] fix: log message before and after reaping zombie process + +--- + core/sysmaster/unit/sigchld.rs | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/core/sysmaster/unit/sigchld.rs b/core/sysmaster/unit/sigchld.rs +index 72da0eb..423b9b9 100644 +--- a/core/sysmaster/unit/sigchld.rs ++++ b/core/sysmaster/unit/sigchld.rs +@@ -197,7 +197,9 @@ impl SigchldData { + } + + // check +- let (pid, _code, _signal) = si.unwrap(); ++ let (pid, code, signal) = si.unwrap(); ++ log::debug!("Process {} exited witch code: {code}, signal: {signal:?}", pid.as_raw()); ++ + if pid.as_raw() <= 0 { + log::debug!("invalid pid in signal: {:?}", pid); + return false; // turn_off +@@ -214,8 +216,9 @@ impl SigchldData { + } + + // pop: reap the zombie +- if let Err(e) = wait::waitid(Id::Pid(pid), WaitPidFlag::WEXITED) { +- log::error!("Error when reap the zombie, ignoring: {}", e); ++ match wait::waitid(Id::Pid(pid), WaitPidFlag::WEXITED) { ++ Err(e) => log::error!("Failed to reap process {}: {e}", pid.as_raw()), ++ Ok(_) => log::debug!("Reaped process {}", pid.as_raw()), + } + + true // stay turn_on +-- +2.33.0 + diff --git a/backport-fix-log-message-out-when-we-create-delete-a-file-or-.patch b/backport-fix-log-message-out-when-we-create-delete-a-file-or-.patch new file mode 100644 index 0000000..ebc0fb7 --- /dev/null +++ b/backport-fix-log-message-out-when-we-create-delete-a-file-or-.patch @@ -0,0 +1,283 @@ +From 09c44e3e4877a283bdb9bfca6ac1036513f2f2c1 Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Wed, 5 Jul 2023 16:29:35 +0800 +Subject: [PATCH] fix: log message out when we create/delete a file or + directory + +--- + coms/service/src/mng.rs | 9 ++------- + core/libsysmaster/rel/api.rs | 17 ++++++++++------- + core/libsysmaster/rel/history.rs | 23 ++++++++++------------- + core/sysmaster/manager/commands.rs | 9 ++++++--- + core/sysmaster/unit/sigchld.rs | 5 ++++- + init/src/runtime/comm.rs | 12 ++++++++---- + libs/cgroup/src/cgroup.rs | 9 +++++++-- + 9 files changed, 53 insertions(+), 46 deletions(-) + +diff --git a/coms/service/src/mng.rs b/coms/service/src/mng.rs +index 4bf20bd..b44a0dd 100644 +--- a/coms/service/src/mng.rs ++++ b/coms/service/src/mng.rs +@@ -20,7 +20,7 @@ use super::rentry::{ + }; + use super::spawn::ServiceSpawn; + use crate::rentry::{ExitStatus, PreserveMode}; +-use basic::{fd_util, IN_SET}; ++use basic::{do_entry_log, fd_util, IN_SET}; + use basic::{file_util, process_util}; + use event::{EventState, EventType, Events, Source}; + use log::Level; +@@ -623,12 +623,7 @@ impl ServiceMng { + } + + if let Some(p) = self.config.pid_file() { +- if let Err(e) = nix::unistd::unlink(&p) { +- log::warn!( +- "{}", +- format!("failed to unlink pid file: {:?}, error: {}", p, e) +- ); +- } ++ do_entry_log!(nix::unistd::unlink, p, "unlink"); + } + } + +diff --git a/core/libsysmaster/rel/api.rs b/core/libsysmaster/rel/api.rs +index ad14796..fb482b8 100644 +--- a/core/libsysmaster/rel/api.rs ++++ b/core/libsysmaster/rel/api.rs +@@ -19,6 +19,7 @@ use super::{ + ReDbTable, ReStation, ReStationKind, + }; + use crate::{error::*, rel::base}; ++use basic::do_entry_or_return_io_error; + use heed::Database; + use std::{ + fs::{self, File}, +@@ -267,6 +268,7 @@ impl Reliability { + } else { + log::info!("reliability debug_clear: first time, try clear."); + File::create(&cfirst).unwrap(); ++ log::debug!("Successfully created {cfirst:?}"); + log::info!("reliability debug_clear: first time, clear ..."); + + // clear data excluding enable +@@ -289,6 +291,7 @@ impl Reliability { + } else { + log::info!("reliability debug_panic: first time, try panic."); + File::create(&pfirst).unwrap(); ++ log::debug!("Successfully created {pfirst:?}"); + log::info!("reliability debug_panic: first time, panic ..."); + panic!("first debug_panic."); + } +@@ -366,15 +369,15 @@ impl Reliability { + pub fn reli_debug_enable_switch(enable: bool) -> Result<()> { + log::info!("reliability debug: enable[{}] switch.", enable); + +- // [enable]touch switch.debug or [disable]rm -rf switch.debug + let dir_string = base::reli_dir_get().unwrap(); + let switch = Path::new(&dir_string).join(RELI_DEBUG_SWITCH_FILE); +- if enable { +- if !switch.exists() { +- File::create(&switch).context(IoSnafu)?; +- } +- } else if switch.exists() { +- fs::remove_file(&switch).context(IoSnafu)?; ++ // touch switch.debug if enable ++ if enable && !switch.exists() { ++ do_entry_or_return_io_error!(File::create, switch, "create"); ++ } ++ // remove switch.debug if disable ++ if !enable && switch.exists() { ++ do_entry_or_return_io_error!(fs::remove_file, switch, "remove"); + } + + Ok(()) +diff --git a/core/libsysmaster/rel/history.rs b/core/libsysmaster/rel/history.rs +index 9381c10..fc31623 100644 +--- a/core/libsysmaster/rel/history.rs ++++ b/core/libsysmaster/rel/history.rs +@@ -12,6 +12,7 @@ + + use super::base::{ReDbRoTxn, ReDbRwTxn, ReDbTable}; + use crate::error::*; ++use basic::{do_entry_log, do_entry_or_return_io_error}; + use heed::{CompactionOption, Env, EnvOpenOptions}; + use std::cell::RefCell; + use std::collections::HashMap; +@@ -126,8 +127,8 @@ impl ReliHistory { + let next_file = next_path.join(RELI_HISTORY_DATA_FILE); + + // clear next: delete and re-create the whole directory +- fs::remove_dir_all(next_path.clone()).context(IoSnafu)?; +- fs::create_dir_all(next_path).context(IoSnafu)?; ++ do_entry_or_return_io_error!(fs::remove_dir_all, next_path, "remove"); ++ do_entry_or_return_io_error!(fs::create_dir_all, next_path, "create"); + + // copy to next + self.env +@@ -138,21 +139,17 @@ impl ReliHistory { + // remark the next flag at last: the another one + let bflag = bflag_path_get(history.clone()); + if self.b_exist { +- fs::remove_file(bflag).context(IoSnafu)?; ++ do_entry_or_return_io_error!(fs::remove_file, bflag, "remove"); + } else { +- File::create(bflag).context(IoSnafu)?; ++ do_entry_or_return_io_error!(File::create, bflag, "create"); + } + + // try to clear previous: it would be done in the next re-exec, but we try to delete it as soon as possible. + let cur_path = history.join(subdir_cur_get(self.b_exist)); + let cur_data = cur_path.join(RELI_HISTORY_DATA_FILE); + let cur_lock = cur_path.join(RELI_HISTORY_LOCK_FILE); +- if let Err(e) = fs::remove_file(cur_data.clone()) { +- log::error!("remove data file {:?} failed, err = {:?}", cur_data, e); +- } +- if let Err(e) = fs::remove_file(cur_lock.clone()) { +- log::error!("remove lock file {:?} failed, err = {:?}", cur_lock, e); +- } ++ do_entry_log!(fs::remove_file, cur_data, "remove"); ++ do_entry_log!(fs::remove_file, cur_lock, "remove"); + + Ok(()) + } +@@ -181,18 +178,18 @@ pub fn prepare(dir_str: &str) -> Result<()> { + // directory + let history = history_path_get(dir_str); + if !history.exists() { +- fs::create_dir_all(&history).context(IoSnafu)?; ++ do_entry_or_return_io_error!(fs::create_dir_all, history, "create"); + } + + // sub-directory + let a = history.join(RELI_HISTORY_A_DIR); + if !a.exists() { +- fs::create_dir_all(&a).context(IoSnafu)?; ++ do_entry_or_return_io_error!(fs::create_dir_all, a, "create"); + } + + let b = history.join(RELI_HISTORY_B_DIR); + if !b.exists() { +- fs::create_dir_all(&b).context(IoSnafu)?; ++ do_entry_or_return_io_error!(fs::create_dir_all, a, "create"); + } + + Ok(()) +diff --git a/core/sysmaster/manager/commands.rs b/core/sysmaster/manager/commands.rs +index 57f9d5d..6e1da40 100644 +--- a/core/sysmaster/manager/commands.rs ++++ b/core/sysmaster/manager/commands.rs +@@ -10,7 +10,7 @@ + // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + // See the Mulan PSL v2 for more details. + +-use basic::socket_util; ++use basic::{do_entry_log, socket_util}; + use cmdproto::proto::execute::ExecuterAction; + use cmdproto::proto::ProstServerStream; + use event::{EventType, Events, Source}; +@@ -37,7 +37,7 @@ impl Commands { + let sctl_socket_path = Path::new(SCTL_SOCKET); + /* remove the old socket if it exists */ + if sctl_socket_path.exists() && !sctl_socket_path.is_symlink() { +- let _ = std::fs::remove_file(sctl_socket_path); ++ do_entry_log!(std::fs::remove_file, sctl_socket_path, "remove"); + } + let sctl_socket_addr = socket::UnixAddr::new(Path::new(SCTL_SOCKET)).unwrap(); + let socket_fd = socket::socket( +@@ -51,7 +51,10 @@ impl Commands { + socket_util::set_pass_cred(socket_fd, true).unwrap(); + /* create the socket with mode 666 */ + let old_mask = stat::umask(stat::Mode::from_bits_truncate(!0o666)); +- let _ = socket::bind(socket_fd, &sctl_socket_addr); ++ match socket::bind(socket_fd, &sctl_socket_addr) { ++ Err(e) => log::error!("Failed to bind {sctl_socket_addr:?}: {e}"), ++ Ok(_) => log::debug!("Successfully bind {sctl_socket_addr:?}"), ++ } + /* restore our umask */ + let _ = stat::umask(old_mask); + /* Allow at most 4096 incoming connections can queue */ +diff --git a/core/sysmaster/unit/sigchld.rs b/core/sysmaster/unit/sigchld.rs +index 423b9b9..eead6f7 100644 +--- a/core/sysmaster/unit/sigchld.rs ++++ b/core/sysmaster/unit/sigchld.rs +@@ -198,7 +198,10 @@ impl SigchldData { + + // check + let (pid, code, signal) = si.unwrap(); +- log::debug!("Process {} exited witch code: {code}, signal: {signal:?}", pid.as_raw()); ++ log::debug!( ++ "Process {} exited witch code: {code}, signal: {signal:?}", ++ pid.as_raw() ++ ); + + if pid.as_raw() <= 0 { + log::debug!("invalid pid in signal: {:?}", pid); +diff --git a/init/src/runtime/comm.rs b/init/src/runtime/comm.rs +index 8f71511..92d52bc 100644 +--- a/init/src/runtime/comm.rs ++++ b/init/src/runtime/comm.rs +@@ -282,11 +282,15 @@ fn create_listen_fd(epoll: &Rc) -> Result<(i32, Inotify, WatchDescriptor) + )?; + + let sock_path = PathBuf::from(INIT_SOCKET); +- let parent_path = sock_path.as_path().parent(); +- match parent_path { +- Some(path) => fs::create_dir_all(path) +- .map_err(|e| Errno::from_i32(e.raw_os_error().unwrap_or(Errno::EINVAL as i32)))?, ++ let path = match sock_path.as_path().parent() { + None => return Err(Errno::EINVAL), ++ Some(v) => v, ++ }; ++ if let Err(e) = fs::create_dir_all(path) { ++ eprintln!("Failed to create directory {path:?}: {e}"); ++ return Err(Errno::from_i32( ++ e.raw_os_error().unwrap_or(Errno::EINVAL as i32), ++ )); + } + + if let Err(e) = unistd::unlink(&sock_path) { +diff --git a/libs/cgroup/src/cgroup.rs b/libs/cgroup/src/cgroup.rs +index 13efee2..02b266c 100644 +--- a/libs/cgroup/src/cgroup.rs ++++ b/libs/cgroup/src/cgroup.rs +@@ -13,6 +13,7 @@ + use super::CgFlags; + use crate::error::*; + use crate::CgType; ++use basic::do_entry_or_return_io_error; + use basic::special::CGROUP_SYSMASTER; + use basic::special::INIT_SCOPE; + use basic::special::SYSMASTER_SLICE; +@@ -146,7 +147,7 @@ pub fn cg_attach(pid: Pid, cg_path: &PathBuf) -> Result<()> { + pub fn cg_create(cg_path: &PathBuf) -> Result<()> { + log::debug!("cgroup create path {:?}", cg_path); + let abs_cg_path: PathBuf = cg_abs_path(cg_path, &PathBuf::from(""))?; +- fs::create_dir_all(abs_cg_path).context(IoSnafu)?; ++ do_entry_or_return_io_error!(fs::create_dir_all, abs_cg_path, "create"); + + Ok(()) + } +@@ -232,7 +233,10 @@ fn remove_dir(cg_path: &PathBuf) -> Result<()> { + let mut try_times = 0; + loop { + let e = match fs::remove_dir(cg_path) { +- Ok(()) => return Ok(()), ++ Ok(()) => { ++ log::debug!("Successfully removed {cg_path:?}"); ++ return Ok(()); ++ } + Err(e) => e, + }; + let os_errno = match e.raw_os_error() { +@@ -244,6 +248,7 @@ fn remove_dir(cg_path: &PathBuf) -> Result<()> { + try_times += 1; + continue; + } ++ log::error!("Failed to remove {cg_path:?}: {e}"); + return Err(Error::Io { source: e }); + } + } +-- +2.33.0 + diff --git a/backport-fix-log-message-when-creating-symlink.patch b/backport-fix-log-message-when-creating-symlink.patch new file mode 100644 index 0000000..7b7208a --- /dev/null +++ b/backport-fix-log-message-when-creating-symlink.patch @@ -0,0 +1,70 @@ +From 9384fffab8369e6390d37a20b969eaec7b1a2b19 Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Wed, 5 Jul 2023 16:26:19 +0800 +Subject: [PATCH] fix: log message when creating symlink. + +Also, rename tmp_to to tmp_link, and add comment to avoid using 'from/to' in this function +--- + libs/basic/src/fs_util.rs | 22 +++++++++++++++------- + 1 file changed, 15 insertions(+), 7 deletions(-) + +diff --git a/libs/basic/src/fs_util.rs b/libs/basic/src/fs_util.rs +index 413008b..ec814e2 100644 +--- a/libs/basic/src/fs_util.rs ++++ b/libs/basic/src/fs_util.rs +@@ -38,7 +38,9 @@ pub fn open_parent(path: &Path, flags: OFlag, mode: Mode) -> Result { + Ok(unsafe { File::from_raw_fd(nix::fcntl::open(parent, flags, mode).context(NixSnafu)?) }) + } + +-/// create symlink link_name -> target ++/// create symlink link -> target ++/* Please don't use "from/to", use "symlink/target" to name path. ++ * Take "A -> B" for example, A is "link", B is "target". */ + pub fn symlink(target: &str, link: &str, relative: bool) -> Result<()> { + let link_path = Path::new(&link); + let target_path = Path::new(&target); +@@ -48,29 +50,35 @@ pub fn symlink(target: &str, link: &str, relative: bool) -> Result<()> { + what: format!("{}'s parent", link_path.to_string_lossy()), + })?; + +- let rel_path = diff_paths(target_path, link_path_parent).unwrap(); ++ let relative_path = diff_paths(target_path, link_path_parent).unwrap(); + let fd = nix::fcntl::open( + link_path_parent, + OFlag::O_DIRECTORY | OFlag::O_CLOEXEC | OFlag::O_NOFOLLOW, + Mode::from_bits(0).unwrap(), + ) + .context(NixSnafu)?; +- (rel_path, Some(unsafe { File::from_raw_fd(fd) })) ++ (relative_path, Some(unsafe { File::from_raw_fd(fd) })) + } else { + (target_path.to_path_buf(), None) + }; + + let mut rng = rand::thread_rng(); +- let tmp_to = format!("{}.{}", link, rng.gen::()); ++ let tmp_link = format!("{}.{}", link, rng.gen::()); + let raw_fd = dir.map(|f| f.as_raw_fd()); + +- nix::unistd::symlinkat(target_path.as_path(), raw_fd, tmp_to.as_str()).context(NixSnafu)?; ++ if let Err(e) = nix::unistd::symlinkat(target_path.as_path(), raw_fd, tmp_link.as_str()) { ++ log::error!("Failed to create symlink {link} -> {target}: {e}"); ++ return Err(Error::Nix { source: e }); ++ } + +- if let Err(e) = renameat(raw_fd, tmp_to.as_str(), raw_fd, link_path) { +- let _ = unlinkat(raw_fd, tmp_to.as_str(), UnlinkatFlags::NoRemoveDir); ++ if let Err(e) = renameat(raw_fd, tmp_link.as_str(), raw_fd, link_path) { ++ log::error!("Failed to rename the temporary path of {link_path:?}: {e}"); ++ let _ = unlinkat(raw_fd, tmp_link.as_str(), UnlinkatFlags::NoRemoveDir); + return Err(Error::Nix { source: e }); + } + ++ log::debug!("Successfully created symlink: {link} -> {target}"); ++ + Ok(()) + } + +-- +2.33.0 + diff --git a/backport-fix-make-config.service.toml-same-as-config.service.patch b/backport-fix-make-config.service.toml-same-as-config.service.patch new file mode 100644 index 0000000..e52405d --- /dev/null +++ b/backport-fix-make-config.service.toml-same-as-config.service.patch @@ -0,0 +1,37 @@ +From 8b447063d1ebde763cbb19563b682d5709282301 Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Fri, 30 Jun 2023 17:17:48 +0800 +Subject: [PATCH] fix: make config.service.toml same as config.service + +--- + tests/test_units/config.service.toml | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/tests/test_units/config.service.toml b/tests/test_units/config.service.toml +index 5b00dc6..8c56508 100644 +--- a/tests/test_units/config.service.toml ++++ b/tests/test_units/config.service.toml +@@ -1,11 +1,12 @@ + [Unit] + Description="CN" + Documentation="192.168.1.1" +- ++Requires="test.service" + + [Service] + Type="Simple" + ExecCondition="/usr/bin/sleep 5" ++ExecStartPre="/usr/bin/echo test" + ExecStart="/bin/echo 'test'" + ExecStop="/bin/kill $MAINPID" + WatchdogSec=10 +@@ -13,5 +14,6 @@ Restart="always" + RestartPreventExitStatus="1 2 SIGKILL" + RestartSec=5 + ++ + [Install] + WantedBy="dbus.service" +-- +2.33.0 + diff --git a/backport-fix-make-test_cgroup-really-work.patch b/backport-fix-make-test_cgroup-really-work.patch new file mode 100644 index 0000000..74c7dfd --- /dev/null +++ b/backport-fix-make-test_cgroup-really-work.patch @@ -0,0 +1,124 @@ +From c818931d9e6f64bcac77c4c4d21a1ec34078bce3 Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Mon, 19 Jun 2023 15:29:13 +0800 +Subject: [PATCH] fix: make test_cgroup really work. + +1. we used to attach our test tasks to system.slice, this is not safe. + Because system.slice is a common name, and there are many system + process attched in this directory, we can't just kill all processes + in this directory. + +2. remove_dir used to return Ok(()) even if there is really a error. + +3. use fs::remove_dir instead of fs::remove_all_dir because /sys/fs/cgroup + is a pseudo file system, we can't really remove files here. +--- + libs/cgroup/src/cgroup.rs | 74 ++++++++++++++++++++++++++++++--------- + 1 file changed, 58 insertions(+), 16 deletions(-) + +diff --git a/libs/cgroup/src/cgroup.rs b/libs/cgroup/src/cgroup.rs +index 83fe8ca..18513c2 100644 +--- a/libs/cgroup/src/cgroup.rs ++++ b/libs/cgroup/src/cgroup.rs +@@ -188,20 +188,64 @@ pub fn cg_get_pids(cg_path: &PathBuf) -> Vec { + } + + fn remove_dir(cg_path: &PathBuf) -> Result<()> { +- let abs_cg_path: PathBuf = cg_abs_path(cg_path, &PathBuf::from(""))?; +- +- match fs::remove_dir_all(abs_cg_path.clone()) { +- Ok(_) => {} ++ if !cg_path.is_absolute() { ++ log::error!("We only support remove absolute directory."); ++ return Err(Error::NotSupported); ++ } ++ /* Note: We can't just call fs::remove_all_dir here. This is because /sys/fs/cgroup ++ * is a pseudo file system, we can only remove directory, but can't remove regular ++ * file. */ ++ let read_dir = match cg_path.read_dir() { + Err(e) => { +- log::debug!( +- "remove dir failed:{:?}, err: {}", +- abs_cg_path, +- e.to_string() +- ); ++ log::error!("Failed to read dir: {:?}", cg_path); ++ return Err(Error::Io { source: e }); ++ } ++ Ok(v) => v, ++ }; ++ ++ for entry in read_dir { ++ let entry = match entry { ++ Err(e) => { ++ log::error!("Failed to get directory entry: {e}"); ++ return Err(Error::Io { source: e }); ++ } ++ Ok(v) => v, ++ }; ++ let entry_file_type = match entry.file_type() { ++ Err(e) => { ++ log::error!( ++ "Failed to geth the file type of {:?}: {e}", ++ entry.file_name() ++ ); ++ return Err(Error::Io { source: e }); ++ } ++ Ok(v) => v, ++ }; ++ if !entry_file_type.is_dir() { ++ continue; + } ++ remove_dir(&entry.path())?; + } + +- Ok(()) ++ /* Sometimes there are still tasks in cg_path, and rmdir will return EBUSY, ++ * we wait 10 us for 10 times. */ ++ let mut try_times = 0; ++ loop { ++ let e = match fs::remove_dir(cg_path) { ++ Ok(()) => return Ok(()), ++ Err(e) => e, ++ }; ++ let os_errno = match e.raw_os_error() { ++ None => return Err(Error::Io { source: e }), ++ Some(v) => v, ++ }; ++ if os_errno == nix::libc::EBUSY && try_times < 10 { ++ std::thread::sleep(std::time::Duration::from_micros(10)); ++ try_times += 1; ++ continue; ++ } ++ return Err(Error::Io { source: e }); ++ } + } + + fn cg_kill_process( +@@ -291,11 +335,9 @@ pub fn cg_kill_recursive( + cg_kill(cg_path, signal, flags, pids)?; + + if flags.contains(CgFlags::REMOVE) { +- match remove_dir(cg_path) { +- Ok(_) => {} +- Err(e) => { +- return Err(e); +- } ++ let abs_cg_path = cg_abs_path(cg_path, &PathBuf::from(""))?; ++ if let Err(e) = remove_dir(&abs_cg_path) { ++ return Err(e); + } + } + +@@ -645,7 +687,7 @@ mod tests { + return; + }; + +- let cg_path = PathBuf::from("system.slice"); ++ let cg_path = PathBuf::from("sysmaster-test.slice"); + let ret = super::cg_create(&cg_path); + assert!(ret.is_ok()); + +-- +2.33.0 + diff --git a/backport-fix-make-the-help-information-clearer.patch b/backport-fix-make-the-help-information-clearer.patch new file mode 100644 index 0000000..bd466bc --- /dev/null +++ b/backport-fix-make-the-help-information-clearer.patch @@ -0,0 +1,168 @@ +From 911a991c592cddda0dd7827e8d42277b1fda43cc Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Tue, 11 Jul 2023 20:40:39 +0800 +Subject: [PATCH] fix: make the help information clearer + +--- + core/sctl/main.rs | 82 ++++++++++++++++++++++++++++------------------- + 1 file changed, 49 insertions(+), 33 deletions(-) + +diff --git a/core/sctl/main.rs b/core/sctl/main.rs +index 664db62..10e9ae8 100644 +--- a/core/sctl/main.rs ++++ b/core/sctl/main.rs +@@ -36,102 +36,118 @@ struct Args { + + #[derive(Parser, Debug)] + enum SubCmd { +- /// [units] start the units ++ /// [unit] Isolate one or more units + #[clap(display_order = 1)] +- Start { ++ Isolate { + #[clap(required = true)] + units: Vec, + }, + +- /// [units] stop the units ++ /// [unit] Reload one or more units + #[clap(display_order = 2)] +- Stop { ++ Reload { + #[clap(required = true)] + units: Vec, + }, + +- /// [units] restart the units ++ /// [unit] Reset the failed state of one or more units + #[clap(display_order = 3)] +- Restart { units: Vec }, ++ ResetFailed { ++ #[clap(required = true)] ++ units: Vec, ++ }, + +- /// [units] status of the units ++ /// [unit] Restart one or more units + #[clap(display_order = 4)] +- Status { ++ Restart { + #[clap(required = true)] + units: Vec, + }, + +- /// [units] reload the units ++ /// [unit] Show the status of one or more units + #[clap(display_order = 5)] +- Reload { ++ Status { + #[clap(required = true)] + units: Vec, + }, + +- /// [units] isolate the units +- Isolate { ++ /// [unit] Start one or more units ++ #[clap(display_order = 6)] ++ Start { + #[clap(required = true)] + units: Vec, + }, + +- /// [units] reset the failed units +- ResetFailed { ++ /// [unit] Stop one or more units ++ #[clap(display_order = 7)] ++ Stop { + #[clap(required = true)] + units: Vec, + }, + +- /// [manager] list all units ++ /// [manager] Reload sysmaster manager configuration ++ #[clap(display_order = 8)] ++ DaemonReload {}, ++ ++ /// [manager] Reexecute sysmaster manager ++ #[clap(display_order = 9)] ++ DaemonReexec {}, ++ ++ /// [manager] List all units ++ #[clap(display_order = 10)] + ListUnits {}, + +- /// [system] shutdown the system +- Shutdown { ++ /// [system] Halt the system ++ #[clap(display_order = 11)] ++ Halt { + #[clap(short, required = false)] + force: bool, + }, + +- /// [system] reboot the system +- Reboot { ++ /// [system] Poweroff the system ++ #[clap(display_order = 12)] ++ Poweroff { + #[clap(short, required = false)] + force: bool, + }, + +- /// [system] halt the system +- Halt { ++ /// [system] Reboot the system ++ #[clap(display_order = 13)] ++ Reboot { + #[clap(short, required = false)] + force: bool, + }, + +- /// [system] poweroff the system +- Poweroff { ++ /// [system] Shutdown the system ++ #[clap(display_order = 14)] ++ Shutdown { + #[clap(short, required = false)] + force: bool, + }, + +- /// [manager] Reload sysmaster manager configuration +- DaemonReload {}, +- +- /// [manager] Reexecute sysmaster manager +- DaemonReexec {}, +- +- /// enable one unit file ++ /// [unit-file] Enable one or more units ++ #[clap(display_order = 15)] + Enable { + #[clap(required = true)] + unit_file: Vec, + }, + +- /// enable one unit file ++ /// [unit-file] Disable one or more units ++ #[clap(display_order = 16)] + Disable { + #[clap(required = true)] + unit_file: Vec, + }, + +- // mask one unit file ++ /// [unit-file] Mask one or more units ++ #[clap(display_order = 17)] + Mask { + #[clap(required = true)] + unit_file: Vec, + }, + +- // unmask one unit file ++ /// [unit-file] Unmask one or more units ++ #[clap(display_order = 18)] + Unmask { + #[clap(required = true)] + unit_file: Vec, +-- +2.33.0 + diff --git a/backport-fix-remove-unit_obj_create_default-we-never-use-it.patch b/backport-fix-remove-unit_obj_create_default-we-never-use-it.patch new file mode 100644 index 0000000..651e231 --- /dev/null +++ b/backport-fix-remove-unit_obj_create_default-we-never-use-it.patch @@ -0,0 +1,185 @@ +From 8c8d9b46e84b4c33afb6a3356e660aaca915ce88 Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Sun, 25 Jun 2023 15:06:52 +0800 +Subject: [PATCH] fix: remove unit_obj_create_default, we never use it + +--- + core/bin/plugin/mod.rs | 120 +++++++++++++++++++++-------------------- + core/lib/unit/base.rs | 18 ------- + 2 files changed, 62 insertions(+), 76 deletions(-) + +diff --git a/core/bin/plugin/mod.rs b/core/bin/plugin/mod.rs +index 0b67f74..69bf8b8 100644 +--- a/core/bin/plugin/mod.rs ++++ b/core/bin/plugin/mod.rs +@@ -62,10 +62,6 @@ use walkdir::{DirEntry, WalkDir}; + + const LIB_PLUGIN_PATH: &str = "/usr/lib/sysmaster/plugin/"; + +-const CONSTRUCTOR_NAME_DEFAULT: &[u8; 25] = b"__unit_obj_create_default"; +- +-const CONSTRUCTOR_NAME_WITH_PARAM: &[u8; 29] = b"__unit_obj_create_with_params"; +- + static INSTANCE: Lazy> = Lazy::new(|| { + let plugin = Plugin::new(); + let default_lib_path = Plugin::get_default_libpath(); +@@ -293,65 +289,73 @@ impl Plugin { + filename: &OsStr, + reload_handler: &mut dynamic_reload::DynamicReload, + ) -> Result<()> { +- if let Some(v) = filename.to_str() { +- let unit_type = self.get_unit_type(v); +- if unit_type == UnitType::UnitTypeInvalid { +- log::error!("lib name {} is invalid, skip it", v); ++ let v = match filename.to_str() { ++ None => return Ok(()), ++ Some(v) => v, ++ }; ++ ++ let unit_type = self.get_unit_type(v); ++ if unit_type == UnitType::UnitTypeInvalid { ++ log::error!("lib name {} is invalid, skipping", v); ++ return Ok(()); ++ } ++ ++ let lib = match unsafe { reload_handler.add_library(v, dynamic_reload::PlatformName::No) } { ++ Err(e) => { ++ error!("Unable to loading dynamic lib, err {:?}", e); + return Ok(()); + } ++ Ok(v) => v, ++ }; + +- match unsafe { reload_handler.add_library(v, dynamic_reload::PlatformName::No) } { +- Ok(lib) => { +- #[allow(clippy::type_complexity)] +- let symunit: Result *mut dyn SubUnit>> = unsafe { +- lib.lib +- .get(CONSTRUCTOR_NAME_DEFAULT) +- .map_err(|e| Error::PluginLoad { msg: e.to_string() }) +- }; +- if symunit.is_err() { +- log::warn!("Lib {} not contain __unit_obj_create_default try __unit_obj_create_with_params", v); +- type SymType = fn( +- um: Rc, +- level: LevelFilter, +- target: &str, +- file: &str, +- ) -> *mut dyn SubUnit; +- #[allow(clippy::type_complexity)] +- let symunit: Result> = unsafe { +- lib.lib +- .get(CONSTRUCTOR_NAME_WITH_PARAM) +- .map_err(|e| Error::PluginLoad { msg: e.to_string() }) +- }; +- if symunit.is_err() { +- log::error!("Lib {} not contain __unit_obj_create_default and __unit_obj_create_with_params skip it", v); +- return Ok(()); +- } +- } ++ /* We need the lib*.so pass SubUnit and UnitManagerObj to sysmaster-core, and we check if ++ * subunit_create_with_params and um_obj_create exists in lib*.so, because these two funs ++ * will be used to generate SubUnit and UnitManagerObj. */ + +- #[allow(clippy::type_complexity)] +- let symum: Result< +- Symbol< +- fn(level: LevelFilter, target: &str, file: &str) -> *mut dyn SubUnit, +- >, +- > = unsafe { +- lib.lib +- .get(b"__um_obj_create") +- .map_err(|e| Error::PluginLoad { msg: e.to_string() }) +- }; +- if symum.is_err() { +- log::error!("Lib {} not contain __um_obj_create sym um skip it", v); +- return Ok(()); +- } +- log::debug!("Insert unit {:?} dynamic lib into libs", unit_type); +- { +- let mut wloadlibs = self.load_libs.write().unwrap(); +- (*wloadlibs).insert(unit_type, lib.clone()); +- } +- log::info!("loading dynamic lib successful"); +- } +- Err(e) => error!("Unable to loading dynamic lib, err {:?}", e), +- } ++ type FnTypeSubUnit = fn(um: Rc) -> *mut dyn SubUnit; ++ type FnTypeUnitManagerObj = fn( ++ um: Rc, ++ level: LevelFilter, ++ target: &str, ++ file_path: &str, ++ file_size: u32, ++ file_number: u32, ++ ) -> *mut dyn UnitManagerObj; ++ ++ /* 1. check if the lib contains __subunit_create_with_params */ ++ #[allow(clippy::type_complexity)] ++ let symunit: Result> = unsafe { ++ lib.lib ++ .get(b"__subunit_create_with_params") ++ .map_err(|e| Error::PluginLoad { msg: e.to_string() }) ++ }; ++ ++ if symunit.is_err() { ++ log::error!( ++ "Lib {} doesn't contain __subunit_create_with_params, skipping", ++ v ++ ); ++ return Ok(()); + } ++ ++ /* 2. check if the lib contains __um_obj_create */ ++ #[allow(clippy::type_complexity)] ++ let symum: Result> = unsafe { ++ lib.lib ++ .get(b"__um_obj_create") ++ .map_err(|e| Error::PluginLoad { msg: e.to_string() }) ++ }; ++ if symum.is_err() { ++ log::error!("Lib {} doesn't contain __um_obj_create, skipping", v); ++ return Ok(()); ++ } ++ ++ /* 3. Insert */ ++ log::debug!("Inserting {:?} dynamic lib", unit_type); ++ let mut wloadlibs = self.load_libs.write().unwrap(); ++ (*wloadlibs).insert(unit_type, lib.clone()); ++ log::info!("Successfully loaded dynamic lib"); ++ + Ok(()) + } + +diff --git a/core/lib/unit/base.rs b/core/lib/unit/base.rs +index 8aea031..20f8c91 100644 +--- a/core/lib/unit/base.rs ++++ b/core/lib/unit/base.rs +@@ -168,24 +168,6 @@ pub trait SubUnit: ReStation + UnitMngUtil { + } + } + +-/// #[macro_use] +-/// the macro for create a sub unit instance +-#[macro_export] +-macro_rules! declure_unitobj_plugin_default { +- ($unit_type:ty, $constructor:path, $name:expr, $level:expr) => { +- /// method for create the unit instance +- #[no_mangle] +- pub fn __unit_obj_create_default() -> *mut dyn $crate::unit::SubUnit { +- logger::init_log_for_subum($name, $level, "console", ""); +- let construcotr: fn() -> $unit_type = $constructor; +- +- let obj = construcotr(); +- let boxed: Box = Box::new(obj); +- Box::into_raw(boxed) +- } +- }; +-} +- + /// #[macro_use] + /// the macro for create a sub unit instance with dyn ref of UmIf, + /// which sub unit wants invoke um interface, about UmIf see doc of UmIf +-- +2.33.0 + diff --git a/backport-fix-rename-config.service.toml-to-config.service.patch b/backport-fix-rename-config.service.toml-to-config.service.patch new file mode 100644 index 0000000..1af9ac1 --- /dev/null +++ b/backport-fix-rename-config.service.toml-to-config.service.patch @@ -0,0 +1,96 @@ +From f7d19b466e118cf2f6e322ab989fa3f91f5f8e2b Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Mon, 3 Jul 2023 15:42:44 +0800 +Subject: [PATCH] fix: rename config.service.toml to config.service + +Now we don't need the file's extension be .toml, rename it. also delete config.service.toml +from our git repo +--- + coms/service/src/config.rs | 2 +- + coms/service/src/mng.rs | 2 +- + core/bin/unit/entry/config.rs | 2 +- + libs/libtests/src/lib.rs | 2 +- + tests/test_units/config.service.toml | 19 ------------------- + 5 files changed, 4 insertions(+), 23 deletions(-) + delete mode 100644 tests/test_units/config.service.toml + +diff --git a/coms/service/src/config.rs b/coms/service/src/config.rs +index 3b7eb43..aa62b00 100644 +--- a/coms/service/src/config.rs ++++ b/coms/service/src/config.rs +@@ -190,7 +190,7 @@ mod tests { + #[test] + fn test_service_parse() { + let mut file_path = get_project_root().unwrap(); +- file_path.push("tests/test_units/config.service.toml"); ++ file_path.push("tests/test_units/config.service"); + + let paths = vec![file_path]; + +diff --git a/coms/service/src/mng.rs b/coms/service/src/mng.rs +index bfa2c9f..4bf20bd 100644 +--- a/coms/service/src/mng.rs ++++ b/coms/service/src/mng.rs +@@ -2542,7 +2542,7 @@ mod tests { + + fn create_mng() -> (Rc, Rc, Rc) { + let mut file_path = get_project_root().unwrap(); +- file_path.push("tests/test_units/config.service.toml"); ++ file_path.push("tests/test_units/config.service"); + let paths = vec![file_path]; + + let comm = Rc::new(ServiceUnitComm::new()); +diff --git a/core/bin/unit/entry/config.rs b/core/bin/unit/entry/config.rs +index 91313c4..ceead3c 100644 +--- a/core/bin/unit/entry/config.rs ++++ b/core/bin/unit/entry/config.rs +@@ -204,7 +204,7 @@ mod tests { + #[test] + fn test_unit_parse() { + let mut file_path = get_project_root().unwrap(); +- file_path.push("test_units/config.service.toml"); ++ file_path.push("test_units/config.service"); + + let mut builder = UeConfigData::builder().env(); + builder = builder.file(&file_path); +diff --git a/libs/libtests/src/lib.rs b/libs/libtests/src/lib.rs +index 260d7f8..c795fca 100644 +--- a/libs/libtests/src/lib.rs ++++ b/libs/libtests/src/lib.rs +@@ -47,7 +47,7 @@ mod tests { + #[test] + fn test_get_project_root() { + let mut file_path = get_project_root().unwrap(); +- file_path.push("tests/test_units/config.service.toml"); ++ file_path.push("tests/test_units/config.service"); + + println!("{file_path:?}"); + assert!(file_path.is_file()) +diff --git a/tests/test_units/config.service.toml b/tests/test_units/config.service.toml +deleted file mode 100644 +index 8c56508..0000000 +--- a/tests/test_units/config.service.toml ++++ /dev/null +@@ -1,19 +0,0 @@ +-[Unit] +-Description="CN" +-Documentation="192.168.1.1" +-Requires="test.service" +- +-[Service] +-Type="Simple" +-ExecCondition="/usr/bin/sleep 5" +-ExecStartPre="/usr/bin/echo test" +-ExecStart="/bin/echo 'test'" +-ExecStop="/bin/kill $MAINPID" +-WatchdogSec=10 +-Restart="always" +-RestartPreventExitStatus="1 2 SIGKILL" +-RestartSec=5 +- +- +-[Install] +-WantedBy="dbus.service" +-- +2.33.0 + diff --git a/backport-fix-rename-create_unit_obj_with_um-to-create_subunit.patch b/backport-fix-rename-create_unit_obj_with_um-to-create_subunit.patch new file mode 100644 index 0000000..bc68187 --- /dev/null +++ b/backport-fix-rename-create_unit_obj_with_um-to-create_subunit.patch @@ -0,0 +1,233 @@ +From d497414fec2b8e5b4a242f32b740113cd49b8398 Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Sun, 25 Jun 2023 15:05:14 +0800 +Subject: [PATCH] fix: rename create_unit_obj_with_um to + create_subunit_with_um, rename __unit_obj_create_with_params to + __subunit_create_with_params, and we don't need to init logger when creating + subunit, because we have already done that when we create UnitManagerObj + +--- + coms/service/src/unit.rs | 4 +-- + coms/target/src/unit.rs | 4 +-- + core/bin/plugin/mod.rs | 66 +++++++++++++++++++---------------- + core/bin/unit/entry/uentry.rs | 2 +- + core/bin/unit/test/mod.rs | 2 +- + core/bin/unit/uload.rs | 11 +++--- + core/lib/unit/base.rs | 9 ++--- + 9 files changed, 49 insertions(+), 58 deletions(-) + +diff --git a/coms/service/src/unit.rs b/coms/service/src/unit.rs +index a4f6a79..2a217d4 100644 +--- a/coms/service/src/unit.rs ++++ b/coms/service/src/unit.rs +@@ -12,13 +12,11 @@ + + use crate::rentry::ServiceRestart; + +-use super::base::PLUGIN_NAME; + use super::comm::ServiceUnitComm; + use super::config::ServiceConfig; + use super::mng::RunningData; + use super::mng::ServiceMng; + use super::rentry::{NotifyAccess, ServiceCommand, ServiceType}; +-use basic::logger; + use basic::special::{BASIC_TARGET, SHUTDOWN_TARGET, SYSINIT_TARGET}; + use nix::sys::signal::Signal; + use nix::sys::socket::UnixCredentials; +@@ -414,4 +412,4 @@ impl ServiceUnit { + }*/ + + use sysmaster::declure_unitobj_plugin_with_param; +-declure_unitobj_plugin_with_param!(ServiceUnit, ServiceUnit::new, PLUGIN_NAME); ++declure_unitobj_plugin_with_param!(ServiceUnit, ServiceUnit::new); +diff --git a/coms/target/src/unit.rs b/coms/target/src/unit.rs +index e4caf5d..bcd97c7 100644 +--- a/coms/target/src/unit.rs ++++ b/coms/target/src/unit.rs +@@ -15,10 +15,8 @@ + //! Trait UnitObj defines the behavior of the sub unit. + //! Trait UnitMngUtil is used to attach the Unitmanager to the sub unit. + //! Trait UnitSubClass implement the convert from sub unit to UnitObj. +-use super::base::PLUGIN_NAME; + use super::comm::TargetUnitComm; + use super::mng::TargetMng; +-use basic::logger; + use nix::sys::wait::WaitStatus; + use std::{path::PathBuf, rc::Rc}; + use sysmaster::error::*; +@@ -193,4 +191,4 @@ impl UnitMngUtil for Target { + }*/ + + use sysmaster::declure_unitobj_plugin_with_param; +-declure_unitobj_plugin_with_param!(Target, Target::new, PLUGIN_NAME); ++declure_unitobj_plugin_with_param!(Target, Target::new); +diff --git a/core/bin/plugin/mod.rs b/core/bin/plugin/mod.rs +index a8f6f24..0b67f74 100644 +--- a/core/bin/plugin/mod.rs ++++ b/core/bin/plugin/mod.rs +@@ -430,43 +430,47 @@ impl Plugin { + } + } + +- /// Create a obj for subclasses of unit ++ /// Create the subunit trait of unit + /// each sub unit need reference of declure_unitobj_plugin_with_param + /// +- pub fn create_unit_obj_with_um( ++ pub fn create_subunit_with_um( + &self, + unit_type: UnitType, + um: Rc, + ) -> Result> { +- type SymType = +- fn(um: Rc, level: LevelFilter, target: &str, file: &str) -> *mut dyn SubUnit; +- match self.get_lib(unit_type) { +- Ok(dy_lib) => { +- let sym: Result> = unsafe { +- dy_lib +- .lib +- .get(CONSTRUCTOR_NAME_WITH_PARAM) +- .map_err(|e| Error::PluginLoad { msg: e.to_string() }) +- }; +- log::debug!( +- "create unit obj with param level filter: {:?}", +- log::max_level() +- ); +- let target = um.get_log_target(); +- let file = um.get_log_file(); +- if let Ok(fun) = sym { +- let boxed_raw = fun(um.clone(), log::max_level(), target, file); +- Ok(unsafe { Box::from_raw(boxed_raw) }) +- } else { +- Err(Error::PluginLoad { +- msg: format!("The library of {:?} is {:?}", unit_type, sym.err()), +- }) +- } ++ type FnType = fn(um: Rc) -> *mut dyn SubUnit; ++ ++ let dy_lib = match self.get_lib(unit_type) { ++ Err(_) => { ++ return Err(Error::PluginLoad { ++ msg: format!("create unit, the {unit_type:?} plugin is not exist"), ++ }) + } +- Err(_) => Err(Error::PluginLoad { +- msg: format!("create unit, the {unit_type:?} plugin is not exist"), +- }), +- } ++ Ok(v) => v, ++ }; ++ ++ let sym: Result> = unsafe { ++ dy_lib ++ .lib ++ .get(b"__subunit_create_with_params") ++ .map_err(|e| Error::PluginLoad { msg: e.to_string() }) ++ }; ++ ++ let fun = match sym { ++ Err(_) => { ++ return Err(Error::PluginLoad { ++ msg: format!("The library of {:?} is {:?}", unit_type, sym.err()), ++ }) ++ } ++ Ok(v) => v, ++ }; ++ ++ log::debug!( ++ "create unit obj with param level filter: {:?}", ++ log::max_level() ++ ); ++ let boxed_raw = fun(um.clone()); ++ Ok(unsafe { Box::from_raw(boxed_raw) }) + } + /// Create a obj for subclasses of unit manager + /// each sub unit manager need reference of declure_umobj_plugin +@@ -583,7 +587,7 @@ mod tests { + fn test_plugin_create_unit() { + let plugin = init_test(); + let umifd = Rc::new(UmIfD); +- let unitobj = plugin.create_unit_obj_with_um(UnitType::UnitService, umifd); ++ let unitobj = plugin.create_subunit_with_um(UnitType::UnitService, umifd); + assert!( + unitobj.is_ok(), + "create unit [{:?}] failed", +diff --git a/core/bin/unit/entry/uentry.rs b/core/bin/unit/entry/uentry.rs +index 44a4af8..45f0e57 100644 +--- a/core/bin/unit/entry/uentry.rs ++++ b/core/bin/unit/entry/uentry.rs +@@ -791,7 +791,7 @@ mod tests { + let plugin = Plugin::get_instance(); + let umifd = Rc::new(UmIfD); + let sub_obj = plugin +- .create_unit_obj_with_um(UnitType::UnitService, umifd.clone()) ++ .create_subunit_with_um(UnitType::UnitService, umifd.clone()) + .unwrap(); + sub_obj.attach_um(umifd); + sub_obj.attach_reli(Rc::clone(&reli)); +diff --git a/core/bin/unit/test/mod.rs b/core/bin/unit/test/mod.rs +index 1fc1965..8f2d120 100644 +--- a/core/bin/unit/test/mod.rs ++++ b/core/bin/unit/test/mod.rs +@@ -39,7 +39,7 @@ pub(crate) mod test_utils { + let unit_type = unit_name_to_type(name); + let umifd = Rc::new(UmIfD); + let plugins = Plugin::get_instance(); +- let subclass = plugins.create_unit_obj_with_um(unit_type, umifd).unwrap(); ++ let subclass = plugins.create_subunit_with_um(unit_type, umifd).unwrap(); + subclass.attach_reli(Rc::clone(relir)); + Rc::new(UnitX::new(dmr, rentryr, &file, unit_type, name, subclass)) + } +diff --git a/core/bin/unit/uload.rs b/core/bin/unit/uload.rs +index d6fea43..382b2c0 100644 +--- a/core/bin/unit/uload.rs ++++ b/core/bin/unit/uload.rs +@@ -157,14 +157,13 @@ impl UnitLoadData { + return None; + } + +- log::info!( +- "begin create obj for type {:?}, name {} by plugin", +- unit_type, +- name +- ); + let um = self.um(); + let um_rc = Rc::clone(&um); +- let subclass = match Plugin::get_instance().create_unit_obj_with_um(unit_type, um_rc) { ++ log::info!( ++ "Creating SubUnit for {:?}: {name} by __subunit_create_with_params()", ++ unit_type ++ ); ++ let subclass = match Plugin::get_instance().create_subunit_with_um(unit_type, um_rc) { + Ok(sub) => sub, + Err(_e) => { + log::error!("Failed to create unit_obj!{}", _e); +diff --git a/core/lib/unit/base.rs b/core/lib/unit/base.rs +index 555bb69..8aea031 100644 +--- a/core/lib/unit/base.rs ++++ b/core/lib/unit/base.rs +@@ -191,19 +191,14 @@ macro_rules! declure_unitobj_plugin_default { + /// which sub unit wants invoke um interface, about UmIf see doc of UmIf + #[macro_export] + macro_rules! declure_unitobj_plugin_with_param { +- ($unit_type:ty, $constructor:path, $name:expr) => { ++ ($unit_type:ty, $constructor:path) => { + use log::LevelFilter; + /// method for create the unit instance + #[no_mangle] +- pub fn __unit_obj_create_with_params( ++ pub fn __subunit_create_with_params( + um: Rc, +- level: LevelFilter, +- target: &str, +- file: &str, + ) -> *mut dyn $crate::unit::SubUnit { +- logger::init_log_for_subum($name, level, target, file); + let construcotr: fn(um: Rc) -> $unit_type = $constructor; +- + let obj = construcotr(um); + let boxed: Box = Box::new(obj); + Box::into_raw(boxed) +-- +2.33.0 + diff --git a/backport-fix-rename-system.toml-to-system.conf.patch b/backport-fix-rename-system.toml-to-system.conf.patch new file mode 100644 index 0000000..dbd3e8d --- /dev/null +++ b/backport-fix-rename-system.toml-to-system.conf.patch @@ -0,0 +1,66 @@ +From ec6b1ff816ac6f1f18c441b3ace4069f744cc301 Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Mon, 3 Jul 2023 16:17:34 +0800 +Subject: [PATCH] fix: rename system.toml to system.conf + +--- + config/conf/{system.toml => system.conf} | 0 + core/bin/manager/config.rs | 22 ++++++++++++++++------ + 5 files changed, 20 insertions(+), 10 deletions(-) + rename config/conf/{system.toml => system.conf} (100%) + +diff --git a/config/conf/system.toml b/config/conf/system.conf +similarity index 100% +rename from config/conf/system.toml +rename to config/conf/system.conf +diff --git a/core/bin/manager/config.rs b/core/bin/manager/config.rs +index 229537f..94f676a 100644 +--- a/core/bin/manager/config.rs ++++ b/core/bin/manager/config.rs +@@ -12,9 +12,9 @@ + // + #![allow(non_snake_case)] + +-use confique::Config; ++use confique::{Config, FileFormat, Partial}; + +-pub const SYSTEM_CONFIG: &str = "/etc/sysmaster/system.toml"; ++pub const SYSTEM_CONFIG: &str = "/etc/sysmaster/system.conf"; + const RELI_HISTORY_MAPSIZE_DEFAULT: usize = 1048576; // 1M + + #[derive(Config, Debug)] +@@ -40,9 +40,19 @@ pub struct ManagerConfig { + impl ManagerConfig { + #[allow(dead_code)] + pub fn new(file: Option<&str>) -> ManagerConfig { +- let builder = ManagerConfig::builder().env(); +- let manager_config = builder.file(file.unwrap_or(SYSTEM_CONFIG)); +- match manager_config.load() { ++ type ConfigPartial = ::Partial; ++ let mut partial: ConfigPartial = match Partial::from_env() { ++ Err(_) => return ManagerConfig::default(), ++ Ok(v) => v, ++ }; ++ partial = match confique::File::with_format(file.unwrap_or(SYSTEM_CONFIG), FileFormat::Toml) ++ .load() ++ { ++ Err(_) => return ManagerConfig::default(), ++ Ok(v) => partial.with_fallback(v), ++ }; ++ partial = partial.with_fallback(ConfigPartial::default_values()); ++ match ManagerConfig::from_partial(partial) { + Ok(v) => v, + Err(_) => ManagerConfig::default(), + } +@@ -72,7 +82,7 @@ mod test { + #[test] + fn load() { + let mut file: PathBuf = get_crate_root().unwrap(); +- file.push("config/system.toml"); ++ file.push("config/system.conf"); + let config = ManagerConfig::new(file.to_str()); + println!("{config:?}"); + assert_eq!(config.DefaultRestartSec, 100); +-- +2.33.0 + diff --git a/backport-fix-set-the-notify-socket-receive-buffer-to-8M.patch b/backport-fix-set-the-notify-socket-receive-buffer-to-8M.patch new file mode 100644 index 0000000..e7598b6 --- /dev/null +++ b/backport-fix-set-the-notify-socket-receive-buffer-to-8M.patch @@ -0,0 +1,35 @@ +From d41a6113c8c109d3436a0de0329984ebec522da5 Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Tue, 11 Jul 2023 17:05:25 +0800 +Subject: [PATCH] fix: set the notify socket receive buffer to 8M + +--- + core/sysmaster/unit/notify.rs | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/core/sysmaster/unit/notify.rs b/core/sysmaster/unit/notify.rs +index 4f92b63..f35ed91 100644 +--- a/core/sysmaster/unit/notify.rs ++++ b/core/sysmaster/unit/notify.rs +@@ -14,7 +14,7 @@ use super::datastore::UnitDb; + use super::entry::UnitX; + use super::rentry::UnitRe; + use crate::job::JobManager; +-use basic::fd_util; ++use basic::{fd_util, socket_util}; + use event::{EventState, EventType, Events, Source}; + use nix::cmsg_space; + use nix::errno::Errno; +@@ -181,6 +181,9 @@ impl Notify { + return Err(e); + } + socket::setsockopt(fd, sockopt::PassCred, &true)?; ++ if let Err(e) = socket_util::set_receive_buffer(fd, 1024 * 1014 * 8) { ++ log::error!("Failed to set the notify socket receive buffer: {e}"); ++ } + + log::debug!("set event fd is: {}", fd); + self.reli.fd_cloexec(fd, false)?; +-- +2.33.0 + diff --git a/backport-fix-several-fixes-on-logger.patch b/backport-fix-several-fixes-on-logger.patch new file mode 100644 index 0000000..61cc6d4 --- /dev/null +++ b/backport-fix-several-fixes-on-logger.patch @@ -0,0 +1,511 @@ +From 0ce2ca0cfe650b88bccdd8e9b62a9b233e794f34 Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Wed, 28 Jun 2023 16:35:55 +0800 +Subject: [PATCH] fix: several fixes on logger + +1. Also use our own logger to log message to console, now log4rs can be removed +2. remove 'rolling_file', as it can only save log file in 644, we can't set the mode +3. change 'console' to 'console-syslog', when users want to print message to console + we will also record the message in syslog +4. check the returned value more +--- + core/bin/manager/config.rs | 4 +- + libs/basic/src/logger.rs | 311 +++++++++++++++++++++++++------------ + 3 files changed, 215 insertions(+), 109 deletions(-) + +diff --git a/core/bin/manager/config.rs b/core/bin/manager/config.rs +index fc4c028..691b692 100644 +--- a/core/bin/manager/config.rs ++++ b/core/bin/manager/config.rs +@@ -26,7 +26,7 @@ pub struct ManagerConfig { + + #[config(default = "info")] + pub LogLevel: log::LevelFilter, +- #[config(default = "console")] ++ #[config(default = "syslog")] + pub LogTarget: String, + #[config(default = "")] + pub LogFile: String, +@@ -57,7 +57,7 @@ impl Default for ManagerConfig { + DefaultRestartSec: 100, + DefaultTimeoutSec: 90, + LogLevel: log::LevelFilter::Debug, +- LogTarget: "console".to_string(), ++ LogTarget: "syslog".to_string(), + LogFile: String::new(), + LogFileSize: 10240, + LogFileNumber: 10, +diff --git a/libs/basic/src/logger.rs b/libs/basic/src/logger.rs +index 06f4ff2..8ee3ffa 100644 +--- a/libs/basic/src/logger.rs ++++ b/libs/basic/src/logger.rs +@@ -12,9 +12,9 @@ + + //! + use std::{ +- fs::{File, OpenOptions}, ++ fs::{self, File, OpenOptions}, + io::Write, +- os::unix::prelude::OpenOptionsExt, ++ os::unix::prelude::{OpenOptionsExt, PermissionsExt}, + path::{Path, PathBuf}, + sync::Mutex, + }; +@@ -37,6 +37,8 @@ use log4rs::{ + use nix::libc; + use time::UtcOffset; + ++use crate::Error; ++ + /// sysmaster log parttern: + /// + /// ```rust,ignore +@@ -65,6 +67,36 @@ impl log::Log for LogPlugin { + } + } + ++fn write_msg_common(writer: &mut impl Write, module: &str, msg: String) { ++ let now = time::OffsetDateTime::now_utc().to_offset(UtcOffset::UTC); ++ let format = time::macros::format_description!("[year]-[month]-[day] [hour]:[minute]:[second]"); ++ let now = match now.format(&format) { ++ Err(_) => "[unknown time]".to_string(), ++ Ok(v) => v, ++ }; ++ ++ /* 1. Write time */ ++ if let Err(e) = writer.write(format!("{now} ").as_bytes()) { ++ println!("Failed to log time message: {e}"); ++ return; ++ } ++ ++ /* 2. Write module */ ++ if let Err(e) = writer.write((module.to_string() + " ").as_bytes()) { ++ println!("Failed to log module message: {e}"); ++ return; ++ } ++ ++ /* 3. Write message */ ++ if let Err(e) = writer.write((msg + "\n").as_bytes()) { ++ println!("Failed to log message: {e}"); ++ } ++} ++ ++fn write_msg_file(writer: &mut File, module: &str, msg: String) { ++ write_msg_common(writer, module, msg); ++} ++ + struct SysLogger; + + /* This is an extremely simple implementation, and only +@@ -92,6 +124,25 @@ impl log::Log for SysLogger { + fn flush(&self) {} + } + ++struct ConsoleLogger; ++ ++impl log::Log for ConsoleLogger { ++ fn enabled(&self, _metadata: &log::Metadata) -> bool { ++ true ++ } ++ ++ fn log(&self, record: &log::Record) { ++ let mut stdout = std::io::stdout(); ++ let module_path = match record.module_path() { ++ None => "unknown", ++ Some(v) => v, ++ }; ++ write_msg_common(&mut stdout, module_path, record.args().to_string()); ++ } ++ ++ fn flush(&self) {} ++} ++ + struct FileLogger { + level: log::Level, + file_path: PathBuf, +@@ -113,30 +164,55 @@ impl log::Log for FileLogger { + } + let current_size: u32; + { +- let mut file = self.file.lock().unwrap(); +- self.write( +- &mut file, +- record.module_path().unwrap(), +- record.args().to_string(), +- ); +- current_size = file.metadata().unwrap().len() as u32; ++ let mut file = match self.file.lock() { ++ Err(_) => return, ++ Ok(v) => v, ++ }; ++ ++ let module_path = match record.module_path() { ++ None => "unknown", ++ Some(v) => v, ++ }; ++ write_msg_file(&mut file, module_path, record.args().to_string()); ++ current_size = match file.metadata() { ++ Err(_) => return, ++ Ok(v) => v.len() as u32, ++ }; + /* file is automatically unlocked. */ + } + if current_size > self.max_size { +- self.rotate(); +- let file = self.file.lock().unwrap(); +- let _ = file.set_len(0); ++ let file = match self.file.lock() { ++ Err(_) => return, ++ Ok(v) => v, ++ }; ++ if let Err(e) = self.rotate() { ++ println!("Failed to rotate log file: {e}"); ++ } ++ if let Err(e) = file.set_len(0) { ++ println!("Failed to clear log file: {e}"); ++ } + } + } + + fn flush(&self) { +- let mut file = self.file.lock().unwrap(); +- let _ = file.flush(); ++ let mut file = match self.file.lock() { ++ Err(_) => return, ++ Ok(v) => v, ++ }; ++ if let Err(e) = file.flush() { ++ println!("Failed to flush log file: {e}"); ++ } + } + } + + impl FileLogger { + fn file_open(file_path: &PathBuf, file_mode: u32) -> File { ++ /* Panic if we cann't open a log file. */ ++ let dir = file_path.parent().unwrap(); ++ if !dir.exists() { ++ fs::create_dir_all(dir).unwrap(); ++ } ++ fs::set_permissions(dir, fs::Permissions::from_mode(0o700)).unwrap(); + OpenOptions::new() + .write(true) + .create(true) +@@ -146,22 +222,6 @@ impl FileLogger { + .unwrap() + } + +- fn mv_file_in_dir(src: &str, dst: Option<&str>, dir: &Path) { +- let src = dir.join(src); +- if dst.is_none() { +- let _ = std::fs::remove_file(src); +- return; +- } +- let dst = dir.join(dst.unwrap()); +- let _ = std::fs::rename(src, dst); +- } +- +- fn cp_file_in_dir(src: &str, dst: &str, dir: &Path) { +- let src = dir.join(src); +- let dst = dir.join(dst); +- let _ = std::fs::copy(src, dst); +- } +- + fn new( + level: log::Level, + file_path: PathBuf, +@@ -180,49 +240,70 @@ impl FileLogger { + } + } + +- fn write(&self, file: &mut File, module: &str, msg: String) { +- let now = time::OffsetDateTime::now_utc().to_offset(UtcOffset::UTC); +- let format = +- time::macros::format_description!("[year]-[month]-[day] [hour]:[minute]:[second]"); +- let now = now.format(&format).unwrap(); +- +- /* 1. Write time */ +- if let Err(e) = file.write(format!("{now} ").as_bytes()) { +- println!("Failed to log time message: {e}"); ++ fn mv_file_in_dir(src: &str, dst: Option<&str>, dir: &Path) { ++ let src = dir.join(src); ++ if dst.is_none() { ++ if let Err(e) = fs::remove_file(src) { ++ println!("Failed to remove old log file: {e}"); ++ } + return; + } +- +- /* 2. Write module */ +- if let Err(e) = file.write((module.to_string() + " ").as_bytes()) { +- println!("Failed to log module message: {e}"); +- return; ++ let dst = dir.join(dst.unwrap()); /* safe here */ ++ if let Err(e) = fs::rename(src, dst) { ++ println!("Failed to rotate log file: {e}"); + } ++ } + +- /* 3. Write message */ +- if let Err(e) = file.write((msg + "\n").as_bytes()) { +- println!("Failed to log message: {e}"); ++ fn cp_file_in_dir(src: &str, dst: &str, dir: &Path) { ++ let src = dir.join(src); ++ let dst = dir.join(dst); ++ if let Err(e) = fs::copy(src, &dst) { ++ println!("Failed to create sysmaster.log.1: {e}"); ++ } ++ if let Err(e) = fs::set_permissions(dst, fs::Permissions::from_mode(0o400)) { ++ println!("Failed to set log file mode: {e}"); + } + } + +- fn rotate(&self) { +- let dir = self.file_path.parent().unwrap(); +- let file_name = self +- .file_path +- .file_name() +- .unwrap() +- .to_string_lossy() +- .to_string(); ++ fn rotate(&self) -> Result<(), Error> { ++ let dir = match self.file_path.parent() { ++ None => { ++ return Err(Error::Other { ++ msg: "Cannot determine the parent directory of log file".to_string(), ++ }) ++ } ++ Some(v) => v, ++ }; ++ let file_name = match self.file_path.file_name() { ++ None => { ++ return Err(Error::Other { ++ msg: "Cannot determine the file name of log file".to_string(), ++ }) ++ } ++ Some(v) => v.to_string_lossy().to_string(), ++ }; + let file_name_dot = String::from(&file_name) + "."; +- let mut num_list: Vec = Vec::new(); + +- for de in dir.read_dir().unwrap() { ++ /* Walk through the parent directory, save the suffix rotate number in num_list */ ++ let mut num_list: Vec = Vec::new(); ++ let read_dir = match dir.read_dir() { ++ Err(e) => return Err(Error::Io { source: e }), ++ Ok(v) => v, ++ }; ++ for de in read_dir { + let de = match de { + Err(_) => continue, + Ok(v) => v, + }; +- if !de.file_type().unwrap().is_file() { ++ ++ let file_type = match de.file_type() { ++ Err(_) => continue, ++ Ok(v) => v, ++ }; ++ if !file_type.is_file() { + continue; + } ++ + let de_file_name = de.file_name().to_string_lossy().to_string(); + let rotated_num = de_file_name.trim_start_matches(&file_name_dot); + let rotated_num = match rotated_num.parse::() { +@@ -238,17 +319,16 @@ impl FileLogger { + + /* 1. delete surplus rotated file */ + /* We only keep (file_number - 1) rotated files, because we will generate a new one later. */ +- let file_number = self.file_number as usize; +- for rotated_num in num_list.iter().skip(file_number - 1) { +- let src = String::from(&file_name_dot) + &rotated_num.to_string(); ++ while num_list.len() > (self.file_number - 1) as usize { ++ let num = num_list.pop().unwrap(); /* safe here */ ++ let src = String::from(&file_name_dot) + &num.to_string(); + Self::mv_file_in_dir(&src, None, dir); + } + +- let end = std::cmp::min(num_list.len(), file_number); + /* 2. {sysmaster.log.1, sysmaster.log.2, ...} => {sysmaster.log.2, sysmaster.log.3, ...} */ +- for i in (0..end).rev() { +- let src = String::from(&file_name_dot) + &num_list[i].to_string(); +- let dst = String::from(&file_name_dot) + &(num_list[i] + 1).to_string(); ++ while let Some(num) = num_list.pop() { ++ let src = String::from(&file_name_dot) + &num.to_string(); ++ let dst = String::from(&file_name_dot) + &(num + 1).to_string(); + Self::mv_file_in_dir(&src, Some(&dst), dir); + } + +@@ -256,37 +336,38 @@ impl FileLogger { + let src = String::from(&file_name); + let dst = String::from(&file_name_dot) + "1"; + Self::cp_file_in_dir(&src, &dst, dir); ++ Ok(()) + } + } + +-fn append_log( +- app_name: &str, +- level: LevelFilter, +- target: &str, +- file_path: &str, +- file_size: u32, +- file_number: u32, +-) { +- if target == "syslog" { +- let _ = log::set_boxed_logger(Box::new(SysLogger)); +- log::set_max_level(level); +- return; ++struct CombinedLogger { ++ loggers: Vec>, ++} ++ ++impl log::Log for CombinedLogger { ++ fn enabled(&self, _metadata: &log::Metadata) -> bool { ++ true + } +- if target == "file" { +- log::set_max_level(level); +- let _ = log::set_boxed_logger(Box::new(FileLogger::new( +- log::Level::Debug, +- PathBuf::from(file_path), +- 0o600, +- file_size, +- file_number, +- ))); +- return; ++ ++ fn log(&self, record: &log::Record) { ++ for logger in &self.loggers { ++ logger.log(record); ++ } ++ } ++ ++ fn flush(&self) {} ++} ++ ++impl CombinedLogger { ++ fn empty() -> Self { ++ Self { ++ loggers: Vec::new(), ++ } ++ } ++ ++ fn push(&mut self, logger: Box) { ++ self.loggers.push(logger) + } +- let config = build_log_config(app_name, level, target, file_path, file_size, file_number); +- let logger = log4rs::Logger::new(config); +- log::set_max_level(level); +- let _ = log::set_boxed_logger(Box::new(LogPlugin(logger))); + } + + /// Init and set the sub unit manager's log +@@ -297,7 +378,11 @@ fn append_log( + /// + /// target: log target + /// +-/// file_path: file path if the target is set to file ++/// file_path: file path (valid when target == "file") ++/// ++/// file_size: the maximum size of an active log file (valid when target == "file") ++/// ++/// file_number: the maximum number of rotated log files (valid when target == "file") + pub fn init_log_for_subum( + app_name: &str, + level: LevelFilter, +@@ -309,7 +394,7 @@ pub fn init_log_for_subum( + /* We should avoid calling init_log here, or we will get many "attempted + * to set a logger after the logging system was already initialized" error + * message. */ +- append_log(app_name, level, target, file_path, file_size, file_number); ++ init_log(app_name, level, target, file_path, file_size, file_number); + } + + /// Init and set the log target to console +@@ -318,7 +403,7 @@ pub fn init_log_for_subum( + /// + /// level: maximum log level + pub fn init_log_to_console(app_name: &str, level: LevelFilter) { +- init_log(app_name, level, "console", "", 0, 0); ++ init_log(app_name, level, "console-syslog", "", 0, 0); + } + + /// Init and set the log target to file +@@ -327,7 +412,11 @@ pub fn init_log_to_console(app_name: &str, level: LevelFilter) { + /// + /// level: maximum log level + /// +-/// file_path: log to which file ++/// file_path: file path ++/// ++/// file_size: the maximum size of an active log file ++/// ++/// file_number: the maximum number of rotated log files + pub fn init_log_to_file( + app_name: &str, + level: LevelFilter, +@@ -346,20 +435,42 @@ pub fn init_log_to_file( + /// + /// target: log target + /// +-/// file_path: file path if the target is set to file ++/// file_path: file path (valid when target == "file") ++/// ++/// file_size: the maximum size of an active log file (valid when target == "file") ++/// ++/// file_number: the maximum number of rotated log files (valid when target == "file") + pub fn init_log( +- app_name: &str, ++ _app_name: &str, + level: LevelFilter, + target: &str, + file_path: &str, + file_size: u32, + file_number: u32, + ) { ++ let mut target = target; ++ if target == "file" && (file_path.is_empty() || file_size == 0 || file_number == 0) { ++ println!( ++ "LogTarget is configured to `file`, but configuration is invalid, changing the \ ++ LogTarget to `console`, file: {file_path}, file_size: {file_size}, file_number: \ ++ {file_number}" ++ ); ++ target = "syslog"; ++ } ++ + if target == "syslog" { + let _ = log::set_boxed_logger(Box::new(SysLogger)); + log::set_max_level(level); + return; + } ++ if target == "console-syslog" { ++ let mut logger = CombinedLogger::empty(); ++ logger.push(Box::new(ConsoleLogger)); ++ logger.push(Box::new(SysLogger)); ++ let _ = log::set_boxed_logger(Box::new(logger)); ++ log::set_max_level(level); ++ return; ++ } + if target == "file" { + let _ = log::set_boxed_logger(Box::new(FileLogger::new( + log::Level::Debug, +@@ -371,13 +482,9 @@ pub fn init_log( + log::set_max_level(level); + return; + } +- let config = build_log_config(app_name, level, target, file_path, file_size, file_number); +- let r = log4rs::init_config(config); +- if let Err(e) = r { +- println!("{e}"); +- } + } + ++#[allow(unused)] + fn build_log_config( + app_name: &str, + level: LevelFilter, +-- +2.33.0 + diff --git a/backport-fix-several-socket-fixes.patch b/backport-fix-several-socket-fixes.patch new file mode 100644 index 0000000..850059a --- /dev/null +++ b/backport-fix-several-socket-fixes.patch @@ -0,0 +1,53 @@ +From 8400fe3ec5ee164a2225cc4445b0e661f7d194f9 Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Tue, 20 Jun 2023 12:03:12 +0800 +Subject: [PATCH] fix: several socket fixes + +1. bump the incomming connections from 10 to 4096 + +2. set SO_PASSCRED explictly +--- + core/bin/manager/commands.rs | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/core/bin/manager/commands.rs b/core/bin/manager/commands.rs +index 0727295..57f9d5d 100644 +--- a/core/bin/manager/commands.rs ++++ b/core/bin/manager/commands.rs +@@ -10,6 +10,7 @@ + // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + // See the Mulan PSL v2 for more details. + ++use basic::socket_util; + use cmdproto::proto::execute::ExecuterAction; + use cmdproto::proto::ProstServerStream; + use event::{EventType, Events, Source}; +@@ -32,6 +33,7 @@ pub(super) struct Commands { + + impl Commands { + pub(super) fn new(relir: &Rc, comm_action: T) -> Self { ++ /* The socket is used to communicate with sctl, panic if any of the following steps fail. */ + let sctl_socket_path = Path::new(SCTL_SOCKET); + /* remove the old socket if it exists */ + if sctl_socket_path.exists() && !sctl_socket_path.is_symlink() { +@@ -45,13 +47,15 @@ impl Commands { + None, + ) + .unwrap(); ++ /* set SO_PASSCRED, we need it to check whether sctl is running under root */ ++ socket_util::set_pass_cred(socket_fd, true).unwrap(); + /* create the socket with mode 666 */ + let old_mask = stat::umask(stat::Mode::from_bits_truncate(!0o666)); + let _ = socket::bind(socket_fd, &sctl_socket_addr); + /* restore our umask */ + let _ = stat::umask(old_mask); +- /* Allow at most 10 incoming connections can queue */ +- let _ = socket::listen(socket_fd, 10); ++ /* Allow at most 4096 incoming connections can queue */ ++ let _ = socket::listen(socket_fd, 4096); + Commands { + reli: Rc::clone(relir), + command_action: Rc::new(comm_action), +-- +2.33.0 + diff --git a/backport-fix-simply-code-a-bit-delete-an-annoying-log-and-don.patch b/backport-fix-simply-code-a-bit-delete-an-annoying-log-and-don.patch new file mode 100644 index 0000000..03c0ee4 --- /dev/null +++ b/backport-fix-simply-code-a-bit-delete-an-annoying-log-and-don.patch @@ -0,0 +1,131 @@ +From e3df7d05b8ab5346c08d5a4d654074225abd68e1 Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Mon, 10 Jul 2023 21:52:36 +0800 +Subject: [PATCH] fix: simply code a bit, delete an annoying log, and don't set + frame if we didn't do anything + +--- + core/sysmaster/unit/runtime.rs | 70 ++++++++++++++++++---------------- + core/sysmaster/unit/uload.rs | 2 - + 2 files changed, 38 insertions(+), 34 deletions(-) + +diff --git a/core/sysmaster/unit/runtime.rs b/core/sysmaster/unit/runtime.rs +index 5c4f45e..24833a5 100644 +--- a/core/sysmaster/unit/runtime.rs ++++ b/core/sysmaster/unit/runtime.rs +@@ -251,7 +251,12 @@ impl UnitRTData { + } + + pub(self) fn dispatch_load_queue(&self) { +- log::trace!("dispatch load queue"); ++ if self.load_queue.borrow().is_empty() { ++ self.dispatch_target_dep_queue(); ++ return; ++ } ++ ++ log::debug!("Dispatching load queue"); + + self.reli + .set_last_frame2(ReliLastFrame::Queue as u32, ReliLastQue::Load as u32); +@@ -260,34 +265,27 @@ impl UnitRTData { + //unitX pop from the load queue and then no need the ref of load queue + //the unitX load process will borrow load queue as mut again + // pop +- let first_unit = self.load_queue.borrow_mut().pop_front(); +- match first_unit { ++ let unit = match self.load_queue.borrow_mut().pop_front() { + None => break, +- Some(unit) => { +- // record + action +- self.reli.set_last_unit(unit.id()); +- match unit.load() { +- Ok(()) => { +- let load_state = unit.load_state(); +- if load_state == UnitLoadState::Loaded { +- self.push_target_dep_queue(Rc::clone(&unit)); +- } +- } +- Err(e) => { +- log::error!("load unit [{}] failed: {}", unit.id(), e.to_string()); +- } +- } +- self.reli.clear_last_unit(); +- } ++ Some(v) => v, ++ }; ++ ++ log::debug!("Loading unit: {}", unit.id()); ++ self.reli.set_last_unit(unit.id()); ++ if let Err(e) = unit.load() { ++ log::error!("Failed to load unit [{}]: {e}", unit.id()); + } ++ ++ let load_state = unit.load_state(); ++ if load_state == UnitLoadState::Loaded { ++ self.push_target_dep_queue(Rc::clone(&unit)); ++ } ++ ++ self.reli.clear_last_unit(); + } +- self.reli.clear_last_frame(); + +- log::trace!("dispatch target dep queue"); +- self.reli +- .set_last_frame2(ReliLastFrame::Queue as u32, ReliLastQue::TargetDeps as u32); +- self.dispatch_target_dep_queue(); + self.reli.clear_last_frame(); ++ self.dispatch_target_dep_queue(); + } + + pub(self) fn unit_add_dependency( +@@ -307,17 +305,25 @@ impl UnitRTData { + } + + fn dispatch_target_dep_queue(&self) { ++ if self.target_dep_queue.borrow().is_empty() { ++ return; ++ } ++ ++ log::debug!("Dispatching target dep queue"); ++ self.reli ++ .set_last_frame2(ReliLastFrame::Queue as u32, ReliLastQue::TargetDeps as u32); ++ + loop { +- let first_unit = self.target_dep_queue.borrow_mut().pop_front(); +- match first_unit { ++ let unit = match self.target_dep_queue.borrow_mut().pop_front() { + None => break, +- Some(unit) => { +- self.reli.set_last_unit(unit.id()); +- dispatch_target_dep_unit(&self.db, &unit); +- self.reli.clear_last_unit(); +- } +- } ++ Some(v) => v, ++ }; ++ self.reli.set_last_unit(unit.id()); ++ dispatch_target_dep_unit(&self.db, &unit); ++ self.reli.clear_last_unit(); + } ++ ++ self.reli.clear_last_frame(); + } + + fn push_target_dep_queue(&self, unit: Rc) { +diff --git a/core/sysmaster/unit/uload.rs b/core/sysmaster/unit/uload.rs +index 382b2c0..fa5f616 100644 +--- a/core/sysmaster/unit/uload.rs ++++ b/core/sysmaster/unit/uload.rs +@@ -140,9 +140,7 @@ impl UnitLoadData { + + pub(self) fn load_unit(&self, name: &str) -> Option> { + self.prepare_unit(name).map(|u| { +- log::debug!("Try to load {name} by dispatching the load queue."); + self.rt.dispatch_load_queue(); +- log::debug!("The loading state of {name}: {:?}", u.load_state()); + u + }) + } +-- +2.33.0 + diff --git a/backport-fix-specify-the-version-of-tempfile.patch b/backport-fix-specify-the-version-of-tempfile.patch new file mode 100644 index 0000000..5325c29 --- /dev/null +++ b/backport-fix-specify-the-version-of-tempfile.patch @@ -0,0 +1,28 @@ +From aaf7cf2eca91dc9490c60a298c83915f99d3436f Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Fri, 21 Jul 2023 17:40:57 +0800 +Subject: [PATCH] fix: specify the version of tempfile + +prost-build depends on tempfile but doesn't specify its version, if tempfile upgrades +to higher version i.e. 3.7.0, it may requires we use rustc 1.63 or newer. Now we can't +upgrate rustc to a newer version, we choose to avoid this problem by pinning the +version of tempfile to 3.6.0. +--- + Cargo.toml | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/Cargo.toml b/Cargo.toml +index e86003d..17cbd79 100644 +--- a/Cargo.toml ++++ b/Cargo.toml +@@ -44,6 +44,7 @@ nix = "0.24" + regex = { version = "1.6.0", default-features = false, features = ["std"] } + serde = "1.0.130" + siphasher = { version = "0.3", features = ["serde"] } ++tempfile = "=3.6.0" + walkdir = "2" + fnmatch-regex = "0.2.0" + snafu = "0.7" +-- +2.33.0 + diff --git a/backport-fix-use-UnixStream-to-test-send_and_recv.patch b/backport-fix-use-UnixStream-to-test-send_and_recv.patch new file mode 100644 index 0000000..a257c5d --- /dev/null +++ b/backport-fix-use-UnixStream-to-test-send_and_recv.patch @@ -0,0 +1,129 @@ +From e4646077cac8c196f676e2711d99ef46a40bda25 Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Fri, 30 Jun 2023 16:07:29 +0800 +Subject: [PATCH] fix: use UnixStream to test send_and_recv + +--- + libs/cmdproto/src/proto/frame.rs | 82 +++++++++++++++++++------------- + 1 file changed, 49 insertions(+), 33 deletions(-) + +diff --git a/libs/cmdproto/src/proto/frame.rs b/libs/cmdproto/src/proto/frame.rs +index 6b6912b..9c48cf0 100644 +--- a/libs/cmdproto/src/proto/frame.rs ++++ b/libs/cmdproto/src/proto/frame.rs +@@ -172,25 +172,25 @@ where + msg.encode_frame(&mut buf)?; + let encoded = buf.freeze(); + let msg_len = msg_len_vec(encoded.len()); +- match socket::send(self.accept_fd, &msg_len, socket::MsgFlags::empty()) { +- Ok(len) => { +- if len != msg_len.len() { +- return Err(Error::SendStream { +- msg: "Invalid message length".to_string(), +- }); +- } +- } ++ ++ let len = match socket::send(self.accept_fd, &msg_len, socket::MsgFlags::empty()) { + Err(e) => return Err(Error::SendStream { msg: e.to_string() }), ++ Ok(v) => v, ++ }; ++ if len != msg_len.len() { ++ return Err(Error::SendStream { ++ msg: "Invalid message length".to_string(), ++ }); + } +- match socket::send(self.accept_fd, &encoded, socket::MsgFlags::empty()) { +- Ok(len) => { +- if len != encoded.len() { +- return Err(Error::SendStream { +- msg: "Invalid message length".to_string(), +- }); +- } +- } ++ ++ let len = match socket::send(self.accept_fd, &encoded, socket::MsgFlags::empty()) { + Err(e) => return Err(Error::SendStream { msg: e.to_string() }), ++ Ok(v) => v, ++ }; ++ if len != encoded.len() { ++ return Err(Error::SendStream { ++ msg: "Invalid message length".to_string(), ++ }); + } + Ok(()) + } +@@ -240,37 +240,53 @@ where + mod tests { + use super::super::abi::unit_comm::Action as UnitAction; + use super::*; +- use std::net::{SocketAddr, TcpStream}; ++ use core::time; ++ use std::os::unix::net::UnixStream; ++ use std::path::Path; + use std::thread; + use std::time::Duration; + + #[test] + fn test_send_and_recv() { ++ let socket_name = "./test-sctl.sock"; ++ let socket_path = Path::new(socket_name); ++ if socket_path.exists() { ++ std::fs::remove_file(&socket_path).unwrap(); ++ } + thread::spawn(move || { + thread::sleep(Duration::from_secs(1)); +- let addrs = [ +- SocketAddr::from(([127, 0, 0, 1], 9528)), +- SocketAddr::from(([127, 0, 0, 1], 9529)), +- ]; +- let stream = TcpStream::connect(&addrs[..]).unwrap(); ++ let stream = match UnixStream::connect(socket_name) { ++ Err(e) => { ++ println!("Failed to connect to sysmaster: {e}"); ++ return; ++ } ++ Ok(v) => v, ++ }; + let mut client = ProstClientStream::new(stream); + let cmd = + CommandRequest::new_unitcomm(UnitAction::Start, vec!["test.service".to_string()]); + let _ = client.execute(cmd).unwrap(); + }); + +- let addrs = [ +- SocketAddr::from(([127, 0, 0, 1], 9528)), +- SocketAddr::from(([127, 0, 0, 1], 9529)), +- ]; +- let fd = std::net::TcpListener::bind(&addrs[..]).unwrap(); +- loop { +- for stream in fd.incoming() { +- match stream { +- Err(e) => panic!("failed: {e}"), +- Ok(_stream) => return, +- } ++ let sctl_socket_addr = socket::UnixAddr::new(Path::new(socket_path)).unwrap(); ++ let socket_fd = socket::socket( ++ socket::AddressFamily::Unix, ++ socket::SockType::Stream, ++ socket::SockFlag::SOCK_CLOEXEC | socket::SockFlag::SOCK_NONBLOCK, ++ None, ++ ) ++ .unwrap(); ++ ++ let _ = socket::bind(socket_fd, &sctl_socket_addr); ++ let _ = socket::listen(socket_fd, 10); ++ ++ for _ in 0..5 { ++ match socket::accept(socket_fd) { ++ Err(nix::Error::EAGAIN) => thread::sleep(time::Duration::from_millis(500)), ++ Ok(_) => break, ++ Err(_) => panic!("Unexpected error when accepting connection."), + } + } ++ std::fs::remove_file(&socket_path).unwrap(); + } + } +-- +2.33.0 + diff --git a/backport-fix-use-localtime-instead-of-UTC.patch b/backport-fix-use-localtime-instead-of-UTC.patch new file mode 100644 index 0000000..61ecd3a --- /dev/null +++ b/backport-fix-use-localtime-instead-of-UTC.patch @@ -0,0 +1,52 @@ +From 67f99391d25fd1108e15887b33df2e7bf19b90ef Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Thu, 29 Jun 2023 10:33:27 +0800 +Subject: [PATCH] fix: use localtime instead of UTC + +--- + libs/basic/Cargo.toml | 2 +- + libs/basic/src/logger.rs | 8 ++++++-- + 2 files changed, 7 insertions(+), 3 deletions(-) + +diff --git a/libs/basic/Cargo.toml b/libs/basic/Cargo.toml +index b7d343c..42ac3ab 100644 +--- a/libs/basic/Cargo.toml ++++ b/libs/basic/Cargo.toml +@@ -21,7 +21,7 @@ lazy_static = "1.4.0" + bitflags = "1.3.2" + pkg-config = "0.3" + rand = "0.4.6" +-time = {version = "=0.3.10", features = ["formatting", "macros"] } ++time = {version = "=0.3.10", features = ["formatting", "macros", "local-offset"] } + constants = { path = "../constants"} + + [dev-dependencies] +diff --git a/libs/basic/src/logger.rs b/libs/basic/src/logger.rs +index 83fce0e..ae12c36 100644 +--- a/libs/basic/src/logger.rs ++++ b/libs/basic/src/logger.rs +@@ -36,7 +36,7 @@ use log4rs::{ + encode::pattern::PatternEncoder, + }; + use nix::libc; +-use time::UtcOffset; ++use time::macros::offset; + + use crate::Error; + +@@ -69,7 +69,11 @@ impl log::Log for LogPlugin { + } + + fn write_msg_common(writer: &mut impl Write, module: &str, msg: String) { +- let now = time::OffsetDateTime::now_utc().to_offset(UtcOffset::UTC); ++ let now = match time::OffsetDateTime::now_local() { ++ Ok(v) => v, ++ Err(_) => time::OffsetDateTime::now_utc().to_offset(offset!(+8)), ++ }; ++ + let format = time::macros::format_description!("[year]-[month]-[day] [hour]:[minute]:[second]"); + let now = match now.format(&format) { + Err(_) => "[unknown time]".to_string(), +-- +2.33.0 + diff --git a/backport-fix-use-var-log-sysmaster-sysmaster.log-to-save-log-.patch b/backport-fix-use-var-log-sysmaster-sysmaster.log-to-save-log-.patch new file mode 100644 index 0000000..605f1be --- /dev/null +++ b/backport-fix-use-var-log-sysmaster-sysmaster.log-to-save-log-.patch @@ -0,0 +1,259 @@ +From 2dfef21c0b7d4fef04ab0e65b3f8cc52944d7b44 Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Thu, 29 Jun 2023 10:08:56 +0800 +Subject: [PATCH] fix: use /var/log/sysmaster/sysmaster.log to save log, don't + allow users change + +--- + core/bin/main.rs | 1 - + core/bin/manager/config.rs | 3 --- + core/bin/plugin/mod.rs | 5 +---- + core/bin/unit/manager.rs | 5 ----- + core/lib/unit/umif.rs | 3 +-- + libs/basic/Cargo.toml | 1 + + libs/basic/src/logger.rs | 30 ++++++++---------------------- + libs/constants/src/lib.rs | 3 +++ + units/system.toml | 1 - + 11 files changed, 20 insertions(+), 49 deletions(-) + +diff --git a/core/bin/main.rs b/core/bin/main.rs +index b75ef0b..c2010e2 100644 +--- a/core/bin/main.rs ++++ b/core/bin/main.rs +@@ -86,7 +86,6 @@ fn main() -> Result<()> { + "sysmaster", + manager_config.LogLevel, + &manager_config.LogTarget, +- &manager_config.LogFile, + manager_config.LogFileSize, + manager_config.LogFileNumber, + ); +diff --git a/core/bin/manager/config.rs b/core/bin/manager/config.rs +index 691b692..229537f 100644 +--- a/core/bin/manager/config.rs ++++ b/core/bin/manager/config.rs +@@ -28,8 +28,6 @@ pub struct ManagerConfig { + pub LogLevel: log::LevelFilter, + #[config(default = "syslog")] + pub LogTarget: String, +- #[config(default = "")] +- pub LogFile: String, + #[config(default = 10240)] + pub LogFileSize: u32, + #[config(default = 10)] +@@ -58,7 +56,6 @@ impl Default for ManagerConfig { + DefaultTimeoutSec: 90, + LogLevel: log::LevelFilter::Debug, + LogTarget: "syslog".to_string(), +- LogFile: String::new(), + LogFileSize: 10240, + LogFileNumber: 10, + DbSize: RELI_HISTORY_MAPSIZE_DEFAULT, +diff --git a/core/bin/plugin/mod.rs b/core/bin/plugin/mod.rs +index 9a8e4f6..e6f5183 100644 +--- a/core/bin/plugin/mod.rs ++++ b/core/bin/plugin/mod.rs +@@ -317,7 +317,6 @@ impl Plugin { + um: Rc, + level: LevelFilter, + target: &str, +- file_path: &str, + file_size: u32, + file_number: u32, + ) -> *mut dyn UnitManagerObj; +@@ -479,7 +478,6 @@ impl Plugin { + &self, + unit_type: UnitType, + target: &str, +- file: &str, + file_size: u32, + file_number: u32, + ) -> Result> { +@@ -495,7 +493,6 @@ impl Plugin { + type FnType = fn( + level: LevelFilter, + target: &str, +- file: &str, + file_size: u32, + file_number: u32, + ) -> *mut dyn UnitManagerObj; +@@ -516,7 +513,7 @@ impl Plugin { + Ok(v) => v, + }; + +- let boxed_raw = fun(log::max_level(), target, file, file_size, file_number); ++ let boxed_raw = fun(log::max_level(), target, file_size, file_number); + Ok(unsafe { Box::from_raw(boxed_raw) }) + } + +diff --git a/core/bin/unit/manager.rs b/core/bin/unit/manager.rs +index 2e6caba..1e8d08f 100644 +--- a/core/bin/unit/manager.rs ++++ b/core/bin/unit/manager.rs +@@ -1030,10 +1030,6 @@ impl UnitManager { + + fn remove_job_result(&self, _source: &str) {} + +- fn get_log_file(&self) -> &str { +- &self.manager_config.LogFile +- } +- + fn get_log_target(&self) -> &str { + &self.manager_config.LogTarget + } +@@ -1314,7 +1310,6 @@ mod unit_submanager { + let sub = match Plugin::get_instance().create_um_obj( + unit_type, + um.get_log_target(), +- um.get_log_file(), + um.get_log_file_size(), + um.get_log_file_number(), + ) { +diff --git a/core/lib/unit/umif.rs b/core/lib/unit/umif.rs +index 85603fa..f0019d0 100644 +--- a/core/lib/unit/umif.rs ++++ b/core/lib/unit/umif.rs +@@ -230,11 +230,10 @@ macro_rules! declare_umobj_plugin { + pub fn __um_obj_create( + level: LevelFilter, + target: &str, +- file_path: &str, + file_size: u32, + file_number: u32, + ) -> *mut dyn $crate::unit::UnitManagerObj { +- logger::init_log_for_subum($name, level, target, file_path, file_size, file_number); ++ logger::init_log_for_subum($name, level, target, file_size, file_number); + let construcotr: fn() -> $unit_type = $constructor; + let obj = construcotr(); + let boxed: Box = Box::new(obj); +diff --git a/libs/basic/Cargo.toml b/libs/basic/Cargo.toml +index 6ee7162..b7d343c 100644 +--- a/libs/basic/Cargo.toml ++++ b/libs/basic/Cargo.toml +@@ -22,6 +22,7 @@ bitflags = "1.3.2" + pkg-config = "0.3" + rand = "0.4.6" + time = {version = "=0.3.10", features = ["formatting", "macros"] } ++constants = { path = "../constants"} + + [dev-dependencies] + libtests = { path = "../libtests" } +diff --git a/libs/basic/src/logger.rs b/libs/basic/src/logger.rs +index 3161513..83fce0e 100644 +--- a/libs/basic/src/logger.rs ++++ b/libs/basic/src/logger.rs +@@ -19,6 +19,7 @@ use std::{ + sync::Mutex, + }; + ++use constants::LOG_FILE_PATH; + use log::{LevelFilter, Log}; + use log4rs::{ + append::{ +@@ -378,8 +379,6 @@ impl CombinedLogger { + /// + /// target: log target + /// +-/// file_path: file path (valid when target == "file") +-/// + /// file_size: the maximum size of an active log file (valid when target == "file") + /// + /// file_number: the maximum number of rotated log files (valid when target == "file") +@@ -387,14 +386,13 @@ pub fn init_log_for_subum( + app_name: &str, + level: LevelFilter, + target: &str, +- file_path: &str, + file_size: u32, + file_number: u32, + ) { + /* We should avoid calling init_log here, or we will get many "attempted + * to set a logger after the logging system was already initialized" error + * message. */ +- init_log(app_name, level, target, file_path, file_size, file_number); ++ init_log(app_name, level, target, file_size, file_number); + } + + /// Init and set the log target to console +@@ -403,7 +401,7 @@ pub fn init_log_for_subum( + /// + /// level: maximum log level + pub fn init_log_to_console(app_name: &str, level: LevelFilter) { +- init_log(app_name, level, "console-syslog", "", 0, 0); ++ init_log(app_name, level, "console-syslog", 0, 0); + } + + /// Init and set the log target to file +@@ -412,19 +410,11 @@ pub fn init_log_to_console(app_name: &str, level: LevelFilter) { + /// + /// level: maximum log level + /// +-/// file_path: file path +-/// + /// file_size: the maximum size of an active log file + /// + /// file_number: the maximum number of rotated log files +-pub fn init_log_to_file( +- app_name: &str, +- level: LevelFilter, +- file_path: &str, +- file_size: u32, +- file_number: u32, +-) { +- init_log(app_name, level, "file", file_path, file_size, file_number); ++pub fn init_log_to_file(app_name: &str, level: LevelFilter, file_size: u32, file_number: u32) { ++ init_log(app_name, level, "file", file_size, file_number); + } + + /// Init and set the logger +@@ -435,8 +425,6 @@ pub fn init_log_to_file( + /// + /// target: log target + /// +-/// file_path: file path (valid when target == "file") +-/// + /// file_size: the maximum size of an active log file (valid when target == "file") + /// + /// file_number: the maximum number of rotated log files (valid when target == "file") +@@ -444,16 +432,14 @@ pub fn init_log( + _app_name: &str, + level: LevelFilter, + target: &str, +- file_path: &str, + file_size: u32, + file_number: u32, + ) { + let mut target = target; +- if target == "file" && (file_path.is_empty() || file_size == 0 || file_number == 0) { ++ if target == "file" && (file_size == 0 || file_number == 0) { + println!( + "LogTarget is configured to `file`, but configuration is invalid, changing the \ +- LogTarget to `console`, file: {file_path}, file_size: {file_size}, file_number: \ +- {file_number}" ++ LogTarget to `syslog`, file_size: {file_size}, file_number: {file_number}" + ); + target = "syslog"; + } +@@ -474,7 +460,7 @@ pub fn init_log( + if target == "file" { + let _ = log::set_boxed_logger(Box::new(FileLogger::new( + log::Level::Debug, +- PathBuf::from(&file_path), ++ PathBuf::from(LOG_FILE_PATH), + 0o600, + file_size, + file_number, +diff --git a/libs/constants/src/lib.rs b/libs/constants/src/lib.rs +index b1db27c..6005067 100644 +--- a/libs/constants/src/lib.rs ++++ b/libs/constants/src/lib.rs +@@ -26,3 +26,6 @@ pub const ALIVE: &str = "ALIVE01234567890"; + + /// Socket used to transfer message between sysmaster and sctl + pub const SCTL_SOCKET: &str = "/run/sysmaster/sctl"; ++ ++/// Default log file path when LogTarget is configured to "file" ++pub const LOG_FILE_PATH: &str = "/var/log/sysmaster/sysmaster.log"; +-- +2.33.0 + diff --git a/backport-fix-version-0.3.10-may-fail-to-build-when-use-tuna-s.patch b/backport-fix-version-0.3.10-may-fail-to-build-when-use-tuna-s.patch new file mode 100644 index 0000000..45eac3d --- /dev/null +++ b/backport-fix-version-0.3.10-may-fail-to-build-when-use-tuna-s.patch @@ -0,0 +1,26 @@ +From f4c2faab82bf903c800417c8b04a9d9763bc7c61 Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Fri, 30 Jun 2023 10:54:12 +0800 +Subject: [PATCH] fix: version 0.3.10 may fail to build when use tuna source, + use 0.3.5 + +--- + libs/basic/Cargo.toml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libs/basic/Cargo.toml b/libs/basic/Cargo.toml +index 42ac3ab..c18991a 100644 +--- a/libs/basic/Cargo.toml ++++ b/libs/basic/Cargo.toml +@@ -21,7 +21,7 @@ lazy_static = "1.4.0" + bitflags = "1.3.2" + pkg-config = "0.3" + rand = "0.4.6" +-time = {version = "=0.3.10", features = ["formatting", "macros", "local-offset"] } ++time = {version = "=0.3.5", features = ["formatting", "macros", "local-offset"] } + constants = { path = "../constants"} + + [dev-dependencies] +-- +2.33.0 + diff --git a/backport-fix-we-shouldn-t-lookup-build-directory-if-we-are-no.patch b/backport-fix-we-shouldn-t-lookup-build-directory-if-we-are-no.patch new file mode 100644 index 0000000..890572e --- /dev/null +++ b/backport-fix-we-shouldn-t-lookup-build-directory-if-we-are-no.patch @@ -0,0 +1,96 @@ +From ca038d416eb1d6b7ae4cd4a709a62fc055e25c12 Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Fri, 30 Jun 2023 10:55:39 +0800 +Subject: [PATCH] fix: we shouldn't lookup build directory if we are not in CI + environment + +--- + libs/basic/src/path_lookup.rs | 51 +++++++++-------------------------- + 1 file changed, 12 insertions(+), 39 deletions(-) + +diff --git a/libs/basic/src/path_lookup.rs b/libs/basic/src/path_lookup.rs +index c711305..4c9797d 100644 +--- a/libs/basic/src/path_lookup.rs ++++ b/libs/basic/src/path_lookup.rs +@@ -11,7 +11,6 @@ + // See the Mulan PSL v2 for more details. + + //! the management of the unit file lookup path +-use std::env; + + /// unit lookup path in /etc + pub const ETC_SYSTEM_PATH: &str = "/etc/sysmaster"; +@@ -55,28 +54,6 @@ impl LookupPaths { + + /// init lookup paths + pub fn init_lookup_paths(&mut self) { +- let devel_path = || { +- let out_dir = env::var("OUT_DIR").unwrap_or_else(|_x| { +- let _tmp_str: Option<&'static str> = option_env!("OUT_DIR"); +- _tmp_str.unwrap_or("").to_string() +- }); +- if out_dir.is_empty() { +- env::var("LD_LIBRARY_PATH").map_or("".to_string(), |_v| { +- let _tmp = _v.split(':').collect::>()[0]; +- let _tmp_path = _tmp.split("target").collect::>()[0]; +- _tmp_path.to_string() +- }) +- } else { +- out_dir +- } +- }; +- +- let out_dir = devel_path(); +- if !out_dir.is_empty() && out_dir.contains("build") { +- let tmp_str: Vec<_> = out_dir.split("build").collect(); +- self.search_path.push(tmp_str[0].to_string()); +- self.preset_path.push(tmp_str[0].to_string()); +- } + self.search_path.push(LIB_SYSTEM_PATH.to_string()); + self.search_path.push(RUN_SYSTEM_PATH.to_string()); + self.search_path.push(ETC_SYSTEM_PATH.to_string()); +@@ -98,29 +75,25 @@ impl Default for LookupPaths { + + #[cfg(test)] + mod tests { +- +- use std::env; +- + use crate::logger; + + use super::LookupPaths; + #[test] + fn test_init_lookup_paths() { + logger::init_log_to_console("test_init_lookup_paths", log::LevelFilter::Trace); +- let mut _lp = LookupPaths::default(); +- _lp.init_lookup_paths(); +- for item in _lp.search_path.iter() { +- log::info!("lookup path is{:?}", item); +- } +- let tmp_dir = env::var("OUT_DIR"); +- if tmp_dir.is_err() { +- return; +- } +- let tmp = tmp_dir.unwrap(); +- let tmp_dir_v: Vec<_> = tmp.split("build").collect(); ++ let mut lp = LookupPaths::default(); ++ lp.init_lookup_paths(); ++ assert_eq!( ++ lp.search_path, ++ vec!["/usr/lib/sysmaster", "/run/sysmaster", "/etc/sysmaster"] ++ ); + assert_eq!( +- _lp.search_path.first().unwrap().to_string(), +- tmp_dir_v[0].to_string() ++ lp.preset_path, ++ vec![ ++ "/etc/sysmaster/system-preset", ++ "/usr/lib/sysmaster/system-preset" ++ ] + ); ++ assert_eq!(lp.persistent_path, "/etc/sysmaster") + } + } +-- +2.33.0 + diff --git a/backport-refactor-don-t-copy-unit-file-to-.toml-file-when-loa.patch b/backport-refactor-don-t-copy-unit-file-to-.toml-file-when-loa.patch new file mode 100644 index 0000000..24c7f68 --- /dev/null +++ b/backport-refactor-don-t-copy-unit-file-to-.toml-file-when-loa.patch @@ -0,0 +1,231 @@ +From fd14e9295a04cb051a70779fd6039d2d25ce9b85 Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Mon, 3 Jul 2023 15:39:47 +0800 +Subject: [PATCH] refactor: don't copy unit file to .toml file when loading a + unit + +We used to do this because we thought confique could only infer +the file format from the file extension, so we copied the file +to .toml to tell confique this is a toml file. But actually, +confique allows us to specify the file format if we use Partial. + +Let's use confique::Partial to avoid copying files. +--- + coms/service/src/config.rs | 24 ++++++++++++-------- + core/bin/manager/pre_install.rs | 40 +++++++++++++++++---------------- + core/bin/unit/entry/config.rs | 25 +++++++++++++-------- + core/bin/unit/util/unit_file.rs | 17 +++----------- + 5 files changed, 69 insertions(+), 57 deletions(-) + +diff --git a/coms/service/src/config.rs b/coms/service/src/config.rs +index e698ac2..3b7eb43 100644 +--- a/coms/service/src/config.rs ++++ b/coms/service/src/config.rs +@@ -13,7 +13,7 @@ + #![allow(non_snake_case)] + use super::comm::ServiceUnitComm; + use super::rentry::{NotifyAccess, SectionService, ServiceCommand, ServiceType}; +-use confique::Config; ++use confique::{Config, FileFormat, Partial}; + use std::cell::RefCell; + use std::collections::{HashMap, VecDeque}; + use std::path::PathBuf; +@@ -64,15 +64,21 @@ impl ServiceConfig { + } + + pub(super) fn load(&self, paths: Vec, update: bool) -> Result<()> { +- let mut builder = ServiceConfigData::builder().env(); +- +- log::debug!("service load path: {:?}", paths); +- // fragment +- for v in paths { +- builder = builder.file(v); ++ type ConfigPartial = ::Partial; ++ let mut partial: ConfigPartial = Partial::from_env().context(ConfiqueSnafu)?; ++ /* The first config wins, so add default values at last. */ ++ log::debug!("Loading service config from: {:?}", paths); ++ for path in paths { ++ partial = match confique::File::with_format(&path, FileFormat::Toml).load() { ++ Err(e) => { ++ log::error!("Failed to load {path:?}: {e}, skipping"); ++ continue; ++ } ++ Ok(v) => partial.with_fallback(v), ++ } + } +- +- *self.data.borrow_mut() = match builder.load() { ++ partial = partial.with_fallback(ConfigPartial::default_values()); ++ *self.data.borrow_mut() = match ServiceConfigData::from_partial(partial) { + Err(e) => { + /* The error message is pretty readable, just print it out. */ + log::error!("{e}"); +diff --git a/core/bin/manager/pre_install.rs b/core/bin/manager/pre_install.rs +index 88150c0..08c795a 100644 +--- a/core/bin/manager/pre_install.rs ++++ b/core/bin/manager/pre_install.rs +@@ -15,7 +15,7 @@ use crate::unit::{unit_name_to_type, UeConfigInstall, UnitType}; + use basic::fs_util; + use basic::path_lookup::LookupPaths; + use bitflags::bitflags; +-use confique::Config; ++use confique::{Config, FileFormat, Partial}; + use nix::unistd::UnlinkatFlags; + use std::{ + cell::RefCell, +@@ -553,14 +553,14 @@ impl Install { + } + + let canon_path = path.canonicalize()?; +- let tmp = format!("{}.toml", canon_path.as_path().display()); +- if let Err(e) = std::fs::copy(canon_path, &tmp).context(IoSnafu) { +- log::warn!("copy file content to toml file error: {}", e); +- return Err(e); +- } +- +- let mut builder = UeConfigData::builder().env(); +- builder = builder.file(&tmp); ++ type ConfigPartial = ::Partial; ++ let mut partial: ConfigPartial = Partial::from_env().context(ConfiqueSnafu)?; ++ /* The first config wins, so add default values at last. */ ++ partial = partial.with_fallback( ++ confique::File::with_format(canon_path, FileFormat::Toml) ++ .load() ++ .context(ConfiqueSnafu)?, ++ ); + + let dropin_dir_name = format!("{}.d", unit_install.name()); + +@@ -570,7 +570,7 @@ impl Install { + let dropin_dir = base_dir.join(&dropin_dir_name); + + if !dropin_dir.exists() { +- log::debug!("dropin path is not exist, ignore it: {:?}", &dropin_dir); ++ log::debug!("Dropin path {dropin_dir:?} does not exist, ignoring"); + continue; + } + +@@ -578,24 +578,26 @@ impl Install { + for entry in dirs { + let dir_entry = entry?; + let fragment = dir_entry.path(); +- if fragment.is_file() { +- let file_name = String::from(fragment.file_name().unwrap().to_str().unwrap()); +- if file_name.starts_with('.') || !file_name.ends_with(".toml") { ++ if !fragment.is_file() { ++ log::debug!("Fragment file {fragment:?} is not a file, ignoring"); ++ continue; ++ } ++ partial = match confique::File::with_format(&fragment, FileFormat::Toml).load() { ++ Err(e) => { ++ log::error!("Failed to load {fragment:?}: {e}, skipping."); + continue; + } +- +- builder = builder.file(fragment); +- } ++ Ok(v) => partial.with_fallback(v), ++ }; + } + } +- +- let configer = builder.load().context(ConfiqueSnafu)?; ++ partial = partial.with_fallback(ConfigPartial::default_values()); ++ let configer = UeConfigData::from_partial(partial).context(ConfiqueSnafu)?; + unit_install.fill_struct(&configer); + + for also in &configer.Install.Also { + self.unit_install_discover(also, ctx.clone())?; + } +- // fs::remove_file(&tmp); + + Ok(()) + } +diff --git a/core/bin/unit/entry/config.rs b/core/bin/unit/entry/config.rs +index 705512d..91313c4 100644 +--- a/core/bin/unit/entry/config.rs ++++ b/core/bin/unit/entry/config.rs +@@ -14,7 +14,7 @@ + use super::base::UeBase; + use crate::unit::rentry::{UeConfigInstall, UeConfigUnit}; + use crate::unit::util::UnitFile; +-use confique::Config; ++use confique::{Config, FileFormat, Partial}; + use serde::{Deserialize, Deserializer, Serialize}; + use std::cell::RefCell; + use std::rc::Rc; +@@ -132,21 +132,28 @@ impl UeConfig { + } + + pub(super) fn load_fragment_and_dropin(&self, files: &UnitFile, name: &String) -> Result<()> { +- let mut builder = UeConfigData::builder().env(); +- ++ type ConfigPartial = ::Partial; ++ let mut partial: ConfigPartial = Partial::from_env().context(ConfiqueSnafu)?; ++ /* The first config wins, so add default values at last. */ + let unit_conf_frag = files.get_unit_id_fragment_pathbuf(name); + if unit_conf_frag.is_empty() { + return Err(format!("{name} doesn't have corresponding config file").into()); + } + // fragment +- for v in unit_conf_frag { +- if !v.exists() { +- return Err(format!("Config file {:?} of {name} doesn't exist", v).into()); ++ for path in unit_conf_frag { ++ if !path.exists() { ++ return Err(format!("Config file {:?} of {name} doesn't exist", path).into()); + } +- builder = builder.file(&v); ++ partial = match confique::File::with_format(&path, FileFormat::Toml).load() { ++ Err(e) => { ++ log::error!("Failed to load {path:?}: {e}, skipping"); ++ continue; ++ } ++ Ok(v) => partial.with_fallback(v), ++ }; + } +- +- let mut configer = builder.load().context(ConfiqueSnafu)?; ++ partial = partial.with_fallback(ConfigPartial::default_values()); ++ let mut configer = UeConfigData::from_partial(partial).context(ConfiqueSnafu)?; + + // dropin + for v in files.get_unit_wants_symlink_units(name) { +diff --git a/core/bin/unit/util/unit_file.rs b/core/bin/unit/util/unit_file.rs +index 0a0fa9f..eb9404b 100644 +--- a/core/bin/unit/util/unit_file.rs ++++ b/core/bin/unit/util/unit_file.rs +@@ -118,12 +118,7 @@ impl UnitFileData { + if file_name.starts_with('.') || file_name.ends_with(".toml") { + continue; + } +- let path = format!("{}.toml", fragment.to_string_lossy()); +- +- if let Err(e) = std::fs::copy(fragment, &path) { +- log::warn!("copy file content to toml file error: {}", e); +- } +- res.push(Path::new(&path).to_path_buf()); ++ res.push(fragment); + } + } + /* {/etc/sysmater, /usr/lib/sysmaster}/foo.service */ +@@ -135,14 +130,8 @@ impl UnitFileData { + if config_path.is_symlink() { + return None; + } +- /* Add .toml to the original path name */ +- let path_toml = format!("{}.toml", config_path.to_string_lossy()); +- let to = Path::new(&path_toml); +- if let Err(e) = std::fs::copy(config_path, to) { +- log::warn!("copy file content to toml file error: {}", e); +- return None; +- } +- res.push(to.to_path_buf()); ++ ++ res.push(config_path); + Some(res) + } + +-- +2.33.0 + diff --git a/backport-refactor-move-UmIf-functions-no-functional-change.patch b/backport-refactor-move-UmIf-functions-no-functional-change.patch new file mode 100644 index 0000000..f5337d4 --- /dev/null +++ b/backport-refactor-move-UmIf-functions-no-functional-change.patch @@ -0,0 +1,541 @@ +From dc03b566b2dc087f1d8ba27d4bcd796578fc68af Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Wed, 28 Jun 2023 10:42:36 +0800 +Subject: [PATCH] refactor: move UmIf functions, no functional change + +There are many functions in 'impl UmIf for UnitManager' just call the same +name function in 'impl UnitManager', this commit moves these functions from +'impl UnitManager' to 'impl UmIf for UnitManager'. No functional change. +--- + core/bin/unit/manager.rs | 369 ++++++++++++++------------------------- + core/lib/unit/umif.rs | 20 --- + 2 files changed, 134 insertions(+), 255 deletions(-) + +diff --git a/core/bin/unit/manager.rs b/core/bin/unit/manager.rs +index f548817..2e6caba 100644 +--- a/core/bin/unit/manager.rs ++++ b/core/bin/unit/manager.rs +@@ -269,7 +269,19 @@ pub struct UnitManager { + impl UmIf for UnitManager { + /// check the unit s_u_name and t_u_name have atom relation + fn unit_has_dependecy(&self, s_u_name: &str, atom: UnitRelationAtom, t_u_name: &str) -> bool { +- self.unit_has_dependecy(s_u_name, atom, t_u_name) ++ let s_unit = if let Some(s_unit) = self.db.units_get(s_u_name) { ++ s_unit ++ } else { ++ return false; ++ }; ++ ++ let t_unit = if let Some(unit) = self.db.units_get(t_u_name) { ++ unit ++ } else { ++ return false; ++ }; ++ ++ self.db.dep_is_dep_atom_with(&s_unit, atom, &t_unit) + } + + ///add a unit dependency to th unit deplist +@@ -284,7 +296,20 @@ impl UmIf for UnitManager { + add_ref: bool, + mask: UnitDependencyMask, + ) -> Result<()> { +- self.unit_add_dependency(unit_name, relation, target_name, add_ref, mask) ++ let s_unit = if let Some(unit) = self.load_unitx(unit_name) { ++ unit ++ } else { ++ return Err(Error::UnitActionENoent); ++ }; ++ let t_unit = if let Some(unit) = self.load_unitx(target_name) { ++ unit ++ } else { ++ return Err(Error::UnitActionENoent); ++ }; ++ ++ self.rt ++ .unit_add_dependency(s_unit, relation, t_unit, add_ref, mask); ++ Ok(()) + } + + ///add two unit dependency to the unit +@@ -307,7 +332,11 @@ impl UmIf for UnitManager { + + /// load the unit for reference name + fn load_unit_success(&self, name: &str) -> bool { +- self.load_unit_success(name) ++ if let Some(unit) = self.load_unitx(name) { ++ return unit.load_state() == UnitLoadState::Loaded; ++ } ++ ++ false + } + + fn unit_enabled(&self, name: &str) -> Result<()> { +@@ -329,17 +358,36 @@ impl UmIf for UnitManager { + Ok(()) + } + ++ /// check if there is already a stop job in process + fn has_stop_job(&self, name: &str) -> bool { +- self.has_stop_job(name) ++ let u = match self.db.units_get(name) { ++ None => return false, ++ Some(v) => v, ++ }; ++ self.jm.has_stop_job(&u) + } + ++ /// check if there is already a start job in process + fn has_start_job(&self, name: &str) -> bool { +- self.has_start_job(name) ++ let u = match self.db.units_get(name) { ++ None => return false, ++ Some(v) => v, ++ }; ++ self.jm.has_start_job(&u) + } + + /// check the unit that will be triggered by {name} is in active or activating state + fn relation_active_or_pending(&self, name: &str) -> bool { +- self.relation_active_or_pending(name) ++ let deps = self.db.dep_gets(name, UnitRelations::UnitTriggers); ++ let mut pending: bool = false; ++ for dep in deps.iter() { ++ if dep.active_or_activating() { ++ pending = true; ++ break; ++ } ++ } ++ ++ pending + } + + fn unit_destroy_runtime_data(&self, runtime_directory: Vec) -> Result<()> { +@@ -355,8 +403,9 @@ impl UmIf for UnitManager { + self.start_unit(name, false, "replace") + } + ++ /// + fn events(&self) -> Rc { +- self.events() ++ Rc::clone(&self.events) + } + + fn child_unwatch_pid(&self, id: &str, pid: Pid) { +@@ -388,32 +437,66 @@ impl UmIf for UnitManager { + } + } + ++ /// add pid and its correspond unit to + fn child_watch_pid(&self, id: &str, pid: Pid) { +- self.child_watch_pid(id, pid) ++ self.db.child_add_watch_pid(id, pid) + } + + fn child_watch_all_pids(&self, id: &str) { +- self.child_watch_all_pids(id) ++ self.db.child_watch_all_pids(id) + } + + fn child_unwatch_all_pids(&self, id: &str) { +- self.child_unwatch_all_pids(id) ++ self.db.child_unwatch_all_pids(id) + } + + fn notify_socket(&self) -> Option { +- self.notify_socket() ++ self.notify.notify_sock() + } + + fn same_unit_with_pid(&self, unit: &str, pid: Pid) -> bool { +- self.same_unit_with_pid(unit, pid) ++ if !process_util::valid_pid(pid) { ++ return false; ++ } ++ ++ let p_unit = self.db.get_unit_by_pid(pid); ++ if p_unit.is_none() { ++ return false; ++ } ++ ++ if p_unit.unwrap().id() == unit { ++ return true; ++ } ++ ++ false + } + + fn collect_socket_fds(&self, name: &str) -> Vec { +- self.collect_socket_fds(name) ++ let deps = self.db.dep_gets(name, UnitRelations::UnitTriggeredBy); ++ let mut fds = Vec::new(); ++ for dep in deps.iter() { ++ if dep.unit_type() != UnitType::UnitSocket { ++ continue; ++ } ++ ++ fds.extend(dep.collect_fds()) ++ } ++ ++ fds + } + +- fn get_dependency_list(&self, _unit_name: &str, _atom: UnitRelationAtom) -> Vec { +- self.get_dependency_list(_unit_name, _atom) ++ fn get_dependency_list(&self, unit_name: &str, atom: UnitRelationAtom) -> Vec { ++ let s_unit = if let Some(unit) = self.db.units_get(unit_name) { ++ unit ++ } else { ++ log::error!("unit [{}] not found!!!!!", unit_name); ++ return Vec::new(); ++ }; ++ let dep_units = self.db.dep_gets_atom(&s_unit, atom); ++ dep_units ++ .iter() ++ .map(|uxr| uxr.unit().id().to_string()) ++ .collect::>() + } + + fn unit_has_default_dependecy(&self, _unit_name: &str) -> bool { +@@ -426,7 +509,11 @@ impl UmIf for UnitManager { + } + + fn units_get_all(&self, unit_type: Option) -> Vec { +- self.units_get_all(unit_type) ++ let units = self.db.units_get_all(unit_type); ++ units ++ .iter() ++ .map(|uxr| uxr.unit().id().to_string()) ++ .collect::>() + } + + fn current_active_state(&self, _unit_name: &str) -> UnitActiveState { +@@ -464,23 +551,40 @@ impl UmIf for UnitManager { + } + + fn restart_unit(&self, name: &str, is_manual: bool) -> Result<()> { +- self.restart_unit(name, is_manual) +- } +- +- fn get_log_file(&self) -> &str { +- self.get_log_file() +- } ++ let unit = match self.load_unitx(name) { ++ None => { ++ return Err(Error::UnitActionENoent); ++ } ++ Some(v) => v, ++ }; + +- fn get_log_target(&self) -> &str { +- self.get_log_target() +- } ++ if is_manual ++ && unit ++ .get_config() ++ .config_data() ++ .borrow() ++ .Unit ++ .RefuseManualStop ++ { ++ return Err(Error::UnitActionERefuseManualStop); ++ } + +- fn get_log_file_size(&self) -> u32 { +- self.get_log_file_size() +- } ++ if unit ++ .get_config() ++ .config_data() ++ .borrow() ++ .Unit ++ .RefuseManualStart ++ { ++ return Err(Error::UnitActionERefuseManualStart); ++ } + +- fn get_log_file_number(&self) -> u32 { +- self.get_log_file_number() ++ self.jm.exec( ++ &JobConf::new(&unit, JobKind::Restart), ++ JobMode::Replace, ++ &mut JobAffect::new(false), ++ )?; ++ Ok(()) + } + + /// set the service's socket fd +@@ -504,21 +608,6 @@ impl UmIf for UnitManager { + + /// the declaration "pub(self)" is for identification only. + impl UnitManager { +- /// add pid and its correspond unit to +- fn child_watch_pid(&self, id: &str, pid: Pid) { +- self.db.child_add_watch_pid(id, pid) +- } +- +- /// add all the pid of unit id, read pids from cgroup path. +- fn child_watch_all_pids(&self, id: &str) { +- self.db.child_watch_all_pids(id) +- } +- +- /// remove all pids +- fn child_unwatch_all_pids(&self, id: &str) { +- self.db.child_unwatch_all_pids(id) +- } +- + /// delete the pid from the db + fn child_unwatch_pid(&self, id: &str, pid: Pid) { + self.db.child_unwatch_pid(id, pid) +@@ -543,102 +632,6 @@ impl UnitManager { + self.db.units_get(name).map(|uxr| uxr.unit()) + } + +- /// +- fn units_get_all(&self, unit_type: Option) -> Vec { +- let units = self.db.units_get_all(unit_type); +- units +- .iter() +- .map(|uxr| uxr.unit().id().to_string()) +- .collect::>() +- } +- +- /// load the unit for reference name +- fn load_unit_success(&self, name: &str) -> bool { +- if let Some(unit) = self.load_unitx(name) { +- return unit.load_state() == UnitLoadState::Loaded; +- } +- +- false +- } +- +- /// check the unit s_u_name and t_u_name have atom relation +- fn unit_has_dependecy(&self, s_u_name: &str, atom: UnitRelationAtom, t_u_name: &str) -> bool { +- let s_unit = if let Some(s_unit) = self.db.units_get(s_u_name) { +- s_unit +- } else { +- return false; +- }; +- +- let t_unit = if let Some(unit) = self.db.units_get(t_u_name) { +- unit +- } else { +- return false; +- }; +- +- self.db.dep_is_dep_atom_with(&s_unit, atom, &t_unit) +- } +- +- ///add a unit dependency to th unit deplist +- /// can called by sub unit +- /// sub unit add some default dependency +- /// +- pub fn unit_add_dependency( +- &self, +- unit_name: &str, +- relation: UnitRelations, +- target_name: &str, +- add_ref: bool, +- mask: UnitDependencyMask, +- ) -> Result<()> { +- let s_unit = if let Some(unit) = self.load_unitx(unit_name) { +- unit +- } else { +- return Err(Error::UnitActionENoent); +- }; +- let t_unit = if let Some(unit) = self.load_unitx(target_name) { +- unit +- } else { +- return Err(Error::UnitActionENoent); +- }; +- +- self.rt +- .unit_add_dependency(s_unit, relation, t_unit, add_ref, mask); +- Ok(()) +- } +- +- /// get the unit the has atom relation with the unit +- fn get_dependency_list(&self, unit_name: &str, atom: UnitRelationAtom) -> Vec { +- let s_unit = if let Some(unit) = self.db.units_get(unit_name) { +- unit +- } else { +- log::error!("unit [{}] not found!!!!!", unit_name); +- return Vec::new(); +- }; +- let dep_units = self.db.dep_gets_atom(&s_unit, atom); +- dep_units +- .iter() +- .map(|uxr| uxr.unit().id().to_string()) +- .collect::>() +- } +- +- /// check if there is already a stop job in process +- fn has_stop_job(&self, name: &str) -> bool { +- let u = match self.db.units_get(name) { +- None => return false, +- Some(v) => v, +- }; +- self.jm.has_stop_job(&u) +- } +- +- /// check if there is already a start job in process +- fn has_start_job(&self, name: &str) -> bool { +- let u = match self.db.units_get(name) { +- None => return false, +- Some(v) => v, +- }; +- self.jm.has_start_job(&u) +- } +- + /// + pub fn unit_emergency_action(&self, action: UnitEmergencyAction, reason: String) { + if action == UnitEmergencyAction::None { +@@ -713,53 +706,6 @@ impl UnitManager { + } + } + +- /// return the fds that trigger the unit {name}; +- fn collect_socket_fds(&self, name: &str) -> Vec { +- let deps = self.db.dep_gets(name, UnitRelations::UnitTriggeredBy); +- let mut fds = Vec::new(); +- for dep in deps.iter() { +- if dep.unit_type() != UnitType::UnitSocket { +- continue; +- } +- +- fds.extend(dep.collect_fds()) +- } +- +- fds +- } +- +- /// check the unit that will be triggered by {name} is in active or activating state +- fn relation_active_or_pending(&self, name: &str) -> bool { +- let deps = self.db.dep_gets(name, UnitRelations::UnitTriggers); +- let mut pending: bool = false; +- for dep in deps.iter() { +- if dep.active_or_activating() { +- pending = true; +- break; +- } +- } +- +- pending +- } +- +- /// check the pid corresponding unit is the same with the unit +- fn same_unit_with_pid(&self, unit: &str, pid: Pid) -> bool { +- if !process_util::valid_pid(pid) { +- return false; +- } +- +- let p_unit = self.db.get_unit_by_pid(pid); +- if p_unit.is_none() { +- return false; +- } +- +- if p_unit.unwrap().id() == unit { +- return true; +- } +- +- false +- } +- + fn start_unit(&self, name: &str, is_manual: bool, job_mode_str: &str) -> Result<()> { + let unit = match self.load_unitx(name) { + None => { +@@ -793,16 +739,6 @@ impl UnitManager { + Ok(()) + } + +- /// return the notify path +- fn notify_socket(&self) -> Option { +- self.notify.notify_sock() +- } +- +- /// +- pub fn events(&self) -> Rc { +- Rc::clone(&self.events) +- } +- + /// + pub fn reliability(&self) -> Rc { + Rc::clone(&self.reli) +@@ -875,43 +811,6 @@ impl UnitManager { + } + } + +- pub(self) fn restart_unit(&self, name: &str, is_manual: bool) -> Result<()> { +- let unit = match self.load_unitx(name) { +- None => { +- return Err(Error::UnitActionENoent); +- } +- Some(v) => v, +- }; +- +- if is_manual +- && unit +- .get_config() +- .config_data() +- .borrow() +- .Unit +- .RefuseManualStop +- { +- return Err(Error::UnitActionERefuseManualStop); +- } +- +- if unit +- .get_config() +- .config_data() +- .borrow() +- .Unit +- .RefuseManualStart +- { +- return Err(Error::UnitActionERefuseManualStart); +- } +- +- self.jm.exec( +- &JobConf::new(&unit, JobKind::Restart), +- JobMode::Replace, +- &mut JobAffect::new(false), +- )?; +- Ok(()) +- } +- + fn get_unit_cgroup_path(&self, unit: Rc) -> String { + let res = match unit.cg_path().to_str() { + Some(res) => res.to_string(), +diff --git a/core/lib/unit/umif.rs b/core/lib/unit/umif.rs +index a000a3d..18616f5 100644 +--- a/core/lib/unit/umif.rs ++++ b/core/lib/unit/umif.rs +@@ -190,26 +190,6 @@ pub trait UmIf { + Ok(()) + } + +- /// get the log file config +- fn get_log_file(&self) -> &str { +- "" +- } +- +- /// get the log file size +- fn get_log_file_size(&self) -> u32 { +- 0 +- } +- +- /// get the log file number +- fn get_log_file_number(&self) -> u32 { +- 0 +- } +- +- /// get the log target config +- fn get_log_target(&self) -> &str { +- "" +- } +- + /* ========== ONLY VALID IN SERVICE ========== */ + /// set the service's socket fd + fn service_set_socket_fd(&self, _service_name: &str, _fd: i32) {} +-- +2.33.0 + diff --git a/backport-refactor-mv-system.toml-to-config-conf.patch b/backport-refactor-mv-system.toml-to-config-conf.patch new file mode 100644 index 0000000..6fbf77d --- /dev/null +++ b/backport-refactor-mv-system.toml-to-config-conf.patch @@ -0,0 +1,17 @@ +From 81acf0ac1e5c6d2afd3159f0c1e0bc1569c7ecd9 Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Thu, 29 Jun 2023 14:28:46 +0800 +Subject: [PATCH] refactor: mv system.toml to config/conf + +--- + {units => config/conf}/system.toml | 0 + 1 file changed, 0 insertions(+), 0 deletions(-) + rename {units => config/conf}/system.toml (100%) + +diff --git a/units/system.toml b/config/conf/system.toml +similarity index 100% +rename from units/system.toml +rename to config/conf/system.toml +-- +2.33.0 + diff --git a/backport-test-add-UT-testcase-for-command-dispatch.patch b/backport-test-add-UT-testcase-for-command-dispatch.patch new file mode 100644 index 0000000..4e142df --- /dev/null +++ b/backport-test-add-UT-testcase-for-command-dispatch.patch @@ -0,0 +1,191 @@ +From 2e5a2327f009432ac9bd247567f2b6d953ec63c6 Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Thu, 13 Jul 2023 14:50:28 +0800 +Subject: [PATCH] test: add UT testcase for command dispatch + +--- + core/sysmaster/manager/commands.rs | 171 +++++++++++++++++++++++++++++ + 1 file changed, 171 insertions(+) + +diff --git a/core/sysmaster/manager/commands.rs b/core/sysmaster/manager/commands.rs +index ad3e97f..a05d949 100644 +--- a/core/sysmaster/manager/commands.rs ++++ b/core/sysmaster/manager/commands.rs +@@ -132,3 +132,174 @@ where + 0i8 + } + } ++ ++#[cfg(test)] ++mod tests { ++ use std::sync::{Arc, Mutex}; ++ use std::{os::unix::net::UnixStream, rc::Rc}; ++ ++ use cmdproto::error::Result; ++ use cmdproto::proto::{execute::ExecuterAction, unit_comm}; ++ use cmdproto::proto::{CommandRequest, ProstClientStream}; ++ use constants::SCTL_SOCKET; ++ use event::{EventState, Events}; ++ use sysmaster::rel::{ReliConf, Reliability}; ++ ++ use crate::manager::RELI_HISTORY_MAX_DBS; ++ ++ use super::Commands; ++ ++ struct TestExecAction {} ++ ++ impl ExecuterAction for TestExecAction { ++ type Error = nix::Error; ++ type Status = nix::Error; ++ ++ fn start(&self, _unit_name: &str) -> Result<(), Self::Error> { ++ Err(nix::Error::ENOENT) ++ } ++ ++ fn stop(&self, _unit_name: &str) -> Result<(), Self::Error> { ++ Ok(()) ++ } ++ ++ fn restart(&self, _unit_name: &str) -> Result<(), Self::Error> { ++ Ok(()) ++ } ++ ++ fn reload(&self, _unit_name: &str) -> Result<(), Self::Error> { ++ Ok(()) ++ } ++ ++ fn isolate(&self, _unit_name: &str) -> Result<(), Self::Error> { ++ Ok(()) ++ } ++ ++ fn reset_failed(&self, _unit_name: &str) -> Result<(), Self::Error> { ++ Ok(()) ++ } ++ ++ fn status(&self, _unit_name: &str) -> Result { ++ Ok(nix::Error::EINVAL) ++ } ++ ++ fn list_units(&self) -> Result { ++ Ok(String::new()) ++ } ++ ++ fn suspend(&self) -> Result { ++ Ok(0) ++ } ++ ++ fn poweroff(&self) -> Result { ++ Ok(0) ++ } ++ ++ fn reboot(&self) -> Result { ++ Ok(0) ++ } ++ ++ fn halt(&self) -> Result { ++ Ok(0) ++ } ++ ++ fn disable(&self, _unit_name: &str) -> Result<(), Self::Error> { ++ Ok(()) ++ } ++ ++ fn enable(&self, _unit_name: &str) -> Result<(), Self::Error> { ++ Ok(()) ++ } ++ ++ fn mask(&self, _unit_name: &str) -> Result<(), Self::Error> { ++ Ok(()) ++ } ++ ++ fn unmask(&self, _unit_name: &str) -> Result<(), Self::Error> { ++ Ok(()) ++ } ++ ++ fn daemon_reload(&self) {} ++ ++ fn daemon_reexec(&self) {} ++ ++ fn switch_root(&self, _init: &[String]) -> Result<(), Self::Error> { ++ Ok(()) ++ } ++ } ++ ++ #[test] ++ fn test_sctl_socket() { ++ if !nix::unistd::getuid().is_root() { ++ println!( ++ "We will create a socket under '/run', so we must be root to run this testcase." ++ ); ++ return; ++ } ++ ++ let mutex_main = Arc::new(Mutex::new(0)); ++ let mutex_child = Arc::clone(&mutex_main); ++ let temp = mutex_main.lock().unwrap(); ++ ++ std::thread::spawn(move || { ++ /* Wait until the main thread are ready to process our request. */ ++ let mut test_ok = mutex_child.lock().unwrap(); ++ /* 1. Start a service as root. */ ++ let stream = UnixStream::connect(SCTL_SOCKET).unwrap(); ++ let mut client = ProstClientStream::new(stream); ++ ++ let req = CommandRequest::new_unitcomm( ++ unit_comm::Action::Start, ++ vec!["foo.service".to_string()], ++ ); ++ let data = client.execute(req).unwrap(); ++ if !data ++ .message ++ .eq("Failed to start foo.service: ENOENT: No such file or directory") ++ { ++ return; ++ } ++ /* 2. Start a service as an unprivileged user. */ ++ if nix::unistd::setuid(nix::unistd::Uid::from_raw(1000)).is_err() { ++ println!("Failed to set ourself to unprivileged user"); ++ return; ++ } ++ let stream = UnixStream::connect(SCTL_SOCKET).unwrap(); ++ let mut client = ProstClientStream::new(stream); ++ ++ let req = CommandRequest::new_unitcomm( ++ unit_comm::Action::Start, ++ vec!["foo.service".to_string()], ++ ); ++ let data = client.execute(req).unwrap(); ++ if !data ++ .message ++ .eq("Failed to execute your command: Operation not permitted.") ++ { ++ return; ++ } ++ *test_ok = 1; ++ }); ++ ++ let exec_action = TestExecAction {}; ++ let reli = Rc::new(Reliability::new( ++ ReliConf::new().set_max_dbs(RELI_HISTORY_MAX_DBS), ++ )); ++ /* This will remove the /run/sysmaster/sctl on the compiling environment. */ ++ let command = Rc::new(Commands::new(&reli, exec_action)); ++ let e = Events::new().unwrap(); ++ e.add_source(command.clone()).unwrap(); ++ e.set_enabled(command.clone(), EventState::On).unwrap(); ++ /* Drop temp, let the child thread go. */ ++ drop(temp); ++ /* We have 2 events to dispatch, but are not sure if we can get these events after waiting ++ * 300ms, 400ms. So we wait one more time to make sure all events are dispatched. */ ++ e.run(300).unwrap(); ++ e.run(400).unwrap(); ++ e.run(300).unwrap(); ++ let test_ok = mutex_main.lock().unwrap(); ++ /* The value should be set to 1 in the child process, if everything works well. */ ++ assert_eq!(*test_ok, 1); ++ e.del_source(command).unwrap(); ++ } ++} +-- +2.33.0 + diff --git a/backport-test-condition-add-unit-test-for-condition.patch b/backport-test-condition-add-unit-test-for-condition.patch new file mode 100644 index 0000000..c582f1f --- /dev/null +++ b/backport-test-condition-add-unit-test-for-condition.patch @@ -0,0 +1,96 @@ +From 614e5cd80a89cf5b4eb3f9cd3fe9e8fca9c30e97 Mon Sep 17 00:00:00 2001 +From: love_hangzhou <421699196@qq.com> +Date: Wed, 19 Jul 2023 22:28:05 +0800 +Subject: [PATCH] test(condition): add unit test for condition + +--- + coms/service/src/config.rs | 13 +++++++ + core/sysmaster/unit/entry/condition.rs | 53 ++++++++++++++++++++++++++ + 2 files changed, 66 insertions(+) + +diff --git a/coms/service/src/config.rs b/coms/service/src/config.rs +index e61340b..ec2ebf4 100644 +--- a/coms/service/src/config.rs ++++ b/coms/service/src/config.rs +@@ -218,4 +218,17 @@ mod tests { + + assert!(result.is_ok()); + } ++ #[test] ++ fn test_get_service_type() { ++ let mut file_path = get_project_root().unwrap(); ++ file_path.push("tests/test_units/config.service"); ++ ++ let paths = vec![file_path]; ++ ++ let comm = Rc::new(ServiceUnitComm::new()); ++ let config = ServiceConfig::new(&comm); ++ ++ let result = config.load(paths, false); ++ assert_eq!(config.service_type(), b"Simple") ++ } + } +diff --git a/core/sysmaster/unit/entry/condition.rs b/core/sysmaster/unit/entry/condition.rs +index c3836b4..225297e 100644 +--- a/core/sysmaster/unit/entry/condition.rs ++++ b/core/sysmaster/unit/entry/condition.rs +@@ -160,3 +160,56 @@ impl UeCondition { + Self::condition_vec_test(assert_conditions) + } + } ++ ++#[cfg(test)] ++mod tests { ++ use basic::condition::ConditionType; ++ ++ use crate::unit::entry::condition::condition_keys::CONDITION_NEEDS_UPDATE; ++ ++ use super::{ ++ assert_keys::ASSERT_PATH_EXISTS, condition_keys::CONDITION_PATH_EXISTS, UeCondition, ++ }; ++ ++ #[test] ++ fn test_new_condition_trigger() { ++ let uc = UeCondition::new(); ++ let c = uc.new_condition(ConditionType::FileNotEmpty, String::from("|!test")); ++ assert_eq!(c.trigger(), 1, "condition trigger is {}", c.trigger()); ++ } ++ #[test] ++ fn test_new_condition_is_not_trigger() { ++ let uc = UeCondition::new(); ++ let c = uc.new_condition(ConditionType::FileNotEmpty, String::from("!test")); ++ assert_eq!(c.trigger(), 0, "condition trigger is {}", c.trigger()); ++ } ++ ++ #[test] ++ fn test_new_condition_is_revert() { ++ let uc = UeCondition::new(); ++ let c = uc.new_condition(ConditionType::FileNotEmpty, String::from("!test")); ++ assert_eq!(c.revert(), 1, "condition revert is {}", c.revert()); ++ } ++ #[test] ++ fn test_new_condition_is_not_revert() { ++ let uc = UeCondition::new(); ++ let c = uc.new_condition(ConditionType::FileNotEmpty, String::from("test")); ++ assert_eq!(c.revert(), 0, "condition revert is {}", c.revert()); ++ } ++ ++ #[test] ++ fn test_add_condition() { ++ let uc = UeCondition::new(); ++ uc.add_condition(CONDITION_PATH_EXISTS, String::from("test")); ++ assert_eq!(uc.conditions.borrow().0.len(), 1); ++ uc.add_condition(CONDITION_NEEDS_UPDATE, String::from("True")); ++ assert_eq!(uc.conditions.borrow().0.len(), 2); ++ } ++ ++ #[test] ++ fn test_add_assert() { ++ let uc = UeCondition::new(); ++ uc.add_assert(ASSERT_PATH_EXISTS, String::from("assert")); ++ assert_eq!(uc.asserts.borrow().0.len(), 1); ++ } ++} +-- +2.33.0 + diff --git a/backport-test-support-yum-install-sysmaster.patch b/backport-test-support-yum-install-sysmaster.patch new file mode 100644 index 0000000..340597c --- /dev/null +++ b/backport-test-support-yum-install-sysmaster.patch @@ -0,0 +1,689 @@ +From 3533162ce06945fe2bae8ddb4d0200e6b3e361c2 Mon Sep 17 00:00:00 2001 +From: oh_thats_great +Date: Tue, 11 Jul 2023 16:37:43 +0800 +Subject: [PATCH] test: support yum install sysmaster + +--- + install.sh | 30 +++++++------ + tests/common/docker_lib.sh | 45 ++++++++++++++++--- + tests/common/monitor.sh | 2 +- + tests/common/util_lib.sh | 36 ++++++--------- + .../unit_config_test/action_001/action_001.sh | 1 - + .../unit_config_test/assert_001/assert_001.sh | 1 - + .../unit_config_test/condition_001/check.sh | 2 +- + .../condition_001/condition_001.sh | 1 - + .../unit_config_test/condition_002/check.sh | 2 +- + .../condition_002/condition_002.sh | 1 - + .../condition_003/condition_003.sh | 1 - + .../unit_config_test/dependency_001/check.sh | 2 +- + .../dependency_001/dependency_001.sh | 1 - + .../dependency_002/dependency_002.sh | 1 - + .../dependency_003/dependency_003.sh | 1 - + .../dependency_004/dependency_004.sh | 1 - + .../dependency_005/dependency_005.sh | 1 - + .../unit_config_test/env_001/env_001.sh | 1 - + .../unit_config_test/exec_001/exec_001.sh | 1 - + .../isolate_001/isolate_001.sh | 1 - + .../unit_config_test/kill_001/kill_001.sh | 1 - + .../unit_config_test/listen_001/check.sh | 2 +- + .../unit_config_test/listen_001/listen_001.sh | 1 - + .../unit_config_test/refuse_001/refuse_001.sh | 1 - + .../restart_001/restart_001.sh | 1 - + .../service_001/service_001.sh | 1 - + .../service_002/service_002.sh | 1 - + .../service_003/service_003.sh | 1 - + .../unit_config_test/service_004/check.sh | 2 +- + .../service_004/service_004.sh | 1 - + .../unit_config_test/socket_001/check.sh | 2 +- + .../unit_config_test/socket_001/socket_001.sh | 1 - + .../startlimit_001/startlimit_001.sh | 1 - + .../timeout_001/timeout_001.sh | 1 - + .../timeout_002/timeout_002.sh | 1 - + .../docker_example_001/check.sh | 3 +- + tests/perf_test/cpu_time_001/check.sh | 2 +- + tests/test_frame.sh | 7 +-- + 38 files changed, 84 insertions(+), 78 deletions(-) + +diff --git a/install.sh b/install.sh +index 675c543..dc0e6da 100644 +--- a/install.sh ++++ b/install.sh +@@ -7,19 +7,23 @@ install_dir=${work_dir}/target/install/usr/lib/sysmaster + + rm -rf "${work_dir}"/target/install + +-install -Dm0755 -t ${work_dir}/target/install/usr/bin ${target_dir}/sctl || exit 1 +-install -Dm0755 -t ${work_dir}/target/install/usr/bin ${target_dir}/init || exit 1 +-install -Dm0755 -t ${install_dir} ${target_dir}/sysmaster || exit 1 +-install -Dm0755 -t ${install_dir} ${target_dir}/fstab || exit 1 +-install -Dm0755 -t ${install_dir} ${target_dir}/sysmonitor || exit 1 +-install -Dm0755 -t ${install_dir} ${target_dir}/random_seed || exit 1 +-install -Dm0755 -t ${install_dir} ${target_dir}/rc-local-generator || exit 1 +-install -Dm0755 -t ${install_dir} ${target_dir}/hostname_setup || exit 1 ++install -Dm0550 -t ${work_dir}/target/install/usr/bin ${target_dir}/sctl || exit 1 ++install -Dm0550 -t ${install_dir} ${target_dir}/init || exit 1 ++install -Dm0550 -t ${install_dir} ${target_dir}/sysmaster || exit 1 ++ ++install -Dm0550 -t ${install_dir} ${target_dir}/fstab || exit 1 ++install -Dm0550 -t ${install_dir} ${target_dir}/sysmonitor || exit 1 ++install -Dm0550 -t ${install_dir} ${target_dir}/random_seed || exit 1 ++install -Dm0550 -t ${install_dir} ${target_dir}/rc-local-generator || exit 1 ++install -Dm0550 -t ${install_dir} ${target_dir}/hostname_setup || exit 1 ++ ++install -Dm0640 -t ${install_dir} ${work_dir}/units/* || exit 1 ++install -Dm0640 -t ${install_dir}/plugin ${target_dir}/conf/plugin.conf || exit 1 ++install -Dm0640 -t ${work_dir}/target/install/etc/sysmaster ${target_dir}/conf/system.conf || exit 1 + + strip ${target_dir}/lib*.so + +-install -Dm0644 -t ${install_dir}/plugin ${target_dir}/libmount.so || exit 1 +-install -Dm0644 -t ${install_dir}/plugin ${target_dir}/libservice.so || exit 1 +-install -Dm0644 -t ${install_dir}/plugin ${target_dir}/libsocket.so || exit 1 +-install -Dm0644 -t ${install_dir}/plugin ${target_dir}/libtarget.so || exit 1 +-install -Dm0644 -t ${install_dir}/plugin ${target_dir}/conf/plugin.conf || exit 1 ++install -Dm0750 -t ${install_dir}/plugin ${target_dir}/libmount.so || exit 1 ++install -Dm0750 -t ${install_dir}/plugin ${target_dir}/libservice.so || exit 1 ++install -Dm0750 -t ${install_dir}/plugin ${target_dir}/libsocket.so || exit 1 ++install -Dm0750 -t ${install_dir}/plugin ${target_dir}/libtarget.so || exit 1 +diff --git a/tests/common/docker_lib.sh b/tests/common/docker_lib.sh +index cc57e51..2ff96b6 100755 +--- a/tests/common/docker_lib.sh ++++ b/tests/common/docker_lib.sh +@@ -43,15 +43,32 @@ function load_isula_img() { + + function build_base_img() { + cp -arf ${BUILD_PATH}/target/install "${TMP_DIR}" ++ cp -arf /etc/yum.repos.d "${TMP_DIR}" + + pushd "${TMP_DIR}" +- cat << EOF > Dockerfile ++ if yum list sysmaster; then ++ cat << EOF > Dockerfile + FROM ${BASE_IMG} as ${SYSMST_BASE_IMG} ++ ++RUN rm -rf /etc/yum.repos.d && mkdir /etc/yum.repos.d ++COPY yum.repos.d /etc/yum.repos.d/ ++RUN yum install -y sysmaster util-linux shadow sudo passwd net-tools iproute nmap ++EOF ++ else ++ cat << EOF > Dockerfile ++FROM ${BASE_IMG} as ${SYSMST_BASE_IMG} ++ ++RUN rm -rf /etc/yum.repos.d && mkdir /etc/yum.repos.d ++COPY yum.repos.d /etc/yum.repos.d/ ++RUN yum install -y util-linux shadow sudo passwd net-tools iproute nmap ++ + COPY install/usr/bin/sctl /usr/bin/ +-COPY install/usr/bin/init /usr/bin/ +-RUN mkdir /usr/lib/sysmaster ++RUN mkdir /usr/lib/sysmaster /etc/sysmaster + COPY install/usr/lib/sysmaster /usr/lib/sysmaster/ ++COPY install/etc/sysmaster /etc/sysmaster/ ++RUN sed -i '/LogTarget/ s/=.*/="console-syslog"/' /etc/sysmaster/system.conf + EOF ++ fi + cat Dockerfile + if ! docker build -t "${SYSMST_BASE_IMG}:latest" .; then + log_error "build ${SYSMST_BASE_IMG} image failed!" +@@ -69,13 +86,29 @@ function build_isula_img() { + + pushd "${TMP_DIR}" + img_name=$(isula-build ctr-img images | grep "${BASE_IMG}" | head -n1 | awk '{print $1}') +- cat << EOF > Dockerfile ++ if yum list sysmaster; then ++ cat << EOF > Dockerfile + FROM ${img_name} as ${SYSMST_BASE_IMG} ++ ++RUN rm -rf /etc/yum.repos.d && mkdir /etc/yum.repos.d ++COPY yum.repos.d /usr/lib/sysmaster/ ++RUN yum install -y sysmaster util-linux shadow sudo passwd net-tools iproute nmap ++EOF ++ else ++ cat << EOF > Dockerfile ++FROM ${img_name} as ${SYSMST_BASE_IMG} ++ ++RUN rm -rf /etc/yum.repos.d && mkdir /etc/yum.repos.d ++COPY yum.repos.d /usr/lib/sysmaster/ ++RUN yum install -y util-linux shadow sudo passwd net-tools iproute nmap ++ + COPY install/usr/bin/sctl /usr/bin/ +-COPY install/usr/bin/init /usr/bin/ +-RUN mkdir /usr/lib/sysmaster ++RUN mkdir /usr/lib/sysmaster /etc/sysmaster + COPY install/usr/lib/sysmaster /usr/lib/sysmaster/ ++COPY install/etc/sysmaster /etc/sysmaster/ ++RUN sed -i '/LogTarget/ s/=.*/="console-syslog"/' /etc/sysmaster/system.conf + EOF ++ fi + cat Dockerfile + if ! isula-build ctr-img build -o isulad:"${SYSMST_BASE_IMG}:latest" -f Dockerfile .; then + log_error "build ${SYSMST_BASE_IMG} image failed!" +diff --git a/tests/common/monitor.sh b/tests/common/monitor.sh +index 2fe790f..24b8e6a 100644 +--- a/tests/common/monitor.sh ++++ b/tests/common/monitor.sh +@@ -2,7 +2,7 @@ + + while ((1)); do + time="$(date)" +- init_data="$(ps aux | grep -v grep | grep '/usr/bin/init')" ++ init_data="$(ps aux | grep -v grep | grep '/usr/lib/sysmaster/init')" + sysmst_data="$(ps aux | grep -v grep | grep '/usr/lib/sysmaster/sysmaster')" + + pid=$(echo ${init_data} | awk '{print $2}') +diff --git a/tests/common/util_lib.sh b/tests/common/util_lib.sh +index 18de448..2cf944a 100644 +--- a/tests/common/util_lib.sh ++++ b/tests/common/util_lib.sh +@@ -5,6 +5,13 @@ export SYSMST_LIB_PATH='/usr/lib/sysmaster/system' + export SYSMST_ETC_PATH='/etc/sysmaster/system' + export SYSMST_RUN_PATH='/run/sysmaster/system' + export SYSMST_LOG='/opt/sysmaster.log' ++[ "${DOCKER_TEST}" -ne 1 ] && SYSMST_LOG='/var/log/messages' ++if ! test -d /usr/lib/sysmaster/system; then ++ SYSMST_LIB_PATH='/usr/lib/sysmaster' ++ SYSMST_ETC_PATH='/etc/sysmaster' ++ SYSMST_RUN_PATH='/run/sysmaster' ++fi ++export SYSMST_PATH='/usr/lib/sysmaster' + export RELIAB_SWITCH_PATH='/run/sysmaster/reliability' + export RELIAB_SWITCH='switch.debug' + export RELIAB_CLR='clear.debug' +@@ -12,7 +19,6 @@ export init_pid='' + export sysmaster_pid='' + export cond_fail_log='Starting failed .* condition test failed' + export asst_fail_log='Starting failed .* assert test failed' +-export yum_proxy='proxy=' + + # ================== log function ================== + function log_info() { +@@ -127,14 +133,13 @@ function expect_str_eq() { + function run_sysmaster() { + local user="${1:-root}" + +- cp -arf "${work_dir}"/tmp_units/*.target ${SYSMST_LIB_PATH} || return 1 + if [ "${user}" = root ]; then +- RUST_BACKTRACE=full /usr/bin/init &> "${SYSMST_LOG}" & ++ RUST_BACKTRACE=full "${SYSMST_PATH}"/init &> "${SYSMST_LOG}" & + else +- chmod 777 /usr/bin/init +- chmod -R 777 /usr/lib/sysmaster /run ++ chmod 777 "${SYSMST_PATH}"/init ++ chmod -R 777 "${SYSMST_PATH}" /run + chmod -R 777 "$(dirname "${SYSMST_LOG}")" +- sudo -u "${user}" /usr/bin/init &> "${SYSMST_LOG}" & ++ sudo -u "${user}" "${SYSMST_PATH}"/init &> "${SYSMST_LOG}" & + fi + init_pid=$! + +@@ -142,17 +147,17 @@ function run_sysmaster() { + sleep 3 + for ((i = 0; i < 300; ++i)); do + sleep 1 +- ps -elf | grep -v grep | grep " $(echo ${user} | cut -c1-7)" | grep -w '/usr/lib/sysmaster/sysmaster' | grep ep_pol && break ++ ps -elf | grep -v grep | grep " $(echo ${user} | cut -c1-7)" | grep -w "${SYSMST_PATH}"/sysmaster | grep ep_pol && break + done + # debug + ps -elf | grep -v grep | grep -Ew 'sysmaster|init' +- if ! ps -elf | grep -v grep | grep " $(echo ${user} | cut -c1-7)" | grep -wq '/usr/lib/sysmaster/sysmaster'; then ++ if ! ps -elf | grep -v grep | grep " $(echo ${user} | cut -c1-7)" | grep -wq "${SYSMST_PATH}"/sysmaster; then + cat "${SYSMST_LOG}" + return 1 + fi + + # get sysmaster pid +- sysmaster_pid="$(ps -elf | grep -v grep | grep " $(echo ${user} | cut -c1-7)" | grep -w '/usr/lib/sysmaster/sysmaster' | awk '{print $4}')" ++ sysmaster_pid="$(ps -elf | grep -v grep | grep " $(echo ${user} | cut -c1-7)" | grep -w "${SYSMST_PATH}"/sysmaster | awk '{print $4}')" + echo > "${SYSMST_LOG}" + return 0 + } +@@ -223,19 +228,6 @@ function get_pids() { + sctl status "${service}" |& sed -n '/PID:/,$p' | sed 's/PID://' | awk '{print $1}' + } + +-# usage: install packages +-# input: packages names or files +-function install_pkg() { +- if ! grep -rq 'proxy=' /etc/yum.repos.d; then +- for file in /etc/yum.repos.d/*.repo; do +- sed -i "/^baseurl=/a ${yum_proxy}" "${file}" +- done +- yum clean all +- yum makecache +- fi +- yum install -y $@ +-} +- + # usage: check netstat + # input: $1: path + # $2: type +diff --git a/tests/config_test/unit_config_test/action_001/action_001.sh b/tests/config_test/unit_config_test/action_001/action_001.sh +index 5f4d505..3d3d07b 100644 +--- a/tests/config_test/unit_config_test/action_001/action_001.sh ++++ b/tests/config_test/unit_config_test/action_001/action_001.sh +@@ -11,7 +11,6 @@ function test_pre() { + pushd "${TEST_SCRIPT_PATH}" + rm -rf tmp_units + mkdir tmp_units +- cp -arf "${TEST_PATH}"/test_units/{shutdown.target,sysinit.target} tmp_units + cp -arf "${TEST_PATH}"/test_units/tests/base.service tmp_units + cp -arf "${TEST_PATH}"/test_units/tests/{reboot.target,poweroff.target,exit.target} tmp_units + popd +diff --git a/tests/config_test/unit_config_test/assert_001/assert_001.sh b/tests/config_test/unit_config_test/assert_001/assert_001.sh +index 60fc3c9..fe40ee3 100644 +--- a/tests/config_test/unit_config_test/assert_001/assert_001.sh ++++ b/tests/config_test/unit_config_test/assert_001/assert_001.sh +@@ -12,7 +12,6 @@ function test_pre() { + pushd "${TEST_SCRIPT_PATH}" + rm -rf tmp_units + mkdir tmp_units +- cp -arf "${TEST_PATH}"/test_units/{shutdown.target,sysinit.target} tmp_units + cp -arf "${TEST_PATH}"/test_units/tests/base.service tmp_units + popd + } +diff --git a/tests/config_test/unit_config_test/condition_001/check.sh b/tests/config_test/unit_config_test/condition_001/check.sh +index 0107bb6..9afb53b 100644 +--- a/tests/config_test/unit_config_test/condition_001/check.sh ++++ b/tests/config_test/unit_config_test/condition_001/check.sh +@@ -165,7 +165,7 @@ function test03() { + expect_eq $? 0 || return 1 + + # ro mounted path +- which mount || install_pkg /usr/bin/mount ++ which mount || yum install -y /usr/bin/mount + expect_eq $? 0 || return 1 + dd if=/dev/zero of=/tmp/mountfile bs=1M count=10 + mkfs.ext4 /tmp/mountfile +diff --git a/tests/config_test/unit_config_test/condition_001/condition_001.sh b/tests/config_test/unit_config_test/condition_001/condition_001.sh +index 4deada6..e082880 100644 +--- a/tests/config_test/unit_config_test/condition_001/condition_001.sh ++++ b/tests/config_test/unit_config_test/condition_001/condition_001.sh +@@ -14,7 +14,6 @@ function test_pre() { + pushd "${TEST_SCRIPT_PATH}" + rm -rf tmp_units + mkdir tmp_units +- cp -arf "${TEST_PATH}"/test_units/{shutdown.target,sysinit.target} tmp_units + cp -arf "${TEST_PATH}"/test_units/tests/base.service tmp_units + popd + } +diff --git a/tests/config_test/unit_config_test/condition_002/check.sh b/tests/config_test/unit_config_test/condition_002/check.sh +index 1deabaa..3ad0455 100644 +--- a/tests/config_test/unit_config_test/condition_002/check.sh ++++ b/tests/config_test/unit_config_test/condition_002/check.sh +@@ -86,7 +86,7 @@ function test04() { + test_user_2="test2_${RANDOM}" + user_pw_1="PW!test1_${RANDOM}" + user_pw_2="PW!test2_${RANDOM}" +- install_pkg shadow sudo ++ yum install -y shadow sudo + expect_eq $? 0 || return 1 + useradd "${test_user_1}" + useradd "${test_user_2}" +diff --git a/tests/config_test/unit_config_test/condition_002/condition_002.sh b/tests/config_test/unit_config_test/condition_002/condition_002.sh +index 3bc857c..207805d 100644 +--- a/tests/config_test/unit_config_test/condition_002/condition_002.sh ++++ b/tests/config_test/unit_config_test/condition_002/condition_002.sh +@@ -12,7 +12,6 @@ function test_pre() { + pushd "${TEST_SCRIPT_PATH}" + rm -rf tmp_units + mkdir tmp_units +- cp -arf "${TEST_PATH}"/test_units/{shutdown.target,sysinit.target} tmp_units + cp -arf "${TEST_PATH}"/test_units/tests/base.service tmp_units + popd + } +diff --git a/tests/config_test/unit_config_test/condition_003/condition_003.sh b/tests/config_test/unit_config_test/condition_003/condition_003.sh +index 54eb5be..af33bad 100644 +--- a/tests/config_test/unit_config_test/condition_003/condition_003.sh ++++ b/tests/config_test/unit_config_test/condition_003/condition_003.sh +@@ -12,7 +12,6 @@ function test_pre() { + pushd "${TEST_SCRIPT_PATH}" + rm -rf tmp_units + mkdir tmp_units +- cp -arf "${TEST_PATH}"/test_units/{shutdown.target,sysinit.target} tmp_units + cp -arf "${TEST_PATH}"/test_units/tests/base.service tmp_units + popd + } +diff --git a/tests/config_test/unit_config_test/dependency_001/check.sh b/tests/config_test/unit_config_test/dependency_001/check.sh +index 9259bab..e9d3774 100644 +--- a/tests/config_test/unit_config_test/dependency_001/check.sh ++++ b/tests/config_test/unit_config_test/dependency_001/check.sh +@@ -11,7 +11,7 @@ function test01() { + cp -arf "${work_dir}"/tmp_units/{conflicts.service,requires.service,wants.service,requisite.service,partof.service,bindsto.service} ${SYSMST_LIB_PATH} || return 1 + sctl daemon-reload + sctl status base.service &> log +- expect_eq $? 1 ++ expect_ne $? 0 + check_log log 'Failed to show the status of base.service: NotExisted' + expect_eq $? 0 || return 1 + rm -rf log +diff --git a/tests/config_test/unit_config_test/dependency_001/dependency_001.sh b/tests/config_test/unit_config_test/dependency_001/dependency_001.sh +index f29e2ee..393b4cd 100644 +--- a/tests/config_test/unit_config_test/dependency_001/dependency_001.sh ++++ b/tests/config_test/unit_config_test/dependency_001/dependency_001.sh +@@ -11,7 +11,6 @@ function test_pre() { + pushd "${TEST_SCRIPT_PATH}" + rm -rf tmp_units + mkdir tmp_units +- cp -arf "${TEST_PATH}"/test_units/{shutdown.target,sysinit.target} tmp_units + cp -arf "${TEST_PATH}"/test_units/tests/{base.service,conflicts.service,requires.service,wants.service,requisite.service,partof.service,bindsto.service} tmp_units + popd + } +diff --git a/tests/config_test/unit_config_test/dependency_002/dependency_002.sh b/tests/config_test/unit_config_test/dependency_002/dependency_002.sh +index b00be90..6f7758f 100644 +--- a/tests/config_test/unit_config_test/dependency_002/dependency_002.sh ++++ b/tests/config_test/unit_config_test/dependency_002/dependency_002.sh +@@ -11,7 +11,6 @@ function test_pre() { + pushd "${TEST_SCRIPT_PATH}" + rm -rf tmp_units + mkdir tmp_units +- cp -arf "${TEST_PATH}"/test_units/{shutdown.target,sysinit.target} tmp_units + cp -arf "${TEST_PATH}"/test_units/tests/base.service tmp_units + popd + } +diff --git a/tests/config_test/unit_config_test/dependency_003/dependency_003.sh b/tests/config_test/unit_config_test/dependency_003/dependency_003.sh +index f43d7f1..163b1d8 100644 +--- a/tests/config_test/unit_config_test/dependency_003/dependency_003.sh ++++ b/tests/config_test/unit_config_test/dependency_003/dependency_003.sh +@@ -11,7 +11,6 @@ function test_pre() { + pushd "${TEST_SCRIPT_PATH}" + rm -rf tmp_units + mkdir tmp_units +- cp -arf "${TEST_PATH}"/test_units/{shutdown.target,sysinit.target} tmp_units + cp -arf "${TEST_PATH}"/test_units/tests/base.service tmp_units + popd + } +diff --git a/tests/config_test/unit_config_test/dependency_004/dependency_004.sh b/tests/config_test/unit_config_test/dependency_004/dependency_004.sh +index a37b502..f11c8b5 100644 +--- a/tests/config_test/unit_config_test/dependency_004/dependency_004.sh ++++ b/tests/config_test/unit_config_test/dependency_004/dependency_004.sh +@@ -11,7 +11,6 @@ function test_pre() { + pushd "${TEST_SCRIPT_PATH}" + rm -rf tmp_units + mkdir tmp_units +- cp -arf "${TEST_PATH}"/test_units/{shutdown.target,sysinit.target} tmp_units + cp -arf "${TEST_PATH}"/test_units/tests/base.service tmp_units + popd + } +diff --git a/tests/config_test/unit_config_test/dependency_005/dependency_005.sh b/tests/config_test/unit_config_test/dependency_005/dependency_005.sh +index 01d76e8..6b71497 100644 +--- a/tests/config_test/unit_config_test/dependency_005/dependency_005.sh ++++ b/tests/config_test/unit_config_test/dependency_005/dependency_005.sh +@@ -11,7 +11,6 @@ function test_pre() { + pushd "${TEST_SCRIPT_PATH}" + rm -rf tmp_units + mkdir tmp_units +- cp -arf "${TEST_PATH}"/test_units/{shutdown.target,sysinit.target} tmp_units + cp -arf "${TEST_PATH}"/test_units/tests/{fork.service,before.service,after.service} tmp_units + popd + } +diff --git a/tests/config_test/unit_config_test/env_001/env_001.sh b/tests/config_test/unit_config_test/env_001/env_001.sh +index 9218e42..6e8f40b 100644 +--- a/tests/config_test/unit_config_test/env_001/env_001.sh ++++ b/tests/config_test/unit_config_test/env_001/env_001.sh +@@ -11,7 +11,6 @@ function test_pre() { + pushd "${TEST_SCRIPT_PATH}" + rm -rf tmp_units + mkdir tmp_units +- cp -arf "${TEST_PATH}"/test_units/{shutdown.target,sysinit.target} tmp_units + cp -arf "${TEST_PATH}"/test_units/tests/env.service tmp_units + popd + } +diff --git a/tests/config_test/unit_config_test/exec_001/exec_001.sh b/tests/config_test/unit_config_test/exec_001/exec_001.sh +index 666a154..90b3f74 100644 +--- a/tests/config_test/unit_config_test/exec_001/exec_001.sh ++++ b/tests/config_test/unit_config_test/exec_001/exec_001.sh +@@ -12,7 +12,6 @@ function test_pre() { + pushd "${TEST_SCRIPT_PATH}" + rm -rf tmp_units + mkdir tmp_units +- cp -arf "${TEST_PATH}"/test_units/{shutdown.target,sysinit.target} tmp_units + cp -arf "${TEST_PATH}"/test_units/tests/{base.service,exec.service} tmp_units + popd + } +diff --git a/tests/config_test/unit_config_test/isolate_001/isolate_001.sh b/tests/config_test/unit_config_test/isolate_001/isolate_001.sh +index 20bd545..8ee2127 100644 +--- a/tests/config_test/unit_config_test/isolate_001/isolate_001.sh ++++ b/tests/config_test/unit_config_test/isolate_001/isolate_001.sh +@@ -11,7 +11,6 @@ function test_pre() { + pushd "${TEST_SCRIPT_PATH}" + rm -rf tmp_units + mkdir tmp_units +- cp -arf "${TEST_PATH}"/test_units/{shutdown.target,sysinit.target} tmp_units + cp -arf "${TEST_PATH}"/test_units/tests/{base.service,reboot.target} tmp_units + popd + } +diff --git a/tests/config_test/unit_config_test/kill_001/kill_001.sh b/tests/config_test/unit_config_test/kill_001/kill_001.sh +index 259fa03..c781f80 100644 +--- a/tests/config_test/unit_config_test/kill_001/kill_001.sh ++++ b/tests/config_test/unit_config_test/kill_001/kill_001.sh +@@ -11,7 +11,6 @@ function test_pre() { + pushd "${TEST_SCRIPT_PATH}" + rm -rf tmp_units + mkdir tmp_units +- cp -arf "${TEST_PATH}"/test_units/{shutdown.target,sysinit.target} tmp_units + cp -arf "${TEST_PATH}"/test_units/tests/fork.service tmp_units + gcc kill_mode.c -o kill_mode + popd +diff --git a/tests/config_test/unit_config_test/listen_001/check.sh b/tests/config_test/unit_config_test/listen_001/check.sh +index 8891f99..c124a38 100644 +--- a/tests/config_test/unit_config_test/listen_001/check.sh ++++ b/tests/config_test/unit_config_test/listen_001/check.sh +@@ -222,7 +222,7 @@ seed="1$((${RANDOM} % 1000))" + test01_socket="/run/test01_${seed}.socket" + test02_socket="/run/test02_${seed}.socket" + test03_socket="/run/test03_${seed}.socket" +-install_pkg net-tools iproute || exit 1 ++yum install -y net-tools iproute || exit 1 + + run_sysmaster || return 1 + test01 || exit 1 +diff --git a/tests/config_test/unit_config_test/listen_001/listen_001.sh b/tests/config_test/unit_config_test/listen_001/listen_001.sh +index c3f9f53..3539237 100644 +--- a/tests/config_test/unit_config_test/listen_001/listen_001.sh ++++ b/tests/config_test/unit_config_test/listen_001/listen_001.sh +@@ -11,7 +11,6 @@ function test_pre() { + pushd "${TEST_SCRIPT_PATH}" + rm -rf tmp_units + mkdir tmp_units +- cp -arf "${TEST_PATH}"/test_units/{shutdown.target,sysinit.target} tmp_units + cp -arf "${TEST_PATH}"/test_units/tests/{base.service,base.socket} tmp_units + popd + } +diff --git a/tests/config_test/unit_config_test/refuse_001/refuse_001.sh b/tests/config_test/unit_config_test/refuse_001/refuse_001.sh +index b43fae6..6157436 100644 +--- a/tests/config_test/unit_config_test/refuse_001/refuse_001.sh ++++ b/tests/config_test/unit_config_test/refuse_001/refuse_001.sh +@@ -11,7 +11,6 @@ function test_pre() { + pushd "${TEST_SCRIPT_PATH}" + rm -rf tmp_units + mkdir tmp_units +- cp -arf "${TEST_PATH}"/test_units/{shutdown.target,sysinit.target} tmp_units + cp -arf "${TEST_PATH}"/test_units/tests/{base.service,requires.service} tmp_units + popd + } +diff --git a/tests/config_test/unit_config_test/restart_001/restart_001.sh b/tests/config_test/unit_config_test/restart_001/restart_001.sh +index 93d1217..5dd1143 100644 +--- a/tests/config_test/unit_config_test/restart_001/restart_001.sh ++++ b/tests/config_test/unit_config_test/restart_001/restart_001.sh +@@ -11,7 +11,6 @@ function test_pre() { + pushd "${TEST_SCRIPT_PATH}" + rm -rf tmp_units + mkdir tmp_units +- cp -arf "${TEST_PATH}"/test_units/{shutdown.target,sysinit.target} tmp_units + cp -arf "${TEST_PATH}"/test_units/tests/{restart_001.service,restart_002.service,restart_003.service,restart_004.service} tmp_units + popd + } +diff --git a/tests/config_test/unit_config_test/service_001/service_001.sh b/tests/config_test/unit_config_test/service_001/service_001.sh +index da79e9c..1aac45f 100644 +--- a/tests/config_test/unit_config_test/service_001/service_001.sh ++++ b/tests/config_test/unit_config_test/service_001/service_001.sh +@@ -11,7 +11,6 @@ function test_pre() { + pushd "${TEST_SCRIPT_PATH}" + rm -rf tmp_units + mkdir tmp_units +- cp -arf "${TEST_PATH}"/test_units/{shutdown.target,sysinit.target} tmp_units + cp -arf "${TEST_PATH}"/test_units/tests/base.service tmp_units + popd + } +diff --git a/tests/config_test/unit_config_test/service_002/service_002.sh b/tests/config_test/unit_config_test/service_002/service_002.sh +index 5cf3d49..6ae0624 100644 +--- a/tests/config_test/unit_config_test/service_002/service_002.sh ++++ b/tests/config_test/unit_config_test/service_002/service_002.sh +@@ -11,7 +11,6 @@ function test_pre() { + pushd "${TEST_SCRIPT_PATH}" + rm -rf tmp_units + mkdir tmp_units +- cp -arf "${TEST_PATH}"/test_units/{shutdown.target,sysinit.target} tmp_units + cp -arf "${TEST_PATH}"/test_units/tests/fork.service tmp_units + gcc fork_exec.c -o fork_exec + popd +diff --git a/tests/config_test/unit_config_test/service_003/service_003.sh b/tests/config_test/unit_config_test/service_003/service_003.sh +index ccf6200..6c4fdd6 100644 +--- a/tests/config_test/unit_config_test/service_003/service_003.sh ++++ b/tests/config_test/unit_config_test/service_003/service_003.sh +@@ -11,7 +11,6 @@ function test_pre() { + pushd "${TEST_SCRIPT_PATH}" + rm -rf tmp_units + mkdir tmp_units +- cp -arf "${TEST_PATH}"/test_units/{shutdown.target,sysinit.target} tmp_units + cp -arf "${TEST_PATH}"/test_units/tests/{base.service,base.socket} tmp_units + popd + } +diff --git a/tests/config_test/unit_config_test/service_004/check.sh b/tests/config_test/unit_config_test/service_004/check.sh +index 387121f..7effdb4 100644 +--- a/tests/config_test/unit_config_test/service_004/check.sh ++++ b/tests/config_test/unit_config_test/service_004/check.sh +@@ -34,7 +34,7 @@ function test01() { + expect_eq $? 0 || return 1 + + # user/group exist +- install_pkg shadow ++ yum install -y shadow + expect_eq $? 0 || return 1 + useradd "${test_user}" + groupadd "${test_grp}" +diff --git a/tests/config_test/unit_config_test/service_004/service_004.sh b/tests/config_test/unit_config_test/service_004/service_004.sh +index 418f389..b2a8398 100644 +--- a/tests/config_test/unit_config_test/service_004/service_004.sh ++++ b/tests/config_test/unit_config_test/service_004/service_004.sh +@@ -11,7 +11,6 @@ function test_pre() { + pushd "${TEST_SCRIPT_PATH}" + rm -rf tmp_units + mkdir tmp_units +- cp -arf "${TEST_PATH}"/test_units/{shutdown.target,sysinit.target} tmp_units + cp -arf "${TEST_PATH}"/test_units/tests/base.service tmp_units + popd + } +diff --git a/tests/config_test/unit_config_test/socket_001/check.sh b/tests/config_test/unit_config_test/socket_001/check.sh +index e055532..9f28604 100644 +--- a/tests/config_test/unit_config_test/socket_001/check.sh ++++ b/tests/config_test/unit_config_test/socket_001/check.sh +@@ -125,7 +125,7 @@ function test03() { + seed="1$((${RANDOM} % 1000))" + test_socket="/run/test_${seed}.socket" + test_symlink="/dev/test_${seed}_link" +-install_pkg net-tools nmap || exit 1 ++yum install -y net-tools nmap || exit 1 + + run_sysmaster || exit 1 + test01 || exit 1 +diff --git a/tests/config_test/unit_config_test/socket_001/socket_001.sh b/tests/config_test/unit_config_test/socket_001/socket_001.sh +index f3efb17..6fd74a3 100644 +--- a/tests/config_test/unit_config_test/socket_001/socket_001.sh ++++ b/tests/config_test/unit_config_test/socket_001/socket_001.sh +@@ -11,7 +11,6 @@ function test_pre() { + pushd "${TEST_SCRIPT_PATH}" + rm -rf tmp_units + mkdir tmp_units +- cp -arf "${TEST_PATH}"/test_units/{shutdown.target,sysinit.target} tmp_units + cp -arf "${TEST_PATH}"/test_units/tests/{base.service,base.socket} tmp_units + popd + } +diff --git a/tests/config_test/unit_config_test/startlimit_001/startlimit_001.sh b/tests/config_test/unit_config_test/startlimit_001/startlimit_001.sh +index bd037e2..fc93149 100644 +--- a/tests/config_test/unit_config_test/startlimit_001/startlimit_001.sh ++++ b/tests/config_test/unit_config_test/startlimit_001/startlimit_001.sh +@@ -11,7 +11,6 @@ function test_pre() { + pushd "${TEST_SCRIPT_PATH}" + rm -rf tmp_units + mkdir tmp_units +- cp -arf "${TEST_PATH}"/test_units/{shutdown.target,sysinit.target} tmp_units + cp -arf "${TEST_PATH}"/test_units/tests/base.service tmp_units + cp -arf "${TEST_PATH}"/test_units/tests/{reboot.target,poweroff.target,exit.target} tmp_units + popd +diff --git a/tests/config_test/unit_config_test/timeout_001/timeout_001.sh b/tests/config_test/unit_config_test/timeout_001/timeout_001.sh +index df2f52f..08d4512 100644 +--- a/tests/config_test/unit_config_test/timeout_001/timeout_001.sh ++++ b/tests/config_test/unit_config_test/timeout_001/timeout_001.sh +@@ -11,7 +11,6 @@ function test_pre() { + pushd "${TEST_SCRIPT_PATH}" + rm -rf tmp_units + mkdir tmp_units +- cp -arf "${TEST_PATH}"/test_units/{shutdown.target,sysinit.target} tmp_units + cp -arf "${TEST_PATH}"/test_units/tests/base.service tmp_units + cp -arf "${TEST_PATH}"/test_units/tests/{reboot.target,poweroff.target,exit.target} tmp_units + popd +diff --git a/tests/config_test/unit_config_test/timeout_002/timeout_002.sh b/tests/config_test/unit_config_test/timeout_002/timeout_002.sh +index 9cfb2a5..9ccf3c7 100644 +--- a/tests/config_test/unit_config_test/timeout_002/timeout_002.sh ++++ b/tests/config_test/unit_config_test/timeout_002/timeout_002.sh +@@ -11,7 +11,6 @@ function test_pre() { + pushd "${TEST_SCRIPT_PATH}" + rm -rf tmp_units + mkdir tmp_units +- cp -arf "${TEST_PATH}"/test_units/{shutdown.target,sysinit.target} tmp_units + cp -arf "${TEST_PATH}"/test_units/tests/timeout.service tmp_units + popd + } +diff --git a/tests/docker_example/docker_example_001/check.sh b/tests/docker_example/docker_example_001/check.sh +index 3db7629..3d89207 100755 +--- a/tests/docker_example/docker_example_001/check.sh ++++ b/tests/docker_example/docker_example_001/check.sh +@@ -1,3 +1,4 @@ ++#!/usr/bin/env bash ++ + ls -l /usr/lib/sysmaster || exit 1 +-ls -l /usr/lib/sysmaster/plugin || exit 1 + ls -l /usr/bin/sctl || exit 1 +diff --git a/tests/perf_test/cpu_time_001/check.sh b/tests/perf_test/cpu_time_001/check.sh +index a6e16a1..26f1dfd 100644 +--- a/tests/perf_test/cpu_time_001/check.sh ++++ b/tests/perf_test/cpu_time_001/check.sh +@@ -6,7 +6,7 @@ source "${work_dir}"/util_lib.sh + set +e + max=1000 + +-install_pkg nginx ++yum install -y nginx + expect_eq $? 0 || exit 1 + + cp -arf "${work_dir}"/tmp_units/*.service ${SYSMST_LIB_PATH} || exit 1 +diff --git a/tests/test_frame.sh b/tests/test_frame.sh +index e2eab7d..c734feb 100644 +--- a/tests/test_frame.sh ++++ b/tests/test_frame.sh +@@ -12,7 +12,9 @@ TMP_DIR='' + function test_setup() { + setenforce 0 + +- install_sysmaster || return 1 ++ if ! yum list sysmaster; then ++ install_sysmaster || return 1 ++ fi + + if [ "${DOCKER_TEST}" == '1' ]; then + if which isula-build; then +@@ -57,9 +59,8 @@ function setup_isula() { + + function test_cleanup() { + [ -n "${TMP_DIR}" ] && rm -rf "${TMP_DIR}" +- rm -rf /usr/bin/sctl "${SYSMST_LIB_PATH}" + +- if [ "${DOCKER_TEST}" == '1' ]; then ++ if [ "${DOCKER_TEST}" == '1' ] && [ -n "${DOCKER_CMD}" ]; then + cleanup_docker || return 1 + fi + +-- +2.33.0 + diff --git a/backport-typo-declure-declare.patch b/backport-typo-declure-declare.patch new file mode 100644 index 0000000..f8dcd98 --- /dev/null +++ b/backport-typo-declure-declare.patch @@ -0,0 +1,125 @@ +From fbfa5543837c69c47c88e6a1c2ed5bbd3d4112f4 Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Wed, 28 Jun 2023 16:43:04 +0800 +Subject: [PATCH] typo: declure -> declare + +--- + coms/service/src/manager.rs | 4 ++-- + coms/service/src/unit.rs | 4 ++-- + coms/target/src/manager.rs | 4 ++-- + coms/target/src/unit.rs | 4 ++-- + core/bin/plugin/mod.rs | 8 ++++---- + core/lib/unit/base.rs | 2 +- + core/lib/unit/umif.rs | 2 +- + 12 files changed, 24 insertions(+), 24 deletions(-) + +diff --git a/coms/service/src/manager.rs b/coms/service/src/manager.rs +index ebcab59..026f710 100644 +--- a/coms/service/src/manager.rs ++++ b/coms/service/src/manager.rs +@@ -60,5 +60,5 @@ impl Default for ServiceManager { + } + } + +-use sysmaster::declure_umobj_plugin; +-declure_umobj_plugin!(ServiceManager, ServiceManager::default, PLUGIN_NAME); ++use sysmaster::declare_umobj_plugin; ++declare_umobj_plugin!(ServiceManager, ServiceManager::default, PLUGIN_NAME); +diff --git a/coms/service/src/unit.rs b/coms/service/src/unit.rs +index 2a217d4..4bb235e 100644 +--- a/coms/service/src/unit.rs ++++ b/coms/service/src/unit.rs +@@ -411,5 +411,5 @@ impl ServiceUnit { + } + }*/ + +-use sysmaster::declure_unitobj_plugin_with_param; +-declure_unitobj_plugin_with_param!(ServiceUnit, ServiceUnit::new); ++use sysmaster::declare_unitobj_plugin_with_param; ++declare_unitobj_plugin_with_param!(ServiceUnit, ServiceUnit::new); +diff --git a/coms/target/src/manager.rs b/coms/target/src/manager.rs +index e3c3975..832037c 100644 +--- a/coms/target/src/manager.rs ++++ b/coms/target/src/manager.rs +@@ -53,5 +53,5 @@ impl UnitMngUtil for TargetManager { + } + } + +-use sysmaster::declure_umobj_plugin; +-declure_umobj_plugin!(TargetManager, TargetManager::new, PLUGIN_NAME); ++use sysmaster::declare_umobj_plugin; ++declare_umobj_plugin!(TargetManager, TargetManager::new, PLUGIN_NAME); +diff --git a/coms/target/src/unit.rs b/coms/target/src/unit.rs +index bcd97c7..4914eec 100644 +--- a/coms/target/src/unit.rs ++++ b/coms/target/src/unit.rs +@@ -190,5 +190,5 @@ impl UnitMngUtil for Target { + } + }*/ + +-use sysmaster::declure_unitobj_plugin_with_param; +-declure_unitobj_plugin_with_param!(Target, Target::new); ++use sysmaster::declare_unitobj_plugin_with_param; ++declare_unitobj_plugin_with_param!(Target, Target::new); +diff --git a/core/bin/plugin/mod.rs b/core/bin/plugin/mod.rs +index 869f360..9a8e4f6 100644 +--- a/core/bin/plugin/mod.rs ++++ b/core/bin/plugin/mod.rs +@@ -34,8 +34,8 @@ + //! ```macro_rules + //! const LOG_LEVEL: u32 = 4; + //! const PLUGIN_NAME: &str = "TargetUnit"; +-//! use sysmaster::declure_unitobj_plugin; +-//! declure_unitobj_plugin!(Target, Target::default, PLUGIN_NAME, LOG_LEVEL); ++//! use sysmaster::declare_unitobj_plugin; ++//! declare_unitobj_plugin!(Target, Target::default, PLUGIN_NAME, LOG_LEVEL); + //! ```` + //! plugin or find the corresponding so according to the name of the corresponding unit configuration file, and load it dynamically, such as XXX.service to find libservice.so, XXX.socket to find libsocket.so + //! +@@ -435,7 +435,7 @@ impl Plugin { + } + + /// Create the subunit trait of unit +- /// each sub unit need reference of declure_unitobj_plugin_with_param ++ /// each sub unit need reference of declare_unitobj_plugin_with_param + /// + pub fn create_subunit_with_um( + &self, +@@ -474,7 +474,7 @@ impl Plugin { + Ok(unsafe { Box::from_raw(boxed_raw) }) + } + /// Create a obj for subclasses of unit manager +- /// each sub unit manager need reference of declure_umobj_plugin ++ /// each sub unit manager need reference of declare_umobj_plugin + pub fn create_um_obj( + &self, + unit_type: UnitType, +diff --git a/core/lib/unit/base.rs b/core/lib/unit/base.rs +index 20f8c91..5550252 100644 +--- a/core/lib/unit/base.rs ++++ b/core/lib/unit/base.rs +@@ -172,7 +172,7 @@ pub trait SubUnit: ReStation + UnitMngUtil { + /// the macro for create a sub unit instance with dyn ref of UmIf, + /// which sub unit wants invoke um interface, about UmIf see doc of UmIf + #[macro_export] +-macro_rules! declure_unitobj_plugin_with_param { ++macro_rules! declare_unitobj_plugin_with_param { + ($unit_type:ty, $constructor:path) => { + use log::LevelFilter; + /// method for create the unit instance +diff --git a/core/lib/unit/umif.rs b/core/lib/unit/umif.rs +index 18616f5..85603fa 100644 +--- a/core/lib/unit/umif.rs ++++ b/core/lib/unit/umif.rs +@@ -222,7 +222,7 @@ pub trait UnitManagerObj: UnitMngUtil + ReStation { + /// #[macro_use] + /// the macro for create a sub unit-manager instance + #[macro_export] +-macro_rules! declure_umobj_plugin { ++macro_rules! declare_umobj_plugin { + ($unit_type:ty, $constructor:path, $name:expr) => { + // method for create the sub-unit-manager instance + use log::LevelFilter; +-- +2.33.0 + diff --git a/backport-typo-fix-clippies.patch b/backport-typo-fix-clippies.patch new file mode 100644 index 0000000..c9a7baa --- /dev/null +++ b/backport-typo-fix-clippies.patch @@ -0,0 +1,33 @@ +From 36331ec407f541f6209f270bfc0ffc2eb55836f3 Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Wed, 28 Jun 2023 16:58:40 +0800 +Subject: [PATCH] typo: fix clippies + +--- + libs/basic/src/logger.rs | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/libs/basic/src/logger.rs b/libs/basic/src/logger.rs +index 8ee3ffa..3161513 100644 +--- a/libs/basic/src/logger.rs ++++ b/libs/basic/src/logger.rs +@@ -207,7 +207,7 @@ impl log::Log for FileLogger { + + impl FileLogger { + fn file_open(file_path: &PathBuf, file_mode: u32) -> File { +- /* Panic if we cann't open a log file. */ ++ /* Panic if we can't open a log file. */ + let dir = file_path.parent().unwrap(); + if !dir.exists() { + fs::create_dir_all(dir).unwrap(); +@@ -480,7 +480,6 @@ pub fn init_log( + file_number, + ))); + log::set_max_level(level); +- return; + } + } + +-- +2.33.0 + diff --git a/backport-typo-fix-some-clippy.patch b/backport-typo-fix-some-clippy.patch new file mode 100644 index 0000000..c5f5a15 --- /dev/null +++ b/backport-typo-fix-some-clippy.patch @@ -0,0 +1,41 @@ +From 4b130fc57ccdc556ca5cb48eac6a54efae65de3d Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Tue, 27 Jun 2023 20:38:48 +0800 +Subject: [PATCH] typo: fix some clippy + +--- + libs/basic/src/logger.rs | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/libs/basic/src/logger.rs b/libs/basic/src/logger.rs +index 3bf579b..06f4ff2 100644 +--- a/libs/basic/src/logger.rs ++++ b/libs/basic/src/logger.rs +@@ -201,7 +201,6 @@ impl FileLogger { + /* 3. Write message */ + if let Err(e) = file.write((msg + "\n").as_bytes()) { + println!("Failed to log message: {e}"); +- return; + } + } + +@@ -235,13 +234,13 @@ impl FileLogger { + num_list.push(rotated_num); + } + +- num_list.sort(); ++ num_list.sort_unstable(); + + /* 1. delete surplus rotated file */ + /* We only keep (file_number - 1) rotated files, because we will generate a new one later. */ + let file_number = self.file_number as usize; +- for i in file_number - 1..num_list.len() { +- let src = String::from(&file_name_dot) + &num_list[i].to_string(); ++ for rotated_num in num_list.iter().skip(file_number - 1) { ++ let src = String::from(&file_name_dot) + &rotated_num.to_string(); + Self::mv_file_in_dir(&src, None, dir); + } + +-- +2.33.0 + diff --git a/backport-typo-fix-some-debugging-messages-and-typoes.patch b/backport-typo-fix-some-debugging-messages-and-typoes.patch new file mode 100644 index 0000000..d1b0c92 --- /dev/null +++ b/backport-typo-fix-some-debugging-messages-and-typoes.patch @@ -0,0 +1,51 @@ +From 7dc67f1bac0dcdd84a5a7eeb2b220ea70f17b3cf Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Sun, 25 Jun 2023 15:34:33 +0800 +Subject: [PATCH] typo: fix some debugging messages and typoes + +--- + core/bin/plugin/mod.rs | 7 ++----- + libs/basic/src/logger.rs | 2 +- + 3 files changed, 4 insertions(+), 9 deletions(-) + +diff --git a/core/bin/plugin/mod.rs b/core/bin/plugin/mod.rs +index 69bf8b8..869f360 100644 +--- a/core/bin/plugin/mod.rs ++++ b/core/bin/plugin/mod.rs +@@ -309,7 +309,7 @@ impl Plugin { + }; + + /* We need the lib*.so pass SubUnit and UnitManagerObj to sysmaster-core, and we check if +- * subunit_create_with_params and um_obj_create exists in lib*.so, because these two funs ++ * subunit_create_with_params and um_obj_create exist in lib*.so, because these two functions + * will be used to generate SubUnit and UnitManagerObj. */ + + type FnTypeSubUnit = fn(um: Rc) -> *mut dyn SubUnit; +@@ -469,10 +469,7 @@ impl Plugin { + Ok(v) => v, + }; + +- log::debug!( +- "create unit obj with param level filter: {:?}", +- log::max_level() +- ); ++ log::debug!("create unit obj with params"); + let boxed_raw = fun(um.clone()); + Ok(unsafe { Box::from_raw(boxed_raw) }) + } +diff --git a/libs/basic/src/logger.rs b/libs/basic/src/logger.rs +index 0bc15bb..56def43 100644 +--- a/libs/basic/src/logger.rs ++++ b/libs/basic/src/logger.rs +@@ -207,7 +207,7 @@ fn build_log_config( + .build(), + ), + "file" => { +- let pattern = file_path.to_string() + &".{}"; ++ let pattern = file_path.to_string() + ".{}"; + let policy = Box::new(CompoundPolicy::new( + Box::new(SizeTrigger::new(file_size as u64 * 1024)), + Box::new( +-- +2.33.0 + diff --git a/backport-typo-fix-some-typoes.patch b/backport-typo-fix-some-typoes.patch new file mode 100644 index 0000000..330244d --- /dev/null +++ b/backport-typo-fix-some-typoes.patch @@ -0,0 +1,39 @@ +From a244377c9a485d252da1cca7c5ba61e4915f7236 Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Fri, 30 Jun 2023 11:29:56 +0800 +Subject: [PATCH] typo: fix some typoes + +--- + libs/basic/src/condition.rs | 2 +- + libs/libtests/src/lib.rs | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/libs/basic/src/condition.rs b/libs/basic/src/condition.rs +index b9743f3..ccdb6ff 100644 +--- a/libs/basic/src/condition.rs ++++ b/libs/basic/src/condition.rs +@@ -440,7 +440,7 @@ mod test { + + #[test] + fn test_condition_test() { +- logger::init_log_to_console("test_init_lookup_paths", log::LevelFilter::Debug); ++ logger::init_log_to_console("test_condition", log::LevelFilter::Debug); + let project_root = get_project_root().unwrap(); + let cond_path_not_exists = Condition::new( + ConditionType::PathExists, +diff --git a/libs/libtests/src/lib.rs b/libs/libtests/src/lib.rs +index 9380dc2..260d7f8 100644 +--- a/libs/libtests/src/lib.rs ++++ b/libs/libtests/src/lib.rs +@@ -45,7 +45,7 @@ mod tests { + use crate::{get_crate_root, get_project_root}; + + #[test] +- fn test_get_projecgt_root() { ++ fn test_get_project_root() { + let mut file_path = get_project_root().unwrap(); + file_path.push("tests/test_units/config.service.toml"); + +-- +2.33.0 + diff --git a/plugin.conf-delete-Socket-and-Mount.patch b/plugin.conf-delete-Socket-and-Mount.patch new file mode 100644 index 0000000..f6c3c31 --- /dev/null +++ b/plugin.conf-delete-Socket-and-Mount.patch @@ -0,0 +1,21 @@ +From f4a9ace1a685aa5ab376ad471eab079e45ab4abd Mon Sep 17 00:00:00 2001 +From: huyubiao +Date: Tue, 25 Jul 2023 11:49:40 +0800 +Subject: [PATCH] plugin.conf delete Socket and Mount + +--- + config/conf/plugin.conf | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/config/conf/plugin.conf b/config/conf/plugin.conf +index e17066d..0a6c31b 100644 +--- a/config/conf/plugin.conf ++++ b/config/conf/plugin.conf +@@ -1,4 +1,2 @@ + Service:libservice + Target:libtarget +-Socket:libsocket +-Mount:libmount +-- +2.33.0 + diff --git a/sysmaster.spec b/sysmaster.spec index 3708239..ba4faae 100644 --- a/sysmaster.spec +++ b/sysmaster.spec @@ -11,14 +11,78 @@ Name: sysmaster Version: 0.2.4 -Release: 4 +Release: 5 Summary: redesign and reimplement process1. License: Mulan PSL v2 URL: https://gitee.com/openeuler/sysmaster Source0: %{name}-%{version}.tar.gz -Patch0001: backport-fix-modify-units-for-sctl-enable.patch +Patch0001: backport-fix-make-test_cgroup-really-work.patch +Patch0002: backport-fix-several-socket-fixes.patch +Patch0003: backport-fix-libbasic-create-relative-symlink-in-right-way.patch +Patch0004: backport-feature-libbasic-add-path_simplify.patch +Patch0005: backport-feature-libbasic-add-remove_dir_until.patch +Patch0006: backport-feature-libbasic-add-opendirat.patch +Patch0007: backport-feature-libbasic-add-more-error-information.patch +Patch0008: backport-fix-libbasic-create-symlink-atomically.patch +Patch0009: backport-fix-init-uses-SIGABRT-to-reexec-sysmaster-increase-s.patch +Patch0010: backport-feature-support-hostname-setup.patch +Patch0011: backport-fix-libbasic-try-to-follow-the-fd-path-to-make-the-u.patch +Patch0012: backport-fix-modify-units-for-sctl-enable.patch +Patch0013: backport-fix-devmaster-deal-with-fd-leak.patch +Patch0014: backport-feature-add-LogFileSize-and-LogFileNumber.patch +Patch0015: backport-feature-use-LogFileSize-and-LogFileNumber-to-rotate-.patch +Patch0016: backport-fix-rename-create_unit_obj_with_um-to-create_subunit.patch +Patch0017: backport-fix-remove-unit_obj_create_default-we-never-use-it.patch +Patch0018: backport-typo-fix-some-debugging-messages-and-typoes.patch +Patch0019: backport-feature-use-our-own-file-logger.patch +Patch0020: backport-typo-fix-some-clippy.patch +Patch0021: backport-refactor-move-UmIf-functions-no-functional-change.patch +Patch0022: backport-fix-several-fixes-on-logger.patch +Patch0023: backport-typo-declure-declare.patch +Patch0024: backport-fix-add-default-system.toml.patch +Patch0025: backport-typo-fix-clippies.patch +Patch0026: backport-fix-use-var-log-sysmaster-sysmaster.log-to-save-log-.patch +Patch0027: backport-fix-use-localtime-instead-of-UTC.patch +Patch0028: backport-refactor-mv-system.toml-to-config-conf.patch +Patch0029: backport-fix-ignore-auto-generated-toml-file-in-tests-test_un.patch +Patch0030: backport-fix-version-0.3.10-may-fail-to-build-when-use-tuna-s.patch +Patch0031: backport-fix-we-shouldn-t-lookup-build-directory-if-we-are-no.patch +Patch0032: backport-fix-avoid-calling-init_lookup_paths-in-testcase.patch +Patch0033: backport-typo-fix-some-typoes.patch +Patch0034: backport-fix-use-UnixStream-to-test-send_and_recv.patch +Patch0035: backport-fix-make-config.service.toml-same-as-config.service.patch +Patch0036: backport-fix-init-does-not-enter-the-freeze-during-normal-run.patch +Patch0037: backport-refactor-don-t-copy-unit-file-to-.toml-file-when-loa.patch +Patch0038: backport-fix-rename-config.service.toml-to-config.service.patch +Patch0039: backport-fix-rename-system.toml-to-system.conf.patch +Patch0040: backport-feature-devmaster-support-update-device-database-and.patch +Patch0041: backport-build-update-version-to-0.2.4.patch +Patch0042: backport-build-To-adjust-the-directory-structure.patch +Patch0043: backport-fix-log-message-before-and-after-reaping-zombie-proc.patch +Patch0044: backport-fix-log-message-when-creating-symlink.patch +Patch0045: backport-fix-add-two-helper-macroes-to-help-us-log-message-ou.patch +Patch0046: backport-fix-log-message-out-when-we-create-delete-a-file-or-.patch +Patch0047: backport-fix-call-clear_last_frame-before-early-return.patch +Patch0048: backport-fix-init-recyle-zombie-process-normally-corrects-doc.patch +Patch0049: backport-fix-adjust-the-mode-of-internal-generated-files.patch +Patch0050: backport-fix-simply-code-a-bit-delete-an-annoying-log-and-don.patch +Patch0051: backport-test-support-yum-install-sysmaster.patch +Patch0052: backport-fix-set-the-notify-socket-receive-buffer-to-8M.patch +Patch0053: backport-fix-make-the-help-information-clearer.patch +Patch0054: backport-test-add-UT-testcase-for-command-dispatch.patch +Patch0055: backport-fix-isolate-debugging-code-through-configuration-pre.patch +Patch0056: backport-fix-integer-overflow.patch +Patch0057: backport-test-condition-add-unit-test-for-condition.patch +Patch0058: backport-fix-check-if-the-words-is-empty-before-using-it.patch +Patch0059: backport-fix-check-if-the-message-is-truncated.patch +Patch0060: backport-fix-fix-the-type-error-of-test_get_service_type.patch +Patch0061: backport-fix-specify-the-version-of-tempfile.patch +Patch0062: backport-fix-add-two-helper-function-to-check-if-the-path-nam.patch +Patch0063: backport-fix-downgrade-the-time-crate-from-0.3.x-to-0.1.45.patch + +Patch9001: plugin.conf-delete-Socket-and-Mount.patch ExclusiveArch: x86_64 aarch64 @@ -49,35 +113,46 @@ sed -i '/\[build\]/arustflags = \["-C", "target-feature=-crt-static", "-C", "lin %{_cargo_build} --profile release %install +# For binary files and .so files, the permission 750 in the install phase to prevent objcopy errors. +# In the files phase, the permission is set back to 550. install -Dm0750 -t %{buildroot}/usr/bin %{sysmaster_install_source}/sctl install -Dm0750 -t %{sysmaster_install_target} %{sysmaster_install_source}/init install -Dm0750 -t %{sysmaster_install_target} %{sysmaster_install_source}/sysmaster -install -Dm0640 -t %{sysmaster_install_target} %{unit_install_source}/* +install -Dm0640 -t %{sysmaster_install_target}/system %{unit_install_source}/* install -Dm0750 -t %{sysmaster_install_target}/plugin %{sysmaster_install_source}/libservice.so install -Dm0750 -t %{sysmaster_install_target}/plugin %{sysmaster_install_source}/libtarget.so install -Dm0640 -t %{sysmaster_install_target}/plugin %{conf_install_source}/plugin.conf +install -Dm0640 -t %{buildroot}/etc/sysmaster %{conf_install_source}/system.conf %files %attr(0550,-,-) /usr/bin/sctl -%dir /usr/lib/sysmaster -/usr/lib/sysmaster/basic.target +%dir %attr(0550,-,-) /usr/lib/sysmaster +%dir %attr(0750,-,-) /usr/lib/sysmaster/system +/usr/lib/sysmaster/system/basic.target %attr(0550,-,-) /usr/lib/sysmaster/init -/usr/lib/sysmaster/multi-user.target -%dir /usr/lib/sysmaster/plugin +/usr/lib/sysmaster/system/multi-user.target +%dir %attr(0550,-,-) /usr/lib/sysmaster/plugin %attr(0550,-,-) /usr/lib/sysmaster/plugin/*.so /usr/lib/sysmaster/plugin/plugin.conf -/usr/lib/sysmaster/shutdown.target -/usr/lib/sysmaster/sshd-keygen.target -/usr/lib/sysmaster/sshd-keygen@ecdsa.service -/usr/lib/sysmaster/sshd-keygen@ed25519.service -/usr/lib/sysmaster/sshd-keygen@rsa.service -/usr/lib/sysmaster/sshd.service -/usr/lib/sysmaster/sysinit.target +/usr/lib/sysmaster/system/shutdown.target +/usr/lib/sysmaster/system/sshd-keygen.target +/usr/lib/sysmaster/system/sshd-keygen@ecdsa.service +/usr/lib/sysmaster/system/sshd-keygen@ed25519.service +/usr/lib/sysmaster/system/sshd-keygen@rsa.service +/usr/lib/sysmaster/system/sshd.service +/usr/lib/sysmaster/system/sysinit.target %attr(0550,-,-) /usr/lib/sysmaster/sysmaster +%dir %attr(0750,-,-) /etc/sysmaster +/etc/sysmaster/system.conf %changelog +* Thu Jul 27 2023 huyubiao - 0.2.4-5 +- sync patches from upstream, + change the path of the unit, + modify permissions for some directories and files + * Wed Jul 19 2023 shenyangyang - 0.2.4-4 - add compile option