home *** CD-ROM | disk | FTP | other *** search
- /**
- * 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 26727 2005-12-22 18:10:40Z fehr $
- *
- * 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 size_to_units (integer bytes) ``{
- global define start_of_region (list region) ``{
- global define end_of_region (list region) ``{
- global define num_primary (list partitions) ``{
- global define contiguous_selection (list selection) ``{
- global define contains_extended (list partitions) ``{
- global define extended_region (list partitions) ``{
- global define calculate_selected_region (list selection, any extended_region) ``{
- global define can_create_logical (list partitions) ``{
- global define bootable (list region) ``{
- global define can_resize( list partitions ) ``{
- global define renumber_logical_partitions (list partitions) ``{
- global define unused_extended_region (list partitions) ``{
- global define unused_logical_region (list partitions) ``{
- global define compute_max_partitions (map target) ``{
- global define compute_max_primary (map target)
- *
- */
- {
- import "Arch";
- import "Partitions";
-
- textdomain "storage";
-
- include "partitioning/partition_defines.ycp";
-
- // --------------------------------------------------------------
- // 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 number of units that holds at least BYTES
-
- define integer size_to_units( integer bytes,
- integer bytes_per_unit) ``{
- return (bytes + bytes_per_unit - 1) / 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 the maximal number of primary partitions
-
- define integer compute_max_primary (map disk) ``{
- return disk["max_primary"]:4;
- };
-
- // Return whether the list of selected partitions is contiguous.
-
- define boolean contiguous_selection (list<map> selection) ``{
- boolean ret = true;
- list<integer> last_region = nil;
-
- foreach (map pentry, selection, ``{
- if (!pentry["create"]:false) {
- list<integer> region = pentry["region"]:[];
- symbol type = pentry["type"]:`unknown;
- if( last_region != nil &&
- (end_of_region(last_region) < start_of_region(region)))
- {
- ret = false;
- }
- last_region = region;
- }
- });
- return ret;
- }; // contiguous_selection
-
-
- // 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;
- };
-
-
- // Return the region for the selected partitions. If EXTENDED_REGION
- // is not nil it is used to clip the region so that it is contained
- // entirely within it.
-
- define list<integer> calculate_selected_region( list selection,
- list<integer> ext_region )
- ``{
- integer start = -1;
- integer end = 0;
- if( size(selection) > 0)
- {
- start = start_of_region( selection[0,"region"]:[] );
- end = end_of_region( selection[size(selection)-1,"region"]:[] );
- }
- if (start != -1)
- {
- if (size (ext_region)>0)
- {
- // Use only the part that is contained in the extended
- // partition
- if (start >= end_of_region (ext_region))
- return [ 0, 0 ];
- if (start < start_of_region (ext_region))
- start = start_of_region (ext_region);
- if (end > end_of_region (ext_region))
- end = end_of_region (ext_region);
- }
- return [ start, end - start ];
- }
- return [ 0, 0 ];
- }; // selected_region
-
-
- // 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 )
- ``{
- list logicals = filter( map pentry, partitions,
- ``(pentry["type"]:`unknown == `logical));
- integer num_logical = size (logicals);
- return ((first_logical_nr + num_logical + 3) <= (max_partitions + 1));
- };
-
- // Check whether the boot partition is located entrely below the bootable
- // cylinder limit
-
- define boolean bootable(list<integer> region, integer bps)
- ``{
- return( start_of_region(region) + size_to_units(size_of_boot,bps) <
- Partitions::BootCyl() );
- };
-
-
- // 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()
-
-
- // --------------------------------------------------------------
- // Renumber the logical partitions if some of them are deleted
- // The returned list is sorted by partition number instead of region
-
- define list<map> renumber_logical_partitions (list<map> partitions) ``{
- partitions = sort (map a, map b, partitions, ``(a["nr"]:0 < b["nr"]:0));
- integer logicals_deleted = 0;
- return maplist (map pentry, partitions, ``{
- if (pentry["type"]:`unknown == `logical) {
- if (pentry["delete"]:false)
- logicals_deleted = logicals_deleted + 1;
- else
- pentry = add (pentry, "nr",
- pentry["nr"]:0 - logicals_deleted);
- }
- return pentry;
- });
- };
-
- // 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];
- };
-
-
- // Find unused space at the start of the extended partition
- define list<integer> unused_logical_region (list<map> partitions) ``{
- list<integer> extended = extended_region (partitions);
- list logicals = filter (map pentry, partitions, ``(pentry["type"]:`unknown == `logical));
- integer start_of_logicals = 0;
-
- if (size (logicals) > 0)
- start_of_logicals = start_of_region (logicals[0,"region"]:[]);
- else
- start_of_logicals = start_of_region (extended);
-
- if (start_of_logicals > start_of_region (extended))
- return [ start_of_region(extended), start_of_region (extended) - start_of_logicals ];
- return [0, 0];
- };
-
- define integer calculate_needed_swap ()
- ``{
- return 1024*1024*Partitions::SwapSizeMb( 0 );
- };
-
- }
-