ACC SHELL
/**
* Module: Partitions.ycp
*
* Authors: Thomas Fehr <fehr@suse.de>
* Arvin Schnell <aschnell@suse.de>
*
* Purpose: Provides information about partitions
*
* $Id: Partitions.ycp 62005 2010-05-12 14:57:07Z aschnell $
*/
{
module "Partitions";
textdomain "storage";
import "Arch";
import "Mode";
import "Stage";
import "AsciiFile";
import "LibStorage";
import "LibStorage::StorageInterface";
import "LibStorage::DlabelCapabilities";
// The filesystem ids for the partitions
global const integer fsid_empty = 0;
global const integer fsid_native = 131;
global const integer fsid_swap = 130;
global const integer fsid_lvm = 142;
global const integer fsid_raid = 253;
global const integer fsid_hibernation = 160;
global const integer fsid_extended = 5;
global const integer fsid_extended_win = 15;
global const integer fsid_fat16 = 6;
global const integer fsid_fat32 = 12;
global const integer fsid_prep_chrp_boot = 0x41;
global const integer fsid_mac_hidden = 0x101;
global const integer fsid_mac_hfs = 0x102;
global const integer fsid_mac_ufs = 0x106;
global const integer fsid_gpt_boot = 0x103;
global const integer fsid_gpt_service = 0x104;
global const integer fsid_gpt_msftres = 0x105;
global const integer fsid_freebsd = 0xa5;
global const integer fsid_openbsd = 0xa6;
global const integer fsid_netbsd = 0xa9;
global const integer fsid_beos = 0xeb;
global const integer fsid_solaris = 0xbf;
global const integer fsid_root = fsid_native;
integer fsid_boot = 0;
integer boot_cyl = 0;
string boot_mount_point = "";
global boolean no_fsid_menu = Arch::s390 ();
global string raid_name = "MD RAID";
global string lv_name = "LV";
global string dm_name = "DM";
global string loop_name = "Loop Device";
global string dmraid_name = "DM RAID";
global string dmmultipath_name = "DM Multipath";
global string nfs_name = "NFS";
// filesystems for /win
global const list<integer> fsid_wintypes = [ 6, 11, 12, 14 ]; /* FAT32, Win95-Fat32, Win95LBA, Win95-Fat16 */
// filesystems for /dos
global const list<integer> fsid_dostypes = [ 1, 4 ]; /* FAT12, FAT16 */
// filesystems for /windows
global const list<integer> fsid_ntfstypes = [ 7, 23 ]; /* NTFS */
// filesystems mounted read-only
global const list<integer> fsid_readonly = [ 7, 23 ];
// filesystems skipped on sparc and axp
global const list<integer> fsid_skipped = [ 0, 5 ];
// partition ids not to delete when suggesting to use whole disk
global const list<integer> do_not_delete = [ 0x12, 0xde, fsid_mac_hfs, fsid_gpt_service ];
// partition ids not to display as windows when fat32 is on it
global const list<integer> no_windows = [ 0x12, 0x82, 0xde, fsid_gpt_boot, fsid_gpt_service,
fsid_gpt_msftres ];
integer minimal_needed_bootsize = 0;
symbol default_fs = `unknown;
symbol default_boot_fs = `unknown;
any sint = nil;
global void InitSlib(any value)
{
sint = value;
}
global boolean EfiBoot()
{
// TODO: move to libstorage
boolean ret = false;
if (Arch::ia64())
{
ret = true;
}
else
{
if (Stage::initial())
{
string tmp = (string) SCR::Read(.etc.install_inf.EFI);
if (tmp != nil && tmp == "1")
ret = true;
}
else
{
string tmp = (string) SCR::Read(.sysconfig.bootloader.LOADER_TYPE);
if (tmp != nil && tmp == "elilo")
ret = true;
}
}
y2milestone("EfiBoot ret:%1", ret);
return ret;
}
global void SetDefaultFs(symbol new_default_fs)
{
default_fs = new_default_fs;
default_boot_fs = `unknown;
}
global symbol DefaultFs()
{
if (default_fs == `unknown)
{
string tmp = (string) SCR::Read(.sysconfig.storage.DEFAULT_FS);
if (tmp == nil || !contains([ "ext2", "ext3", "ext4", "reiser", "xfs" ], tolower(tmp)))
tmp = "ext4";
default_fs = tosymbol(tolower(tmp));
}
return default_fs;
}
global symbol DefaultBootFs()
{
if (default_boot_fs == `unknown)
{
default_boot_fs = DefaultFs();
if (EfiBoot())
{
default_boot_fs = `vfat;
}
else if (Arch::board_mac())
{
default_boot_fs = `hfs;
}
}
return default_boot_fs;
}
global string BootMount()
{
if (boot_mount_point == "")
{
boot_mount_point = "/boot";
if (EfiBoot())
{
boot_mount_point = "/boot/efi";
}
}
return boot_mount_point;
}
global define integer MinimalNeededBootsize()
``{
if( minimal_needed_bootsize == 0 )
{
minimal_needed_bootsize = 64 * 1024 * 1024;
if( Arch::ia64() )
{
minimal_needed_bootsize = 200*1024*1024;
}
else if( Arch::board_chrp() )
{
minimal_needed_bootsize = 200*1024*1024;
}
else if( Arch::board_prep() )
{
minimal_needed_bootsize = 200*1024*1024;
}
else if( Arch::board_iseries() )
{
minimal_needed_bootsize = 200*1024*1024;
}
else if( Arch::board_mac() )
{
minimal_needed_bootsize = 32*1024*1024;
}
}
return( minimal_needed_bootsize );
}
global define integer MinimalRequiredBootsize()
``{
integer need = MinimalNeededBootsize();
integer ret = need;
if( Arch::ia64() )
ret = ret / 10 * 9;
else if( Arch::board_mac() )
ret = 800 * 1024;
if( ret!=need )
y2milestone( "MinimalRequiredBootsize ret %1 Req:%2", ret, need );
return( ret );
}
global define integer BootCyl()
``{
if( boot_cyl == 0 )
{
boot_cyl = 1024;
if( !Arch::i386 () )
{
// Assume on non-i386 archs machine can boot from every cylinder
boot_cyl = 4*1024*1024*1024;
}
else
{
list internal_bios = (list<map>) SCR::Read (.probe.bios);
boolean lba = internal_bios[0, "lba_support"]:false;
y2milestone( "BootCyl lba_support %1", lba );
if( !lba )
{
map st = (map)SCR::Read( .target.stat,
"/proc/xen/capabilities" );
y2milestone( "BootCyl /proc/xen/capabilities %1", st );
if( size(st)>0 )
lba = (integer)SCR::Execute( .target.bash,
"grep control_d /proc/xen/capabilities" )>0;
y2milestone( "BootCyl lba_support %1", lba );
}
if( lba )
{
boot_cyl = 4*1024*1024*1024;
}
}
}
return( boot_cyl );
}
boolean prep_boot_first = true;
global define boolean PrepBoot()
``{
boolean ret = Arch::ppc() &&
(Arch::board_chrp() || Arch::board_prep() || Arch::board_iseries());
if( ret && prep_boot_first )
{
y2milestone( "PrepBoot ret:%1", ret );
prep_boot_first = false;
}
return( ret );
};
global define boolean BootPrimary()
{
boolean ret = PrepBoot();
return( ret );
}
global integer FsidBoot()
{
if( fsid_boot == 0 )
{
fsid_boot = fsid_native;
if (EfiBoot() || Arch::ia64())
{
fsid_boot = fsid_gpt_boot;
}
else if( PrepBoot() )
{
fsid_boot = fsid_prep_chrp_boot;
}
else if( Arch::board_mac () )
{
fsid_boot = fsid_mac_hfs;
}
}
return fsid_boot;
}
global boolean NeedBoot()
{
boolean ret = false;
if (EfiBoot() || Arch::ia64() || Arch::ppc() || Arch::sparc() || Arch::alpha())
{
ret = true;
}
y2milestone( "NeedBoot ret:%1", ret );
return ret;
}
global define boolean IsDosPartition( integer fsid )
``{
return (contains( fsid_dostypes, fsid) || contains( fsid_wintypes, fsid));
}
global define boolean IsDosWinNtPartition( integer fsid )
``{
return( IsDosPartition( fsid ) || contains( fsid_ntfstypes, fsid ));
}
global define boolean IsExtendedPartition( integer fsid )
``{
return( fsid==fsid_extended || fsid==fsid_extended_win );
}
global define boolean IsSwapPartition( integer fsid )
``{
return( !IsDosWinNtPartition( fsid ) && fsid==fsid_swap );
}
global integer SwapSizeMb( integer slot_size )
{
map mem_info_map = (map) SCR::Read(.proc.meminfo);
integer mem = mem_info_map["memtotal"]:0 / 1024;
y2milestone("mem_info_map:%1 mem:%2", mem_info_map, mem);
// a good approach swap == mem x 2
integer swap_size = 0;
if( slot_size==0 )
{
if( mem <= 256 )
{
swap_size = mem * 2;
}
else
{
swap_size = mem + mem/2;
}
}
else
{
if( mem * 9 < slot_size )
{
swap_size = mem * 2;
}
else if( mem * 5 < slot_size )
{
swap_size = mem;
}
else if( mem * 3 < slot_size )
{
swap_size = mem / 2;
}
else if( mem * 2 < slot_size )
{
swap_size = mem / 3;
}
else
{
swap_size = mem / 4;
}
}
if( swap_size > 2048 )
{
swap_size = 2048;
}
if( swap_size < 0 )
{
swap_size = 0;
}
// look for a min size
// 1G -> 128MB
// 2G -> 256MB
// 10G -> 512MB
// 40G -> 1GB
if( slot_size > (40 * 1024) && (swap_size + mem) < 1024 )
{
swap_size = 1024 - mem;
}
else if( slot_size > (10 * 1024) && (swap_size + mem) < 512 )
{
swap_size = 512 - mem;
}
else if( slot_size > (2 * 1024) && (swap_size + mem) < 256 )
{
swap_size = 256 - mem;
}
else if( slot_size > (1 * 1024) && (swap_size + mem) < 128 )
{
swap_size = 128 - mem;
}
if( swap_size == 0 )
{
swap_size = -1;
}
y2milestone( "SwapSizeMb mem %1 slot_size %2 swap_size %3", mem,
slot_size, swap_size );
return( swap_size );
}
global define boolean IsResizable( integer fsid )
``{
boolean ret = false;
ret = IsDosWinNtPartition(fsid) || fsid == fsid_swap || fsid == fsid_native ||
IsExtendedPartition(fsid);
y2milestone( "IsResizable fsid:%1 ret:%2", fsid, ret );
return( ret );
}
global define boolean IsLinuxPartition( integer fsid )
``{
return ( fsid==fsid_native || fsid==fsid_swap || fsid==fsid_lvm ||
fsid==fsid_raid || fsid==fsid_gpt_boot );
};
global define map GetLoopOn( string device )
``{
map ret = $[];
string cmd = sformat( "/sbin/losetup %1", device );
map bash_call = (map) SCR::Execute (.target.bash_output, cmd, $[] );
if( bash_call["exit"]:1 == 0)
{
string text = bash_call["stdout"]:"";
integer fi = search( text, ")" );
if( fi!=nil && fi>0 )
{
text = substring( text, 0, fi );
fi = search( text, "(" );
if( fi!=nil && fi>0 )
{
text = substring( text, fi+1 );
ret["file"] = text;
map stat = (map) SCR::Read( .target.stat, text );
ret["blockdev"] = stat["isblock"]:false;
}
}
}
y2milestone( "dev %1 ret %2", device, ret );
return( ret );
}
global define string TranslateMapperName( string device )
``{
string ret = device;
string regex = "[^-](--)*-[^-]";
if( search( device, "/dev/mapper/" )==0 )
{
list<integer> pos = regexppos( device, regex );
y2milestone( "pos=%1", pos );
if( size(pos)>0 )
{
ret = "/dev/" + substring(device,12,pos[0]:0+pos[1]:0-14) + "/" +
substring(device,pos[0]:0+pos[1]:0-1);
integer spos = 4;
integer newpos = search(substring(ret,spos), "--");
if( newpos!=nil )
spos = spos + newpos;
else
spos = -1;
while( spos>=0 )
{
ret = substring(ret, 0, spos+1) + substring( ret, spos+2 );
spos = spos + 1;
newpos = search(substring(ret,spos), "--");
if( newpos!=nil )
spos = spos + newpos;
else
spos = -1;
}
}
y2milestone( "TranslateMapperName %1 -> %2", device, ret );
}
return( ret );
}
/**
* Return a list with all mounted partition
* @return list<map>
*/
global list<map> CurMounted()
{
SCR::UnmountAgent (.proc.mounts);
SCR::UnmountAgent (.proc.swaps);
SCR::UnmountAgent (.etc.mtab);
list<map> mounts = (list<map>) SCR::Read(.proc.mounts);
list<map> swaps = (list<map>) SCR::Read(.proc.swaps );
list<map> mtab = (list<map>) SCR::Read(.etc.mtab );
if (mounts == nil || swaps == nil || mtab == nil)
{
y2error("failed to read .proc.mounts or .proc.swaps or .etc.mtab");
return [];
}
foreach(map swap, swaps,
``{
map swap_entry = $[
"file" : "swap",
"spec" : swap["file"]:""
];
mounts = add( mounts, swap_entry );
});
map mtab_root = (map) find(map mount, mtab, ``( mount["file"]:"" == "/" ));
map root_map = (map) find(map mount, mounts,
``( mount["spec"]:"" == "/dev/root" ));
if( root_map == nil )
{
root_map = (map) find(map mount, mounts,
``( mount["spec"]:"" != "rootfs"&&
mount["file"]:"" == "/"));
}
y2milestone( "mtab_root %1 root_map %2", mtab_root, root_map );
// root_map = add (root_map, "spec", mtab_root["spec"]:"");
if( root_map["spec"]:"" == "/dev/root" )
root_map["spec"] = mtab_root["spec"]:"";
if( (search( root_map["spec"]:"", "LABEL=" )==0 ||
search( root_map["spec"]:"", "UUID=" )==0) && !Stage::initial () )
{
map bo = (map) SCR::Execute (.target.bash_output, "fsck -N /", $[] );
y2milestone( "CurMounted bo:%1", bo );
string dev = "";
if( bo["exit"]:1==0 )
{
list tmp = filter( string k, splitstring( bo["stdout"]:"", " \n" ),
``(size(k)>0) );
if( size(tmp)>0 )
dev = tmp[size(tmp)-1]:"";
y2milestone( "CurMounted LABEL/UUID dev:%1", dev );
}
if( size(dev)>0 )
{
root_map["spec"] = dev;
}
}
y2milestone( "root_map %1", root_map );
// this version makes some problems with interpreter, above lookup/add is OK
mounts = filter(map mount, mounts, ``( mount["file"]:"" != "/"));
mounts = add( mounts, root_map );
list<map> ret = [];
foreach(map p, mounts, ``{
if( search( p["spec"]:"", "/dev/loop" )!=nil )
{
map r = GetLoopOn( p["spec"]:"" );
if( r["blockdev"]:false )
{
p["loop_on"] = r["file"]:"";
}
}
ret = add( ret, p );
});
ret = maplist( map p, ret,
``{
p["spec"] = TranslateMapperName( p["spec"]:"" );
return( p );
});
y2milestone( "CurMounted all mounts %1", ret);
return ret;
};
global define map GetFstab( string pathname )
``{
map file = $[];
AsciiFile::SetComment( file, "^[ \t]*#" );
AsciiFile::SetDelimiter( file, " \t" );
AsciiFile::SetListWidth( file, [ 20, 20, 10, 21, 1, 1 ] );
AsciiFile::ReadFile( file, pathname );
return( file );
};
global define map GetCrypto( string pathname )
``{
map file = $[];
AsciiFile::SetComment( file, "^[ \t]*#" );
AsciiFile::SetDelimiter( file, " \t" );
AsciiFile::SetListWidth( file, [ 11, 15, 20, 10, 10, 1 ] );
AsciiFile::ReadFile( file, pathname );
return( file );
};
global string ToHexString(integer num)
{
return "0x" + toupper(substring(tohexstring(num, 2), 2));
}
global string FsIdToString(integer fs_id)
{
switch (fs_id)
{
case 0x0: return "empty";
case 0x1: return "FAT12";
case 0x2: return "XENIX root";
case 0x3: return "XENIX usr";
case 0x4: return "FAT16 <32M";
case 0x5: return "Extended";
case 0x6: return "FAT16";
case 0x7: return "HPFS/NTFS";
case 0x8: return "AIX";
case 0x9: return "AIX boot";
case 0xa: return "OS/2 boot manager";
case 0xb: return "Win95 FAT32";
case 0xc: return "Win95 FAT32 LBA";
case 0xe: return "Win95 FAT16";
case 0xf: return "Extended";
case 0xa7: return "NeXTSTEP";
case 0xb7: return "BSDI fs";
case 0xb8: return "BSDI swap";
case 0xc1: return "DRDOS/sec";
case 0xc4: return "DRDOS/sec";
case 0xc6: return "DRDOS/sec";
case 0xc7: return "Syrinx";
case 0xda: return "Non-Fs data";
case 0xdb: return "CP/M / CTOS";
case 0xde: return "Dell Utility";
case 0xe1: return "DOS access";
case 0xe3: return "DOS R/O";
case 0xe4: return "SpeedStor";
case 0xeb: return "BeOS fs";
case 0xee: return "EFI GPT";
case 0xef: return "EFI (FAT-12/16)";
case 0xf1: return "SpeedStor";
case 0xf4: return "SpeedStor";
case 0xf2: return "DOS secondary";
case 0xfd: return "Linux RAID";
case 0xfe: return "LANstep";
case 0xff: return "BBT or NBO reserved";
case 0x10: return "OPUS";
case 0x11: return "Hidden FAT12";
case 0x12: return "Vendor diag";
case 0x14: return "Hidden FAT16";
case 0x16: return "Hidden FAT16";
case 0x17: return "Hidden HPFS/NTFS";
case 0x18: return "AST Windows";
case 0x1b: return "Hidden Win95";
case 0x1c: return "Hidden Win95";
case 0x1e: return "Hidden Win95";
case 0x24: return "NEC DOS";
case 0x39: return "Plan 9";
case 0x3c: return "PartitionMagic";
case 0x40: return "Venix 80286";
case 0x41: return "PPC PReP Boot";
case 0x42: return "SFS";
case 0x4d: return "QNX4.x";
case 0x4e: return "QNX4.x 2nd par";
case 0x4f: return "QNX4.x 3rd par";
case 0x50: return "OnTrack DM";
case 0x51: return "OnTrack DM6";
case 0x52: return "CP/M";
case 0x53: return "OnTrack DM6";
case 0x54: return "OnTrack DM6";
case 0x55: return "EZ-Drive";
case 0x56: return "Golden Bow";
case 0x5c: return "Priam Edisk";
case 0x61: return "SpeedStor";
case 0x63: return "GNU HURD";
case 0x64: return "Novell NetWare";
case 0x65: return "Novell NetWare";
case 0x70: return "DiskSecure";
case 0x75: return "PC/IX";
case 0x80: return "Old Minix";
case 0x81: return "Minix";
case 0x82: return "Linux swap";
case 0x83: return "Linux native";
case 0x84: return "OS/2 hidden";
case 0x85: return "Linux extended";
case 0x86: return "NTFS volume";
case 0x87: return "NTFS volume";
case 0x8e: return "Linux LVM";
case 0x93: return "Amoeba";
case 0x94: return "Amoeba BBT";
case 0x9f: return "BSD/OS";
case 0xa0: return "Hibernation";
case 0xa5: return "FreeBSD";
case 0xa6: return "OpenBSD";
case 0xa9: return "NetBSD";
case 0x102: return "Apple_HFS";
case 0x103: return "EFI boot";
case 0x104: return "Service";
case 0x105: return "Microsoft reserved";
case 0x106: return "Apple_UFS";
default: return "unknown";
}
}
global integer MaxPrimary(string dlabel)
{
integer ret = 0;
any caps = LibStorage::DlabelCapabilities::new("LibStorage::DlabelCapabilities");
if (LibStorage::StorageInterface::getDlabelCapabilities(sint, dlabel, caps))
ret = LibStorage::DlabelCapabilities::swig_maxPrimary_get(caps);
y2milestone("MaxPrimary dlabel:%1 ret:%2", dlabel, ret);
return ret;
}
global boolean HasExtended(string dlabel)
{
boolean ret = false;
any caps = LibStorage::DlabelCapabilities::new("LibStorage::DlabelCapabilities");
if (LibStorage::StorageInterface::getDlabelCapabilities(sint, dlabel, caps))
ret = LibStorage::DlabelCapabilities::swig_extendedPossible_get(caps);
y2milestone("HasExtended dlabel:%1 ret:%2", dlabel, ret);
return ret;
}
global integer MaxLogical(string dlabel)
{
integer ret = 0;
any caps = LibStorage::DlabelCapabilities::new("LibStorage::DlabelCapabilities");
if (LibStorage::StorageInterface::getDlabelCapabilities(sint, dlabel, caps))
ret = LibStorage::DlabelCapabilities::swig_maxLogical_get(caps);
y2milestone("MaxLogical dlabel:%1 ret:%2", dlabel, ret);
return ret;
}
global integer MaxSectors(string dlabel)
{
integer ret = 0;
any caps = LibStorage::DlabelCapabilities::new("LibStorage::DlabelCapabilities");
if (LibStorage::StorageInterface::getDlabelCapabilities(sint, dlabel, caps))
ret = LibStorage::DlabelCapabilities::swig_maxSectors_get(caps);
y2milestone("MaxSizeK dlabel:%1 ret:%2", dlabel, ret);
return ret;
}
global define string RdonlyText( string disk, boolean expert_partitioner )
``{
string text = "";
if( expert_partitioner )
{
text = sformat( "Operation not permitted on disk %1 !\n", disk );
}
// popup text %1 is replaced by disk name e.g. /dev/hda
text = text + sformat( _("
The partitioning on your disk %1 is either not readable by
the partitioning tool parted used to change the
partition table or is not supported by this tool.
You may use the partitions on disk %1 as they are or
format them and assign mount points to them, but you
cannot add, edit, resize, or remove partitions from that
disk here.\n"), disk );
if( expert_partitioner )
{
// popup text
text = text + _("
You may initialize the disk partition table to a sane state in the Expert
Partitioner by selecting \"Expert\"->\"Delete Partition Table
and Disk Label\", but this will destroy all data on all partitions of this
disk.
");
}
else
{
// popup text
text = text + _("
Safely ignore this message if you do not intend to use
this disk during installation.
");
}
return( text );
}
}
ACC SHELL 2018