ACC SHELL

Path : /usr/share/YaST2/include/partitioning/
File Upload :
Current File : //usr/share/YaST2/include/partitioning/auto_part_functions.ycp

/**
 * Module: 		auto_part_functions.ycp
 *
 * Authors: 		Andreas Schwab (schwab@suse.de)
 *			Klaus Kämpf (kkaempf@suse.de)
 *
 * Purpose: 		This module define functions of general use
 *			to the automatic partitioner
 *
 * $Id: auto_part_functions.ycp 61402 2010-03-19 14:10:31Z aschnell $
 *
 * needs global variables:
 *
 * integer bytes_per_unit
 * integer first_logical_nr
 * integer max_partitions
 *
 * defined functions:
    global define size_of_region (list region) ``{
    global define start_of_region (list region) ``{
    global define end_of_region (list region) ``{
    global define num_primary (list partitions) ``{
    global define contains_extended (list partitions) ``{
    global define extended_region (list partitions) ``{
    global define can_create_logical (list partitions, integer first_logical,
                                      integer max_logical ) ``{
    global define can_resize( list partitions ) ``{
    global define unused_extended_region (list partitions) ``{
    global define compute_max_partitions (map target) ``{
 *
 */
{
    import "Arch";

    textdomain "storage";

    // --------------------------------------------------------------
    // helper functions

    // Return the size of a disk region in bytes

define integer size_of_region (list<integer> region, 
                                          integer bytes_per_unit) ``{
	return region[1]:0 * bytes_per_unit;
    };

    // Return the start of the region.

define integer start_of_region (list<integer> region) ``{
	return region[0]:0;
    };

    // Return the end of the region, ie. start of the next region

define integer end_of_region (list<integer> region) ``{
	return region[0]:0 + region[1]:0;
    };

    // Return the number of primary partitions

define integer num_primary (list<map> partitions) ``{
	integer n = 0;

	foreach (map pentry, partitions, ``{
	    if (pentry["type"]:`unknown == `primary)
		n = n + 1;
	});

	return n;
    };

    // The maximum partition number the kernel can handle for the target
    // disk, count from 0 on, return the maximal allowed value for
    // a partition number

define integer compute_max_partitions (map disk) 
	``{
	integer ret = disk["max_primary"]:4 - 1;
	if( disk["label"]:""=="msdos" )
	    {
	    if( disk["bus"]:"" == "IDE" )
		{
		ret = 63;
		}
	    else
		{
		ret = 15;
		}
	    }
	return( ret );
	};


    // Return true if an extended partition exists

define boolean contains_extended (list<map> partitions) ``{
	boolean ret = find( map p, partitions, 
	                    ``(p["type"]:`unknown==`extended && 
			       !p["delete"]:false)) != nil;
	return( ret );
    };

define boolean ignored_partition( map disk, map part )
    ``{
    // skip #3 on AlphaBSD and SparcBSD
    boolean ret = disk["label"]:""=="bsd" || disk["label"]:""=="sun";
    if( ret )
	{
	ret = part["nr"]:0 == 3;
	}
    return( ret );
    };

    // Return the region of the extended partition

define list<integer> extended_region (list<map> partitions) ``{
	list<integer> ret = [ 0, 0 ];
	foreach (map pentry, partitions, ``{
	if (pentry["type"]:`unknown == `extended)
	    ret = (list<integer>) (pentry["region"]:[]);
	});
	return ret;
    };


    // Check whether three logical partitions can be created without
    // running past the kernel limit for the number of partitions

define boolean can_create_logical( list<map> partitions,  
                                   integer first_logical_nr,
				   integer max_logical )
    ``{
    list logicals = filter( map pentry, partitions,
			    ``(pentry["type"]:`unknown == `logical));
    integer num_logical = size (logicals);
    return ((first_logical_nr + num_logical + 2) <= max_logical);
    };

    // Check if the given partition is a FAT partition
    // Input:  partition map to be checked (from targets)
    // Return: true if partition is FAT, false otherwise
    //
define boolean is_fat_partition( map partition ) ``{
	return ( partition["fsid"]:-1 == 0x06 ||	// FAT16
		 partition["fsid"]:-1 == 0x0b ||	// Win95 FAT32 CHS
		 partition["fsid"]:-1 == 0x0c ||	// Win95 FAT32 LBA
		 partition["fsid"]:-1 == 0x0e );	// Win95 FAT16 LBA	
    }


    // Check if the given partition is a NTFS partition
    // Input:  partition map to be checked (from targets)
    // Return: true if partition is NTFS, false otherwise
    //
define boolean is_ntfs_partition( map partition ) ``{
	return ( partition["fsid"]:-1 == 0x07 || 	// HPFS/NTFS
		 partition["fsid"]:-1 == 0x86 || 	// NTFS-Datenträger
		 partition["fsid"]:-1 == 0x87 );	// NTFS-Datenträger
    }

    
    // Get the partition map with the highest minor number out of the given partition list
    // Input:  List of partition maps.
    // Return: Partition map if found or $[] if not.
    //
define map get_last_used_partition( list<map> partitions ) 
    ``{
    map last_partition = $[];
    integer minor = -1;

    y2milestone( "get_last_used_partition p:%1", partitions );

    foreach( map partition, partitions, 
	``{
	if ( partition["nr"]:-1 > minor )
	    {
	    minor = partition["nr"]:-1;
	    last_partition = partition;
	    }
	});
    y2milestone( "get_last_used_partition ret %1", last_partition );
    return last_partition;
    }

    
// Check whether the partition list has a resizable partition as the highest partition.
// Input:  List of partition maps
// Return: resizeable partition map or $[] if none found
//
define map can_resize( list<map> partitions ) 
    ``{
    map last_used_partition = $[];
	
    if( !Arch::i386 () )
	{
	y2warning( "Wrong architecture - can't resize partitions" );
	return $[];	// for now
	}

    // Filter out empty space that might exist behind valid partitions.
    // This space would be there as a pseudo partition of type `free.
    //
    list<map> partitions_local =
	filter( map pentry, partitions, ``( pentry["type"]:`dummy != `free ));

    last_used_partition = get_last_used_partition( partitions_local );
	
    if ( last_used_partition == $[] ) return $[];	// no last resizeable partition found
	    
    // Check for supported filesystem types.
    //	
    if( is_fat_partition( last_used_partition ) )
	return last_used_partition;
    else
	return $[];
    }

    
    // Check if the given file does exist.
    // Input:  File to be checked incl. path as string, e.g. "/usr/lib/YaST2/clients/installation.ycp"
    //         This may also point to a directory.
    // Return: true if found, false if not.
    //
define boolean file_exist( string file_path ) ``{
	  boolean file_found = (integer)SCR::Read(.target.size, file_path) >= 0;
	  y2milestone( "file %1 found %2 ret:%3", file_path, file_found,
	               SCR::Read(.target.size, file_path) );
	  return file_found;
    }

    
// Check whether the partition list has a resizable partition as the highest 
// partition.
// Input:  map of data containing the disk
// Return: true if there is NT on the system, otherwise false
//
define integer check_win_nt_system( map disk ) 
    ``{
    boolean is_nt = false;
    boolean go_on = true;
    integer local_ret = 0;
    boolean local_err = false;
    list<map> partitions = [];
    list<map> partitions_local = [];
    string fat_partition = "";
    
    partitions = disk["partitions"]:[];
    if ( ! is_nt && ! local_err && go_on )
	{
	// First check if there are any NTFS partitions on the system
	//
	partitions_local = filter( map pentry, partitions, 
	                           ``( is_ntfs_partition( pentry ) ) );

	if ( size( partitions_local ) != 0 ) is_nt = true;	// is NT system
	}

    if( !is_nt && !local_err && go_on )
	{
	// Then look for specific files on all FAT partitions
	//
	partitions_local = filter( map pentry, partitions, 
	                           ``( is_fat_partition( pentry ) ) );
	
	if ( size( partitions_local ) == 0 ) go_on = false;	// not an NT system
	}

    // If there are FAT partitions mount them and check specific files
    //
    if( ! is_nt && ! local_err && go_on )
	{
	foreach( map pentry, partitions_local, 
	    ``{
	    // Now we are looping over all partitions for the current device.
	    // get some special values from the partition entry.

	    if( ! is_nt && ! local_err && go_on )
		{
		// build devicename.
		fat_partition = pentry["device"]:"";

		// mount the partition
		local_ret = 
		    (integer)SCR::Execute( .target.bash, 
					   "/bin/mount "+fat_partition+" /mnt" );

		if ( local_ret != 0 )
		    {
		    y2error( "FAT partition <%1> could not be mounted. Canceled", fat_partition );
		    local_err = true;
		    }
		}

	    if( ! is_nt && ! local_err && go_on )
		{
		if ( file_exist( "/mnt/winnt/system32/ntoskrnl.exe" ) ||
		     file_exist( "/mnt/winnt/system32/dllcache" ) )
		    {
		    y2error( "Current Windows device <%1> is NT or 2000. Canceled", fat_partition );
		    is_nt = true;
		    }
		}

	    // unmount the partition if was mounted
	    if ( !local_err ) SCR::Execute(.target.bash, "/bin/umount " + fat_partition );
	    });   // loop over all partitions
	}

    if ( local_err ) return 2;
    if ( is_nt )     return 1;
    else 	     return 0;
    }; // End of check_win_nt_system()


    // Find unused space at the end of the extended partition
define list<integer> unused_extended_region (list<map> partitions) ``{
	list<integer> extended = extended_region (partitions);
	list logicals = filter (map pentry, partitions, ``(pentry["type"]:`unknown == `logical));
	integer end_of_logicals = 0;

	if (size (logicals) > 0)
	    end_of_logicals = end_of_region(logicals[size(logicals)-1,"region"]:[]);
	else
	    end_of_logicals = start_of_region (extended);

	if (end_of_logicals < end_of_region (extended))
	    return [ end_of_logicals, end_of_region (extended) - end_of_logicals ];
	return [0, 0];
    };

}

ACC SHELL 2018