Exemple #1
0
/*
 * returns the volume label key = the label identifier
 * right after it has been translated to ASCII
 */
char *
vtoc_volume_label_get_label (volume_label_t *vlabel, char *lbl)
{
	PDEBUG
	vtoc_ebcdic_dec(vlabel->vollbl, lbl, 4);

	return lbl;
}
Exemple #2
0
/*
 * returns the volume serial number right after it is translated
 * to ASCII
 */
char *
vtoc_volume_label_get_volser (volume_label_t *vlabel, char *volser)
{
	PDEBUG
	vtoc_ebcdic_dec(vlabel->volid, volser, VOLSER_LENGTH);

	return volser;
}
Exemple #3
0
static int
dasd_update_type (const PedDisk* disk, struct fdasd_anchor *anchor,
		  partition_info_t *part_info[USABLE_PARTITIONS])
{
	PedPartition* part;
	LinuxSpecific* arch_specific;
	DasdDiskSpecific* disk_specific;

	arch_specific = LINUX_SPECIFIC(disk->dev);
	disk_specific = disk->disk_specific;

	PDEBUG;

	unsigned int i;
	for (i = 1; i <= USABLE_PARTITIONS; i++) {
		partition_info_t *p;
		char *ch = NULL;
		DasdPartitionData* dasd_data;

		PDEBUG;

		part = ped_disk_get_partition(disk, i);
		if (!part)
			continue;

		PDEBUG;

		dasd_data = part->disk_specific;
		p = part_info[i - 1];

		if (!p ) {
			PDEBUG;
			continue;
		}

		vtoc_ebcdic_dec(p->f1->DS1DSNAM, p->f1->DS1DSNAM, 44);
		ch = strstr(p->f1->DS1DSNAM, "PART");

		PDEBUG;
		if (ch == NULL) {
			vtoc_ebcdic_enc(p->f1->DS1DSNAM, p->f1->DS1DSNAM, 44);
			PDEBUG;
			continue;
		}

		ch += 9;

		switch (dasd_data->system) {
			case PARTITION_LINUX_LVM:
				PDEBUG;
				strncpy(ch, PART_TYPE_LVM, 6);
				break;
			case PARTITION_LINUX_RAID:
				PDEBUG;
				strncpy(ch, PART_TYPE_RAID, 6);
				break;
			case PARTITION_LINUX:
				PDEBUG;
				strncpy(ch, PART_TYPE_NATIVE, 6);
				break;
			case PARTITION_LINUX_SWAP:
				PDEBUG;
				strncpy(ch, PART_TYPE_SWAP, 6);
				break;
			default:
				PDEBUG;
				strncpy(ch, PART_TYPE_NATIVE, 6);
				break;
		}

		anchor->vtoc_changed++;
		vtoc_ebcdic_enc(p->f1->DS1DSNAM, p->f1->DS1DSNAM, 44);
	}

	return 1;
}
Exemple #4
0
int 
read_dasd_pt(int fd, struct slice all, struct slice *sp, int ns)
{
	int retval = -1;
	int blocksize;
	uint64_t disksize;
	uint64_t offset, size, fmt_size;
	dasd_information_t info;
	struct hd_geometry geo;
	char type[5] = {0,};
	volume_label_t vlabel;
	unsigned char *data = NULL;
	uint64_t blk;
	int fd_dasd = -1;
	struct stat sbuf;
	dev_t dev;
	char *devname;
	char pathname[256];

	if (fd < 0) {
		return -1;
	}

	if (fstat(fd, &sbuf) == -1) {
		return -1;
	}

	devname = dm_mapname(major(sbuf.st_rdev), minor(sbuf.st_rdev));

	if (devname != NULL) {
		/* We were passed a handle to a dm device.
		 * Get the first target and operate on that instead.
		 */
		if (!(dev = dm_get_first_dep(devname))) {
			free(devname);
			return -1;
		}
		free(devname);

		if ((unsigned int)major(dev) != 94) {
			/* Not a DASD */
			return -1;
		}

		/*
		 * Hard to believe, but there's no simple way to translate
		 * major/minor into an openable device file, so we have
		 * to create one for ourselves.
		 */
		
		sprintf(pathname, "/dev/.kpartx-node-%u-%u",
			(unsigned int)major(dev), (unsigned int)minor(dev));
		if ((fd_dasd = open(pathname, O_RDONLY)) == -1) {
			/* Devicenode does not exist. Try to create one */
			if (mknod(pathname, 0600 | S_IFBLK, dev) == -1) {
				/* Couldn't create a device node */
				return -1;
			}
			fd_dasd = open(pathname, O_RDONLY);
			/*
			 * The file will vanish when the last process (we)
			 * has ceased to access it.
			 */
			unlink(pathname);
		}
		if (!fd_dasd) {
			/* Couldn't open the device */
			return -1;
		}
	} else {
		fd_dasd = fd;
	}

	if (ioctl(fd_dasd, BIODASDINFO, (unsigned long)&info) != 0) {
		goto out;
	}

	if (ioctl(fd_dasd, HDIO_GETGEO, (unsigned long)&geo) != 0) {
		goto out;
	}

	if (ioctl(fd_dasd, BLKGETSIZE64, &disksize) != 0)
		goto out;
	disksize >>= 9;

	if (ioctl(fd_dasd, BLKSSZGET, &blocksize) != 0)
		goto out;

	if (blocksize < 512 || blocksize > 4096)
		goto out;

	/*
	 * Get volume label, extract name and type.
	 */

	if (!(data = (unsigned char *)malloc(blocksize)))
		goto out;


	if (lseek(fd_dasd, info.label_block * blocksize, SEEK_SET) == -1)
		goto out;
	if (read(fd_dasd, data, blocksize) == -1) {
		perror("read");
		goto out;
	}

	if ((!info.FBA_layout) && (!strcmp(info.type, "ECKD")))
		memcpy (&vlabel, data, sizeof(vlabel));
	else {
		bzero(&vlabel,4);
		memcpy (&vlabel.vollbl, data, sizeof(vlabel) - 4);
	}
	vtoc_ebcdic_dec(vlabel.vollbl, type, 4);

	/*
	 * Three different types: CMS1, VOL1 and LNX1/unlabeled
	 */
	if (strncmp(type, "CMS1", 4) == 0) {
		/*
		 * VM style CMS1 labeled disk
		 */
		label_ints_t *label = (label_ints_t *) &vlabel;

		blocksize = label[4];
		if (label[14] != 0) {
			/* disk is reserved minidisk */
			offset = label[14];
			size   = sectors512(label[8] - 1, blocksize);
		} else {
			offset = info.label_block + 1;
			size   = sectors512(label[8], blocksize);
		}
		sp[0].start = sectors512(offset, blocksize);
		sp[0].size  = size - sp[0].start;
		retval = 1;
	} else if ((strncmp(type, "VOL1", 4) == 0) &&
		(!info.FBA_layout) && (!strcmp(info.type, "ECKD"))) {
		/*
		 * New style VOL1 labeled disk
		 */
		int counter;

		/* get block number and read then go through format1 labels */
		blk = cchhb2blk(&vlabel.vtoc, &geo) + 1;
		counter = 0;
		if (lseek(fd_dasd, blk * blocksize, SEEK_SET) == -1)
			goto out;

		while (read(fd_dasd, data, blocksize) != -1) {
			format1_label_t f1;

			memcpy(&f1, data, sizeof(format1_label_t));

			/* skip FMT4 / FMT5 / FMT7 labels */
			if (EBCtoASC[f1.DS1FMTID] == '4'
			    || EBCtoASC[f1.DS1FMTID] == '5'
			    || EBCtoASC[f1.DS1FMTID] == '7'
			    || EBCtoASC[f1.DS1FMTID] == '9') {
			        blk++;
				continue;
			}

			/* only FMT1 and FMT8 valid at this point */
			if (EBCtoASC[f1.DS1FMTID] != '1' &&
			    EBCtoASC[f1.DS1FMTID] != '8')
				break;

			/* OK, we got valid partition data */
		        offset = cchh2blk(&f1.DS1EXT1.llimit, &geo);
			size  = cchh2blk(&f1.DS1EXT1.ulimit, &geo) -
				offset + geo.sectors;
			sp[counter].start = sectors512(offset, blocksize);
			sp[counter].size  = sectors512(size, blocksize);
			counter++;
			blk++;
		}
		retval = counter;
	} else {
		/*
		 * Old style LNX1 or unlabeled disk
		 */
		if (strncmp(type, "LNX1", 4) == 0) {
			if (vlabel.ldl_version == 0xf2) {
				fmt_size = sectors512(vlabel.formatted_blocks,
						      blocksize);
			} else if (!strcmp(info.type, "ECKD")) {
				/* formated w/o large volume support */
				fmt_size = geo.cylinders * geo.heads
					* geo.sectors * (blocksize >> 9);
			} else {
				/* old label and no usable disk geometry
				 * (e.g. DIAG) */
				fmt_size = disksize;
			}
			size = disksize;
			if (fmt_size < size)
				size = fmt_size;
		} else
Exemple #5
0
static int
dasd_read (PedDisk* disk)
{
	int i;
	char str[20];
	PedDevice* dev;
	PedPartition* part;
	PedFileSystemType *fs;
	PedSector start, end;
	PedConstraint* constraint_exact;
	partition_info_t *p;
	LinuxSpecific* arch_specific;
	DasdDiskSpecific* disk_specific;
	struct fdasd_anchor anchor;

	PDEBUG;

	PED_ASSERT (disk != NULL);
	PDEBUG;
	PED_ASSERT (disk->dev != NULL);
	PDEBUG;

	dev = disk->dev;

	arch_specific = LINUX_SPECIFIC(dev);
	disk_specific = disk->disk_specific;

	PDEBUG;

	fdasd_initialize_anchor(&anchor);

	if (fdasd_get_geometry(disk->dev, &anchor, arch_specific->fd) == 0)
                goto error_close_dev;

	disk_specific->label_block = anchor.label_block;

	if ((anchor.geo.cylinders * anchor.geo.heads) > BIG_DISK_SIZE)
		anchor.big_disk++;

	/* check dasd for labels and vtoc */
	if (fdasd_check_volume(&anchor, arch_specific->fd)) {
		DasdPartitionData* dasd_data;

		/* Kernel partitioning code will report 'implicit' partitions
		 * for non-CDL format DASDs even when there is no
		 * label/VTOC.  */
		if (anchor.FBA_layout == 0)
			goto error_close_dev;

		disk_specific->format_type = 1;

		/* Register implicit partition */
		ped_disk_delete_all (disk);

		start = (PedSector) arch_specific->real_sector_size /
			(PedSector) disk->dev->sector_size *
			(PedSector) (anchor.label_block + 1);
		end = disk->dev->length - 1;
		part = ped_partition_new (disk, PED_PARTITION_NORMAL, NULL,
					  start, end);
		if (!part)
			goto error_close_dev;

		part->num = 1;
		part->fs_type = ped_file_system_probe (&part->geom);
		dasd_data = part->disk_specific;
		dasd_data->raid = 0;
		dasd_data->lvm = 0;
		dasd_data->type = 0;

		if (!ped_disk_add_partition (disk, part, NULL))
			goto error_close_dev;

		fdasd_cleanup(&anchor);

		return 1;
	}

	/* Save volume label (read by fdasd_check_volume) for writing */
	memcpy(&disk_specific->vlabel, anchor.vlabel, sizeof(volume_label_t));

	ped_disk_delete_all (disk);

	bool is_ldl = strncmp(anchor.vlabel->volkey,
			 vtoc_ebcdic_enc("LNX1", str, 4), 4) == 0;
	bool is_cms = strncmp(anchor.vlabel->volkey,
			 vtoc_ebcdic_enc("CMS1", str, 4), 4) == 0;
	if (is_ldl || is_cms) {
		DasdPartitionData* dasd_data;

		union vollabel {
			volume_label_t ldl;
			cms_volume_label_t cms;
		};
		union vollabel *cms_ptr1 = (union vollabel *) anchor.vlabel;
		cms_volume_label_t *cms_ptr = &cms_ptr1->cms;
		volume_label_t *ldl_ptr = &cms_ptr1->ldl;
		int partition_start_block;

		disk_specific->format_type = 1;

		if (is_cms && cms_ptr->usable_count >= cms_ptr->block_count)
			partition_start_block = 2;   /* FBA DASD */
		else
			partition_start_block = 3;   /* CKD DASD */

		if (is_ldl)
			start = (long long) arch_specific->real_sector_size
				/ (long long) disk->dev->sector_size
				* (long long) partition_start_block;
		else if (cms_ptr->disk_offset == 0)
			start = (long long) cms_ptr->block_size
				/ (long long) disk->dev->sector_size
				* (long long) partition_start_block;
		else
			start = (long long) cms_ptr->block_size
				/ (long long) disk->dev->sector_size
				* (long long) cms_ptr->disk_offset;

		if (is_ldl)
		   if (ldl_ptr->ldl_version >= 0xf2)
		      end = (long long) arch_specific->real_sector_size
			    / (long long) disk->dev->sector_size
			    * (long long) ldl_ptr->formatted_blocks - 1;
		   else
		      end = disk->dev->length - 1;
		else
		   if (cms_ptr->disk_offset == 0)
		      end = (long long) cms_ptr->block_size
			    / (long long) disk->dev->sector_size
			    * (long long) cms_ptr->block_count - 1;
		   else
		      /*
			 Frankly, I do not understand why the last block
			 of the CMS reserved file is not included in the
			 partition; but this is the algorithm used by the
			 Linux kernel.  See fs/partitions/ibm.c in the
			 Linux kernel source code.
		      */
		      end = (long long) cms_ptr->block_size
			    / (long long) disk->dev->sector_size
			    * (long long) (cms_ptr->block_count - 1) - 1;

		part = ped_partition_new (disk, PED_PARTITION_NORMAL, NULL, start, end);
		if (!part)
			goto error_close_dev;

		part->num = 1;
		part->fs_type = ped_file_system_probe (&part->geom);
		dasd_data = part->disk_specific;
		dasd_data->raid = 0;
		dasd_data->lvm = 0;
		dasd_data->type = 0;

		if (!ped_disk_add_partition (disk, part, NULL))
			goto error_close_dev;

		fdasd_cleanup(&anchor);

		return 1;
	}

	/* CDL format, newer */
	disk_specific->format_type = 2;

	p = anchor.first;
	PDEBUG;

	for (i = 1 ; i <= USABLE_PARTITIONS; i++) {
		char *ch = p->f1->DS1DSNAM;
		DasdPartitionData* dasd_data;


		if (p->used != 0x01)
			continue;

        PDEBUG;

		start = (long long)(long long) p->start_trk
				* (long long) disk->dev->hw_geom.sectors
				* (long long) arch_specific->real_sector_size
				/ (long long) disk->dev->sector_size;
		end   = (long long)((long long) p->end_trk + 1)
				* (long long) disk->dev->hw_geom.sectors
				* (long long) arch_specific->real_sector_size
				/ (long long) disk->dev->sector_size - 1;
		part = ped_partition_new(disk, PED_PARTITION_NORMAL, NULL,
                                         start, end);
        PDEBUG;

		if (!part)
			goto error_close_dev;

        PDEBUG;

		part->num = i;
		part->fs_type = ped_file_system_probe(&part->geom);

		vtoc_ebcdic_dec(p->f1->DS1DSNAM, p->f1->DS1DSNAM, 44);
		ch = strstr(p->f1->DS1DSNAM, "PART");

		if (ch != NULL) {
			strncpy(str, ch+9, 6);
			str[6] = '\0';
		}

		dasd_data = part->disk_specific;

		if ((strncmp(PART_TYPE_RAID, str, 6) == 0) &&
		    (ped_file_system_probe(&part->geom) == NULL))
			ped_partition_set_flag(part, PED_PARTITION_RAID, 1);
		else
			ped_partition_set_flag(part, PED_PARTITION_RAID, 0);

		if ((strncmp(PART_TYPE_LVM, str, 6) == 0) &&
		    (ped_file_system_probe(&part->geom) == NULL))
			ped_partition_set_flag(part, PED_PARTITION_LVM, 1);
		else
			ped_partition_set_flag(part, PED_PARTITION_LVM, 0);

		if (strncmp(PART_TYPE_SWAP, str, 6) == 0) {
			fs = ped_file_system_probe(&part->geom);
			if (fs && is_linux_swap(fs->name)) {
				dasd_data->system = PARTITION_LINUX_SWAP;
				PDEBUG;
			}
		}

		vtoc_ebcdic_enc(p->f1->DS1DSNAM, p->f1->DS1DSNAM, 44);

		dasd_data->type = 0;

		constraint_exact = ped_constraint_exact (&part->geom);
		if (!constraint_exact)
			goto error_close_dev;
		if (!ped_disk_add_partition(disk, part, constraint_exact)) {
			ped_constraint_destroy(constraint_exact);
			goto error_close_dev;
		}
		ped_constraint_destroy(constraint_exact);

		if (p->fspace_trk > 0) {
			start = (long long)((long long) p->end_trk + 1)
					* (long long) disk->dev->hw_geom.sectors
					* (long long) arch_specific->real_sector_size
					/ (long long) disk->dev->sector_size;
			end   = (long long)((long long) p->end_trk + 1 + p->fspace_trk)
					* (long long) disk->dev->hw_geom.sectors
					* (long long) arch_specific->real_sector_size
					/ (long long) disk->dev->sector_size - 1;
			part = ped_partition_new (disk, PED_PARTITION_NORMAL,
                                                  NULL, start, end);

			if (!part)
				goto error_close_dev;

			part->type = PED_PARTITION_FREESPACE;
			constraint_exact = ped_constraint_exact(&part->geom);

			if (!constraint_exact)
				goto error_close_dev;
			if (!ped_disk_add_partition(disk, part, constraint_exact)) {
				ped_constraint_destroy(constraint_exact);
				goto error_close_dev;
			}

			ped_constraint_destroy (constraint_exact);
		}

		p = p->next;
	}

	PDEBUG;
	fdasd_cleanup(&anchor);
	return 1;

error_close_dev:
	PDEBUG;
	fdasd_cleanup(&anchor);
	return 0;
}