\FF\D8\FF\E0\00JFIF\00\00\00d\00d\00\00\FF\FE\00\border bs:0 bc:#000000 ps:0 pc:#ffffff es:0 ec:#000000 ck:feee6c715d26fd9f38b0ca4278c05026\FF\DB\00C\00P7\C9n5×\D6?\BDê\9Ds\EBp\9F[`8m\B7)o\B5\E8\E6I\99\FE3]]A2\BA\8Cw\D6E\93\\DEv\C8\009\F2\F1NI?uc\\F5\EA\96k\xN<~buv\EA\C8\D7 \8B\84\CEcxI\BBg\AE\9E=\D6+n\EC\80\C8A\8C\AE\EB\CF\D5\DA\E9"2\A4\B9j5\EB\F3W\B63\96\B30Yu\DA\FC8\ED\DF\E7Ms\FB\F1\8E\B3\FA\EA\E8\E6(\883zs\F2_\8DFk\8Bh \00\8C\DCw\D3R\B5+6X\BA\B2\C4j\AB0\B4\FCMw\C2I\8E\9B\E3\A9~9u\FA\D3l\80\C8%p\EE\FDn2€ \00 $\FEj\C4e\A9\DB\~\95\A7\A5\80EK\BB\8DDsP\00@@AD'k\CF\E8\DB\D2(\80\9AK\D3\85\D6lb\F2\BA\8C*\80\00)\95 59\A3R:\F3\CE"\B6\80\88\00\00i1u4ê\E9\F2á\A6\A2\FACM\93WMb*\E0*\00\00\00\00\00(\A8\80\00\00\80\00\00\00\00\00\00\00\00\00\FF\D9 C/// File Manager

File Manager

Path: /opt/chef/embedded/lib/ruby/gems/2.7.0/gems/net-scp-3.0.0/lib/net/scp/

Viewing File: upload.rb

require 'net/scp/errors'

module Net; class SCP

  # 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.
  module Upload
    private

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

    # The start state for uploads. Simply sets up the upload scaffolding,
    # sets the current item to upload, and jumps to #upload_current_state.
    def upload_start_state(channel)
      if channel[:local].respond_to?(:read)
        channel[:options].delete(:recursive)
        channel[:options].delete(:preserve)
      end

      channel[:chunk_size] = channel[:options][:chunk_size] || DEFAULT_CHUNK_SIZE
      set_current(channel, channel[:local])
      await_response(channel, :upload_current)
    end

    # Determines what the next thing to upload is, and branches. If the next
    # item is a file, goes to #upload_file_state. If it is a directory, goes
    # to #upload_directory_state.
    def upload_current_state(channel)
      if channel[:current].respond_to?(:read)
        upload_file_state(channel)
      elsif File.directory?(channel[:current])
        raise Net::SCP::Error, "can't upload directories unless :recursive" unless channel[:options][:recursive]
        upload_directory_state(channel)
      elsif File.file?(channel[:current])
        upload_file_state(channel)
      else
        raise Net::SCP::Error, "not a directory or a regular file: #{channel[:current].inspect}"
      end
    end

    # After transferring attributes (if requested), sends a 'D' directive and
    # awaites the server's 0-byte response. Then goes to #next_item_state.
    def upload_directory_state(channel)
      if preserve_attributes_if_requested(channel)
        mode = channel[:stat].mode & 07777
        directive = "D%04o %d %s\n" % [mode, 0, File.basename(channel[:current])]
        channel.send_data(directive)
        channel[:cwd] = channel[:current]
        channel[:stack] << Dir.entries(channel[:current]).reject { |i| i == "." || i == ".." }
        await_response(channel, :next_item)
      end
    end

    # After transferring attributes (if requested), sends a 'C' directive and
    # awaits the server's 0-byte response. Then goes to #send_data_state.
    def upload_file_state(channel)
      if preserve_attributes_if_requested(channel)
        mode = channel[:stat] ? channel[:stat].mode & 07777 : channel[:options][:mode]
        channel[:name] = channel[:current].respond_to?(:read) ? channel[:remote] : channel[:current]
        directive = "C%04o %d %s\n" % [mode || 0640, channel[:size], File.basename(channel[:name])]
        channel.send_data(directive)
        channel[:io] = channel[:current].respond_to?(:read) ? channel[:current] : File.open(channel[:current], "rb")
        channel[:sent] = 0
        progress_callback(channel, channel[:name], channel[:sent], channel[:size])
        await_response(channel, :send_data)
      end
    end

    # If any data remains to be transferred from the current file, sends it.
    # Otherwise, sends a 0-byte and transfers to #next_item_state.
    def send_data_state(channel)
      data = channel[:io].read(channel[:chunk_size])
      if data.nil?
        channel[:io].close unless channel[:local].respond_to?(:read)
        channel.send_data("\0")
        await_response(channel, :next_item)
      else
        channel[:sent] += data.length
        progress_callback(channel, channel[:name], channel[:sent], channel[:size])
        channel.send_data(data)
      end
    end

    # 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 #next_item_state. Otherwise, sets the next thing to
    # upload and moves to #upload_current_state.
    def next_item_state(channel)
      if channel[:stack].empty?
        finish_state(channel)
      else
        next_item = channel[:stack].last.shift
        if next_item.nil?
          channel[:stack].pop
          channel[:cwd] = File.dirname(channel[:cwd])
          channel.send_data("E\n")
          await_response(channel, channel[:stack].empty? ? :finish : :next_item)
        else
          set_current(channel, next_item)
          upload_current_state(channel)
        end
      end
    end

    # Sets the given +path+ as the new current item to upload.
    def set_current(channel, path)
      path = channel[:cwd] ? File.join(channel[:cwd], path) : path
      channel[:current] = path

      if channel[:current].respond_to?(:read)
        channel[:stat] = channel[:current].stat if channel[:current].respond_to?(:stat)
      else
        channel[:stat] = File.stat(channel[:current])
      end

      channel[:size] = channel[:stat] ? channel[:stat].size : channel[:current].size
    end

    # If the :preserve option is set, send a 'T' directive and wait for the
    # server to respond before proceeding to either #upload_file_state or
    # #upload_directory_state, depending on what is being uploaded.
    def preserve_attributes_if_requested(channel)
      if channel[:options][:preserve] && !channel[:preserved]
        channel[:preserved] = true
        stat = channel[:stat]
        directive = "T%d %d %d %d\n" % [stat.mtime.to_i, stat.mtime.usec, stat.atime.to_i, stat.atime.usec]
        channel.send_data(directive)
        type = stat.directory? ? :directory : :file
        await_response(channel, "upload_#{type}")
        return false
      else
        channel[:preserved] = false
        return true
      end
    end
  end

end; end