@@ -16,7 +16,7 @@ def initialize
1616
1717 BaseMetaDataFile = 'modules_metadata_base.json'
1818 UserMetaDataFile = 'modules_metadata.json'
19- CacheMetaDataFile = 'cache_metadata_base .json'
19+ CacheMetaDataFile = 'module_metadata_cache .json'
2020
2121 #
2222 # Initializes from user store (under ~/store/.msf4) if it exists. else base file (under $INSTALL_ROOT/db) is copied and loaded.
@@ -138,31 +138,33 @@ def self.valid_checksum?
138138
139139 # If no cached checksum exists, create the cache file with current checksum
140140 if cached_sha . nil?
141- create_or_update_cache_file ( get_cache_path , current_checksum )
141+ update_cache_checksum ( current_checksum )
142142 return false
143143 end
144144
145145 checksums_match? ( current_checksum , cached_sha )
146146 end
147147
148148 # Calculate the current checksum for all module and library files
149- # This calculates checksums for each file, caches them, and then
150- # generates an overall checksum from the individual file checksums.
149+ # This calculates checksums for each file and generates an overall checksum
150+ # from the individual file checksums. Does NOT update the cached checksum .
151151 #
152- # @return [String ] The current overall checksum
152+ # @return [Integer ] The current overall checksum
153153 def self . get_current_checksum
154154 files = collect_files_to_check
155- per_file_cache_file = get_per_file_cache_path
156- per_file_cache = load_per_file_cache ( per_file_cache_file )
155+ cache_file = get_cache_path
156+ cache_data = load_combined_cache ( cache_file )
157157
158- file_crc32s_with_metadata = calculate_file_checksums ( files , per_file_cache )
158+ files_lookup = { }
159+ cache_data [ 'files' ] . each { |entry | files_lookup [ entry [ 'path' ] ] = entry }
159160
160- updated_cache = file_crc32s_with_metadata . to_h
161- file_crc32s = file_crc32s_with_metadata . map { |_ , meta | meta [ 'crc32' ] }
161+ file_crc32s_with_metadata = calculate_file_checksums ( files , files_lookup )
162162
163- save_per_file_cache ( per_file_cache_file , updated_cache )
163+ file_crc32s = file_crc32s_with_metadata . map { | _ , meta | meta [ 'crc32' ] } . sort
164164
165- calculate_overall_checksum ( file_crc32s )
165+ overall_checksum = calculate_overall_checksum ( file_crc32s )
166+
167+ overall_checksum
166168 end
167169
168170 # Compare the current checksum with the cached checksum
@@ -175,9 +177,9 @@ def self.checksums_match?(current_checksum, cached_checksum)
175177
176178 # Calculate the overall checksum from individual file checksums
177179 # @param [Array<Integer>] file_crc32s Array of individual file CRC32 values
178- # @return [String ] The hexadecimal representation of the overall CRC32
180+ # @return [Integer ] The overall CRC32 as an integer
179181 def self . calculate_overall_checksum ( file_crc32s )
180- Zlib . crc32 ( file_crc32s . join ) . to_s ( 16 )
182+ Zlib . crc32 ( file_crc32s . join ( ',' ) , 0 )
181183 end
182184
183185 # Collect all files that need to be checked for checksums
@@ -204,7 +206,7 @@ def self.calculate_file_checksums(files, cache)
204206 if cache_entry && cache_entry [ 'mtime' ] == file_metadata . mtime . to_i && cache_entry [ 'size' ] == file_metadata . size
205207 crc32 = cache_entry [ 'crc32' ]
206208 else
207- crc32 = File . open ( file , 'rb' ) { |fd | Zlib . crc32 ( fd . read ) }
209+ crc32 = File . open ( file , 'rb' ) { |fd | Zlib . crc32 ( fd . read , 0 ) }
208210 end
209211 # Return file and its metadata for later aggregation
210212 [ file , {
@@ -215,80 +217,74 @@ def self.calculate_file_checksums(files, cache)
215217 end
216218 end
217219
218- # Get the path to the per-file cache
219- # @return [String] Path to the per-file cache
220- def self . get_per_file_cache_path
221- File . join ( Msf ::Config . config_directory , 'store' , 'per_file_metadata_cache.json' )
222- end
223-
224220 # Get the path to the cache file
225221 # @return [String] Path to the cache file
226222 def self . get_cache_path
227223 File . join ( Msf ::Config . config_directory , "store" , CacheMetaDataFile )
228224 end
229225
230- # Load the per-file cache from disk
226+ # Load the combined cache from disk (contains both files and checksum)
231227 # @param [String] cache_file Path to the cache file
232- # @return [Hash] The loaded cache or an empty hash if the file doesn't exist
233- def self . load_per_file_cache ( cache_file )
234- File . exist? ( cache_file ) ? JSON . parse ( File . read ( cache_file ) ) : { }
228+ # @return [Hash] The loaded cache with 'files' and 'checksum' keys, or empty structure if file doesn't exist
229+ def self . load_combined_cache ( cache_file )
230+ if File . exist? ( cache_file )
231+ cache_content = JSON . parse ( File . read ( cache_file ) )
232+ # Ensure the cache has the expected structure
233+ {
234+ 'files' => cache_content [ 'files' ] || [ ] ,
235+ 'checksum' => cache_content [ 'checksum' ]
236+ }
237+ else
238+ { 'files' => [ ] , 'checksum' => nil }
239+ end
235240 end
236241
237- # Save the updated per-file cache to disk
242+ # Save the combined cache to disk (files and checksum in one file)
238243 # @param [String] cache_file Path to the cache file
239- # @param [Hash] updated_cache The cache data to save
244+ # @param [Hash] files_cache The per-file cache data
245+ # @param [Integer] overall_checksum The overall checksum
240246 # @return [void]
241- def self . save_per_file_cache ( cache_file , updated_cache )
247+ def self . save_combined_cache ( cache_file , files_cache , overall_checksum )
242248 # Ensure the directory for the cache file exists before writing
243249 FileUtils . mkdir_p ( File . dirname ( cache_file ) )
244- # Save the updated per-file cache to disk
245- File . write ( cache_file , JSON . pretty_generate ( updated_cache ) )
246- end
247250
248- # Create or update a cache file with the given checksum
249- # @param [String] file_path Path to the cache file
250- # @param [String] checksum The checksum to store
251- # @return [void]
252- def self . create_or_update_cache_file ( file_path , checksum )
253- # Ensure directory exists
254- FileUtils . mkdir_p ( File . dirname ( file_path ) )
255-
256- if File . exist? ( file_path )
257- # Update existing file
258- cache_content = JSON . parse ( File . read ( file_path ) )
259- cache_content [ 'checksum' ] [ 'crc32' ] = checksum
260- else
261- # Create new file
262- cache_content = {
263- "checksum" => {
264- "crc32" => checksum
265- }
266- }
267- end
251+ cache_content = {
252+ 'checksum' => overall_checksum ,
253+ 'files' => files_cache
254+ }
268255
269- File . write ( file_path , JSON . pretty_generate ( cache_content ) )
256+ File . write ( cache_file , JSON . pretty_generate ( cache_content ) )
270257 end
271258
272- # Get the cached checksum value from the user's cache file
273- # @return [String , nil] The cached checksum value or nil if no cache exists
259+ # Get the cached checksum value from the combined cache file
260+ # @return [Integer , nil] The cached checksum value or nil if no cache exists
274261 def self . get_cached_checksum
275262 cache_path = get_cache_path
276-
277- if File . exist? ( cache_path )
278- cache_content = JSON . parse ( File . read ( cache_path ) )
279- return cache_content . dig ( 'checksum' , 'crc32' )
280- end
281-
282- # If no cache exists, return nil to trigger creation of a new cache file
283- nil
263+ cache_data = load_combined_cache ( cache_path )
264+ cache_data [ 'checksum' ]
284265 end
285266
286- # Update the cache checksum file with the current crc32 checksum of the module paths.
287- #
288- # @param [String] current_checksum The current checksum to store in the cache
267+ # Update the cache with the current checksum and file data
268+ # @param [Integer] current_checksum The current checksum to store in the cache
289269 # @return [void]
290270 def self . update_cache_checksum ( current_checksum )
291- cache_path = get_cache_path
292- create_or_update_cache_file ( cache_path , current_checksum )
271+ # Recalculate file checksums and update both overall checksum and file cache
272+ files = collect_files_to_check
273+ cache_file = get_cache_path
274+ cache_data = load_combined_cache ( cache_file )
275+
276+ files_lookup = { }
277+ cache_data [ 'files' ] . each { |entry | files_lookup [ entry [ 'path' ] ] = entry }
278+
279+ file_crc32s_with_metadata = calculate_file_checksums ( files , files_lookup )
280+
281+ updated_files_cache = file_crc32s_with_metadata . map do |file_path , metadata |
282+ metadata . merge ( 'path' => file_path )
283+ end
284+
285+ updated_files_cache . sort_by! { |entry | entry [ 'path' ] }
286+
287+ # Save both the updated file cache and the new overall checksum
288+ save_combined_cache ( cache_file , updated_files_cache , current_checksum )
293289 end
294290end
0 commit comments