recls-ruby 2.6.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,251 @@
1
+ # ######################################################################### #
2
+ # File: recls/filesearch.rb
3
+ #
4
+ # Purpose: Defines the Recls::FileSearch class for the recls.Ruby library.
5
+ #
6
+ # Created: 24th July 2012
7
+ # Updated: 29th December 2015
8
+ #
9
+ # Author: Matthew Wilson
10
+ #
11
+ # Copyright (c) 2012-2015, Matthew Wilson and Synesis Software
12
+ # All rights reserved.
13
+ #
14
+ # Redistribution and use in source and binary forms, with or without
15
+ # modification, are permitted provided that the following conditions are met:
16
+ #
17
+ # * Redistributions of source code must retain the above copyright notice,
18
+ # this list of conditions and the following disclaimer.
19
+ #
20
+ # * Redistributions in binary form must reproduce the above copyright notice,
21
+ # this list of conditions and the following disclaimer in the documentation
22
+ # and/or other materials provided with the distribution.
23
+ #
24
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
28
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34
+ # POSSIBILITY OF SUCH DAMAGE.
35
+ #
36
+ # ######################################################################### #
37
+
38
+
39
+ require 'recls/entry'
40
+ require 'recls/flags'
41
+ require 'recls/ximpl/os'
42
+
43
+ module Recls
44
+
45
+ class FileSearch
46
+
47
+ include Enumerable
48
+
49
+ def initialize(search_root, patterns, flags)
50
+
51
+ if not search_root
52
+ search_root = '.'
53
+ else
54
+ search_root = search_root.to_s
55
+ end
56
+ search_root = '.' if search_root.empty?
57
+ search_root = File.expand_path(search_root) if '~' == search_root[0]
58
+
59
+ case patterns
60
+ when NilClass
61
+ patterns = []
62
+ when String
63
+ patterns = patterns.split(/[|#{Recls::Ximpl::OS::PATH_SEPARATOR}]/)
64
+ when Array
65
+ else
66
+ patterns = patterns.to_a
67
+ end
68
+
69
+ patterns = [ Recls::WILDCARDS_ALL ] if patterns.empty?
70
+
71
+ if(0 == (Recls::TYPEMASK & flags))
72
+ flags |= Recls::FILES
73
+ end
74
+
75
+ # now de-dup the patterns, to avoid duplicates in search
76
+ patterns = patterns.flatten
77
+ patterns = patterns.uniq
78
+
79
+ @search_root = search_root
80
+ @patterns = patterns
81
+ @flags = flags
82
+ end
83
+
84
+ attr_reader :search_root
85
+ attr_reader :patterns
86
+ attr_reader :flags
87
+
88
+ def each(&blk)
89
+
90
+ search_root = @search_root
91
+ search_root = Recls::Ximpl::absolute_path search_root
92
+
93
+ search_root = search_root.gsub(/\\/, '/') if Recls::Ximpl::OS::OS_IS_WINDOWS
94
+
95
+ # set the (type part of the) flags to zero if we want
96
+ # everything, to facilitate later optimisation
97
+
98
+ flags = @flags
99
+
100
+ if(Recls::Ximpl::OS::OS_IS_WINDOWS)
101
+ mask = (Recls::FILES | Recls::DIRECTORIES)
102
+ else
103
+ mask = (Recls::FILES | Recls::DIRECTORIES | Recls::LINKS | Recls::DEVICES)
104
+ end
105
+
106
+ if(mask == (mask & flags))
107
+ flags = flags & ~Recls::TYPEMASK
108
+ end
109
+
110
+ patterns = @patterns
111
+
112
+ patterns = patterns.map do |pattern|
113
+
114
+ pattern = pattern.gsub(/\./, '\\.')
115
+ pattern = pattern.gsub(/\?/, '.')
116
+ pattern = pattern.gsub(/\*/, '.*')
117
+ pattern
118
+ end
119
+
120
+ search_dir = search_root
121
+ search_root = Recls::Ximpl::Util.append_trailing_slash search_root
122
+
123
+ FileSearch::search_directory_(search_root, search_dir, patterns, flags, &blk)
124
+ end
125
+
126
+ private
127
+ def FileSearch::is_dots(name)
128
+
129
+ case name
130
+ when '.', '..'
131
+ true
132
+ else
133
+ false
134
+ end
135
+ end
136
+
137
+ def FileSearch::stat_or_nil_(path, flags)
138
+
139
+ begin
140
+ Recls::Ximpl::FileStat.stat path
141
+ rescue Errno::ENOENT => x
142
+ nil
143
+ rescue SystemCallError => x
144
+ # TODO this should be filtered up and/or logged
145
+
146
+ if(0 != (STOP_ON_ACCESS_FAILURE & flags))
147
+ raise
148
+ end
149
+
150
+ nil
151
+ end
152
+ end
153
+
154
+ # searches all entries - files, directories, links, devices
155
+ # - that match the given (patterns) in the given directory
156
+ # (dir) according to the given (flags), invoking the given
157
+ # block (blk). The search directory (search_root) is passed in
158
+ # order to allow calculation of search_relative_path in the
159
+ # entry.
160
+
161
+ def FileSearch::search_directory_(search_root, dir, patterns, flags, &blk)
162
+
163
+ # array of FileStat instances
164
+ entries = []
165
+
166
+ patterns.each do |pattern|
167
+
168
+ Recls::Ximpl::dir_entries_maybe(dir, flags).each do |name|
169
+
170
+ next if is_dots(name)
171
+
172
+ if not name =~ /^#{pattern}$/
173
+ next
174
+ end
175
+
176
+ entry_path = File::join(dir, name)
177
+
178
+ fs = stat_or_nil_(entry_path, flags)
179
+
180
+ entries << fs
181
+ end
182
+ end
183
+
184
+ # array of FileStat instances
185
+ subdirectories = []
186
+
187
+ Recls::Ximpl::dir_entries_maybe(dir, flags).each do |subdir|
188
+
189
+ next if is_dots(subdir)
190
+
191
+ subdir_path = File::join(dir, subdir)
192
+
193
+ fs = stat_or_nil_(subdir_path, flags)
194
+
195
+ next if not fs
196
+
197
+ next unless fs.directory?
198
+
199
+ subdirectories << fs
200
+ end
201
+
202
+
203
+ # now filter the file-stat instances and send each
204
+ # remaining to the block in Entry instance
205
+ entries.each do |fs|
206
+
207
+ next if not fs
208
+
209
+ if(0 == (Recls::SHOW_HIDDEN & flags))
210
+ if fs.hidden?
211
+ next
212
+ end
213
+ end
214
+
215
+ match = false
216
+
217
+ match ||= (0 != (Recls::FILES & flags) && fs.file?)
218
+ match ||= (0 != (Recls::DIRECTORIES & flags) && fs.directory?)
219
+ match ||= (0 != (Recls::DEVICES & flags) && fs.blockdev?)
220
+
221
+ next unless match
222
+
223
+ blk.call Recls::Entry.new(fs.path, fs, search_root, flags)
224
+ end
225
+
226
+ # sub-directories
227
+
228
+ return unless (0 != (Recls::RECURSIVE & flags))
229
+
230
+ subdirectories.each do |fs|
231
+
232
+ if(0 == (Recls::SHOW_HIDDEN & flags))
233
+ if fs.hidden?
234
+ next
235
+ end
236
+ end
237
+
238
+ if(0 == (Recls::SEARCH_THROUGH_LINKS & flags))
239
+ if File.symlink? fs.path
240
+ next
241
+ end
242
+ end
243
+
244
+ FileSearch::search_directory_(search_root, fs.path, patterns, flags, &blk)
245
+ end
246
+ end
247
+ end
248
+ end
249
+
250
+ # ############################## end of file ############################# #
251
+
@@ -0,0 +1,77 @@
1
+ # ######################################################################### #
2
+ # File: recls/flags.rb
3
+ #
4
+ # Purpose: Defines the Recls::Flags module for the recls.Ruby library.
5
+ #
6
+ # Created: 24th July 2012
7
+ # Updated: 27th August 2015
8
+ #
9
+ # Author: Matthew Wilson
10
+ #
11
+ # Copyright (c) 2012-2015, Matthew Wilson and Synesis Software
12
+ # All rights reserved.
13
+ #
14
+ # Redistribution and use in source and binary forms, with or without
15
+ # modification, are permitted provided that the following conditions are met:
16
+ #
17
+ # * Redistributions of source code must retain the above copyright notice,
18
+ # this list of conditions and the following disclaimer.
19
+ #
20
+ # * Redistributions in binary form must reproduce the above copyright notice,
21
+ # this list of conditions and the following disclaimer in the documentation
22
+ # and/or other materials provided with the distribution.
23
+ #
24
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
28
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34
+ # POSSIBILITY OF SUCH DAMAGE.
35
+ #
36
+ # ######################################################################### #
37
+
38
+
39
+ module Recls
40
+
41
+ # Specifies that files are to be listed
42
+ FILES = 0x00000001
43
+ # Specifies that directories are to be listed
44
+ DIRECTORIES = 0x00000002
45
+ # Specifies that links are to be listed (and not followed)
46
+ LINKS = 0x00000004
47
+ # Specifies that devices are to be listed
48
+ DEVICES = 0x00000008
49
+ TYPEMASK = 0x000000ff
50
+
51
+ # Specifies that hidden items are to be shown and hidden directories are
52
+ # to be searched
53
+ SHOW_HIDDEN = 0x00000100
54
+
55
+ DIR_PROGRESS = 0x00001000
56
+ # Causes search to terminate if a directory cannot be entered or an
57
+ # entry's information cannot be stat()'d
58
+ STOP_ON_ACCESS_FAILURE = 0x00002000
59
+ LINK_COUNT = 0000004000
60
+ NODE_INDEX = 0x00008000
61
+
62
+ RECURSIVE = 0x00010000
63
+ private
64
+ NO_SEARCH_LINKS = 0x00020000
65
+ public
66
+ DIRECTORY_PARTS = 0x00040000
67
+ DETAILS_LATER = 0x00080000
68
+
69
+ MARK_DIRECTORIES = 0x00200000
70
+
71
+ # Causes sub-directories that are links to be searched; default is not
72
+ # to search through links
73
+ SEARCH_THROUGH_LINKS = 0x00100000
74
+ end
75
+
76
+ # ############################## end of file ############################# #
77
+
@@ -0,0 +1,103 @@
1
+ # ######################################################################### #
2
+ # File: recls/foreach.rb
3
+ #
4
+ # Purpose: Definition of Recls::foreach() utility function
5
+ #
6
+ # Created: 22nd October 2014
7
+ # Updated: 27th August 2015
8
+ #
9
+ # Author: Matthew Wilson
10
+ #
11
+ # Copyright (c) 2012-2015, Matthew Wilson and Synesis Software
12
+ # All rights reserved.
13
+ #
14
+ # Redistribution and use in source and binary forms, with or without
15
+ # modification, are permitted provided that the following conditions are met:
16
+ #
17
+ # * Redistributions of source code must retain the above copyright notice,
18
+ # this list of conditions and the following disclaimer.
19
+ #
20
+ # * Redistributions in binary form must reproduce the above copyright notice,
21
+ # this list of conditions and the following disclaimer in the documentation
22
+ # and/or other materials provided with the distribution.
23
+ #
24
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
28
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34
+ # POSSIBILITY OF SUCH DAMAGE.
35
+ #
36
+ # ######################################################################### #
37
+
38
+
39
+ require 'recls/filesearch'
40
+
41
+ module Recls
42
+
43
+ private
44
+ class FileSearchLineEnumerator
45
+
46
+ include Enumerable
47
+
48
+ def initialize(fs)
49
+
50
+ @fs = fs
51
+ end
52
+
53
+ def each(&block)
54
+
55
+ @fs.each do |fe|
56
+
57
+ IO::readlines(fe).each_with_index do |line, index|
58
+
59
+ case block.arity
60
+ when 1
61
+ yield line
62
+ when 2
63
+ yield line, index
64
+ when 3
65
+ yield line, index, fe
66
+ else
67
+ raise ArgumentError, "block must take 1, 2, or 3 parameters - #{block.arity} given. (Perhaps you have applied each_with_index, which cannot be done to Recls.foreach)"
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+ public
74
+
75
+ def self.foreach(*args, &block)
76
+
77
+ fs = nil
78
+
79
+ case args.length
80
+ when 1
81
+ raise ArgumentError "Single argument must be of type #{Recls::FileSearch}" unless args[0].kind_of? Recls::FileSearch
82
+
83
+ fs = args[0]
84
+ when 3
85
+ fs = Recls::FileSearch.new(args[0], args[1], args[2])
86
+ else
87
+ raise ArgumentError "Function requires single argument (#{Recls::FileSearch}) or three arguments (directory, patterns, flags)"
88
+ end
89
+
90
+ if block_given?
91
+
92
+ FileSearchLineEnumerator.new(fs).each(block)
93
+
94
+ return nil
95
+ else
96
+
97
+ return FileSearchLineEnumerator.new(fs)
98
+ end
99
+ end
100
+ end
101
+
102
+ # ############################## end of file ############################# #
103
+
@@ -0,0 +1,113 @@
1
+ # ######################################################################### #
2
+ # File: recls/recls.rb
3
+ #
4
+ # Purpose: Main source file for recls library
5
+ #
6
+ # Created: 19th July 2012
7
+ # Updated: 29th December 2015
8
+ #
9
+ # Author: Matthew Wilson
10
+ #
11
+ # Copyright (c) 2012-2015, Matthew Wilson and Synesis Software
12
+ # All rights reserved.
13
+ #
14
+ # Redistribution and use in source and binary forms, with or without
15
+ # modification, are permitted provided that the following conditions are met:
16
+ #
17
+ # * Redistributions of source code must retain the above copyright notice,
18
+ # this list of conditions and the following disclaimer.
19
+ #
20
+ # * Redistributions in binary form must reproduce the above copyright notice,
21
+ # this list of conditions and the following disclaimer in the documentation
22
+ # and/or other materials provided with the distribution.
23
+ #
24
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
28
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34
+ # POSSIBILITY OF SUCH DAMAGE.
35
+ #
36
+ # ######################################################################### #
37
+
38
+
39
+ require 'recls/version'
40
+
41
+ require 'recls/filesearch'
42
+ require 'recls/foreach'
43
+ require 'recls/stat'
44
+ require 'recls/util'
45
+ require 'recls/ximpl/os'
46
+
47
+ module Recls
48
+
49
+ # Represents the "all" wildcards string for the ambient operating
50
+ # system
51
+ WILDCARDS_ALL = Recls::Ximpl::OS::WILDCARDS_ALL
52
+
53
+ PATH_NAME_SEPARATOR = Recls::Ximpl::OS::PATH_NAME_SEPARATOR
54
+
55
+ PATH_SEPARATOR = Recls::Ximpl::OS::PATH_SEPARATOR
56
+ end
57
+
58
+ # ######################################################################### #
59
+ # Obsolete symbols
60
+
61
+ if not defined? RECLS_NO_OBSOLETE
62
+
63
+ module Recls
64
+
65
+ def self.pathNameSeparator
66
+ PATH_NAME_SEPARATOR
67
+ end
68
+
69
+ def self.pathSeparator
70
+ PATH_SEPARATOR
71
+ end
72
+
73
+ def self.wildcardsAll
74
+ WILDCARDS_ALL
75
+ end
76
+
77
+ class FileSearch
78
+
79
+ alias_method :searchRoot, :search_root
80
+ alias_method :pattern, :patterns
81
+ end
82
+
83
+ class Entry
84
+
85
+ alias_method :uncDrive, :drive
86
+ alias_method :directoryPath, :directory_path
87
+ alias_method :directoryParts, :directory_parts
88
+ alias_method :file, :file_full_name
89
+ alias_method :shortFile, :file_short_name
90
+ alias_method :fileBaseName, :file_name_only
91
+ alias_method :fileName, :file_name_only
92
+ alias_method :fileExt, :file_extension
93
+ alias_method :searchDirectory, :search_directory
94
+ alias_method :searchRelativePath, :search_relative_path
95
+
96
+ alias_method :isDirectory, :directory?
97
+ alias_method :isFile, :file?
98
+ #alias_method :isLink, :link?
99
+ alias_method :isReadOnly, :readonly?
100
+ def isUNC
101
+
102
+ d = drive
103
+
104
+ d and d.size > 2
105
+ end
106
+
107
+ alias_method :creationTime, :modification_time
108
+ end
109
+ end
110
+ end
111
+
112
+ # ############################## end of file ############################# #
113
+