This file is indexed.

/usr/lib/ruby/vendor_ruby/ffi/tools/struct_generator.rb is in ruby-ffi 1.9.10debian-1build2.

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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
require 'tempfile'

module FFI

  ##
  # Generates an FFI Struct layout.
  #
  # Given the @@@ portion in:
  #
  #   module Zlib::ZStream < FFI::Struct
  #     @@@
  #     name "struct z_stream_s"
  #     include "zlib.h"
  #   
  #     field :next_in,   :pointer
  #     field :avail_in,  :uint
  #     field :total_in,  :ulong
  #   
  #     # ...
  #     @@@
  #   end
  #
  # StructGenerator will create the layout:
  #
  #   layout :next_in, :pointer, 0,
  #          :avail_in, :uint, 4,
  #          :total_in, :ulong, 8,
  #          # ...
  #
  # StructGenerator does its best to pad the layout it produces to preserve
  # line numbers.  Place the struct definition as close to the top of the file
  # for best results.

  class StructGenerator
    @options = {}
    attr_accessor :size
    attr_reader   :fields

    def initialize(name, options = {})
      @name = name
      @struct_name = nil
      @includes = []
      @fields = []
      @found = false
      @size = nil

      if block_given? then
        yield self
        calculate self.class.options.merge(options)
      end
    end
    def self.options=(options)
      @options = options
    end
    def self.options
      @options
    end
    def calculate(options = {})
      binary = File.join Dir.tmpdir, "rb_struct_gen_bin_#{Process.pid}"

      raise "struct name not set" if @struct_name.nil?

      Tempfile.open("#{@name}.struct_generator") do |f|
        f.puts "#include <stdio.h>"

        @includes.each do |inc|
          f.puts "#include <#{inc}>"
        end

        f.puts "#include <stddef.h>\n\n"
        f.puts "int main(int argc, char **argv)\n{"
        f.puts "  #{@struct_name} s;"
        f.puts %[  printf("sizeof(#{@struct_name}) %u\\n", (unsigned int) sizeof(#{@struct_name}));]

        @fields.each do |field|
          f.puts <<-EOF
    printf("#{field.name} %u %u\\n", (unsigned int) offsetof(#{@struct_name}, #{field.name}),
           (unsigned int) sizeof(s.#{field.name}));
  EOF
        end

        f.puts "\n  return 0;\n}"
        f.flush

        output = `gcc #{options[:cppflags]} #{options[:cflags]} -D_DARWIN_USE_64_BIT_INODE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -x c -Wall -Werror #{f.path} -o #{binary} 2>&1`

        unless $?.success? then
          @found = false
          output = output.split("\n").map { |l| "\t#{l}" }.join "\n"
          raise "Compilation error generating struct #{@name} (#{@struct_name}):\n#{output}"
        end
      end
      
      output = `#{binary}`.split "\n"
      File.unlink(binary + (FFI::Platform.windows? ? ".exe" : ""))
      sizeof = output.shift
      unless @size
        m = /\s*sizeof\([^)]+\) (\d+)/.match sizeof
        @size = m[1]
      end

      line_no = 0
      output.each do |line|
        md = line.match(/.+ (\d+) (\d+)/)
        @fields[line_no].offset = md[1].to_i
        @fields[line_no].size   = md[2].to_i

        line_no += 1
      end

      @found = true
    end

    def field(name, type=nil)
      field = Field.new(name, type)
      @fields << field
      return field
    end

    def found?
      @found
    end

    def dump_config(io)
      io.puts "rbx.platform.#{@name}.sizeof = #{@size}"

      @fields.each { |field| io.puts field.to_config(@name) }
    end

    def generate_layout
      buf = ""

      @fields.each_with_index do |field, i|
        if buf.empty?
          buf << "layout :#{field.name}, :#{field.type}, #{field.offset}"
        else
          buf << "       :#{field.name}, :#{field.type}, #{field.offset}"
        end

        if i < @fields.length - 1
          buf << ",\n"
        end
      end

      buf
    end

    def get_field(name)
      @fields.find { |f| name == f.name }
    end

    def include(i)
      @includes << i
    end

    def name(n)
      @struct_name = n
    end

  end

  ##
  # A field in a Struct.

  class StructGenerator::Field

    attr_reader :name
    attr_reader :type
    attr_reader :offset
    attr_accessor :size

    def initialize(name, type)
      @name = name
      @type = type
      @offset = nil
      @size = nil
    end

    def offset=(o)
      @offset = o
    end

    def to_config(name)
      buf = []
      buf << "rbx.platform.#{name}.#{@name}.offset = #{@offset}"
      buf << "rbx.platform.#{name}.#{@name}.size = #{@size}"
      buf << "rbx.platform.#{name}.#{@name}.type = #{@type}" if @type
      buf
    end

  end

end