source: MondoRescue/branches/stable/mondo/mondo/mondorestore/mondo-prep.c@ 681

Last change on this file since 681 was 681, checked in by andree, 18 years ago

Replaced all occurrences of egrep with 'grep -E' and of fgrep with
'grep -F' in mondo.
egrep and fgrep are usually just script wrappers around grep these
days which means additional overhead compared to calling grep with the
relevant option. Also, it appears that egrep and fgrep have been
deprecated by POSIX some time ago.

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