Net::SCP::Upload

This module implements the state machine for uploading information to a remote server. It exposes no public methods. See Net::SCP#upload for a discussion of how to use Net::SCP to upload data.

Constants

DEFAULT_CHUNK_SIZE

The default read chunk size, if an explicit chunk-size is not specified by the client.

Private Instance Methods

next_item_state(channel) click to toggle source

Checks the work queue to see what needs to be done next. If there is nothing to do, calls Net::SCP#finish_state. If we’re at the end of a directory, sends an ‘E’ directive and waits for the server to respond before moving to #. Otherwise, sets the next thing to upload and moves to #.

     # File lib/net/scp/upload.rb, line 92
 92:     def next_item_state(channel)
 93:       if channel[:stack].empty?
 94:         finish_state(channel)
 95:       else
 96:         next_item = channel[:stack].last.shift
 97:         if next_item.nil?
 98:           channel[:stack].pop
 99:           channel[:cwd] = File.dirname(channel[:cwd])
100:           channel.send_data("E\n")
101:           await_response(channel, channel[:stack].empty? ? :finish : :next_item)
102:         else
103:           set_current(channel, next_item)
104:           upload_current_state(channel)
105:         end
106:       end
107:     end
preserve_attributes_if_requested(channel) click to toggle source

If the :preserve option is set, send a ‘T’ directive and wait for the server to respond before proceeding to either # or #, depending on what is being uploaded.

     # File lib/net/scp/upload.rb, line 126
126:     def preserve_attributes_if_requested(channel)
127:       if channel[:options][:preserve] && !channel[:preserved]
128:         channel[:preserved] = true
129:         stat = channel[:stat]
130:         directive = "T%d %d %d %d\n" % [stat.mtime.to_i, stat.mtime.usec, stat.atime.to_i, stat.atime.usec]
131:         channel.send_data(directive)
132:         type = stat.directory? ? :directory : :file
133:         await_response(channel, "upload_#{type}")
134:         return false
135:       else
136:         channel[:preserved] = false
137:         return true
138:       end
139:     end
send_data_state(channel) click to toggle source

If any data remains to be transferred from the current file, sends it. Otherwise, sends a 0-byte and transfers to #.

    # File lib/net/scp/upload.rb, line 74
74:     def send_data_state(channel)
75:       data = channel[:io].read(channel[:chunk_size])
76:       if data.nil?
77:         channel[:io].close unless channel[:local].respond_to?(:read)
78:         channel.send_data("\00"")
79:         await_response(channel, :next_item)
80:       else
81:         channel[:sent] += data.length
82:         progress_callback(channel, channel[:name], channel[:sent], channel[:size])
83:         channel.send_data(data)
84:       end
85:     end
set_current(channel, path) click to toggle source

Sets the given path as the new current item to upload.

     # File lib/net/scp/upload.rb, line 110
110:     def set_current(channel, path)
111:       path = channel[:cwd] ? File.join(channel[:cwd], path) : path
112:       channel[:current] = path
113: 
114:       if channel[:current].respond_to?(:read)
115:         channel[:stat] = channel[:current].stat if channel[:current].respond_to?(:stat)
116:       else
117:         channel[:stat] = File.stat(channel[:current])
118:       end
119: 
120:       channel[:size] = channel[:stat] ? channel[:stat].size : channel[:current].size
121:     end
upload_current_state(channel) click to toggle source

Determines what the next thing to upload is, and branches. If the next item is a file, goes to #. If it is a directory, goes to #.

    # File lib/net/scp/upload.rb, line 31
31:     def upload_current_state(channel)
32:       if channel[:current].respond_to?(:read)
33:         upload_file_state(channel)
34:       elsif File.directory?(channel[:current])
35:         raise Net::SCP::Error, "can't upload directories unless :recursive" unless channel[:options][:recursive]
36:         upload_directory_state(channel)
37:       elsif File.file?(channel[:current])
38:         upload_file_state(channel)
39:       else
40:         raise Net::SCP::Error, "not a directory or a regular file: #{channel[:current].inspect}"
41:       end
42:     end
upload_directory_state(channel) click to toggle source

After transferring attributes (if requested), sends a ‘D’ directive and awaites the server’s 0-byte response. Then goes to #.

    # File lib/net/scp/upload.rb, line 46
46:     def upload_directory_state(channel)
47:       if preserve_attributes_if_requested(channel)
48:         mode = channel[:stat].mode & 07777
49:         directive = "D%04o %d %s\n" % [mode, 0, File.basename(channel[:current])]
50:         channel.send_data(directive)
51:         channel[:cwd] = channel[:current]
52:         channel[:stack] << Dir.entries(channel[:current]).reject { |i| i == "." || i == ".." }
53:         await_response(channel, :next_item)
54:       end
55:     end
upload_file_state(channel) click to toggle source

After transferring attributes (if requested), sends a ‘C’ directive and awaits the server’s 0-byte response. Then goes to #.

    # File lib/net/scp/upload.rb, line 59
59:     def upload_file_state(channel)
60:       if preserve_attributes_if_requested(channel)
61:         mode = channel[:stat] ? channel[:stat].mode & 07777 : channel[:options][:mode]
62:         channel[:name] = channel[:current].respond_to?(:read) ? channel[:remote] : channel[:current]
63:         directive = "C%04o %d %s\n" % [mode || 0640, channel[:size], File.basename(channel[:name])]
64:         channel.send_data(directive)
65:         channel[:io] = channel[:current].respond_to?(:read) ? channel[:current] : File.open(channel[:current], "rb")
66:         channel[:sent] = 0
67:         progress_callback(channel, channel[:name], channel[:sent], channel[:size])
68:         await_response(channel, :send_data)
69:       end
70:     end
upload_start_state(channel) click to toggle source

The start state for uploads. Simply sets up the upload scaffolding, sets the current item to upload, and jumps to #.

    # File lib/net/scp/upload.rb, line 17
17:     def upload_start_state(channel)
18:       if channel[:local].respond_to?(:read)
19:         channel[:options].delete(:recursive)
20:         channel[:options].delete(:preserve)
21:       end
22: 
23:       channel[:chunk_size] = channel[:options][:chunk_size] || DEFAULT_CHUNK_SIZE
24:       set_current(channel, channel[:local])
25:       await_response(channel, :upload_current)
26:     end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.