facter 1.6.18 → 1.7.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of facter might be problematic. Click here for more details.
- data/Gemfile +23 -8
- data/bin/facter +4 -1
- data/ext/build_defaults.yaml +1 -1
- data/ext/debian/changelog.erb +4 -22
- data/ext/debian/control +2 -2
- data/ext/project_data.yaml +1 -1
- data/ext/redhat/facter.spec.erb +10 -9
- data/install.rb +27 -53
- data/lib/facter.rb +23 -5
- data/lib/facter/application.rb +21 -0
- data/lib/facter/blockdevices.rb +105 -0
- data/lib/facter/domain.rb +19 -7
- data/lib/facter/filesystems.rb +38 -0
- data/lib/facter/hardwaremodel.rb +3 -2
- data/lib/facter/ipaddress6.rb +1 -2
- data/lib/facter/kernelrelease.rb +10 -2
- data/lib/facter/ldom.rb +47 -0
- data/lib/facter/macaddress.rb +1 -1
- data/lib/facter/manufacturer.rb +7 -1
- data/lib/facter/memory.rb +58 -160
- data/lib/facter/operatingsystem.rb +17 -2
- data/lib/facter/operatingsystemmajrelease.rb +33 -0
- data/lib/facter/operatingsystemrelease.rb +88 -37
- data/lib/facter/osfamily.rb +6 -2
- data/lib/facter/processor.rb +2 -2
- data/lib/facter/ps.rb +5 -0
- data/lib/facter/ssh.rb +50 -12
- data/lib/facter/util/cfpropertylist.rb +6 -0
- data/lib/facter/util/cfpropertylist/LICENSE +19 -0
- data/lib/facter/util/cfpropertylist/README +44 -0
- data/lib/facter/util/cfpropertylist/Rakefile +44 -0
- data/lib/facter/util/cfpropertylist/THANKS +7 -0
- data/lib/facter/util/cfpropertylist/lib/cfpropertylist.rb +6 -0
- data/lib/facter/util/cfpropertylist/lib/rbBinaryCFPropertyList.rb +562 -0
- data/lib/facter/util/cfpropertylist/lib/rbCFPlistError.rb +26 -0
- data/lib/facter/util/cfpropertylist/lib/rbCFPropertyList.rb +402 -0
- data/lib/facter/util/cfpropertylist/lib/rbCFTypes.rb +244 -0
- data/lib/facter/util/cfpropertylist/lib/rbLibXMLParser.rb +135 -0
- data/lib/facter/util/cfpropertylist/lib/rbNokogiriParser.rb +140 -0
- data/lib/facter/util/cfpropertylist/lib/rbREXMLParser.rb +136 -0
- data/lib/facter/util/collection.rb +36 -14
- data/lib/facter/util/composite_loader.rb +12 -0
- data/lib/facter/util/config.rb +36 -0
- data/lib/facter/util/confine.rb +1 -6
- data/lib/facter/util/directory_loader.rb +83 -0
- data/lib/facter/util/fact.rb +49 -42
- data/lib/facter/util/file_read.rb +32 -0
- data/lib/facter/util/ip.rb +2 -9
- data/lib/facter/util/loader.rb +16 -2
- data/lib/facter/util/macosx.rb +15 -2
- data/lib/facter/util/memory.rb +154 -27
- data/lib/facter/util/nothing_loader.rb +15 -0
- data/lib/facter/util/parser.rb +141 -0
- data/lib/facter/util/processor.rb +27 -35
- data/lib/facter/util/resolution.rb +97 -26
- data/lib/facter/util/solaris_zones.rb +153 -0
- data/lib/facter/util/virtual.rb +32 -3
- data/lib/facter/version.rb +72 -2
- data/lib/facter/virtual.rb +56 -3
- data/lib/facter/zfs_version.rb +10 -0
- data/lib/facter/zonename.rb +6 -0
- data/lib/facter/zones.rb +17 -0
- data/lib/facter/zpool_version.rb +10 -0
- data/spec/fixtures/ifconfig/ifconfig_net_tools_1.60.txt +19 -0
- data/spec/fixtures/ifconfig/ifconfig_ubuntu_1204.txt +16 -0
- data/spec/fixtures/ldom/ldom_v1 +6 -0
- data/spec/fixtures/unit/filesystems/linux +28 -0
- data/spec/fixtures/unit/util/manufacturer/intel_linux_dmidecode +549 -0
- data/spec/fixtures/unit/virtual/sysfs_dmi_entries_raw.txt +0 -0
- data/spec/fixtures/unit/zfs_version/freebsd_8.2 +14 -0
- data/spec/fixtures/unit/zfs_version/freebsd_9.0 +13 -0
- data/spec/fixtures/unit/zfs_version/linux-fuse_0.6.9 +14 -0
- data/spec/fixtures/unit/zfs_version/solaris_10 +10 -0
- data/spec/fixtures/unit/zfs_version/solaris_11 +12 -0
- data/spec/fixtures/unit/zpool_version/freebsd_8.2 +26 -0
- data/spec/fixtures/unit/zpool_version/freebsd_9.0 +38 -0
- data/spec/fixtures/unit/zpool_version/linux-fuse_0.6.9 +35 -0
- data/spec/fixtures/unit/zpool_version/solaris_10 +31 -0
- data/spec/fixtures/unit/zpool_version/solaris_11 +43 -0
- data/spec/integration/facter_spec.rb +12 -0
- data/spec/spec_helper.rb +9 -0
- data/spec/unit/architecture_spec.rb +1 -1
- data/spec/unit/blockdevices_spec.rb +109 -0
- data/spec/unit/domain_spec.rb +189 -81
- data/spec/unit/ec2_spec.rb +15 -8
- data/spec/unit/filesystems_spec.rb +50 -0
- data/spec/unit/hardwaremodel_spec.rb +8 -1
- data/spec/unit/id_spec.rb +6 -5
- data/spec/unit/ipaddress6_spec.rb +14 -2
- data/spec/unit/ipaddress_spec.rb +1 -1
- data/spec/unit/kernel_spec.rb +24 -0
- data/spec/unit/kernelmajversion_spec.rb +17 -0
- data/spec/unit/kernelrelease_spec.rb +53 -0
- data/spec/unit/kernelversion_spec.rb +32 -0
- data/spec/unit/ldom_spec.rb +74 -0
- data/spec/unit/macaddress_spec.rb +3 -1
- data/spec/unit/manufacturer_spec.rb +115 -0
- data/spec/unit/memory_spec.rb +442 -75
- data/spec/unit/operatingsystem_spec.rb +16 -2
- data/spec/unit/operatingsystemmajrelease_spec.rb +16 -0
- data/spec/unit/operatingsystemrelease_spec.rb +110 -1
- data/spec/unit/processor_spec.rb +22 -7
- data/spec/unit/ps_spec.rb +42 -0
- data/spec/unit/ssh_spec.rb +76 -0
- data/spec/unit/util/collection_spec.rb +94 -118
- data/spec/unit/util/config_spec.rb +36 -5
- data/spec/unit/util/confine_spec.rb +31 -43
- data/spec/unit/util/directory_loader_spec.rb +87 -0
- data/spec/unit/util/fact_spec.rb +37 -25
- data/spec/unit/util/file_read_spec.rb +29 -0
- data/spec/unit/util/ip_spec.rb +4 -2
- data/spec/unit/util/loader_spec.rb +102 -45
- data/spec/unit/util/macosx_spec.rb +40 -9
- data/spec/unit/util/manufacturer_spec.rb +12 -1
- data/spec/unit/util/parser_spec.rb +135 -0
- data/spec/unit/util/resolution_spec.rb +136 -4
- data/spec/unit/util/solaris_zones_spec.rb +127 -0
- data/spec/unit/util/virtual_spec.rb +54 -0
- data/spec/unit/version_spec.rb +42 -0
- data/spec/unit/virtual_spec.rb +102 -27
- data/spec/unit/zfs_version_spec.rb +76 -0
- data/spec/unit/zonename_spec.rb +14 -0
- data/spec/unit/zones_spec.rb +55 -0
- data/spec/unit/zpool_version_spec.rb +76 -0
- metadata +113 -11
- data/lib/facter/arp.rb +0 -28
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Exceptions used:
|
4
|
+
# CFPlistError:: General base exception
|
5
|
+
# CFFormatError:: Format error
|
6
|
+
# CFTypeError:: Type error
|
7
|
+
#
|
8
|
+
# Easy and simple :-)
|
9
|
+
#
|
10
|
+
# Author:: Christian Kruse (mailto:cjk@wwwtech.de)
|
11
|
+
# Copyright:: Copyright (c) 2010
|
12
|
+
# License:: MIT License
|
13
|
+
|
14
|
+
# general plist error. All exceptions thrown are derived from this class.
|
15
|
+
class CFPlistError < Exception
|
16
|
+
end
|
17
|
+
|
18
|
+
# Exception thrown when format errors occur
|
19
|
+
class CFFormatError < CFPlistError
|
20
|
+
end
|
21
|
+
|
22
|
+
# Exception thrown when type errors occur
|
23
|
+
class CFTypeError < CFPlistError
|
24
|
+
end
|
25
|
+
|
26
|
+
# eof
|
@@ -0,0 +1,402 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'kconv'
|
4
|
+
require 'date'
|
5
|
+
require 'time'
|
6
|
+
|
7
|
+
#
|
8
|
+
# Facter::Util::CFPropertyList implementation
|
9
|
+
#
|
10
|
+
# class to read, manipulate and write both XML and binary property list
|
11
|
+
# files (plist(5)) as defined by Apple. Have a look at Facter::Util::CFPropertyList::List
|
12
|
+
# for more documentation.
|
13
|
+
#
|
14
|
+
# == Example
|
15
|
+
# require 'cfpropertylist'
|
16
|
+
#
|
17
|
+
# # create a arbitrary data structure of basic data types
|
18
|
+
# data = {
|
19
|
+
# 'name' => 'John Doe',
|
20
|
+
# 'missing' => true,
|
21
|
+
# 'last_seen' => Time.now,
|
22
|
+
# 'friends' => ['Jane Doe','Julian Doe'],
|
23
|
+
# 'likes' => {
|
24
|
+
# 'me' => false
|
25
|
+
# }
|
26
|
+
# }
|
27
|
+
#
|
28
|
+
# # create Facter::Util::CFPropertyList::List object
|
29
|
+
# plist = Facter::Util::CFPropertyList::List.new
|
30
|
+
#
|
31
|
+
# # call Facter::Util::CFPropertyList.guess() to create corresponding CFType values
|
32
|
+
# # pass in optional :convert_unknown_to_string => true to convert things like symbols into strings.
|
33
|
+
# plist.value = Facter::Util::CFPropertyList.guess(data)
|
34
|
+
#
|
35
|
+
# # write plist to file
|
36
|
+
# plist.save("example.plist", Facter::Util::CFPropertyList::List::FORMAT_BINARY)
|
37
|
+
#
|
38
|
+
# # … later, read it again
|
39
|
+
# plist = Facter::Util::CFPropertyList::List.new(:file => "example.plist")
|
40
|
+
# data = Facter::Util::CFPropertyList.native_types(plist.value)
|
41
|
+
#
|
42
|
+
# Author:: Christian Kruse (mailto:cjk@wwwtech.de)
|
43
|
+
# Copyright:: Copyright (c) 2010
|
44
|
+
# License:: MIT License
|
45
|
+
module Facter::Util::CFPropertyList
|
46
|
+
# interface class for PList parsers
|
47
|
+
class ParserInterface
|
48
|
+
# load a plist
|
49
|
+
def load(opts={})
|
50
|
+
return ""
|
51
|
+
end
|
52
|
+
|
53
|
+
# convert a plist to string
|
54
|
+
def to_str(opts={})
|
55
|
+
return true
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
class XMLParserInterface < ParserInterface
|
60
|
+
def new_node(name)
|
61
|
+
end
|
62
|
+
|
63
|
+
def new_text(val)
|
64
|
+
end
|
65
|
+
|
66
|
+
def append_node(parent, child)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
class String
|
72
|
+
unless("".respond_to?(:blob) && "".respond_to?(:blob=)) then
|
73
|
+
# The blob status of this string (to set to true if a binary string)
|
74
|
+
attr_accessor :blob
|
75
|
+
end
|
76
|
+
|
77
|
+
unless("".respond_to?(:blob?)) then
|
78
|
+
# Returns whether or not +str+ is a blob.
|
79
|
+
# @return [true,false] If true, this string contains binary data. If false, its a regular string
|
80
|
+
def blob?
|
81
|
+
blob
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
unless("".respond_to?(:bytesize)) then
|
86
|
+
def bytesize
|
87
|
+
self.length
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
dirname = File.dirname(__FILE__)
|
93
|
+
require dirname + '/rbCFPlistError.rb'
|
94
|
+
require dirname + '/rbCFTypes.rb'
|
95
|
+
require dirname + '/rbBinaryCFPropertyList.rb'
|
96
|
+
|
97
|
+
require 'iconv' unless "".respond_to?("encode")
|
98
|
+
|
99
|
+
begin
|
100
|
+
Enumerable::Enumerator.new([])
|
101
|
+
rescue NameError => e
|
102
|
+
module Enumerable
|
103
|
+
class Enumerator
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
begin
|
109
|
+
require dirname + '/rbLibXMLParser.rb'
|
110
|
+
try_nokogiri = false
|
111
|
+
rescue LoadError => e
|
112
|
+
try_nokogiri = true
|
113
|
+
end
|
114
|
+
|
115
|
+
if try_nokogiri then
|
116
|
+
begin
|
117
|
+
require dirname + '/rbNokogiriParser.rb'
|
118
|
+
rescue LoadError => e
|
119
|
+
require dirname + '/rbREXMLParser.rb'
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
|
124
|
+
module Facter::Util::CFPropertyList
|
125
|
+
# Create CFType hierarchy by guessing the correct CFType, e.g.
|
126
|
+
#
|
127
|
+
# x = {
|
128
|
+
# 'a' => ['b','c','d']
|
129
|
+
# }
|
130
|
+
# cftypes = Facter::Util::CFPropertyList.guess(x)
|
131
|
+
#
|
132
|
+
# pass optional options hash. Only possible value actually:
|
133
|
+
# +convert_unknown_to_string+:: Convert unknown objects to string calling to_str()
|
134
|
+
# +converter_method+:: Convert unknown objects to known objects calling +method_name+
|
135
|
+
#
|
136
|
+
# cftypes = Facter::Util::CFPropertyList.guess(x,:convert_unknown_to_string => true,:converter_method => :to_hash, :converter_with_opts => true)
|
137
|
+
def guess(object, options = {})
|
138
|
+
case object
|
139
|
+
when Fixnum, Integer then CFInteger.new(object)
|
140
|
+
when Float then CFReal.new(object)
|
141
|
+
when TrueClass, FalseClass then CFBoolean.new(object)
|
142
|
+
|
143
|
+
when String
|
144
|
+
object.blob? ? CFData.new(object, CFData::DATA_RAW) : CFString.new(object)
|
145
|
+
|
146
|
+
when Time, DateTime, Date then CFDate.new(object)
|
147
|
+
|
148
|
+
when Array, Enumerator, Enumerable::Enumerator
|
149
|
+
ary = Array.new
|
150
|
+
object.each do |o|
|
151
|
+
ary.push Facter::Util::CFPropertyList.guess(o, options)
|
152
|
+
end
|
153
|
+
CFArray.new(ary)
|
154
|
+
|
155
|
+
when Hash
|
156
|
+
hsh = Hash.new
|
157
|
+
object.each_pair do |k,v|
|
158
|
+
k = k.to_s if k.is_a?(Symbol)
|
159
|
+
hsh[k] = Facter::Util::CFPropertyList.guess(v, options)
|
160
|
+
end
|
161
|
+
CFDictionary.new(hsh)
|
162
|
+
else
|
163
|
+
case
|
164
|
+
when Object.const_defined?('BigDecimal') && object.is_a?(BigDecimal)
|
165
|
+
CFReal.new(object)
|
166
|
+
when object.respond_to?(:read)
|
167
|
+
CFData.new(object.read(), CFData::DATA_RAW)
|
168
|
+
when options[:converter_method] && object.respond_to?(options[:converter_method])
|
169
|
+
if options[:converter_with_opts]
|
170
|
+
Facter::Util::CFPropertyList.guess(object.send(options[:converter_method],options),options)
|
171
|
+
else
|
172
|
+
Facter::Util::CFPropertyList.guess(object.send(options[:converter_method]),options)
|
173
|
+
end
|
174
|
+
when options[:convert_unknown_to_string]
|
175
|
+
CFString.new(object.to_s)
|
176
|
+
else
|
177
|
+
raise CFTypeError.new("Unknown class #{object.class.to_s}. Try using :convert_unknown_to_string if you want to use unknown object types!")
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
# Converts a CFType hiercharchy to native Ruby types
|
183
|
+
def native_types(object,keys_as_symbols=false)
|
184
|
+
return if object.nil?
|
185
|
+
|
186
|
+
if(object.is_a?(CFDate) || object.is_a?(CFString) || object.is_a?(CFInteger) || object.is_a?(CFReal) || object.is_a?(CFBoolean)) then
|
187
|
+
return object.value
|
188
|
+
elsif(object.is_a?(CFData)) then
|
189
|
+
return object.decoded_value
|
190
|
+
elsif(object.is_a?(CFArray)) then
|
191
|
+
ary = []
|
192
|
+
object.value.each do
|
193
|
+
|v|
|
194
|
+
ary.push Facter::Util::CFPropertyList.native_types(v)
|
195
|
+
end
|
196
|
+
|
197
|
+
return ary
|
198
|
+
elsif(object.is_a?(CFDictionary)) then
|
199
|
+
hsh = {}
|
200
|
+
object.value.each_pair do
|
201
|
+
|k,v|
|
202
|
+
k = k.to_sym if keys_as_symbols
|
203
|
+
hsh[k] = Facter::Util::CFPropertyList.native_types(v)
|
204
|
+
end
|
205
|
+
|
206
|
+
return hsh
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
module_function :guess, :native_types
|
211
|
+
|
212
|
+
# Class representing a Facter::Util::CFPropertyList. Instanciate with #new
|
213
|
+
class List
|
214
|
+
# Format constant for binary format
|
215
|
+
FORMAT_BINARY = 1
|
216
|
+
|
217
|
+
# Format constant for XML format
|
218
|
+
FORMAT_XML = 2
|
219
|
+
|
220
|
+
# Format constant for automatic format recognizing
|
221
|
+
FORMAT_AUTO = 0
|
222
|
+
|
223
|
+
@@parsers = [Binary,XML]
|
224
|
+
|
225
|
+
# Path of PropertyList
|
226
|
+
attr_accessor :filename
|
227
|
+
# Path of PropertyList
|
228
|
+
attr_accessor :format
|
229
|
+
# the root value in the plist file
|
230
|
+
attr_accessor :value
|
231
|
+
|
232
|
+
# initialize a new Facter::Util::CFPropertyList, arguments are:
|
233
|
+
#
|
234
|
+
# :file:: Parse a file
|
235
|
+
# :format:: Format is one of FORMAT_BINARY or FORMAT_XML. Defaults to FORMAT_AUTO
|
236
|
+
# :data:: Parse a string
|
237
|
+
#
|
238
|
+
# All arguments are optional
|
239
|
+
def initialize(opts={})
|
240
|
+
@filename = opts[:file]
|
241
|
+
@format = opts[:format] || FORMAT_AUTO
|
242
|
+
@data = opts[:data]
|
243
|
+
|
244
|
+
load(@filename) unless @filename.nil?
|
245
|
+
load_str(@data) unless @data.nil?
|
246
|
+
end
|
247
|
+
|
248
|
+
# Load an XML PropertyList
|
249
|
+
# filename = nil:: The filename to read from; if nil, read from the file defined by instance variable +filename+
|
250
|
+
def load_xml(filename=nil)
|
251
|
+
load(filename,List::FORMAT_XML)
|
252
|
+
end
|
253
|
+
|
254
|
+
# read a binary plist file
|
255
|
+
# filename = nil:: The filename to read from; if nil, read from the file defined by instance variable +filename+
|
256
|
+
def load_binary(filename=nil)
|
257
|
+
load(filename,List::FORMAT_BINARY)
|
258
|
+
end
|
259
|
+
|
260
|
+
# load a plist from a XML string
|
261
|
+
# str:: The string containing the plist
|
262
|
+
def load_xml_str(str=nil)
|
263
|
+
load_str(str,List::FORMAT_XML)
|
264
|
+
end
|
265
|
+
|
266
|
+
# load a plist from a binary string
|
267
|
+
# str:: The string containing the plist
|
268
|
+
def load_binary_str(str=nil)
|
269
|
+
load_str(str,List::FORMAT_BINARY)
|
270
|
+
end
|
271
|
+
|
272
|
+
# load a plist from a string
|
273
|
+
# str = nil:: The string containing the plist
|
274
|
+
# format = nil:: The format of the plist
|
275
|
+
def load_str(str=nil,format=nil)
|
276
|
+
str = @data if str.nil?
|
277
|
+
format = @format if format.nil?
|
278
|
+
|
279
|
+
@value = {}
|
280
|
+
case format
|
281
|
+
when List::FORMAT_BINARY, List::FORMAT_XML then
|
282
|
+
prsr = @@parsers[format-1].new
|
283
|
+
@value = prsr.load({:data => str})
|
284
|
+
|
285
|
+
when List::FORMAT_AUTO then # what we now do is ugly, but neccessary to recognize the file format
|
286
|
+
filetype = str[0..5]
|
287
|
+
version = str[6..7]
|
288
|
+
|
289
|
+
prsr = nil
|
290
|
+
if filetype == "bplist" then
|
291
|
+
raise CFFormatError.new("Wong file version #{version}") unless version == "00"
|
292
|
+
prsr = Binary.new
|
293
|
+
else
|
294
|
+
prsr = XML.new
|
295
|
+
end
|
296
|
+
|
297
|
+
@value = prsr.load({:data => str})
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
# Read a plist file
|
302
|
+
# file = nil:: The filename of the file to read. If nil, use +filename+ instance variable
|
303
|
+
# format = nil:: The format of the plist file. Auto-detect if nil
|
304
|
+
def load(file=nil,format=nil)
|
305
|
+
file = @filename if file.nil?
|
306
|
+
format = @format if format.nil?
|
307
|
+
@value = {}
|
308
|
+
|
309
|
+
raise IOError.new("File #{file} not readable!") unless File.readable? file
|
310
|
+
|
311
|
+
case format
|
312
|
+
when List::FORMAT_BINARY, List::FORMAT_XML then
|
313
|
+
prsr = @@parsers[format-1].new
|
314
|
+
@value = prsr.load({:file => file})
|
315
|
+
|
316
|
+
when List::FORMAT_AUTO then # what we now do is ugly, but neccessary to recognize the file format
|
317
|
+
magic_number = IO.read(file,8)
|
318
|
+
filetype = magic_number[0..5]
|
319
|
+
version = magic_number[6..7]
|
320
|
+
|
321
|
+
prsr = nil
|
322
|
+
if filetype == "bplist" then
|
323
|
+
raise CFFormatError.new("Wong file version #{version}") unless version == "00"
|
324
|
+
prsr = Binary.new
|
325
|
+
else
|
326
|
+
prsr = XML.new
|
327
|
+
end
|
328
|
+
|
329
|
+
@value = prsr.load({:file => file})
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|
333
|
+
# Serialize Facter::Util::CFPropertyList object to specified format and write it to file
|
334
|
+
# file = nil:: The filename of the file to write to. Uses +filename+ instance variable if nil
|
335
|
+
# format = nil:: The format to save in. Uses +format+ instance variable if nil
|
336
|
+
def save(file=nil,format=nil,opts={})
|
337
|
+
format = @format if format.nil?
|
338
|
+
file = @filename if file.nil?
|
339
|
+
|
340
|
+
raise CFFormatError.new("Format #{format} not supported, use List::FORMAT_BINARY or List::FORMAT_XML") if format != FORMAT_BINARY && format != FORMAT_XML
|
341
|
+
|
342
|
+
if(!File.exists?(file)) then
|
343
|
+
raise IOError.new("File #{file} not writable!") unless File.writable?(File.dirname(file))
|
344
|
+
elsif(!File.writable?(file)) then
|
345
|
+
raise IOError.new("File #{file} not writable!")
|
346
|
+
end
|
347
|
+
|
348
|
+
opts[:root] = @value
|
349
|
+
prsr = @@parsers[format-1].new
|
350
|
+
content = prsr.to_str(opts)
|
351
|
+
|
352
|
+
File.open(file, 'wb') {
|
353
|
+
|fd|
|
354
|
+
fd.write content
|
355
|
+
}
|
356
|
+
end
|
357
|
+
|
358
|
+
# convert plist to string
|
359
|
+
# format = List::FORMAT_BINARY:: The format to save the plist
|
360
|
+
# opts={}:: Pass parser options
|
361
|
+
def to_str(format=List::FORMAT_BINARY,opts={})
|
362
|
+
prsr = @@parsers[format-1].new
|
363
|
+
opts[:root] = @value
|
364
|
+
return prsr.to_str(opts)
|
365
|
+
end
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
369
|
+
class Array
|
370
|
+
# convert an array to plist format
|
371
|
+
def to_plist(options={})
|
372
|
+
options[:plist_format] ||= Facter::Util::CFPropertyList::List::FORMAT_BINARY
|
373
|
+
|
374
|
+
plist = Facter::Util::CFPropertyList::List.new
|
375
|
+
plist.value = Facter::Util::CFPropertyList.guess(self, options)
|
376
|
+
plist.to_str(options[:plist_format])
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
class Enumerator
|
381
|
+
# convert an array to plist format
|
382
|
+
def to_plist(options={})
|
383
|
+
options[:plist_format] ||= Facter::Util::CFPropertyList::List::FORMAT_BINARY
|
384
|
+
|
385
|
+
plist = Facter::Util::CFPropertyList::List.new
|
386
|
+
plist.value = Facter::Util::CFPropertyList.guess(self, options)
|
387
|
+
plist.to_str(options[:plist_format])
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
391
|
+
class Hash
|
392
|
+
# convert a hash to plist format
|
393
|
+
def to_plist(options={})
|
394
|
+
options[:plist_format] ||= Facter::Util::CFPropertyList::List::FORMAT_BINARY
|
395
|
+
|
396
|
+
plist = Facter::Util::CFPropertyList::List.new
|
397
|
+
plist.value = Facter::Util::CFPropertyList.guess(self, options)
|
398
|
+
plist.to_str(options[:plist_format])
|
399
|
+
end
|
400
|
+
end
|
401
|
+
|
402
|
+
# eof
|
@@ -0,0 +1,244 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# CFTypes, e.g. CFString, CFInteger
|
4
|
+
# needed to create unambiguous plists
|
5
|
+
#
|
6
|
+
# Author:: Christian Kruse (mailto:cjk@wwwtech.de)
|
7
|
+
# Copyright:: Copyright (c) 2009
|
8
|
+
# License:: MIT License
|
9
|
+
|
10
|
+
require 'base64'
|
11
|
+
|
12
|
+
module Facter::Util::CFPropertyList
|
13
|
+
# This class defines the base class for all CFType classes
|
14
|
+
#
|
15
|
+
class CFType
|
16
|
+
# value of the type
|
17
|
+
attr_accessor :value
|
18
|
+
|
19
|
+
def initialize(value=nil)
|
20
|
+
@value = value
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_xml(parser)
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_binary(bplist) end
|
27
|
+
end
|
28
|
+
|
29
|
+
# This class holds string values, both, UTF-8 and UTF-16BE
|
30
|
+
# It will convert the value to UTF-16BE if necessary (i.e. if non-ascii char contained)
|
31
|
+
class CFString < CFType
|
32
|
+
# convert to XML
|
33
|
+
def to_xml(parser)
|
34
|
+
n = parser.new_node('string')
|
35
|
+
n = parser.append_node(n, parser.new_text(@value)) unless @value.nil?
|
36
|
+
n
|
37
|
+
end
|
38
|
+
|
39
|
+
# convert to binary
|
40
|
+
def to_binary(bplist)
|
41
|
+
bplist.string_to_binary(@value);
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# This class holds integer/fixnum values
|
46
|
+
class CFInteger < CFType
|
47
|
+
# convert to XML
|
48
|
+
def to_xml(parser)
|
49
|
+
n = parser.new_node('integer')
|
50
|
+
n = parser.append_node(n, parser.new_text(@value.to_s))
|
51
|
+
n
|
52
|
+
end
|
53
|
+
|
54
|
+
# convert to binary
|
55
|
+
def to_binary(bplist)
|
56
|
+
bplist.num_to_binary(self)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# This class holds float values
|
61
|
+
class CFReal < CFType
|
62
|
+
# convert to XML
|
63
|
+
def to_xml(parser)
|
64
|
+
n = parser.new_node('real')
|
65
|
+
n = parser.append_node(n, parser.new_text(@value.to_s))
|
66
|
+
n
|
67
|
+
end
|
68
|
+
|
69
|
+
# convert to binary
|
70
|
+
def to_binary(bplist)
|
71
|
+
bplist.num_to_binary(self)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# This class holds Time values. While Apple uses seconds since 2001,
|
76
|
+
# the rest of the world uses seconds since 1970. So if you access value
|
77
|
+
# directly, you get the Time class. If you access via get_value you either
|
78
|
+
# geht the timestamp or the Apple timestamp
|
79
|
+
class CFDate < CFType
|
80
|
+
TIMESTAMP_APPLE = 0
|
81
|
+
TIMESTAMP_UNIX = 1;
|
82
|
+
DATE_DIFF_APPLE_UNIX = 978307200
|
83
|
+
|
84
|
+
# create a XML date strimg from a time object
|
85
|
+
def CFDate.date_string(val)
|
86
|
+
# 2009-05-13T20:23:43Z
|
87
|
+
val.getutc.strftime("%Y-%m-%dT%H:%M:%SZ")
|
88
|
+
end
|
89
|
+
|
90
|
+
# parse a XML date string
|
91
|
+
def CFDate.parse_date(val)
|
92
|
+
# 2009-05-13T20:23:43Z
|
93
|
+
val =~ %r{^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})Z$}
|
94
|
+
year,month,day,hour,min,sec = $1, $2, $3, $4, $5, $6
|
95
|
+
return Time.utc(year,month,day,hour,min,sec).getlocal
|
96
|
+
end
|
97
|
+
|
98
|
+
# set value to defined state
|
99
|
+
def initialize(value = nil,format=CFDate::TIMESTAMP_UNIX)
|
100
|
+
if(value.is_a?(Time) || value.nil?) then
|
101
|
+
@value = value.nil? ? Time.now : value
|
102
|
+
elsif value.instance_of? Date
|
103
|
+
@value = Time.utc(value.year, value.month, value.day, 0, 0, 0)
|
104
|
+
elsif value.instance_of? DateTime
|
105
|
+
@value = value.to_time.utc
|
106
|
+
else
|
107
|
+
set_value(value,format)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# set value with timestamp, either Apple or UNIX
|
112
|
+
def set_value(value,format=CFDate::TIMESTAMP_UNIX)
|
113
|
+
if(format == CFDate::TIMESTAMP_UNIX) then
|
114
|
+
@value = Time.at(value)
|
115
|
+
else
|
116
|
+
@value = Time.at(value + CFDate::DATE_DIFF_APPLE_UNIX)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
# get timestamp, either UNIX or Apple timestamp
|
121
|
+
def get_value(format=CFDate::TIMESTAMP_UNIX)
|
122
|
+
if(format == CFDate::TIMESTAMP_UNIX) then
|
123
|
+
@value.to_i
|
124
|
+
else
|
125
|
+
@value.to_f - CFDate::DATE_DIFF_APPLE_UNIX
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
# convert to XML
|
130
|
+
def to_xml(parser)
|
131
|
+
n = parser.new_node('date')
|
132
|
+
n = parser.append_node(n, parser.new_text(CFDate::date_string(@value)))
|
133
|
+
n
|
134
|
+
end
|
135
|
+
|
136
|
+
# convert to binary
|
137
|
+
def to_binary(bplist)
|
138
|
+
bplist.date_to_binary(@value)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
# This class contains a boolean value
|
143
|
+
class CFBoolean < CFType
|
144
|
+
# convert to XML
|
145
|
+
def to_xml(parser)
|
146
|
+
parser.new_node(@value ? 'true' : 'false')
|
147
|
+
end
|
148
|
+
|
149
|
+
# convert to binary
|
150
|
+
def to_binary(bplist)
|
151
|
+
bplist.bool_to_binary(@value);
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
# This class contains binary data values
|
156
|
+
class CFData < CFType
|
157
|
+
# Base64 encoded data
|
158
|
+
DATA_BASE64 = 0
|
159
|
+
# Raw data
|
160
|
+
DATA_RAW = 1
|
161
|
+
|
162
|
+
# set value to defined state, either base64 encoded or raw
|
163
|
+
def initialize(value=nil,format=DATA_BASE64)
|
164
|
+
if(format == DATA_RAW)
|
165
|
+
@raw_value = value
|
166
|
+
@raw_value.blob = true
|
167
|
+
else
|
168
|
+
@value = value
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
# get base64 encoded value
|
173
|
+
def encoded_value
|
174
|
+
@value ||= "\n#{Base64.encode64(@raw_value).gsub("\n", '').scan(/.{1,76}/).join("\n")}\n"
|
175
|
+
end
|
176
|
+
|
177
|
+
# get base64 decoded value
|
178
|
+
def decoded_value
|
179
|
+
@raw_value ||= String.new(Base64.decode64(@value))
|
180
|
+
@raw_value.blob = true
|
181
|
+
@raw_value
|
182
|
+
end
|
183
|
+
|
184
|
+
# convert to XML
|
185
|
+
def to_xml(parser)
|
186
|
+
n = parser.new_node('data')
|
187
|
+
n = parser.append_node(n, parser.new_text(encoded_value()))
|
188
|
+
n
|
189
|
+
end
|
190
|
+
|
191
|
+
# convert to binary
|
192
|
+
def to_binary(bplist)
|
193
|
+
bplist.data_to_binary(decoded_value())
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
# This class contains an array of values
|
198
|
+
class CFArray < CFType
|
199
|
+
# create a new array CFType
|
200
|
+
def initialize(val=[])
|
201
|
+
@value = val
|
202
|
+
end
|
203
|
+
|
204
|
+
# convert to XML
|
205
|
+
def to_xml(parser)
|
206
|
+
n = parser.new_node('array')
|
207
|
+
@value.each do |v|
|
208
|
+
n = parser.append_node(n, v.to_xml(parser))
|
209
|
+
end
|
210
|
+
n
|
211
|
+
end
|
212
|
+
|
213
|
+
# convert to binary
|
214
|
+
def to_binary(bplist)
|
215
|
+
bplist.array_to_binary(self)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
# this class contains a hash of values
|
220
|
+
class CFDictionary < CFType
|
221
|
+
# Create new CFDictonary type.
|
222
|
+
def initialize(value={})
|
223
|
+
@value = value
|
224
|
+
end
|
225
|
+
|
226
|
+
# convert to XML
|
227
|
+
def to_xml(parser)
|
228
|
+
n = parser.new_node('dict')
|
229
|
+
@value.each_pair do |key, value|
|
230
|
+
k = parser.append_node(parser.new_node('key'), parser.new_text(key.to_s))
|
231
|
+
n = parser.append_node(n, k)
|
232
|
+
n = parser.append_node(n, value.to_xml(parser))
|
233
|
+
end
|
234
|
+
n
|
235
|
+
end
|
236
|
+
|
237
|
+
# convert to binary
|
238
|
+
def to_binary(bplist)
|
239
|
+
bplist.dict_to_binary(self)
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
# eof
|