Esempio n. 1
0
static void sgi_set_entire(struct fdisk_context *cxt)
{
	size_t n;

	for (n = 10; n < cxt->label->nparts_max; n++) {
		if (!sgi_get_num_sectors(cxt, n)) {
			set_partition(cxt, n, 0, sgi_get_lastblock(cxt), SGI_TYPE_ENTIRE_DISK);
			break;
		}
	}
}
Esempio n. 2
0
static void sgi_set_volhdr(struct fdisk_context *cxt)
{
	size_t n;

	for (n = 8; n < cxt->label->nparts_max; n++) {
		if (!sgi_get_num_sectors(cxt, n)) {
			/* Choose same default volume header size as IRIX fx uses. */
			if (4096 < sgi_get_lastblock(cxt))
				set_partition(cxt, n, 0, 4096, SGI_TYPE_VOLHDR);
			break;
		}
	}
}
Esempio n. 3
0
static int sgi_delete_partition(struct fdisk_context *cxt, size_t partnum)
{
	int rc;

	assert(cxt);
	assert(cxt->label);

	if (partnum > cxt->label->nparts_max)
		return -EINVAL;

	rc = set_partition(cxt, partnum, 0, 0, 0);

	cxt->label->nparts_cur = count_used_partitions(cxt);

	return rc;
}
Esempio n. 4
0
static int sun_add_partition(
		struct fdisk_context *cxt,
		struct fdisk_partition *pa,
		size_t *partno)
{
	struct sun_disklabel *sunlabel = self_disklabel(cxt);
	uint32_t starts[SUN_MAXPARTITIONS], lens[SUN_MAXPARTITIONS];
	struct sun_partition *part;
	struct sun_info *info;
	uint32_t start, stop, stop2;
	int whole_disk = 0;
	int sys = pa && pa->type ? pa->type->code : SUN_TAG_LINUX_NATIVE;
	int rc;
	size_t n;

	char mesg[256];
	size_t i;
	unsigned int first, last;

	rc = fdisk_partition_next_partno(pa, cxt, &n);
	if (rc)
		return rc;

	part = &sunlabel->partitions[n];
	info = &sunlabel->vtoc.infos[n];

	if (part->num_sectors && be16_to_cpu(info->id) != SUN_TAG_UNASSIGNED) {
		fdisk_info(cxt, _("Partition %zu is already defined.  Delete "
			"it before re-adding it."), n + 1);
		return -EINVAL;
	}

	fetch_sun(cxt, starts, lens, &start, &stop);

	if (stop <= start) {
		if (n == 2)
			whole_disk = 1;
		else {
			fdisk_info(cxt, _("Other partitions already cover the "
				"whole disk. Delete some/shrink them before retry."));
			return -EINVAL;
		}
	}

	if (pa && pa->start_follow_default)
		first = start;
	else if (pa && fdisk_partition_has_start(pa)) {
		first = pa->start;

		if (!whole_disk && !is_free_sector(cxt, first, starts, lens))
			return -ERANGE;
	} else {
		struct fdisk_ask *ask;

		snprintf(mesg, sizeof(mesg), _("First %s"),
				fdisk_get_unit(cxt, FDISK_SINGULAR));
		for (;;) {
			ask = fdisk_new_ask();
			if (!ask)
				return -ENOMEM;

			fdisk_ask_set_query(ask, mesg);
			fdisk_ask_set_type(ask, FDISK_ASKTYPE_NUMBER);

			if (whole_disk) {
				fdisk_ask_number_set_low(ask,     0);	/* minimal */
				fdisk_ask_number_set_default(ask, 0);	/* default */
				fdisk_ask_number_set_high(ask,    0);	/* maximal */
			} else {
				fdisk_ask_number_set_low(ask,     fdisk_scround(cxt, start));	/* minimal */
				fdisk_ask_number_set_default(ask, fdisk_scround(cxt, start));	/* default */
				fdisk_ask_number_set_high(ask,    fdisk_scround(cxt, stop));	/* maximal */
			}
			rc = fdisk_do_ask(cxt, ask);
			first = fdisk_ask_number_get_result(ask);
			fdisk_unref_ask(ask);
			if (rc)
				return rc;

			if (fdisk_use_cylinders(cxt))
				first *= fdisk_get_units_per_sector(cxt);

			/* ewt asks to add: "don't start a partition at cyl 0"
			   However, [email protected] writes:
			   "In addition to having a Sun partition table, to be able to
			   boot from the disc, the first partition, /dev/sdX1, must
			   start at cylinder 0. This means that /dev/sdX1 contains
			   the partition table and the boot block, as these are the
			   first two sectors of the disc. Therefore you must be
			   careful what you use /dev/sdX1 for. In particular, you must
			   not use a partition starting at cylinder 0 for Linux swap,
			   as that would overwrite the partition table and the boot
			   block. You may, however, use such a partition for a UFS
			   or EXT2 file system, as these file systems leave the first
			   1024 bytes undisturbed. */
			/* On the other hand, one should not use partitions
			   starting at block 0 in an md, or the label will
			   be trashed. */
			if (!is_free_sector(cxt, first, starts,  lens) && !whole_disk) {
				if (n == 2 && !first) {
				    whole_disk = 1;
				    break;
				}
				fdisk_warnx(cxt, _("Sector %d is already allocated"), first);
			} else
				break;
		}
	}

	if (n == 2 && first != 0)
		fdisk_warnx(cxt, _("It is highly recommended that the "
				   "third partition covers the whole disk "
				   "and is of type `Whole disk'"));

	if (!fdisk_use_cylinders(cxt)) {
		/* Starting sector has to be properly aligned */
		int cs = cxt->geom.heads * cxt->geom.sectors;
		int x = first % cs;

		if (x) {
			fdisk_info(cxt, _("Aligning the first sector from %u to %u "
					  "to be on cylinder boundary."),
					first, first + cs - x);
			first += cs - x;
		}
	}

	stop = cxt->geom.cylinders * cxt->geom.heads * cxt->geom.sectors;	/* ancient */
	stop2 = stop;
	for (i = 0; i < cxt->label->nparts_max; i++) {
		if (starts[i] > first && starts[i] < stop)
			stop = starts[i];
	}

	/* last */
	if (pa && pa->end_follow_default)
		last = whole_disk || (n == 2 && !first) ? stop2 : stop;
	else if (pa && fdisk_partition_has_size(pa)) {
		last = first + pa->size - 1ULL;

		if (!whole_disk && last > stop)
			return -ERANGE;
	} else {
		struct fdisk_ask *ask = fdisk_new_ask();

		if (!ask)
			return -ENOMEM;

		snprintf(mesg, sizeof(mesg),
			 _("Last %s or +%s or +size{K,M,G,T,P}"),
			 fdisk_get_unit(cxt, FDISK_SINGULAR),
			 fdisk_get_unit(cxt, FDISK_PLURAL));
		fdisk_ask_set_query(ask, mesg);
		fdisk_ask_set_type(ask, FDISK_ASKTYPE_OFFSET);

		if (whole_disk) {
			fdisk_ask_number_set_low(ask,     fdisk_scround(cxt, stop2));	/* minimal */
			fdisk_ask_number_set_default(ask, fdisk_scround(cxt, stop2));	/* default */
			fdisk_ask_number_set_high(ask,    fdisk_scround(cxt, stop2));	/* maximal */
			fdisk_ask_number_set_base(ask,    0);
		} else if (n == 2 && !first) {
			fdisk_ask_number_set_low(ask,     fdisk_scround(cxt, first));	/* minimal */
			fdisk_ask_number_set_default(ask, fdisk_scround(cxt, stop2));	/* default */
			fdisk_ask_number_set_high(ask,    fdisk_scround(cxt, stop2));	/* maximal */
			fdisk_ask_number_set_base(ask,	  fdisk_scround(cxt, first));
		} else {
			fdisk_ask_number_set_low(ask,     fdisk_scround(cxt, first));	/* minimal */
			fdisk_ask_number_set_default(ask, fdisk_scround(cxt, stop));	/* default */
			fdisk_ask_number_set_high(ask,    fdisk_scround(cxt, stop));	/* maximal */
			fdisk_ask_number_set_base(ask,    fdisk_scround(cxt, first));
		}

		if (fdisk_use_cylinders(cxt))
			fdisk_ask_number_set_unit(ask,
				     cxt->sector_size *
				     fdisk_get_units_per_sector(cxt));
		else
			fdisk_ask_number_set_unit(ask,	cxt->sector_size);

		rc = fdisk_do_ask(cxt, ask);
		last = fdisk_ask_number_get_result(ask);

		fdisk_unref_ask(ask);
		if (rc)
			return rc;
		if (fdisk_use_cylinders(cxt))
			last *= fdisk_get_units_per_sector(cxt);
	}

	if (n == 2 && !first) {
		if (last >= stop2) {
		    whole_disk = 1;
		    last = stop2;
		} else if (last > stop) {
		    fdisk_warnx(cxt,
   _("You haven't covered the whole disk with the 3rd partition, but your value\n"
     "%lu %s covers some other partition. Your entry has been changed\n"
     "to %lu %s"),
			(unsigned long) fdisk_scround(cxt, last), fdisk_get_unit(cxt, FDISK_SINGULAR),
			(unsigned long) fdisk_scround(cxt, stop), fdisk_get_unit(cxt, FDISK_SINGULAR));
		    last = stop;
		}
	} else if (!whole_disk && last > stop)
		last = stop;

	if (whole_disk)
		sys = SUN_TAG_WHOLEDISK;

	set_partition(cxt, n, first, last, sys);
	cxt->label->nparts_cur = count_used_partitions(cxt);
	if (partno)
		*partno = n;
	return 0;
}
Esempio n. 5
0
static int sun_create_disklabel(struct fdisk_context *cxt)
{
	unsigned int ndiv;
	struct fdisk_sun_label *sun;		/* libfdisk sun handler */
	struct sun_disklabel *sunlabel;	/* on disk data */
	int rc = 0;

	assert(cxt);
	assert(cxt->label);
	assert(fdisk_is_label(cxt, SUN));

	/* map first sector to header */
	rc = fdisk_init_firstsector_buffer(cxt, 0, 0);
	if (rc)
		return rc;

	sun = (struct fdisk_sun_label *) cxt->label;
	sun->header = (struct sun_disklabel *) cxt->firstsector;

	sunlabel = sun->header;

	cxt->label->nparts_max = SUN_MAXPARTITIONS;

	sunlabel->magic = cpu_to_be16(SUN_LABEL_MAGIC);
	sunlabel->vtoc.version = cpu_to_be32(SUN_VTOC_VERSION);
	sunlabel->vtoc.sanity = cpu_to_be32(SUN_VTOC_SANITY);
	sunlabel->vtoc.nparts = cpu_to_be16(SUN_MAXPARTITIONS);

#ifdef HDIO_GETGEO
	if (cxt->geom.heads && cxt->geom.sectors) {
		fdisk_sector_t llsectors;

		if (blkdev_get_sectors(cxt->dev_fd, (unsigned long long *) &llsectors) == 0) {
			int sec_fac = cxt->sector_size / 512;
			fdisk_sector_t llcyls;

			llcyls = llsectors / (cxt->geom.heads * cxt->geom.sectors * sec_fac);
			cxt->geom.cylinders = llcyls;
			if (cxt->geom.cylinders != llcyls)
				cxt->geom.cylinders = ~0;
		} else {
			fdisk_warnx(cxt,
				_("BLKGETSIZE ioctl failed on %s. "
				  "Using geometry cylinder value of %llu. "
				  "This value may be truncated for devices "
				  "> 33.8 GB."),
				cxt->dev_path, cxt->geom.cylinders);
		}
	} else
#endif
		ask_geom(cxt);

	sunlabel->acyl   = cpu_to_be16(0);
	sunlabel->pcyl   = cpu_to_be16(cxt->geom.cylinders);
	sunlabel->rpm    = cpu_to_be16(5400);
	sunlabel->intrlv = cpu_to_be16(1);
	sunlabel->apc    = cpu_to_be16(0);

	sunlabel->nhead  = cpu_to_be16(cxt->geom.heads);
	sunlabel->nsect  = cpu_to_be16(cxt->geom.sectors);
	sunlabel->ncyl   = cpu_to_be16(cxt->geom.cylinders);

	snprintf((char *) sunlabel->label_id, sizeof(sunlabel->label_id),
		 "Linux cyl %ju alt %u hd %u sec %ju",
		 (uintmax_t) cxt->geom.cylinders,
		 be16_to_cpu(sunlabel->acyl),
		 cxt->geom.heads,
		 (uintmax_t) cxt->geom.sectors);

	if (cxt->geom.cylinders * cxt->geom.heads * cxt->geom.sectors >= 150 * 2048) {
	        ndiv = cxt->geom.cylinders - (50 * 2048 / (cxt->geom.heads * cxt->geom.sectors)); /* 50M swap */
	} else
	        ndiv = cxt->geom.cylinders * 2 / 3;

	/* create the default layout only if no-script defined */
	if (!cxt->script) {
		set_partition(cxt, 0, 0, ndiv * cxt->geom.heads * cxt->geom.sectors,
			  SUN_TAG_LINUX_NATIVE);
		set_partition(cxt, 1, ndiv * cxt->geom.heads * cxt->geom.sectors,
			  cxt->geom.cylinders * cxt->geom.heads * cxt->geom.sectors,
			  SUN_TAG_LINUX_SWAP);
		sunlabel->vtoc.infos[1].flags |= cpu_to_be16(SUN_FLAG_UNMNT);

		set_partition(cxt, 2, 0,
			  cxt->geom.cylinders * cxt->geom.heads * cxt->geom.sectors,
			  SUN_TAG_WHOLEDISK);
	}

	{
		unsigned short *ush = (unsigned short *)sunlabel;
		unsigned short csum = 0;
		while(ush < (unsigned short *)(&sunlabel->csum))
			csum ^= *ush++;
		sunlabel->csum = csum;
	}

	fdisk_label_set_changed(cxt->label, 1);
	cxt->label->nparts_cur = count_used_partitions(cxt);

	fdisk_info(cxt, _("Created a new Sun disklabel."));
	return 0;
}
Esempio n. 6
0
void dos_add_partition(struct fdisk_context *cxt, int n, int sys)
{
	char mesg[256];		/* 48 does not suffice in Japanese */
	int i, read = 0;
	struct partition *p = ptes[n].part_table;
	struct partition *q = ptes[ext_index].part_table;
	sector_t start, stop = 0, limit, temp,
		first[partitions], last[partitions];

	if (p && p->sys_ind) {
		printf(_("Partition %d is already defined.  Delete "
			 "it before re-adding it.\n"), n + 1);
		return;
	}
	fill_bounds(first, last);
	if (n < 4) {
		start = sector_offset;
		if (display_in_cyl_units || !cxt->total_sectors)
			limit = cxt->geom.heads * cxt->geom.sectors * cxt->geom.cylinders - 1;
		else
			limit = cxt->total_sectors - 1;

		if (limit > UINT_MAX)
			limit = UINT_MAX;

		if (extended_offset) {
			first[ext_index] = extended_offset;
			last[ext_index] = get_start_sect(q) +
				get_nr_sects(q) - 1;
		}
	} else {
		start = extended_offset + sector_offset;
		limit = get_start_sect(q) + get_nr_sects(q) - 1;
	}
	if (display_in_cyl_units)
		for (i = 0; i < partitions; i++)
			first[i] = (cround(first[i]) - 1) * units_per_sector;

	snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
	do {
		sector_t dflt, aligned;

		temp = start;
		dflt = start = get_unused_start(n, start, first, last);

		/* the default sector should be aligned and unused */
		do {
			aligned = align_lba_in_range(cxt, dflt, dflt, limit);
			dflt = get_unused_start(n, aligned, first, last);
		} while (dflt != aligned && dflt > aligned && dflt < limit);

		if (dflt >= limit)
			dflt = start;
		if (start > limit)
			break;
		if (start >= temp+units_per_sector && read) {
			printf(_("Sector %llu is already allocated\n"), temp);
			temp = start;
			read = 0;
		}
		if (!read && start == temp) {
			sector_t i = start;

			start = read_int(cxt, cround(i), cround(dflt), cround(limit),
					 0, mesg);
			if (display_in_cyl_units) {
				start = (start - 1) * units_per_sector;
				if (start < i) start = i;
			}
			read = 1;
		}
	} while (start != temp || !read);
	if (n > 4) {			/* NOT for fifth partition */
		struct pte *pe = &ptes[n];

		pe->offset = start - sector_offset;
		if (pe->offset == extended_offset) { /* must be corrected */
			pe->offset++;
			if (sector_offset == 1)
				start++;
		}
	}

	for (i = 0; i < partitions; i++) {
		struct pte *pe = &ptes[i];

		if (start < pe->offset && limit >= pe->offset)
			limit = pe->offset - 1;
		if (start < first[i] && limit >= first[i])
			limit = first[i] - 1;
	}
	if (start > limit) {
		printf(_("No free sectors available\n"));
		if (n > 4)
			partitions--;
		return;
	}
	if (cround(start) == cround(limit)) {
		stop = limit;
	} else {
		int is_suffix_used = 0;

		snprintf(mesg, sizeof(mesg),
			_("Last %1$s, +%2$s or +size{K,M,G}"),
			 str_units(SINGULAR), str_units(PLURAL));

		stop = read_int_with_suffix(cxt,
					    cround(start), cround(limit), cround(limit),
					    cround(start), mesg, &is_suffix_used);
		if (display_in_cyl_units) {
			stop = stop * units_per_sector - 1;
			if (stop >limit)
				stop = limit;
		}

		if (is_suffix_used && alignment_required) {
			/* the last sector has not been exactly requested (but
			 * defined by +size{K,M,G} convention), so be smart
			 * and align the end of the partition. The next
			 * partition will start at phy.block boundary.
			 */
			stop = align_lba_in_range(cxt, stop, start, limit) - 1;
			if (stop > limit)
				stop = limit;
		}
	}

	set_partition(cxt, n, 0, start, stop, sys);
	if (n > 4)
		set_partition(cxt, n - 1, 1, ptes[n].offset, stop, EXTENDED);

	if (IS_EXTENDED (sys)) {
		struct pte *pe4 = &ptes[4];
		struct pte *pen = &ptes[n];

		ext_index = n;
		pen->ext_pointer = p;
		pe4->offset = extended_offset = start;
		pe4->sectorbuffer = xcalloc(1, cxt->sector_size);
		pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
		pe4->ext_pointer = pe4->part_table + 1;
		pe4->changed = 1;
		partitions = 5;
	}
}
Esempio n. 7
0
static int sgi_add_partition(struct fdisk_context *cxt,
			     struct fdisk_partition *pa,
			     size_t *partno)
{
	struct fdisk_sgi_label *sgi;
	char mesg[256];
	unsigned int first = 0, last = 0;
	struct fdisk_ask *ask;
	int sys = pa && pa->type ? pa->type->code : SGI_TYPE_XFS;
	int rc;
	size_t n;

	assert(cxt);
	assert(cxt->label);
	assert(fdisk_is_label(cxt, SGI));

	rc = fdisk_partition_next_partno(pa, cxt, &n);
	if (rc)
		return rc;
	if (n == 10)
		sys = SGI_TYPE_ENTIRE_DISK;
	else if (n == 8)
		sys = 0;

	sgi = self_label(cxt);

	if (sgi_get_num_sectors(cxt, n)) {
		fdisk_warnx(cxt, _("Partition %zu is already defined.  "
				   "Delete it before re-adding it."), n + 1);
		return -EINVAL;
	}
	if (!cxt->script && sgi_entire(cxt) == -1 &&  sys != SGI_TYPE_ENTIRE_DISK) {
		fdisk_info(cxt, _("Attempting to generate entire disk entry automatically."));
		sgi_set_entire(cxt);
		sgi_set_volhdr(cxt);
	}
	if (sgi_gaps(cxt) == 0 && sys != SGI_TYPE_ENTIRE_DISK) {
		fdisk_warnx(cxt, _("The entire disk is already covered with partitions."));
		return -EINVAL;
	}
	if (sgi_gaps(cxt) < 0) {
		fdisk_warnx(cxt, _("You got a partition overlap on the disk. Fix it first!"));
		return -EINVAL;
	}

	if (sys == SGI_TYPE_ENTIRE_DISK) {
		first = 0;
		last = sgi_get_lastblock(cxt);
	} else {
		first = sgi->freelist[0].first;
		last  = sgi->freelist[0].last;
	}

	/* first sector */
	if (pa && pa->start_follow_default)
		;
	else if (pa && fdisk_partition_has_start(pa)) {
		first = pa->start;
		last = is_in_freelist(cxt, first);

		if (sys != SGI_TYPE_ENTIRE_DISK && !last)
			return -ERANGE;
	} else {
		snprintf(mesg, sizeof(mesg), _("First %s"),
				fdisk_get_unit(cxt, FDISK_SINGULAR));
		ask = fdisk_new_ask();
		if (!ask)
			return -ENOMEM;

		fdisk_ask_set_query(ask, mesg);
		fdisk_ask_set_type(ask, FDISK_ASKTYPE_NUMBER);

		fdisk_ask_number_set_low(ask,     fdisk_scround(cxt, first));	/* minimal */
		fdisk_ask_number_set_default(ask, fdisk_scround(cxt, first));	/* default */
		fdisk_ask_number_set_high(ask,    fdisk_scround(cxt, last) - 1); /* maximal */

		rc = fdisk_do_ask(cxt, ask);
		first = fdisk_ask_number_get_result(ask);
		fdisk_unref_ask(ask);

		if (rc)
			return rc;
		if (fdisk_use_cylinders(cxt))
			first *= fdisk_get_units_per_sector(cxt);
	}

	if (first && sys == SGI_TYPE_ENTIRE_DISK)
		fdisk_info(cxt, _("It is highly recommended that the "
				  "eleventh partition covers the entire "
				  "disk and is of type 'SGI volume'."));
	if (!last)
		last = is_in_freelist(cxt, first);

	/* last sector */
	if (pa && pa->end_follow_default)
		last -= 1ULL;
	else if (pa && fdisk_partition_has_size(pa)) {
		if (first + pa->size - 1ULL > last)
			return -ERANGE;
		last = first + pa->size - 1ULL;
	} else {
		snprintf(mesg, sizeof(mesg),
			 _("Last %s or +%s or +size{K,M,G,T,P}"),
			 fdisk_get_unit(cxt, FDISK_SINGULAR),
			 fdisk_get_unit(cxt, FDISK_PLURAL));

		ask = fdisk_new_ask();
		if (!ask)
			return -ENOMEM;

		fdisk_ask_set_query(ask, mesg);
		fdisk_ask_set_type(ask, FDISK_ASKTYPE_OFFSET);

		fdisk_ask_number_set_low(ask,     fdisk_scround(cxt, first));	/* minimal */
		fdisk_ask_number_set_default(ask, fdisk_scround(cxt, last) - 1);/* default */
		fdisk_ask_number_set_high(ask,    fdisk_scround(cxt, last) - 1);/* maximal */
		fdisk_ask_number_set_base(ask,    fdisk_scround(cxt, first));

		if (fdisk_use_cylinders(cxt))
			fdisk_ask_number_set_unit(ask,
				     cxt->sector_size *
				     fdisk_get_units_per_sector(cxt));
		else
			fdisk_ask_number_set_unit(ask,cxt->sector_size);

		rc = fdisk_do_ask(cxt, ask);
		last = fdisk_ask_number_get_result(ask) + 1;

		fdisk_unref_ask(ask);
		if (rc)
			return rc;
		if (fdisk_use_cylinders(cxt))
			last *= fdisk_get_units_per_sector(cxt);
	}

	if (sys == SGI_TYPE_ENTIRE_DISK
	    && (first != 0 || last != sgi_get_lastblock(cxt)))
		fdisk_info(cxt, _("It is highly recommended that the "
				  "eleventh partition covers the entire "
				  "disk and is of type 'SGI volume'."));

	set_partition(cxt, n, first, last - first, sys);
	cxt->label->nparts_cur = count_used_partitions(cxt);
	if (partno)
		*partno = n;
	return 0;
}