ia64/xen-unstable

view tools/pygrub/src/GrubConf.py @ 7238:971e7c7411b3

Raise an exception if an error appears on the pipes to our children, and make
sure that the child's pipes are closed even under that exception. Move the
handling of POLLHUP to the end of the loop, so that we guarantee to read any
remaining data from the child if POLLHUP and POLLIN appear at the same time.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author emellor@ewan
date Thu Oct 06 10:13:11 2005 +0100 (2005-10-06)
parents f85eb51dc313
children 2e8b1175fd37
line source
1 #
2 # GrubConf.py - Simple grub.conf parsing
3 #
4 # Copyright 2005 Red Hat, Inc.
5 # Jeremy Katz <katzj@redhat.com>
6 #
7 # This software may be freely redistributed under the terms of the GNU
8 # general public license.
9 #
10 # You should have received a copy of the GNU General Public License
11 # along with this program; if not, write to the Free Software
12 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
13 #
15 import os, sys
16 import logging
18 def grub_split(s, maxsplit = -1):
19 """Split a grub option screen separated with either '=' or whitespace."""
20 eq = s.find('=')
21 if eq == -1:
22 return s.split(None, maxsplit)
24 # see which of a space or tab is first
25 sp = s.find(' ')
26 tab = s.find('\t')
27 if (tab != -1 and tab < sp) or (tab != -1 and sp == -1):
28 sp = tab
30 if eq != -1 and eq < sp or (eq != -1 and sp == -1):
31 return s.split('=', maxsplit)
32 else:
33 return s.split(None, maxsplit)
35 def get_path(s):
36 """Returns a tuple of (GrubDiskPart, path) corresponding to string."""
37 if not s.startswith('('):
38 return (None, s)
39 idx = s.find(')')
40 if idx == -1:
41 raise ValueError, "Unable to find matching ')'"
42 d = s[:idx]
43 return (GrubDiskPart(d), s[idx + 1:])
45 class GrubDiskPart(object):
46 def __init__(self, str):
47 if str.find(',') != -1:
48 (self.disk, self.part) = str.split(",", 2)
49 else:
50 self.disk = str
51 self.part = None
53 def __repr__(self):
54 if self.part is not None:
55 return "d%dp%d" %(self.disk, self.part)
56 else:
57 return "d%d" %(self,disk,)
59 def get_disk(self):
60 return self._disk
61 def set_disk(self, val):
62 val = val.replace("(", "").replace(")", "")
63 self._disk = int(val[2:])
64 disk = property(get_disk, set_disk)
66 def get_part(self):
67 return self._part
68 def set_part(self, val):
69 if val is None:
70 self._part = val
71 return
72 val = val.replace("(", "").replace(")", "")
73 self._part = int(val)
74 part = property(get_part, set_part)
76 class GrubImage(object):
77 def __init__(self, lines):
78 self._root = self._initrd = self._kernel = self._args = None
79 for l in lines:
80 (com, arg) = grub_split(l, 1)
82 if self.commands.has_key(com):
83 if self.commands[com] is not None:
84 exec("%s = r\"%s\"" %(self.commands[com], arg.strip()))
85 else:
86 logging.info("Ignored image directive %s" %(com,))
87 else:
88 logging.warning("Unknown image directive %s" %(com,))
90 def __repr__(self):
91 return ("title: %s\n"
92 " root: %s\n"
93 " kernel: %s\n"
94 " args: %s\n"
95 " initrd: %s" %(self.title, self.root, self.kernel,
96 self.args, self.initrd))
98 def set_root(self, val):
99 self._root = GrubDiskPart(val)
100 def get_root(self):
101 return self._root
102 root = property(get_root, set_root)
104 def set_kernel(self, val):
105 if val.find(" ") == -1:
106 self._kernel = get_path(val)
107 self._args = None
108 return
109 (kernel, args) = val.split(None, 1)
110 self._kernel = get_path(kernel)
111 self._args = args
112 def get_kernel(self):
113 return self._kernel
114 def get_args(self):
115 return self._args
116 kernel = property(get_kernel, set_kernel)
117 args = property(get_args)
119 def set_initrd(self, val):
120 self._initrd = get_path(val)
121 def get_initrd(self):
122 return self._initrd
123 initrd = property(get_initrd, set_initrd)
125 # set up command handlers
126 commands = { "title": "self.title",
127 "root": "self.root",
128 "rootnoverify": "self.root",
129 "kernel": "self.kernel",
130 "initrd": "self.initrd",
131 "chainloader": None,
132 "module": None}
135 class GrubConfigFile(object):
136 def __init__(self, fn = None):
137 self.filename = fn
138 self.images = []
139 self.timeout = -1
141 if fn is not None:
142 self.parse()
144 def parse(self, buf = None):
145 if buf is None:
146 if self.filename is None:
147 raise ValueError, "No config file defined to parse!"
149 f = open(self.filename, 'r')
150 lines = f.readlines()
151 f.close()
152 else:
153 lines = buf.split("\n")
155 img = []
156 for l in lines:
157 l = l.strip()
158 # skip blank lines
159 if len(l) == 0:
160 continue
161 # skip comments
162 if l.startswith('#'):
163 continue
164 # new image
165 if l.startswith("title"):
166 if len(img) > 0:
167 self.images.append(GrubImage(img))
168 img = [l]
169 continue
171 if len(img) > 0:
172 img.append(l)
173 continue
175 try:
176 (com, arg) = grub_split(l, 1)
177 except ValueError:
178 com = l
179 arg = ""
181 if self.commands.has_key(com):
182 if self.commands[com] is not None:
183 exec("%s = r\"%s\"" %(self.commands[com], arg.strip()))
184 else:
185 logging.info("Ignored directive %s" %(com,))
186 else:
187 logging.warning("Unknown directive %s" %(com,))
189 if len(img) > 0:
190 self.images.append(GrubImage(img))
192 def _get_default(self):
193 return self._default
194 def _set_default(self, val):
195 if val == "saved":
196 self._default = -1
197 else:
198 self._default = int(val)
200 if self._default < 0:
201 raise ValueError, "default must be positive number"
202 default = property(_get_default, _set_default)
204 def set_splash(self, val):
205 self._splash = get_path(val)
206 def get_splash(self):
207 return self._splash
208 splash = property(get_splash, set_splash)
210 # set up command handlers
211 commands = { "default": "self.default",
212 "timeout": "self.timeout",
213 "fallback": "self.fallback",
214 "hiddenmenu": "self.hiddenmenu",
215 "splashimage": "self.splash",
216 "password": "self.password" }
217 for c in ("bootp", "color", "device", "dhcp", "hide", "ifconfig",
218 "pager", "partnew", "parttype", "rarp", "serial",
219 "setkey", "terminal", "terminfo", "tftpserver", "unhide"):
220 commands[c] = None
221 del c
224 if __name__ == "__main__":
225 if sys.argv < 2:
226 raise RuntimeError, "Need a grub.conf to read"
227 g = GrubConfigFile(sys.argv[1])
228 for i in g.images:
229 print i #, i.title, i.root, i.kernel, i.args, i.initrd