ec2_amitools 1.0.2
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.
- 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
|