Class: Ext4::Inode

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

Overview

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

Constant Summary collapse

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)
DF_STICKY =

Bits 9 to 11 of file mode.

0x0200
DF_SET_GID =
0x0400
DF_SET_UID =
0x0800
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
MSK_FILE_MODE =

For accessor convenience.

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

Inode flags.

0x00000001
IF_KEEP_COPY =

wipe when deleting

0x00000002
IF_COMPRESS =

never delete

0x00000004
IF_SYNCHRO =

compress content

0x00000008
IF_IMMUTABLE =

don’t cache

0x00000010
IF_APPEND =

file cannot change

0x00000020
IF_NO_DUMP =

always append

0x00000040
IF_NO_ATIME =

don’t cat

0x00000080
IF_DIRTY =

don’t update atime

0x00000100
IF_COMPR_CL =

One or more compressed clusters

0x00000200
IF_NOCOMPR =

Don’t compress

0x00000400
IF_ECOMPR =

Compression error

0x00000800
IF_HASH_INDEX =

if dir, has hash index

0x00001000
IF_AFS_DIR =

AFS directory

0x00002000
IF_JOURNAL =

if using journal, is journal inode

0x00004000
IF_NOTAIL =

file tail should not be merged

0x00008000
IF_DIRSYNC =

dirsync behaviour (directories only)

0x00010000
IF_TOPDIR =

Top of directory hierarchies

0x00020000
IF_HUGE_FILE =

Set to each huge file

0x00040000
IF_EXTENTS =

Inode uses extents

0x00080000
IF_EA_INODE =

Inode used for large EA

0x00200000
IF_EOFBLOCKS =

Blocks allocated beyond EOF

0x00400000
IF_FLAGS =
(IF_SECURE_DEL | IF_KEEP_COPY | IF_COMPRESS | IF_SYNCHRO | IF_IMMUTABLE | IF_APPEND | IF_NO_DUMP | IF_NO_ATIME | IF_DIRTY | IF_COMPR_CL | IF_NOCOMPR | IF_ECOMPR | IF_HASH_INDEX | IF_AFS_DIR | IF_JOURNAL | IF_NOTAIL | IF_DIRSYNC | IF_TOPDIR | IF_HUGE_FILE | IF_EXTENTS | IF_EA_INODE | IF_EOFBLOCKS)
FLAG_STR =
{
  IF_SECURE_DEL => 'IF_SECURE_DEL',
  IF_KEEP_COPY  => 'IF_KEEP_COPY',
  IF_COMPRESS   => 'IF_COMPRESS',
  IF_SYNCHRO    => 'IF_SYNCHRO',
  IF_IMMUTABLE  => 'IF_IMMUTABLE',
  IF_APPEND     => 'IF_APPEND',
  IF_NO_DUMP    => 'IF_NO_DUMP',
  IF_NO_ATIME   => 'IF_NO_ATIME',
  IF_DIRTY      => 'IF_DIRTY',
  IF_COMPR_CL   => 'IF_COMPR_CL',
  IF_NOCOMPR    => 'IF_NOCOMPR',
  IF_ECOMPR     => 'IF_ECOMPR',
  IF_HASH_INDEX => 'IF_HASH_INDEX',
  IF_AFS_DIR    => 'IF_AFS_DIR',
  IF_JOURNAL    => 'IF_JOURNAL',
  IF_NOTAIL     => 'IF_NOTAIL',
  IF_DIRSYNC    => 'IF_DIRSYNC',
  IF_TOPDIR     => 'IF_TOPDIR',
  IF_HUGE_FILE  => 'IF_HUGE_FILE',
  IF_EXTENTS    => 'IF_EXTENTS',
  IF_EA_INODE   => 'IF_EA_INODE',
  IF_EOFBLOCKS  => 'IF_EOFBLOCKS'
}
@@FM2FT =

Lookup table for File Mode to File Type.

{
  Inode::FM_FIFO      => DirectoryEntry::FT_FIFO,
  Inode::FM_CHAR      => DirectoryEntry::FT_CHAR,
  Inode::FM_DIRECTORY => DirectoryEntry::FT_DIRECTORY,
  Inode::FM_BLOCK_DEV => DirectoryEntry::FT_BLOCK,
  Inode::FM_FILE      => DirectoryEntry::FT_FILE,
  Inode::FM_SYM_LNK   => DirectoryEntry::FT_SYM_LNK,
  Inode::FM_SOCKET    => DirectoryEntry::FT_SOCKET
}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(buf, superblock, inum) ⇒ Inode

Returns a new instance of Inode.



152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/fs/ext4/inode.rb', line 152

def initialize(buf, superblock, inum)
  raise "Ext4::Inode.initialize: Nil buffer" if buf.nil?
  @in = INODE.decode(buf)

  @sb    = superblock
  @inum  = inum
  @mode  = @in['file_mode']
  @flags = @in['flags']

  if self.isSymLink? && length < SYM_LNK_SIZE
    @data_method = nil
    @symlnk = @in['data']
  elsif hasExtents?
    @data_method = :extents
  else
    @data_method = :indirect
  end

  rewind
end

Instance Attribute Details

#flagsObject (readonly)

Returns the value of attribute flags.



150
151
152
# File 'lib/fs/ext4/inode.rb', line 150

def flags
  @flags
end

#modeObject (readonly)

Returns the value of attribute mode.



150
151
152
# File 'lib/fs/ext4/inode.rb', line 150

def mode
  @mode
end

#posObject (readonly)

Returns the value of attribute pos.



150
151
152
# File 'lib/fs/ext4/inode.rb', line 150

def pos
  @pos
end

#symlnkObject (readonly)

Returns the value of attribute symlnk.



150
151
152
# File 'lib/fs/ext4/inode.rb', line 150

def symlnk
  @symlnk
end

Instance Method Details

#aTimeObject



256
257
258
# File 'lib/fs/ext4/inode.rb', line 256

def aTime
  @atime ||= Time.at(@in['atime'])
end

#cTimeObject



260
261
262
# File 'lib/fs/ext4/inode.rb', line 260

def cTime
  @ctime ||= Time.at(@in['ctime'])
end

#dTimeObject



268
269
270
# File 'lib/fs/ext4/inode.rb', line 268

def dTime
  @dtime ||= Time.at(@in['dtime'])
end

#dumpObject



311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
# File 'lib/fs/ext4/inode.rb', line 311

def dump
  out = "\#<#{self.class}:0x#{'%08x' % object_id}>\n"
  out += "Inode Number : #{@inum}\n"
  out += "File mode    : 0x#{'%04x' % @in['file_mode']}\n"
  out += "UID          : #{uid}\n"
  out += "Size         : #{length}\n"
  out += "ATime        : #{aTime}\n"
  out += "CTime        : #{cTime}\n"
  out += "MTime        : #{mTime}\n"
  out += "DTime        : #{dTime}\n"
  out += "GID          : #{gid}\n"
  out += "Link count   : #{@in['link_count']}\n"
  out += "Block count  : #{nblocks}\n"
  out += "Flags        : #{flags_to_s}\n"
  extra = @flags - (@flags & IF_FLAGS)
  out << "  Extra Flags: 0x#{'%08x' % extra}\n" if extra != 0
  out += "Version      : #{@in['version']}\n"
  out += "Data         : \n#{@in['data'].hex_dump}"
  out += "Generation   : 0x#{'%08x' % @in['gen_num']}\n"
  out += "Ext attrib   : 0x#{'%08x' % @in['ext_attrib']}\n"
  out += "Frag blk adrs: 0x#{'%08x' % @in['frag_blk']}\n"
  out += "Frag index   : 0x#{'%02x' % @in['frag_idx']}\n"
  out += "Frag size    : 0x#{'%02x' % @in['frag_siz']}\n"
  out
end

#fileModeToFileTypeObject

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



291
292
293
# File 'lib/fs/ext4/inode.rb', line 291

def fileModeToFileType
  @@FM2FT[@mode & MSK_FILE_MODE]
end

#flags_to_sObject



303
304
305
306
307
308
309
# File 'lib/fs/ext4/inode.rb', line 303

def flags_to_s
  str_flags = []
  FLAG_STR.each_key do |flag|
    str_flags << FLAG_STR[flag] if flagSet?(flag)
  end
  str_flags.join(' ')
end

#flagSet?(bit) ⇒ Boolean

Returns:

  • (Boolean)


299
300
301
# File 'lib/fs/ext4/inode.rb', line 299

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

#gidObject



220
221
222
# File 'lib/fs/ext4/inode.rb', line 220

def gid
  @gid ||= (@in['gid_hi'] << 16) | @in['gid_lo']
end

#groupPermissionsObject



280
281
282
# File 'lib/fs/ext4/inode.rb', line 280

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

#hasExtents?Boolean

Returns:

  • (Boolean)


252
253
254
# File 'lib/fs/ext4/inode.rb', line 252

def hasExtents?
  flagSet?(IF_EXTENTS)
end

#isDev?Boolean

Returns:

  • (Boolean)


240
241
242
# File 'lib/fs/ext4/inode.rb', line 240

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

#isDir?Boolean

Returns:

  • (Boolean)


232
233
234
# File 'lib/fs/ext4/inode.rb', line 232

def isDir?
  modeSet?(FM_DIRECTORY)
end

#isFile?Boolean

Returns:

  • (Boolean)


236
237
238
# File 'lib/fs/ext4/inode.rb', line 236

def isFile?
  modeSet?(FM_FILE)
end

#isHashedDir?Boolean

Returns:

  • (Boolean)


248
249
250
# File 'lib/fs/ext4/inode.rb', line 248

def isHashedDir?
  isDir? && flagSet?(IF_HASH_INDEX)
end

#isSymLink?Boolean

Returns:

  • (Boolean)


244
245
246
# File 'lib/fs/ext4/inode.rb', line 244

def isSymLink?
  modeSet?(FM_SYM_LNK)
end

#lengthObject



228
229
230
# File 'lib/fs/ext4/inode.rb', line 228

def length
  @length ||= (@in['size_hi'] << 32) | @in['size_lo']
end

#modeSet?(bit) ⇒ Boolean

Returns:

  • (Boolean)


295
296
297
# File 'lib/fs/ext4/inode.rb', line 295

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

#mTimeObject



264
265
266
# File 'lib/fs/ext4/inode.rb', line 264

def mTime
  @mtime ||= Time.at(@in['mtime'])
end

#nblocksObject



224
225
226
# File 'lib/fs/ext4/inode.rb', line 224

def nblocks
  @nblocks ||= (@in['blocks_hi'] << 32) | @in['blocks_lo']
end

#ownerPermissionsObject



276
277
278
# File 'lib/fs/ext4/inode.rb', line 276

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

#permissionsObject



272
273
274
# File 'lib/fs/ext4/inode.rb', line 272

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

#read(nbytes = length) ⇒ Object



190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/fs/ext4/inode.rb', line 190

def read(nbytes = length)
  raise "Ext4::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

  # Handle symbolic links.
  if symlnk
    out = symlnk[@pos...nbytes]
    @pos += nbytes
    return out
  end
  nbytes = length - @pos if @pos + nbytes > length

  # get data.
  start_block, start_byte, end_block, end_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



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

def rewind
  @pos = 0
end

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



179
180
181
182
183
184
185
186
187
188
# File 'lib/fs/ext4/inode.rb', line 179

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

#uidObject

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



216
217
218
# File 'lib/fs/ext4/inode.rb', line 216

def uid
  @uid ||= (@in['uid_hi'] << 16) | @in['uid_lo']
end

#userPermissionsObject



284
285
286
# File 'lib/fs/ext4/inode.rb', line 284

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

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



209
210
211
# File 'lib/fs/ext4/inode.rb', line 209

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