source: MondoRescue/branches/2.2.10/mondo/src/mondorestore/mondo-prep.c@ 2816

Last change on this file since 2816 was 2816, checked in by Bruno Cornec, 13 years ago

svn merge (in svk) -r 2714:2773 2.2.9 in 2.2.10

r4207@localhost (orig r2716): bruno | 2011-02-03 01:29:51 +0100

  • Increase boot size again to support better fedora 13/14


r4208@localhost (orig r2717): bruno | 2011-02-12 15:43:36 +0100

  • Excluding vmhgfs FS for VMWare guests mounting areas of the host.


r4209@localhost (orig r2718): bruno | 2011-02-18 00:30:35 +0100
-Extend EXTRA-SIZE for Debian 6.0 (at least)


r4210@localhost (orig r2719): bruno | 2011-02-18 00:45:40 +0100

  • Fix #462 (removes temp dir if analyze-my-lvm launched in stand alonae mode)


r4213@localhost (orig r2722): bruno | 2011-02-25 18:44:47 +0100

  • Fixes for RHEL6 support at least around dm extensions, bnx2x and cp210x dependencies


r4214@localhost (orig r2723): bruno | 2011-02-25 19:00:17 +0100

  • Adds a restore quiet option


r4215@localhost (orig r2724): bruno | 2011-02-25 19:43:50 +0100

  • Adds support for dm-log used on RHEL6 as well.


r4216@localhost (orig r2725): bruno | 2011-02-25 21:26:54 +0100

  • Update mindi-busybox to 1.18.3 to avoid problems with the tar command which is now failing on recent versions with busybox 1.7.3


r4217@localhost (orig r2726): bruno | 2011-02-26 11:38:29 +0100

  • Fix error introduced in previous patch in the if/then/else case without member in the then


r4218@localhost (orig r2727): bruno | 2011-02-26 12:05:33 +0100

  • With mindi-busybox 1.18.3 the syntax of openvt changed. This patch keeps a compatible init script for both previous and current version.


r4219@localhost (orig r2728): bruno | 2011-02-26 15:27:40 +0100

  • Latest lvdisplay print MiB instead of MB. Impact on analyze-my-lvm fixed.


r4220@localhost (orig r2729): bruno | 2011-02-26 16:39:32 +0100

  • Adds feature rpc to mindi-busybox in case of need



r4221@localhost (orig r2730): bruno | 2011-02-26 16:42:43 +0100

  • Adds the rebot command to the list of mandatory ones at restore time


r4222@localhost (orig r2731): bruno | 2011-02-26 17:37:13 +0100

  • Adds functions and /bin/loadkeys (new location) to minimal set of commands to have
  • provides a makemessage option to mindi and this function now works with pbdistrocheck
  • Do not create an error when a phys device has 0 size and is a /dev/dm-* device


r4223@localhost (orig r2732): bruno | 2011-02-26 19:07:43 +0100

  • Syntax fix


r4224@localhost (orig r2733): bruno | 2011-02-26 19:51:16 +0100

  • Fix test on dm which was made in wrong sense
  • Adds a driver to allow raid456 to work


r4225@localhost (orig r2734): bruno | 2011-02-26 20:55:00 +0100

  • Fix 2 redirections issues


r4317@localhost (orig r2737): bruno | 2011-03-13 13:12:57 +0100

  • Add support for libahci driver, mandatory for debian 6.


r4318@localhost (orig r2738): bruno | 2011-03-13 14:46:37 +0100

  • Update from Lester Wade (lester.wade_at_hp.com) incorporating latest ML feedbacks


r4319@localhost (orig r2739): bruno | 2011-03-13 17:49:15 +0100

  • Updated Lab for TES 2011


r4323@localhost (orig r2743): bruno | 2011-03-20 01:37:40 +0100

  • Fix a seg fault bug when using the GUI in case exclude_paths was NULL (mc_at_carreira.com.pt)


r4324@localhost (orig r2744): bruno | 2011-03-20 19:38:14 +0100

  • Adds Arch Linux Keyboard support (mc_at_carreira.com.pt)


r4325@localhost (orig r2745): bruno | 2011-03-20 19:48:01 +0100

  • Avoids coredump again when exclude_path is NULL with mr_make_devlist_from_pathlist (feedback from mc_at_carreira.com.pt)


r4326@localhost (orig r2746): bruno | 2011-03-20 19:39:47 +0100

  • Remove blkid from busybox to solve #435


r4327@localhost (orig r2747): bruno | 2011-03-20 19:43:22 +0100

  • Adds reboot to fix #435


r4328@localhost (orig r2748): bruno | 2011-03-22 00:58:07 +0100

  • Fix Arch Linux kbd printed in log file now instead of screen.


r4329@localhost (orig r2749): bruno | 2011-03-22 00:59:58 +0100

  • Again increase size for boot env to support better fedora 14 and other latest distros


r4356@localhost (orig r2750): bruno | 2011-03-25 19:30:01 +0100

  • Improve Arch Linux support for mindi tools (mc_at_carreira.com.pt)


r4357@localhost (orig r2751): bruno | 2011-03-25 19:48:33 +0100

  • Accept to work with either wodim or cdreord and genisoimage or mkisofs


r4358@localhost (orig r2752): bruno | 2011-03-25 20:20:49 +0100

  • Documents option -v of mondoarchive


r4359@localhost (orig r2753): bruno | 2011-03-29 01:34:30 +0200

  • Use modprobe instead of insmod to load loop, cd, ... modules (in order to force them at rstore time). Also drop very old aes support for mdk 9.2


r4360@localhost (orig r2754): bruno | 2011-03-29 01:38:49 +0200

  • Arch Linux support for boot message of mindi (mc_at_carreira.com.pt) using /etc/arch-release and pacman.log


r4383@localhost (orig r2755): bruno | 2011-04-07 09:49:38 +0200

  • Adds a UdevadmTrigger function at restore time to deal with the various syntax formats changes ddepending on version (mc_at_carreira.com.pt)


r4384@localhost (orig r2756): bruno | 2011-04-07 10:05:24 +0200

  • Increase again sizes for Debian 6 support (victor.gattegno_at_hp.com)


r4385@localhost (orig r2757): bruno | 2011-04-07 10:13:00 +0200
Conform to the report of size really !


r4386@localhost (orig r2758): bruno | 2011-04-07 11:31:12 +0200

  • Improved message for Arch Linux for rebuilding the initrd (mc_at_carreira.com.pt)


r4390@localhost (orig r2759): bruno | 2011-04-12 01:15:00 +0200

  • Typo in Web site


r4392@localhost (orig r2761): bruno | 2011-04-14 00:23:38 +0200

  • Adds download references for latest versions.


r4394@localhost (orig r2763): bruno | 2011-04-16 00:35:08 +0200

  • Adds support for MT back mandatory for OBDR.


r4395@localhost (orig r2764): bruno | 2011-04-20 12:18:46 +0200
Function resize_drive_proportionately_to_suit_new_drives

  • Integrate some mr_asprintf
  • Use systematically long long data types in all computation to match the struct mountlist_reference size member and have correct precision
  • Apply JB general_at_itpsg.com patch to make the partition resizing work properly according to the drive size (keeping all calculation in KB and converting only for display)


r4396@localhost (orig r2765): bruno | 2011-04-21 11:20:58 +0200

  • Remove very old code creating confusing symlinks pico to nano in init (patch from MC). Fix #477


r4397@localhost (orig r2766): bruno | 2011-04-21 11:57:44 +0200

  • text's are properly centered in open_and_list_dir (Patch from Chucky). Fix #404.


r4398@localhost (orig r2767): bruno | 2011-04-21 12:49:40 +0200

  • Attempt to fix #432 with a better message at a start.


r4399@localhost (orig r2768): bruno | 2011-04-21 13:00:37 +0200

Log content of mondo-restore.cfg


r4400@localhost (orig r2769): bruno | 2011-04-21 13:48:52 +0200

  • Introduce a new bkpinfo member (subdir) to support storing the subdir under which ISO images are stored on an external HDD. Should fix mostly #433.


r4401@localhost (orig r2770): bruno | 2011-04-21 14:14:52 +0200

  • Fix compilation issues due to level of visibility of functions


r4402@localhost (orig r2771): bruno | 2011-04-22 01:49:03 +0200

  • Adds GUI support for compresion type. Fix half of #468.


r4403@localhost (orig r2772): bruno | 2011-04-22 02:00:07 +0200

  • Adds support of ext attr through the GUI. Fix second part of #468


r4404@localhost (orig r2773): bruno | 2011-04-22 02:22:24 +0200

  • Propose more variables in the mindi.conf example
  • More explicit messages when size unsufficient in mindi for kernel + initrd as per #471
  • Better loging of labeling in mondo when in nuke mode


  • Property svn:keywords set to Id
File size: 71.2 KB
Line 
1/***************************************************************************
2$Id: mondo-prep.c 2816 2011-04-29 13:42:55Z bruno $
3* Functions for prepping hard drives: partitioning, formatting, etc.
4*/
5
6
7#include "my-stuff.h"
8#include "mr_mem.h"
9#include "../common/mondostructures.h"
10#include "mondoprep.h"
11#include "../common/libmondo.h"
12#include "mondo-rstr-tools-EXT.h"
13#include <sys/ioctl.h>
14#include <linux/hdreg.h>
15#include <math.h>
16
17
18#define FDISK_LOG "/var/log/mondofdisk.log"
19
20#ifdef __FreeBSD__
21#define DKTYPENAMES
22#define FSTYPENAMES
23#include <sys/disklabel.h>
24#include <sys/disk.h>
25#include <err.h>
26#include <libgen.h>
27#define OSSWAP(x,y) y
28#else
29#define OSSWAP(x,y) x
30#endif
31
32#define ARCHIVES_PATH MNT_CDROM"/archives"
33#define MONDO_WAS_HERE "MONDOWOZEREMONDOWOZEREMONDOWOZEREhahahaMOJOJOJO"
34
35//static char cvsid[] = "$Id: mondo-prep.c 2816 2011-04-29 13:42:55Z bruno $";
36
37extern long g_current_progress, g_maximum_progress;
38
39extern bool g_text_mode;
40
41extern void pause_for_N_seconds(int, char *);
42extern char *MONDO_LOGFILE;
43
44FILE *g_fprep = NULL;
45
46
47
48int g_partition_table_locked_up = 0;
49
50
51
52
53
54
55
56
57
58
59void wipe_MBRs_and_reboot_if_necessary(struct mountlist_itself *mountlist)
60{
61 char *command = NULL;
62 int lino;
63 int i;
64 int res = 0;
65 FILE *fout;
66 char *buf;
67 const int blocksize = 512;
68 struct list_of_disks *drivelist = NULL;
69
70// If LVMs are present and a zero-and-reboot wasn't recently undertaken
71// then zero & insist on reboot.
72 buf = malloc(blocksize);
73 if (does_file_exist(MINDI_CACHE"/i-want-my-lvm")) // FIXME - cheating :)
74 {
75 drivelist = malloc(sizeof(struct list_of_disks));
76 make_list_of_drives_in_mountlist(mountlist, drivelist);
77 for (lino = 0; lino < drivelist->entries; lino++) {
78 mr_asprintf(command, "dd if=%s bs=512 count=1 2> /dev/null | grep \"%s\"", drivelist->el[lino].device, MONDO_WAS_HERE);
79 res = run_program_and_log_output(command, 1);
80 mr_free(command);
81 if (!res) {
82 log_msg(1, "Found MONDO_WAS_HERE marker on drive#%d (%s)",
83 lino, drivelist->el[lino].device);
84 break;
85 }
86 }
87
88 if (lino == drivelist->entries) {
89// zero & reboot
90 log_to_screen("I am sorry for the inconvenience but I must ask you to reboot.");
91 log_to_screen("I need to reset the Master Boot Record; in order to be");
92 log_to_screen("sure the kernel notices, I must reboot after doing it.");
93 log_to_screen("Please hit 'Enter' to reboot.");
94 for (lino = 0; lino < drivelist->entries; lino++) {
95 for (i = 0; i < blocksize; i++) {
96 buf[i] = 0;
97 }
98 sprintf(buf, "%s\n", MONDO_WAS_HERE);
99 fout = fopen(drivelist->el[lino].device, "w+");
100 if (!fout) {
101 log_msg(1, "Unable to open+wipe %s",
102 drivelist->el[lino].device);
103 } else {
104 if (1 != fwrite(buf, blocksize, 1, fout)) {
105 log_msg(1, "Failed to wipe %s",
106 drivelist->el[lino].device);
107 } else {
108 log_msg(1, "Successfully wiped %s",
109 drivelist->el[lino].device);
110 }
111 fclose(fout);
112 }
113 }
114 sync();
115 sync();
116 sync();
117 popup_and_OK
118 ("I must now reboot. Please leave the boot media in the drive and repeat your actions - e.g. type 'nuke' - and it should work fine.");
119 system("reboot");
120 }
121 }
122// Still here? Cool!
123 log_msg(1, "Cool. I didn't have to wipe anything.");
124}
125
126
127
128
129
130
131int fput_string_one_char_at_a_time(FILE * fout, char *str)
132{
133 int i, j;
134 FILE *fq;
135
136 if (ferror(fout)) {
137 return (-1);
138 }
139 log_msg(5, "Writing string '%s', one char at a time", str);
140 j = strlen(str);
141 for (i = 0; i < j; i++) {
142 log_msg(6, "Writing %d ('%c')", str[i], str[i]);
143 if ((fq = fopen(FDISK_LOG, "a+"))) {
144 fputc(str[i], fq);
145 fclose(fq);
146 }
147 fputc(str[i], fout);
148 fflush(fout);
149 usleep(1000L * 100L);
150 if (str[i] < 32) {
151 usleep(1000L * 10L);
152 }
153 }
154 log_msg(5, "Returning");
155
156 return (i);
157}
158
159
160
161
162
163
164
165
166
167
168/**
169 * @addtogroup prepGroup
170 * @{
171 */
172/**
173 * Execute the commands in MINDI_CACHE"i-want-my-lvm.
174 * These should probably be commands to set up LVM.
175 * @return The number of errors encountered (0 for success).
176 */
177
178
179int do_my_funky_lvm_stuff(bool just_erase_existing_volumes,
180 bool vacuum_pack)
181{
182 /** buffers **********************************************/
183 char *tmp = NULL;
184 char *tmp1 = NULL;
185 char *incoming = NULL;
186 char *command;
187 char *lvscan_sz = NULL;
188 char *lvremove_sz = NULL;
189 char *pvscan_sz = NULL;
190 char *vgscan_sz = NULL;
191 char *vgchange_sz = NULL;
192 char *vgremove_sz = NULL;
193
194 /** char **************************************************/
195 char *p;
196 char *q;
197
198 /** int ***************************************************/
199 int retval = 0;
200 int res = 0;
201 int i;
202 int lvmversion = 1;
203 long extents;
204 fpos_t orig_pos;
205
206 /** pointers **********************************************/
207 FILE *fin;
208
209 /** end *****************************************************/
210
211#ifdef __FreeBSD__
212 return (0);
213#endif
214
215 tmp = call_program_and_get_last_line_of_output("cat "CMDLINE,TRUE);
216 if (strstr(tmp, "nolvm")) {
217 mr_free(tmp);
218 return(0);
219 }
220 mr_free(tmp);
221
222 if (!(fin = fopen(MINDI_CACHE"/i-want-my-lvm", "r"))) {
223 log_OS_error(MINDI_CACHE"/i-want-my-lvm");
224 return (1);
225 }
226
227 command = malloc(1024);
228
229 log_it("STARTING");
230 log_msg(1, "OK, opened i-want-my-lvm. Shutting down LVM volumes...");
231 tmp1 = find_home_of_exe("lvm");
232 if (tmp1) // found it :) cool
233 {
234 mr_asprintf(lvscan_sz, "lvm lvscan");
235 mr_asprintf(lvremove_sz, "lvm lvremove");
236 mr_asprintf(vgscan_sz, "lvm vgscan");
237 mr_asprintf(pvscan_sz, "lvm pvscan");
238 mr_asprintf(vgchange_sz, "lvm vgchange");
239 mr_asprintf(vgremove_sz, "lvm vgremove -f");
240 } else {
241 mr_asprintf(lvscan_sz, "lvscan");
242 mr_asprintf(lvremove_sz, "lvremove");
243 mr_asprintf(vgscan_sz, "vgscan");
244 mr_asprintf(pvscan_sz, "pvscan");
245 mr_asprintf(vgchange_sz, "vgchange");
246 mr_asprintf(vgremove_sz, "vgremove");
247 }
248 mr_free(tmp1);
249
250 mr_asprintf(tmp1, "for i in `%s | cut -d\"'\" -f2 | sort -r` ; do echo \"Shutting down lv $i\" >> %s ; %s -f $i; done", lvscan_sz, MONDO_LOGFILE, lvremove_sz);
251 mr_free(lvscan_sz);
252 mr_free(lvremove_sz);
253
254 run_program_and_log_output(tmp1, 5);
255 mr_free(tmp1);
256
257 sleep(1);
258 sprintf(command, "for i in `%s | grep -i lvm | cut -d'\"' -f2` ; do %s -a n $i ; %s $i; echo \"Shutting down vg $i\" >> %s ; done", vgscan_sz, vgchange_sz, vgremove_sz, MONDO_LOGFILE);
259 mr_free(vgchange_sz);
260 mr_free(vgremove_sz);
261
262 run_program_and_log_output(command, 5);
263 if (just_erase_existing_volumes) {
264 paranoid_fclose(fin);
265 log_msg(1, "Closed i-want-my-lvm. Finished erasing LVMs.");
266 retval = 0;
267 } else {
268
269 log_msg(1, "OK, rewound i-want-my-lvm. Doing funky stuff...");
270 rewind(fin);
271 for (mr_getline(incoming, fin); !feof(fin); mr_getline(incoming, fin)) {
272 fgetpos(fin, &orig_pos);
273 if (incoming[0] != '#') {
274 mr_free(incoming);
275 continue;
276 }
277 if (res && strstr(command, "create") && vacuum_pack) {
278 sleep(2);
279 sync();
280 sync();
281 sync();
282 }
283 if ((p = strstr(incoming, "vgcreate"))) {
284 // include next line(s) if they end in /dev (cos we've got a broken i-want-my-lvm)
285 for (mr_getline(tmp, fin); !feof(fin); mr_getline(tmp, fin)) {
286 if (tmp[0] == '#') {
287 fsetpos(fin, &orig_pos);
288 break;
289 } else {
290 fgetpos(fin, &orig_pos);
291 mr_strcat(incoming, tmp);
292 }
293 mr_free(tmp);
294 }
295 mr_free(tmp);
296
297 for (q = incoming; *q != '\0'; q++) {
298 if (*q < 32) {
299 *q = ' ';
300 }
301 }
302 mr_asprintf(tmp, "%s", p + strlen("vgcreate") + 1);
303 for (q = tmp; *q > 32; q++);
304 *q = '\0';
305 log_msg(1, "Deleting old entries at /dev/%s", tmp);
306 mr_asprintf(tmp1, "rm -Rf /dev/%s", tmp);
307 mr_free(tmp);
308
309 run_program_and_log_output(tmp1, 1);
310 mr_free(tmp1);
311
312 run_program_and_log_output(vgscan_sz, 1);
313 run_program_and_log_output(pvscan_sz, 1);
314 log_msg(3, "After working around potentially broken i-want-my-lvm, incoming[] is now '%s'", incoming);
315 }
316 for (p = incoming + 1; *p == ' '; p++);
317 mr_free(incoming);
318
319 strcpy(command, p);
320 for (p = command; *p != '\0'; p++);
321 for (; *(p - 1) < 32; p--);
322 *p = '\0';
323 res = run_program_and_log_output(command, 5);
324 if (res > 0 && (p = strstr(command, "lvm "))) {
325 *p = *(p + 1) = *(p + 2) = ' ';
326 res = run_program_and_log_output(command, 5);
327 }
328 log_msg(0, "%s --> %d", command, res);
329 if (res > 0) {
330 res = 1;
331 }
332 if (res && strstr(command, "lvcreate") && vacuum_pack) {
333 res = 0;
334 if (strstr(command, "lvm lvcreate"))
335 lvmversion = 2;
336 if (lvmversion == 2) {
337 mr_asprintf(tmp1, "tail -n5 %s | grep Insufficient | tail -n1", MONDO_LOGFILE);
338 tmp = call_program_and_get_last_line_of_output(tmp1,TRUE);
339 mr_free(tmp1);
340 } else {
341 mr_asprintf(tmp1, "tail -n5 %s | grep lvcreate | tail -n1", MONDO_LOGFILE);
342 tmp = call_program_and_get_last_line_of_output(tmp1,TRUE);
343 mr_free(tmp1);
344 }
345 for (p = tmp; *p != '\0' && !isdigit(*p); p++);
346 extents = atol(p);
347 log_msg(5, "p='%s' --> extents=%ld", p, extents);
348 mr_free(tmp);
349
350 p = strstr(command, "-L");
351 if (!p) {
352 log_msg(0, "Fiddlesticks. '%s' returned %d", command, res);
353 } else {
354 if (lvmversion == 2) {
355 *p++ = '-';
356 *p++ = 'l';
357 *p++ = ' ';
358 for (q = p; *q != ' '; q++) {
359 *q = ' ';
360 }
361 sprintf(p, "%ld", extents);
362 i = strlen(p);
363 *(p + i) = ' ';
364 } else {
365 p++;
366 p++;
367 p++;
368 for (q = p; *q != ' '; q++) {
369 *(q - 1) = ' ';
370 }
371 sprintf(p, "%ld%c", extents, 'm');
372 i = strlen(p);
373 *(p + i) = ' ';
374 }
375 log_msg(5, "Retrying with '%s'", command);
376 res = run_program_and_log_output(command, 5);
377 if (res > 0) {
378 res = 1;
379 }
380 if (g_fprep) {
381 fprintf(g_fprep, "%s\n", command);
382 }
383 log_msg(0, "%s --> %d", command, res);
384 if (!res) {
385 log_msg(5, "YAY! This time, it succeeded.");
386 }
387 }
388 }
389 if (strstr(command, "vgcreate")) {
390 log_msg(0, "In case you're interested...");
391 run_program_and_log_output(vgscan_sz, 1);
392 run_program_and_log_output(pvscan_sz, 1);
393 }
394 if (res != 0 && !strstr(command, "insmod")) {
395 retval++;
396 }
397 mr_asprintf(tmp1, "echo \"%s\" >> /tmp/out.sh", command);
398 system(tmp1);
399 mr_free(tmp1);
400 sleep(1);
401 }
402 mr_free(incoming);
403 mr_free(vgscan_sz);
404 mr_free(pvscan_sz);
405
406 paranoid_fclose(fin);
407 log_msg(1, "Closed i-want-my-lvm. Finished doing funky stuff.");
408 }
409 paranoid_free(command);
410 sync();
411 sync();
412 sync();
413 sleep(1);
414 log_it("ENDING");
415 if (retval > 2) {
416 log_msg(1, "%d errors. I'm reporting this.", retval);
417 return (retval);
418 } else {
419 log_msg(1, "Not many errors. Returning 0.");
420 return (0);
421 }
422}
423
424
425/**
426 * Add RAID partitions while copying @p old_mountlist to @p new_mountlist.
427 * We go through @p old_mountlist and check if any RAID device (/dev/md? on Linux)
428 * is in it; if it is, then we put the disks contained within that RAID device
429 * into the mountlist as well.
430 * @param old_mountlist The mountlist to read.
431 * @param new_mountlist The mountlist to write, with the RAID partitions added.
432 * @return 0 for success, nonzero for failure.
433 */
434int extrapolate_mountlist_to_include_raid_partitions(struct mountlist_itself
435 *new_mountlist, struct mountlist_itself
436 *old_mountlist)
437{
438 /** pointers *********************************************************/
439 FILE *fin;
440
441 /** int **************************************************************/
442 int lino;
443 int j;
444
445 /** buffers **********************************************************/
446 char *incoming = NULL;
447
448 /** pointers *********************************************************/
449 char *p;
450
451 /** init *************************************************************/
452 new_mountlist->entries = 0;
453
454 /** end **************************************************************/
455
456 assert(new_mountlist != NULL);
457 assert(old_mountlist != NULL);
458
459#ifdef __FreeBSD__
460 log_to_screen("I don't know how to extrapolate the mountlist on FreeBSD. Sorry.");
461 return (1);
462#endif
463
464 for (lino = 0; lino < old_mountlist->entries; lino++) {
465 if (strstr(old_mountlist->el[lino].device, RAID_DEVICE_STUB)) // raid
466 {
467 if (!does_file_exist("/etc/raidtab")) {
468 log_to_screen("Cannot find /etc/raidtab - cannot extrapolate the fdisk entries");
469 finish(1);
470 }
471 if (!(fin = fopen("/etc/raidtab", "r"))) {
472 log_OS_error("Cannot open /etc/raidtab");
473 finish(1);
474 }
475 mr_getline(incoming, fin);
476 while (feof(fin) && !strstr(incoming, old_mountlist->el[lino].device)) {
477 mr_free(incoming);
478 mr_getline(incoming, fin);
479 }
480 mr_free(incoming);
481
482 if (!feof(fin)) {
483 log_it("Investigating %s", old_mountlist->el[lino].device);
484
485 for (mr_getline(incoming, fin); !feof(fin) && !strstr(incoming, "raiddev"); mr_getline(incoming, fin)) {
486 if (strstr(incoming, OSSWAP("device", "drive")) && !strchr(incoming, '#')) {
487 for (p = incoming + strlen(incoming); *(p - 1) <= 32; p--);
488 *p = '\0';
489 for (p--; p > incoming && *(p - 1) > 32; p--);
490
491 log_it("Extrapolating %s", p);
492
493 for (j = 0; j < new_mountlist->entries && strcmp(new_mountlist->el[j].device, p); j++);
494 if (j >= new_mountlist->entries) {
495 strcpy(new_mountlist->el[new_mountlist->entries].device, p);
496 strcpy(new_mountlist->el[new_mountlist->entries].mountpoint, "raid");
497 strcpy(new_mountlist->el[new_mountlist->entries].format, "raid");
498 new_mountlist->el[new_mountlist->entries].size = old_mountlist->el[lino].size;
499 new_mountlist->entries++;
500 } else {
501 log_it("Not adding %s to mountlist: it's already there", p);
502 }
503 mr_free(incoming);
504 }
505 }
506 mr_free(incoming);
507 }
508 paranoid_fclose(fin);
509 } else {
510 strcpy(new_mountlist->el[new_mountlist->entries].device,
511 old_mountlist->el[lino].device);
512 strcpy(new_mountlist->el[new_mountlist->entries].mountpoint,
513 old_mountlist->el[lino].mountpoint);
514 strcpy(new_mountlist->el[new_mountlist->entries].format,
515 old_mountlist->el[lino].format);
516 new_mountlist->el[new_mountlist->entries].size =
517 old_mountlist->el[lino].size;
518 new_mountlist->entries++;
519 }
520 }
521 paranoid_free(incoming);
522
523 return (0);
524}
525
526
527/**
528 * Create @p RAID device using information from @p structure.
529 * This will create the specified RAID devive using information provided in
530 * raidlist by means of the mdadm tool.
531 * @param raidlist The structure containing all RAID information
532 * @param device The RAID device to create.
533 * @return 0 for success, nonzero for failure.
534 */
535int create_raid_device_via_mdadm(struct raidlist_itself *raidlist, char *device)
536{
537 /** int **************************************************************/
538 int i = 0;
539 int j = 0;
540 int res = 0;
541
542 /** buffers ***********************************************************/
543 char *devices = NULL;
544 char *strtmp = NULL;
545 char *level = NULL;
546 char *program = NULL;
547
548 // leave straight away if raidlist is initial or has no entries
549 if (!raidlist || raidlist->entries == 0) {
550 log_msg(1, "No RAID arrays found.");
551 return 1;
552 } else {
553 log_msg(1, "%d RAID arrays found.", raidlist->entries);
554 }
555 // find raidlist entry for requested device
556 for (i = 0; i < raidlist->entries; i++) {
557 if (!strcmp(raidlist->el[i].raid_device, device)) break;
558 }
559 // check whether RAID device was found in raidlist
560 if (i == raidlist->entries) {
561 log_msg(1, "RAID device %s not found in list.", device);
562 return 1;
563 }
564 // create device list from normal disks followed by spare ones
565 mr_asprintf(devices, "%s", raidlist->el[i].data_disks.el[0].device);
566 for (j = 1; j < raidlist->el[i].data_disks.entries; j++) {
567 mr_asprintf(strtmp, "%s", devices);
568 mr_free(devices);
569 mr_asprintf(devices, "%s %s", strtmp, raidlist->el[i].data_disks.el[j].device);
570 mr_free(strtmp);
571 }
572 for (j = 0; j < raidlist->el[i].spare_disks.entries; j++) {
573 mr_asprintf(strtmp, "%s", devices);
574 mr_free(devices);
575 mr_asprintf(devices, "%s %s", strtmp, raidlist->el[i].spare_disks.el[j].device);
576 mr_free(strtmp);
577 }
578 // translate RAID level
579 if (raidlist->el[i].raid_level == -2) {
580 mr_asprintf(level, "multipath");
581 } else if (raidlist->el[i].raid_level == -1) {
582 mr_asprintf(level, "linear");
583 } else {
584 mr_asprintf(level, "raid%d", raidlist->el[i].raid_level);
585 }
586 // create RAID device:
587 // - RAID device, number of devices and devices mandatory
588 // - parity algorithm, chunk size and spare devices optional
589 // - faulty devices ignored
590 // - persistent superblock always used as this is recommended
591 mr_asprintf(program, "mdadm --create --force --run --auto=yes %s --level=%s --raid-devices=%d", raidlist->el[i].raid_device, level, raidlist->el[i].data_disks.entries);
592 if (raidlist->el[i].parity != -1) {
593 mr_asprintf(strtmp, "%s", program);
594 mr_free(program);
595 switch(raidlist->el[i].parity) {
596 case 0:
597 mr_asprintf(program, "%s --parity=%s", strtmp, "la");
598 break;
599 case 1:
600 mr_asprintf(program, "%s --parity=%s", strtmp, "ra");
601 break;
602 case 2:
603 mr_asprintf(program, "%s --parity=%s", strtmp, "ls");
604 break;
605 case 3:
606 mr_asprintf(program, "%s --parity=%s", strtmp, "rs");
607 break;
608 default:
609 fatal_error("Unknown RAID parity algorithm.");
610 break;
611 }
612 paranoid_free(strtmp);
613 }
614 if (raidlist->el[i].chunk_size != -1) {
615 mr_asprintf(strtmp, "%s", program);
616 mr_free(program);
617 mr_asprintf(program, "%s --chunk=%d", strtmp, raidlist->el[i].chunk_size);
618 mr_free(strtmp);
619 }
620 if (raidlist->el[i].spare_disks.entries > 0) {
621 mr_asprintf(strtmp, "%s", program);
622 mr_free(program);
623 mr_asprintf(program, "%s --spare-devices=%d", strtmp, raidlist->el[i].spare_disks.entries);
624 mr_free(strtmp);
625 }
626 mr_asprintf(strtmp, "%s", program);
627 mr_free(program);
628 mr_asprintf(program, "%s %s", strtmp, devices);
629 mr_free(strtmp);
630 res = run_program_and_log_output(program, 1);
631 mr_free(devices);
632 mr_free(level);
633 mr_free(program);
634 return res;
635}
636
637
638/**
639 * Format @p device as a @p format filesystem.
640 * This will use the format command returned by which_format_command_do_i_need().
641 * If @p device is an LVM PV, it will not be formatted, and LVM will be started
642 * (if not already done). If it's an imagedev, software RAID component, or
643 * (under BSD) swap partition, no format will be done.
644 * @param device The device to format.
645 * @param format The filesystem type to format it as.
646 * @return 0 for success, nonzero for failure.
647 */
648int format_device(char *device, char *format, struct raidlist_itself *raidlist)
649{
650 /** int **************************************************************/
651#ifdef __FreeBSD__
652 static bool vinum_started_yet = FALSE;
653 char *line = NULL;
654 char *status;
655#endif
656
657 /** buffers ***********************************************************/
658 char *program = NULL;
659 char *tmp = NULL;
660 int res = 0;
661 int retval = 0;
662
663 /** end ****************************************************************/
664
665 assert_string_is_neither_NULL_nor_zerolength(device);
666 assert(format != NULL);
667
668 if (strstr(format, "raid")) { // do not form RAID disks; do it to /dev/md* instead
669 log_it("Not formatting %s (it is a RAID disk)", device);
670 return (0);
671 }
672#ifdef __FreeBSD__
673 if (strcmp(format, "swap") == 0) {
674 log_it("Not formatting %s - it's swap", device);
675 return (0);
676 }
677#endif
678 if (strlen(format) <= 2) {
679 log_it("%s has a really small format type ('%s') - this is probably a hexadecimal string, which would suggest the partition is an image --- I shouldn't format it", device, format);
680 return (0);
681 }
682 if (is_this_device_mounted(device)) {
683 log_to_screen("%s is mounted - cannot format it ", device);
684 return (1);
685 }
686 if (strstr(device, RAID_DEVICE_STUB)) {
687 newtSuspend();
688#ifdef __FreeBSD__
689 if (!vinum_started_yet) {
690 if (!does_file_exist("/tmp/raidconf.txt")) {
691 log_to_screen("/tmp/raidconf.txt does not exist. I therefore cannot start Vinum.");
692 } else {
693 int res;
694 res =
695 run_program_and_log_output
696 ("vinum create /tmp/raidconf.txt", TRUE);
697 if (res) {
698 log_to_screen("`vinum create /tmp/raidconf.txt' returned errors. Please fix them and re-run mondorestore.");
699 finish(1);
700 }
701 vinum_started_yet = TRUE;
702 }
703 }
704
705 if (vinum_started_yet) {
706 FILE *fin;
707
708 log_to_screen("Initializing Vinum device %s (this may take a *long* time)", device);
709
710 /* format raid partition */
711 mr_asprintf(program, "for plex in `vinum lv -r %s | grep '^P' | tr '\t' ' ' | tr -s ' ' | cut -d' ' -f2`; do echo $plex; done > /tmp/plexes", basename(device));
712 system(program);
713 if (g_fprep) {
714 fprintf(g_fprep, "%s\n", program);
715 }
716 mr_free(program);
717
718 fin = fopen("/tmp/plexes", "r");
719 /* BERLIOS: doesn't work */
720 while (mr_getline(line, fin)) {
721 if (strchr(line, '\n'))
722 *(strchr(line, '\n')) = '\0'; // get rid of the \n on the end
723
724 mr_asprintf(tmp, "Initializing plex: %s", line);
725 open_evalcall_form(tmp);
726 mr_free(tmp);
727
728 mr_asprintf(tmp, "vinum init %s", line);
729 system(tmp);
730 mr_free(tmp);
731
732 while (1) {
733 mr_asprintf(tmp, "vinum lp -r %s | grep '^S' | head -1 | tr -s ' ' | cut -d: -f2 | cut -f1 | sed 's/^ //' | sed 's/I //' | sed 's/%%//'", line);
734 FILE *pin = popen(tmp, "r");
735 mr_free(tmp);
736
737 mr_getline(status, pin);
738 pclose(pin);
739
740 if (!strcmp(status, "up")) {
741 mr_free(status);
742 break; /* it's done */
743 }
744 update_evalcall_form(atoi(status));
745 usleep(250000);
746 mr_free(status);
747 }
748 close_evalcall_form();
749 mr_free(line);
750 }
751 mr_free(line);
752 fclose(fin);
753 unlink("/tmp/plexes");
754 }
755#else
756 log_to_screen("Initializing RAID device %s", device);
757
758// Shouldn't be necessary.
759 log_to_screen("Stopping %s", device);
760 stop_raid_device(device);
761 sync();
762 sleep(1);
763
764 log_msg(1, "Making %s", device);
765 // use mkraid if it exists, otherwise use mdadm
766 if (run_program_and_log_output("which mkraid", FALSE)) {
767 res = create_raid_device_via_mdadm(raidlist, device);
768 log_msg(1, "Creating RAID device %s via mdadm returned %d", device, res);
769 } else {
770 mr_asprintf(program, "mkraid --really-force %s", device);
771 res = run_program_and_log_output(program, 1);
772 log_msg(1, "%s returned %d", program, res);
773 sync();
774 sleep(3);
775 start_raid_device(device);
776 if (g_fprep) {
777 fprintf(g_fprep, "%s\n", program);
778 }
779 mr_free(program);
780 }
781 sync();
782 sleep(2);
783#endif
784 sync();
785 sleep(1);
786 newtResume();
787 }
788
789 if (!strcmp(format, "lvm")) {
790 log_msg(1, "Don't format %s - it's part of an lvm volume", device);
791 return (0);
792 }
793 program = which_format_command_do_i_need(format);
794 mr_asprintf(tmp, "%s %s", program, device);
795 if (strstr(program, "kludge")) {
796 mr_strcat(tmp, " /");
797 }
798 mr_free(program);
799
800 mr_asprintf(program, "sh -c 'echo -en \"y\\ny\\ny\\n\" | %s'", tmp);
801 mr_free(tmp);
802
803 mr_asprintf(tmp, "Formatting %s as %s", device, format);
804 update_progress_form(tmp);
805
806 res = run_program_and_log_output(program, FALSE);
807 if (res) {
808 mr_strcat(tmp, "...failed");
809 } else {
810 mr_strcat(tmp, "...OK");
811 }
812 log_to_screen(tmp);
813 mr_free(tmp);
814
815 if (res && strstr(program, "kludge")) {
816 mr_asprintf(tmp, "Kludge failed; using regular mkfs.%s to format %s", format, device);
817 mr_free(program);
818#ifdef __FreeBSD__
819 mr_asprintf(program, "newfs_msdos -F 32 %s", device);
820#else
821#ifdef __IA64__
822 /* For EFI partitions take fat16
823 * as we want to make small ones */
824 mr_asprintf(program, "mkfs -t %s -F 16 %s", format, device);
825#else
826 mr_asprintf(program, "mkfs -t %s -F 32 %s", format, device);
827#endif
828#endif
829 res = run_program_and_log_output(program, FALSE);
830 if (g_fprep) {
831 fprintf(g_fprep, "%s\n", program);
832 }
833 if (retval) {
834 mr_strcat(tmp, "...failed");
835 } else {
836 mr_strcat(tmp, "...OK");
837 }
838
839 log_to_screen(tmp);
840 mr_free(tmp);
841
842 }
843 mr_free(program);
844 retval += res;
845 sync();
846 sleep(1);
847 return (retval);
848}
849
850
851
852
853
854/**
855 * Format all drives (except those excluded by format_device()) in @p mountlist.
856 * @param mountlist The mountlist containing partitions to be formatted.
857 * @param interactively If TRUE, then prompt the user before each partition.
858 * @return The number of errors encountered (0 for success).
859 */
860int format_everything(struct mountlist_itself *mountlist, bool interactively,
861 struct raidlist_itself *raidlist)
862{
863 /** int **************************************************************/
864 int retval = 0;
865 int lino;
866 int res;
867
868 /** long *************************************************************/
869 long progress_step;
870
871 /** bools ************************************************************/
872 bool do_it;
873
874 /** buffers **********************************************************/
875 char *tmp = NULL;
876
877 /** pointers *********************************************************/
878 struct mountlist_line *me; // mountlist entry
879 /** end **************************************************************/
880
881 assert(mountlist != NULL);
882 log_it("format_everything (mountlist, interactively = %s", (interactively) ? "true" : "false");
883
884 mvaddstr_and_log_it(g_currentY, 0, "Formatting partitions ");
885 open_progress_form("Formatting partitions",
886 "I am now formatting your hard disk partitions.",
887 "This may take up to five minutes.", "",
888 mountlist->entries + 1);
889
890 progress_step =
891 (mountlist->entries >
892 0) ? g_maximum_progress / mountlist->entries : 1;
893 // start soft-raids now (because LVM might depend on them)
894 // ...and for simplicity's sake, let's format them at the same time :)
895 log_msg(1, "Stopping all RAID devices");
896 stop_all_raid_devices(mountlist);
897 sync();
898 sync();
899 sync();
900 sleep(2);
901 log_msg(1, "Prepare soft-RAIDs"); // prep and format too
902 for (lino = 0; lino < mountlist->entries; lino++) {
903 me = &mountlist->el[lino]; // the current mountlist entry
904 log_msg(2, "Examining %s", me->device);
905 if (!strncmp(me->device, "/dev/md", 7)) {
906 if (interactively) {
907 // ask user if we should format the current device
908 mr_asprintf(tmp, "Shall I format %s (%s) ?", me->device, me->mountpoint);
909 do_it = ask_me_yes_or_no(tmp);
910 mr_free(tmp);
911 } else {
912 do_it = TRUE;
913 }
914 if (do_it) {
915 // NB: format_device() also stops/starts RAID device if necessary
916 retval += format_device(me->device, me->format, raidlist);
917 }
918 g_current_progress += progress_step;
919 }
920 }
921 sync();
922 sync();
923 sync();
924 sleep(2);
925// This last step is probably necessary
926// log_to_screen("Re-starting software RAIDs...");
927// start_all_raid_devices(mountlist);
928// system("sync"); system("sync"); system("sync");
929// sleep(5);
930// do LVMs now
931 log_msg(1, "Creating LVMs");
932 if (does_file_exist(MINDI_CACHE"/i-want-my-lvm")) {
933 wait_until_software_raids_are_prepped("/proc/mdstat", 100);
934 log_to_screen("Configuring LVM");
935 if (!g_text_mode) {
936 newtSuspend();
937 }
938 res = do_my_funky_lvm_stuff(FALSE, TRUE);
939 if (!g_text_mode) {
940 newtResume();
941 }
942 if (!res) {
943 log_to_screen("LVM initialized OK");
944 } else {
945 log_to_screen("Failed to initialize LVM");
946 }
947 if (res) {
948 retval++;
949 }
950 sleep(3);
951 }
952 // do regulars at last
953 sleep(2); // woo!
954 log_msg(1, "Formatting regulars");
955 for (lino = 0; lino < mountlist->entries; lino++) {
956 me = &mountlist->el[lino]; // the current mountlist entry
957 if (!strcmp(me->mountpoint, "image")) {
958 log_it("Not formatting %s - it's an image", me->device);
959 } else if (!strcmp(me->format, "raid")) {
960 log_it("Not formatting %s - it's a raid-let", me->device);
961 continue;
962 } else if (!strcmp(me->format, "lvm")) {
963 log_it("Not formatting %s - it's an LVM", me->device);
964 continue;
965 } else if (!strncmp(me->device, "/dev/md", 7)) {
966 log_it("Already formatted %s - it's a soft-RAID dev", me->device);
967 continue;
968 } else if (!does_file_exist(me->device)
969 && strncmp(me->device, "/dev/hd", 7)
970 && strncmp(me->device, "/dev/sd", 7)) {
971 log_it("Not formatting %s yet - doesn't exist - probably an LVM", me->device);
972 continue;
973 } else {
974 if (interactively) {
975 // ask user if we should format the current device
976 mr_asprintf(tmp, "Shall I format %s (%s) ?", me->device, me->mountpoint);
977 do_it = ask_me_yes_or_no(tmp);
978 mr_free(tmp);
979 } else {
980 do_it = TRUE;
981 }
982
983 if (do_it)
984 retval += format_device(me->device, me->format, raidlist);
985 }
986
987 // update progress bar
988 g_current_progress += progress_step;
989 }
990
991
992 // update progress bar to 100% to compensate for
993 // rounding errors of the progress_step calculation
994 if (lino >= mountlist->entries)
995 g_current_progress = g_maximum_progress;
996
997 close_progress_form();
998
999 if (retval) {
1000 mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1001 log_to_screen("Errors occurred during the formatting of your hard drives.");
1002 } else {
1003 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1004 }
1005
1006 log_it("format_everything () - %s", (retval) ? "failed!" : "finished successfully");
1007
1008 if (g_partition_table_locked_up > 0) {
1009 if (retval > 0 && !interactively) {
1010//123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
1011 log_to_screen("Partition table locked up %d times. At least one 'mkfs' (format) command", g_partition_table_locked_up);
1012 log_to_screen("failed. I think these two events are related. Sometimes, fdisk's ioctl() call");
1013 log_to_screen("to refresh its copy of the partition table causes the kernel to lock the ");
1014 log_to_screen("partition table. I believe this has just happened.");
1015 if (ask_me_yes_or_no("Please choose 'yes' to reboot and try again; or 'no' to ignore this warning and continue.")) {
1016 sync();
1017 sync();
1018 sync();
1019 system("reboot");
1020 }
1021 } else {
1022 log_to_screen("Partition table locked up %d time%c. However, disk formatting succeeded.", g_partition_table_locked_up, (g_partition_table_locked_up == 1) ? '.' : 's');
1023 }
1024 }
1025 newtSuspend();
1026 system("clear");
1027 newtResume();
1028 return (retval);
1029}
1030
1031
1032/**
1033 * Create small dummy partitions to fill in the gaps in partition numbering for @p drivename.
1034 * Each partition created is 32k in size.
1035 * @param drivename The drive to create the dummy partitions on.
1036 * @param devno_we_must_allow_for The lowest-numbered real partition; create
1037 * dummies up to (this - 1).
1038 * @return The number of errors encountered (0 for success).
1039 */
1040int make_dummy_partitions(FILE * pout_to_fdisk, char *drivename,
1041 int devno_we_must_allow_for)
1042{
1043 /** int **************************************************************/
1044 int current_devno;
1045 int previous_devno;
1046 int retval = 0;
1047 int res;
1048
1049 /** end **************************************************************/
1050
1051 assert_string_is_neither_NULL_nor_zerolength(drivename);
1052
1053 if (devno_we_must_allow_for >= 5) {
1054 log_it("Making dummy primary 1 on %s", drivename);
1055
1056 g_maximum_progress++;
1057 res =
1058 partition_device(pout_to_fdisk, drivename, 1, 0, "ext2",
1059 32000);
1060 retval += res;
1061 previous_devno = 1;
1062 current_devno = 5;
1063 } else {
1064 previous_devno = 0;
1065 current_devno = 1;
1066 }
1067 for (; current_devno < devno_we_must_allow_for; current_devno++) {
1068 log_it("Creating dummy partition %d on %s", current_devno, drivename);
1069 g_maximum_progress++;
1070 res =
1071 partition_device(pout_to_fdisk, drivename, current_devno,
1072 previous_devno, OSSWAP("ext2", "ufs"), 32000);
1073 retval += res;
1074 previous_devno = current_devno;
1075 }
1076 return (previous_devno);
1077}
1078
1079
1080/**
1081 * Decide whether @p mountlist contains any RAID devices.
1082 * @param mountlist The mountlist to examine.
1083 * @return TRUE if it does, FALSE if it doesn't.
1084 */
1085bool mountlist_contains_raid_devices(struct mountlist_itself * mountlist)
1086{
1087 /** int *************************************************************/
1088 int i;
1089 int matching = 0;
1090
1091 /** end **************************************************************/
1092
1093 assert(mountlist != NULL);
1094
1095 for (i = 0; i < mountlist->entries; i++) {
1096 if (strstr(mountlist->el[i].device, RAID_DEVICE_STUB)) {
1097 matching++;
1098 }
1099 }
1100 if (matching) {
1101 return (TRUE);
1102 } else {
1103 return (FALSE);
1104 }
1105}
1106
1107/* The following 2 functions are stolen from /usr/src/sbin/disklabel/disklabel.c */
1108#ifdef __FreeBSD__
1109static void display_disklabel(FILE * f, const struct disklabel *lp)
1110{
1111 int i, j;
1112 const struct partition *pp;
1113
1114 fprintf(f, "# %s\n", "Generated by Mondo Rescue");
1115 if (lp->d_type < DKMAXTYPES)
1116 fprintf(f, "type: %s\n", dktypenames[lp->d_type]);
1117 else
1118 fprintf(f, "type: %u\n", lp->d_type);
1119 fprintf(f, "disk: %.*s\n", (int) sizeof(lp->d_typename),
1120 lp->d_typename);
1121 fprintf(f, "label: %.*s\n", (int) sizeof(lp->d_packname),
1122 lp->d_packname);
1123 fprintf(f, "flags:");
1124 if (lp->d_flags & D_REMOVABLE)
1125 fprintf(f, " removeable");
1126 if (lp->d_flags & D_ECC)
1127 fprintf(f, " ecc");
1128 if (lp->d_flags & D_BADSECT)
1129 fprintf(f, " badsect");
1130 fprintf(f, "\n");
1131 fprintf(f, "bytes/sector: %lu\n", (u_long) lp->d_secsize);
1132 fprintf(f, "sectors/track: %lu\n", (u_long) lp->d_nsectors);
1133 fprintf(f, "tracks/cylinder: %lu\n", (u_long) lp->d_ntracks);
1134 fprintf(f, "sectors/cylinder: %lu\n", (u_long) lp->d_secpercyl);
1135 fprintf(f, "cylinders: %lu\n", (u_long) lp->d_ncylinders);
1136 fprintf(f, "sectors/unit: %lu\n", (u_long) lp->d_secperunit);
1137 fprintf(f, "rpm: %u\n", lp->d_rpm);
1138 fprintf(f, "interleave: %u\n", lp->d_interleave);
1139 fprintf(f, "trackskew: %u\n", lp->d_trackskew);
1140 fprintf(f, "cylinderskew: %u\n", lp->d_cylskew);
1141 fprintf(f, "headswitch: %lu\t\t# milliseconds\n",
1142 (u_long) lp->d_headswitch);
1143 fprintf(f, "track-to-track seek: %ld\t# milliseconds\n",
1144 (u_long) lp->d_trkseek);
1145 fprintf(f, "drivedata: ");
1146 for (i = NDDATA - 1; i >= 0; i--)
1147 if (lp->d_drivedata[i])
1148 break;
1149 if (i < 0)
1150 i = 0;
1151 for (j = 0; j <= i; j++)
1152 fprintf(f, "%lu ", (u_long) lp->d_drivedata[j]);
1153 fprintf(f, "\n\n%u partitions:\n", lp->d_npartitions);
1154 fprintf(f,
1155 "# size offset fstype [fsize bsize bps/cpg]\n");
1156 pp = lp->d_partitions;
1157 for (i = 0; i < lp->d_npartitions; i++, pp++) {
1158 if (pp->p_size) {
1159 fprintf(f, " %c: %8lu %8lu ", 'a' + i, (u_long) pp->p_size,
1160 (u_long) pp->p_offset);
1161 if (pp->p_fstype < FSMAXTYPES)
1162 fprintf(f, "%8.8s", fstypenames[pp->p_fstype]);
1163 else
1164 fprintf(f, "%8d", pp->p_fstype);
1165 switch (pp->p_fstype) {
1166
1167 case FS_UNUSED: /* XXX */
1168 fprintf(f, " %5lu %5lu %5.5s ", (u_long) pp->p_fsize,
1169 (u_long) (pp->p_fsize * pp->p_frag), "");
1170 break;
1171
1172 case FS_BSDFFS:
1173 fprintf(f, " %5lu %5lu %5u ", (u_long) pp->p_fsize,
1174 (u_long) (pp->p_fsize * pp->p_frag), pp->p_cpg);
1175 break;
1176
1177 case FS_BSDLFS:
1178 fprintf(f, " %5lu %5lu %5d", (u_long) pp->p_fsize,
1179 (u_long) (pp->p_fsize * pp->p_frag), pp->p_cpg);
1180 break;
1181
1182 default:
1183 fprintf(f, "%20.20s", "");
1184 break;
1185 }
1186 fprintf(f, "\t# (Cyl. %4lu",
1187 (u_long) (pp->p_offset / lp->d_secpercyl));
1188 if (pp->p_offset % lp->d_secpercyl)
1189 putc('*', f);
1190 else
1191 putc(' ', f);
1192 fprintf(f, "- %lu",
1193 (u_long) ((pp->p_offset + pp->p_size +
1194 lp->d_secpercyl - 1) / lp->d_secpercyl -
1195 1));
1196 if (pp->p_size % lp->d_secpercyl)
1197 putc('*', f);
1198 fprintf(f, ")\n");
1199 }
1200 }
1201 fflush(f);
1202}
1203
1204static struct disklabel *get_virgin_disklabel(char *dkname)
1205{
1206 static struct disklabel loclab;
1207 struct partition *dp;
1208 char lnamebuf[BBSIZE];
1209 int f;
1210 u_int secsize, u;
1211 off_t mediasize;
1212
1213 (void) snprintf(lnamebuf, BBSIZE, "%s", dkname);
1214 if ((f = open(lnamebuf, O_RDONLY)) == -1) {
1215 warn("cannot open %s", lnamebuf);
1216 return (NULL);
1217 }
1218
1219 /* New world order */
1220 if ((ioctl(f, DIOCGMEDIASIZE, &mediasize) != 0)
1221 || (ioctl(f, DIOCGSECTORSIZE, &secsize) != 0)) {
1222 close(f);
1223 return (NULL);
1224 }
1225 memset(&loclab, 0, sizeof loclab);
1226 loclab.d_magic = DISKMAGIC;
1227 loclab.d_magic2 = DISKMAGIC;
1228 loclab.d_secsize = secsize;
1229 loclab.d_secperunit = mediasize / secsize;
1230
1231 /*
1232 * Nobody in these enligthened days uses the CHS geometry for
1233 * anything, but nontheless try to get it right. If we fail
1234 * to get any good ideas from the device, construct something
1235 * which is IBM-PC friendly.
1236 */
1237 if (ioctl(f, DIOCGFWSECTORS, &u) == 0)
1238 loclab.d_nsectors = u;
1239 else
1240 loclab.d_nsectors = 63;
1241 if (ioctl(f, DIOCGFWHEADS, &u) == 0)
1242 loclab.d_ntracks = u;
1243 else if (loclab.d_secperunit <= 63 * 1 * 1024)
1244 loclab.d_ntracks = 1;
1245 else if (loclab.d_secperunit <= 63 * 16 * 1024)
1246 loclab.d_ntracks = 16;
1247 else
1248 loclab.d_ntracks = 255;
1249 loclab.d_secpercyl = loclab.d_ntracks * loclab.d_nsectors;
1250 loclab.d_ncylinders = loclab.d_secperunit / loclab.d_secpercyl;
1251 loclab.d_npartitions = MAXPARTITIONS;
1252
1253 /* Various (unneeded) compat stuff */
1254 loclab.d_rpm = 3600;
1255 loclab.d_bbsize = BBSIZE;
1256 loclab.d_interleave = 1;;
1257 strncpy(loclab.d_typename, "amnesiac", sizeof(loclab.d_typename));
1258
1259 dp = &loclab.d_partitions[RAW_PART];
1260 dp->p_size = loclab.d_secperunit;
1261 loclab.d_checksum = dkcksum(&loclab);
1262 close(f);
1263 return (&loclab);
1264}
1265
1266/* End stolen from /usr/src/sbin/disklabel/disklabel.c. */
1267
1268char *canonical_name(char *drivename)
1269{
1270 if (drivename) {
1271 if (strncmp(drivename, "/dev/", 5) == 0) {
1272 return drivename + 5;
1273 }
1274 }
1275 return drivename;
1276}
1277
1278/**
1279 * (BSD only) Create a disklabel on @p drivename according to @p mountlist.
1280 * @param mountlist The mountlist to get the subpartition information from.
1281 * @param drivename The drive or slice to create a disklabel on.
1282 * @param ret If non-NULL, store the created disklabel here.
1283 * @return The number of errors encountered (0 for success).
1284 */
1285int label_drive_or_slice(struct mountlist_itself *mountlist,
1286 char *drivename, struct disklabel *ret)
1287{
1288 char *subdev_str = NULL
1289 char *command = NULL;
1290 struct disklabel *lp;
1291 int i, lo = 0;
1292 int retval = 0;
1293 char c;
1294 FILE *ftmp;
1295
1296 lp = get_virgin_disklabel(drivename);
1297 for (c = 'a'; c <= 'z'; ++c) {
1298 int idx;
1299 mr_asprintf(subdev_str, "%s%c", drivename, c);
1300 if ((idx = find_device_in_mountlist(mountlist, subdev_str)) < 0) {
1301 lp->d_partitions[c - 'a'].p_size = 0;
1302 lp->d_partitions[c - 'a'].p_fstype = FS_UNUSED;
1303 } else {
1304 lo = c - 'a';
1305 lp->d_partitions[c - 'a'].p_size = mountlist->el[idx].size * 2;
1306 lp->d_partitions[c - 'a'].p_fsize = 0;
1307 lp->d_partitions[c - 'a'].p_frag = 0;
1308 lp->d_partitions[c - 'a'].p_cpg = 0;
1309 if (!strcmp(mountlist->el[idx].format, "ufs")
1310 || !strcmp(mountlist->el[idx].format, "ffs")
1311 || !strcmp(mountlist->el[idx].format, "4.2BSD")) {
1312 lp->d_partitions[c - 'a'].p_fstype = FS_BSDFFS;
1313 lp->d_partitions[c - 'a'].p_fsize = 2048;
1314 lp->d_partitions[c - 'a'].p_frag = 8;
1315 lp->d_partitions[c - 'a'].p_cpg = 64;
1316 } else if (!strcasecmp(mountlist->el[idx].format, "raid")
1317 || !strcasecmp(mountlist->el[idx].format, "vinum")) {
1318 lp->d_partitions[c - 'a'].p_fstype = FS_VINUM;
1319 } else if (!strcmp(mountlist->el[idx].format, "swap")) {
1320 lp->d_partitions[c - 'a'].p_fstype = FS_SWAP;
1321 } else
1322 lp->d_partitions[c - 'a'].p_fstype = FS_OTHER;
1323 }
1324 mr_free(subdev_str);
1325 }
1326
1327 // fix up the offsets
1328 lp->d_partitions[0].p_offset = 0;
1329 lp->d_partitions[RAW_PART].p_offset = 0;
1330 lp->d_partitions[RAW_PART].p_size = lp->d_secperunit;
1331 lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED;
1332
1333 for (i = 1; i < lp->d_npartitions; ++i) {
1334 int lastone;
1335 if ((i == RAW_PART) || (lp->d_partitions[i].p_size == 0))
1336 continue;
1337 for (lastone = i - 1; lastone >= 0; lastone--) {
1338 if ((lp->d_partitions[lastone].p_size)
1339 && (lastone != RAW_PART))
1340 break;
1341 }
1342 lp->d_partitions[i].p_offset =
1343 lp->d_partitions[lastone].p_offset +
1344 lp->d_partitions[lastone].p_size;
1345 }
1346 if (lp->d_partitions[lo].p_offset + lp->d_partitions[lo].p_size >
1347 lp->d_secperunit) {
1348 lp->d_partitions[lo].p_size =
1349 lp->d_secperunit - lp->d_partitions[lo].p_offset;
1350 }
1351
1352 ftmp = fopen("/tmp/disklabel", "w");
1353 display_disklabel(ftmp, lp);
1354 fclose(ftmp);
1355 mr_asprintf(command, "disklabel -wr %s auto", canonical_name(drivename));
1356 retval += run_program_and_log_output(command, TRUE);
1357 mr_free(command);
1358
1359 mr_asprintf(command, "disklabel -R %s /tmp/disklabel", canonical_name(drivename));
1360 retval += run_program_and_log_output(command, TRUE);
1361 mr_free(command);
1362 if (ret)
1363 *ret = *lp;
1364 return retval;
1365}
1366#endif
1367
1368
1369/**
1370 * Partition @p drivename based on @p mountlist.
1371 * @param mountlist The mountlist to use to guide the partitioning.
1372 * @param drivename The drive to partition.
1373 * @return 0 for success, nonzero for failure.
1374 */
1375int partition_drive(struct mountlist_itself *mountlist, char *drivename)
1376{
1377 /** int *************************************************************/
1378 int current_devno;
1379 int previous_devno = 0;
1380 int lino;
1381 int retval = 0;
1382 int i;
1383 FILE *pout_to_fdisk = NULL;
1384
1385#ifdef __FreeBSD__
1386 bool fbsd_part = FALSE;
1387 char *subdev_str = NULL;
1388 char *command = NULL;
1389 int r = 0;
1390#endif
1391
1392 /** long long *******************************************************/
1393 long long partsize;
1394
1395 /** buffers *********************************************************/
1396 char *device_str = NULL;
1397 char *format = NULL;
1398 char *tmp = NULL;
1399 char *tmp1 = NULL;
1400
1401 /** end *************************************************************/
1402
1403 assert(mountlist != NULL);
1404 assert_string_is_neither_NULL_nor_zerolength(drivename);
1405
1406 log_it("Partitioning drive %s", drivename);
1407
1408#if __FreeBSD__
1409 log_it("(Not opening fdisk now; that's the Linux guy's job)");
1410 pout_to_fdisk = NULL;
1411#else
1412 make_hole_for_file(FDISK_LOG);
1413 mr_asprintf(tmp, "parted2fdisk %s >> %s 2>> %s", drivename, FDISK_LOG, FDISK_LOG);
1414 pout_to_fdisk = popen(tmp, "w");
1415 mr_free(tmp);
1416 if (!pout_to_fdisk) {
1417 log_to_screen("Cannot call parted2fdisk to configure %s", drivename);
1418 return (1);
1419 }
1420#endif
1421 for (current_devno = 1; current_devno < 99; current_devno++) {
1422 device_str = build_partition_name(drivename, current_devno);
1423 lino = find_device_in_mountlist(mountlist, device_str);
1424
1425 if (lino < 0) {
1426 // device not found in mountlist
1427#if __FreeBSD__
1428 // If this is the first partition (just as a sentinel value),
1429 // then see if the user has picked 'dangerously-dedicated' mode.
1430 // If so, then we just call label_drive_or_slice() and return.
1431 char c;
1432 if (current_devno == 1) {
1433 // try DangerouslyDedicated mode
1434 for (c = 'a'; c <= 'z'; c++) {
1435 mr_asprintf(subdev_str, "%s%c", drivename, c);
1436 if (find_device_in_mountlist(mountlist, subdev_str) > 0) {
1437 fbsd_part = TRUE;
1438 }
1439 mr_free(subdev_str);
1440 }
1441 if (fbsd_part) {
1442 r = label_drive_or_slice(mountlist,
1443 drivename,
1444 0);
1445 mr_asprintf(command, "disklabel -B %s", basename(drivename));
1446 if (system(command)) {
1447 log_to_screen("Warning! Unable to make the drive bootable.");
1448 }
1449 mr_free(command);
1450 mr_free(device_str);
1451 return r;
1452 }
1453 }
1454 for (c = 'a'; c <= 'z'; c++) {
1455 mr_asprintf(subdev_str, "%s%c", device_str, c);
1456 if (find_device_in_mountlist(mountlist, subdev_str) > 0) {
1457 fbsd_part = TRUE;
1458 }
1459 mr_free(subdev_str);
1460 }
1461 // Now we check the subpartitions of the current partition.
1462 if (fbsd_part) {
1463 int i, line;
1464
1465 mr_asprintf(format, "ufs");
1466 partsize = 0;
1467 for (i = 'a'; i < 'z'; ++i) {
1468 mr_asprintf(subdev_str, "%s%c", device_str, i);
1469 line = find_device_in_mountlist(mountlist, subdev_str);
1470 mr_free(subdev_str);
1471
1472 if (line > 0) {
1473 // We found one! Add its size to the total size.
1474 partsize += mountlist->el[line].size;
1475 }
1476 }
1477 } else {
1478 mr_free(device_str);
1479 continue;
1480 }
1481#else
1482 mr_free(device_str);
1483 continue;
1484#endif
1485 }
1486
1487 /* OK, we've found partition /dev/hdxN in mountlist; let's prep it */
1488 /* For FreeBSD, that is /dev/adXsY */
1489
1490 log_it("Found partition %s in mountlist", device_str);
1491 if (!previous_devno) {
1492
1493 log_it("Wiping %s's partition table", drivename);
1494#if __FreeBSD__
1495 // FreeBSD doesn't let you write to blk devices in <512byte chunks.
1496 file = open(drivename, O_WRONLY);
1497 if (file != -1) {
1498 log_to_screen("Warning - unable to open %s for wiping it's partition table", drivename);
1499 }
1500
1501 for (i = 0; i < 512; i++) {
1502 if (!write(file, "\0", 1)) {
1503 log_to_screen("Warning - unable to write to %s", drivename);
1504 }
1505 }
1506 sync();
1507#else
1508 log_it("New, kernel-friendly partition remover");
1509 for (i = 20; i > 0; i--) {
1510 fprintf(pout_to_fdisk, "d\n%d\n", i);
1511 fflush(pout_to_fdisk);
1512 }
1513#endif
1514 if (current_devno > 1) {
1515 previous_devno =
1516 make_dummy_partitions(pout_to_fdisk, drivename,
1517 current_devno);
1518 }
1519 }
1520#ifdef __FreeBSD__
1521 if (!fbsd_part) {
1522 mr_free(format);
1523#endif
1524
1525 mr_asprintf(format, "%s", mountlist->el[lino].format);
1526 partsize = mountlist->el[lino].size;
1527
1528#ifdef __FreeBSD__
1529 }
1530#endif
1531
1532#ifndef __IA64__
1533 if (current_devno == 5 && previous_devno == 4) {
1534 log_to_screen("You must leave at least one partition spare as the Extended partition.");
1535 mr_free(device_str);
1536 mr_free(format);
1537 return (1);
1538 }
1539#endif
1540
1541 retval += partition_device(pout_to_fdisk, drivename, current_devno, previous_devno, format, partsize);
1542 mr_free(format);
1543
1544#ifdef __FreeBSD__
1545 if ((current_devno <= 4) && fbsd_part) {
1546 mr_asprintf(tmp, "disklabel -B %s", basename(device_str));
1547 retval += label_drive_or_slice(mountlist, device_str, 0);
1548 if (system(tmp)) {
1549 log_to_screen("Warning! Unable to make the slice bootable.");
1550 }
1551 mr_free(tmp);
1552 }
1553#endif
1554 mr_free(device_str);
1555
1556 previous_devno = current_devno;
1557 }
1558
1559 if (pout_to_fdisk) {
1560 // mark relevant partition as bootable
1561 tmp1 = call_program_and_get_last_line_of_output ("make-me-bootable "MINDI_CACHE"/mountlist.txt dummy",TRUE);
1562 mr_asprintf(tmp, "a\n%s\n", tmp1);
1563 mr_free(tmp1);
1564
1565 fput_string_one_char_at_a_time(pout_to_fdisk, tmp);
1566 mr_free(tmp);
1567
1568 // close fdisk
1569 fput_string_one_char_at_a_time(pout_to_fdisk, "w\n");
1570 sync();
1571 paranoid_pclose(pout_to_fdisk);
1572 log_msg(0,
1573 "------------------- fdisk.log looks like this ------------------");
1574 mr_asprintf(tmp, "cat %s >> %s", FDISK_LOG, MONDO_LOGFILE);
1575 system(tmp);
1576 mr_free(tmp);
1577
1578 log_msg(0,
1579 "------------------- end of fdisk.log... word! ------------------");
1580 mr_asprintf(tmp, "tail -n6 %s | grep -F \"16: \"", FDISK_LOG);
1581 if (!run_program_and_log_output(tmp, 5)) {
1582 g_partition_table_locked_up++;
1583 }
1584 mr_free(tmp);
1585
1586 mr_asprintf(tmp, "partprobe %s", drivename);
1587 if (!run_program_and_log_output(tmp, 5)) {
1588 g_partition_table_locked_up--;
1589 }
1590 mr_free(tmp);
1591
1592 if (g_partition_table_locked_up > 0) {
1593 log_to_screen("A flaw in the Linux kernel has locked the partition table. Even calling partprobe did not suceed :-(");
1594 }
1595 }
1596 return (retval);
1597}
1598
1599/**
1600 * Create partition number @p partno on @p drive with @p fdisk.
1601 * @param drive The drive to create the partition on.
1602// * @param partno The partition number of the new partition (1-4 are primary, >=5 is logical).
1603 * @param prev_partno The partition number of the most recently prepped partition.
1604 * @param format The filesystem type of this partition (used to set the type).
1605 * @param partsize The size of the partition in @e bytes.
1606 * @return 0 for success, nonzero for failure.
1607 */
1608int partition_device(FILE * pout_to_fdisk, const char *drive, int partno,
1609 int prev_partno, const char *format,
1610 long long partsize)
1611{
1612 /** int **************************************************************/
1613 int retval = 0;
1614 int res = 0;
1615
1616 /** buffers **********************************************************/
1617 char *program = NULL;
1618 char *partition_name = NULL;
1619 char *tmp = NULL;
1620 char *output = NULL;
1621
1622 /** pointers **********************************************************/
1623 char *p;
1624 char *part_table_fmt = NULL;
1625 FILE *fout;
1626
1627 /** end ***************************************************************/
1628
1629 assert_string_is_neither_NULL_nor_zerolength(drive);
1630 assert(format != NULL);
1631
1632 log_it("partition_device('%s', %d, %d, '%s', %lld) --- starting",
1633 drive, partno, prev_partno, format, partsize);
1634
1635 if (!strncmp(drive, RAID_DEVICE_STUB, strlen(RAID_DEVICE_STUB))) {
1636 log_it("Not partitioning %s - it is a virtual drive", drive);
1637 return (0);
1638 }
1639 partition_name = build_partition_name(drive, partno);
1640 if (partsize <= 0) {
1641 mr_asprintf(tmp, "Partitioning device %s (max size)", partition_name);
1642 } else {
1643 mr_asprintf(tmp, "Partitioning device %s (%lld MB)", partition_name, (long long) partsize / 1024);
1644 }
1645 update_progress_form(tmp);
1646 log_it(tmp);
1647 mr_free(tmp);
1648
1649 if (is_this_device_mounted(partition_name)) {
1650 log_to_screen("%s is mounted, and should not be partitioned", partition_name);
1651 mr_free(partition_name);
1652 return (1);
1653 }
1654
1655
1656 p = (char *) strrchr(partition_name, '/');
1657
1658 /* BERLIOS: should not be called each time */
1659 part_table_fmt = which_partition_format(drive);
1660 mr_asprintf(output, "");
1661 /* make it a primary/extended/logical */
1662 if (partno <= 4) {
1663 mr_strcat(output, "n\np\n%d\n", partno);
1664 } else {
1665 /* MBR needs an extended partition if more than 4 partitions */
1666 if (strcmp(part_table_fmt, "MBR") == 0) {
1667 if (partno == 5) {
1668 if (prev_partno >= 4) {
1669 log_to_screen("You need to leave at least one partition free, for 'extended/logical'");
1670 mr_free(partition_name);
1671 mr_free(output);
1672 mr_free(part_table_fmt);
1673 return (1);
1674 } else {
1675 mr_strcat(output, "n\ne\n%d\n\n\n", prev_partno + 1);
1676 }
1677 }
1678 mr_strcat(output, "n\nl\n");
1679 } else {
1680 /* GPT allows more than 4 primary partitions */
1681 mr_strcat(output, "n\np\n%d\n", partno);
1682 }
1683 }
1684 mr_free(part_table_fmt);
1685
1686 mr_strcat(output, "\n"); /*start block (ENTER for next free blk */
1687 if (partsize > 0) {
1688 if (!strcmp(format, "7")) {
1689 log_msg(1, "Adding 512K, just in case");
1690 partsize += 512;
1691 }
1692 mr_strcat(output, "+%lldK", (long long) (partsize));
1693 }
1694 mr_strcat(output, "\n");
1695 log_it("PARTSIZE = +%ld",(long)partsize);
1696
1697 log_it("---fdisk command---");
1698 log_it(output);
1699 log_it("---end of fdisk---");
1700
1701 mr_asprintf(program, "parted2fdisk %s >> %s 2>> %s", drive, MONDO_LOGFILE, MONDO_LOGFILE);
1702 if (pout_to_fdisk) {
1703 log_msg(1, "Doing the new all-in-one fdisk thing");
1704 log_msg(1, "output = '%s'", output);
1705 fput_string_one_char_at_a_time(pout_to_fdisk, output);
1706 fput_string_one_char_at_a_time(pout_to_fdisk, "\n\np\n");
1707 tmp = last_line_of_file(FDISK_LOG);
1708 if (strstr(tmp, " (m ")) {
1709 log_msg(1, "Successfully created partition %d on %s", partno, drive);
1710 } else {
1711 log_msg(1, "last line = %s", tmp);
1712 log_msg(1, "Failed to create partition %d on %s; sending 'Enter'...", partno, drive);
1713 }
1714 mr_free(tmp);
1715
1716 if (!retval) {
1717 log_msg(1, "Trying to set partition %d type now on %s", partno, drive);
1718 retval =
1719 set_partition_type(pout_to_fdisk, drive, partno, format,
1720 partsize);
1721 if (retval) {
1722 log_msg(1, "Failed. Trying again...");
1723 retval =
1724 set_partition_type(pout_to_fdisk, drive, partno,
1725 format, partsize);
1726 }
1727 }
1728 if (retval) {
1729 log_msg(1, "...but failed to set type");
1730 }
1731 } else {
1732 mr_strcat(output, "w\n\n");
1733 if (g_fprep) {
1734 fprintf(g_fprep, "echo \"%s\" | %s\n", output, program);
1735 }
1736 /* write to disk; close fdisk's stream */
1737 if (!(fout = popen(program, "w"))) {
1738 log_OS_error("can't popen-out to program");
1739 } else {
1740 fputs(output, fout);
1741 paranoid_pclose(fout);
1742 }
1743 if (!does_partition_exist(drive, partno) && partsize > 0) {
1744 log_it("Vaccum-packing");
1745 g_current_progress--;
1746 res =
1747 partition_device(pout_to_fdisk, drive, partno, prev_partno,
1748 format, -1);
1749 if (res) {
1750 log_it("Failed to vacuum-pack %s", partition_name);
1751
1752 retval++;
1753 } else {
1754 retval = 0;
1755 }
1756 }
1757 if (does_partition_exist(drive, partno)) {
1758 retval =
1759 set_partition_type(pout_to_fdisk, drive, partno, format,
1760 partsize);
1761 if (retval) {
1762 log_it("Partitioned %s but failed to set its type", partition_name);
1763 } else {
1764 if (partsize > 0) {
1765 log_to_screen("Partition %s created+configured OK", partition_name);
1766 } else {
1767 log_it("Returning from a successful vacuum-pack");
1768 }
1769 }
1770 } else {
1771 mr_asprintf(tmp, "Failed to partition %s", partition_name);
1772 if (partsize > 0) {
1773 log_to_screen(tmp);
1774 } else {
1775 log_it(tmp);
1776 }
1777 mr_free(tmp);
1778 retval++;
1779 }
1780 }
1781 mr_free(program);
1782 mr_free(partition_name);
1783 paranoid_free(output);
1784
1785 g_current_progress++;
1786 log_it("partition_device() --- leaving");
1787 return (retval);
1788}
1789
1790
1791
1792/**
1793 * Create all partitions listed in @p mountlist.
1794 * @param mountlist The mountlist to use to guide the partitioning.
1795 * @return The number of errors encountered (0 for success).
1796 * @note This sets the partition types but doesn't actually do the formatting.
1797 * Use format_everything() for that.
1798 */
1799int partition_everything(struct mountlist_itself *mountlist)
1800{
1801 /** int ************************************************************/
1802 int lino;
1803 int retval = 0;
1804 int i;
1805 int res;
1806
1807 /** buffer *********************************************************/
1808 struct list_of_disks *drivelist;
1809 /* struct mountlist_itself new_mtlist, *mountlist; */
1810
1811 /** end ************************************************************/
1812
1813 drivelist = malloc(sizeof(struct list_of_disks));
1814 assert(mountlist != NULL);
1815
1816 log_it("partition_everything() --- starting");
1817 mvaddstr_and_log_it(g_currentY, 0, "Partitioning hard drives ");
1818 /* mountlist=orig_mtlist; */
1819 if (mountlist_contains_raid_devices(mountlist)) {
1820 /* mountlist=&new_mtlist; */
1821 /* extrapolate_mountlist_to_include_raid_partitions(mountlist,orig_mtlist); */
1822 log_msg(0,
1823 "Mountlist, including the partitions incorporated in RAID devices:-");
1824 for (i = 0; i < mountlist->entries; i++) {
1825 log_it(mountlist->el[i].device);
1826 }
1827 log_msg(0, "End of mountlist.");
1828 }
1829 log_msg(0, "Stopping all LVMs, just in case");
1830 if (!g_text_mode) {
1831 newtSuspend();
1832 }
1833 do_my_funky_lvm_stuff(TRUE, FALSE); // just remove old partitions
1834 if (!g_text_mode) {
1835 newtResume();
1836 }
1837 log_msg(0, "Stopping all software RAID devices, just in case");
1838 stop_all_raid_devices(mountlist);
1839 log_msg(0, "Done.");
1840
1841 open_progress_form("Partitioning devices",
1842 "I am now going to partition all your drives.",
1843 "This should not take more than five minutes.", "",
1844 mountlist->entries);
1845
1846 make_list_of_drives_in_mountlist(mountlist, drivelist);
1847
1848 /* partition each drive */
1849 for (lino = 0; lino < drivelist->entries; lino++) {
1850 res = partition_drive(mountlist, drivelist->el[lino].device);
1851 retval += res;
1852 }
1853 close_progress_form();
1854 if (retval) {
1855 mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1856 log_to_screen("Errors occurred during the partitioning of your hard drives.");
1857 } else {
1858 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1859 paranoid_system("rm -f /tmp/fdisk*.log 2> /dev/null");
1860 }
1861 newtSuspend();
1862 system("clear");
1863 newtResume();
1864 paranoid_free(drivelist);
1865 return (retval);
1866}
1867
1868
1869
1870
1871
1872
1873/**
1874 * Set the type of partition number @p partno on @p drive to @p format.
1875 * @param drive The drive to change the type of a partition on.
1876 * @param partno The partition number on @p drive to change the type of.
1877 * @param format The filesystem type this partition will eventually contain.
1878 * @param partsize The size of this partition, in @e bytes (used for vfat
1879 * type calculations).
1880 * @return 0 for success, nonzero for failure.
1881 */
1882int set_partition_type(FILE * pout_to_fdisk, const char *drive, int partno,
1883 const char *format, long long partsize)
1884{
1885 /** buffers *********************************************************/
1886 char *partition = NULL;
1887 char *command = NULL;
1888 char *output = NULL;
1889 char *tmp = NULL;
1890 char *tmp1 = NULL;
1891 char *partcode = NULL;
1892
1893 /** pointers *********************************************************/
1894 char *p;
1895 FILE *fout;
1896
1897 /** int **************************************************************/
1898 int res = 0;
1899
1900 /** end **************************************************************/
1901
1902 assert_string_is_neither_NULL_nor_zerolength(drive);
1903 assert(format != NULL);
1904
1905 partition = build_partition_name(drive, partno);
1906 p = (char *) strrchr(partition, '/');
1907 if (strcmp(format, "swap") == 0) {
1908 mr_asprintf(partcode, "82");
1909 } else if (strcmp(format, "vfat") == 0) {
1910 if (partsize / 1024 > 8192) {
1911 mr_asprintf(partcode, "c");
1912 } else {
1913 mr_asprintf(partcode, "b");
1914 }
1915 } else if (strcmp(format, "ext2") == 0
1916 || strcmp(format, "reiserfs") == 0
1917 || strcmp(format, "ext3") == 0
1918 || strcmp(format, "ext4") == 0
1919 || strcmp(format, "xfs") == 0
1920 || strcmp(format, "jfs") == 0) {
1921 mr_asprintf(partcode, "83");
1922 } else if (strcmp(format, "minix") == 0) {
1923 mr_asprintf(partcode, "81");
1924 } else if (strcmp(format, "vmfs3") == 0) {
1925 mr_asprintf(partcode, "fb");
1926 } else if (strcmp(format, "vmkcore") == 0) {
1927 mr_asprintf(partcode, "fc");
1928 } else if (strcmp(format, "raid") == 0) {
1929 mr_asprintf(partcode, "fd");
1930 } else if (strcmp(format, "ntfs") == 0) {
1931 mr_asprintf(partcode, "7");
1932 } else if ((strcmp(format, "ufs") == 0)
1933 || (strcmp(format, "ffs") == 0)) { /* raid autodetect */
1934 mr_asprintf(partcode, "a5");
1935 } else if (strcmp(format, "lvm") == 0) {
1936 mr_asprintf(partcode, "8e");
1937 } else if (format[0] == '\0') { /* LVM physical partition */
1938 mr_asprintf(partcode, "");
1939 } else if (strlen(format) >= 1 && strlen(format) <= 2) {
1940 mr_asprintf(partcode, "%s", format);
1941 } else {
1942 /* probably an image */
1943 mr_asprintf(tmp, "Unknown format ('%s') - using supplied string anyway", format);
1944 mvaddstr_and_log_it(g_currentY++, 0, tmp);
1945 mr_free(tmp);
1946#ifdef __FreeBSD__
1947 mr_asprintf(partcode, "%s", format); // was a5
1948#else
1949 mr_asprintf(partcode, "%s", format); // was 83
1950#endif
1951 }
1952 log_msg(1, tmp, "Setting %s's type to %s (%s)", partition, format, partcode);
1953 mr_free(partition);
1954
1955 if (partcode != NULL && strcmp(partcode, "83")) { /* no need to set type if 83: 83 is default */
1956
1957 if (pout_to_fdisk) {
1958 res = 0;
1959 fput_string_one_char_at_a_time(pout_to_fdisk, "t\n");
1960 tmp1 = last_line_of_file(FDISK_LOG);
1961 if (partno > 1 || strstr(tmp1, " (1-4)")) {
1962 log_msg(5, "Specifying partno (%d) - yay", partno);
1963 mr_asprintf(tmp, "%d\n", partno);
1964 fput_string_one_char_at_a_time(pout_to_fdisk, tmp);
1965 mr_free(tmp);
1966
1967 mr_free(tmp1);
1968 tmp1 = last_line_of_file(FDISK_LOG);
1969 log_msg(5, "A - last line = '%s'", tmp1);
1970 }
1971 mr_free(tmp1);
1972
1973 mr_asprintf(tmp, "%s\n", partcode);
1974 fput_string_one_char_at_a_time(pout_to_fdisk, tmp);
1975 mr_free(tmp);
1976
1977 tmp1 = last_line_of_file(FDISK_LOG);
1978 log_msg(5, "B - last line = '%s'", tmp1);
1979 mr_free(tmp1);
1980
1981 fput_string_one_char_at_a_time(pout_to_fdisk, "\n");
1982 tmp1 = last_line_of_file(FDISK_LOG);
1983 log_msg(5, "C - last line = '%s'", tmp1);
1984 mr_free(tmp1);
1985
1986 tmp1 = last_line_of_file(FDISK_LOG);
1987 if (!strstr(tmp1, " (m ")) {
1988 log_msg(1, "last line = '%s'; part type set failed", tmp1);
1989 res++;
1990 fput_string_one_char_at_a_time(pout_to_fdisk, "\n");
1991 }
1992 mr_free(tmp1);
1993
1994 fput_string_one_char_at_a_time(pout_to_fdisk, "p\n");
1995 } else {
1996 mr_asprintf(output, "t\n%d\n%s\nw\n", partno, partcode);
1997 mr_asprintf(command, "parted2fdisk %s >> %s 2>> %s", drive, MONDO_LOGFILE, MONDO_LOGFILE);
1998 log_msg(5, "output = '%s'", output);
1999 log_msg(5, "partno=%d; partcode=%s", partno, partcode);
2000 log_msg(5, "command = '%s'", command);
2001 fout = popen(command, "w");
2002 if (!fout) {
2003 log_OS_error(command);
2004 res = 1;
2005 } else {
2006 res = 0;
2007 fprintf(fout, "%s", output);
2008 paranoid_pclose(fout);
2009 }
2010 paranoid_free(output);
2011 mr_free(command);
2012 }
2013 }
2014
2015 mr_free(partcode);
2016 return (res);
2017}
2018
2019
2020int start_raid_device(char *raid_device)
2021{
2022 /** int *************************************************************/
2023 int res;
2024 int retval = 0;
2025
2026 /** buffers *********************************************************/
2027 char *program = NULL;
2028
2029 /** end *************************************************************/
2030
2031 assert_string_is_neither_NULL_nor_zerolength(raid_device);
2032
2033#ifdef __FreeBSD__
2034 if (is_this_device_mounted(raid_device)) {
2035 log_it("Can't start %s when it's mounted!", raid_device);
2036 return 1;
2037 }
2038 mr_asprintf(program, "vinum start -f %s", raid_device);
2039#else
2040 mr_asprintf(program, "raidstart %s", raid_device);
2041#endif
2042 log_msg(1, "program = %s", program);
2043 res = run_program_and_log_output(program, 1);
2044 if (g_fprep) {
2045 fprintf(g_fprep, "%s\n", program);
2046 }
2047 mr_free(program);
2048
2049 if (res) {
2050 log_msg(1, "Warning - failed to start RAID device %s",
2051 raid_device);
2052 }
2053 retval += res;
2054 sleep(1);
2055 return (retval);
2056}
2057
2058
2059
2060/**
2061 * Stop @p raid_device using @p raidstop.
2062 * @param raid_device The software RAID device to stop.
2063 * @return 0 for success, nonzero for failure.
2064 */
2065int stop_raid_device(char *raid_device)
2066{
2067 /** int *************************************************************/
2068 int res;
2069 int retval = 0;
2070
2071 /** buffers *********************************************************/
2072 char *program = NULL;
2073
2074 /** end *************************************************************/
2075
2076 assert_string_is_neither_NULL_nor_zerolength(raid_device);
2077
2078#ifdef __FreeBSD__
2079 if (is_this_device_mounted(raid_device)) {
2080 log_it("Can't stop %s when it's mounted!", raid_device);
2081 return 1;
2082 }
2083 mr_asprintf(program, "vinum stop -f %s", raid_device);
2084#else
2085 // use raidstop if it exists, otherwise use mdadm
2086 if (run_program_and_log_output("which raidstop", FALSE)) {
2087 mr_asprintf(program, "mdadm -S %s", raid_device);
2088 } else {
2089 mr_asprintf(program, "raidstop %s", raid_device);
2090 }
2091#endif
2092 log_msg(1, "program = %s", program);
2093 res = run_program_and_log_output(program, 1);
2094 if (g_fprep) {
2095 fprintf(g_fprep, "%s\n", program);
2096 }
2097 mr_free(program);
2098
2099 if (res) {
2100 log_msg(1, "Warning - failed to stop RAID device %s", raid_device);
2101 }
2102 retval += res;
2103 return (retval);
2104}
2105
2106
2107int start_all_raid_devices(struct mountlist_itself *mountlist)
2108{
2109 int i;
2110 int retval = 0;
2111 int res;
2112
2113 for (i = 0; i < mountlist->entries; i++) {
2114 if (!strncmp
2115 (mountlist->el[i].device, RAID_DEVICE_STUB,
2116 strlen(RAID_DEVICE_STUB))) {
2117 log_msg(1, "Starting %s", mountlist->el[i].device);
2118 res = start_raid_device(mountlist->el[i].device);
2119 retval += res;
2120 }
2121 }
2122 if (retval) {
2123 log_msg(1, "Started all s/w raid devices OK");
2124 } else {
2125 log_msg(1, "Failed to start some/all s/w raid devices");
2126 }
2127 return (retval);
2128}
2129
2130/**
2131 * Stop all software RAID devices listed in @p mountlist.
2132 * @param mountlist The mountlist to stop the RAID devices in.
2133 * @return The number of errors encountered (0 for success).
2134 * @bug @p mountlist is not used.
2135 */
2136int stop_all_raid_devices(struct mountlist_itself *mountlist)
2137{
2138 /** int *************************************************************/
2139 int retval = 0;
2140
2141 /** char ************************************************************/
2142 char *incoming = NULL;
2143#ifndef __FreeBSD__
2144 char *dev;
2145 char *p;
2146 int res;
2147#endif
2148
2149 /** pointers ********************************************************/
2150 FILE *fin;
2151 int i;
2152
2153 /** end ****************************************************************/
2154
2155 assert(mountlist != NULL);
2156
2157 for (i = 0; i < 3; i++) {
2158#ifdef __FreeBSD__
2159 fin = popen("vinum list | grep '^[PVS]' | sed 's/S/1/;s/P/2/;s/V/3/' | sort | cut -d' ' -f2", "r");
2160 if (!fin) {
2161 return (1);
2162 }
2163 for (mr_getline(incoming, fin); !feof(fin); mr_getline(incoming, fin)) {
2164 retval += stop_raid_device(incoming);
2165 mr_free(incoming);
2166 }
2167 mr_free(incoming);
2168#else
2169 fin = fopen("/proc/mdstat", "r");
2170 if (!fin) {
2171 log_OS_error("/proc/mdstat");
2172 return (1);
2173 }
2174 for (mr_getline(incoming, fin); !feof(fin); mr_getline(incoming, fin)) {
2175 for (p = incoming; *p != '\0' && (*p != 'm' || *(p + 1) != 'd' || !isdigit(*(p + 2))); p++);
2176 if (*p != '\0') {
2177 mr_asprintf(dev, "/dev/%s", p);
2178 for (p = dev; *p > 32; p++);
2179 *p = '\0';
2180 res = stop_raid_device(dev);
2181 mr_free(dev);
2182 }
2183 mr_free(incoming);
2184 }
2185 mr_free(incoming);
2186#endif
2187 }
2188 paranoid_fclose(fin);
2189 if (retval) {
2190 log_msg(1, "Warning - unable to stop some RAID devices");
2191 }
2192 sync();
2193 sync();
2194 sync();
2195 sleep(1);
2196 return (retval);
2197}
2198
2199
2200
2201/**
2202 * Decide which command we need to use to format a device of type @p format.
2203 * @param format The filesystem type we are about to format.
2204 * @param program Where to put the binary name for this format.
2205 * @return 0 for success, nonzero for failure.
2206 */
2207char *which_format_command_do_i_need(char *format)
2208{
2209 /** int *************************************************************/
2210 int res = 0;
2211
2212 /** buffers *********************************************************/
2213 char *program = NULL;
2214
2215 /** end ***************************************************************/
2216
2217 assert_string_is_neither_NULL_nor_zerolength(format);
2218
2219 if (strcmp(format, "swap") == 0) {
2220#ifdef __FreeBSD__
2221 mr_asprintf(program, "true");
2222#else
2223 mr_asprintf(program, "mkswap");
2224#endif
2225 } else if (strcmp(format, "vfat") == 0) {
2226 mr_asprintf(program, "format-and-kludge-vfat");
2227#ifndef __FreeBSD__
2228 } else if (strcmp(format, "reiserfs") == 0) {
2229 mr_asprintf(program, "mkreiserfs -ff");
2230 } else if (strcmp(format, "xfs") == 0) {
2231 mr_asprintf(program, "mkfs.xfs -f -q");
2232 } else if (strcmp(format, "jfs") == 0) {
2233 mr_asprintf(program, "mkfs.jfs");
2234 } else if (strcmp(format, "ext3") == 0) {
2235 mr_asprintf(program, "mkfs -t ext3 -F -q");
2236 } else if (strcmp(format, "ext4") == 0) {
2237 mr_asprintf(program, "mkfs -t ext4 -F -q");
2238 } else if (strcmp(format, "minix") == 0) {
2239 mr_asprintf(program, "mkfs.minix");
2240 } else if (strcmp(format, "vmfs") == 0) {
2241 mr_asprintf(program, "mkfs -t vmfs");
2242 } else if (strcmp(format, "ntfs") == 0) {
2243 /*
2244 * mkfs.ntfs treats the '-c' switch as 'specify cluster size'
2245 * so the default "mkfs -t %s -c" command structure fails
2246 */
2247 mr_asprintf(program, "mkfs -t ntfs");
2248 } else if (strcmp(format, "ocfs2") == 0) {
2249 /*
2250 * For existing OCFS2 volumes, mkfs.ocfs2 ensures the volume is not mounted on any node in the cluster before formatting. For that to work, mkfs.ocfs2 expects the O2CB cluster service to be running. Specify this option to disable this check.
2251 *
2252 */
2253 mr_asprintf(program, "mkfs -t ocfs2 -F");
2254#endif
2255 } else if (strcmp(format, "ext2") == 0) {
2256 mr_asprintf(program, "mke2fs -F -q");
2257 } else {
2258#ifdef __FreeBSD__
2259 mr_asprintf(program, "newfs_%s", format);
2260#else
2261 mr_asprintf(program, "mkfs -t %s -c", format); // -c checks for bad blocks
2262#endif
2263 log_it("Unknown format (%s) - assuming '%s' will do", format, program);
2264 res = 0;
2265 }
2266 return (program);
2267}
2268
2269
2270/**
2271 * Resize a drive's entries in @p mountlist proportionately to fit its new size.
2272 * There are a few problems with this function:
2273 * - It won't work if there was any unallocated space on the user's hard drive
2274 * when it was backed up.
2275 * - It won't work if the user's hard drive lies about its size (more common
2276 * than you'd think).
2277 *
2278 * @param mountlist The mountlist to use for resizing @p drive_name.
2279 * @param drive_name The drive to resize.
2280 */
2281void resize_drive_proportionately_to_suit_new_drives(struct mountlist_itself
2282 *mountlist,
2283 char *drive_name)
2284{
2285
2286 /** int *************************************************************/
2287 int partno, lastpart;
2288 /** remove driveno, noof_drives stan benoit apr 2002**/
2289
2290 /** float ***********************************************************/
2291 long long factor;
2292 long long new_size;
2293
2294 /** long *************************************************************/
2295 long long newsizL = 0LL;
2296 long long totalsizL = 0LL;
2297 long long current_size_of_drive = 0LL; /* use KB interally for precision */
2298 long long original_size_of_drive = 0LL; /* use KB interally for precision */
2299 struct mountlist_reference *drivemntlist;
2300
2301 /** structures *******************************************************/
2302
2303 /** end **************************************************************/
2304
2305 assert(mountlist != NULL);
2306 assert_string_is_neither_NULL_nor_zerolength(drive_name);
2307
2308 if (strlen(drive_name) >= strlen(RAID_DEVICE_STUB)) {
2309 if (strncmp(drive_name, RAID_DEVICE_STUB, strlen(RAID_DEVICE_STUB))
2310 == 0) {
2311 return;
2312 }
2313 }
2314
2315 current_size_of_drive = (long long) get_phys_size_of_drive(drive_name) * 1024LL;
2316
2317 if (current_size_of_drive <= 0LL) {
2318 log_it("Not resizing to match %s - can't find drive", drive_name);
2319 return;
2320 }
2321 log_to_screen("Expanding entries to suit drive %s (%lld MB)", drive_name, current_size_of_drive / 1024);
2322
2323 drivemntlist = malloc(sizeof(struct mountlist_reference));
2324 drivemntlist->el =
2325 malloc(sizeof(struct mountlist_line *) * MAX_MOUNTLIST_ENTRIES);
2326
2327 if (!drivemntlist) {
2328 fatal_error("Cannot malloc temporary mountlist\n");
2329 }
2330 create_mountlist_for_drive(mountlist, drive_name, drivemntlist);
2331
2332 for (partno = 0; partno < drivemntlist->entries; partno++) {
2333 if (drivemntlist->el[partno]->size > 0LL) {
2334 /* Keep KB here */
2335 original_size_of_drive += drivemntlist->el[partno]->size;
2336 }
2337 }
2338
2339 if (original_size_of_drive <= 0) {
2340 log_to_screen("Cannot resize %s's entries. Drive not found.", drive_name);
2341 return;
2342 }
2343 factor = (current_size_of_drive) / (original_size_of_drive);
2344 log_to_screen("Disk %s was %lld MB; is now %lld MB; Proportionally resizing partitions (factor ~= %lld)", drive_name, original_size_of_drive/1024, current_size_of_drive/1024, factor);
2345
2346 lastpart = drivemntlist->entries - 1;
2347 for (partno = 0; partno < drivemntlist->entries; partno++) {
2348 /* the 'atoi' thing is to make sure we don't try to resize _images_, whose formats will be numeric */
2349 if (!atoi(drivemntlist->el[partno]->format)) {
2350 new_size = (drivemntlist->el[partno]->size) * factor;
2351 } else {
2352 new_size = drivemntlist->el[partno]->size;
2353 }
2354
2355 if (!strcmp(drivemntlist->el[partno]->mountpoint, "image")) {
2356 log_msg(1, "Skipping %s (%s) because it's an image",
2357 drivemntlist->el[partno]->device,
2358 drivemntlist->el[partno]->mountpoint);
2359 }
2360 newsizL = new_size;
2361
2362 /* Do not apply the factor if partition was of negative size */
2363 if (newsizL < 0LL) {
2364 newsizL = drivemntlist->el[partno]->size;
2365 }
2366 totalsizL += newsizL;
2367
2368 log_to_screen("Changing %s from %lld KB to %lld KB", drivemntlist->el[partno]->device, drivemntlist->el[partno]->size, newsizL);
2369 drivemntlist->el[partno]->size = newsizL;
2370 }
2371 // Ensures over-allocation alert and prompt for interactive mode does not happen
2372 if (totalsizL > current_size_of_drive) {
2373 log_to_screen("Last partition size calculated would be over-allocated, reducing %s from %lld KB to %lld KB.", drivemntlist->el[lastpart]->device, drivemntlist->el[lastpart]->size, drivemntlist->el[lastpart]->size - (totalsizL - current_size_of_drive));
2374 drivemntlist->el[drivemntlist->entries-1]->size -= (totalsizL - current_size_of_drive);
2375 } else if (totalsizL < current_size_of_drive) {
2376 log_to_screen("Last partition size calculated would be under-allocated, increasing %s from %lld KB to %lld KB.",drivemntlist->el[lastpart]->device, drivemntlist->el[lastpart]->size, drivemntlist->el[lastpart]->size + (current_size_of_drive - totalsizL));
2377 drivemntlist->el[drivemntlist->entries-1]->size += (current_size_of_drive - totalsizL);
2378 }
2379 log_to_screen("final_size = %lld MB", current_size_of_drive / 1024);
2380}
2381
2382
2383/**
2384 * Resize all partitions in @p mountlist proportionately (each one
2385 * grows or shrinks by the same percentage) to fit them into the new
2386 * drives (presumably different from the old ones).
2387 * @param mountlist The mountlist to resize the drives in.
2388 */
2389void resize_mountlist_proportionately_to_suit_new_drives(struct mountlist_itself
2390 *mountlist)
2391{
2392 /** buffers *********************************************************/
2393 struct list_of_disks *drivelist;
2394
2395 /** int *************************************************************/
2396 int driveno;
2397
2398 /** end *************************************************************/
2399
2400 drivelist = malloc(sizeof(struct list_of_disks));
2401 assert(mountlist != NULL);
2402
2403 log_it("Resizing mountlist");
2404 make_list_of_drives_in_mountlist(mountlist, drivelist);
2405 log_it("Back from MLoDiM");
2406 for (driveno = 0; driveno < drivelist->entries; driveno++) {
2407 resize_drive_proportionately_to_suit_new_drives(mountlist,
2408 drivelist->
2409 el[driveno].
2410 device);
2411 }
2412 log_to_screen("Mountlist adjusted to suit current hard drive(s)");
2413 paranoid_free(drivelist);
2414}
2415
2416/**
2417 * Create a mountlist_reference structure for @p drive_name in @p mountlist.
2418 * @param mountlist The complete mountlist to get the drive references from.
2419 * @param drive_name The drive to put in @p drivemntlist.
2420 * @param drivemntlist The mountlist_reference structure to put the drive's entries in.
2421 * @note @p drivemntlist and @p drivemntlist->el must be allocated by the caller.
2422 * @author Ralph Grewe
2423 */
2424void create_mountlist_for_drive(struct mountlist_itself *mountlist,
2425 char *drive_name,
2426 struct mountlist_reference *drivemntlist)
2427{
2428 int partno;
2429 char *tmp_drive_name, *c;
2430
2431 assert(mountlist != NULL);
2432 assert(drive_name != NULL);
2433 assert(drivemntlist != NULL);
2434
2435 log_msg(1, "Creating list of partitions for drive %s", drive_name);
2436
2437 tmp_drive_name = strdup(drive_name);
2438 if (!tmp_drive_name)
2439 fatal_error("Out of memory");
2440
2441 /* devfs devices? */
2442 c = strrchr(tmp_drive_name, '/');
2443 if (c && strncmp(c, "/disc", 5) == 0) {
2444 /* yup its devfs, change the "disc" to "part" so the existing code works */
2445 strcpy(c + 1, "part");
2446 }
2447 drivemntlist->entries = 0;
2448 for (partno = 0; partno < mountlist->entries; partno++) {
2449 if (strncmp
2450 (mountlist->el[partno].device, tmp_drive_name,
2451 strlen(tmp_drive_name)) == 0) {
2452 drivemntlist->el[drivemntlist->entries] =
2453 &mountlist->el[partno];
2454 drivemntlist->entries++;
2455 }
2456 }
2457 if (tmp_drive_name)
2458 free(tmp_drive_name);
2459}
2460
2461/* @} - end of prepGroup */
Note: See TracBrowser for help on using the repository browser.