recls-ruby 2.6.4

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.
@@ -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
+