fff6d7fa0c2ba71b1e80d375ed2191292b466d8d
[virt-mem.git] / uname / virt_uname.ml
1 (* Memory info for virtual domains.
2    (C) Copyright 2008 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
20 open Printf
21
22 open Virt_mem_gettext.Gettext
23 open Virt_mem_utils
24 open Virt_mem_mmap
25
26 let usage = s_"NAME
27   virt-uname - uname command for virtual machines
28
29 SUMMARY
30   virt-uname [-options] [domains]
31
32 DESCRIPTION
33   virt-uname prints the uname information such as OS version,
34   architecture and node name for virtual machines running under
35   libvirt."
36
37 let _, images = Virt_mem.start usage
38
39 let () =
40   (* Print new_utsname structure from bitstring. *)
41   let print_new_utsname name bs =
42     (* Truncate an OCaml string at the first ASCII NUL character, ie. as
43      * if it were a C string.
44      *)
45     let truncate str =
46       try
47         let i = String.index str '\000' in
48         String.sub str 0 i
49       with
50         Not_found -> str
51     in
52     (* Expect the first (sysname) field to always be "Linux", which is
53      * also a good way to tell if we're synchronized to the right bit of
54      * memory.
55      *)
56     bitmatch bs with
57     | { "Linux\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" : 65*8 : string;
58         nodename : 65*8 : string;
59         release : 65*8 : string;
60         version : 65*8 : string;
61         machine : 65*8 : string;
62         domainname : 65*8 : string } ->
63         printf "%s: Linux %s %s %s %s %s\n"
64           name
65           (truncate nodename) (truncate release)
66           (truncate version) (truncate machine) (truncate domainname)
67     | { _ } ->
68         eprintf (f_"%s: unexpected system_utsname in kernel image\n")
69           name
70   in
71
72   List.iter (
73     fun (name, arch, mem, lookup_ksym) ->
74       (* In Linux 2.6.25, the symbol is init_uts_ns.
75        * http://lxr.linux.no/linux/init/version.c
76        *)
77       try
78         let addr = lookup_ksym "init_uts_ns" in
79
80         let bs = Bitmatch.bitstring_of_string (get_bytes mem addr (65*6+4)) in
81         (bitmatch bs with
82          | { _ : 32 : int;              (* the kref, atomic_t, always 32 bits *)
83              new_utsname : -1 : bitstring } ->
84              print_new_utsname name new_utsname
85          | { _ } ->
86              eprintf (f_"%s: unexpected init_uts_ns in kernel image\n")
87                name)
88       with
89         Not_found ->
90           (* In Linux 2.6.9, the symbol is system_utsname.
91            * http://lxr.linux.no/linux-bk+v2.6.9/include/linux/utsname.h#L24
92            *)
93           try
94             let addr = lookup_ksym "system_utsname" in
95
96             let bs =
97               Bitmatch.bitstring_of_string (get_bytes mem addr (65*6)) in
98             print_new_utsname name bs
99           with
100             Not_found ->
101               eprintf (f_"%s: could not find utsname in kernel image\n") name
102   ) images