8dca6640270ae5e80408239c56ecc25626877228
[dragonfly.git] / contrib / bsdinstaller-1.1.6 / src / backend / lua / install / 250_partition_disk.lua
1 -- $Id: 250_partition_disk.lua,v 1.21 2005/03/31 12:35:50 den Exp $
2
3 require "gettext"
4
5 local datasets_list = nil
6
7 local name_to_sysid_map = {
8     ["DragonFly/FreeBSD"] =     165,
9     ["OpenBSD"] =               166,
10     ["NetBSD"] =                169,
11     ["MS-DOS"] =                15,
12     ["Linux"] =                 131,
13     ["Plan9"] =                 57
14 }
15
16 local options_list = {}
17 local sysid_to_name_map = {}
18 local k, v
19 for k, v in name_to_sysid_map do
20         table.insert(options_list, k)
21         sysid_to_name_map[v] = k
22 end
23
24 local populate_from_disk = function(dd)
25         local pd
26         local list = {}
27
28         local toyn = function(bool)
29                 if bool then
30                         return "Y"
31                 else
32                         return "N"
33                 end
34         end
35
36         for pd in dd:get_parts() do
37                 table.insert(list, {
38                         capstring = StorageDescriptor.format_capstring(pd:get_size()),
39                         sysid = sysid_to_name_map[pd:get_sysid()] or
40                                 tostring(pd:get_sysid()),
41                         active = toyn(pd:is_active())
42                 })
43         end
44
45         return list
46 end
47
48 local populate_one_big_partition = function(dd)
49         return {
50                 {
51                         capstring = "*",
52                         sysid     = "165",
53                         active    = "Y"
54                 }
55         }
56 end
57
58 local edit_partitions = function(fsm)
59         if not datasets_list then
60                 datasets_list = populate_from_disk(App.state.sel_disk)
61         end
62
63         local fields_list = {
64                 {
65                     id = "capstring",
66                     name = _("Capacity")
67                 },
68                 {
69                     id = "sysid",
70                     name = _("Partition Type"),
71                     options = options_list,
72                     editable = "false"
73                 },
74                 {
75                     id = "active",
76                     name = _("Active?"),
77                     control = "checkbox"
78                 }
79         }
80
81         local actions_list = {
82                 {
83                     id = "ok",
84                     name = _("Accept and Create"),
85                 },
86                 {
87                     id = "cancel",
88                     name = _("Return to %s", fsm:prev().title),
89                 }
90         }
91
92         local response = App.ui:present({
93             id = "edit_partitions",
94             name = _("Edit Partitions"),
95             short_desc = _("Select the partitions (also known "         ..
96                 "as `slices' in BSD tradition) you want to "            ..
97                 "have on this disk.\n\n"                                ..
98                 "For Capacity, use 'M' to indicate megabytes, 'G' to "  ..
99                 "indicate gigabytes, or a single '*' to indicate "      ..
100                 "'use the remaining space on the disk'."),
101             special = "bsdinstaller_edit_partitions",
102             minimum_width = "64",
103
104             actions = actions_list,
105             fields = fields_list,
106             datasets = datasets_list,
107
108             multiple = "true",
109             extensible = "true"
110         })
111
112         -- remember these subpartition selections in case we come back here.
113         datasets_list = response.datasets
114
115         return response.action_id == "ok"
116 end
117
118 local check_datasets = function(dd, list)
119         local i, dataset
120         local size
121         local disk_size = dd:get_raw_size()
122         local used_size = 60    -- initial offset
123         local wildcard_size = false
124
125         for i, dataset in list do
126                 if (name_to_sysid_map[dataset.sysid] or tonumber(dataset.sysid)) == 0 then
127                         App.ui:inform(_(
128                             "'%s' is not a recognized partition type. " ..
129                             "Please use a numeric identifier if you "   ..
130                             "wish to use an unlisted partition type.",
131                             dataset.sysid
132                         ))
133                         return false
134                 end
135
136                 if dataset.capstring == "*" then
137                         if wildcard_size then
138                                 App.ui:inform(_(
139                                     "Only one partition may have a " ..
140                                     "capacity of '*'."
141                                 ))
142                                 return false
143                         end
144                         wildcard_size = true
145                 end
146
147                 size = StorageDescriptor.parse_capstring(dataset.capstring, 0)
148                 if not size then
149                         App.ui:inform(_(
150                             "Capacity must either end in 'M' "          ..
151                             "for megabytes, 'G' for gigabytes, "        ..
152                             "or be '*' to indicate 'use all "           ..
153                             "remaining space.'"
154                         ))
155                         return false
156                 end
157
158                 used_size = used_size + size
159         end
160
161         if used_size > disk_size then
162                 if not App.ui:confirm(_(
163                     "WARNING: The total number of sectors needed "      ..
164                     "for the requested partitions (%d) exceeds the "    ..
165                     "number of sectors available on the disk (%d) "     ..
166                     "by %d sectors (%s.)\n\n"                           ..
167                     "This is an invalid configuration; we "             ..
168                     "recommend shrinking the size of one or "           ..
169                     "more partitions before proceeding.\n\n"            ..
170                     "Proceed anyway?",
171                     used_size, disk_size, used_size - disk_size,
172                     StorageDescriptor.format_capstring(used_size - disk_size))) then
173                         return false
174                 end
175         end
176
177         if used_size < disk_size - App.state.max_waste and
178            not wildcard_size then
179                 if not App.ui:confirm(_(
180                     "Note: the total number of sectors needed "         ..
181                     "for the requested partitions (%d) does not make "  ..
182                     "full use of the number of sectors available "      ..
183                     "on the disk (%d.)  There will be %d unused "       ..
184                     "sectors (%s.)\n\n"                                 ..
185                     "You may wish to expand one or more partitions "    ..
186                     "before proceeding.\n\n"                            ..
187                     "Proceed anyway?",
188                     used_size, disk_size, disk_size - used_size,
189                     StorageDescriptor.format_capstring(disk_size - used_size))) then
190                         return false
191                 end
192         end
193
194         return true
195 end
196
197 --
198 -- This assumes check_datasets has already been called.
199 --
200 local create_partitions_from_datasets = function(dd, list)
201         local i, dataset
202         local part_no = 1
203         local offset = 60
204         local disk_size = dd:get_raw_size()
205         local used_size = offset
206         local size
207         local sysid
208
209         dd:clear_parts()
210
211         for i, dataset in list do
212                 used_size = used_size +
213                     StorageDescriptor.parse_capstring(dataset.capstring, 0)
214         end
215
216         for i, dataset in list do
217                 size = StorageDescriptor.parse_capstring(dataset.capstring,
218                     disk_size - used_size)
219
220                 dd:add_part(PartitionDescriptor.new{
221                     parent = dd,
222                     number = part_no,
223                     start  = offset,
224                     size   = size,
225                     sysid  = name_to_sysid_map[dataset.sysid] or tonumber(dataset.sysid),
226                     active = (dataset.active == "Y")
227                 })
228
229                 offset = offset + size
230                 part_no = part_no + 1
231         end
232
233         return true
234 end
235
236 local do_edit_partitions = function(fsm)
237         if edit_partitions(fsm) then
238                 local cmds = CmdChain.new()
239
240                 if check_datasets(App.state.sel_disk, datasets_list) and
241                    create_partitions_from_datasets(
242                     App.state.sel_disk, datasets_list) then
243
244                         App.state.sel_disk:cmds_partition(cmds)
245                         cmds:execute()
246
247                         -- refresh our knowledge of the storage
248                         App.state.sel_disk, App.state.sel_part =
249                             App.state.storage:resurvey(
250                                 App.state.sel_disk, App.state.sel_part
251                             )
252
253                         -- Mark this disk as having been 'touched'
254                         -- (modified destructively, i.e. partitioned)
255                         -- by us.
256                         if App.state.sel_disk then
257                                 App.state.sel_disk:touch()
258                         end
259
260                         return fsm:next()
261                 else
262                         return fsm:current()
263                 end
264         else
265                 return fsm:prev()
266         end
267 end
268
269 return {
270     name = "partition_disk",
271     title = "Partition Disk",
272     action = function(fsm)
273         local choices = {}
274
275         if App.state.sel_disk:has_been_touched() then
276                 return do_edit_partitions(fsm)
277         end
278
279         if App.state.sel_disk:get_part_count() == 0 then
280                 App.ui:inform(_(
281                     "No valid partitions were found on this disk. "     ..
282                     "You will have to create at least one in which "    ..
283                     "to install %s.",
284                     App.os.name
285                 ))
286                 return do_edit_partitions(fsm)
287         end
288
289         choices[_("Format and Partition Disk")] = function()
290                 return do_edit_partitions(fsm)
291         end
292
293         choices[_("Skip this Step")] = function()
294                 return fsm:next()
295         end
296
297         choices[_("Return to %s", fsm:prev().title)] = function()
298                 return fsm:prev()
299         end
300
301         return App.ui:select(_(
302             "You may now format and partition this disk if you desire."         ..
303             "\n\n"                                                              ..
304             "If this is a brand new disk, you should do this. If you "          ..
305             "would like to place multiple operating systems on this disk, "     ..
306             "you should create multiple partitions, one for each operating "    ..
307             "system."                                                           ..
308             "\n\n"                                                              ..
309             "If this disk already has operating systems on it that you wish "   ..
310             "to keep, you should NOT do this, and should skip this step."       ..
311             "\n\n"                                                              ..
312             "Format and partition this disk?"),
313             choices
314         )()
315     end
316 }