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.
The default read chunk size, if an explicit chunk-size is not specified by the client.
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
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
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
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
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
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
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
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.
Generated with the Darkfish Rdoc Generator 1.1.6.