manageiq-smartstate 0.6.0 → 0.8.0

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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +34 -35
  3. data/.rubocop.yml +3 -3
  4. data/.rubocop_cc.yml +3 -4
  5. data/.rubocop_local.yml +1 -1
  6. data/.travis.yml +2 -3
  7. data/lib/MiqVm/MiqRhevmVm.rb +1 -1
  8. data/lib/db/MiqBdb/MiqBdb.rb +0 -2
  9. data/lib/db/MiqBdb/MiqBdbPage.rb +0 -2
  10. data/lib/db/MiqSqlite/MiqSqlite3.rb +0 -2
  11. data/lib/db/MiqSqlite/MiqSqlite3Cell.rb +0 -2
  12. data/lib/db/MiqSqlite/MiqSqlite3Page.rb +0 -2
  13. data/lib/db/MiqSqlite/MiqSqlite3Table.rb +0 -2
  14. data/lib/disk/modules/MSCommon.rb +3 -1
  15. data/lib/disk/modules/VhdxDisk.rb +3 -1
  16. data/lib/fs/MiqMountManager.rb +2 -29
  17. data/lib/fs/VimDatastoreFS/VimDatastoreFS.rb +1 -6
  18. data/lib/fs/fat32/directory_entry.rb +540 -540
  19. data/lib/fs/iso9660/boot_sector.rb +3 -2
  20. data/lib/fs/iso9660/directory_entry.rb +3 -2
  21. data/lib/fs/iso9660/rock_ridge.rb +3 -1
  22. data/lib/fs/ntfs/attrib_attribute_list.rb +3 -1
  23. data/lib/fs/ntfs/attrib_file_name.rb +3 -1
  24. data/lib/fs/ntfs/attrib_header.rb +3 -1
  25. data/lib/fs/ntfs/attrib_index_root.rb +3 -1
  26. data/lib/fs/ntfs/attrib_volume_name.rb +3 -1
  27. data/lib/manageiq/smartstate/util.rb +18 -0
  28. data/lib/manageiq/smartstate/version.rb +1 -1
  29. data/lib/metadata/MIQExtract/MIQExtract.rb +2 -3
  30. data/lib/metadata/VmConfig/GetNativeCfg.rb +2 -4
  31. data/lib/metadata/VmConfig/VmConfig.rb +7 -6
  32. data/lib/metadata/VmConfig/cfgConfig.rb +4 -0
  33. data/lib/metadata/VmConfig/xmlConfig.rb +3 -3
  34. data/lib/metadata/linux/MiqRpmPackages.rb +3 -1
  35. data/lib/metadata/util/win32/Win32Accounts.rb +3 -1
  36. data/lib/metadata/util/win32/Win32EventLog.rb +3 -1
  37. data/lib/metadata/util/win32/Win32Software.rb +5 -3
  38. data/lib/metadata/util/win32/decode.rb +0 -0
  39. data/lib/metadata/util/win32/fleece_hives.rb +0 -9
  40. data/lib/metadata/util/win32/ms-registry.rb +3 -2
  41. data/lib/metadata/util/win32/peheader.rb +3 -2
  42. data/lib/metadata/util/win32/system_path_win.rb +0 -2
  43. data/lib/miq_unicode.rb +45 -0
  44. data/manageiq-smartstate.gemspec +8 -6
  45. metadata +66 -23
  46. data/lib/fs/MetakitFS/MetakitFS.rb +0 -530
@@ -20,6 +20,8 @@ Gem::Specification.new do |spec|
20
20
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
21
  spec.require_paths = ["lib"]
22
22
 
23
+ spec.add_dependency "activesupport"
24
+ spec.add_dependency "awesome_spawn", "~> 1.5"
23
25
  spec.add_dependency "azure-armrest", "~> 0.9"
24
26
  spec.add_dependency "binary_struct", "~> 2.1"
25
27
  spec.add_dependency "iniparse"
@@ -29,16 +31,16 @@ Gem::Specification.new do |spec|
29
31
  spec.add_dependency "rufus-lru", "~>1.0.3"
30
32
  spec.add_dependency "sys-uname", "~>1.2.1"
31
33
  spec.add_dependency "uuidtools", "~>2.1"
32
- spec.add_dependency "vmware_web_service", "~>2.0"
34
+ spec.add_dependency "vmware_web_service", "~>3.0"
33
35
 
34
36
  spec.add_development_dependency "bundler"
37
+ spec.add_development_dependency "camcorder"
38
+ spec.add_development_dependency "codeclimate-test-reporter", "~> 1.0.0"
39
+ spec.add_development_dependency "manageiq-style"
35
40
  spec.add_development_dependency "rake"
36
41
  spec.add_development_dependency "rspec", "~> 3.0"
37
- spec.add_development_dependency "camcorder"
42
+ spec.add_development_dependency "simplecov"
43
+ spec.add_development_dependency "sqlite3"
38
44
  spec.add_development_dependency "vcr", "~>3.0.2"
39
45
  spec.add_development_dependency "webmock", "~>2.3.1"
40
- spec.add_development_dependency "simplecov"
41
- spec.add_development_dependency "rubocop"
42
- spec.add_development_dependency "codeclimate-test-reporter", "~> 1.0.0"
43
-
44
46
  end
metadata CHANGED
@@ -1,15 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: manageiq-smartstate
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.8.0
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-08-04 00:00:00.000000000 Z
11
+ date: 2021-07-16 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: awesome_spawn
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.5'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.5'
13
41
  - !ruby/object:Gem::Dependency
14
42
  name: azure-armrest
15
43
  requirement: !ruby/object:Gem::Requirement
@@ -142,14 +170,14 @@ dependencies:
142
170
  requirements:
143
171
  - - "~>"
144
172
  - !ruby/object:Gem::Version
145
- version: '2.0'
173
+ version: '3.0'
146
174
  type: :runtime
147
175
  prerelease: false
148
176
  version_requirements: !ruby/object:Gem::Requirement
149
177
  requirements:
150
178
  - - "~>"
151
179
  - !ruby/object:Gem::Version
152
- version: '2.0'
180
+ version: '3.0'
153
181
  - !ruby/object:Gem::Dependency
154
182
  name: bundler
155
183
  requirement: !ruby/object:Gem::Requirement
@@ -165,7 +193,7 @@ dependencies:
165
193
  - !ruby/object:Gem::Version
166
194
  version: '0'
167
195
  - !ruby/object:Gem::Dependency
168
- name: rake
196
+ name: camcorder
169
197
  requirement: !ruby/object:Gem::Requirement
170
198
  requirements:
171
199
  - - ">="
@@ -179,21 +207,21 @@ dependencies:
179
207
  - !ruby/object:Gem::Version
180
208
  version: '0'
181
209
  - !ruby/object:Gem::Dependency
182
- name: rspec
210
+ name: codeclimate-test-reporter
183
211
  requirement: !ruby/object:Gem::Requirement
184
212
  requirements:
185
213
  - - "~>"
186
214
  - !ruby/object:Gem::Version
187
- version: '3.0'
215
+ version: 1.0.0
188
216
  type: :development
189
217
  prerelease: false
190
218
  version_requirements: !ruby/object:Gem::Requirement
191
219
  requirements:
192
220
  - - "~>"
193
221
  - !ruby/object:Gem::Version
194
- version: '3.0'
222
+ version: 1.0.0
195
223
  - !ruby/object:Gem::Dependency
196
- name: camcorder
224
+ name: manageiq-style
197
225
  requirement: !ruby/object:Gem::Requirement
198
226
  requirements:
199
227
  - - ">="
@@ -207,33 +235,33 @@ dependencies:
207
235
  - !ruby/object:Gem::Version
208
236
  version: '0'
209
237
  - !ruby/object:Gem::Dependency
210
- name: vcr
238
+ name: rake
211
239
  requirement: !ruby/object:Gem::Requirement
212
240
  requirements:
213
- - - "~>"
241
+ - - ">="
214
242
  - !ruby/object:Gem::Version
215
- version: 3.0.2
243
+ version: '0'
216
244
  type: :development
217
245
  prerelease: false
218
246
  version_requirements: !ruby/object:Gem::Requirement
219
247
  requirements:
220
- - - "~>"
248
+ - - ">="
221
249
  - !ruby/object:Gem::Version
222
- version: 3.0.2
250
+ version: '0'
223
251
  - !ruby/object:Gem::Dependency
224
- name: webmock
252
+ name: rspec
225
253
  requirement: !ruby/object:Gem::Requirement
226
254
  requirements:
227
255
  - - "~>"
228
256
  - !ruby/object:Gem::Version
229
- version: 2.3.1
257
+ version: '3.0'
230
258
  type: :development
231
259
  prerelease: false
232
260
  version_requirements: !ruby/object:Gem::Requirement
233
261
  requirements:
234
262
  - - "~>"
235
263
  - !ruby/object:Gem::Version
236
- version: 2.3.1
264
+ version: '3.0'
237
265
  - !ruby/object:Gem::Dependency
238
266
  name: simplecov
239
267
  requirement: !ruby/object:Gem::Requirement
@@ -249,7 +277,7 @@ dependencies:
249
277
  - !ruby/object:Gem::Version
250
278
  version: '0'
251
279
  - !ruby/object:Gem::Dependency
252
- name: rubocop
280
+ name: sqlite3
253
281
  requirement: !ruby/object:Gem::Requirement
254
282
  requirements:
255
283
  - - ">="
@@ -263,19 +291,33 @@ dependencies:
263
291
  - !ruby/object:Gem::Version
264
292
  version: '0'
265
293
  - !ruby/object:Gem::Dependency
266
- name: codeclimate-test-reporter
294
+ name: vcr
267
295
  requirement: !ruby/object:Gem::Requirement
268
296
  requirements:
269
297
  - - "~>"
270
298
  - !ruby/object:Gem::Version
271
- version: 1.0.0
299
+ version: 3.0.2
272
300
  type: :development
273
301
  prerelease: false
274
302
  version_requirements: !ruby/object:Gem::Requirement
275
303
  requirements:
276
304
  - - "~>"
277
305
  - !ruby/object:Gem::Version
278
- version: 1.0.0
306
+ version: 3.0.2
307
+ - !ruby/object:Gem::Dependency
308
+ name: webmock
309
+ requirement: !ruby/object:Gem::Requirement
310
+ requirements:
311
+ - - "~>"
312
+ - !ruby/object:Gem::Version
313
+ version: 2.3.1
314
+ type: :development
315
+ prerelease: false
316
+ version_requirements: !ruby/object:Gem::Requirement
317
+ requirements:
318
+ - - "~>"
319
+ - !ruby/object:Gem::Version
320
+ version: 2.3.1
279
321
  description: ManageIQ SmartState Analysis
280
322
  email:
281
323
  executables: []
@@ -376,7 +418,6 @@ files:
376
418
  - lib/disk/modules/miq_dummy_disk.rb
377
419
  - lib/disk/modules/vhdx_bat_entry.rb
378
420
  - lib/disk/test.rb
379
- - lib/fs/MetakitFS/MetakitFS.rb
380
421
  - lib/fs/MiqFS/FsProbe.rb
381
422
  - lib/fs/MiqFS/MiqFS.rb
382
423
  - lib/fs/MiqFS/modules/AUFSProbe.rb
@@ -546,6 +587,7 @@ files:
546
587
  - lib/metadata/util/win32/Win32Software.rb
547
588
  - lib/metadata/util/win32/Win32System.rb
548
589
  - lib/metadata/util/win32/boot_info_win.rb
590
+ - lib/metadata/util/win32/decode.rb
549
591
  - lib/metadata/util/win32/fleece_hives.rb
550
592
  - lib/metadata/util/win32/ms-registry.rb
551
593
  - lib/metadata/util/win32/peheader.rb
@@ -553,6 +595,7 @@ files:
553
595
  - lib/metadata/util/win32/system_path_win.rb
554
596
  - lib/metadata/util/win32/versioninfo.rb
555
597
  - lib/miq_tempfile.rb
598
+ - lib/miq_unicode.rb
556
599
  - lib/tasks/azure.rake
557
600
  - log/.gitkeep
558
601
  - manageiq-smartstate.gemspec
@@ -575,7 +618,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
575
618
  - !ruby/object:Gem::Version
576
619
  version: '0'
577
620
  requirements: []
578
- rubygems_version: 3.1.3
621
+ rubygems_version: 3.2.5
579
622
  signing_key:
580
623
  specification_version: 4
581
624
  summary: ManageIQ SmartState Analysis
@@ -1,530 +0,0 @@
1
- # encoding: US-ASCII
2
-
3
- require 'mk4rb'
4
-
5
- module MetakitFS
6
- MK_FENTRY = "fentry[fpath:S,ftype:I,fsize:I,ftags:B,fdata:B]"
7
- MK_HASHVW = "sec[_H:I,_R:I]"
8
-
9
- TYPE_FILE = 1
10
- TYPE_DIR = 2
11
- TYPE_SYMLINK = 3
12
-
13
- def self.supported?(dobj)
14
- return(false) unless dobj.mkfile
15
- storage = Metakit::Storage.open(dobj.mkfile, 1)
16
- return(false) if storage.description != "#{MK_FENTRY},#{MK_HASHVW}"
17
- (true)
18
- end
19
-
20
- def fs_init
21
- raise "No metakit file has been specified" unless @dobj.mkfile
22
- @storage = Metakit::Storage.open(@dobj.mkfile, 1)
23
-
24
- newFs = false
25
- if @storage.description != "#{MK_FENTRY},#{MK_HASHVW}"
26
- raise "#{@dobj.mkfile} is not a MetakitFS" unless @dobj.create
27
- newFs = true
28
- end
29
-
30
- self.fsType = "MetakitFS"
31
-
32
- vData = @storage.get_as MK_FENTRY
33
- vSec = @storage.get_as MK_HASHVW
34
- @vFentry = vData.hash(vSec, 1)
35
-
36
- @pPath = Metakit::StringProp.new "fpath"
37
- @pType = Metakit::IntProp.new "ftype"
38
- @pSize = Metakit::IntProp.new "fsize"
39
- @pTags = Metakit::BytesProp.new "ftags"
40
- @pData = Metakit::BytesProp.new "fdata"
41
-
42
- @findRow = Metakit::Row.new
43
-
44
- #
45
- # If we're creating a new file system, create the root directory.
46
- #
47
- if newFs
48
- create("/", TYPE_DIR) if newFs
49
- @storage.commit
50
- end
51
-
52
- labels = fs_tagValues("/", "LABEL")
53
- @fsId = labels[0] unless labels.empty?
54
- end
55
-
56
- def fs_dirEntries(p)
57
- raise "Directory: #{p} does not exist" if (i = getFileIndex(p)) < 0
58
- raise "#{p} is not a directory" if @pType.get(@vFentry[i]) != TYPE_DIR
59
-
60
- data = @pData.get(@vFentry[i])
61
- return [] if data.size == 0
62
- data.contents.split("\0")
63
- end
64
-
65
- def fs_dirMkdir(p)
66
- #
67
- # If the target exists, succeed if it is a directory, otherwise fail.
68
- #
69
- if (i = getFileIndex(p)) >= 0
70
- return if @pType.get(@vFentry[i]) == TYPE_DIR
71
- raise "Cannot create directory, #{p}: file exists"
72
- end
73
-
74
- #
75
- # Create the directory.
76
- #
77
- create(p, TYPE_DIR)
78
-
79
- #
80
- # Apply changes to database.
81
- #
82
- @storage.commit
83
- end
84
-
85
- def fs_dirRmdir(p)
86
- #
87
- # Before we can remove a directory, it must:
88
- # exist, be a directory and be empty.
89
- #
90
- raise "#{p}: no such directory" if (di = getFileIndex(p)) < 0
91
- dirRow = @vFentry[di]
92
- raise "#{p}: not a directory" if @pType.get(dirRow) != TYPE_DIR
93
- raise "#{p}: directory not empty" if @pSize.get(dirRow) != 0
94
-
95
- rmCommon(p, di)
96
- end
97
-
98
- def fs_fileExists?(p)
99
- return false if getFileIndex(p) < 0
100
- true
101
- end
102
-
103
- def fs_fileFile?(p)
104
- return false if (i = getFileIndex(p)) < 0
105
- return true if @pType.get(@vFentry[i]) == TYPE_FILE
106
- false
107
- end
108
-
109
- def fs_fileDirectory?(p)
110
- return false if (i = getFileIndex(p)) < 0
111
- return true if @pType.get(@vFentry[i]) == TYPE_DIR
112
- false
113
- end
114
-
115
- def fs_fileSize(p)
116
- raise "File: #{p} does not exist" if (i = getFileIndex(p)) < 0
117
- (@pSize.get(@vFentry[i]))
118
- end
119
-
120
- def fs_fileSize_obj(fobj)
121
- (@pSize.get(fobj.fileRow))
122
- end
123
-
124
- def fs_fileAtime(p)
125
- File.atime(p)
126
- end
127
-
128
- def fs_fileCtime(p)
129
- File.ctime(p)
130
- end
131
-
132
- def fs_fileMtime(p)
133
- File.mtime(p)
134
- end
135
-
136
- def fs_fileAtime_obj(fobj)
137
- fobj.atime
138
- end
139
-
140
- def fs_fileCtime_obj(fobj)
141
- fobj.ctime
142
- end
143
-
144
- def fs_fileMtime_obj(fobj)
145
- fobj.mtime
146
- end
147
-
148
- def fs_fileOpen(p, mode = "r")
149
- fread = fwrite = fcreate = ftruncate = fappend = false
150
- mode.delete!("b")
151
-
152
- case mode[0, 1]
153
- when "r"
154
- fread = true
155
- fwrite = true if mode[-1, 1] == "+"
156
- when "w"
157
- fwrite = true
158
- fcreate = true
159
- ftruncate = true
160
- fread = true if mode[-1, 1] == "+"
161
- when "a"
162
- fwrite = true
163
- fcreate = true
164
- fappend = true
165
- fread = true if mode[-1, 1] == "+"
166
- else
167
- raise "Unrecognized open mode: #{mode}"
168
- end
169
-
170
- fileRow = nil
171
- fi = getFileIndex(p)
172
-
173
- if fi < 0
174
- #
175
- # Should we create the file? If not, fail.
176
- #
177
- raise "#{p}: No such file" unless fcreate
178
-
179
- #
180
- # Create the file if it doesn't exist.
181
- #
182
- fileRow = create(p, TYPE_FILE)
183
- fi = getFileIndex(p)
184
- else
185
- fileRow = @vFentry[fi]
186
- end
187
-
188
- fpos = 0
189
- fsize = @pSize.get(fileRow)
190
- if ftruncate && fsize != 0
191
- @pSize.set fileRow, 0
192
- @pData.set fileRow, Metakit::Bytes.new("", 0)
193
- @storage.commit
194
- elsif fappend
195
- fpos = fsize
196
- end
197
-
198
- (MkFile.new(p, fileRow, fpos, fread, fwrite))
199
- end # def fs_fileOpen
200
-
201
- def fs_fileSeek(fobj, _offset, whence)
202
- seekPos = 0
203
- case whence
204
- when IO::SEEK_CUR
205
- seekPos = filePos + amt
206
- when IO::SEEK_END
207
- seekPos = fs_fileSize_obj(fobj) + amt
208
- when IO::SEEK_SET
209
- seekPos = amt
210
- else
211
- raise "Invalid whence value: #{whence}"
212
- end
213
- raise "Invalid seek position: #{seekPos}" if seekPos < 0 || seekPos > fs_fileSize_obj(fobj)
214
-
215
- fobj.filePos = seekPos
216
- end
217
-
218
- def fs_fileRead(fobj, len)
219
- dataRef = @pData.ref(fobj.fileRow)
220
- rb = dataRef.access(fobj.filePos, len)
221
- fobj.filePos += rb.size
222
- return(rb.contents) if rb.contents.length > 0
223
- (nil)
224
- end
225
-
226
- def fs_fileWrite(fobj, buf, len)
227
- raise "fs_fileWrite: write length is larger than buffer" if len > buf.length
228
- size = fs_fileSize_obj(fobj)
229
-
230
- if fobj.filePos == size
231
- #
232
- # We're appending to the end of the file, so we can just use the
233
- # modify operation to add the data to the end of the file.
234
- #
235
- dataRef = @pData.ref(fobj.fileRow)
236
- data = Metakit::Bytes.new(buf, len)
237
- dataRef.modify(data, size, len)
238
- @pSize.set(fobj.fileRow, size + len)
239
- fobj.filePos += len
240
- @storage.commit
241
- return(len)
242
- end
243
- #
244
- # The Metakit modify operation inserts data. So if we need to overwrite
245
- # existing data, we must read the whole file, modify the data, and write
246
- # it out again.
247
- #
248
- dataStr = @pData.get(fobj.fileRow).contents
249
- dataStr[fobj.filePos, len] = buf[0, len]
250
- data = Metakit::Bytes.new(dataStr, dataStr.length)
251
- @pData.set(fobj.fileRow, data)
252
- @pSize.set(fobj.fileRow, dataStr.length)
253
- @storage.commit
254
- (len)
255
- end
256
-
257
- def fs_fileClose(_fobj)
258
- nil
259
- end
260
-
261
- def fs_fileDelete(p)
262
- #
263
- # Before we can remove a directory, it must:
264
- # exist, be a directory and be empty.
265
- #
266
- raise "#{p}: no such file" if (fi = getFileIndex(p)) < 0
267
- dirRow = @vFentry[di]
268
- raise "#{p}: is a directory" if @pType.get(dirRow) == TYPE_DIR
269
-
270
- rmCommon(p, fi)
271
- end
272
-
273
- def tagAdd(p, tag)
274
- fs_tagAdd(normalizePath(p), tag)
275
- end
276
-
277
- def fs_tagAdd(p, tag)
278
- raise "Path: #{p} does not exist" if (i = getFileIndex(p)) < 0
279
- fileRow = @vFentry[i]
280
- fs_tagAddCommon(fileRow, tag)
281
- end
282
-
283
- def fs_fileTagAdd(fobj, tag)
284
- fs_tagAddCommon(fobj.fileRow, tag)
285
- end
286
-
287
- def fs_tagAddCommon(fileRow, tag)
288
- tagStr = @pTags.get(fileRow).contents
289
- tags = tagStr.split("\0")
290
- return if tags.include? tag
291
- tags << tag
292
- tagStr = tags.join("\0")
293
- @pTags.set(fileRow, Metakit::Bytes.new(tagStr, tagStr.length))
294
- @storage.commit
295
- end
296
-
297
- def tagDelete(p, tag)
298
- fs_tagDelete(normalizePath(p), tag)
299
- end
300
-
301
- def fs_tagDelete(p, tag)
302
- raise "Path: #{p} does not exist" if (i = getFileIndex(p)) < 0
303
- fileRow = @vFentry[i]
304
- fs_tagDeleteCommon(fileRow, tag)
305
- end
306
-
307
- def fs_fileTagDelete(fobj, tag)
308
- fs_tagDeleteCommon(fobj.fileRow, tag)
309
- end
310
-
311
- def fs_tagDeleteCommon(fileRow, tag)
312
- tagStr = @pTags.get(fileRow).contents
313
- tags = tagStr.split("\0")
314
- tags.delete(tag) { raise "Tag #{tag} not found" }
315
- tagStr = tags.join("\0")
316
- @pTags.set(fileRow, Metakit::Bytes.new(tagStr, tagStr.length))
317
- @storage.commit
318
- end
319
-
320
- def tags(p)
321
- fs_tags(normalizePath(p))
322
- end
323
-
324
- def fs_tags(p)
325
- raise "Path: #{p} does not exist" if (i = getFileIndex(p)) < 0
326
- fileRow = @vFentry[i]
327
- fs_tagsCommon(fileRow)
328
- end
329
-
330
- def fs_fileTags(fobj)
331
- fs_tagsCommon(fobj.fileRow)
332
- end
333
-
334
- def fs_tagsCommon(fileRow)
335
- tags = @pTags.get(fileRow)
336
- return [] if tags.size == 0
337
- tags.contents.split("\0")
338
- end
339
-
340
- def hasTagName?(p, tag)
341
- fs_hasTagName?(normalizePath(p), tag)
342
- end
343
-
344
- def fs_hasTagName?(p, tagName)
345
- raise "Path: #{p} does not exist" if (i = getFileIndex(p)) < 0
346
- fileRow = @vFentry[i]
347
- fs_hasTagNameCommon?(fileRow, tagName)
348
- end
349
-
350
- def fs_fileHasTagName?(fobj, tagName)
351
- fs_hasTagNameCommon?(fobj.fileRow, tagName)
352
- end
353
-
354
- def fs_hasTagNameCommon?(fileRow, tagName)
355
- fs_tagsCommon(fileRow).each { |t| return true if t =~ /#{tagName}(=.*)*$/ }
356
- false
357
- end
358
-
359
- def hasTag?(p, tag)
360
- fs_hasTag?(normalizePath(p), tag)
361
- end
362
-
363
- def fs_hasTag?(p, tag)
364
- raise "Path: #{p} does not exist" if (i = getFileIndex(p)) < 0
365
- fileRow = @vFentry[i]
366
- fs_hasTagCommon?(fileRow, tag)
367
- end
368
-
369
- def fs_fileHasTag?(fobj, tag)
370
- fs_tagsCommon(fobj.fileRow).include?(tag)
371
- end
372
-
373
- def fs_hasTagCommon?(fileRow, tag)
374
- fs_tagsCommon(fileRow).include?(tag)
375
- end
376
-
377
- def tagValues(p, tag)
378
- fs_tagValues(normalizePath(p), tag)
379
- end
380
-
381
- def fs_tagValues(p, tag)
382
- raise "Path: #{p} does not exist" if (i = getFileIndex(p)) < 0
383
- fileRow = @vFentry[i]
384
- fs_tagValuesCommon(fileRow, tag)
385
- end
386
-
387
- def fs_fileTagValues(fobj, tag)
388
- fs_tagValuesCommon(fobj.fileRow, tag)
389
- end
390
-
391
- def fs_tagValuesCommon(fileRow, tag)
392
- values = []
393
- tagFound = false
394
- fs_tagsCommon(fileRow).each do |t|
395
- if t =~ /#{tag}(=(.*))*$/
396
- tagFound = true
397
- values << $2 if $2
398
- end
399
- end
400
-
401
- return [] unless tagFound
402
- values
403
- end
404
-
405
- def fs_fileObjExtend(fo)
406
- fo.extend MkFileMod
407
- end
408
-
409
- private
410
-
411
- def getFileIndex(p)
412
- @pPath.set @findRow, p
413
- (@vFentry.find(@findRow, 0))
414
- end
415
-
416
- def rmCommon(p, idx)
417
- #
418
- # If we get here, the parent hast to exist and it has to be a directory,
419
- # so if it isn't, there's a bug somewhere.
420
- #
421
- parent = File.dirname(p)
422
- raise "[BUG] #{parent}: no such directory" if (pi = getFileIndex(parent)) < 0
423
- parentRow = @vFentry[pi]
424
- raise "[BUG] #{parent}: not a directory" if @pType.get(parentRow) != TYPE_DIR
425
-
426
- #
427
- # First, remove the reference in the parent directory.
428
- #
429
- dirName = File.basename(p)
430
- dataStr = @pData.get(parentRow).contents
431
- dirEnts = dataStr.split("\0")
432
- dirEnts.delete(dirName) { raise "[BUG] Directory #{parent} does not contain entry for #{dirName}" }
433
- dataStr = dirEnts.join("\0")
434
- @pData.set(parentRow, Metakit::Bytes.new(dataStr, dataStr.length))
435
-
436
- #
437
- # Then, remove the directory's row from the database.
438
- #
439
- @vFentry.remove_at(idx)
440
-
441
- #
442
- # Apply changes to database.
443
- #
444
- @storage.commit
445
- end
446
-
447
- def create(p, type)
448
- #
449
- # Fail if the parent component of the path doesn't exist,
450
- # or if it is not a directory.
451
- #
452
- if p != "/"
453
- parent = File.dirname(p)
454
- raise "#{parent}: no such directory" if (i = getFileIndex(parent)) < 0
455
- parentRow = @vFentry[i]
456
- raise "#{parent}: not a directory" if @pType.get(parentRow) != TYPE_DIR
457
- end
458
-
459
- #
460
- # Create the new empty file or directory.
461
- #
462
- newRow = Metakit::Row.new
463
- @pPath.set newRow, p
464
- @pType.set newRow, type
465
- @pSize.set newRow, 0
466
- @pTags.set newRow, Metakit::Bytes.new("", 0)
467
- @pData.set newRow, Metakit::Bytes.new("", 0)
468
- @vFentry.add newRow
469
-
470
- if p != "/"
471
- #
472
- # Then, add an entry for the new file or directory in its parent.
473
- #
474
- dirName = File.basename(p) + "\0"
475
- dataRef = @pData.ref(parentRow)
476
- data = Metakit::Bytes.new(dirName, dirName.length)
477
- size = @pSize.get(parentRow)
478
- dataRef.modify(data, size, data.size)
479
- @pSize.set(parentRow, size + data.size)
480
- end
481
-
482
- @storage.commit
483
-
484
- fi = getFileIndex(p)
485
- raise "[BUG] can't find new file: #{p}" if fi < 0
486
-
487
- #
488
- # Must use row obtained through @vFentry.
489
- #
490
- (@vFentry[fi])
491
- end
492
-
493
- class MkFile
494
- attr_accessor :filePath, :fileRow, :filePos, :fileRead, :fileWrite
495
-
496
- def initialize(path, fileRow, fpos, fread, fwrite)
497
- @filePath = path
498
- @fileRow = fileRow
499
- @filePos = fpos
500
- @fileRead = fread
501
- @fileWrite = fwrite
502
- end
503
- end # class MkFile
504
- end # module MetakitFS
505
-
506
- module MkFileMod
507
- def addTag(tag)
508
- @fs.fs_fileTagAdd(@fobj, tag)
509
- end
510
-
511
- def deleteTag(tag)
512
- @fs.fs_fileTagDelete(@fobj, tag)
513
- end
514
-
515
- def tags
516
- @fs.fs_fileTags(@fobj)
517
- end
518
-
519
- def hasTagName?(tagName)
520
- @fs.fs_fileHasTagName?(@fobj, tagName)
521
- end
522
-
523
- def hasTag?(tag)
524
- @fs.fs_fileHasTag?(@fobj, tag)
525
- end
526
-
527
- def tagValues(tag)
528
- @fs.fs_fileTagValues(@fobj, tag)
529
- end
530
- end