ec2_amitools 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +54 -0
- data/bin/console +14 -0
- data/bin/ec2-ami-tools-version +6 -0
- data/bin/ec2-bundle-image +6 -0
- data/bin/ec2-bundle-vol +6 -0
- data/bin/ec2-delete-bundle +6 -0
- data/bin/ec2-download-bundle +6 -0
- data/bin/ec2-migrate-bundle +6 -0
- data/bin/ec2-migrate-manifest +6 -0
- data/bin/ec2-unbundle +6 -0
- data/bin/ec2-upload-bundle +6 -0
- data/bin/setup +8 -0
- data/etc/ec2/amitools/cert-ec2-cn-north-1.pem +28 -0
- data/etc/ec2/amitools/cert-ec2-gov.pem +17 -0
- data/etc/ec2/amitools/cert-ec2.pem +23 -0
- data/etc/ec2/amitools/mappings.csv +9 -0
- data/lib/ec2/amitools/bundle.rb +251 -0
- data/lib/ec2/amitools/bundle_base.rb +58 -0
- data/lib/ec2/amitools/bundleimage.rb +94 -0
- data/lib/ec2/amitools/bundleimageparameters.rb +42 -0
- data/lib/ec2/amitools/bundlemachineparameters.rb +60 -0
- data/lib/ec2/amitools/bundleparameters.rb +120 -0
- data/lib/ec2/amitools/bundlevol.rb +240 -0
- data/lib/ec2/amitools/bundlevolparameters.rb +164 -0
- data/lib/ec2/amitools/crypto.rb +379 -0
- data/lib/ec2/amitools/decryptmanifest.rb +20 -0
- data/lib/ec2/amitools/defaults.rb +12 -0
- data/lib/ec2/amitools/deletebundle.rb +212 -0
- data/lib/ec2/amitools/deletebundleparameters.rb +78 -0
- data/lib/ec2/amitools/downloadbundle.rb +161 -0
- data/lib/ec2/amitools/downloadbundleparameters.rb +84 -0
- data/lib/ec2/amitools/exception.rb +86 -0
- data/lib/ec2/amitools/fileutil.rb +219 -0
- data/lib/ec2/amitools/format.rb +127 -0
- data/lib/ec2/amitools/instance-data.rb +97 -0
- data/lib/ec2/amitools/manifest_wrapper.rb +132 -0
- data/lib/ec2/amitools/manifestv20070829.rb +361 -0
- data/lib/ec2/amitools/manifestv20071010.rb +403 -0
- data/lib/ec2/amitools/manifestv3.rb +331 -0
- data/lib/ec2/amitools/mapids.rb +148 -0
- data/lib/ec2/amitools/migratebundle.rb +222 -0
- data/lib/ec2/amitools/migratebundleparameters.rb +173 -0
- data/lib/ec2/amitools/migratemanifest.rb +225 -0
- data/lib/ec2/amitools/migratemanifestparameters.rb +118 -0
- data/lib/ec2/amitools/minimalec2.rb +116 -0
- data/lib/ec2/amitools/parameter_exceptions.rb +34 -0
- data/lib/ec2/amitools/parameters_base.rb +168 -0
- data/lib/ec2/amitools/region.rb +93 -0
- data/lib/ec2/amitools/s3toolparameters.rb +183 -0
- data/lib/ec2/amitools/showversion.rb +12 -0
- data/lib/ec2/amitools/syschecks.rb +27 -0
- data/lib/ec2/amitools/tool_base.rb +224 -0
- data/lib/ec2/amitools/unbundle.rb +107 -0
- data/lib/ec2/amitools/unbundleparameters.rb +65 -0
- data/lib/ec2/amitools/uploadbundle.rb +361 -0
- data/lib/ec2/amitools/uploadbundleparameters.rb +108 -0
- data/lib/ec2/amitools/util.rb +532 -0
- data/lib/ec2/amitools/version.rb +33 -0
- data/lib/ec2/amitools/xmlbuilder.rb +237 -0
- data/lib/ec2/amitools/xmlutil.rb +55 -0
- data/lib/ec2/common/constants.rb +16 -0
- data/lib/ec2/common/curl.rb +110 -0
- data/lib/ec2/common/headers.rb +95 -0
- data/lib/ec2/common/headersv4.rb +173 -0
- data/lib/ec2/common/http.rb +333 -0
- data/lib/ec2/common/s3support.rb +231 -0
- data/lib/ec2/common/signature.rb +68 -0
- data/lib/ec2/oem/LICENSE.txt +58 -0
- data/lib/ec2/oem/open4.rb +399 -0
- data/lib/ec2/platform/base/architecture.rb +26 -0
- data/lib/ec2/platform/base/constants.rb +54 -0
- data/lib/ec2/platform/base/pipeline.rb +181 -0
- data/lib/ec2/platform/base.rb +57 -0
- data/lib/ec2/platform/current.rb +55 -0
- data/lib/ec2/platform/linux/architecture.rb +35 -0
- data/lib/ec2/platform/linux/constants.rb +23 -0
- data/lib/ec2/platform/linux/fstab.rb +99 -0
- data/lib/ec2/platform/linux/identity.rb +16 -0
- data/lib/ec2/platform/linux/image.rb +811 -0
- data/lib/ec2/platform/linux/mtab.rb +74 -0
- data/lib/ec2/platform/linux/pipeline.rb +40 -0
- data/lib/ec2/platform/linux/rsync.rb +114 -0
- data/lib/ec2/platform/linux/tar.rb +124 -0
- data/lib/ec2/platform/linux/uname.rb +50 -0
- data/lib/ec2/platform/linux.rb +83 -0
- data/lib/ec2/platform/solaris/architecture.rb +28 -0
- data/lib/ec2/platform/solaris/constants.rb +30 -0
- data/lib/ec2/platform/solaris/fstab.rb +43 -0
- data/lib/ec2/platform/solaris/identity.rb +16 -0
- data/lib/ec2/platform/solaris/image.rb +327 -0
- data/lib/ec2/platform/solaris/mtab.rb +29 -0
- data/lib/ec2/platform/solaris/pipeline.rb +40 -0
- data/lib/ec2/platform/solaris/rsync.rb +24 -0
- data/lib/ec2/platform/solaris/tar.rb +36 -0
- data/lib/ec2/platform/solaris/uname.rb +21 -0
- data/lib/ec2/platform/solaris.rb +38 -0
- data/lib/ec2/platform.rb +69 -0
- data/lib/ec2/version.rb +8 -0
- data/lib/ec2_amitools +1 -0
- data/lib/ec2_amitools.rb +7 -0
- metadata +184 -0
@@ -0,0 +1,84 @@
|
|
1
|
+
# Copyright 2008-2014 Amazon.com, Inc. or its affiliates. All Rights
|
2
|
+
# Reserved. Licensed under the Amazon Software License (the
|
3
|
+
# "License"). You may not use this file except in compliance with the
|
4
|
+
# License. A copy of the License is located at
|
5
|
+
# http://aws.amazon.com/asl or in the "license" file accompanying this
|
6
|
+
# file. This file is distributed on an "AS IS" BASIS, WITHOUT
|
7
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
|
8
|
+
# the License for the specific language governing permissions and
|
9
|
+
# limitations under the License.
|
10
|
+
|
11
|
+
require 'ec2/amitools/s3toolparameters'
|
12
|
+
|
13
|
+
#------------------------------------------------------------------------------#
|
14
|
+
|
15
|
+
class DownloadBundleParameters < S3ToolParameters
|
16
|
+
|
17
|
+
PREFIX_DESCRIPTION = "The filename prefix for bundled AMI files. Defaults to 'image'."
|
18
|
+
DIRECTORY_DESCRIPTION = ['The directory into which to download the bundled AMI parts.',
|
19
|
+
"Defaults to the current working directory."]
|
20
|
+
MANIFEST_DESCRIPTION = ["The local manifest filename. Required only for manifests that",
|
21
|
+
"pre-date the version 3 manifest file format."]
|
22
|
+
RETRY_DESCRIPTION = "Automatically retry failed downloads."
|
23
|
+
|
24
|
+
attr_accessor :manifest,
|
25
|
+
:prefix,
|
26
|
+
:privatekey,
|
27
|
+
:directory,
|
28
|
+
:retry
|
29
|
+
|
30
|
+
#----------------------------------------------------------------------------#
|
31
|
+
|
32
|
+
def mandatory_params()
|
33
|
+
super()
|
34
|
+
|
35
|
+
on('-k', '--privatekey KEY', String, USER_PK_PATH_DESCRIPTION) do |privatekey|
|
36
|
+
assert_file_exists(privatekey, '--privatekey')
|
37
|
+
@privatekey = privatekey
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
#----------------------------------------------------------------------------#
|
42
|
+
|
43
|
+
def optional_params()
|
44
|
+
super()
|
45
|
+
|
46
|
+
on('-m', '--manifest FILE', String, *MANIFEST_DESCRIPTION) do |manifest|
|
47
|
+
assert_good_key(manifest, '--manifest')
|
48
|
+
@manifest = manifest
|
49
|
+
end
|
50
|
+
|
51
|
+
on('-p', '--prefix PREFIX', String, PREFIX_DESCRIPTION) do |prefix|
|
52
|
+
assert_good_key(prefix, '--prefix')
|
53
|
+
@prefix = prefix
|
54
|
+
end
|
55
|
+
|
56
|
+
on('-d', '--directory DIRECTORY', String, *DIRECTORY_DESCRIPTION) do |directory|
|
57
|
+
assert_directory_exists(directory, '--directory')
|
58
|
+
@directory = directory
|
59
|
+
end
|
60
|
+
|
61
|
+
on('--retry', RETRY_DESCRIPTION) do
|
62
|
+
@retry = true
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
#----------------------------------------------------------------------------#
|
67
|
+
|
68
|
+
def validate_params()
|
69
|
+
super()
|
70
|
+
raise MissingMandatory.new('--privatekey') unless @privatekey
|
71
|
+
raise InvalidCombination.new('--prefix', '--manifest') if (@prefix and @manifest)
|
72
|
+
end
|
73
|
+
|
74
|
+
#----------------------------------------------------------------------------#
|
75
|
+
|
76
|
+
def set_defaults()
|
77
|
+
super()
|
78
|
+
@directory = Dir::pwd() unless @directory
|
79
|
+
@prefix = @manifest.split('.')[0..-2].join('.') if (@manifest)
|
80
|
+
@prefix = 'image' unless @prefix
|
81
|
+
@manifest = "#{@prefix}.manifest.xml" unless @manifest
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# Copyright 2008-2014 Amazon.com, Inc. or its affiliates. All Rights
|
2
|
+
# Reserved. Licensed under the Amazon Software License (the
|
3
|
+
# "License"). You may not use this file except in compliance with the
|
4
|
+
# License. A copy of the License is located at
|
5
|
+
# http://aws.amazon.com/asl or in the "license" file accompanying this
|
6
|
+
# file. This file is distributed on an "AS IS" BASIS, WITHOUT
|
7
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
|
8
|
+
# the License for the specific language governing permissions and
|
9
|
+
# limitations under the License.
|
10
|
+
|
11
|
+
##
|
12
|
+
# An exception thrown to indicate an unrecoverable error has been encountered.
|
13
|
+
# The process should be terminated and the exception's message should be
|
14
|
+
# displayed to the user.
|
15
|
+
#
|
16
|
+
class FatalError < Exception
|
17
|
+
##
|
18
|
+
# ((|message|)) The message that should be displayed to the user.
|
19
|
+
# ((|cause|)) The exception that caused the fatal error.
|
20
|
+
#
|
21
|
+
def initialize(message, cause = nil)
|
22
|
+
super(message)
|
23
|
+
@cause = cause
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
#------------------------------------------------------------------------------#
|
28
|
+
|
29
|
+
##
|
30
|
+
# File access error.
|
31
|
+
#
|
32
|
+
class FileError < FatalError
|
33
|
+
def initialize(filename, error_description, sys_call_err = nil)
|
34
|
+
message = "File Error: #{error_description} \n" +
|
35
|
+
"File name: #{filename}\n"
|
36
|
+
super(message, sys_call_err)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
#------------------------------------------------------------------------------#
|
41
|
+
|
42
|
+
##
|
43
|
+
# Directory access exception.
|
44
|
+
#
|
45
|
+
class DirectoryError < FatalError
|
46
|
+
def initialize(dirname, error_description, sys_call_err = nil)
|
47
|
+
message = "Directory Error: #{error_description} \n" +
|
48
|
+
"Directory name: #{dirname} \n"
|
49
|
+
super(message, sys_call_error)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
#----------------------------------------------------------------------------#
|
54
|
+
|
55
|
+
class DownloadError < FatalError
|
56
|
+
def initialize(resource, addr, port, path, error=nil)
|
57
|
+
super("could not download #{resource} from #{addr}/#{path} on #{port}", error)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
#----------------------------------------------------------------------------#
|
62
|
+
|
63
|
+
class UploadError < FatalError
|
64
|
+
def initialize(resource, addr, port, path, error=nil)
|
65
|
+
super("could not upload #{resource} to #{addr}/#{path} on #{port}", error)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
#------------------------------------------------------------------------------#
|
70
|
+
|
71
|
+
##
|
72
|
+
# Parameter error.
|
73
|
+
#
|
74
|
+
class ParameterError < FatalError
|
75
|
+
def initialize(message)
|
76
|
+
super(message)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
#------------------------------------------------------------------------------#
|
81
|
+
|
82
|
+
class AMIInvalid < FatalError
|
83
|
+
def initialize(message)
|
84
|
+
super(message)
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,219 @@
|
|
1
|
+
# Copyright 2008-2014 Amazon.com, Inc. or its affiliates. All Rights
|
2
|
+
# Reserved. Licensed under the Amazon Software License (the
|
3
|
+
# "License"). You may not use this file except in compliance with the
|
4
|
+
# License. A copy of the License is located at
|
5
|
+
# http://aws.amazon.com/asl or in the "license" file accompanying this
|
6
|
+
# file. This file is distributed on an "AS IS" BASIS, WITHOUT
|
7
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
|
8
|
+
# the License for the specific language governing permissions and
|
9
|
+
# limitations under the License.
|
10
|
+
|
11
|
+
# Utility class and methods.
|
12
|
+
|
13
|
+
require 'ec2/amitools/exception'
|
14
|
+
require 'tmpdir'
|
15
|
+
require 'fileutils'
|
16
|
+
require 'pathname'
|
17
|
+
require 'tempfile'
|
18
|
+
require 'zlib'
|
19
|
+
|
20
|
+
##
|
21
|
+
# Module containing file utility methods.
|
22
|
+
#
|
23
|
+
module FileUtil
|
24
|
+
include Zlib
|
25
|
+
BUFFER_SIZE = 1024 * 1024 # Buffer size in bytes.
|
26
|
+
PART_SUFFIX = '.part.'
|
27
|
+
|
28
|
+
#----------------------------------------------------------------------------#
|
29
|
+
|
30
|
+
##
|
31
|
+
# Assert the specified file exists.
|
32
|
+
# An exception is raised if it does not.
|
33
|
+
#
|
34
|
+
def FileUtil.assert_exists(filename)
|
35
|
+
raise FileError(filename, 'a required file could not be found') unless exists?(filename)
|
36
|
+
end
|
37
|
+
|
38
|
+
#----------------------------------------------------------------------------#
|
39
|
+
|
40
|
+
##
|
41
|
+
# Compress the specified file and return the path to the temporary compressed
|
42
|
+
# file that will be deleted upon termination of the process.
|
43
|
+
#
|
44
|
+
def FileUtil.compress(filename)
|
45
|
+
outfilename = filename+'.gz'
|
46
|
+
GzipWriter.open(outfilename) do |outfile|
|
47
|
+
begin
|
48
|
+
File.open(filename, 'r') do |infile|
|
49
|
+
while not (infile.eof)
|
50
|
+
outfile.write(infile.read(BUFFER_SIZE))
|
51
|
+
end
|
52
|
+
end
|
53
|
+
ensure
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
57
|
+
outfilename
|
58
|
+
end
|
59
|
+
|
60
|
+
#----------------------------------------------------------------------------#
|
61
|
+
|
62
|
+
##
|
63
|
+
# Expand ((|src_filename|)) to ((|dst_filename|)).
|
64
|
+
#
|
65
|
+
def FileUtil.expand(src_filename, dst_filename)
|
66
|
+
GzipReader.open(src_filename) do |gzfile|
|
67
|
+
File.open(dst_filename, 'w') do |file|
|
68
|
+
while not (gzfile.eof?)
|
69
|
+
file.write(gzfile.read(BUFFER_SIZE))
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
#----------------------------------------------------------------------------#
|
76
|
+
|
77
|
+
##
|
78
|
+
# Split the specified file into chunks of the specified size.
|
79
|
+
# yields the <file,chunk,chunk size> to a block which writes the actual chunks
|
80
|
+
# The chunks are output to the local directory.
|
81
|
+
# Typical invocation looks like:
|
82
|
+
# FileUtil.split('file',5){|sf,cf,cs| ChunkWriter.write_chunk(sf,cf,cs)}
|
83
|
+
#
|
84
|
+
# ((|filename|)) The file to split.
|
85
|
+
# ((|part_name_prefix|)) The prefix for the parts filenames.
|
86
|
+
# ((|cb_size|)) The chunk size in bytes.
|
87
|
+
# ((|dst_dir|)) The destination to create the file parts in.
|
88
|
+
#
|
89
|
+
# Returns a list of the created filenames.
|
90
|
+
#
|
91
|
+
def FileUtil.split(filename, part_name_prefix, cb_size, dst_dir)
|
92
|
+
begin
|
93
|
+
# Check file exists and is accessible.
|
94
|
+
begin
|
95
|
+
file = File.new(filename, File::RDONLY)
|
96
|
+
rescue SystemCallError => e
|
97
|
+
raise FileError.new(filename, "could not open file to split", e)
|
98
|
+
end
|
99
|
+
|
100
|
+
# Create the part file upfront to catch any creation/access errors
|
101
|
+
# before writing out data.
|
102
|
+
nr_parts = (Float(File.size(filename)) / Float(cb_size)).ceil
|
103
|
+
part_names = []
|
104
|
+
nr_parts.times do |i|
|
105
|
+
begin
|
106
|
+
nr_parts_digits = nr_parts.to_s.length
|
107
|
+
part_name_suffix = PART_SUFFIX + i.to_s.rjust(nr_parts_digits).gsub(' ', '0')
|
108
|
+
part_names[i] = part_name = part_name_prefix + part_name_suffix
|
109
|
+
FileUtils.touch File.join(dst_dir, part_name)
|
110
|
+
rescue SystemCallError => e
|
111
|
+
raise FileError.new(filename, "could not create part file", e)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# Write parts to files.
|
116
|
+
part_names.each do |part_file_name|
|
117
|
+
File.open(File.join(dst_dir, part_file_name), 'w+') do |pf|
|
118
|
+
write_chunk(file, pf, cb_size)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
part_names
|
123
|
+
ensure
|
124
|
+
file.close if not file.nil?
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
#----------------------------------------------------------------------------#
|
129
|
+
|
130
|
+
##
|
131
|
+
# Concatenate the specified files into a single file.
|
132
|
+
# If the specified output file already exists it will be overwritten.
|
133
|
+
# ((|filenames|)) An ordered collection of the names of split files.
|
134
|
+
# ((|out_filename|)) The output filename.
|
135
|
+
#
|
136
|
+
def FileUtil.cat(filenames, out_filename)
|
137
|
+
File.open(out_filename, 'w') do |of|
|
138
|
+
filenames.each do |filename|
|
139
|
+
File.open(filename) do |file|
|
140
|
+
while not (file.eof?)
|
141
|
+
of.write(file.read(BUFFER_SIZE))
|
142
|
+
of.flush
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
#----------------------------------------------------------------------------#
|
150
|
+
|
151
|
+
def FileUtil.exists?(fullname)
|
152
|
+
FileTest.exists?(fullname)
|
153
|
+
end
|
154
|
+
|
155
|
+
#----------------------------------------------------------------------------#
|
156
|
+
|
157
|
+
def FileUtil.directory?(fullname)
|
158
|
+
File::Stat.new(fullname).directory?
|
159
|
+
end
|
160
|
+
|
161
|
+
#----------------------------------------------------------------------------#
|
162
|
+
|
163
|
+
def FileUtil.symlink?(fullname)
|
164
|
+
File::Stat.new(fullname).symlink?
|
165
|
+
end
|
166
|
+
|
167
|
+
#----------------------------------------------------------------------------#
|
168
|
+
|
169
|
+
def FileUtil.tempdir(basename, tmpdir=Dir::tmpdir, tries=10)
|
170
|
+
tmpdir = '/tmp' if $SAFE > 0 and tmpdir.tainted?
|
171
|
+
fail = 0
|
172
|
+
tmpname = nil
|
173
|
+
begin
|
174
|
+
begin
|
175
|
+
tmpname = File.join(tmpdir, sprintf('%s%d.%s', basename, $$, Time.now.to_f.to_s))
|
176
|
+
end until !File.exist? tmpname
|
177
|
+
rescue
|
178
|
+
fail += 1
|
179
|
+
retry if fail < tries
|
180
|
+
raise "failed to generate a temporary directory name '%s'" % tmpname
|
181
|
+
end
|
182
|
+
tmpname
|
183
|
+
end
|
184
|
+
|
185
|
+
|
186
|
+
#----------------------------------------------------------------------------#
|
187
|
+
|
188
|
+
def FileUtil.size(f)
|
189
|
+
total = `du -s #{f}`.split[0].to_i rescue nil
|
190
|
+
if total.nil? or $?.exitstatus != 0
|
191
|
+
total = 0
|
192
|
+
Find.find(f) do |s|
|
193
|
+
total += File.directory?(s) ? 0 : File.size(s)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
total
|
197
|
+
end
|
198
|
+
|
199
|
+
#----------------------------------------------------------------------------#
|
200
|
+
|
201
|
+
##
|
202
|
+
# Write chunk to file.
|
203
|
+
# ((|sf|)) Source file.
|
204
|
+
# ((|cf|)) Chunk file.
|
205
|
+
# ((|cs|)) Chunk size in bytes.
|
206
|
+
# Returns true if eof was encountered.
|
207
|
+
#
|
208
|
+
def FileUtil.write_chunk(sf, cf, cs)
|
209
|
+
cb_written = 0 # Bytes written.
|
210
|
+
cb_left = cs # Bytes left to write in this chunk.
|
211
|
+
while (!sf.eof? && cb_left > 0) do
|
212
|
+
buf = sf.read(BUFFER_SIZE < cb_left ? BUFFER_SIZE : cb_left)
|
213
|
+
cf.write(buf)
|
214
|
+
cb_written += buf.length
|
215
|
+
cb_left = cs - cb_written
|
216
|
+
end
|
217
|
+
sf.eof
|
218
|
+
end
|
219
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
# Copyright 2008-2014 Amazon.com, Inc. or its affiliates. All Rights
|
2
|
+
# Reserved. Licensed under the Amazon Software License (the
|
3
|
+
# "License"). You may not use this file except in compliance with the
|
4
|
+
# License. A copy of the License is located at
|
5
|
+
# http://aws.amazon.com/asl or in the "license" file accompanying this
|
6
|
+
# file. This file is distributed on an "AS IS" BASIS, WITHOUT
|
7
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
|
8
|
+
# the License for the specific language governing permissions and
|
9
|
+
# limitations under the License.
|
10
|
+
|
11
|
+
require 'stringio'
|
12
|
+
|
13
|
+
module Format
|
14
|
+
|
15
|
+
#----------------------------------------------------------------------------#
|
16
|
+
|
17
|
+
##
|
18
|
+
# Convert the binary data ((|data|)) to an ASCII string of hexadecimal digits
|
19
|
+
# that represents it.
|
20
|
+
#
|
21
|
+
# E.g. if ((|data|)) is the string of bytes 0x1, 0x1A, 0xFF, it is converted
|
22
|
+
# to the string "011AFF".
|
23
|
+
#
|
24
|
+
def Format.bin2hex(data)
|
25
|
+
hex = StringIO.new
|
26
|
+
data.unpack('H*').each {|digit| hex.write(digit)}
|
27
|
+
hex.string
|
28
|
+
end
|
29
|
+
|
30
|
+
#----------------------------------------------------------------------------#
|
31
|
+
|
32
|
+
##
|
33
|
+
# Breaks ((|data|)) into blocks of size ((|blocksize|)). The last block maybe
|
34
|
+
# less than ((|blocksize||).
|
35
|
+
#
|
36
|
+
def Format.block(data, blocksize)
|
37
|
+
blocks = Array.new
|
38
|
+
read = 0
|
39
|
+
while read < data.size
|
40
|
+
left = data.size - read
|
41
|
+
blocks << data[read, (left < blocksize) ? left : blocksize]
|
42
|
+
read += (left < blocksize ? left : blocksize)
|
43
|
+
end
|
44
|
+
|
45
|
+
blocks
|
46
|
+
end
|
47
|
+
|
48
|
+
#----------------------------------------------------------------------------#
|
49
|
+
|
50
|
+
##
|
51
|
+
# Convert ASCII string of hexadecimal digits ((|hex|)) into the binary data it
|
52
|
+
# represents. If there are an odd number of hexedecimal digits in ((|hex|)) it
|
53
|
+
# is left padded with a leading '0' character.
|
54
|
+
#
|
55
|
+
# E.g. if ((|hex|)) is "11AFF", it is converted to the string of bytes 0x1,
|
56
|
+
# 0x1A, 0xFF.
|
57
|
+
#
|
58
|
+
def Format.hex2bin(hex)
|
59
|
+
hex = '0' + hex unless (hex.size % 2) == 0
|
60
|
+
data = StringIO.new
|
61
|
+
[[hex].pack('H*')].each {|digit| data.write(digit)}
|
62
|
+
data.string
|
63
|
+
end
|
64
|
+
|
65
|
+
#----------------------------------------------------------------------------#
|
66
|
+
|
67
|
+
##
|
68
|
+
# Return a single character string containing ((|int|)) converted to a single
|
69
|
+
# byte unsigned integer. The operand must be less than 256.
|
70
|
+
#
|
71
|
+
def Format.int2byte int
|
72
|
+
raise ArgumentError.new('argument greater than 255') unless int < 256
|
73
|
+
int.chr
|
74
|
+
end
|
75
|
+
|
76
|
+
#----------------------------------------------------------------------------#
|
77
|
+
|
78
|
+
# Convert integer _i_ to an unsigned 16 bit int packed into two bytes in big
|
79
|
+
# endian order.
|
80
|
+
def Format::int2int16( i )
|
81
|
+
raise ArgumentError.new( 'argument greater than 65535' ) unless i < 65536
|
82
|
+
hi_byte = ( i >> 8 ).chr
|
83
|
+
lo_byte = ( i & 0xFF).chr
|
84
|
+
return [ hi_byte, lo_byte ]
|
85
|
+
end
|
86
|
+
|
87
|
+
#----------------------------------------------------------------------------#
|
88
|
+
|
89
|
+
##
|
90
|
+
# Pad data string ((|data|)) according to the PKCS #7 padding scheme.
|
91
|
+
#
|
92
|
+
def Format.pad_pkcs7(data, blocksize)
|
93
|
+
raise ArgumentError.new("invalid data: #{data.to_s}") unless data and data.kind_of? String
|
94
|
+
raise ArgumentError.new("illegal blocksize: #{blocksize}") unless blocksize > 0x0 and blocksize < 0xFF
|
95
|
+
|
96
|
+
# Determine the number of padding characters required. If the data size is
|
97
|
+
# divisible by the blocksize, a block of padding is required.
|
98
|
+
nr_padchars = blocksize - (data.size % blocksize)
|
99
|
+
nr_padchars = blocksize unless nr_padchars != 0
|
100
|
+
|
101
|
+
# Create padding, where the padding byte is the number of padding bytes.
|
102
|
+
padchar = nr_padchars.chr
|
103
|
+
padding = padchar * nr_padchars
|
104
|
+
|
105
|
+
data + padding
|
106
|
+
end
|
107
|
+
|
108
|
+
#----------------------------------------------------------------------------#
|
109
|
+
|
110
|
+
##
|
111
|
+
# Pad ((|data|)) according to the PKCS #7 padding scheme.
|
112
|
+
#
|
113
|
+
def Format.unpad_pkcs7(data, blocksize)
|
114
|
+
raise ArgumentError.new("illegal blocksize: #{blocksize}") unless blocksize > 0x0 and blocksize < 0xFF
|
115
|
+
raise ArgumentError.new("invalid data: #{data.to_s}") unless data and data.kind_of? String
|
116
|
+
raise ArgumentError.new("invalid data size: #{data.size}") unless data.size > 0 and (data.size % blocksize) == 0
|
117
|
+
|
118
|
+
nr_padchars = data[data.size - 1]
|
119
|
+
raise ArgumentError.new("data padding character invalid: #{nr_padchars}") unless (nr_padchars > 0 and nr_padchars <= blocksize)
|
120
|
+
|
121
|
+
data[0, data.size - nr_padchars]
|
122
|
+
end
|
123
|
+
|
124
|
+
|
125
|
+
|
126
|
+
|
127
|
+
end
|