Bring kernel version checking (utsname) into the central process.
[virt-mem.git] / lib / virt_mem_utsname.ml
1 (* Memory info command 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_types
25 open Virt_mem_mmap
26
27 (* Truncate an OCaml string at the first ASCII NUL character, ie. as
28  * if it were a C string.
29  *)
30 let truncate str =
31   try
32     let i = String.index str '\000' in
33     String.sub str 0 i
34   with
35     Not_found -> str
36
37 let parse_utsname bits =
38   (* Expect the first (sysname) field to always be "Linux", which is
39    * also a good way to tell if we're synchronized to the right bit of
40    * memory.
41    *)
42   bitmatch bits with
43   | { "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;
44       nodename : 65*8 : string;
45       release : 65*8 : string;
46       version : 65*8 : string;
47       machine : 65*8 : string;
48       domainname : 65*8 : string } ->
49       Some {
50         kernel_name = "Linux";
51         nodename = truncate nodename;
52         kernel_release = truncate release;
53         kernel_version = truncate version;
54         machine = truncate machine;
55         domainname = truncate domainname
56       }
57   | { _ } ->
58       None
59
60 let find_utsname debug (domid, name, arch, mem, lookup_ksym) =
61   let utsname =
62     (* In Linux 2.6.25, the symbol is init_uts_ns.
63      * http://lxr.linux.no/linux/init/version.c
64      *)
65     try
66       let addr = lookup_ksym "init_uts_ns" in
67
68       let bs = Bitstring.bitstring_of_string (get_bytes mem addr (65*6+4)) in
69       (bitmatch bs with
70        | { _ : 32 : int;              (* the kref, atomic_t, always 32 bits *)
71            new_utsname : -1 : bitstring } ->
72            parse_utsname new_utsname
73        | { _ } ->
74            if debug then
75              eprintf (f_"%s: unexpected init_uts_ns in kernel image\n") name;
76            None
77       )
78     with
79       Not_found ->
80         (* In Linux 2.6.9, the symbol is system_utsname.
81          * http://lxr.linux.no/linux-bk+v2.6.9/include/linux/utsname.h#L24
82          *)
83         try
84           let addr = lookup_ksym "system_utsname" in
85
86           let bits =
87             Bitstring.bitstring_of_string (get_bytes mem addr (65*6)) in
88           parse_utsname bits
89             with
90               Not_found ->
91                 eprintf (f_"%s: could not find utsname in kernel image\n") name
92   in
93   (domid, name, arch, mem, lookup_ksym, utsname)