machinery-tool 1.17.0 → 1.18.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.git_revision +1 -1
- data/NEWS +17 -1
- data/bin/machinery +1 -1
- data/export_helpers/merge_users_and_groups.pl.erb +1 -1
- data/html/comparison.html.haml +14 -9
- data/html/index.html.haml +5 -2
- data/html/landing_page.html.haml +4 -1
- data/html/partials/changed_managed_files.html.haml +2 -0
- data/html/partials/compare/alert.html.haml +1 -1
- data/html/partials/compare/unmanaged_file_list.html.haml +12 -0
- data/html/partials/config_files.html.haml +2 -0
- data/html/partials/landing_page/alert.html.haml +1 -1
- data/html/partials/unmanaged_files.html.haml +14 -0
- data/inspect_helpers/changed_files.sh +1 -1
- data/inspect_helpers/dpkg_unmanaged_files.sh +1 -1
- data/inspect_helpers/yum_repositories.py +1 -1
- data/lib/analyze_config_file_diffs_task.rb +1 -1
- data/lib/array.rb +1 -1
- data/lib/autoyast.rb +34 -34
- data/lib/build_task.rb +1 -1
- data/lib/cli.rb +21 -6
- data/lib/compare_task.rb +1 -1
- data/lib/comparison.rb +1 -1
- data/lib/config.rb +1 -1
- data/lib/config_base.rb +1 -1
- data/lib/config_task.rb +1 -1
- data/lib/constants.rb +2 -2
- data/lib/containerize_task.rb +1 -1
- data/lib/containerized_app.rb +1 -1
- data/lib/copy_task.rb +1 -1
- data/lib/current_user.rb +1 -1
- data/lib/deploy_task.rb +1 -1
- data/lib/docker_system.rb +4 -5
- data/lib/dpkg_database.rb +2 -2
- data/lib/element_filter.rb +1 -1
- data/lib/exceptions.rb +2 -2
- data/lib/export_task.rb +1 -1
- data/lib/exporter.rb +1 -1
- data/lib/file_diff.rb +1 -1
- data/lib/file_scope.rb +1 -1
- data/lib/file_validator.rb +1 -1
- data/lib/filter.rb +1 -1
- data/lib/filter_option_parser.rb +1 -1
- data/lib/helper.rb +1 -1
- data/lib/hint.rb +1 -1
- data/lib/html.rb +1 -1
- data/lib/inspect_task.rb +1 -1
- data/lib/inspector.rb +1 -1
- data/lib/json_schema_monkey_patch.rb +35 -0
- data/lib/json_validation_error_cleaner.rb +1 -1
- data/lib/json_validator.rb +1 -1
- data/lib/kiwi_config.rb +69 -67
- data/lib/list_task.rb +1 -1
- data/lib/local_system.rb +1 -1
- data/lib/logged_cheetah.rb +1 -1
- data/lib/machinery.rb +6 -2
- data/lib/machinery_helper.rb +28 -8
- data/lib/machinery_logger.rb +1 -1
- data/lib/man_task.rb +50 -5
- data/lib/managed_files_database.rb +24 -17
- data/lib/manifest.rb +3 -2
- data/lib/migration.rb +1 -1
- data/lib/mountpoints.rb +1 -1
- data/lib/move_task.rb +1 -1
- data/lib/object.rb +1 -1
- data/lib/remote_system.rb +2 -2
- data/lib/remove_task.rb +1 -1
- data/lib/renderer.rb +1 -1
- data/lib/renderer_helper.rb +1 -1
- data/lib/rpm.rb +1 -1
- data/lib/rpm_database.rb +1 -1
- data/lib/scope.rb +1 -1
- data/lib/scope_file_store.rb +1 -1
- data/lib/serve_html_task.rb +1 -1
- data/lib/server.rb +32 -2
- data/lib/show_task.rb +1 -1
- data/lib/system.rb +1 -1
- data/lib/system_description.rb +2 -2
- data/lib/system_description_memory_store.rb +1 -1
- data/lib/system_description_store.rb +1 -1
- data/lib/system_file.rb +1 -1
- data/lib/tarball.rb +1 -1
- data/lib/tee_io.rb +39 -0
- data/lib/try.rb +1 -1
- data/lib/ui.rb +1 -1
- data/lib/upgrade_format_task.rb +1 -1
- data/lib/validate_task.rb +1 -1
- data/lib/version.rb +2 -2
- data/lib/workload_mapper.rb +1 -1
- data/lib/workload_mapper_dsl.rb +1 -1
- data/lib/zypper.rb +3 -3
- data/machinery-helper/Rakefile +2 -8
- data/machinery-helper/file_utils.go +28 -0
- data/machinery-helper/file_utils_test.go +21 -0
- data/machinery-helper/machinery_helper.go +121 -8
- data/machinery-helper/machinery_helper_test.go +102 -0
- data/machinery-helper/mountpoints_test.go +33 -33
- data/machinery-helper/version.go +1 -1
- data/man/generated/machinery.1.gz +0 -0
- data/manual/custom_theme/base.html +42 -0
- data/manual/docs/CNAME +1 -0
- data/manual/docs/README.md +128 -0
- data/manual/docs/css/bootstrap.min.css +7 -0
- data/manual/docs/css/custom.css +788 -0
- data/manual/docs/css/fixed-positioning.css +45 -0
- data/manual/docs/custom.css +804 -0
- data/manual/docs/docs.md +7 -0
- data/manual/docs/favicon.png +0 -0
- data/manual/docs/hand3.png +0 -0
- data/manual/docs/img/arrow.png +0 -0
- data/manual/docs/img/background/1.png +0 -0
- data/manual/docs/img/background/2.png +0 -0
- data/manual/docs/img/background/3.png +0 -0
- data/manual/docs/img/background/4.png +0 -0
- data/manual/docs/img/background/5.png +0 -0
- data/manual/docs/img/background/6.png +0 -0
- data/manual/docs/img/background/7.png +0 -0
- data/manual/docs/img/bk-cloud.png +0 -0
- data/manual/docs/img/bk-sec-15.png +0 -0
- data/manual/docs/img/book.png +0 -0
- data/manual/docs/img/configuration-discovery.png +0 -0
- data/manual/docs/img/dot-line-left.png +0 -0
- data/manual/docs/img/dot-line-right.png +0 -0
- data/manual/docs/img/gear.png +0 -0
- data/manual/docs/img/gear2.png +0 -0
- data/manual/docs/img/gear3.png +0 -0
- data/manual/docs/img/hand.png +0 -0
- data/manual/docs/img/hand2.png +0 -0
- data/manual/docs/img/hand3.png +0 -0
- data/manual/docs/img/home2.png +0 -0
- data/manual/docs/img/moustache.png +0 -0
- data/manual/docs/img/navig.png +0 -0
- data/manual/docs/img/philo.png +0 -0
- data/manual/docs/img/service-migration.png +0 -0
- data/manual/docs/img/system-validation.png +0 -0
- data/manual/docs/img/ticket2.png +0 -0
- data/manual/docs/img/usecase-default.png +0 -0
- data/manual/docs/img/usecase1.png +0 -0
- data/manual/docs/img/usecase2.png +0 -0
- data/manual/docs/img/usecase3.png +0 -0
- data/manual/docs/img/usecase4.png +0 -0
- data/manual/docs/img/wheels.png +0 -0
- data/manual/docs/index.html +402 -0
- data/manual/docs/js/bootstrap.min.js +6 -0
- data/manual/docs/js/custom.js +148 -0
- data/manual/docs/js/jquery.js +4 -0
- data/manual/docs/js/jquery.nicescroll.min.js +116 -0
- data/manual/docs/js/jquery.pageslide.min.js +11 -0
- data/manual/docs/js/parallaxImg.js +146 -0
- data/manual/docs/js/skrollr.min.js +2 -0
- data/manual/docs/machinery-analyze.1.md +37 -0
- data/manual/docs/machinery-build.1.md +62 -0
- data/manual/docs/machinery-compare.1.md +63 -0
- data/manual/docs/machinery-config.1.md +45 -0
- data/manual/docs/machinery-copy.1.md +31 -0
- data/manual/docs/machinery-deploy.1.md +71 -0
- data/manual/docs/machinery-export-autoyast.1.md +58 -0
- data/manual/docs/machinery-export-kiwi.1.md +38 -0
- data/manual/docs/machinery-inspect-docker.1.md +108 -0
- data/manual/docs/machinery-inspect.1.md +145 -0
- data/manual/docs/machinery-list.1.md +51 -0
- data/manual/docs/machinery-man.1.md +16 -0
- data/manual/docs/machinery-move.1.md +29 -0
- data/manual/docs/machinery-remove.1.md +44 -0
- data/manual/docs/machinery-serve.1.md +45 -0
- data/manual/docs/machinery-show.1.md +63 -0
- data/manual/docs/machinery-upgrade-format.1.md +47 -0
- data/manual/docs/machinery-validate.1.md +34 -0
- data/manual/docs/machinery.ymp +114 -0
- data/manual/docs/machinery_main_general.1.md +139 -0
- data/manual/docs/machinery_main_scopes.1.md +98 -0
- data/manual/docs/machinery_main_usecases.1.md +49 -0
- data/manual/docs/machinery_security_implications.1.md +89 -0
- data/manual/docs/subcommand-template.1.md +46 -0
- data/manual/docs/wheels.png +0 -0
- data/manual/mkdocs.yml +30 -0
- data/manual/site/CNAME +1 -0
- data/manual/site/base.html +42 -0
- data/manual/site/css/bootstrap.min.css +7 -0
- data/manual/site/css/custom.css +788 -0
- data/manual/site/css/fixed-positioning.css +45 -0
- data/manual/site/custom.css +804 -0
- data/manual/site/docs/index.html +144 -0
- data/manual/site/favicon.png +0 -0
- data/manual/site/hand3.png +0 -0
- data/manual/site/img/arrow.png +0 -0
- data/manual/site/img/background/1.png +0 -0
- data/manual/site/img/background/2.png +0 -0
- data/manual/site/img/background/3.png +0 -0
- data/manual/site/img/background/4.png +0 -0
- data/manual/site/img/background/5.png +0 -0
- data/manual/site/img/background/6.png +0 -0
- data/manual/site/img/background/7.png +0 -0
- data/manual/site/img/bk-cloud.png +0 -0
- data/manual/site/img/bk-sec-15.png +0 -0
- data/manual/site/img/book.png +0 -0
- data/manual/site/img/configuration-discovery.png +0 -0
- data/manual/site/img/dot-line-left.png +0 -0
- data/manual/site/img/dot-line-right.png +0 -0
- data/manual/site/img/gear.png +0 -0
- data/manual/site/img/gear2.png +0 -0
- data/manual/site/img/gear3.png +0 -0
- data/manual/site/img/hand.png +0 -0
- data/manual/site/img/hand2.png +0 -0
- data/manual/site/img/hand3.png +0 -0
- data/manual/site/img/home2.png +0 -0
- data/manual/site/img/moustache.png +0 -0
- data/manual/site/img/navig.png +0 -0
- data/manual/site/img/philo.png +0 -0
- data/manual/site/img/service-migration.png +0 -0
- data/manual/site/img/system-validation.png +0 -0
- data/manual/site/img/ticket2.png +0 -0
- data/manual/site/img/usecase-default.png +0 -0
- data/manual/site/img/usecase1.png +0 -0
- data/manual/site/img/usecase2.png +0 -0
- data/manual/site/img/usecase3.png +0 -0
- data/manual/site/img/usecase4.png +0 -0
- data/manual/site/img/wheels.png +0 -0
- data/manual/site/index.html +402 -0
- data/manual/site/js/bootstrap.min.js +6 -0
- data/manual/site/js/custom.js +148 -0
- data/manual/site/js/jquery.js +4 -0
- data/manual/site/js/jquery.nicescroll.min.js +116 -0
- data/manual/site/js/jquery.pageslide.min.js +11 -0
- data/manual/site/js/parallaxImg.js +146 -0
- data/manual/site/js/skrollr.min.js +2 -0
- data/manual/site/machinery-analyze.1/index.html +167 -0
- data/manual/site/machinery-build.1/index.html +198 -0
- data/manual/site/machinery-compare.1/index.html +200 -0
- data/manual/site/machinery-config.1/index.html +175 -0
- data/manual/site/machinery-copy.1/index.html +164 -0
- data/manual/site/machinery-deploy.1/index.html +200 -0
- data/manual/site/machinery-export-autoyast.1/index.html +188 -0
- data/manual/site/machinery-export-kiwi.1/index.html +169 -0
- data/manual/site/machinery-inspect-docker.1/index.html +242 -0
- data/manual/site/machinery-inspect.1/index.html +283 -0
- data/manual/site/machinery-list.1/index.html +180 -0
- data/manual/site/machinery-man.1/index.html +148 -0
- data/manual/site/machinery-move.1/index.html +162 -0
- data/manual/site/machinery-remove.1/index.html +175 -0
- data/manual/site/machinery-serve.1/index.html +174 -0
- data/manual/site/machinery-show.1/index.html +199 -0
- data/manual/site/machinery-upgrade-format.1/index.html +173 -0
- data/manual/site/machinery-validate.1/index.html +161 -0
- data/manual/site/machinery.ymp +114 -0
- data/manual/site/machinery_main_general.1/index.html +260 -0
- data/manual/site/machinery_main_scopes.1/index.html +242 -0
- data/manual/site/machinery_main_usecases.1/index.html +182 -0
- data/manual/site/machinery_security_implications.1/index.html +223 -0
- data/manual/site/mkdocs/js/lunr-0.5.7.min.js +7 -0
- data/manual/site/mkdocs/js/mustache.min.js +1 -0
- data/manual/site/mkdocs/js/require.js +36 -0
- data/manual/site/mkdocs/js/search-results-template.mustache +4 -0
- data/manual/site/mkdocs/js/search.js +88 -0
- data/manual/site/mkdocs/js/text.js +390 -0
- data/manual/site/mkdocs/search_index.json +824 -0
- data/manual/site/sitemap.xml +152 -0
- data/manual/site/wheels.png +0 -0
- data/plugins/changed_managed_files/changed_managed_files_inspector.rb +1 -1
- data/plugins/changed_managed_files/changed_managed_files_model.rb +1 -1
- data/plugins/changed_managed_files/changed_managed_files_renderer.rb +1 -1
- data/plugins/changed_managed_files/schema/system-description-changed-managed-files.schema-v7.json +160 -0
- data/plugins/config_files/config_files_inspector.rb +1 -1
- data/plugins/config_files/config_files_model.rb +1 -1
- data/plugins/config_files/config_files_renderer.rb +1 -1
- data/plugins/config_files/schema/system-description-config-files.schema-v7.json +160 -0
- data/plugins/environment/environment_inspector.rb +1 -1
- data/plugins/environment/environment_model.rb +1 -1
- data/plugins/environment/schema/system-description-environment.schema-v7.json +17 -0
- data/plugins/groups/groups_inspector.rb +1 -1
- data/plugins/groups/groups_model.rb +1 -1
- data/plugins/groups/groups_renderer.rb +1 -1
- data/plugins/groups/schema/system-description-groups.schema-v7.json +49 -0
- data/plugins/os/os_inspector.rb +1 -1
- data/plugins/os/os_model.rb +1 -1
- data/plugins/os/os_renderer.rb +1 -1
- data/plugins/os/schema/system-description-os.schema-v7.json +21 -0
- data/plugins/packages/packages_inspector.rb +1 -1
- data/plugins/packages/packages_model.rb +1 -1
- data/plugins/packages/packages_renderer.rb +1 -1
- data/plugins/packages/schema/system-description-packages.schema-v7.json +115 -0
- data/plugins/patterns/patterns_inspector.rb +6 -6
- data/plugins/patterns/patterns_model.rb +1 -1
- data/plugins/patterns/patterns_renderer.rb +1 -1
- data/plugins/patterns/schema/system-description-patterns.schema-v7.json +58 -0
- data/plugins/repositories/repositories_inspector.rb +16 -16
- data/plugins/repositories/repositories_model.rb +1 -1
- data/plugins/repositories/repositories_renderer.rb +1 -1
- data/plugins/repositories/schema/system-description-repositories.schema-v7.json +165 -0
- data/plugins/services/schema/system-description-services.schema-v7.json +93 -0
- data/plugins/services/services_inspector.rb +1 -1
- data/plugins/services/services_model.rb +1 -1
- data/plugins/services/services_renderer.rb +1 -1
- data/plugins/unmanaged_files/schema/system-description-unmanaged-files.schema-v6.json +19 -61
- data/plugins/unmanaged_files/schema/system-description-unmanaged-files.schema-v7.json +124 -0
- data/plugins/unmanaged_files/unmanaged_files_inspector.rb +21 -436
- data/plugins/unmanaged_files/unmanaged_files_model.rb +2 -2
- data/plugins/unmanaged_files/unmanaged_files_renderer.rb +2 -2
- data/plugins/users/schema/system-description-users.schema-v7.json +86 -0
- data/plugins/users/users_inspector.rb +1 -1
- data/plugins/users/users_model.rb +1 -1
- data/plugins/users/users_renderer.rb +1 -1
- data/schema/migrations/migrate1to2.rb +1 -1
- data/schema/migrations/migrate6to7.rb +38 -0
- data/schema/system-description-global.schema-v7.json +43 -0
- data/tools/go.rb +92 -0
- data/tools/helper_builder.rb +16 -49
- metadata +182 -6
- data/man/generated/machinery.1.html +0 -1399
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2013-
|
1
|
+
# Copyright (c) 2013-2016 SUSE LLC
|
2
2
|
#
|
3
3
|
# This program is free software; you can redistribute it and/or
|
4
4
|
# modify it under the terms of version 3 of the GNU General Public License as
|
@@ -21,239 +21,18 @@ class UnmanagedFilesInspector < Inspector
|
|
21
21
|
# checks if all required binaries are present
|
22
22
|
def check_requirements(check_tar)
|
23
23
|
@system.check_requirement(["rpm", "dpkg"], "--version")
|
24
|
-
@system.check_requirement("sed", "--version")
|
25
|
-
@system.check_requirement("cat", "--version")
|
26
|
-
@system.check_requirement("find", "--version")
|
27
24
|
@system.check_create_archive_dependencies if check_tar
|
28
25
|
end
|
29
26
|
|
30
|
-
# extract pathes from rpm database into ruby hashes
|
31
|
-
def extract_rpm_database
|
32
|
-
out = @system.run_command(
|
33
|
-
["rpm", "-qlav"],
|
34
|
-
["sed", "s/^\\(.\\)[^/]* /\\1 /"],
|
35
|
-
:stdout => :capture
|
36
|
-
)
|
37
|
-
|
38
|
-
files = {}
|
39
|
-
dirh = {}
|
40
|
-
links = {}
|
41
|
-
# result of above command is lines with type as first character, then a path
|
42
|
-
# handled types are: "-" for normal files, "d" for directories, "l" for links
|
43
|
-
# links have " -> " with link content after path
|
44
|
-
out.each_line do |l|
|
45
|
-
type = l[0]
|
46
|
-
entry = l[2..-2]
|
47
|
-
if type == "-"
|
48
|
-
files[entry] = ""
|
49
|
-
elsif type == "d"
|
50
|
-
dirh[entry] = true
|
51
|
-
elsif type == "l"
|
52
|
-
pair = entry.split(" -> ",2)
|
53
|
-
files[pair.first] = pair[1]
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
process_managed_files_and_dirs(files, dirh)
|
58
|
-
end
|
59
|
-
|
60
|
-
def extract_dpkg_database
|
61
|
-
out = @system.run_script_with_progress("dpkg_unmanaged_files.sh")
|
62
|
-
parsed_data = parse_dpkg_package_files_output(out)
|
63
|
-
files = parsed_data[:files]
|
64
|
-
dirh = parsed_data[:directories]
|
65
|
-
|
66
|
-
process_managed_files_and_dirs(files, dirh)
|
67
|
-
end
|
68
|
-
|
69
|
-
def process_managed_files_and_dirs(files, dirs)
|
70
|
-
# make sure that all parent directories of managed rpm directories are considered
|
71
|
-
# managed
|
72
|
-
dirs.dup.keys.each do |d|
|
73
|
-
dir = d.rpartition("/").first
|
74
|
-
|
75
|
-
while !dirs.key?(dir) && dir.size > 1
|
76
|
-
dirs[dir] = false
|
77
|
-
dir = dir[0..dir.rindex("/") - 1]
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
files.each do |f,e|
|
82
|
-
dir, sep, file = f.rpartition("/")
|
83
|
-
|
84
|
-
# make sure that dirs leading to a managed file are treated as if they were
|
85
|
-
# in rpm database, otherwise we cannot exclude whole unmanaged trees
|
86
|
-
while !dirs.key?(dir) && dir.size > 1
|
87
|
-
dirs[dir] = false
|
88
|
-
dir=dir[0..dir.rindex("/") - 1]
|
89
|
-
end
|
90
|
-
|
91
|
-
# put links to a managed directory also into directory hash
|
92
|
-
if !e.empty? && dirs.key?(e)
|
93
|
-
dirs[f] = false
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
[files, dirs]
|
98
|
-
end
|
99
|
-
|
100
|
-
def parse_dpkg_package_files_output(data)
|
101
|
-
result = { files: {}, directories: {} }
|
102
|
-
|
103
|
-
data.each_line do |line|
|
104
|
-
type, value = line.chomp.split(" ", 2)
|
105
|
-
|
106
|
-
if type == "-" # file
|
107
|
-
result[:files][value] = ""
|
108
|
-
elsif type == "d" && value != "/." # directory
|
109
|
-
result[:directories][value] = true
|
110
|
-
elsif type == "l" # link
|
111
|
-
pair = value.split(" -> ", 2)
|
112
|
-
result[:files][pair[0]] = pair[1]
|
113
|
-
end
|
114
|
-
end
|
115
|
-
result
|
116
|
-
end
|
117
|
-
|
118
|
-
def check_consistency(files, dirh)
|
119
|
-
p "files=#{files.size} dirs=#{dirh.size}"
|
120
|
-
p "dirs in rpmdb=#{dirh.select{|k,e| e}.size} added:#{dirh.select{|k,e| !e}.size}"
|
121
|
-
list = files.select { |f| !f.start_with?("/") }
|
122
|
-
p "should not happen non-abs file:#{list}" unless list.empty?
|
123
|
-
list = dirh.select { |f| !f.start_with?("/") }
|
124
|
-
p "should not happen non-abs dirs:#{list}" unless list.empty?
|
125
|
-
end
|
126
|
-
|
127
|
-
# extract metadata from extracted tar archives and put data into Object
|
128
|
-
def extract_tar_metadata(osl, destdir)
|
129
|
-
if Dir.exists?(destdir)
|
130
|
-
tarballs = [File.join(destdir, "files.tgz")]
|
131
|
-
osl.select{ |os| os.type == "dir" }.map(&:name).each do |d|
|
132
|
-
base = File.dirname(d)
|
133
|
-
tarballs << File.join(destdir, "trees", base, "#{File.basename(d)}.tgz")
|
134
|
-
end
|
135
|
-
|
136
|
-
tarballs.each do | archive|
|
137
|
-
files = Tarball.new(archive).list
|
138
|
-
|
139
|
-
files.each do |file|
|
140
|
-
os = osl.find do |o|
|
141
|
-
o.name == "/#{file[:path]}#{file[:type] == :dir ? "/" : ""}"
|
142
|
-
end
|
143
|
-
if !os
|
144
|
-
raise Machinery::Errors::UnexpectedInputData.new(
|
145
|
-
"The inspection failed because of the unexpected input data:\n#{file.inspect}\n\n" \
|
146
|
-
"Please file a bug report at: https://github.com/SUSE/machinery/issues/new"
|
147
|
-
)
|
148
|
-
end
|
149
|
-
|
150
|
-
os.user = file[:user]
|
151
|
-
os.group = file[:group]
|
152
|
-
if file[:type] != :link
|
153
|
-
os.size = file[:size]
|
154
|
-
os.mode = file[:mode]
|
155
|
-
end
|
156
|
-
|
157
|
-
# unmanaged dirs are trees and only have one entry in the manifest
|
158
|
-
if os.type == "dir"
|
159
|
-
os.size = files.map { |d| d[:size] }.reduce(:+)
|
160
|
-
os.files = files.size
|
161
|
-
break
|
162
|
-
end
|
163
|
-
end
|
164
|
-
end
|
165
|
-
end
|
166
|
-
osl
|
167
|
-
end
|
168
|
-
|
169
|
-
# find paths below dir until a certain depth is reached
|
170
|
-
def get_find_data(dir, depth )
|
171
|
-
dep = depth - 1
|
172
|
-
files = {}
|
173
|
-
dirs = {}
|
174
|
-
|
175
|
-
# compute command line
|
176
|
-
cmd = ["find", dir, "-xdev", "-maxdepth", "1", "-maxdepth", depth.to_s]
|
177
|
-
cmd += ["-printf", '%y\0%P\0%l\0']
|
178
|
-
|
179
|
-
out = ""
|
180
|
-
begin
|
181
|
-
out = @system.run_command(
|
182
|
-
*cmd,
|
183
|
-
stdout: :capture,
|
184
|
-
disable_logging: true,
|
185
|
-
privileged: true
|
186
|
-
).force_encoding("binary")
|
187
|
-
rescue Cheetah::ExecutionFailed => e
|
188
|
-
out = e.stdout
|
189
|
-
message = "Warning: The command find of the unmanaged-file inspector" \
|
190
|
-
" ran into an issue. The error output was:\n#{e.stderr}"
|
191
|
-
Machinery.logger.warn(message)
|
192
|
-
Machinery::Ui.warn(message)
|
193
|
-
end
|
194
|
-
|
195
|
-
# find creates three field per path
|
196
|
-
out.split("\0", -1).each_slice(3) do |type, raw_path, raw_link|
|
197
|
-
next unless raw_path && !raw_path.empty?
|
198
|
-
|
199
|
-
# Filenames can contain invalid UTF-8 characters, so we treat the data as
|
200
|
-
# binary information first while splitting the raw output and then convert
|
201
|
-
# the separate strings to UTF-8, replacing invalid characters with the
|
202
|
-
# "REPLACEMENT CHARACTER" (U+FFFD). That way we have both the raw data
|
203
|
-
# (which is needed in order to be able to access the files) and the cleaned
|
204
|
-
# string which can be safely used.
|
205
|
-
path = Machinery.scrub(raw_path)
|
206
|
-
link = Machinery.scrub(raw_link)
|
207
|
-
|
208
|
-
if [path, link].any? { |f| f.include?("\uFFFD") }
|
209
|
-
broken_names = []
|
210
|
-
if path.include?("\uFFFD")
|
211
|
-
broken_names << "filename '#{path}'"
|
212
|
-
end
|
213
|
-
if link.include?("\uFFFD")
|
214
|
-
broken_names << "link target '#{link}'"
|
215
|
-
end
|
216
|
-
|
217
|
-
warning = broken_names.join(" and ")
|
218
|
-
warning += " contain#{"s" if broken_names.length == 1}"
|
219
|
-
warning += " invalid UTF-8 characters. Skipping."
|
220
|
-
warning[0] = warning[0].upcase
|
221
|
-
|
222
|
-
Machinery.logger.warn(warning)
|
223
|
-
Machinery::Ui.warn(warning)
|
224
|
-
next
|
225
|
-
end
|
226
|
-
|
227
|
-
files[path] = link if type == "l"
|
228
|
-
files[path] = "" if type == "f"
|
229
|
-
|
230
|
-
# dirs at maxdepth could be non-leafs all othere are leafs
|
231
|
-
dirs[path] = path.count("/") == dep if type == "d"
|
232
|
-
end
|
233
|
-
Machinery.logger.debug "get_find_data dir:#{dir} depth:#{depth} file:#{files.size}" \
|
234
|
-
" dirs:#{dirs.size}"
|
235
|
-
[files, dirs]
|
236
|
-
end
|
237
|
-
|
238
|
-
def max_depth
|
239
|
-
6
|
240
|
-
end
|
241
|
-
|
242
|
-
def start_depth
|
243
|
-
3
|
244
|
-
end
|
245
|
-
|
246
27
|
def initialize(system, description)
|
247
28
|
@system = system
|
248
29
|
@description = description
|
249
30
|
end
|
250
31
|
|
251
32
|
def inspect(filter, options = {})
|
252
|
-
do_extract = options
|
33
|
+
do_extract = options[:extract_unmanaged_files]
|
253
34
|
check_requirements(do_extract)
|
254
35
|
|
255
|
-
determine_package_manager
|
256
|
-
|
257
36
|
scope = UnmanagedFilesScope.new
|
258
37
|
|
259
38
|
file_store_tmp = @description.scope_file_store("unmanaged_files.tmp")
|
@@ -271,40 +50,26 @@ class UnmanagedFilesInspector < Inspector
|
|
271
50
|
end
|
272
51
|
|
273
52
|
helper = MachineryHelper.new(@system)
|
53
|
+
|
274
54
|
if helper_usable?(helper)
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
run_inspection(file_filter, options, do_extract, file_store_tmp, file_store_final, scope)
|
279
|
-
end
|
280
|
-
end
|
55
|
+
helper_options = {}
|
56
|
+
helper_options[:do_extract] = do_extract
|
57
|
+
helper_options[:extract_metadata] = options[:extract_metadata]
|
281
58
|
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
59
|
+
run_helper_inspection(helper, file_filter, file_store_tmp, file_store_final,
|
60
|
+
scope, helper_options)
|
61
|
+
else
|
62
|
+
raise Machinery::Errors::MissingRequirement.new(
|
63
|
+
"There is no machinery-helper available for the remote system architecture #{@system.arch}."
|
64
|
+
)
|
287
65
|
end
|
288
66
|
end
|
289
67
|
|
290
68
|
def helper_usable?(helper)
|
291
|
-
|
292
|
-
Machinery::Ui.puts(
|
293
|
-
"Note: Using traditional inspection because there is no helper binary for" \
|
294
|
-
" architecture '#{@system.arch}' available."
|
295
|
-
)
|
296
|
-
elsif @system.respond_to?(:remote_user) && @system.remote_user != "root"
|
297
|
-
Machinery::Ui.puts(
|
298
|
-
"Note: Using traditional inspection because only 'root' is supported as remote user."
|
299
|
-
)
|
300
|
-
elsif ["rpm", "dpkg"].include?(@package_manager)
|
301
|
-
return true
|
302
|
-
end
|
303
|
-
|
304
|
-
false
|
69
|
+
helper.can_help?
|
305
70
|
end
|
306
71
|
|
307
|
-
def run_helper_inspection(helper, filter,
|
72
|
+
def run_helper_inspection(helper, filter, file_store_tmp, file_store_final, scope, options)
|
308
73
|
begin
|
309
74
|
helper.inject_helper
|
310
75
|
if !helper.has_compatible_version?
|
@@ -314,10 +79,13 @@ class UnmanagedFilesInspector < Inspector
|
|
314
79
|
)
|
315
80
|
end
|
316
81
|
|
317
|
-
|
82
|
+
args = []
|
83
|
+
args.push("--extract-metadata") if options[:extract_metadata] || options[:do_extract]
|
84
|
+
|
85
|
+
helper.run_helper(scope, *args)
|
318
86
|
scope.delete_if { |f| filter.matches?(f.name) }
|
319
87
|
|
320
|
-
if do_extract
|
88
|
+
if options[:do_extract]
|
321
89
|
mount_points = MountPoints.new(@system)
|
322
90
|
excluded_trees = mount_points.remote + mount_points.special
|
323
91
|
|
@@ -333,14 +101,15 @@ class UnmanagedFilesInspector < Inspector
|
|
333
101
|
show_extraction_progress(files.count + count)
|
334
102
|
end
|
335
103
|
|
336
|
-
scope = extract_tar_metadata(scope, file_store_tmp.path)
|
337
104
|
file_store_final.remove
|
338
105
|
file_store_tmp.rename(file_store_final.store_name)
|
339
106
|
scope.scope_file_store = file_store_final
|
340
107
|
scope.extracted = true
|
108
|
+
scope.has_metadata = true
|
341
109
|
else
|
342
110
|
file_store_final.remove
|
343
111
|
scope.extracted = false
|
112
|
+
scope.has_metadata = !!options[:extract_metadata]
|
344
113
|
end
|
345
114
|
ensure
|
346
115
|
helper.remove_helper
|
@@ -349,178 +118,6 @@ class UnmanagedFilesInspector < Inspector
|
|
349
118
|
@description["unmanaged_files"] = scope
|
350
119
|
end
|
351
120
|
|
352
|
-
def run_inspection(file_filter, options, do_extract, file_store_tmp, file_store_final, scope)
|
353
|
-
mount_points = MountPoints.new(@system)
|
354
|
-
|
355
|
-
if @package_manager == "rpm"
|
356
|
-
inspected_files, inspected_dirs = extract_rpm_database
|
357
|
-
elsif @package_manager == "dpkg"
|
358
|
-
inspected_files, inspected_dirs = extract_dpkg_database
|
359
|
-
end
|
360
|
-
|
361
|
-
# Btrfs subvolumes and local mounts need to be inspected separately because
|
362
|
-
# they are not part of the `get_find_data` return data
|
363
|
-
local_filesystems = mount_points.local + btrfs_subvolumes
|
364
|
-
|
365
|
-
unmanaged_files = []
|
366
|
-
unmanaged_trees = []
|
367
|
-
excluded_files = []
|
368
|
-
unmanaged_links = {}
|
369
|
-
remote_dirs = mount_points.remote
|
370
|
-
special_dirs = mount_points.special
|
371
|
-
|
372
|
-
|
373
|
-
remote_dirs.delete_if { |e| file_filter.matches?(e) }
|
374
|
-
|
375
|
-
excluded_files += remote_dirs
|
376
|
-
excluded_files += special_dirs
|
377
|
-
|
378
|
-
if options[:verbose] && !remote_dirs.empty?
|
379
|
-
warning = "The content of the following remote directories is ignored:" \
|
380
|
-
" #{remote_dirs.uniq.join(", ")}."
|
381
|
-
Machinery.logger.warn(warning)
|
382
|
-
Machinery::Ui.warn(warning)
|
383
|
-
end
|
384
|
-
if options[:verbose] && !special_dirs.empty?
|
385
|
-
warning = "The content of the following special directories is ignored:" \
|
386
|
-
" #{special_dirs.uniq.join(", ")}."
|
387
|
-
Machinery.logger.warn(warning)
|
388
|
-
Machinery::Ui.warn(warning)
|
389
|
-
end
|
390
|
-
|
391
|
-
dirs_todo = ["/"]
|
392
|
-
start = start_depth
|
393
|
-
max = max_depth
|
394
|
-
find_count = 0
|
395
|
-
sub_tree_containing_remote_fs = []
|
396
|
-
|
397
|
-
while !dirs_todo.empty?
|
398
|
-
find_dir = dirs_todo.first
|
399
|
-
|
400
|
-
# determine files and directories below find_dir until a certain depth
|
401
|
-
depth = local_filesystems.include?(find_dir) ? start : max
|
402
|
-
files, dirs = get_find_data(find_dir, depth)
|
403
|
-
find_count += 1
|
404
|
-
find_dir += "/" if find_dir.size > 1
|
405
|
-
if !local_filesystems.empty?
|
406
|
-
# force all mount points to be non-leave directories (find is called with -xdev)
|
407
|
-
local_filesystems.each do |mp|
|
408
|
-
path = mp.sub(/^\//, "")
|
409
|
-
dirs[path] = true if dirs.key?(path)
|
410
|
-
end
|
411
|
-
local_filesystems.reject! { |mp| dirs.has_key?(mp) }
|
412
|
-
end
|
413
|
-
if find_dir == "/"
|
414
|
-
dirs.reject! do |dir|
|
415
|
-
file_filter.matches?("/" + dir)
|
416
|
-
end
|
417
|
-
|
418
|
-
files.reject! do |dir|
|
419
|
-
file_filter.matches?("/" + dir)
|
420
|
-
end
|
421
|
-
end
|
422
|
-
managed, unmanaged = dirs.keys.partition { |d| inspected_dirs.key?(find_dir + d) }
|
423
|
-
|
424
|
-
# unmanaged dirs lead to removal of files and dirs below that dir
|
425
|
-
while !unmanaged.empty?
|
426
|
-
dir = unmanaged.shift
|
427
|
-
|
428
|
-
# Ignore special mounts, e.g. procfs mounts in a chroot
|
429
|
-
next if special_dirs.include?(find_dir + dir)
|
430
|
-
|
431
|
-
# save into list of unmanaged trees
|
432
|
-
if !remote_dirs.include?(find_dir + dir)
|
433
|
-
unmanaged_trees << find_dir + dir
|
434
|
-
end
|
435
|
-
dir = File.join(dir, "/")
|
436
|
-
|
437
|
-
# find sub trees containing remote file systems
|
438
|
-
remote_dirs.each do |remote_dir|
|
439
|
-
if unmanaged.include?(remote_dir[1..-1])
|
440
|
-
sub_tree_containing_remote_fs << remote_dir
|
441
|
-
unmanaged = unmanaged.drop_while{ |d| d.start_with?(remote_dir[1...-1]) }
|
442
|
-
end
|
443
|
-
end
|
444
|
-
# remove all possible further references starting with this subdir
|
445
|
-
unmanaged = unmanaged.drop_while{ |d| d.start_with?(dir) }
|
446
|
-
files.reject!{ |d| d.start_with?(dir) }
|
447
|
-
end
|
448
|
-
|
449
|
-
# remove all (currently known) leaf directories
|
450
|
-
managed.select!{ |d| dirs[d] }
|
451
|
-
|
452
|
-
# update list for still to handle directories
|
453
|
-
dirs_todo.shift
|
454
|
-
managed.map!{ |d| find_dir + d }
|
455
|
-
dirs_todo.push(*managed)
|
456
|
-
|
457
|
-
# unmanaged files are simply stored
|
458
|
-
managed, unmanaged = files.keys.partition { |d| inspected_files.key?(find_dir + d) }
|
459
|
-
links = unmanaged.reject { |d| files[d].empty? }
|
460
|
-
unmanaged.map!{ |d| find_dir + d }
|
461
|
-
unmanaged_files.push(*unmanaged)
|
462
|
-
links.each { |d| unmanaged_links[find_dir + d] = "" }
|
463
|
-
|
464
|
-
count = unmanaged_files.length + unmanaged_trees.length
|
465
|
-
progress = Machinery::pluralize(
|
466
|
-
count, " -> Found %d file or tree...", " -> Found %d files and trees...",
|
467
|
-
)
|
468
|
-
Machinery::Ui.progress(progress)
|
469
|
-
end
|
470
|
-
Machinery.logger.debug "inspect unmanaged files find calls:#{find_count} files:#{unmanaged_files.size} trees:#{unmanaged_trees.size}"
|
471
|
-
|
472
|
-
processed_files = run_extraction(unmanaged_files, unmanaged_trees, unmanaged_links,
|
473
|
-
excluded_files, remote_dirs, do_extract, file_store_tmp, file_store_final, scope)
|
474
|
-
|
475
|
-
scope.extracted = !!do_extract
|
476
|
-
scope += processed_files.sort_by(&:name)
|
477
|
-
@description["unmanaged_files"] = scope
|
478
|
-
end
|
479
|
-
|
480
|
-
def run_extraction(unmanaged_files, unmanaged_trees, unmanaged_links, excluded_files, remote_dirs,
|
481
|
-
do_extract, file_store_tmp, file_store_final, scope)
|
482
|
-
begin
|
483
|
-
if do_extract
|
484
|
-
file_store_tmp.remove
|
485
|
-
file_store_tmp.create
|
486
|
-
|
487
|
-
scope.retrieve_files_from_system_as_archive(@system,
|
488
|
-
unmanaged_files, excluded_files)
|
489
|
-
show_extraction_progress(unmanaged_files.count)
|
490
|
-
|
491
|
-
scope.retrieve_trees_from_system_as_archive(@system,
|
492
|
-
unmanaged_trees, excluded_files) do |count|
|
493
|
-
show_extraction_progress(unmanaged_files.count + count)
|
494
|
-
end
|
495
|
-
else
|
496
|
-
file_store_final.remove
|
497
|
-
end
|
498
|
-
osl = unmanaged_files.map do |p|
|
499
|
-
type = unmanaged_links.has_key?(p) ? "link" : "file"
|
500
|
-
UnmanagedFile.new(name: p, type: type)
|
501
|
-
end
|
502
|
-
osl += unmanaged_trees.map { |p| UnmanagedFile.new( name: p + "/", type: "dir") }
|
503
|
-
if do_extract
|
504
|
-
osl = extract_tar_metadata(osl, file_store_tmp.path)
|
505
|
-
file_store_final.remove
|
506
|
-
file_store_tmp.rename(file_store_final.store_name)
|
507
|
-
scope.scope_file_store = file_store_final
|
508
|
-
end
|
509
|
-
rescue SignalException => e
|
510
|
-
# Handle SIGHUP(1), SIGINT(2) and SIGTERM(15) gracefully
|
511
|
-
if [1, 2, 15].include?(e.signo)
|
512
|
-
Machinery::Ui.warn "Interrupted by user. The partly extracted unmanaged-files are available" \
|
513
|
-
" under '#{@description.file_store(file_store_tmp)}'"
|
514
|
-
end
|
515
|
-
raise
|
516
|
-
end
|
517
|
-
remote_dirs.each do |remote_dir|
|
518
|
-
osl << UnmanagedFile.new( name: remote_dir + "/", type: "remote_dir")
|
519
|
-
end
|
520
|
-
|
521
|
-
osl
|
522
|
-
end
|
523
|
-
|
524
121
|
def summary
|
525
122
|
"#{@description.unmanaged_files.extracted ? "Extracted" : "Found"} " +
|
526
123
|
"#{@description.unmanaged_files.count} unmanaged files and trees."
|
@@ -534,16 +131,4 @@ class UnmanagedFilesInspector < Inspector
|
|
534
131
|
)
|
535
132
|
Machinery::Ui.progress(progress)
|
536
133
|
end
|
537
|
-
|
538
|
-
def btrfs_subvolumes
|
539
|
-
if @system.has_command?("/sbin/btrfs")
|
540
|
-
@system.run_command(
|
541
|
-
["/sbin/btrfs", "subvolume", "list", "/"],
|
542
|
-
["awk", "{print $NF}"],
|
543
|
-
stdout: :capture
|
544
|
-
).split
|
545
|
-
else
|
546
|
-
[]
|
547
|
-
end
|
548
|
-
end
|
549
134
|
end
|