@@ -16,7 +16,7 @@ def initialize
16
16
17
17
BaseMetaDataFile = 'modules_metadata_base.json'
18
18
UserMetaDataFile = 'modules_metadata.json'
19
- CacheMetaDataFile = 'cache_metadata_base .json'
19
+ CacheMetaDataFile = 'module_metadata_cache .json'
20
20
21
21
#
22
22
# 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?
138
138
139
139
# If no cached checksum exists, create the cache file with current checksum
140
140
if cached_sha . nil?
141
- create_or_update_cache_file ( get_cache_path , current_checksum )
141
+ update_cache_checksum ( current_checksum )
142
142
return false
143
143
end
144
144
145
145
checksums_match? ( current_checksum , cached_sha )
146
146
end
147
147
148
148
# 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 .
151
151
#
152
- # @return [String ] The current overall checksum
152
+ # @return [Integer ] The current overall checksum
153
153
def self . get_current_checksum
154
154
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 )
157
157
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 }
159
160
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 )
162
162
163
- save_per_file_cache ( per_file_cache_file , updated_cache )
163
+ file_crc32s = file_crc32s_with_metadata . map { | _ , meta | meta [ 'crc32' ] } . sort
164
164
165
- calculate_overall_checksum ( file_crc32s )
165
+ overall_checksum = calculate_overall_checksum ( file_crc32s )
166
+
167
+ overall_checksum
166
168
end
167
169
168
170
# Compare the current checksum with the cached checksum
@@ -175,9 +177,9 @@ def self.checksums_match?(current_checksum, cached_checksum)
175
177
176
178
# Calculate the overall checksum from individual file checksums
177
179
# @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
179
181
def self . calculate_overall_checksum ( file_crc32s )
180
- Zlib . crc32 ( file_crc32s . join ) . to_s ( 16 )
182
+ Zlib . crc32 ( file_crc32s . join ( ',' ) , 0 )
181
183
end
182
184
183
185
# Collect all files that need to be checked for checksums
@@ -204,7 +206,7 @@ def self.calculate_file_checksums(files, cache)
204
206
if cache_entry && cache_entry [ 'mtime' ] == file_metadata . mtime . to_i && cache_entry [ 'size' ] == file_metadata . size
205
207
crc32 = cache_entry [ 'crc32' ]
206
208
else
207
- crc32 = File . open ( file , 'rb' ) { |fd | Zlib . crc32 ( fd . read ) }
209
+ crc32 = File . open ( file , 'rb' ) { |fd | Zlib . crc32 ( fd . read , 0 ) }
208
210
end
209
211
# Return file and its metadata for later aggregation
210
212
[ file , {
@@ -215,80 +217,74 @@ def self.calculate_file_checksums(files, cache)
215
217
end
216
218
end
217
219
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
-
224
220
# Get the path to the cache file
225
221
# @return [String] Path to the cache file
226
222
def self . get_cache_path
227
223
File . join ( Msf ::Config . config_directory , "store" , CacheMetaDataFile )
228
224
end
229
225
230
- # Load the per-file cache from disk
226
+ # Load the combined cache from disk (contains both files and checksum)
231
227
# @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
235
240
end
236
241
237
- # Save the updated per-file cache to disk
242
+ # Save the combined cache to disk (files and checksum in one file)
238
243
# @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
240
246
# @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 )
242
248
# Ensure the directory for the cache file exists before writing
243
249
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
247
250
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
+ }
268
255
269
- File . write ( file_path , JSON . pretty_generate ( cache_content ) )
256
+ File . write ( cache_file , JSON . pretty_generate ( cache_content ) )
270
257
end
271
258
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
274
261
def self . get_cached_checksum
275
262
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' ]
284
265
end
285
266
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
289
269
# @return [void]
290
270
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 )
293
289
end
294
290
end
0 commit comments