home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 February / CHIP_2_98.iso / misc / src / install / libfdisk / partspec.c < prev    next >
C/C++ Source or Header  |  1997-10-09  |  12KB  |  494 lines

  1. /* handles the PartitionSpec type and operations we do on them */
  2.  
  3. #include <stdio.h>
  4. #include <unistd.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7.  
  8. #include "libfdisk.h"
  9.  
  10. /* some globals used to keep up with last allocation error (sortof like errno) */
  11. enum allocReason LastAllocStat = ALLOC_UNDEF;
  12.  
  13. static char *reasons[] = { "Reason Undefined",
  14.     "Allocation Succeeded",
  15.     "Not enough free space",
  16.     "Requested Start",
  17.     "Requested Cylinder",
  18.     "Requested drive(s)",
  19.     "No free primary",
  20.     "Extended Failed",
  21.     "No free slots",
  22.     NULL
  23. };
  24.  
  25. /* returns pointers to a const char string of why */
  26. char *GetReasonString( enum allocReason reason ) {
  27.     int i;
  28.     
  29.     for (i=0; i < (int) reason && reasons[i]; i++);
  30.     if (!reasons[i])
  31.     return "Unknown reason";
  32.     else
  33.     return reasons[i];
  34. }
  35.  
  36.  
  37.  
  38.  
  39. /* give priority to the constraints of a partition */
  40. /* if priority is < 0 then there was an error      */
  41. int fdiskGetConstraintPriority( Partition *p ) {
  42.     int pri;
  43.     
  44.     pri = 0;
  45.  
  46.     if (p->immutable)
  47.     pri += 16384;
  48.     if (fdiskDriveSetIsActive( &p->drive ))
  49.     pri += 128;
  50.     if (fdiskConstraintIsActive( &p->endcyl))
  51.     pri +=  64;
  52.     if (fdiskConstraintIsActive( &p->start))
  53.     pri +=  32;
  54.     if (fdiskConstraintIsActive( &p->size))
  55.     pri +=  16;
  56.  
  57.     return pri;
  58. }
  59.  
  60.  
  61. /* sort in order of priority                                   */
  62. /* we now worry about <1024 cyl contraints if necessary        */
  63. int fdiskSortPartitionSpec( PartitionSpec *spec ) {
  64.     unsigned int i, j;
  65.     int          f;
  66.     unsigned int pri1, pri2;
  67.     unsigned int lsize1, lsize2;
  68.     unsigned int msize1, msize2;
  69.     unsigned int csize1, csize2;
  70.     unsigned int act1,   act2;
  71.     Partition *p1, *p2;
  72.     PartitionSpecEntry tmpe;
  73.  
  74.  
  75.     /* now see if there is anything to sort */
  76.     if (spec->num < 2)
  77.     return FDISK_SUCCESS;
  78.  
  79.     for (i=0; i<spec->num-1; i++) {
  80.     p1 = &spec->entry[i].partition;
  81.  
  82. #if 0
  83.     if (p1->immutable)
  84.         continue;
  85. #endif
  86.     
  87.     pri1 = fdiskGetConstraintPriority(p1);
  88.     fdiskGetConstraint(&p1->size,&csize1,&lsize1,&msize1,&act1 );
  89.     for (j=i+1; j < spec->num; j++) {
  90.         p2 = &spec->entry[j].partition;
  91.  
  92.         /* we dont want to reorder immutable specs */
  93.         /* but we want to bubble them to top over  */
  94.         /* user specifified partitions             */
  95.         if (p1->immutable && p2->immutable)
  96.         continue;
  97.         
  98.         pri2 = fdiskGetConstraintPriority(p2);
  99.  
  100.         if (pri1 < pri2)
  101.         f = 1;
  102.         else if (pri1 > pri2)
  103.         f = -1;
  104.         else {
  105.         fdiskGetConstraint(&p2->size,&csize2,&lsize2,&msize2,&act2 );
  106.         f = (lsize1 < lsize2);
  107.         }
  108.  
  109.         if (f > 0) {
  110.         memcpy(&tmpe, &spec->entry[i], sizeof(PartitionSpecEntry));
  111.         memcpy(&spec->entry[i], &spec->entry[j],
  112.                sizeof(PartitionSpecEntry));
  113.         memcpy(&spec->entry[j], &tmpe, sizeof(PartitionSpecEntry));
  114.  
  115.         }
  116.     }
  117.     }
  118.     return FDISK_SUCCESS;
  119. }
  120.  
  121. /* check for special partitions and setup constraints if they exist */
  122. int fdiskHandleSpecialPartitions( PartitionSpec *spec ) {
  123.     unsigned int i, j;
  124.     Partition *p1, *p2;
  125.  
  126.     /* oh man are PCs braindead */
  127. #if defined(__i386__)
  128.     /* see if we have any special partitions (like bootable) */
  129.     i = fdiskReturnPartitionSpec( spec, "/",     &p1 );
  130.     j = fdiskReturnPartitionSpec( spec, "/boot", &p2 );
  131.     
  132.     if (j == FDISK_SUCCESS) {
  133.     /* if "/" exists make it a normal partition again */
  134.     if (i==FDISK_SUCCESS) {
  135.         fdiskSetConstraint(&p1->endcyl,
  136.                    0,FDISK_ENDCYL_MIN,FDISK_ENDCYL_MAX,0);
  137.         fdiskActivateAllDriveSet( &p1->drive );
  138.         fdiskModifyPartitionSpec( spec, "/", p1, REQUEST_PENDING );
  139.         free(p1);
  140.     }
  141.     
  142.     /* set "/boot" as bootable partition */
  143.     fdiskSetConstraint(&p2->endcyl, 0,0,1023,1);
  144.     fdiskDeactivateAllDriveSet( &p2->drive );
  145.     fdiskActivateDriveSet( &p2->drive, 1 );
  146.     fdiskActivateDriveSet( &p2->drive, 2 );
  147.     fdiskModifyPartitionSpec( spec, "/boot", p2, REQUEST_PENDING );
  148.     free(p2);
  149.     } else if (i == FDISK_SUCCESS) {
  150.     /* make "/" bootable */
  151.     fdiskSetConstraint(&p1->endcyl,0,0,1023,1);
  152.     fdiskDeactivateAllDriveSet( &p1->drive );
  153.     fdiskActivateDriveSet( &p1->drive, 1 );
  154.     fdiskActivateDriveSet( &p1->drive, 2 );
  155.     fdiskModifyPartitionSpec( spec, "/", p1, REQUEST_PENDING );
  156.     free(p1);
  157.     }
  158.  
  159.     fdiskSortPartitionSpec( spec );
  160. #endif
  161.     return FDISK_SUCCESS;
  162. }
  163.  
  164.  
  165. /* get index of partition spec requested */
  166. /* return value is non-zero if not found */
  167. int fdiskIndexPartitionSpec(PartitionSpec *spec, char *name,
  168.                 unsigned int *index ) {
  169.  
  170.     unsigned int j, found;
  171.     
  172.     /* see if it already exists */
  173.     found = 0;
  174.     for (j=0; j<spec->num && !found;)
  175.     if (!strcmp(spec->entry[j].name, name))
  176.         found = 1;
  177.     else
  178.         j++;
  179.  
  180.     if (found) {
  181.     *index = j;
  182.     return FDISK_SUCCESS;
  183.     } else {
  184.     return FDISK_ERR_BADNUM;
  185.     }
  186. }
  187.  
  188. /* insert new specification into existing PartitionSpec */
  189. int fdiskInsertPartitionSpec( PartitionSpec *spec,
  190.                   char          *name,
  191.                   Partition     *p,
  192.                   unsigned int  status) {
  193.     unsigned int num;
  194.     unsigned int j, found;
  195.  
  196.     if ((num=spec->num) >=MAX_PARTITION_SPEC)
  197.     return FDISK_ERR_NOFREE;
  198.  
  199.     /* see if it already exists */
  200.     found = 0;
  201.     for (j=0; j<spec->num && !found;)
  202.     if (!strcmp(spec->entry[j].name, name))
  203.         found = 1;
  204.     else
  205.         j++;
  206.  
  207.     if (found)
  208.     return FDISK_ERR_INUSE;
  209.     
  210.     /* Ok insert the bugger */
  211.     spec->entry[num].name  = strdup(name);
  212.     memcpy(&spec->entry[num].partition, p, sizeof(Partition));
  213.     spec->entry[num].status = status;
  214.     spec->num++;
  215.  
  216.     fdiskSortPartitionSpec( spec );
  217.     return FDISK_SUCCESS;
  218. }
  219.  
  220. /* delete specification based on mount point */
  221. int fdiskDeletePartitionSpec( PartitionSpec *spec,
  222.                   char          *name ) {
  223.  
  224.     unsigned int j, k, found;
  225.  
  226.     found = 0;
  227.     for (j=0; j<spec->num && !found;)
  228.     if (!strcmp(spec->entry[j].name, name))
  229.         found = 1;
  230.     else
  231.         j++;
  232.  
  233.     if (!found)
  234.     return FDISK_ERR_BADNUM;
  235.     else {
  236.     /* cant delete immutable partitions */
  237.     if (spec->entry[j].partition.immutable)
  238.         return FDISK_ERR_BADNUM;
  239.     
  240.     if (spec->entry[j].name)
  241.         free(spec->entry[j].name);
  242.     for (k=j; k < spec->num-1; k++)
  243.         memcpy(&spec->entry[k], &spec->entry[k+1],
  244.            sizeof(PartitionSpecEntry));
  245.  
  246.     memset(&spec->entry[spec->num-1], 0, sizeof(PartitionSpecEntry));
  247.     spec->num--;
  248.     }
  249.  
  250.     return FDISK_SUCCESS;
  251. }
  252.  
  253. /* complete erase contents of a PartitionSpec - frees up names */
  254. int fdiskWipePartitionSpec( PartitionSpec *spec ) {
  255.     unsigned int i;
  256.  
  257.     for (i=0; i<spec->num; i++)
  258.     free(spec->entry[i].name);
  259.  
  260.     memset(spec, 0, sizeof(PartitionSpec));
  261.     spec->num = 0;
  262.     return FDISK_SUCCESS;
  263. }
  264.  
  265.  
  266.     
  267. /* update 'original' drives in partitionspec, in case any were removed  */
  268. /* leave specs the user has added since we started alone                */
  269. int fdiskCleanOriginalSpecs( HardDrive **hdarr, unsigned int numhd,
  270.                  PartitionSpec *spec ) {
  271.     unsigned int j, k, l;
  272.     unsigned int drive, start, size;
  273.     unsigned int tsize, tstart;
  274.     unsigned int first, last;
  275.     unsigned int remove;
  276.     unsigned int found;
  277.     Partition *p;
  278.  
  279.     for (j=0; j<spec->num; )
  280.     if (spec->entry[j].status != REQUEST_ORIGINAL) {
  281.         j++;
  282.         continue;
  283.     } else {
  284.         p = &spec->entry[j].partition;
  285.         
  286.         fdiskGetCurrentDriveSet(&p->drive, &drive );
  287.         fdiskGetCurrentConstraint(&p->size , &size  );
  288.         fdiskGetCurrentConstraint(&p->start, &start );
  289.  
  290.         /* find the HardDrive containing the drive we want */
  291.         for ( l=0; l<numhd; l++)
  292.         if (hdarr[l]->num == drive)
  293.             break;
  294.  
  295.         /* shouldnt happen */
  296.         if (l == numhd)
  297.         return FDISK_ERR_BADNUM;
  298.         else
  299.         drive = l;
  300.         
  301.         /* see if the partition still exists */
  302.         remove = 0;
  303.         found  = 0;
  304.         if (fdiskFirstPartition(hdarr[drive], &first)) {
  305.         remove = 1;
  306.         } else {
  307.         fdiskLastPartition(hdarr[drive], &last);
  308.  
  309.         for (l=first; l <=last && !found; l++) {
  310.             if (fdiskGetAttrPartition(hdarr[drive], l, &p) ==
  311.             FDISK_SUCCESS) {
  312.             fdiskGetCurrentConstraint(&p->size , &tsize  );
  313.             fdiskGetCurrentConstraint(&p->start, &tstart );
  314.             if (tstart == start && tsize == size) {
  315.                 found = 1;
  316.                 /* lets update partition info */
  317.                 memcpy(&spec->entry[j].partition, p,
  318.                    sizeof(Partition));
  319.             }
  320.  
  321.             free(p);
  322.             }
  323.         }
  324.         if (!found)
  325.             remove = 1;
  326.         }
  327.             
  328.         if (remove) {
  329.         if (spec->entry[j].name)
  330.             free(spec->entry[j].name);
  331.         for (k=j; k < spec->num-1; k++) 
  332.             memcpy(&spec->entry[k], &spec->entry[k+1],
  333.                sizeof(PartitionSpecEntry));
  334.         memset(&spec->entry[spec->num-1],0,sizeof(PartitionSpecEntry));
  335.         spec->num--;
  336.         } else {
  337.         j++;
  338.         }
  339.     }
  340.     fdiskSortPartitionSpec( spec );
  341.     return FDISK_SUCCESS;
  342. }
  343.  
  344. /* given a hard drive with original partitions, add to partition spec */
  345. /* any user added partition specs are untouched                       */
  346. int fdiskSetupPartitionSpec( HardDrive **hdarr, unsigned int numhd,
  347.                  PartitionSpec *spec ) {
  348.     unsigned int first, last, i, j;
  349.     int          status;
  350.     Partition    *p;
  351.     char         *name;
  352.     
  353.     /* make sure there are any partitions to process */
  354.     status = 0;
  355.     for (i=0; i<numhd; i++)
  356.     if (fdiskFirstPartition(hdarr[i], &first ) == FDISK_SUCCESS) {
  357.         status = 1;
  358.         break;
  359.     }
  360.  
  361.     /* no partitions to process */
  362.     if (status == 0)
  363.     return FDISK_SUCCESS;
  364.     
  365.     /* go thru all drives and insert all pre-existing partitions */
  366.     for (i=0; i<numhd; i++) {
  367.     if (fdiskFirstPartition(hdarr[i], &first ) != FDISK_SUCCESS) 
  368.         continue;
  369.     fdiskLastPartition(hdarr[i], &last );
  370.     /* insert existing partitions using a temporary name */
  371.     for (j=first; j <= last; j++) {
  372.         status = fdiskGetAttrPartition(hdarr[i], j, &p);
  373.         if (status == FDISK_SUCCESS) {
  374.         if (p->type.current == LINUX_SWAP_PARTITION)
  375.             fdiskMakeSwapSpecName( spec, &name);
  376.         else {
  377.             name = malloc(16);
  378.             sprintf(name, "Exist%03d%03d", hdarr[i]->num, j);
  379.         }
  380.         fdiskInsertPartitionSpec( spec, name, p, REQUEST_ORIGINAL );
  381.         free(name);
  382.         free(p);
  383.         }
  384.     }
  385.     }
  386.  
  387.     fdiskSortPartitionSpec( spec );
  388.     
  389.     return FDISK_SUCCESS;
  390. }
  391.         
  392.  
  393. /* return specification based on mount point */
  394. int fdiskReturnPartitionSpec( PartitionSpec *spec,
  395.                   char          *name,
  396.                   Partition     **p) {
  397.  
  398.     unsigned int j, found;
  399.  
  400.     found = 0;
  401.     for (j=0; j<spec->num && !found;)
  402.     if (!strcmp(spec->entry[j].name, name))
  403.         found = 1;
  404.     else
  405.         j++;
  406.  
  407.     if (!found)
  408.     return FDISK_ERR_BADNUM;
  409.     else {
  410.     *p = (Partition *) malloc( sizeof(Partition) );
  411.     memcpy(*p, &spec->entry[j].partition, sizeof(Partition));
  412.     return FDISK_SUCCESS;
  413.     }
  414. }
  415.  
  416. /* rename a spec */
  417. int fdiskRenamePartitionSpec( PartitionSpec *spec,
  418.                   char          *name,
  419.                   char          *newname ) {
  420.     unsigned int j, found;
  421.  
  422.     found = 0;
  423.     for (j=0; j<spec->num && !found;)
  424.     if (!strcmp(spec->entry[j].name, name))
  425.         found = 1;
  426.     else
  427.         j++;
  428.  
  429.     if (!found)
  430.     return FDISK_ERR_BADNUM;
  431.     else {
  432.     free(spec->entry[j].name);
  433.     spec->entry[j].name = strdup(newname);
  434.     return FDISK_SUCCESS;
  435.     }
  436. }
  437.     
  438. /* return specification based on mount point */
  439. int fdiskModifyPartitionSpec( PartitionSpec *spec,
  440.                    char          *name,
  441.                    Partition     *p,
  442.                    unsigned int  status) {
  443.  
  444.     unsigned int j, found;
  445.  
  446.     found = 0;
  447.     for (j=0; j<spec->num && !found;)
  448.     if (!strcmp(spec->entry[j].name, name))
  449.         found = 1;
  450.     else
  451.         j++;
  452.  
  453.     if (!found)
  454.     return FDISK_ERR_BADNUM;
  455.     else {
  456.     /* dont change immutable partitions! */
  457.     if (p->immutable)
  458.         return FDISK_ERR_BADNUM;
  459.     else {
  460.         memcpy(&spec->entry[j].partition, p, sizeof(Partition));
  461.         spec->entry[j].status = status;
  462.         fdiskSortPartitionSpec( spec );
  463.         return FDISK_SUCCESS;
  464.     }
  465.     }
  466. }
  467.  
  468. /* make a unique name for a partition spec */
  469. int fdiskMakeUniqSpecName( PartitionSpec *spec, char *base, char **name ) {
  470.     int  i;
  471.     char *s;
  472.     unsigned int j;
  473.  
  474.     s = malloc(4+strlen(base));
  475.     for (i=0; i < 1000; i++) {
  476.     snprintf(s, 4+strlen(base), "%s%03d", base, i);
  477.     if (fdiskIndexPartitionSpec(spec, s, &j) != FDISK_SUCCESS)
  478.         break;
  479.     }
  480.     
  481.     *name = s;
  482.     return FDISK_SUCCESS;
  483. }
  484.  
  485.  
  486. /* make a unique name for a swap partition spec */
  487. int fdiskMakeSwapSpecName( PartitionSpec *spec, char **name ) {
  488.     int rc;
  489.     
  490.     rc = fdiskMakeUniqSpecName( spec, "Swap", name );
  491.     return rc;
  492. }
  493.     
  494.