/* * 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; }
/* * 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; }
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; }
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
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; }