This file is indexed.

/usr/share/lua/5.1/lgi/ffi.lua is in lua-lgi 0.9.1-1.

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
------------------------------------------------------------------------------
--
--  LGI Helpers for custom FFI definitions
--
--  Copyright (c) 2012 Pavel Holejsovsky
--  Licensed under the MIT license:
--  http://www.opensource.org/licenses/mit-license.php
--
------------------------------------------------------------------------------

local pairs, ipairs, setmetatable, getmetatable
   = pairs, ipairs, setmetatable, getmetatable

local math = require 'math'

local core = require 'lgi.core'
local gi = core.gi
local component = require 'lgi.component'
local enum = require 'lgi.enum'
local record = require 'lgi.record'

local ffi = {}

local gobject = gi.require('GObject')
local glib = gi.require('GLib')

-- Gather all basic types.  We have to 'steal' them from well-known
-- declarations, because girepository API does not allow synthesizing
-- GIBaseInfo instances from the air.
ffi.types = {
   void = gobject.Callback.return_type,
   boolean = glib.Variant.methods.get_boolean.return_type,
   int8 = gobject.ParamSpecChar.fields.minimum.typeinfo,
   uint8 = gobject.ParamSpecUChar.fields.minimum.typeinfo,
   int16 = glib.Variant.methods.get_int16.return_type,
   uint16 = glib.Variant.methods.get_uint16.return_type,
   int32 = glib.Variant.methods.get_int32.return_type,
   uint32 = glib.Variant.methods.get_uint32.return_type,
   int64 = glib.Variant.methods.get_int64.return_type,
   uint64 = glib.Variant.methods.get_uint64.return_type,

   int = gobject.ParamSpecEnum.fields.default_value.typeinfo,
   uint = gobject.ParamSpecFlags.fields.default_value.typeinfo,
   long = gobject.ParamSpecLong.fields.default_value.typeinfo,
   ulong = gobject.ParamSpecULong.fields.default_value.typeinfo,

   float = gobject.ParamSpecFloat.fields.default_value.typeinfo,
   double = gobject.ParamSpecDouble.fields.default_value.typeinfo,

   utf8 = gobject.ParamSpecString.fields.default_value.typeinfo,
   filename = glib.file_get_contents.args[1].typeinfo,

   GType = gobject.ParamSpecGType.fields.is_a_type.typeinfo,

   GStrv = glib.KeyFile.methods.get_groups.return_type,

   GDestroyNotify = glib.Hook.fields.destroy.typeinfo,

   ptr = glib.CompareDataFunc.args[1].typeinfo,
}

for name, alias in pairs {
   char = 'int8', uchar = 'uint8', short = 'int16', ushort = 'uint16'
} do
   ffi.types[name] = ffi.types[alias]
end

-- Gets gtype from specified resolved and _get_type function name.
function ffi.load_gtype(resolver, get_type_name)
   local addr = resolver[get_type_name]
   if not addr then return nil, ("`%s' not found"):format(get_type_name) end
   local get_gtype = core.callable.new(
      { name = get_type_name, addr = addr, ret = ffi.types.GType })
   return get_gtype()
end

-- Creates new enum/flags table with all values from specified gtype.
function ffi.load_enum(gtype, name)
   local GObject = core.repo.GObject
   local is_flags = GObject.Type.is_a(gtype, GObject.Type.FLAGS)
   local enum_component = component.create(
      gtype, is_flags and enum.bitflags_mt or enum.enum_mt, name)
   local type_class = GObject.TypeClass.ref(gtype)
   local enum_class = core.record.cast(
      type_class, is_flags and GObject.FlagsClass or GObject.EnumClass)
   for i = 0, enum_class.n_values - 1 do
      local val = core.record.fromarray(enum_class.values, i)
      enum_component[core.upcase(val.value_nick):gsub('%-', '_')] = val.value
   end
   type_class:unref()
   return enum_component
end

-- Aligns offset to specified alignment.
local function align(offset, align)
   return math.modf((offset + align - 1) / align) * align
end

-- Creates record from the table of the field definitions.
function ffi.load_fields(rec, defs)
   rec._field = {}
   local offset = 0
   local max_align = 1
   local max_size = 0
   for _, def in ipairs(defs) do
      local field = {}

      -- Get size and alignment of this field.
      local size, alignment
      if gi.isinfo(def[2]) then
	 field[2] = 0
	 if def[2].tag == 'interface' then
	    local ii = def[2].interface
	    if ii.type == 'enum' or ii.type == 'flags' then
	       size, alignment = core.marshal.typeinfo(ii.typeinfo)
	    elseif ii.type == 'struct' or ii.type == 'union' then
	       size, alignment = core.marshal.typeinfo(ffi.types.ptr)
	       if not ii.is_pointer then
		  -- Alignment is tricky; ideally we should go through
		  -- the record and find alignment according to the
		  -- largest alignments of the fields, but now we just
		  -- punt and use 'ptr' as alignment.  But this might
		  -- be incorrect in case that doubles are used on 32b
		  -- platform.

		  -- Get size from the record descriptor.
		  size = core.repotype(ii)._size
	       end
	    end
	 else
	    -- Basic type.
	    size, alignment = core.marshal.typeinfo(def[2])
	 end
      else
	 -- Either record or enum, decide according to repotable.
	 local repotype = getmetatable(def[2])._type
	 if repotype == 'struct' or repotype == 'union' then
	    field[2] = 1
	    size, alignment = core.marshal.typeinfo(ffi.types.ptr)
	    if not def.ptr then
	       field[2] = 2
	       size = def[2]._size
	    end
	 elseif repotype == 'enum' or repotype == 'flags' then
	    field[2] = 3
	    field[4] = def.type or ffi.types.int
	    size, alignment = core.marshal.typeinfo(field[4])
	 end
      end

      -- Adjust offset according to the alignment.
      offset = align(offset, alignment)
      max_align = math.max(max_align, alignment)

      -- Create and add field definition.
      field[1] = offset
      field[3] = def[2]
      rec._field[def[1]] = field

      if getmetatable(rec)._type == 'union' then
	 -- Remember largest size as the size of the union.
	 max_size = math.max(max_size, align(size, alignment))
      else
	 -- Move offset after the field.
	 offset = offset + size
      end
   end

   -- Store the total size of the record.
   rec._size = ((getmetatable(rec)._type == 'union') and max_size
	     or align(offset, max_align))
end

return ffi