summaryrefslogtreecommitdiffstats
path: root/virt-df/virt_df_ext2.ml
blob: d2b51f38a8c8fb72445701d6a7c2979568dbec81 (plain)
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
(* 'df' command for virtual domains.
   (C) Copyright 2007 Richard W.M. Jones, Red Hat Inc.
   http://libvirt.org/

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

   Support for EXT2/EXT3 filesystems.
*)

open Unix
open Printf

(* Int64 operators for convenience. *)
let (+^) = Int64.add
let (-^) = Int64.sub
let ( *^ ) = Int64.mul
let (/^) = Int64.div

let sector_size = Virt_df.sector_size
let read_int32_le = Virt_df.read_int32_le

let probe_ext2 target part_type fd start size =
  LargeFile.lseek fd ((start+^2L) *^ sector_size) SEEK_SET;
  let str = String.create 128 in
  if read fd str 0 128 <> 128 then
    failwith "error reading ext2/ext3 magic"
  else (
    if str.[56] != '\x53' || str.[57] != '\xEF' then (
      Virt_df.ProbeFailed "partition marked EXT2/3 but no valid filesystem"
    ) else (
      (* Refer to <linux/ext2_fs.h> *)
      let s_inodes_count = read_int32_le str 0 in
      let s_blocks_count = read_int32_le str 4 in
      let s_r_blocks_count = read_int32_le str 8 in
      let s_free_blocks_count = read_int32_le str 12 in
      let s_free_inodes_count = read_int32_le str 16 in
      let s_first_data_block = read_int32_le str 20 in
      let s_log_block_size = read_int32_le str 24 in
      (*let s_log_frag_size = read_int32_le str 28 in*)
      let s_blocks_per_group = read_int32_le str 32 in

      (* Work out the block size in bytes. *)
      let s_log_block_size = Int64.to_int s_log_block_size in
      let block_size = 1024L in
      let block_size = Int64.shift_left block_size s_log_block_size in

      (* Number of groups. *)
      let s_groups_count =
	(s_blocks_count -^ s_first_data_block -^ 1L)
	/^ s_blocks_per_group +^ 1L in

(*
      (* Number of group descriptors per block. *)
      let s_inodes_per_block = s_blocksize / 
	let s_desc_per_block = block_size / s_inodes_per_block in
	let db_count =
	  (s_groups_count +^ s_desc_per_block -^ 1L)
	  /^ s_desc_per_block
*)

      (* Calculate the block overhead (used by superblocks, inodes, etc.)
       * See fs/ext2/super.c.
       *)
      let overhead = s_first_data_block in
      let overhead = (* XXX *) overhead in


      Virt_df.Filesystem {
	Virt_df.fs_name = "Linux ext2/3";
	fs_block_size = block_size;
	fs_blocks_total = s_blocks_count -^ overhead;
	fs_blocks_reserved = s_r_blocks_count;
	fs_blocks_avail = s_free_blocks_count;
	fs_blocks_used = s_blocks_count -^ overhead -^ s_free_blocks_count;
	fs_inodes_total = s_inodes_count;
	fs_inodes_reserved = 0L;	(* XXX? *)
	fs_inodes_avail = s_free_inodes_count;
	fs_inodes_used = s_inodes_count (*-^ 0L*) -^ s_free_inodes_count;
      }
    )
  )

(* Register with main code. *)
let () =
  Virt_df.fs_register
    [ 0x83 ]				(* Partition type. *)
    probe_ext2