1acd85517640244ae2980ec6a2aca885596ec9ca
[virt-top.git] / virt-df / virt_df_ext2.ml
1 (* 'df' command for virtual domains.
2    (C) Copyright 2007 Richard W.M. Jones, Red Hat Inc.
3    http://libvirt.org/
4
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
19    Support for EXT2/EXT3 filesystems.
20 *)
21
22 open Unix
23 open Printf
24 open Virt_df_gettext.Gettext
25
26 (* Int64 operators for convenience. *)
27 let (+^) = Int64.add
28 let (-^) = Int64.sub
29 let ( *^ ) = Int64.mul
30 let (/^) = Int64.div
31
32 let sector_size = Virt_df.sector_size
33 let read_int32_le = Virt_df.read_int32_le
34
35 let probe_ext2 target part_type fd start size =
36   LargeFile.lseek fd ((start+^2L) *^ sector_size) SEEK_SET;
37   let str = String.create 128 in
38   if read fd str 0 128 <> 128 then
39     failwith (s_ "error reading ext2/ext3 magic")
40   else (
41     if str.[56] != '\x53' || str.[57] != '\xEF' then (
42       Virt_df.ProbeFailed (s_ "partition marked EXT2/3 but no valid filesystem")
43     ) else (
44       (* Refer to <linux/ext2_fs.h> *)
45       let s_inodes_count = read_int32_le str 0 in
46       let s_blocks_count = read_int32_le str 4 in
47       let s_r_blocks_count = read_int32_le str 8 in
48       let s_free_blocks_count = read_int32_le str 12 in
49       let s_free_inodes_count = read_int32_le str 16 in
50       let s_first_data_block = read_int32_le str 20 in
51       let s_log_block_size = read_int32_le str 24 in
52       (*let s_log_frag_size = read_int32_le str 28 in*)
53       let s_blocks_per_group = read_int32_le str 32 in
54
55       (* Work out the block size in bytes. *)
56       let s_log_block_size = Int64.to_int s_log_block_size in
57       let block_size = 1024L in
58       let block_size = Int64.shift_left block_size s_log_block_size in
59
60       (* Number of groups. *)
61       let s_groups_count =
62         (s_blocks_count -^ s_first_data_block -^ 1L)
63         /^ s_blocks_per_group +^ 1L in
64
65 (*
66       (* Number of group descriptors per block. *)
67       let s_inodes_per_block = s_blocksize / 
68         let s_desc_per_block = block_size / s_inodes_per_block in
69         let db_count =
70           (s_groups_count +^ s_desc_per_block -^ 1L)
71           /^ s_desc_per_block
72 *)
73
74       (* Calculate the block overhead (used by superblocks, inodes, etc.)
75        * See fs/ext2/super.c.
76        *)
77       let overhead = s_first_data_block in
78       let overhead = (* XXX *) overhead in
79
80
81       Virt_df.Filesystem {
82         Virt_df.fs_name = s_ "Linux ext2/3";
83         fs_block_size = block_size;
84         fs_blocks_total = s_blocks_count -^ overhead;
85         fs_blocks_reserved = s_r_blocks_count;
86         fs_blocks_avail = s_free_blocks_count;
87         fs_blocks_used = s_blocks_count -^ overhead -^ s_free_blocks_count;
88         fs_inodes_total = s_inodes_count;
89         fs_inodes_reserved = 0L;        (* XXX? *)
90         fs_inodes_avail = s_free_inodes_count;
91         fs_inodes_used = s_inodes_count (*-^ 0L*) -^ s_free_inodes_count;
92       }
93     )
94   )
95
96 (* Register with main code. *)
97 let () =
98   Virt_df.fs_register
99     [ 0x83 ]                            (* Partition type. *)
100     probe_ext2