unit ex2;

interface

uses Windows;

type LONG = LongInt; // I hope!
type ULONG = LongWord; // I hope!
type USHORT = Word;//SmallInt; // I Hope!

const                                 
  EXT2_SUPER_MAGIC : USHORT =	$EF53;

type ext2_super_block = record
	s_inodes_count       : ULONG; // Inodes count
	s_blocks_count       : ULONG;	// Blocks count */
	s_r_blocks_count     : ULONG;	// Reserved blocks count */
	s_free_blocks_count  : ULONG; // Free blocks count */
	s_free_inodes_count  : ULONG; // Free inodes count */
	s_first_data_block   : ULONG;	// First Data Block */
	s_log_block_size     : ULONG;	// Block size */
	s_log_frag_size      : LONG;  // Fragment size */
	s_blocks_per_group   : ULONG;	// # Blocks per group */
	s_frags_per_group    : ULONG;	// # Fragments per group */
	s_inodes_per_group   : ULONG;	// # Inodes per group */
	s_mtime              : ULONG; // Mount time */
	s_wtime              : ULONG;	// Write time */
	s_mnt_count          : USHORT;// Mount count */
	s_max_mnt_count      : SHORT;	// Maximal mount count */
	s_magic              : USHORT;// Magic signature */
	s_state              : USHORT;// File system state */
	s_errors             : USHORT;// Behaviour when detecting errors */
	s_pad                : USHORT;
	s_lastcheck          : ULONG; // time of last check */
	s_checkinterval      : ULONG;	// max. time between checks */
	s_creator_os         : ULONG;	// OS */
	s_rev_level          : ULONG;	// Revision level */
	s_reserved           : array [0..235] of ULONG;	// Padding to the end of the block */
 end;
 Pext2_super_block = ^ext2_super_block;

 
const
   EXT2_NDIR_BLOCKS  = 12;
 	EXT2_IND_BLOCK    = EXT2_NDIR_BLOCKS + 1;
 	EXT2_DIND_BLOCK   = (EXT2_IND_BLOCK + 1);
   EXT2_TIND_BLOCK   = (EXT2_DIND_BLOCK + 1);
   EXT2_N_BLOCKS	   = 15; //(EXT2_TIND_BLOCK + 1); // 15

   // fs state
   EXT2_VALID_FS     = $0001; // unmounted cleanly
   EXT2_ERROR_FS     = $0002; // contains errors

 // Inode flags
 	EXT2_SECRM_FL     =  $00000001; // Secure deletion */
   EXT2_UNRM_FL		=	$00000002; //* Undelete */
   EXT2_COMPR_FL		=	$00000004; // Compress file */
   EXT2_SYNC_FL		=	$00000008; // Synchronous updates */
   EXT2_IMMUTABLE_FL	=	$00000010; // Immutable file */
   EXT2_APPEND_FL		=	$00000020; // writes to file may only append */
   EXT2_NODUMP_FL		=	$00000040; // do not dump file */

///*
// * Special inodes numbers
// */
const
  EXT2_BAD_INO          = 1;  // Bad blocks inode */
  EXT2_ROOT_INO         = 2;	// Root inode */
  EXT2_ACL_IDX_INO      = 3;	// ACL inode */
  EXT2_ACL_DATA_INO     = 4;	// ACL inode */
  EXT2_BOOT_LOADER_INO  = 5;	// Boot loader inode */
  EXT2_UNDEL_DIR_INO    = 6;  // Undelete directory inode */
  EXT2_FIRST_INO        = 11;	// First non reserved inode */


{/*
 * Structure of an inode on the disk
 * Please do not remove the union by removing the struct definiftions
 * for other OS's as it affects the size of struct ext2_inode
 */}

type
  ext2_inode = record
    	i_mode         : USHORT;	// File mode */
	 	i_uid          : USHORT;	// Owner Uid */
	  	i_size         : ULONG;		// Size in bytes */
	  	i_atime        : ULONG;		// Access time */
	  	i_ctime        : ULONG;		// Creation í˙˙˙˙˙˙˙time */
	  	i_mtime        : ULONG;		// Modification time */
	  	i_dtime        : ULONG;		// Deletion Time */
	 	i_gid          : USHORT;	// Group Id */
	 	i_links_count  : USHORT;	// Links count */
	  	i_blocks       : ULONG;		// Blocks count */
	  	i_flags        : ULONG;		// File flags */

		l_i_reserved1  : ULONG;    // OS dependent 1 */

	  	i_block        : array [1..EXT2_N_BLOCKS] of ULONG;	// Pointers to blocks */
	  	i_version      : ULONG;    // File version (for NFS) */
	  	i_file_acl     : ULONG;		// File ACL */
	  	i_dir_acl      : ULONG;		// Directory ACL */
	  	i_faddr        : ULONG;		// Fragment address */

		l_i_frag       : UCHAR;		// Fragment number */
      l_i_fsize      : UCHAR;		// Fragment size */
		i_pad1         : USHORT;
		l_i_reserved2 : array[1..2] of ULONG;
  end;
  Pext2_inode = ^ext2_inode;
  Aext2_inode = array[0..0] of ext2_inode;

  type ext2_group = record // group descriptor
      bg_block_bitmap      : ULONG;
      bg_inode_bitmap      : ULONG;
      bg_inode_table       : ULONG;
      bg_free_blocks_count : USHORT;
      bg_free_inodes_count : USHORT;
      bg_used_dirs_count   : USHORT;
      bg_pad               : USHORT;
      bg_reserved          : array[1..3] of ULONG;
  end;
  Pext2_group = ^ext2_group;

const
 // these are inode mode flags, taken from stat.h

   S_IFMT   = $F000; // format mask
   S_IFSOCK = $C000; // socket
   S_IFLNK  = $A000; // symbolic link
   S_IFREG  = $8000; // regular file
   S_IFBLK  = $6000; // block device
   S_IFDIR  = $4000; // directory
   S_IFCHR  = $2000; // character device
   S_IFIFO  = $1000; // fifo

   S_ISUID  = $0800; // SUID
   S_ISGID  = $0400; // SGID
   S_ISVTX  = $0200; // sticky bit

   S_IRWXU  = $01C0; // user mask
   S_IRUSR  = $0100;
   S_IWUSR  = $0080;
   S_IXUSR  = $0040;

   S_IRWXG  = $0038; // group mask
   S_IRGRP  = $0020;
   S_IWGRP  = $0010;
   S_IXGRP  = $0008;

   S_IRWXO  = $0007; // other mask
   S_IROTH  = $0004;
   S_IWOTH  = $0002;
   S_IXOTH  = $0001;


///*
// * Inode flags
// */
EXT2_SECRM_FL		=	$00000001; //* Secure deletion */
EXT2_UNRM_FL		=	$00000002; //* Undelete */
EXT2_COMPR_FL		=	$00000004; //* Compress file */
EXT2_SYNC_FL		=	$00000008; //* Synchronous updates */
EXT2_IMMUTABLE_FL	=	$00000010; //* Immutable file */
EXT2_APPEND_FL		=	$00000020; //* writes to file may only append */
EXT2_NODUMP_FL		=	$00000040; //* do not dump file */
EXT2_NOATIME_FL	=	$00000080; //* do not update atime */
EXT2_RESERVED_FL	=	$80000000; //* reserved for ext2 lib */



type
  ext2_dir_entry = record
   inode    : ULONG;
   rec_len  : USHORT;
   name_len : USHORT;
   name     : array[0..0] of Char;
  end;
  Pext2_dir_entry = ^ext2_dir_entry;

  // fast symbolic links:
  // I think, from inital experiments that if a symbolic link points
  // to the same file system, immediatly after the name the inode of
  // the destination inode is written as a string.
  // this is only speculation, and it seems safe to ignore this
  // if you want (which is what I do)

implementation

{
Format of disk?
Boot sector = 512 bytes
Superblock = 1024 bytes always at offset 1024
^ contains log_block_size
blocks of n size start at the block offset specified in the superblock


the filesystem is divided up into block-groups
each block group has
superblock | descriptors | group info | data blocks
the last group may not be complete, depending on the partition size.
}

end.
