manageiq-smartstate 0.3.5 → 0.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/fs/modules/LinuxMount.rb +18 -14
- data/lib/manageiq/smartstate/version.rb +1 -1
- data/lib/metadata/util/find_class_methods.rb +132 -0
- data/lib/metadata/util/md5deep.rb +24 -16
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 329da11c20c2a1ea5a2089d9d8b50fbd4c2f5b4a
|
4
|
+
data.tar.gz: 8f29a1c35119e098e0b1a8e8421adc773545aa67
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1117fc552c4ef5931f86e7e612a395f98339cfe8ae49737f1c0f9a3515be3682011f574b4bd6144e849e0deeae4cebab63863ecefee6974cfeba7256964cc929
|
7
|
+
data.tar.gz: 73f022ff2c9a8bbfa940837f0b3aa3a54000b719024150d6774485189248cd15a9feacb880bd31934b3b77dc1fe46d4dae1fe81f88eef5f143b96f014af32dd6
|
@@ -309,23 +309,27 @@ module LinuxMount
|
|
309
309
|
#
|
310
310
|
components.each do |c|
|
311
311
|
ncp = File.join(cp, c)
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
312
|
+
cp = follow_all_symlinks(ncp)
|
313
|
+
end
|
314
|
+
cp
|
315
|
+
end
|
316
|
+
|
317
|
+
def follow_all_symlinks(link_ptr)
|
318
|
+
#
|
319
|
+
# Each filesystem knows how to check for,
|
320
|
+
# and read its own links.
|
321
|
+
#
|
322
|
+
no_more_links = false
|
323
|
+
until no_more_links
|
324
|
+
filesys, link_ptr = getFsPathBase(link_ptr)
|
325
|
+
if filesys.fileSymLink?(link_ptr)
|
326
|
+
symlink = getSymLink(filesys, linkptr)
|
327
|
+
link_ptr = symlink[0, 1] == '/' ? symlink : File.join(File.dirname(link_ptr), symlink)
|
324
328
|
else
|
325
|
-
|
329
|
+
no_more_links = true
|
326
330
|
end
|
327
331
|
end
|
328
|
-
|
332
|
+
link_ptr
|
329
333
|
end
|
330
334
|
|
331
335
|
def getSymLink(fs, p)
|
@@ -0,0 +1,132 @@
|
|
1
|
+
module FindClassMethods
|
2
|
+
# Return directory entries matching specified glob pattern
|
3
|
+
#
|
4
|
+
# @param glob_pattern [String] pattern to match
|
5
|
+
# @param flags [Integer] file match flags
|
6
|
+
# @yield block invoked with each match if specified
|
7
|
+
#
|
8
|
+
# @see VfsRealFile.fnmatch
|
9
|
+
# @see FindClassMethods#dir_and_glob which does most of the work regarding globbing
|
10
|
+
# @see FindClassMethods#find which retrieves stats information & dir entries for found files
|
11
|
+
#
|
12
|
+
def self.glob(glob_pattern, filesys, flags = 0)
|
13
|
+
@fs = filesys
|
14
|
+
return [] unless (glob = dir_and_glob(glob_pattern))
|
15
|
+
|
16
|
+
ra = []
|
17
|
+
find(@search_path, glob_depth(glob)) do |p|
|
18
|
+
p = check_file(p, glob, flags)
|
19
|
+
p && block_given? ? yield(p) : ra << p
|
20
|
+
end
|
21
|
+
ra.sort_by(&:downcase)
|
22
|
+
end
|
23
|
+
|
24
|
+
#
|
25
|
+
# Determine if the file returned from "find" will be used or skipped.
|
26
|
+
#
|
27
|
+
def self.check_file(file, glob, flags)
|
28
|
+
return nil if file == @search_path
|
29
|
+
|
30
|
+
if @search_path == File::SEPARATOR
|
31
|
+
file.sub!(File::SEPARATOR, "")
|
32
|
+
else
|
33
|
+
file.sub!("#{@search_path}#{File::SEPARATOR}", "")
|
34
|
+
end
|
35
|
+
|
36
|
+
return nil if file == "" || !File.fnmatch(glob, file, flags)
|
37
|
+
|
38
|
+
@specified_path ? File.join(@specified_path, file) : file
|
39
|
+
end
|
40
|
+
|
41
|
+
#
|
42
|
+
# Modified version of Find.find:
|
43
|
+
# - Accepts only a single path.
|
44
|
+
# - Can be restricted by depth - optimization for glob searches.
|
45
|
+
#
|
46
|
+
# @param path [String] starting directory of the find
|
47
|
+
# @param max_depth [Integer] max number of levels to decend befroelookup
|
48
|
+
# @yield files found
|
49
|
+
#
|
50
|
+
def self.find(path, max_depth = nil)
|
51
|
+
block_given? || (return enum_for(__method__, path, max_depth))
|
52
|
+
|
53
|
+
depths = [0]
|
54
|
+
paths = [path.dup]
|
55
|
+
|
56
|
+
while (file = paths.shift)
|
57
|
+
depth = depths.shift
|
58
|
+
yield file.dup.taint
|
59
|
+
next if max_depth && depth + 1 > max_depth
|
60
|
+
|
61
|
+
get_dir_entries(file).each do |f|
|
62
|
+
f = File.join(file, f)
|
63
|
+
paths.unshift f.untaint
|
64
|
+
depths.unshift depth + 1
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.get_dir_entries(directory)
|
70
|
+
return [] unless @fs.fileExists?(directory) && @fs.fileDirectory?(directory)
|
71
|
+
|
72
|
+
files = @fs.dirEntries(directory)
|
73
|
+
files.difference([".", ".."])
|
74
|
+
files.sort!
|
75
|
+
files.reverse_each
|
76
|
+
rescue Errno::ENOENT, Errno::EACCES, Errno::ENOTDIR, Errno::ELOOP, Errno::ENAMETOOLONG
|
77
|
+
$log.info "find: while-loop @fs.dirEntries #{directory} returned an error"
|
78
|
+
[]
|
79
|
+
end
|
80
|
+
|
81
|
+
GLOB_CHARS = '*?[{'.freeze
|
82
|
+
def self.glob_str?(str)
|
83
|
+
str.gsub(/\\./, "X").count(GLOB_CHARS) != 0
|
84
|
+
end
|
85
|
+
|
86
|
+
# Returns files matching glob pattern
|
87
|
+
#
|
88
|
+
# @api private
|
89
|
+
# @param glob_pattern [String,Regex] pattern to search for
|
90
|
+
# @return [String] paths to files found
|
91
|
+
#
|
92
|
+
def self.dir_and_glob(glob_pattern)
|
93
|
+
stripped_path = glob_pattern.sub(/^[a-zA-Z]:/, "")
|
94
|
+
glob_path = Pathname.new(stripped_path)
|
95
|
+
@search_path = File::SEPARATOR
|
96
|
+
@specified_path = File::SEPARATOR
|
97
|
+
|
98
|
+
unless glob_path.absolute?
|
99
|
+
@search_path = Dir.getwd
|
100
|
+
@specified_path = nil
|
101
|
+
end
|
102
|
+
|
103
|
+
components = path_components(glob_path)
|
104
|
+
@search_path = File.expand_path(@search_path, "/")
|
105
|
+
@fs.fileExists?(@search_path) ? File.join(components) : nil
|
106
|
+
end
|
107
|
+
|
108
|
+
def self.path_components(glob_path, search_path = @search_path)
|
109
|
+
components = glob_path.each_filename.to_a
|
110
|
+
while (comp = components.shift)
|
111
|
+
if glob_str?(comp)
|
112
|
+
components.unshift(comp)
|
113
|
+
break
|
114
|
+
end
|
115
|
+
@search_path = File.join(search_path, comp)
|
116
|
+
@specified_path = @specified_path ? File.join(@specified_path, comp) : comp
|
117
|
+
end
|
118
|
+
components
|
119
|
+
end
|
120
|
+
|
121
|
+
# Return max levels which glob pattern may resolve to
|
122
|
+
#
|
123
|
+
# @api private
|
124
|
+
# @param glob_pattern [String,Regex] pattern to search for
|
125
|
+
# @return [Integer] max levels which pattern may match
|
126
|
+
def self.glob_depth(glob_pattern)
|
127
|
+
path_components = Pathname(glob_pattern).each_filename.to_a
|
128
|
+
return nil if path_components.include?('**')
|
129
|
+
|
130
|
+
path_components.length
|
131
|
+
end
|
132
|
+
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'time'
|
2
2
|
require 'metadata/util/win32/peheader'
|
3
3
|
require 'metadata/util/win32/versioninfo'
|
4
|
+
require 'metadata/util/find_class_methods'
|
4
5
|
require 'util/miq-xml'
|
5
6
|
require 'ostruct'
|
6
7
|
require 'util/miq-encode'
|
@@ -54,29 +55,35 @@ class MD5deep
|
|
54
55
|
def scan_glob(filename)
|
55
56
|
filename.tr!("\\", "/")
|
56
57
|
startDir = File.dirname(filename)
|
57
|
-
globPattern = File.basename(filename)
|
58
58
|
@xml.root.add_attribute("base_path", startDir)
|
59
|
-
|
59
|
+
path_prefix = startDir[0, 2]
|
60
|
+
@drive_letter = path_prefix.match?(/^\w\:/) ? path_prefix : ""
|
60
61
|
|
61
62
|
# First check if we are passed a fully qualifed file name
|
62
63
|
if @fs.fileExists?(filename)
|
63
|
-
|
64
|
+
base_file = File.basename(filename)
|
65
|
+
isDir?(filename) ? process_dir_as_file(startDir, base_file, @xml.root) : processFile(startDir, base_file, @xml.root)
|
64
66
|
else
|
65
67
|
# If the file is not found then process the data as a glob pattern.
|
66
|
-
|
67
|
-
# $log.info "Glob file found: [#{f}]"
|
68
|
-
# Passing "startDir" as the first parameter is a work-around for issues
|
69
|
-
# when scanning Win VMs from Linux where the path returned from dirGlob
|
70
|
-
# do not include the drive letter.
|
71
|
-
# Below is the original line
|
72
|
-
# processFile(File.dirname(f), File.basename(f), @xml.root)
|
73
|
-
processFile(startDir, File.basename(f), @xml.root)
|
74
|
-
end
|
68
|
+
process_each_glob_file(filename)
|
75
69
|
end
|
76
70
|
@xml
|
77
71
|
end
|
78
72
|
|
73
|
+
def process_each_glob_file(file_name)
|
74
|
+
FindClassMethods.glob(file_name, @fs) do |f|
|
75
|
+
# Passing "startDir" as the first parameter is a work-around for issues
|
76
|
+
# when scanning Win VMs from Linux where the path returned from dirGlob
|
77
|
+
# do not include the drive letter.
|
78
|
+
processFile(File.dirname(f), File.basename(f), @xml.root)
|
79
|
+
end
|
80
|
+
rescue => err
|
81
|
+
$log.info "scan_glob: Exception #{err} rescued"
|
82
|
+
$log.debug err.backtrace.join("\n")
|
83
|
+
end
|
84
|
+
|
79
85
|
def read_fs(path, xmlNode)
|
86
|
+
@drive_letter = @drive_letter.nil? ? "" : @drive_letter
|
80
87
|
if @fs
|
81
88
|
@fs.dirForeach(path) { |x| processFile(path, x, xmlNode) }
|
82
89
|
@fs.dirForeach(path) { |x| processDir(path, x, xmlNode) }
|
@@ -91,7 +98,7 @@ class MD5deep
|
|
91
98
|
|
92
99
|
def processDir(path, x, xmlNode)
|
93
100
|
if x != "." && x != ".."
|
94
|
-
currFile = File.join(path, x)
|
101
|
+
currFile = File.join(@drive_letter, path, x)
|
95
102
|
|
96
103
|
begin
|
97
104
|
if File.directory?(currFile)
|
@@ -110,7 +117,7 @@ class MD5deep
|
|
110
117
|
|
111
118
|
def process_dir_as_file(path, x, xml_node)
|
112
119
|
if x != "." && x != ".."
|
113
|
-
curr_dir = File.join(path, x)
|
120
|
+
curr_dir = File.join(@drive_letter, path, x)
|
114
121
|
if isDir?(curr_dir)
|
115
122
|
xml_file_node = xml_node.add_element("file", "name" => x, "fqname" => curr_dir)
|
116
123
|
stat_hash = {}
|
@@ -122,7 +129,7 @@ class MD5deep
|
|
122
129
|
|
123
130
|
def processFile(path, x, xmlNode)
|
124
131
|
if (@opts.exclude.include?(x) == false) && x[0..0] != "$"
|
125
|
-
currFile = File.join(path, x)
|
132
|
+
currFile = File.join(@drive_letter, path, x)
|
126
133
|
|
127
134
|
begin
|
128
135
|
# unless File.directory?(currFile) then
|
@@ -150,13 +157,14 @@ class MD5deep
|
|
150
157
|
fh.close if fh.kind_of?(File) && !fh.closed?
|
151
158
|
end
|
152
159
|
end
|
160
|
+
$log.debug "processFile: finished @xml is #{@xml}"
|
153
161
|
end
|
154
162
|
|
155
163
|
def process_pe_header(pe_hdr, xml_file_node)
|
156
164
|
xml_file_node.add_element("versioninfo", pe_hdr.versioninfo) if @opts.versioninfo && pe_hdr.versioninfo.present?
|
157
165
|
xml_file_node.add_element("libraries", "imports" => pe_hdr.getImportList) if @opts.imports && pe_hdr.imports.present?
|
158
166
|
rescue TypeError => err
|
159
|
-
$log.info "
|
167
|
+
$log.info "process_pe_header: TypeError handling PEheader; skipping PEheader info"
|
160
168
|
$log.debug err.backtrace.join("\n")
|
161
169
|
end
|
162
170
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: manageiq-smartstate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ManageIQ Developers
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-03-
|
11
|
+
date: 2020-03-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: azure-armrest
|
@@ -525,6 +525,7 @@ files:
|
|
525
525
|
- lib/metadata/linux/MiqConaryPackages.rb
|
526
526
|
- lib/metadata/linux/MiqRpmPackages.rb
|
527
527
|
- lib/metadata/util/event_log_filter.rb
|
528
|
+
- lib/metadata/util/find_class_methods.rb
|
528
529
|
- lib/metadata/util/md5deep.rb
|
529
530
|
- lib/metadata/util/win32/Win32Accounts.rb
|
530
531
|
- lib/metadata/util/win32/Win32EventLog.rb
|