This file is indexed.

/usr/lib/ruby/vendor_ruby/net/scp/upload.rb is in ruby-net-scp 1.2.1-4.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
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