Class: XFS::Inode

Inherits:
Object
  • Object
show all
Defined in:
lib/fs/xfs/inode.rb

Overview

//////////////////////////////////////////////////////////////////////////// // Class.

Constant Summary collapse

MAX_READ =
4_294_967_296
XFS_DINODE_MAGIC =
0x494e
PF_O_EXECUTE =

Bits 0 to 8 of file mode.

0x0001
PF_O_WRITE =

owner execute

0x0002
PF_O_READ =

owner write

0x0004
PF_G_EXECUTE =

owner read

0x0008
PF_G_WRITE =

group execute

0x0010
PF_G_READ =

group write

0x0020
PF_U_EXECUTE =

group read

0x0040
PF_U_WRITE =

user execute

0x0080
PF_U_READ =

user write

0x0100
MSK_PERM_OWNER =

For accessor convenience.

(PF_O_EXECUTE | PF_O_WRITE | PF_O_READ)
MSK_PERM_GROUP =
(PF_G_EXECUTE | PF_G_WRITE | PF_G_READ)
MSK_PERM_USER =
(PF_U_EXECUTE | PF_U_WRITE | PF_U_READ)
FM_FIFO =

Bits 12 to 15 of file mode.

0x1000
FM_CHAR =

fifo device (pipe)

0x2000
FM_DIRECTORY =

char device

0x4000
FM_BLOCK_DEV =

directory

0x6000
FM_FILE =

block device

0x8000
FM_SYM_LNK =

regular file

0xa000
FM_SOCKET =

symbolic link

0xc000
FT_UNKNOWN =

Values our callers may know

0
FT_FILE =
1
FT_DIRECTORY =
2
FT_CHAR =
3
FT_BLOCK =
4
FT_FIFO =
5
FT_SOCKET =
6
FT_SYM_LNK =
7
FILE_MODE_TO_FILE_TYPE_LOOKUP_TABLE =
{
  FM_FIFO      => FT_FIFO,
  FM_CHAR      => FT_CHAR,
  FM_DIRECTORY => FT_DIRECTORY,
  FM_BLOCK_DEV => FT_BLOCK,
  FM_FILE      => FT_FILE,
  FM_SYM_LNK   => FT_SYM_LNK,
  FM_SOCKET    => FT_SOCKET
}
MSK_FILE_MODE =

For accessor convenience.

0xf000
MSK_IS_DEV =
(FM_FIFO | FM_CHAR | FM_BLOCK_DEV | FM_SOCKET)
XFS_DINODE_FMT_DEV =

For Data Fork Data Format

0
XFS_DINODE_FMT_LOCAL =

Device Type

1
XFS_DINODE_FMT_EXTENTS =

Bulk Data

2
XFS_DINODE_FMT_BTREE =

xfs_bmbt_rec

3
XFS_DINODE_FMT_UUID =

xfs_bmdr_block

4
XFS_DATA_FORK =

uuid

0
XFS_ATTR_FORK =
1

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(buffer, offset, superblock, inode_number) ⇒ Inode

Returns a new instance of Inode.



225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
# File 'lib/fs/xfs/inode.rb', line 225

def initialize(buffer, offset, superblock, inode_number)
  raise "XFS::Inode: Nil buffer for inode #{inode_number}" if buffer.nil?
  @sb               = superblock
  @inode_number     = inode_number
  @offset           = offset
  if @sb.inode_size < SIZEOF_EXTENDED_INODE
    @in             = INODE.decode(buffer[offset..(offset + SIZEOF_INODE)])
  else
    @in             = EXTENDED_INODE.decode(buffer[offset..(offset + SIZEOF_EXTENDED_INODE)])
  end
  valid_inode? || return
  rewind
  @disk_buffer      = buffer
  @mode             = @in['file_mode']
  @flags            = @in['flags']
  @version          = @in['version']
  @length           = @in['size']
  @format           = @in['format']
  @block_offset     = 1
  @data_method      = inode_format
end

Instance Attribute Details

#attribute_forkObject

Returns the value of attribute attribute_fork.



205
206
207
# File 'lib/fs/xfs/inode.rb', line 205

def attribute_fork
  @attribute_fork
end

#data_forkObject

Returns the value of attribute data_fork.



205
206
207
# File 'lib/fs/xfs/inode.rb', line 205

def data_fork
  @data_fork
end

#data_methodObject (readonly)

Returns the value of attribute data_method.



204
205
206
# File 'lib/fs/xfs/inode.rb', line 204

def data_method
  @data_method
end

#disk_bufferObject (readonly)

Returns the value of attribute disk_buffer.



204
205
206
# File 'lib/fs/xfs/inode.rb', line 204

def disk_buffer
  @disk_buffer
end

#flagsObject (readonly)

Returns the value of attribute flags.



204
205
206
# File 'lib/fs/xfs/inode.rb', line 204

def flags
  @flags
end

#inObject (readonly)

Returns the value of attribute in.



204
205
206
# File 'lib/fs/xfs/inode.rb', line 204

def in
  @in
end

#inode_numberObject (readonly)

Returns the value of attribute inode_number.



204
205
206
# File 'lib/fs/xfs/inode.rb', line 204

def inode_number
  @inode_number
end

#lengthObject (readonly)

Returns the value of attribute length.



204
205
206
# File 'lib/fs/xfs/inode.rb', line 204

def length
  @length
end

#modeObject (readonly)

Returns the value of attribute mode.



204
205
206
# File 'lib/fs/xfs/inode.rb', line 204

def mode
  @mode
end

#sbObject (readonly)

Returns the value of attribute sb.



204
205
206
# File 'lib/fs/xfs/inode.rb', line 204

def sb
  @sb
end

#versionObject (readonly)

Returns the value of attribute version.



204
205
206
# File 'lib/fs/xfs/inode.rb', line 204

def version
  @version
end

Instance Method Details

#access_timeObject



301
302
303
# File 'lib/fs/xfs/inode.rb', line 301

def access_time
  @access_time ||= Time.at(@in['atime_secs'])
end

#aTimeObject

For compatibility with other filesystem methods



306
307
308
# File 'lib/fs/xfs/inode.rb', line 306

def aTime
  access_time
end

#create_timeObject



310
311
312
# File 'lib/fs/xfs/inode.rb', line 310

def create_time
  @create_time ||= Time.at(@in['ctime_secs'])
end

#cTimeObject

For compatibility with other filesystem methods



315
316
317
# File 'lib/fs/xfs/inode.rb', line 315

def cTime
  create_time
end

#device?Boolean

Returns:

  • (Boolean)


293
294
295
# File 'lib/fs/xfs/inode.rb', line 293

def device?
  (@mode & MSK_IS_DEV) > 0
end

#dfork_aptrObject



196
197
198
# File 'lib/fs/xfs/inode.rb', line 196

def dfork_aptr
  dfork_dptr + dfork_boff
end

#dfork_asizeObject



183
184
185
# File 'lib/fs/xfs/inode.rb', line 183

def dfork_asize
  dfork_q ? litino - dfork_boff : 0
end

#dfork_boffObject



175
176
177
# File 'lib/fs/xfs/inode.rb', line 175

def dfork_boff
  @in['attr_fork_offset'] << 3
end

#dfork_dptrObject



191
192
193
194
# File 'lib/fs/xfs/inode.rb', line 191

def dfork_dptr
  start = @offset + dinode_size(@version)
  @disk_buffer[start..start + @sb.inode_size]
end

#dfork_dsizeObject



179
180
181
# File 'lib/fs/xfs/inode.rb', line 179

def dfork_dsize
  dfork_q ? dfork_boff : litino
end

#dfork_qObject



171
172
173
# File 'lib/fs/xfs/inode.rb', line 171

def dfork_q
  @in['attr_fork_offset'] != 0
end

#dfork_size(which_fork) ⇒ Object



187
188
189
# File 'lib/fs/xfs/inode.rb', line 187

def dfork_size(which_fork)
  which_fork == XFS_DATA_FORK ? dfork_dsize : dfork_asize
end

#dinode_good_version(version) ⇒ Object



159
160
161
# File 'lib/fs/xfs/inode.rb', line 159

def dinode_good_version(version)
  version >= 1 && version <= 3
end

#dinode_size(version) ⇒ Object



163
164
165
166
167
168
169
# File 'lib/fs/xfs/inode.rb', line 163

def dinode_size(version)
  if version == 3
    SIZEOF_EXTENDED_INODE
  else
    SIZEOF_INODE
  end
end

#directory?Boolean

//////////////////////////////////////////////////////////////////////////// // Class helpers & accessors.

Returns:

  • (Boolean)


285
286
287
# File 'lib/fs/xfs/inode.rb', line 285

def directory?
  mode_set?(FM_DIRECTORY)
end

#dumpObject



359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
# File 'lib/fs/xfs/inode.rb', line 359

def dump
  out = "\#<#{self.class}:0x#{format('%08x', object_id)}>\n"
  out += "Inode Number : #{@inode_number}\n"
  out += "File mode    : 0x#{format('%04x', @in['file_mode'])}\n"
  out += "UID          : #{@in['uid']}\n"
  out += "Size         : #{@in['size']}\n"
  out += "ATime Secs/NSecs: #{@in['atime_secs']}/#{@in['atime_nsecs']}\n"
  out += "CTime Secs/NSecs: #{@in['ctime_secs']}/#{@in['ctime_nsecs']}\n"
  out += "MTime Secs/NSecs: #{@in['mtime_secs']}/#{@in['mtime_nsecs']}\n"
  out += "GID          : #{@in['gid']}\n"
  out += "Link count   : #{@in['num_links']}\n"
  out += "Old Link cnt : #{@in['old_num_links']}\n"
  out += "Block count  : #{@in['nblocks']}\n"
  out += "Extent size  : #{@in['extent_size']}\n"
  out += "Num extents  : #{@in['num_extents']}\n"
  out += "Data Fork Fmt : #{@data_method}\n"
  out += "Attr Fork Exts: #{@in['attr_num_extents']}\n"
  out += "Attr Fork Off : #{@in['attr_fork_offset']}\n"
  out += "Attr Fork Fmt : #{@in['attr_fork_format']}\n"
  out += "Flags        : #{format('%04x', @in['flags'])}\n"
  out += "Version      : #{@in['version']}\n"
  out += "Flush Iter   : #{@in['flush_iterator']}\n"
  out += "Generation   : #{@in['gen_num']}\n"
  out
end

#file?Boolean

Returns:

  • (Boolean)


289
290
291
# File 'lib/fs/xfs/inode.rb', line 289

def file?
  mode_set?(FM_FILE)
end

#file_mode_to_file_typeObject

//////////////////////////////////////////////////////////////////////////// // Utility functions.



347
348
349
# File 'lib/fs/xfs/inode.rb', line 347

def file_mode_to_file_type
  FILE_MODE_TO_FILE_TYPE_LOOKUP_TABLE[@mode & MSK_FILE_MODE]
end

#flag_set?(bit) ⇒ Boolean

Returns:

  • (Boolean)


355
356
357
# File 'lib/fs/xfs/inode.rb', line 355

def flag_set?(bit)
  (@flags & bit) == bit
end

#group_permissionsObject



336
337
338
# File 'lib/fs/xfs/inode.rb', line 336

def group_permissions
  @group_permissions ||= @in['file_mode'] & MSK_PERM_GROUP
end

#inode_formatObject



214
215
216
217
218
219
220
221
222
223
# File 'lib/fs/xfs/inode.rb', line 214

def inode_format
  if @format == XFS_DINODE_FMT_LOCAL
    data_method    = :local
  elsif @format == XFS_DINODE_FMT_EXTENTS
    data_method    = :extents
  else
    data_method    = :btree
  end
  data_method
end

#litinoObject



200
201
202
# File 'lib/fs/xfs/inode.rb', line 200

def litino
  @sb.inode_size - dinode_size(@version)
end

#mode_set?(bit) ⇒ Boolean

Returns:

  • (Boolean)


351
352
353
# File 'lib/fs/xfs/inode.rb', line 351

def mode_set?(bit)
  (@mode & bit) == bit
end

#modification_timeObject



319
320
321
# File 'lib/fs/xfs/inode.rb', line 319

def modification_time
  @modification_time ||= Time.at(@in['mtime_secs'])
end

#mTimeObject

For compatibility with other filesystem methods



324
325
326
# File 'lib/fs/xfs/inode.rb', line 324

def mTime
  modification_time
end

#owner_permissionsObject



332
333
334
# File 'lib/fs/xfs/inode.rb', line 332

def owner_permissions
  @owner_permissions ||= @in['file_mode'] & MSK_PERM_OWNER
end

#permissionsObject



328
329
330
# File 'lib/fs/xfs/inode.rb', line 328

def permissions
  @permissions ||= @in['file_mode'] & (MSK_PERM_OWNER | MSK_PERM_GROUP | MSK_PERM_USER)
end

#read(nbytes = @length) ⇒ Object



264
265
266
267
268
269
270
271
272
273
274
275
276
# File 'lib/fs/xfs/inode.rb', line 264

def read(nbytes = @length)
  raise "XFS::Inode.read: Can't read 4G or more at a time (use a smaller read size)" if nbytes >= MAX_READ
  return nil if @pos >= @length

  nbytes = @length - @pos if @pos + nbytes > @length
  return read_short_form(nbytes) if @data_method == :local

  # get data.
  start_block, start_byte, nblocks = pos_to_block(@pos, nbytes)
  out = read_blocks(start_block, nblocks)
  @pos += nbytes
  out[start_byte, nbytes]
end

#rewindObject

//////////////////////////////////////////////////////////////////////////// // Method for data access



249
250
251
# File 'lib/fs/xfs/inode.rb', line 249

def rewind
  @pos = 0
end

#seek(offset, method = IO::SEEK_SET) ⇒ Object



253
254
255
256
257
258
259
260
261
262
# File 'lib/fs/xfs/inode.rb', line 253

def seek(offset, method = IO::SEEK_SET)
  @pos = case method
         when IO::SEEK_SET then offset
         when IO::SEEK_CUR then @pos + offset
         when IO::SEEK_END then @length - offset
         end
  @pos = 0           if @pos < 0
  @pos = @length if @pos > @length
  @pos
end

#symlink?Boolean

Returns:

  • (Boolean)


297
298
299
# File 'lib/fs/xfs/inode.rb', line 297

def symlink?
  mode_set?(FM_SYM_LNK)
end

#user_permissionsObject



340
341
342
# File 'lib/fs/xfs/inode.rb', line 340

def user_permissions
  @user_permissions ||= @in['file_mode'] & MSK_PERM_USER
end

#valid_inode?Boolean

Returns:

  • (Boolean)


207
208
209
210
211
212
# File 'lib/fs/xfs/inode.rb', line 207

def valid_inode?
  $log.error "XFS::Inode: Bad Magic # inode #{@inode_number}" unless @in['magic'] == XFS_DINODE_MAGIC
  raise "XFS::Inode: Invalid Magic Number for inode #{@inode_number}"  unless @in['magic'] == XFS_DINODE_MAGIC
  raise "XFS::Inode: Invalid Inode Version for inode #{@inode_number}" unless dinode_good_version(@in['version'])
  true
end

#write(buf, _len = buf.length) ⇒ Object



278
279
280
# File 'lib/fs/xfs/inode.rb', line 278

def write(buf, _len = buf.length)
  raise "XFS::Inode.write: Write functionality is not yet supported on XFS."
end