unit properties;

interface

uses Windows, SysUtils, Classes, Graphics, Forms, Controls, StdCtrls,
  Buttons, ExtCtrls, ComCtrls, ex2, Linuxfs, INode, Users;

type
  TPropertiesDlg = class(TForm)
    OKBtn: TButton;
    CancelBtn: TButton;
    PageControl1: TPageControl;
    PartitionTab: TTabSheet;
    FileTab: TTabSheet;
    SuperblockTab: TTabSheet;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    Label6: TLabel;
    Label7: TLabel;
    Label8: TLabel;
    Label9: TLabel;
    Label10: TLabel;
    Label11: TLabel;
    Label12: TLabel;
    Label13: TLabel;
    Label14: TLabel;
    Label15: TLabel;
    Label16: TLabel;
    Label17: TLabel;
    Label18: TLabel;
    Label19: TLabel;
    Label20: TLabel;
    Label21: TLabel;
    Label22: TLabel;
    DirectLabel: TLabel;
    IndirectLabel: TLabel;
    Indirect2Label: TLabel;
    Indirect3Label: TLabel;
    Label27: TLabel;
    Label28: TLabel;
    Label29: TLabel;
    Label30: TLabel;
    Label31: TLabel;
    Label32: TLabel;
    Label33: TLabel;
    Label34: TLabel;
    Label35: TLabel;
    Label36: TLabel;
    Label37: TLabel;
    Label38: TLabel;
    Label39: TLabel;
    Blocksize: TLabel;
    blockcount: TLabel;
    inodecount: TLabel;
    reservecount: TLabel;
    freeblocks: TLabel;
    freeinodes: TLabel;
    blockspergroup: TLabel;
    fragspergroup: TLabel;
    inodespergroup: TLabel;
    mountime: TLabel;
    writetime: TLabel;
    mountcount: TLabel;
    maxcount: TLabel;
    fsstate: TLabel;
    error: TLabel;
    lastcheck: TLabel;
    maxtime: TLabel;
    os: TLabel;
    revision: TLabel;
    Location: TLabel;
    PartSize: TLabel;
    SectorSize: TLabel;
    INodeFileName: TLabel;
    inodeNo: TLabel;
    mode: TLabel;
    uid: TLabel;
    gid: TLabel;
    size: TLabel;
    atime: TLabel;
    ctime: TLabel;
    mtime: TLabel;
    dtime: TLabel;
    links: TLabel;
    blocks: TLabel;
    flags: TLabel;
    directblocks: TLabel;
    indirectblocks: TLabel;
    indirect2blocks: TLabel;
    indirect3blocks: TLabel;
    AttributeTabSheet: TTabSheet;
    GroupBox1: TGroupBox;
    GroupBox2: TGroupBox;
    GroupBox3: TGroupBox;
    URCheckBox: TCheckBox;
    UWCheckBox: TCheckBox;
    UXCheckBox: TCheckBox;
    SUIDCheckBox: TCheckBox;
    GRCheckBox: TCheckBox;
    GWCheckBox: TCheckBox;
    GXCheckBox: TCheckBox;
    SGIDCheckBox: TCheckBox;
    ORCheckBox: TCheckBox;
    OWCheckBox: TCheckBox;
    OXCheckBox: TCheckBox;
    INodeFlags: TLabel;
    Label40: TLabel;
    UserIDEdit: TEdit;
    Label41: TLabel;
    GroupIDEdit: TEdit;
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormCreate(Sender: TObject);
    procedure OKBtnClick(Sender: TObject);
    procedure UserIDEditChange(Sender: TObject);
  private
    Modified : Boolean;
    AttINode : TINode;
    { Private declarations }
    procedure SetAttributes(INode : TINode);
    procedure SaveAttributes;
  public
    { Public declarations }
    function Execute(Superblock : Pext2_super_block; Partition : TLinuxPartition; INode : TINode; FileName : String; UserLib : TUserList) : Integer;
  end;

var
  PropertiesDlg: TPropertiesDlg;

implementation

uses ex2explore, Time;

{$R *.DFM}

procedure TPropertiesDlg.FormClose(Sender: TObject;
  var Action: TCloseAction);
begin
   Action := caFree;
end;

function TPropertiesDlg.Execute(Superblock : Pext2_super_block; Partition : TLinuxPartition; INode : TINode; FileName : String; UserLib : TUserList) : Integer;
var
   i : Integer;
   Temp : String;
begin
   if Assigned(INode) then
   begin
      PageControl1.Pages[0].Tabvisible := True;
      INodeFileName.Caption  := FileName;
      INodeNo.Caption   := IntToStr(INode.INodeNo);
      mode.Caption      := INode.ModeString;
      uid.Caption       := IntToStr(INode.info.i_uid);
      gid.Caption       := IntToStr(INode.info.i_gid);
      if Assigned(UserLib) then
      begin
         uid.Caption := uid.Caption + ' (' + UserLib.GetName(INode.info.i_uid) + ')';
         gid.Caption := gid.Caption + ' (' + UserLib.GetGroup(INode.info.i_gid) + ')';
      end;
      size.Caption      := IntToStr(INode.info.i_size);
      atime.Caption     := Time.CTime(INode.info.i_atime);
      ctime.Caption     := Time.CTime(INode.info.i_ctime);
      mtime.Caption     := Time.CTime(INode.info.i_mtime);
      dtime.Caption     := Time.CTime(INode.info.i_dtime);
      links.Caption     := IntToStr(INode.info.i_links_count);
      blocks.Caption    := IntToStr(INode.info.i_blocks);
      flags.Caption     := IntToStr(INode.info.i_flags);

      if ((INode.Info.i_mode and S_IFMT) = S_IFLNK) then
      begin
         DirectLabel.Caption := 'link destination';
         IndirectBlocks.Caption := '';
         IndirectLabel.Visible := False;
         Indirect2Blocks.Caption := '';
         Indirect2Label.Visible := False;
         Indirect3Blocks.Caption := '';
         Indirect3Label.Visible := False;
         // use the blocks as a string....
         if (INode.Info.i_size <= (EXT2_N_BLOCKS * sizeof(ULONG))) then
         begin
            SetString(Temp, PChar(@INode.info.i_block[1]), INode.Info.i_size);
            directblocks.Caption := Temp;
         end
         else
         begin
            directblocks.Caption := 'Please export this file to view the link';
         end;
      end
      else if (INode.Info.i_mode and S_IFMT) = S_IFBLK then
      begin
         DirectLabel.Caption := 'block device';
         Directblocks.Caption := IntToHex(INode.info.i_block[1], 4);
         IndirectBlocks.Caption := '';
         IndirectLabel.Visible := False;
         Indirect2Blocks.Caption := '';
         Indirect2Label.Visible := False;
         Indirect3Blocks.Caption := '';
         Indirect3Label.Visible := False;
      end
      else if (INode.Info.i_mode and S_IFMT) = S_IFCHR then
      begin
         DirectLabel.Caption := 'character device';
         Directblocks.Caption := IntToHex(INode.info.i_block[1], 4);
         IndirectBlocks.Caption := '';
         IndirectLabel.Visible := False;
         Indirect2Blocks.Caption := '';
         Indirect2Label.Visible := False;
         Indirect3Blocks.Caption := '';
         Indirect3Label.Visible := False;
      end
      else
      begin
         directblocks.Caption := '';
         for i := 1 to EXT2_NDIR_BLOCKS do
         begin
            directblocks.Caption := directblocks.Caption + IntToStr(INode.info.i_block[i]) + ' ';
         end;
         indirectBlocks.Caption := IntToStr(INode.info.i_block[EXT2_IND_BLOCK]);
         indirect2Blocks.Caption := IntToStr(INode.info.i_block[EXT2_DIND_BLOCK]);
         indirect3Blocks.Caption := IntToStr(INode.info.i_block[EXT2_TIND_BLOCK]);
      end;

      PageControl1.Pages[0].Show;

      SetAttributes(INode);
   end
   else
   begin
      PageControl1.Pages[0].Tabvisible := False;
   end;

   if Assigned(Partition) then
   begin
      PageControl1.Pages[1].Tabvisible := True;
      Location.Caption     := Partition.GetFileName;
      PartSize.Caption     := IntToStr(Partition.GetLength.QuadPart);
      SectorSize.Caption   := IntToStr(Partition.GetSectorSize);
      PageControl1.Pages[1].Show;
   end
   else
   begin
      PageControl1.Pages[1].Tabvisible := False;
   end;

   if Assigned(Superblock) then
   begin
      PageControl1.Pages[2].Tabvisible := True;
      case Superblock.s_log_block_size of
         0: BlockSize.Caption := '1024';
         1: BlockSize.Caption := '2048';
         2: BlockSize.Caption := '4096';
         else BlockSize.Caption := 'unknown';
      end;
      Blockcount.Caption      := IntToStr(Superblock.s_blocks_count);
      inodecount.Caption      := IntToStr(Superblock.s_inodes_count);
      reservecount.Caption    := IntToStr(Superblock.s_r_blocks_count);
      freeblocks.Caption      := IntToStr(Superblock.s_free_blocks_count);
      freeinodes.Caption      := IntToStr(Superblock.s_free_inodes_count);
      Blockspergroup.Caption  := IntToStr(Superblock.s_blocks_per_group);
      fragspergroup.Caption   := IntToStr(Superblock.s_frags_per_group);
      inodespergroup.Caption  := IntToStr(Superblock.s_inodes_per_group);
      mountime.Caption        := IntToStr(Superblock.s_mtime);
      writetime.Caption       := IntToStr(Superblock.s_wtime);
      mountcount.Caption      := IntToStr(Superblock.s_mnt_count);
      maxcount.Caption        := IntToStr(Superblock.s_max_mnt_count);
      if (Superblock.s_state and EXT2_VALID_FS) = EXT2_VALID_FS then
      begin
         fsstate.Caption := 'Clean';
      end
      else
      begin
         fsstate.Caption := 'Not clean';
      end;

      if (Superblock.s_state and EXT2_ERROR_FS) = EXT2_ERROR_FS then
      begin
         fsstate.Caption := fsstate.Caption + ' & contains errors';
      end;
      error.Caption     := IntToStr(Superblock.s_errors);
      lastcheck.Caption := IntToStr(Superblock.s_lastcheck);
      maxtime.Caption   := IntToStr(Superblock.s_checkinterval);
      os.Caption        := IntToStr(Superblock.s_creator_os);
      revision.Caption  := IntToStr(Superblock.s_rev_level);
      PageControl1.Pages[2].Show;
   end
   else
   begin
      PageControl1.Pages[2].Tabvisible := False;
   end;

   Result := ShowModal;
end;

procedure TPropertiesDlg.SetAttributes(INode : TINode);
begin
   URCheckBox.Checked := ((INode.info.i_mode and S_IRUSR) = S_IRUSR);
   UWCheckBox.Checked := ((INode.info.i_mode and S_IWUSR) = S_IWUSR);
   UXCheckBox.Checked := ((INode.info.i_mode and S_IXUSR) = S_IXUSR);

   GRCheckBox.Checked := ((INode.info.i_mode and S_IRGRP) = S_IRGRP);
   GWCheckBox.Checked := ((INode.info.i_mode and S_IWGRP) = S_IWGRP);
   GXCheckBox.Checked := ((INode.info.i_mode and S_IXGRP) = S_IXGRP);

   ORCheckBox.Checked := ((INode.info.i_mode and S_IROTH) = S_IROTH);
   OWCheckBox.Checked := ((INode.info.i_mode and S_IWOTH) = S_IWOTH);
   OXCheckBox.Checked := ((INode.info.i_mode and S_IXOTH) = S_IXOTH);

   SUIDCheckBox.Checked := ((INode.info.i_mode and S_ISUID) = S_ISUID);
   SGIDCheckBox.Checked := ((INode.info.i_mode and S_ISGID) = S_ISGID);

   UserIDEdit.Text := IntToStr(INode.info.i_uid);
   GroupIDEdit.Text := IntToStr(INode.info.i_gid);

   AttINode := INode;

   if INode.Part.ReadWrite then
   begin
      AttributeTabSheet.Enabled := True;
   end;
end;


procedure TPropertiesDlg.FormCreate(Sender: TObject);
begin
    Modified := False;
end;

procedure TPropertiesDlg.OKBtnClick(Sender: TObject);
begin
   if Modified and AttINode.Part.ReadWrite then
   begin
      SaveAttributes;
   end;
end;

procedure TPropertiesDlg.SaveAttributes;
   procedure SetFlag(var Flags : USHORT; Flag : USHORT; Value : Boolean);
   begin
      Flags := Flags or Flag; // set the flag
      if not Value then
      begin
         Flags := Flags xor Flag; // toggle the flag
      end;
   end;

begin
   //
   SetFlag(AttINode.info.i_mode, S_IRUSR, URCheckBox.Checked);
   SetFlag(AttINode.info.i_mode, S_IWUSR, UWCheckBox.Checked);
   SetFlag(AttINode.info.i_mode, S_IXUSR, UXCheckBox.Checked);

   SetFlag(AttINode.info.i_mode, S_IRGRP, GRCheckBox.Checked);
   SetFlag(AttINode.info.i_mode, S_IWGRP, GWCheckBox.Checked);
   SetFlag(AttINode.info.i_mode, S_IXGRP, GXCheckBox.Checked);

   SetFlag(AttINode.info.i_mode, S_IROTH, ORCheckBox.Checked);
   SetFlag(AttINode.info.i_mode, S_IWOTH, OWCheckBox.Checked);
   SetFlag(AttINode.info.i_mode, S_IXOTH, OXCheckBox.Checked);

   SetFlag(AttINode.info.i_mode, S_ISUID, SUIDCheckBox.Checked);
   SetFlag(AttINode.info.i_mode, S_ISGID, SGIDCheckBox.Checked);

   AttINode.info.i_uid := StrToIntDef(UserIDEdit.Text, AttINode.info.i_uid);
   AttINode.info.i_gid := StrToIntDef(GroupIDEdit.Text, AttINode.info.i_gid);

   AttINode.Dirty := True;
end;


procedure TPropertiesDlg.UserIDEditChange(Sender: TObject);
begin
   Modified := True;
end;

end.
