home *** CD-ROM | disk | FTP | other *** search
- /* Raw disk i/o handling the partition tables on a hard drive */
- /* */
- /* Michael Fulbright <msf@redhat.com> June 1997 */
- /* Recoded to use new HardDrive structure */
-
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
- #include <fcntl.h>
- #include <malloc.h>
- #include <linux/fs.h>
- #include <sys/types.h>
- #include <sys/ioctl.h>
- #include "libfdisk.h"
-
-
- long long llseek(int fd, long long offset, int whence);
-
-
- int fdiskSectorToCHS( HardDrive *hd, unsigned int start,
- unsigned int *c, unsigned int *h, unsigned int *s ) {
-
- *s = start % hd->geom.sectors + 1;
- start /= hd->geom.sectors;
- *h = start % hd->geom.heads;
- start /= hd->geom.heads;
- *c = start;
- return FDISK_SUCCESS;
- }
-
- /* move absolute sector position to the next highest cylinder boundary */
- /* HOWEVER, if we are within 2 heads of the previous cylinder we dont */
- /* round up. This is how partitions with partition tables at the front */
- /* work (like LP). */
- int fdiskRoundStartToCylinder( HardDrive *hd, unsigned int *start ) {
- unsigned int m;
-
- m = *start % (hd->geom.heads*hd->geom.sectors);
- if (m > 2*hd->geom.sectors)
- *start += (hd->geom.heads*hd->geom.sectors) - m;
-
- return FDISK_SUCCESS;
- }
-
- /* move absolute sector position to the next lowest cylinder boundary */
- int fdiskRoundEndToCylinder( HardDrive *hd, unsigned int *end ) {
- unsigned int m;
-
- if (*end > hd->geom.heads*hd->geom.sectors) {
- m = (*end % (hd->geom.heads*hd->geom.sectors));
- if (m != hd->geom.heads*hd->geom.sectors-1)
- *end -= m+1;
- }
- return FDISK_SUCCESS;
- }
-
-
-
- /* these routes return < 0 on system error, errno has error */
- /* 0 on success */
- /* > 0 on other errors */
- /* open device dev, returns allocated HardDrive structure */
- /* num is the booting numbers, ie, IDE drives come first, then SCSI, etc */
- /* up to caller to set values */
- int fdiskOpenDevice(char *dev, unsigned int num, HardDrive **hddev) {
- int fd;
- int i;
- HDGeometry g;
- HardDrive *hd;
-
- *hddev = NULL;
-
- /* try to determine everything, if it works then we return */
- /* filled in hd_device struct */
- fd = open(dev, O_RDWR);
- if (fd < 0)
- return -1;
-
- if (ioctl(fd, HDIO_GETGEO, &g))
- return -1;
-
- hd = (HardDrive *) malloc(sizeof(HardDrive));
- hd->fd = fd;
- strncpy(hd->name, dev, MAX_HD_NAMELEN);
- memcpy(&hd->geom, &g, sizeof(HDGeometry));
- hd->totalsectors = hd->geom.sectors*hd->geom.heads*hd->geom.cylinders;
-
- *hddev = hd;
-
- /* zero out the partition table */
- memset(&hd->table, 0, (MAX_PARTITIONS+1)*sizeof(Partition));
- memset(&hd->eptable, 0, (MAX_PARTITIONS+1)*sizeof(Partition));
-
- /* set all primaries as available and all extended as unavailable */
- for (i=1; i <= MAX_PARTITIONS; i++) {
- if (i < 5)
- hd->table[i].status = AVAILABLE;
- else
- hd->table[i].status = UNAVAILABLE;
-
- /* set all eptable entries as UNAVAILABLE */
- hd->eptable[i].status = UNAVAILABLE;
- }
-
- /* no PEP yet! */
- hd->pep = 0;
-
- hd->num = num;
-
- return FDISK_SUCCESS;
- }
-
- /* Note - no error checking (yet) */
- int fdiskCloseDevice(HardDrive *hddev) {
- close(hddev->fd);
- free(hddev);
- return FDISK_SUCCESS;
- }
-
- /* cause kernel to re-read partition table */
- int fdiskReReadPartitions( HardDrive *hd ) {
- return ioctl(hd->fd, BLKRRPART);
- }
-
- /* these two routines read/write a Partition Table at the location */
- /* specified by the caller */
- /* returns a value of FDISK_ERR_BADNUM if no table found at loc */
- int fdiskReadPartitionTable(HardDrive *hddev, unsigned int loc,
- RawPartitionTable **pt ) {
- int i;
- long long offset;
- unsigned int magic;
- unsigned char b[SECTORSIZE];
- RawPartitionTable *t;
-
- offset = loc * SECTORSIZE;
- if (llseek(hddev->fd, offset, SEEK_SET) < 0)
- return -1;
-
- if (read(hddev->fd, b, SECTORSIZE) != SECTORSIZE)
- return -1;
-
- /* see if we really got something */
- magic = b[PARTMAGOFF]*256 + b[PARTMAGOFF+1];
- if (magic != PARTMAGIC)
- return FDISK_ERR_BADMAGIC;
-
- t = (RawPartitionTable *) malloc(sizeof(RawPartitionTable));
-
- for (i=0; i<4; i++)
- memcpy( &t->entry[i],
- b+PARTTBLOFF+i*sizeof(RawPartition),
- sizeof(RawPartition));
- *pt = t;
- return FDISK_SUCCESS;
- }
-
- /* we read the current sector and modify it, in case there is some */
- /* boot code there we need to preserve */
- /* not sure this is what we want to ALWAYS do */
- /* accepts location as the SECTOR OFFSET!!! */
- int fdiskWritePartitionTable(HardDrive *hddev, unsigned int loc,
- RawPartitionTable *pt ) {
- int i;
- long long offset;
- unsigned char b[SECTORSIZE];
-
- #ifdef REALLY_DEBUG
- printf("seeking to %d and writing partition table\n",loc);
- print_raw_partition_table(0, pt);
- #endif
- offset = loc * SECTORSIZE;
- if (llseek(hddev->fd, offset, SEEK_SET) < 0)
- return -1;
-
- if (read(hddev->fd, b, SECTORSIZE) != SECTORSIZE)
- return -1;
-
- /* move partition data into the sector */
- for (i=0; i<4; i++)
- memcpy( b+PARTTBLOFF+i*sizeof(RawPartition),
- &pt->entry[i],
- sizeof(RawPartition));
-
- /* stick the magic on there */
- b[PARTMAGOFF ] = PARTMAGIC >> 8;
- b[PARTMAGOFF+1 ] = PARTMAGIC & 0xff;
-
- if (llseek(hddev->fd, offset, SEEK_SET) < 0)
- return -1;
-
- if (write(hddev->fd, b, SECTORSIZE) != SECTORSIZE)
- return -1;
-
- return FDISK_SUCCESS;
- }
-
-
- int fdiskReadMBR( HardDrive *hddev, RawPartitionTable **pt ) {
- return fdiskReadPartitionTable(hddev, 0L, pt );
- }
-
- int fdiskWriteMBR( HardDrive *hddev, RawPartitionTable *pt ) {
- return fdiskWritePartitionTable( hddev, 0L, pt );
- }
-
- int fdiskZeroMBR( HardDrive *hddev ) {
- RawPartitionTable pt;
-
- memset(&pt, 0, sizeof(RawPartitionTable));
-
- return fdiskWriteMBR( hddev, &pt );
- }
-
-
-