home *** CD-ROM | disk | FTP | other *** search
/ PC Plus SuperCD (UK) 1999 May / pcp151c.iso / misc / src / install / libfdisk / rawio.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-10-02  |  6.9 KB  |  242 lines

  1. /* Raw disk i/o handling the partition tables on a hard drive       */
  2. /*                                                                  */
  3. /* Michael Fulbright <msf@redhat.com>  June 1997                    */
  4. /* Recoded to use new HardDrive structure                           */
  5.  
  6. #include <stdio.h>
  7. #include <unistd.h>
  8. #include <string.h>
  9. #include <fcntl.h>
  10. #include <malloc.h>
  11. #include <linux/fs.h>
  12. #include <sys/types.h>
  13. #include <sys/ioctl.h>
  14. #include "libfdisk.h"
  15. #ifdef __sparc__
  16. #include "sunlabel.h"
  17. #endif
  18.  
  19. long long llseek(int fd, long long offset,  int whence);
  20.  
  21.  
  22. int fdiskSectorToCHS( HardDrive *hd, unsigned int start,
  23.               unsigned int *c, unsigned int *h, unsigned int *s ) {
  24.  
  25.     *s = start % hd->geom.sectors + 1;
  26.     start /= hd->geom.sectors;
  27.     *h = start % hd->geom.heads;
  28.     start /= hd->geom.heads;
  29.     *c = start;
  30.     return FDISK_SUCCESS;
  31. }
  32.  
  33. /* move absolute sector position to the next highest cylinder boundary */
  34. /* HOWEVER, if we are within 2 heads of the previous cylinder we dont  */
  35. /* round up. This is how partitions with partition tables at the front */
  36. /* work (like LP).                                                     */
  37. int fdiskRoundStartToCylinder( HardDrive *hd, unsigned int *start ) {
  38.     unsigned int m;
  39.  
  40.     m = *start % (hd->geom.heads*hd->geom.sectors);
  41.     if (m > 2*hd->geom.sectors)
  42.     *start += (hd->geom.heads*hd->geom.sectors) - m;
  43.     
  44.     return FDISK_SUCCESS;
  45. }
  46.  
  47. /* move absolute sector position to the next lowest  cylinder boundary */
  48. int fdiskRoundEndToCylinder( HardDrive *hd, unsigned int *end ) {
  49.     unsigned int m;
  50.  
  51.     if (*end > hd->geom.heads*hd->geom.sectors) {
  52.     m = (*end % (hd->geom.heads*hd->geom.sectors));
  53.     if (m != hd->geom.heads*hd->geom.sectors-1)
  54.         *end -= m+1;
  55.     }
  56.     return FDISK_SUCCESS;
  57. }
  58.  
  59.  
  60.     
  61. /* these routes return < 0 on system error, errno has error */
  62. /*                       0 on success                       */
  63. /*                     > 0 on other errors                  */
  64. /* open device dev, returns allocated HardDrive structure */
  65. /* num is the booting numbers, ie, IDE drives come first, then SCSI, etc */
  66. /* up to caller to set values                                            */
  67. int fdiskOpenDevice(char *dev, unsigned int num, HardDrive **hddev) {
  68.     int fd;
  69.     int i;
  70.     HDGeometry g;
  71.     HardDrive *hd;
  72. #ifdef __sparc__
  73.     struct sun_disklabel label;
  74.     unsigned short *ush;
  75.     int csum;
  76. #endif
  77.  
  78.     *hddev = NULL;
  79.     
  80.     /* try to determine everything, if it works then we return */
  81.     /* filled in hd_device struct                              */
  82.     fd = open(dev, O_RDWR);
  83.     if (fd < 0)
  84.     return -1;
  85.  
  86.     if (ioctl(fd, HDIO_GETGEO, &g)) {
  87.         close(fd);
  88.     return -1;
  89.     }
  90.  
  91.     hd = (HardDrive *) malloc(sizeof(HardDrive));
  92.     hd->fd = fd;
  93.     strncpy(hd->name, dev, MAX_HD_NAMELEN);
  94.     memcpy(&hd->geom, &g, sizeof(HDGeometry));
  95.  
  96. #ifdef __sparc__
  97.  
  98.     /* XXXXXXXXXXXX                                            */
  99.     /* We can't trust the geometry from the ioctl on the sun   */
  100.     /* Use the geometry in the label instead                   */
  101.     /* This is pretty gross, especially error handling.        */
  102.     /* I don't feel that bad about returning -1 if it can't    */
  103.     /* read the sunlabel because it's in the first 512 bytes   */
  104.     /* so other stuff would fail later.                        */
  105.  
  106.     if (lseek(hd->fd, 0, SEEK_SET)) return -1;
  107.     if (read(hd->fd, &label, sizeof(label)) != sizeof(label)) return -1;
  108.     if (label.magic == SUN_LABEL_MAGIC) {
  109.         ush = ((unsigned short *) (&label + 1)) - 1;
  110.         for (csum = 0; ush >= (unsigned short *) &label;) csum ^= *ush--;
  111.         /*  Checksum != 0, checksum fails */
  112.         if (!csum) {
  113.         hd->geom.heads = label.ntrks;
  114.         hd->geom.cylinders = label.ncyl;
  115.            hd->geom.sectors = label.nsect;
  116.         } else {
  117.         close(fd);
  118.         free(hd);
  119.             return FDISK_ERR_CORRUPT;
  120.     }
  121.     } else {
  122.         close(fd);
  123.     free(hd);
  124.         return FDISK_ERR_CORRUPT;
  125.     }
  126.  
  127. #endif
  128.  
  129.     hd->totalsectors = hd->geom.sectors*hd->geom.heads*hd->geom.cylinders;
  130.     
  131.     *hddev = hd;
  132.     
  133.     /* zero out the partition table */
  134.     memset(&hd->table, 0, (MAX_PARTITIONS+1)*sizeof(Partition));
  135.     memset(&hd->eptable, 0, (MAX_PARTITIONS+1)*sizeof(Partition));
  136.     
  137.     /* we initialize the available/unavailable stuff when we read the
  138.        table */
  139.     
  140.     /* no PEP yet! */
  141.     hd->pep = 0;
  142.     
  143.     hd->num = num;
  144.     return FDISK_SUCCESS;
  145. }
  146.  
  147. /* Note - no error checking (yet) */
  148. int fdiskCloseDevice(HardDrive *hddev) {
  149.     close(hddev->fd);
  150.     free(hddev);
  151.     return FDISK_SUCCESS;
  152. }
  153.  
  154. /* cause kernel to re-read partition table */
  155. int fdiskReReadPartitions( HardDrive *hd ) {
  156.     return ioctl(hd->fd, BLKRRPART);
  157. }
  158.  
  159. /* these two routines read/write a Partition Table at the location */
  160. /* specified by the caller                                         */
  161. /* returns a value of FDISK_ERR_BADNUM if no table found at loc    */
  162. int fdiskReadPartitionTable(HardDrive *hddev, unsigned int loc,
  163.                  RawPartitionTable **pt ) {
  164.     int i;
  165.     long long offset;
  166.     unsigned int magic;
  167.     unsigned char b[SECTORSIZE];
  168.     RawPartitionTable *t;
  169.  
  170.     offset = (long long) loc * (long long) SECTORSIZE;
  171.     if (llseek(hddev->fd, offset, SEEK_SET) < 0)
  172.     return -1;
  173.  
  174.     if (read(hddev->fd, b, SECTORSIZE) != SECTORSIZE)
  175.     return -1;
  176.  
  177.     /* see if we really got something */
  178.     magic = b[PARTMAGOFF]*256 + b[PARTMAGOFF+1];
  179.     if (magic != PARTMAGIC)
  180.     return FDISK_ERR_BADMAGIC;
  181.  
  182.     t = (RawPartitionTable *) malloc(sizeof(RawPartitionTable));
  183.     
  184.     for (i=0; i<4; i++)
  185.     memcpy(  &t->entry[i],
  186.          b+PARTTBLOFF+i*sizeof(RawPartition),
  187.          sizeof(RawPartition));
  188.     *pt = t;
  189.     return FDISK_SUCCESS;
  190. }
  191.  
  192. /* we read the current sector and modify it, in case there is some */
  193. /* boot code there we need to preserve                             */
  194. /* not sure this is what we want to ALWAYS do                      */
  195. /* accepts location as the SECTOR OFFSET!!!                        */
  196. int fdiskWritePartitionTable(HardDrive *hddev, unsigned int loc,
  197.                  RawPartitionTable *pt ) {
  198.     int i;
  199.     long long offset;
  200.     unsigned char b[SECTORSIZE];
  201.  
  202. #ifdef REALLY_DEBUG
  203.     printf("seeking to %d and writing partition table\n",loc);
  204.     print_raw_partition_table(0, pt);
  205. #endif
  206.     offset = (long long) loc * (long long) SECTORSIZE;
  207.     if (llseek(hddev->fd, offset, SEEK_SET) < 0)
  208.     return -1;
  209.  
  210.     if (read(hddev->fd, b, SECTORSIZE) != SECTORSIZE)
  211.     return -1;
  212.  
  213.     /* move partition data into the sector */
  214.     for (i=0; i<4; i++)
  215.     memcpy(  b+PARTTBLOFF+i*sizeof(RawPartition),
  216.          &pt->entry[i],
  217.          sizeof(RawPartition));
  218.  
  219.     /* stick the magic on there */
  220.     b[PARTMAGOFF   ] = PARTMAGIC >> 8;
  221.     b[PARTMAGOFF+1 ] = PARTMAGIC & 0xff;
  222.     
  223.     if (llseek(hddev->fd, offset, SEEK_SET) < 0)
  224.     return -1;
  225.  
  226.     if (write(hddev->fd, b, SECTORSIZE) != SECTORSIZE)
  227.     return -1;
  228.  
  229.     return FDISK_SUCCESS;
  230. }
  231.  
  232.  
  233. int fdiskZeroMBR( HardDrive *hddev ) {
  234.     RawPartitionTable pt;
  235.  
  236.     memset(&pt, 0, sizeof(RawPartitionTable));
  237.  
  238.     return fdiskWritePartitionTable( hddev, 0, &pt );
  239. }
  240.         
  241.  
  242.