home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 February / CHIP_2_98.iso / misc / src / install / libfdisk / rawio.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-09-17  |  6.0 KB  |  216 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.  
  16.  
  17. long long llseek(int fd, long long offset,  int whence);
  18.  
  19.  
  20. int fdiskSectorToCHS( HardDrive *hd, unsigned int start,
  21.               unsigned int *c, unsigned int *h, unsigned int *s ) {
  22.  
  23.     *s = start % hd->geom.sectors + 1;
  24.     start /= hd->geom.sectors;
  25.     *h = start % hd->geom.heads;
  26.     start /= hd->geom.heads;
  27.     *c = start;
  28.     return FDISK_SUCCESS;
  29. }
  30.  
  31. /* move absolute sector position to the next highest cylinder boundary */
  32. /* HOWEVER, if we are within 2 heads of the previous cylinder we dont  */
  33. /* round up. This is how partitions with partition tables at the front */
  34. /* work (like LP).                                                     */
  35. int fdiskRoundStartToCylinder( HardDrive *hd, unsigned int *start ) {
  36.     unsigned int m;
  37.  
  38.     m = *start % (hd->geom.heads*hd->geom.sectors);
  39.     if (m > 2*hd->geom.sectors)
  40.     *start += (hd->geom.heads*hd->geom.sectors) - m;
  41.     
  42.     return FDISK_SUCCESS;
  43. }
  44.  
  45. /* move absolute sector position to the next lowest  cylinder boundary */
  46. int fdiskRoundEndToCylinder( HardDrive *hd, unsigned int *end ) {
  47.     unsigned int m;
  48.  
  49.     if (*end > hd->geom.heads*hd->geom.sectors) {
  50.     m = (*end % (hd->geom.heads*hd->geom.sectors));
  51.     if (m != hd->geom.heads*hd->geom.sectors-1)
  52.         *end -= m+1;
  53.     }
  54.     return FDISK_SUCCESS;
  55. }
  56.  
  57.  
  58.     
  59. /* these routes return < 0 on system error, errno has error */
  60. /*                       0 on success                       */
  61. /*                     > 0 on other errors                  */
  62. /* open device dev, returns allocated HardDrive structure */
  63. /* num is the booting numbers, ie, IDE drives come first, then SCSI, etc */
  64. /* up to caller to set values                                            */
  65. int fdiskOpenDevice(char *dev, unsigned int num, HardDrive **hddev) {
  66.     int fd;
  67.     int i;
  68.     HDGeometry g;
  69.     HardDrive *hd;
  70.     
  71.     *hddev = NULL;
  72.     
  73.     /* try to determine everything, if it works then we return */
  74.     /* filled in hd_device struct                              */
  75.     fd = open(dev, O_RDWR);
  76.     if (fd < 0)
  77.     return -1;
  78.  
  79.     if (ioctl(fd, HDIO_GETGEO, &g))
  80.     return -1;
  81.     
  82.     hd = (HardDrive *) malloc(sizeof(HardDrive));
  83.     hd->fd = fd;
  84.     strncpy(hd->name, dev, MAX_HD_NAMELEN);
  85.     memcpy(&hd->geom, &g, sizeof(HDGeometry));
  86.     hd->totalsectors = hd->geom.sectors*hd->geom.heads*hd->geom.cylinders;
  87.     
  88.     *hddev = hd;
  89.  
  90.     /* zero out the partition table */
  91.     memset(&hd->table, 0, (MAX_PARTITIONS+1)*sizeof(Partition));
  92.     memset(&hd->eptable, 0, (MAX_PARTITIONS+1)*sizeof(Partition));
  93.  
  94.     /* set all primaries as available and all extended as unavailable */
  95.     for (i=1; i <= MAX_PARTITIONS; i++) {
  96.     if (i < 5)
  97.         hd->table[i].status = AVAILABLE;
  98.     else
  99.         hd->table[i].status = UNAVAILABLE;
  100.  
  101.     /* set all eptable entries as UNAVAILABLE */
  102.     hd->eptable[i].status = UNAVAILABLE;
  103.     }
  104.  
  105.     /* no PEP yet! */
  106.     hd->pep = 0;
  107.  
  108.     hd->num = num;
  109.     
  110.     return FDISK_SUCCESS;
  111. }
  112.  
  113. /* Note - no error checking (yet) */
  114. int fdiskCloseDevice(HardDrive *hddev) {
  115.     close(hddev->fd);
  116.     free(hddev);
  117.     return FDISK_SUCCESS;
  118. }
  119.  
  120. /* cause kernel to re-read partition table */
  121. int fdiskReReadPartitions( HardDrive *hd ) {
  122.     return ioctl(hd->fd, BLKRRPART);
  123. }
  124.  
  125. /* these two routines read/write a Partition Table at the location */
  126. /* specified by the caller                                         */
  127. /* returns a value of FDISK_ERR_BADNUM if no table found at loc    */
  128. int fdiskReadPartitionTable(HardDrive *hddev, unsigned int loc,
  129.                  RawPartitionTable **pt ) {
  130.     int i;
  131.     long long offset;
  132.     unsigned int magic;
  133.     unsigned char b[SECTORSIZE];
  134.     RawPartitionTable *t;
  135.  
  136.     offset = loc * SECTORSIZE;
  137.     if (llseek(hddev->fd, offset, SEEK_SET) < 0)
  138.     return -1;
  139.  
  140.     if (read(hddev->fd, b, SECTORSIZE) != SECTORSIZE)
  141.     return -1;
  142.  
  143.     /* see if we really got something */
  144.     magic = b[PARTMAGOFF]*256 + b[PARTMAGOFF+1];
  145.     if (magic != PARTMAGIC)
  146.     return FDISK_ERR_BADMAGIC;
  147.  
  148.     t = (RawPartitionTable *) malloc(sizeof(RawPartitionTable));
  149.     
  150.     for (i=0; i<4; i++)
  151.     memcpy(  &t->entry[i],
  152.          b+PARTTBLOFF+i*sizeof(RawPartition),
  153.          sizeof(RawPartition));
  154.     *pt = t;
  155.     return FDISK_SUCCESS;
  156. }
  157.  
  158. /* we read the current sector and modify it, in case there is some */
  159. /* boot code there we need to preserve                             */
  160. /* not sure this is what we want to ALWAYS do                      */
  161. /* accepts location as the SECTOR OFFSET!!!                        */
  162. int fdiskWritePartitionTable(HardDrive *hddev, unsigned int loc,
  163.                  RawPartitionTable *pt ) {
  164.     int i;
  165.     long long offset;
  166.     unsigned char b[SECTORSIZE];
  167.  
  168. #ifdef REALLY_DEBUG
  169.     printf("seeking to %d and writing partition table\n",loc);
  170.     print_raw_partition_table(0, pt);
  171. #endif
  172.     offset = loc * SECTORSIZE;
  173.     if (llseek(hddev->fd, offset, SEEK_SET) < 0)
  174.     return -1;
  175.  
  176.     if (read(hddev->fd, b, SECTORSIZE) != SECTORSIZE)
  177.     return -1;
  178.  
  179.     /* move partition data into the sector */
  180.     for (i=0; i<4; i++)
  181.     memcpy(  b+PARTTBLOFF+i*sizeof(RawPartition),
  182.          &pt->entry[i],
  183.          sizeof(RawPartition));
  184.  
  185.     /* stick the magic on there */
  186.     b[PARTMAGOFF   ] = PARTMAGIC >> 8;
  187.     b[PARTMAGOFF+1 ] = PARTMAGIC & 0xff;
  188.     
  189.     if (llseek(hddev->fd, offset, SEEK_SET) < 0)
  190.     return -1;
  191.  
  192.     if (write(hddev->fd, b, SECTORSIZE) != SECTORSIZE)
  193.     return -1;
  194.  
  195.     return FDISK_SUCCESS;
  196. }
  197.  
  198.  
  199. int fdiskReadMBR( HardDrive *hddev, RawPartitionTable **pt ) {
  200.     return fdiskReadPartitionTable(hddev, 0L, pt );
  201. }
  202.  
  203. int fdiskWriteMBR( HardDrive *hddev, RawPartitionTable *pt ) {
  204.     return fdiskWritePartitionTable( hddev, 0L, pt );
  205. }
  206.  
  207. int fdiskZeroMBR( HardDrive *hddev ) {
  208.     RawPartitionTable pt;
  209.  
  210.     memset(&pt, 0, sizeof(RawPartitionTable));
  211.  
  212.     return fdiskWriteMBR( hddev, &pt );
  213. }
  214.         
  215.  
  216.