home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / boot / i386 / root / usr / share / YaST2 / include / partitioning / auto_part_functions.ycp < prev    next >
Text File  |  2006-11-29  |  14KB  |  457 lines

  1. /**
  2.  * Module:         auto_part_functions.ycp
  3.  *
  4.  * Authors:         Andreas Schwab (schwab@suse.de)
  5.  *            Klaus KΣmpf (kkaempf@suse.de)
  6.  *
  7.  * Purpose:         This module define functions of general use
  8.  *            to the automatic partitioner
  9.  *
  10.  * $Id: auto_part_functions.ycp 26727 2005-12-22 18:10:40Z fehr $
  11.  *
  12.  * needs global variables:
  13.  *
  14.  * integer bytes_per_unit
  15.  * integer first_logical_nr
  16.  * integer max_partitions
  17.  *
  18.  * defined functions:
  19.     global define size_of_region (list region) ``{
  20.     global define size_to_units (integer bytes) ``{
  21.     global define start_of_region (list region) ``{
  22.     global define end_of_region (list region) ``{
  23.     global define num_primary (list partitions) ``{
  24.     global define contiguous_selection (list selection) ``{
  25.     global define contains_extended (list partitions) ``{
  26.     global define extended_region (list partitions) ``{
  27.     global define calculate_selected_region (list selection, any extended_region) ``{
  28.     global define can_create_logical (list partitions) ``{
  29.     global define bootable (list region) ``{
  30.     global define can_resize( list partitions ) ``{
  31.     global define renumber_logical_partitions (list partitions) ``{
  32.     global define unused_extended_region (list partitions) ``{
  33.     global define unused_logical_region (list partitions) ``{
  34.     global define compute_max_partitions (map target) ``{
  35.     global define compute_max_primary (map target)
  36.  *
  37.  */
  38. {
  39.     import "Arch";
  40.     import "Partitions";
  41.  
  42.     textdomain "storage";
  43.  
  44.     include "partitioning/partition_defines.ycp";
  45.  
  46.     // --------------------------------------------------------------
  47.     // helper functions
  48.  
  49.     // Return the size of a disk region in bytes
  50.  
  51. define integer size_of_region (list<integer> region, 
  52.                                           integer bytes_per_unit) ``{
  53.     return region[1]:0 * bytes_per_unit;
  54.     };
  55.  
  56.     // Return the number of units that holds at least BYTES
  57.  
  58. define integer size_to_units( integer bytes, 
  59.                                          integer bytes_per_unit) ``{
  60.     return (bytes + bytes_per_unit - 1) / bytes_per_unit;
  61.     };
  62.  
  63.     // Return the start of the region.
  64.  
  65. define integer start_of_region (list<integer> region) ``{
  66.     return region[0]:0;
  67.     };
  68.  
  69.     // Return the end of the region, ie. start of the next region
  70.  
  71. define integer end_of_region (list<integer> region) ``{
  72.     return region[0]:0 + region[1]:0;
  73.     };
  74.  
  75.     // Return the number of primary partitions
  76.  
  77. define integer num_primary (list<map> partitions) ``{
  78.     integer n = 0;
  79.  
  80.     foreach (map pentry, partitions, ``{
  81.         if (pentry["type"]:`unknown == `primary)
  82.         n = n + 1;
  83.     });
  84.  
  85.     return n;
  86.     };
  87.  
  88.     // The maximum partition number the kernel can handle for the target
  89.     // disk, count from 0 on, return the maximal allowed value for
  90.     // a partition number
  91.  
  92. define integer compute_max_partitions (map disk) 
  93.     ``{
  94.     integer ret = disk["max_primary"]:4 - 1;
  95.     if( disk["label"]:""=="msdos" )
  96.         {
  97.         if( disk["bus"]:"" == "IDE" )
  98.         {
  99.         ret = 63;
  100.         }
  101.         else
  102.         {
  103.         ret = 15;
  104.         }
  105.         }
  106.     return( ret );
  107.     };
  108.  
  109.     // return the maximal number of primary partitions
  110.  
  111. define integer compute_max_primary (map disk) ``{
  112.     return disk["max_primary"]:4;
  113.     };
  114.  
  115.     // Return whether the list of selected partitions is contiguous.
  116.  
  117. define boolean contiguous_selection (list<map> selection) ``{
  118.     boolean ret = true;
  119.     list<integer>    last_region = nil;
  120.  
  121.     foreach (map pentry, selection, ``{
  122.         if (!pentry["create"]:false) {
  123.         list<integer> region = pentry["region"]:[];
  124.         symbol type = pentry["type"]:`unknown;
  125.         if( last_region != nil &&
  126.             (end_of_region(last_region) < start_of_region(region)))
  127.             {
  128.             ret = false;
  129.             }
  130.         last_region = region;
  131.         }
  132.     });
  133.     return ret;
  134.     }; // contiguous_selection
  135.  
  136.  
  137.     // Return true if an extended partition exists
  138.  
  139. define boolean contains_extended (list<map> partitions) ``{
  140.     boolean ret = find( map p, partitions, 
  141.                         ``(p["type"]:`unknown==`extended && 
  142.                    !p["delete"]:false)) != nil;
  143.     return( ret );
  144.     };
  145.  
  146. define boolean ignored_partition( map disk, map part )
  147.     ``{
  148.     // skip #3 on AlphaBSD and SparcBSD
  149.     boolean ret = disk["label"]:""=="bsd" || disk["label"]:""=="sun";
  150.     if( ret )
  151.     {
  152.     ret = part["nr"]:0 == 3;
  153.     }
  154.     return( ret );
  155.     };
  156.  
  157.     // Return the region of the extended partition
  158.  
  159. define list<integer> extended_region (list<map> partitions) ``{
  160.     list<integer> ret = [ 0, 0 ];
  161.     foreach (map pentry, partitions, ``{
  162.     if (pentry["type"]:`unknown == `extended)
  163.         ret = (list<integer>) (pentry["region"]:[]);
  164.     });
  165.     return ret;
  166.     };
  167.  
  168.  
  169.     // Return the region for the selected partitions.  If EXTENDED_REGION
  170.     // is not nil it is used to clip the region so that it is contained
  171.     // entirely within it.
  172.  
  173. define list<integer> calculate_selected_region( list selection, 
  174.                                                 list<integer> ext_region ) 
  175.     ``{
  176.     integer start = -1;
  177.     integer end = 0;
  178.     if( size(selection) > 0) 
  179.     {
  180.     start = start_of_region( selection[0,"region"]:[] );
  181.     end = end_of_region( selection[size(selection)-1,"region"]:[] );
  182.     }
  183.     if (start != -1) 
  184.     {
  185.     if (size (ext_region)>0) 
  186.         {
  187.         // Use only the part that is contained in the extended
  188.         // partition
  189.         if (start >= end_of_region (ext_region))
  190.         return [ 0, 0 ];
  191.         if (start < start_of_region (ext_region))
  192.         start = start_of_region (ext_region);
  193.         if (end > end_of_region (ext_region))
  194.         end = end_of_region (ext_region);
  195.         }
  196.     return [ start, end - start ];
  197.     }
  198.     return [ 0, 0 ];
  199.     }; // selected_region
  200.  
  201.  
  202.     // Check whether three logical partitions can be created without
  203.     // running past the kernel limit for the number of partitions
  204.  
  205. define boolean can_create_logical( list<map> partitions )
  206.     ``{
  207.     list logicals = filter( map pentry, partitions,
  208.                 ``(pentry["type"]:`unknown == `logical));
  209.     integer num_logical = size (logicals);
  210.     return ((first_logical_nr + num_logical + 3) <= (max_partitions + 1));
  211.     };
  212.  
  213.     // Check whether the boot partition is located entrely below the bootable
  214.     // cylinder limit
  215.  
  216. define boolean bootable(list<integer> region, integer bps) 
  217.     ``{
  218.     return( start_of_region(region) + size_to_units(size_of_boot,bps) < 
  219.         Partitions::BootCyl() );
  220.     };
  221.  
  222.  
  223.     // Check if the given partition is a FAT partition
  224.     // Input:  partition map to be checked (from targets)
  225.     // Return: true if partition is FAT, false otherwise
  226.     //
  227. define boolean is_fat_partition( map partition ) ``{
  228.     return ( partition["fsid"]:-1 == 0x06 ||    // FAT16
  229.          partition["fsid"]:-1 == 0x0b ||    // Win95 FAT32 CHS
  230.          partition["fsid"]:-1 == 0x0c ||    // Win95 FAT32 LBA
  231.          partition["fsid"]:-1 == 0x0e );    // Win95 FAT16 LBA    
  232.     }
  233.  
  234.  
  235.     // Check if the given partition is a NTFS partition
  236.     // Input:  partition map to be checked (from targets)
  237.     // Return: true if partition is NTFS, false otherwise
  238.     //
  239. define boolean is_ntfs_partition( map partition ) ``{
  240.     return ( partition["fsid"]:-1 == 0x07 ||     // HPFS/NTFS
  241.          partition["fsid"]:-1 == 0x86 ||     // NTFS-DatentrΣger
  242.          partition["fsid"]:-1 == 0x87 );    // NTFS-DatentrΣger
  243.     }
  244.  
  245.     
  246.     // Get the partition map with the highest minor number out of the given partition list
  247.     // Input:  List of partition maps.
  248.     // Return: Partition map if found or $[] if not.
  249.     //
  250. define map get_last_used_partition( list<map> partitions ) 
  251.     ``{
  252.     map last_partition = $[];
  253.     integer minor = -1;
  254.  
  255.     y2milestone( "get_last_used_partition p:%1", partitions );
  256.  
  257.     foreach( map partition, partitions, 
  258.     ``{
  259.     if ( partition["nr"]:-1 > minor )
  260.         {
  261.         minor = partition["nr"]:-1;
  262.         last_partition = partition;
  263.         }
  264.     });
  265.     y2milestone( "get_last_used_partition ret %1", last_partition );
  266.     return last_partition;
  267.     }
  268.  
  269.     
  270. // Check whether the partition list has a resizable partition as the highest partition.
  271. // Input:  List of partition maps
  272. // Return: resizeable partition map or $[] if none found
  273. //
  274. define map can_resize( list<map> partitions ) 
  275.     ``{
  276.     map last_used_partition = $[];
  277.     
  278.     if( !Arch::i386 () )
  279.     {
  280.     y2warning( "Wrong architecture - can't resize partitions" );
  281.     return $[];    // for now
  282.     }
  283.  
  284.     // Filter out empty space that might exist behind valid partitions.
  285.     // This space would be there as a pseudo partition of type `free.
  286.     //
  287.     list<map> partitions_local =
  288.     filter( map pentry, partitions, ``( pentry["type"]:`dummy != `free ));
  289.  
  290.     last_used_partition = get_last_used_partition( partitions_local );
  291.     
  292.     if ( last_used_partition == $[] ) return $[];    // no last resizeable partition found
  293.         
  294.     // Check for supported filesystem types.
  295.     //    
  296.     if( is_fat_partition( last_used_partition ) )
  297.     return last_used_partition;
  298.     else
  299.     return $[];
  300.     }
  301.  
  302.     
  303.     // Check if the given file does exist.
  304.     // Input:  File to be checked incl. path as string, e.g. "/usr/lib/YaST2/clients/installation.ycp"
  305.     //         This may also point to a directory.
  306.     // Return: true if found, false if not.
  307.     //
  308. define boolean file_exist( string file_path ) ``{
  309.       boolean file_found = (integer)SCR::Read(.target.size, file_path) >= 0;
  310.       y2milestone( "file %1 found %2 ret:%3", file_path, file_found,
  311.                    SCR::Read(.target.size, file_path) );
  312.       return file_found;
  313.     }
  314.  
  315.     
  316. // Check whether the partition list has a resizable partition as the highest 
  317. // partition.
  318. // Input:  map of data containing the disk
  319. // Return: true if there is NT on the system, otherwise false
  320. //
  321. define integer check_win_nt_system( map disk ) 
  322.     ``{
  323.     boolean is_nt = false;
  324.     boolean go_on = true;
  325.     integer local_ret = 0;
  326.     boolean local_err = false;
  327.     list<map> partitions = [];
  328.     list<map> partitions_local = [];
  329.     string fat_partition = "";
  330.     
  331.     partitions = disk["partitions"]:[];
  332.     if ( ! is_nt && ! local_err && go_on )
  333.     {
  334.     // First check if there are any NTFS partitions on the system
  335.     //
  336.     partitions_local = filter( map pentry, partitions, 
  337.                                ``( is_ntfs_partition( pentry ) ) );
  338.  
  339.     if ( size( partitions_local ) != 0 ) is_nt = true;    // is NT system
  340.     }
  341.  
  342.     if( !is_nt && !local_err && go_on )
  343.     {
  344.     // Then look for specific files on all FAT partitions
  345.     //
  346.     partitions_local = filter( map pentry, partitions, 
  347.                                ``( is_fat_partition( pentry ) ) );
  348.     
  349.     if ( size( partitions_local ) == 0 ) go_on = false;    // not an NT system
  350.     }
  351.  
  352.     // If there are FAT partitions mount them and check specific files
  353.     //
  354.     if( ! is_nt && ! local_err && go_on )
  355.     {
  356.     foreach( map pentry, partitions_local, 
  357.         ``{
  358.         // Now we are looping over all partitions for the current device.
  359.         // get some special values from the partition entry.
  360.  
  361.         if( ! is_nt && ! local_err && go_on )
  362.         {
  363.         // build devicename.
  364.         fat_partition = pentry["device"]:"";
  365.  
  366.         // mount the partition
  367.         local_ret = 
  368.             (integer)SCR::Execute( .target.bash, 
  369.                        "/bin/mount "+fat_partition+" /mnt" );
  370.  
  371.         if ( local_ret != 0 )
  372.             {
  373.             y2error( "FAT partition <%1> could not be mounted. Canceled", fat_partition );
  374.             local_err = true;
  375.             }
  376.         }
  377.  
  378.         if( ! is_nt && ! local_err && go_on )
  379.         {
  380.         if ( file_exist( "/mnt/winnt/system32/ntoskrnl.exe" ) ||
  381.              file_exist( "/mnt/winnt/system32/dllcache" ) )
  382.             {
  383.             y2error( "Current Windows device <%1> is NT or 2000. Canceled", fat_partition );
  384.             is_nt = true;
  385.             }
  386.         }
  387.  
  388.         // unmount the partition if was mounted
  389.         if ( !local_err ) SCR::Execute(.target.bash, "/bin/umount " + fat_partition );
  390.         });   // loop over all partitions
  391.     }
  392.  
  393.     if ( local_err ) return 2;
  394.     if ( is_nt )     return 1;
  395.     else          return 0;
  396.     }; // End of check_win_nt_system()
  397.  
  398.  
  399.     // --------------------------------------------------------------
  400.     // Renumber the logical partitions if some of them are deleted
  401.     // The returned list is sorted by partition number instead of region
  402.  
  403. define list<map> renumber_logical_partitions (list<map> partitions) ``{
  404.     partitions = sort (map a, map b, partitions, ``(a["nr"]:0 < b["nr"]:0));
  405.     integer logicals_deleted = 0;
  406.     return maplist (map pentry, partitions, ``{
  407.         if (pentry["type"]:`unknown == `logical) {
  408.         if (pentry["delete"]:false)
  409.             logicals_deleted = logicals_deleted + 1;
  410.         else
  411.             pentry = add (pentry, "nr",
  412.                 pentry["nr"]:0 - logicals_deleted);
  413.         }
  414.         return pentry;
  415.     });
  416.     };
  417.  
  418.     // Find unused space at the end of the extended partition
  419. define list<integer> unused_extended_region (list<map> partitions) ``{
  420.     list<integer> extended = extended_region (partitions);
  421.     list logicals = filter (map pentry, partitions, ``(pentry["type"]:`unknown == `logical));
  422.     integer end_of_logicals = 0;
  423.  
  424.     if (size (logicals) > 0)
  425.         end_of_logicals = end_of_region(logicals[size(logicals)-1,"region"]:[]);
  426.     else
  427.         end_of_logicals = start_of_region (extended);
  428.  
  429.     if (end_of_logicals < end_of_region (extended))
  430.         return [ end_of_logicals, end_of_region (extended) - end_of_logicals ];
  431.     return [0, 0];
  432.     };
  433.  
  434.  
  435.     // Find unused space at the start of the extended partition
  436. define list<integer> unused_logical_region (list<map> partitions) ``{
  437.     list<integer> extended = extended_region (partitions);
  438.     list logicals = filter (map pentry, partitions, ``(pentry["type"]:`unknown == `logical));
  439.     integer start_of_logicals = 0;
  440.  
  441.     if (size (logicals) > 0)
  442.         start_of_logicals = start_of_region (logicals[0,"region"]:[]);
  443.     else
  444.         start_of_logicals = start_of_region (extended);
  445.  
  446.     if (start_of_logicals > start_of_region (extended))
  447.         return [ start_of_region(extended), start_of_region (extended) - start_of_logicals ];
  448.     return [0, 0];
  449.     };
  450.  
  451. define integer calculate_needed_swap ()
  452.     ``{
  453.     return 1024*1024*Partitions::SwapSizeMb( 0 );
  454.     };
  455.  
  456. }
  457.