Exemple #1
0
static int sgi_check_bootfile(struct fdisk_context *cxt, const char *name)
{
	size_t sz;
	struct sgi_disklabel *sgilabel = self_disklabel(cxt);

	sz = strlen(name);

	if (sz < 3) {
		/* "/a\n" is minimum */
		fdisk_warnx(cxt, _("Invalid Bootfile! "
			 "The bootfile must be an absolute non-zero pathname,"
			 "e.g. \"/unix\" or \"/unix.save\"."));
		return -EINVAL;

	} else if (sz > sizeof(sgilabel->boot_file)) {
		fdisk_warnx(cxt, _("Name of Bootfile too long: %zu bytes maximum."),
				sizeof(sgilabel->boot_file));
		return -EINVAL;

	} else if (*name != '/') {
		fdisk_warnx(cxt, _("Bootfile must have a fully qualified pathname."));
		return -EINVAL;
	}

	if (strncmp(name, (char *) sgilabel->boot_file,
				sizeof(sgilabel->boot_file))) {
		fdisk_warnx(cxt, _("Be aware, that the bootfile is not checked "
			"for existence. SGI's default is \"/unix\" and for "
			"backup \"/unix.save\"."));
		/* filename is correct and did change */
		return 0;
	}

	return 1;	/* filename did not change */
}
Exemple #2
0
static int sgi_probe_label(struct fdisk_context *cxt)
{
	struct fdisk_sgi_label *sgi;
	struct sgi_disklabel *sgilabel;

	assert(cxt);
	assert(cxt->label);
	assert(fdisk_is_disklabel(cxt, SGI));
	assert(sizeof(struct sgi_disklabel) <= 512);

	/* map first sector to header */
	sgi = (struct fdisk_sgi_label *) cxt->label;
	sgi->header = (struct sgi_disklabel *) cxt->firstsector;
	sgilabel = sgi->header;

	if (be32_to_cpu(sgilabel->magic) != SGI_LABEL_MAGIC) {
		sgi->header = NULL;
		return 0;
	}

	/*
	 * test for correct checksum
	 */
	if (sgi_pt_checksum(sgilabel) != 0)
		fdisk_warnx(cxt, _("Detected sgi disklabel with wrong checksum."));

	clear_freelist(cxt);
	cxt->label->nparts_max = SGI_MAXPARTITIONS;
	cxt->label->nparts_cur = count_used_partitions(cxt);
	return 1;
}
Exemple #3
0
void change_partition_type(struct fdisk_context *cxt)
{
	size_t i;
	struct fdisk_parttype *t = NULL, *org_t = NULL;

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

	if (fdisk_ask_partnum(cxt, &i, FALSE))
		return;

	org_t = t = fdisk_get_partition_type(cxt, i);
	if (!t)
                fdisk_warnx(cxt, _("Partition %zu does not exist yet!"), i + 1);
        else {
		do {
			t = ask_partition_type(cxt);
		} while (!t);

		if (fdisk_set_partition_type(cxt, i, t) == 0)
			fdisk_sinfo(cxt, FDISK_INFO_SUCCESS,
				_("Changed type of partition '%s' to '%s'."),
				org_t ? org_t->name : _("Unknown"),
				    t ?     t->name : _("Unknown"));
		else
			fdisk_info(cxt,
				_("Type of partition %zu is unchanged: %s."),
				i + 1,
				org_t ? org_t->name : _("Unknown"));
        }

	fdisk_free_parttype(t);
	fdisk_free_parttype(org_t);
}
Exemple #4
0
static int sgi_set_partition(struct fdisk_context *cxt, size_t i,
			     unsigned int start, unsigned int length, int sys)
{
	struct sgi_disklabel *sgilabel;

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

	sgilabel = self_disklabel(cxt);
	sgilabel->partitions[i].type = cpu_to_be32(sys);
	sgilabel->partitions[i].num_blocks = cpu_to_be32(length);
	sgilabel->partitions[i].first_block = cpu_to_be32(start);

	fdisk_label_set_changed(cxt->label, 1);

	if (sgi_gaps(cxt) < 0)	/* rebuild freelist */
		fdisk_warnx(cxt, _("Partition overlap on the disk."));
	if (length) {
		struct fdisk_parttype *t = fdisk_get_parttype_from_code(cxt, sys);
		fdisk_info_new_partition(cxt, i + 1, start, start + length, t);
	}

	return 0;
}
Exemple #5
0
static int sgi_set_partition(struct fdisk_context *cxt,
		size_t i,
		struct fdisk_partition *pa)
{
	struct sgi_disklabel *sgilabel;

	if (i >= cxt->label->nparts_max)
		return -EINVAL;

	sgilabel = self_disklabel(cxt);

	if (pa->type) {
		struct fdisk_parttype *t = pa->type;

		if (sgi_get_num_sectors(cxt, i) == 0)	/* caught already before, ... */ {
			fdisk_warnx(cxt, _("Sorry, only for non-empty partitions you can change the tag."));
			return -EINVAL;
		}

		if ((i == 10 && t->code != SGI_TYPE_ENTIRE_DISK)
		    || (i == 8 && t->code != 0))
			fdisk_info(cxt, _("Consider leaving partition 9 as volume header (0), "
					  "and partition 11 as entire volume (6), "
					  "as IRIX expects it."));

		if (cxt->script == NULL
		    && ((t->code != SGI_TYPE_ENTIRE_DISK) && (t->code != SGI_TYPE_VOLHDR))
		    && (sgi_get_start_sector(cxt, i) < 1)) {
			int yes = 0;
			fdisk_ask_yesno(cxt,
				_("It is highly recommended that the partition at offset 0 "
				  "is of type \"SGI volhdr\", the IRIX system will rely on it to "
				  "retrieve from its directory standalone tools like sash and fx. "
				  "Only the \"SGI volume\" entire disk section may violate this. "
				  "Are you sure about tagging this partition differently?"), &yes);
			if (!yes)
				return 1;
		}

		sgilabel->partitions[i].type = cpu_to_be32(t->code);
	}

	if (fdisk_partition_has_start(pa))
		sgilabel->partitions[i].first_block = cpu_to_be32(pa->start);
	if (fdisk_partition_has_size(pa))
		sgilabel->partitions[i].num_blocks = cpu_to_be32(pa->size);

	fdisk_label_set_changed(cxt->label, 1);
	return 0;
}
Exemple #6
0
/*
 * Read a bsd_disklabel from sector 0 or from the starting sector of p.
 * If it has the right magic, return 0.
 */
static int bsd_readlabel(struct fdisk_context *cxt)
{
    struct fdisk_bsd_label *l;
    struct bsd_disklabel *d;
    int t;
    off_t offset = 0;

    l = self_label(cxt);
    d = self_disklabel(cxt);

    if (l->dos_part)
        /* BSD is nested within DOS partition, get the begin of the
         * partition. Note that DOS uses native sector size. */
        offset = dos_partition_get_start(l->dos_part) * cxt->sector_size;

    if (lseek(cxt->dev_fd, offset, SEEK_SET) == -1)
        return -1;
    if (read_all(cxt->dev_fd, l->bsdbuffer, sizeof(l->bsdbuffer)) < 0)
        return errno ? -errno : -1;

    /* The offset to begin of the disk label. Note that BSD uses
     * 512-byte (default) sectors. */
    memmove(d, &l->bsdbuffer[BSD_LABELSECTOR * DEFAULT_SECTOR_SIZE
                             + BSD_LABELOFFSET], sizeof(*d));

    if (d->d_magic != BSD_DISKMAGIC || d->d_magic2 != BSD_DISKMAGIC) {
        DBG(LABEL, ul_debug("not found magic"));
        return -1;
    }

    for (t = d->d_npartitions; t < BSD_MAXPARTITIONS; t++) {
        d->d_partitions[t].p_size   = 0;
        d->d_partitions[t].p_offset = 0;
        d->d_partitions[t].p_fstype = BSD_FS_UNUSED;
    }

    if (d->d_npartitions > BSD_MAXPARTITIONS)
        fdisk_warnx(cxt, ("Too many partitions (%d, maximum is %d)."),
                    d->d_npartitions, BSD_MAXPARTITIONS);

    /* let's follow in-PT geometry */
    cxt->geom.sectors = d->d_nsectors;
    cxt->geom.heads = d->d_ntracks;
    cxt->geom.cylinders = d->d_ncylinders;

    cxt->label->nparts_cur = d->d_npartitions;
    cxt->label->nparts_max = BSD_MAXPARTITIONS;
    DBG(LABEL, ul_debug("read BSD label"));
    return 0;
}
Exemple #7
0
/*
 * look for DOS partition usable for nested BSD partition table
 */
static int bsd_assign_dos_partition(struct fdisk_context *cxt)
{
    struct fdisk_bsd_label *l = self_label(cxt);
    size_t i;

    for (i = 0; i < 4; i++) {
        sector_t ss;

        l->dos_part = fdisk_dos_get_partition(cxt->parent, i);

        if (!l->dos_part || !is_bsd_partition_type(l->dos_part->sys_ind))
            continue;

        ss = dos_partition_get_start(l->dos_part);
        if (!ss) {
            fdisk_warnx(cxt, _("Partition %zd: has invalid starting "
                               "sector 0."), i + 1);
            return -1;
        }

        if (cxt->parent->dev_path) {
            free(cxt->dev_path);
            cxt->dev_path = fdisk_partname(
                                cxt->parent->dev_path, i + 1);
        }

        DBG(LABEL, ul_debug("partition %zu assigned to BSD", i + 1));
        return 0;
    }

    fdisk_warnx(cxt, _("There is no *BSD partition on %s."),
                cxt->parent->dev_path);
    free(cxt->dev_path);
    cxt->dev_path = NULL;
    l->dos_part = NULL;
    return 1;
}
Exemple #8
0
int fdisk_missing_geometry(struct fdisk_context *cxt)
{
	int rc;

	assert(cxt);

	rc = (fdisk_require_geometry(cxt) &&
		    (!cxt->geom.heads || !cxt->geom.sectors
				      || !cxt->geom.cylinders));

	if (rc && !fdisk_context_listonly(cxt))
		fdisk_warnx(cxt, _("Incomplete geometry setting."));

	return rc;
}
Exemple #9
0
/*
 * This function prints a warning if the device is not wiped (e.g. wipefs(8).
 * Please don't call this function if there is already a PT.
 *
 * Returns: 0 if nothing found, < 0 on error, 1 if found a signature
 */
static int warn_wipe(struct fdisk_context *cxt)
{
#ifdef HAVE_LIBBLKID
	blkid_probe pr;
#endif
	int rc = 0;

	assert(cxt);

	if (fdisk_dev_has_disklabel(cxt) || cxt->dev_fd < 0)
		return -EINVAL;
#ifdef HAVE_LIBBLKID
	DBG(LABEL, dbgprint("wipe check: initialize libblkid prober"));

	pr = blkid_new_probe();
	if (!pr)
		return -ENOMEM;
	rc = blkid_probe_set_device(pr, cxt->dev_fd, 0, 0);
	if (rc)
		return rc;

	blkid_probe_enable_superblocks(pr, 1);
	blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_TYPE);
	blkid_probe_enable_partitions(pr, 1);

	/* we care about the first found FS/raid, so don't call blkid_do_probe()
	 * in loop or don't use blkid_do_fullprobe() ... */
	rc = blkid_do_probe(pr);
	if (rc == 0) {
		const char *name = NULL;

		if (blkid_probe_lookup_value(pr, "TYPE", &name, 0) == 0 ||
		    blkid_probe_lookup_value(pr, "PTTYPE", &name, 0) == 0) {
			fdisk_warnx(cxt, _(
				"%s: device contains a valid '%s' signature, it's "
				"strongly recommended to wipe the device by command wipefs(8) "
				"if this setup is unexpected to avoid "
				"possible collisions."), cxt->dev_path, name);
			rc = 1;
		}
	}

	blkid_free_probe(pr);
#endif
	return rc;
}
Exemple #10
0
static int ask_menu(struct fdisk_context *cxt, struct fdisk_ask *ask,
		    char *buf, size_t bufsz)

{
	const char *q = fdisk_ask_get_query(ask);
	int dft = fdisk_ask_menu_get_default(ask);

	if (q) {
		fputs(q, stdout);		/* print header */
		fputc('\n', stdout);
	}

	do {
		char prompt[128];
		int key, c, rc;
		const char *name, *desc;
		size_t i = 0;

		/* print menu items */
		while (fdisk_ask_menu_get_item(ask, i++, &key, &name, &desc) == 0)
			fprintf(stdout, "   %c   %s (%s)\n", key, name, desc);

		/* ask for key */
		snprintf(prompt, sizeof(prompt), _("Select (default %c): "), dft);
		rc = get_user_reply(cxt, prompt, buf, bufsz);
		if (rc)
			return rc;
		if (!*buf) {
			fdisk_info(cxt, _("Using default response %c."), dft);
			c = dft;
		} else
			c = tolower(buf[0]);

		/* check result */
		i = 0;
		while (fdisk_ask_menu_get_item(ask, i++, &key, NULL, NULL) == 0) {
			if (c == key) {
				fdisk_ask_menu_set_result(ask, c);
				return 0;	/* success */
			}
		}
		fdisk_warnx(cxt, _("Value out of range."));
	} while (1);

	return -EINVAL;
}
Exemple #11
0
/*
 * link partition from parent (DOS) to nested BSD partition table
 */
int fdisk_bsd_link_partition(struct fdisk_context *cxt)
{
    size_t k, i;
    int rc;
    struct dos_partition *p;
    struct bsd_disklabel *d = self_disklabel(cxt);

    if (!cxt->parent || !fdisk_is_disklabel(cxt->parent, DOS)) {
        fdisk_warnx(cxt, _("BSD label is not nested within a DOS partition."));
        return -EINVAL;
    }

    /* ask for DOS partition */
    rc = fdisk_ask_partnum(cxt->parent, &k, FALSE);
    if (rc)
        return rc;
    /* ask for BSD partition */
    rc = fdisk_ask_partnum(cxt, &i, TRUE);
    if (rc)
        return rc;

    if (i >= BSD_MAXPARTITIONS)
        return -EINVAL;

    p = fdisk_dos_get_partition(cxt->parent, k);

    d->d_partitions[i].p_size   = dos_partition_get_size(p);
    d->d_partitions[i].p_offset = dos_partition_get_start(p);
    d->d_partitions[i].p_fstype = bsd_translate_fstype(p->sys_ind);

    if (i >= d->d_npartitions)
        d->d_npartitions = i + 1;

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

    fdisk_sinfo(cxt, FDISK_INFO_SUCCESS,
                _("BSD partition '%c' linked to DOS partition %zu."),
                'a' + (int) i, k + 1);
    return 0;
}
Exemple #12
0
void list_disklabel(struct fdisk_context *cxt)
{
	struct fdisk_table *tb = NULL;
	struct fdisk_partition *pa = NULL;
	struct fdisk_iter *itr = NULL;
	struct fdisk_label *lb;
	struct libscols_table *out = NULL;
	const char *bold = NULL;
	int *ids = NULL;		/* IDs of fdisk_fields */
	size_t	nids = 0, i;
	int post = 0;

	/* print label specific stuff by libfdisk FDISK_ASK_INFO API */
	fdisk_list_disklabel(cxt);

	/* get partitions and generate output */
	if (fdisk_get_partitions(cxt, &tb) || fdisk_table_get_nents(tb) <= 0)
		goto done;

	ids = init_fields(cxt, NULL, &nids);
	if (!ids)
		goto done;

	itr = fdisk_new_iter(FDISK_ITER_FORWARD);
	if (!itr) {
		fdisk_warn(cxt, _("faild to allocate iterator"));
		goto done;
	}

	out = scols_new_table();
	if (!out) {
		fdisk_warn(cxt, _("faild to allocate output table"));
		goto done;
	}

	if (colors_wanted()) {
		scols_table_enable_colors(out, 1);
		bold = color_scheme_get_sequence("header", UL_COLOR_BOLD);
	}

	lb = fdisk_get_label(cxt, NULL);
	assert(lb);

	/* define output table columns */
	for (i = 0; i < nids; i++) {
		int fl = 0;
		struct libscols_column *co;
		const struct fdisk_field *field =
				fdisk_label_get_field(lb, ids[i]);
		if (!field)
			continue;
		if (fdisk_field_is_number(field))
			fl |= SCOLS_FL_RIGHT;
		if (fdisk_field_get_id(field) == FDISK_FIELD_TYPE)
			fl |= SCOLS_FL_TRUNC;

		co = scols_table_new_column(out,
				fdisk_field_get_name(field),
				fdisk_field_get_width(field), fl);
		if (!co)
			goto done;

		/* set colum header color */
		if (bold)
			scols_cell_set_color(scols_column_get_header(co), bold);
	}

	/* fill-in output table */
	while (fdisk_table_next_partition(tb, itr, &pa) == 0) {
		struct libscols_line *ln = scols_table_new_line(out, NULL);

		if (!ln) {
			fdisk_warn(cxt, _("faild to allocate output line"));
			goto done;
		}

		for (i = 0; i < nids; i++) {
			char *data = NULL;

			if (fdisk_partition_to_string(pa, cxt, ids[i], &data))
				continue;
			scols_line_refer_data(ln, i, data);
		}
	}

	/* print */
	if (!scols_table_is_empty(out)) {
		fputc('\n', stdout);
		scols_print_table(out);
	}

	/* print warnings */
	fdisk_reset_iter(itr, FDISK_ITER_FORWARD);
	while (itr && fdisk_table_next_partition(tb, itr, &pa) == 0) {
		if (!fdisk_partition_has_start(pa))
			continue;
		if (!fdisk_lba_is_phy_aligned(cxt, fdisk_partition_get_start(pa))) {
			if (!post)
				fputc('\n', stdout);
			fdisk_warnx(cxt, _("Partition %zu does not start on physical sector boundary."),
					  fdisk_partition_get_partno(pa) + 1);
			post++;
		}
	}

	if (fdisk_table_wrong_order(tb)) {
		if (!post)
			fputc('\n', stdout);
		fdisk_info(cxt, _("Partition table entries are not in disk order."));
	}
done:
	scols_unref_table(out);
	fdisk_unref_table(tb);
	fdisk_free_iter(itr);
}
Exemple #13
0
static int ask_offset(struct fdisk_context *cxt,
		      struct fdisk_ask *ask,
		      char *buf, size_t bufsz)
{
	char prompt[128] = { '\0' };
	const char *q = fdisk_ask_get_query(ask);
	const char *range = fdisk_ask_number_get_range(ask);

	uint64_t dflt = fdisk_ask_number_get_default(ask),
		 low = fdisk_ask_number_get_low(ask),
		 high = fdisk_ask_number_get_high(ask),
		 base = fdisk_ask_number_get_base(ask);

	assert(q);

	DBG(ASK, ul_debug("asking for offset ['%s', <%ju,%ju>, base=%ju, default=%ju, range: %s]",
				q, low, high, base, dflt, range));

	if (range && dflt >= low && dflt <= high)
		snprintf(prompt, sizeof(prompt), _("%s (%s, default %ju): "), q, range, dflt);
	else if (dflt >= low && dflt <= high)
		snprintf(prompt, sizeof(prompt), _("%s (%ju-%ju, default %ju): "), q, low, high, dflt);
	else
		snprintf(prompt, sizeof(prompt), _("%s (%ju-%ju): "), q, low, high);

	do {
		uint64_t num = 0;
		char sig = 0, *p;
		int pwr = 0;

		int rc = get_user_reply(cxt, prompt, buf, bufsz);
		if (rc)
			return rc;
		if (!*buf && dflt >= low && dflt <= high)
			return fdisk_ask_number_set_result(ask, dflt);

		p = buf;
		if (*p == '+' || *p == '-') {
			sig = *buf;
			p++;
		}

		rc = parse_size(p, &num, &pwr);
		if (rc)
			continue;
		DBG(ASK, ul_debug("parsed size: %ju", num));
		if (sig && pwr) {
			/* +{size}{K,M,...} specified, the "num" is in bytes */
			uint64_t unit = fdisk_ask_number_get_unit(ask);
			num += unit/2;	/* round */
			num /= unit;
		}
		if (sig == '+')
			num += base;
		else if (sig == '-')
			num = base - num;

		DBG(ASK, ul_debug("final offset: %ju [sig: %c, power: %d, %s]",
				num, sig, pwr,
				sig ? "relative" : "absolute"));
		if (num >= low && num <= high) {
			if (sig)
				fdisk_ask_number_set_relative(ask, 1);
			return fdisk_ask_number_set_result(ask, num);
		}
		fdisk_warnx(cxt, _("Value out of range."));
	} while (1);

	return -1;
}
Exemple #14
0
static int ask_number(struct fdisk_context *cxt,
		      struct fdisk_ask *ask,
		      char *buf, size_t bufsz)
{
	char prompt[128] = { '\0' };
	const char *q = fdisk_ask_get_query(ask);
	const char *range = fdisk_ask_number_get_range(ask);

	uint64_t dflt = fdisk_ask_number_get_default(ask),
		 low = fdisk_ask_number_get_low(ask),
		 high = fdisk_ask_number_get_high(ask);
	int inchar = fdisk_ask_number_inchars(ask);

	assert(q);

	DBG(ASK, ul_debug("asking for number "
			"['%s', <%ju,%ju>, default=%ju, range: %s]",
			q, low, high, dflt, range));

	if (range && dflt >= low && dflt <= high) {
		if (inchar)
			snprintf(prompt, sizeof(prompt), _("%s (%s, default %c): "),
					q, range, tochar(dflt));
		else
			snprintf(prompt, sizeof(prompt), _("%s (%s, default %ju): "),
					q, range, dflt);

	} else if (dflt >= low && dflt <= high) {
		if (inchar)
			snprintf(prompt, sizeof(prompt), _("%s (%c-%c, default %c): "),
					q, tochar(low), tochar(high), tochar(dflt));
		else
			snprintf(prompt, sizeof(prompt), _("%s (%ju-%ju, default %ju): "),
					q, low, high, dflt);
	} else if (inchar)
		snprintf(prompt, sizeof(prompt), _("%s (%c-%c): "),
				q, tochar(low), tochar(high));
	else
		snprintf(prompt, sizeof(prompt), _("%s (%ju-%ju): "),
				q, low, high);

	do {
		int rc = get_user_reply(cxt, prompt, buf, bufsz);
		uint64_t num;

		if (rc)
			return rc;
		if (!*buf && dflt >= low && dflt <= high)
			return fdisk_ask_number_set_result(ask, dflt);

		if (isdigit_string(buf)) {
			char *end;

			errno = 0;
			num = strtoumax(buf, &end, 10);
			if (errno || buf == end || (end && *end))
				continue;
		} else if (inchar && isalpha(*buf)) {
			num = tolower(*buf) - 'a' + 1;
		} else
			rc = -EINVAL;

		if (rc == 0 && num >= low && num <= high)
			return fdisk_ask_number_set_result(ask, num);

		fdisk_warnx(cxt, _("Value out of range."));
	} while (1);

	return -1;
}
Exemple #15
0
/* returns: 1=0 on success, < 0 on error, 1 if no free/used partition */
int fdisk_ask_partnum(struct fdisk_context *cxt, size_t *partnum, int wantnew)
{
	int rc = 0, inchar = 0;
	char range[BUFSIZ], *ptr = range;
	size_t i, len = sizeof(range), begin = 0, run = 0;
	struct fdisk_ask *ask = NULL;
	__typeof__(ask->data.num) *num;

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

	if (cxt->label && cxt->label->flags & FDISK_LABEL_FL_INCHARS_PARTNO)
		inchar = 1;

	DBG(ASK, dbgprint("%s: asking for %s partition number "
			  "(max: %zd, inchar: %s)",
			cxt->label->name,
			wantnew ? "new" : "used",
			cxt->label->nparts_max,
			inchar ? "yes" : "not"));

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

	fdisk_ask_set_type(ask, FDISK_ASKTYPE_NUMBER);
	num = &ask->data.num;

	ask->data.num.inchars = inchar ? 1 : 0;

	for (i = 0; i < cxt->label->nparts_max; i++) {
		int status = 0;

		rc = fdisk_partition_get_status(cxt, i, &status);
		if (rc)
			break;
		if (wantnew && !(status & FDISK_PARTSTAT_USED)) {
			ptr = mk_string_list(ptr, &len, &begin, &run, i, inchar);
			if (!ptr) {
				rc = -EINVAL;
				break;
			}
			if (!num->low)
				num->dfl = num->low = i + 1;
			num->hig = i + 1;
		} else if (!wantnew && (status & FDISK_PARTSTAT_USED)) {
			ptr = mk_string_list(ptr, &len, &begin, &run, i, inchar);
			if (!num->low)
				num->low = i + 1;
			num->dfl = num->hig = i + 1;
		}
	}

	DBG(ASK, dbgprint("ask limits: low: %zd, high: %zd, default: %zd",
				num->low, num->hig, num->dfl));

	if (!rc && !wantnew && num->low == num->hig) {
		if (num->low > 0) {
			/* only one existing partiton, don't ask, return the number */
			fdisk_ask_number_set_result(ask, num->low);
			fdisk_info(cxt, _("Selected partition %d"), num->low);

		} else if (num->low == 0) {
			fdisk_warnx(cxt, _("No partition is defined yet!"));
			rc = 1;
		}
		goto dont_ask;
	}
	if (!rc && wantnew && num->low == num->hig) {
		if (num->low > 0) {
			/* only one free partition, don't ask, return the number */
			fdisk_ask_number_set_result(ask, num->low);
			fdisk_info(cxt, _("Selected partition %d"), num->low);
		}
		if (num->low == 0) {
			fdisk_warnx(cxt, _("No free partition available!"));
			rc = 1;
		}
		goto dont_ask;
	}
	if (!rc) {
		mk_string_list(ptr, &len, &begin, &run, -1, inchar);	/* terminate the list */
		rc = fdisk_ask_number_set_range(ask, range);
	}
	if (!rc)
		rc = fdisk_ask_set_query(ask, _("Partition number"));
	if (!rc)
		rc = fdisk_do_ask(cxt, ask);

dont_ask:
	if (!rc) {
		*partnum = fdisk_ask_number_get_result(ask);
		if (*partnum)
			*partnum -= 1;
	}
	DBG(ASK, dbgprint("result: %zd [rc=%d]\n", fdisk_ask_number_get_result(ask), rc));
	fdisk_free_ask(ask);
	return rc;
}
Exemple #16
0
static int sun_verify_disklabel(struct fdisk_context *cxt)
{
    uint32_t starts[SUN_MAXPARTITIONS], lens[SUN_MAXPARTITIONS], start, stop;
    uint32_t i,j,k,starto,endo;
#ifdef HAVE_QSORT_R
    int array[SUN_MAXPARTITIONS];
    unsigned int *verify_sun_starts;
#endif
    assert(cxt);
    assert(cxt->label);
    assert(fdisk_is_label(cxt, SUN));

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

    for (k = 0; k < 7; k++) {
	for (i = 0; i < SUN_MAXPARTITIONS; i++) {
	    if (k && (lens[i] % (cxt->geom.heads * cxt->geom.sectors)))
	        fdisk_warnx(cxt, _("Partition %u doesn't end on cylinder boundary."), i+1);
	    if (lens[i]) {
	        for (j = 0; j < i; j++)
	            if (lens[j]) {
	                if (starts[j] == starts[i]+lens[i]) {
	                    starts[j] = starts[i]; lens[j] += lens[i];
	                    lens[i] = 0;
	                } else if (starts[i] == starts[j]+lens[j]){
	                    lens[j] += lens[i];
	                    lens[i] = 0;
	                } else if (!k) {
	                    if (starts[i] < starts[j]+lens[j] &&
				starts[j] < starts[i]+lens[i]) {
	                        starto = starts[i];
	                        if (starts[j] > starto)
					starto = starts[j];
	                        endo = starts[i]+lens[i];
	                        if (starts[j]+lens[j] < endo)
					endo = starts[j]+lens[j];
	                        fdisk_warnx(cxt, _("Partition %u overlaps with others in "
				       "sectors %u-%u."), i+1, starto, endo);
	                    }
	                }
	            }
	    }
	}
    }

#ifdef HAVE_QSORT_R
    for (i = 0; i < SUN_MAXPARTITIONS; i++) {
        if (lens[i])
            array[i] = i;
        else
            array[i] = -1;
    }
    verify_sun_starts = starts;

    qsort_r(array,ARRAY_SIZE(array),sizeof(array[0]),
	  (int (*)(const void *,const void *,void *)) verify_sun_cmp,
	  verify_sun_starts);

    if (array[0] == -1) {
	fdisk_info(cxt, _("No partitions defined."));
	return 0;
    }
    stop = cxt->geom.cylinders * cxt->geom.heads * cxt->geom.sectors;
    if (starts[array[0]])
        fdisk_warnx(cxt, _("Unused gap - sectors 0-%u."), starts[array[0]]);
    for (i = 0; i < 7 && array[i+1] != -1; i++) {
        fdisk_warnx(cxt, _("Unused gap - sectors %u-%u."),
	       (starts[array[i]] + lens[array[i]]),
	       starts[array[i+1]]);
    }
    start = (starts[array[i]] + lens[array[i]]);
    if (start < stop)
        fdisk_warnx(cxt, _("Unused gap - sectors %u-%u."), start, stop);
#endif
    return 0;
}
Exemple #17
0
static int sgi_create_disklabel(struct fdisk_context *cxt)
{
	struct fdisk_sgi_label *sgi;
	struct sgi_disklabel *sgilabel;
	struct hd_geometry geometry;
	sector_t llsectors;
	int res; 		/* the result from the ioctl */
	int sec_fac; 		/* the sector factor */

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

	sec_fac = cxt->sector_size / 512;	/* determine the sector factor */
	res = blkdev_get_sectors(cxt->dev_fd, &llsectors);

#ifdef HDIO_GETGEO
	/* TODO: it seems unnecessary, geometry is already set in the context */
	if (ioctl(cxt->dev_fd, HDIO_GETGEO, &geometry) < 0) {
		fdisk_warn(cxt, _("HDIO_GETGEO ioctl failed on %s"), cxt->dev_path);
		return -1;
	}
	cxt->geom.heads = geometry.heads;
	cxt->geom.sectors = geometry.sectors;
	if (res == 0) {
		/* the get device size ioctl was successful */
	        sector_t llcyls;
		llcyls = llsectors / (cxt->geom.heads * cxt->geom.sectors * sec_fac);
		cxt->geom.cylinders = llcyls;
		if (cxt->geom.cylinders != llcyls)	/* truncated? */
			cxt->geom.cylinders = ~0;
	} else {
		/* otherwise print error and use truncated version */
		cxt->geom.cylinders = geometry.cylinders;
		fdisk_warnx(cxt,
			_("Warning:  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);
	}
#endif
	fdisk_zeroize_firstsector(cxt);
	sgi = (struct fdisk_sgi_label *) cxt->label;
	sgi->header = (struct sgi_disklabel *) cxt->firstsector;

	sgilabel = sgi->header;

	sgilabel->magic = cpu_to_be32(SGI_LABEL_MAGIC);
	sgilabel->root_part_num = cpu_to_be16(0);
	sgilabel->swap_part_num = cpu_to_be16(1);

	/* sizeof(sgilabel->boot_file) = 16 > 6 */
	memset(sgilabel->boot_file, 0, 16);
	strcpy((char *) sgilabel->boot_file, "/unix");

	sgilabel->devparam.skew			= (0);
	sgilabel->devparam.gap1			= (0);
	sgilabel->devparam.gap2			= (0);
	sgilabel->devparam.sparecyl			= (0);
	sgilabel->devparam.pcylcount	= cpu_to_be16(geometry.cylinders);
	sgilabel->devparam.head_vol0	= cpu_to_be16(0);
	sgilabel->devparam.ntrks	= cpu_to_be16(geometry.heads);
	/* tracks/cylinder (heads) */
	sgilabel->devparam.cmd_tag_queue_depth	= (0);
	sgilabel->devparam.unused0			= (0);
	sgilabel->devparam.unused1	= cpu_to_be16(0);
	sgilabel->devparam.nsect	= cpu_to_be16(geometry.sectors);
	/* sectors/track */
	sgilabel->devparam.bytes	= cpu_to_be16(cxt->sector_size);
	sgilabel->devparam.ilfact	= cpu_to_be16(1);
	sgilabel->devparam.flags	= cpu_to_be32(
			SGI_DEVPARAM_TRACK_FWD
			| SGI_DEVPARAM_IGNORE_ERRORS
			| SGI_DEVPARAM_RESEEK);
	sgilabel->devparam.datarate	= cpu_to_be32(0);
	sgilabel->devparam.retries_on_error	= cpu_to_be32(1);
	sgilabel->devparam.ms_per_word		= cpu_to_be32(0);
	sgilabel->devparam.xylogics_gap1	= cpu_to_be16(0);
	sgilabel->devparam.xylogics_syncdelay	= cpu_to_be16(0);
	sgilabel->devparam.xylogics_readdelay	= cpu_to_be16(0);
	sgilabel->devparam.xylogics_gap2	= cpu_to_be16(0);
	sgilabel->devparam.xylogics_readgate	= cpu_to_be16(0);
	sgilabel->devparam.xylogics_writecont	= cpu_to_be16(0);

	memset(&(sgilabel->volume), 0,
			sizeof(struct sgi_volume) * SGI_MAXVOLUMES);
	memset(&(sgilabel->partitions), 0,
			sizeof(struct sgi_partition) * SGI_MAXPARTITIONS);
	cxt->label->nparts_max = SGI_MAXPARTITIONS;
	sgi_set_entire(cxt);
	sgi_set_volhdr(cxt);

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

	fdisk_sinfo(cxt, FDISK_INFO_SUCCESS,
			_("Created a new SGI disklabel."));
	return 0;
}
Exemple #18
0
static int sgi_add_partition(struct fdisk_context *cxt,
		size_t n,
		struct fdisk_parttype *t)
{
	struct fdisk_sgi_label *sgi;
	char mesg[256];
	unsigned int first = 0, last = 0;
	struct fdisk_ask *ask;
	int sys = t ? t->type : SGI_TYPE_XFS;
	int rc;

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

	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 %zd is already defined.  Delete "
			 "it before re-adding it."), n + 1);
		return -EINVAL;
	}
	if (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;
	}

	snprintf(mesg, sizeof(mesg), _("First %s"),
			fdisk_context_get_unit(cxt, 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 (sys == SGI_TYPE_ENTIRE_DISK) {
			last = sgi_get_lastblock(cxt);
			fdisk_ask_number_set_low(ask,     0);	/* minimal */
			fdisk_ask_number_set_default(ask, 0);	/* default */
			fdisk_ask_number_set_high(ask, last - 1); /* maximal */
		} else {
			first = sgi->freelist[0].first;
			last  = sgi->freelist[0].last;
			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_free_ask(ask);

		if (rc)
			return rc;

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

		if (fdisk_context_use_cylinders(cxt))
			first *= fdisk_context_get_units_per_sector(cxt);
		/*else
			first = first; * align to cylinder if you know how ... */
		if (!last)
			last = is_in_freelist(cxt, first);
		if (last == 0)
			fdisk_warnx(cxt, _("You will get a partition overlap "
				"on the disk. Fix it first!"));
		else
			break;
	}

	snprintf(mesg, sizeof(mesg),
		 _("Last %s or +%s or +size{K,M,G,T,P}"),
		 fdisk_context_get_unit(cxt, SINGULAR),
		 fdisk_context_get_unit(cxt, 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_context_use_cylinders(cxt))
		fdisk_ask_number_set_unit(ask,
			     cxt->sector_size *
			     fdisk_context_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_free_ask(ask);
	if (rc)
		return rc;

	if (fdisk_context_use_cylinders(cxt))
		last *= fdisk_context_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 eleventh "
			"partition covers the entire disk and is of type "
			"`SGI volume'"));

	sgi_set_partition(cxt, n, first, last - first, sys);
	cxt->label->nparts_cur = count_used_partitions(cxt);

	return 0;
}
Exemple #19
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;
}
Exemple #20
0
static int sgi_create_disklabel(struct fdisk_context *cxt)
{
	struct fdisk_sgi_label *sgi;
	struct sgi_disklabel *sgilabel;
	int rc;

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

#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) {
			/* the get device size ioctl was successful */
			fdisk_sector_t llcyls;
			int sec_fac = cxt->sector_size / 512;

			llcyls = llsectors / (cxt->geom.heads * cxt->geom.sectors * sec_fac);
			cxt->geom.cylinders = llcyls;
			if (cxt->geom.cylinders != llcyls)	/* truncated? */
				cxt->geom.cylinders = ~0;
		} else {
			/* otherwise print error and use truncated version */
			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);
		}
	}
#endif
	rc = fdisk_init_firstsector_buffer(cxt, 0, 0);
	if (rc)
		return rc;

	sgi = (struct fdisk_sgi_label *) cxt->label;
	sgi->header = (struct sgi_disklabel *) cxt->firstsector;

	sgilabel = sgi->header;

	sgilabel->magic = cpu_to_be32(SGI_LABEL_MAGIC);
	sgilabel->root_part_num = cpu_to_be16(0);
	sgilabel->swap_part_num = cpu_to_be16(1);

	/* sizeof(sgilabel->boot_file) = 16 > 6 */
	memset(sgilabel->boot_file, 0, 16);
	strcpy((char *) sgilabel->boot_file, "/unix");

	sgilabel->devparam.skew			= (0);
	sgilabel->devparam.gap1			= (0);
	sgilabel->devparam.gap2			= (0);
	sgilabel->devparam.sparecyl			= (0);
	sgilabel->devparam.pcylcount	= cpu_to_be16(cxt->geom.cylinders);
	sgilabel->devparam.head_vol0	= cpu_to_be16(0);
	sgilabel->devparam.ntrks	= cpu_to_be16(cxt->geom.heads);
	/* tracks/cylinder (heads) */
	sgilabel->devparam.cmd_tag_queue_depth	= (0);
	sgilabel->devparam.unused0			= (0);
	sgilabel->devparam.unused1	= cpu_to_be16(0);
	sgilabel->devparam.nsect	= cpu_to_be16(cxt->geom.sectors);
	/* sectors/track */
	sgilabel->devparam.bytes	= cpu_to_be16(cxt->sector_size);
	sgilabel->devparam.ilfact	= cpu_to_be16(1);
	sgilabel->devparam.flags	= cpu_to_be32(
			SGI_DEVPARAM_TRACK_FWD
			| SGI_DEVPARAM_IGNORE_ERRORS
			| SGI_DEVPARAM_RESEEK);
	sgilabel->devparam.datarate	= cpu_to_be32(0);
	sgilabel->devparam.retries_on_error	= cpu_to_be32(1);
	sgilabel->devparam.ms_per_word		= cpu_to_be32(0);
	sgilabel->devparam.xylogics_gap1	= cpu_to_be16(0);
	sgilabel->devparam.xylogics_syncdelay	= cpu_to_be16(0);
	sgilabel->devparam.xylogics_readdelay	= cpu_to_be16(0);
	sgilabel->devparam.xylogics_gap2	= cpu_to_be16(0);
	sgilabel->devparam.xylogics_readgate	= cpu_to_be16(0);
	sgilabel->devparam.xylogics_writecont	= cpu_to_be16(0);

	memset(&(sgilabel->volume), 0,
			sizeof(struct sgi_volume) * SGI_MAXVOLUMES);
	memset(&(sgilabel->partitions), 0,
			sizeof(struct sgi_partition) * SGI_MAXPARTITIONS);
	cxt->label->nparts_max = SGI_MAXPARTITIONS;

	/* don't create default layout when a script defined */
	if (!cxt->script) {
		sgi_set_entire(cxt);
		sgi_set_volhdr(cxt);
	}
	cxt->label->nparts_cur = count_used_partitions(cxt);

	fdisk_info(cxt, _("Created a new SGI disklabel."));
	return 0;
}
Exemple #21
0
static int sun_create_disklabel(struct fdisk_context *cxt)
{
    struct hd_geometry geometry;
    sector_t llsectors, llcyls;
    unsigned int ndiv, sec_fac;
    int res;

    struct fdisk_sun_label *sun;		/* libfdisk sun handler */
    struct sun_disklabel *sunlabel;	/* on disk data */

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

    /* map first sector to header */
    fdisk_zeroize_firstsector(cxt);
    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);

    res = blkdev_get_sectors(cxt->dev_fd, &llsectors);
    sec_fac = cxt->sector_size / 512;

#ifdef HDIO_GETGEO
    if (!ioctl(cxt->dev_fd, HDIO_GETGEO, &geometry)) {
        cxt->geom.heads = geometry.heads;
        cxt->geom.sectors = geometry.sectors;
        if (res == 0) {
            llcyls = llsectors / (cxt->geom.heads * cxt->geom.sectors * sec_fac);
            cxt->geom.cylinders = llcyls;
            if (cxt->geom.cylinders != llcyls)
                cxt->geom.cylinders = ~0;
        } else {
            cxt->geom.cylinders = geometry.cylinders;
            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 %llu alt %u hd %u sec %llu",
             cxt->geom.cylinders, be16_to_cpu(sunlabel->acyl),
             cxt->geom.heads, 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;

    set_sun_partition(cxt, 0, 0, ndiv * cxt->geom.heads * cxt->geom.sectors,
                      SUN_TAG_LINUX_NATIVE);
    set_sun_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_sun_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_sinfo(cxt, FDISK_INFO_SUCCESS,
                _("Created a new Sun disklabel."));
    return 0;
}
Exemple #22
0
/*
 * Uses template @tpl to recount start and size change of the partition @res. The
 * @tpl->size and @tpl->start are interpreted as relative to the current setting.
 */
static int recount_resize(
			struct fdisk_context *cxt, size_t partno,
			struct fdisk_partition *res, struct fdisk_partition *tpl)
{
	fdisk_sector_t start, size;
	struct fdisk_partition *cur = NULL;
	struct fdisk_table *tb = NULL;
	int rc;

	DBG(PART, ul_debugobj(tpl, "resize requested"));

	FDISK_INIT_UNDEF(start);
	FDISK_INIT_UNDEF(size);

	rc = fdisk_get_partitions(cxt, &tb);
	if (!rc)
		rc = fdisk_get_freespaces(cxt, &tb);
	if (rc)
		return rc;

	cur = fdisk_table_get_partition_by_partno(tb, partno);
	if (!cur) {
		fdisk_unref_table(tb);
		return -EINVAL;
	}

	/* 1a) set new start - change relative to the current on-disk setting */
	if (tpl->movestart && fdisk_partition_has_start(tpl)) {
		start = fdisk_partition_get_start(cur);
		if (tpl->movestart == FDISK_MOVE_DOWN) {
			if (fdisk_partition_get_start(tpl) > start)
				goto erange;
			start -= fdisk_partition_get_start(tpl);
		} else
			start += fdisk_partition_get_start(tpl);

	/* 1b) set new start - absolute number */
	} else if (fdisk_partition_has_start(tpl))
		start = fdisk_partition_get_start(tpl);

	/* 2) verify that start is within the current partition or any freespace area */
	if (!FDISK_IS_UNDEF(start)) {
		struct fdisk_partition *area = resize_get_by_offset(tb, start);
		if (area == cur)
			DBG(PART, ul_debugobj(tpl, "resize: start points to the current partition"));
		else if (area && fdisk_partition_is_freespace(area))
			DBG(PART, ul_debugobj(tpl, "resize: start points to freespace"));
		else if (!area && start >= cxt->first_lba && start < cxt->first_lba + (cxt->grain / cxt->sector_size))
			DBG(PART, ul_debugobj(tpl, "resize: start points before first partition"));
		else
			goto erange;
	} else {
		/* no change, start points to the current partition */
		start = fdisk_partition_get_start(cur);
	}

	/* 3a) set new size -- reduce */
	if (tpl->resize == FDISK_RESIZE_REDUCE && fdisk_partition_has_size(tpl)) {
		DBG(PART, ul_debugobj(tpl, "resize: reduce"));
		size = fdisk_partition_get_size(cur);
		if (fdisk_partition_get_size(tpl) > size)
			goto erange;
		size -= fdisk_partition_get_size(tpl);

	/* 3b) set new size -- enlarge */
	} else if (tpl->resize == FDISK_RESIZE_ENLARGE && fdisk_partition_has_size(tpl)) {
		DBG(PART, ul_debugobj(tpl, "resize: enlarge"));
		size = fdisk_partition_get_size(cur);
		size += fdisk_partition_get_size(tpl);

	/* 3c) set new size -- no size specified, enlarge to all freespace */
	} else if (tpl->resize == FDISK_RESIZE_ENLARGE) {
		DBG(PART, ul_debugobj(tpl, "resize: enlarge to all possible"));
		if (resize_get_last_possible(tb, cur, start, &size))
			goto erange;

	/* 3d) set new size -- absolute number */
	} else if (fdisk_partition_has_size(tpl)) {
		DBG(PART, ul_debugobj(tpl, "resize: new absolute size"));
		size = fdisk_partition_get_size(tpl);
	}

	/* 4) verify that size is within the current partition or next free space */
	if (!FDISK_IS_UNDEF(size)) {
		fdisk_sector_t maxsz;
		if (resize_get_last_possible(tb, cur, start, &maxsz))
			goto erange;
		DBG(PART, ul_debugobj(tpl, "resize: size wanted=%ju, max=%ju",
					(uintmax_t) size, (uintmax_t) maxsz));
		if (size > maxsz)
			goto erange;
	}

	DBG(PART, ul_debugobj(tpl, "resize: SUCCESS: start %ju->%ju; size %ju->%ju",
			(uintmax_t) fdisk_partition_get_start(cur), (uintmax_t) start,
			(uintmax_t) fdisk_partition_get_size(cur), (uintmax_t) size));
	res->start = start;
	res->size = size;
	fdisk_unref_table(tb);
	return 0;
erange:
	DBG(PART, ul_debugobj(tpl, "resize: FAILED"));
	fdisk_warnx(cxt, _("Failed to resize partition #%zu."), partno + 1);
	fdisk_unref_table(tb);
	return -ERANGE;

}
Exemple #23
0
static int sun_probe_label(struct fdisk_context *cxt)
{
	struct fdisk_sun_label *sun;
	struct sun_disklabel *sunlabel;
	unsigned short *ush;
	int csum;
	int need_fixing = 0;

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

	/* map first sector to header */
	sun = (struct fdisk_sun_label *) cxt->label;
	sun->header = (struct sun_disklabel *) cxt->firstsector;
	sunlabel = sun->header;

	if (be16_to_cpu(sunlabel->magic) != SUN_LABEL_MAGIC) {
		sun->header = NULL;
		return 0;		/* failed */
	}

	ush = ((unsigned short *) (sunlabel + 1)) - 1;
	for (csum = 0; ush >= (unsigned short *)sunlabel;)
		csum ^= *ush--;

	if (csum) {
		fdisk_warnx(cxt, _("Detected sun disklabel with wrong checksum. "
			      "Probably you'll have to set all the values, "
			      "e.g. heads, sectors, cylinders and partitions "
			      "or force a fresh label (s command in main menu)"));
		return 1;
	}

	cxt->label->nparts_max = SUN_MAXPARTITIONS;
	cxt->geom.heads = be16_to_cpu(sunlabel->nhead);
	cxt->geom.cylinders = be16_to_cpu(sunlabel->ncyl);
	cxt->geom.sectors = be16_to_cpu(sunlabel->nsect);

	if (be32_to_cpu(sunlabel->vtoc.version) != SUN_VTOC_VERSION) {
		fdisk_warnx(cxt, _("Detected sun disklabel with wrong version [%d]."),
			be32_to_cpu(sunlabel->vtoc.version));
		need_fixing = 1;
	}
	if (be32_to_cpu(sunlabel->vtoc.sanity) != SUN_VTOC_SANITY) {
		fdisk_warnx(cxt, _("Detected sun disklabel with wrong vtoc.sanity [0x%08x]."),
			be32_to_cpu(sunlabel->vtoc.sanity));
		need_fixing = 1;
	}
	if (be16_to_cpu(sunlabel->vtoc.nparts) != SUN_MAXPARTITIONS) {
		fdisk_warnx(cxt, _("Detected sun disklabel with wrong vtoc.nparts [%u]."),
			be16_to_cpu(sunlabel->vtoc.nparts));
		need_fixing = 1;
	}
	if (need_fixing) {
		fdisk_warnx(cxt, _("Warning: Wrong values need to be fixed up and "
			           "will be corrected by w(rite)"));

		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);

		ush = (unsigned short *)sunlabel;
		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);

	return 1;
}
Exemple #24
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;
}
Exemple #25
0
int fdisk_bsd_write_bootstrap(struct fdisk_context *cxt)
{
    struct bsd_disklabel dl, *d = self_disklabel(cxt);
    struct fdisk_bsd_label *l = self_label(cxt);
    char *name = d->d_type == BSD_DTYPE_SCSI ? "sd" : "wd";
    char buf[BUFSIZ];
    char *res, *dp, *p;
    int rc;
    sector_t sector;

    snprintf(buf, sizeof(buf),
             _("Bootstrap: %1$sboot -> boot%1$s (default %1$s)"),
             name);
    rc = fdisk_ask_string(cxt, buf, &res);
    if (rc)
        goto done;
    if (res && *res)
        name = res;

    snprintf(buf, sizeof(buf), "%s/%sboot", BSD_LINUX_BOOTDIR, name);
    rc = bsd_get_bootstrap(cxt, buf, l->bsdbuffer,	(int) d->d_secsize);
    if (rc)
        goto done;

    /* We need a backup of the disklabel (might have changed). */
    dp = &l->bsdbuffer[BSD_LABELSECTOR * DEFAULT_SECTOR_SIZE];
    memmove(&dl, dp, sizeof(struct bsd_disklabel));

    /* The disklabel will be overwritten by 0's from bootxx anyway */
    memset(dp, 0, sizeof(struct bsd_disklabel));

    snprintf(buf, sizeof(buf), "%s/boot%s", BSD_LINUX_BOOTDIR, name);
    rc = bsd_get_bootstrap(cxt, buf,
                           &l->bsdbuffer[d->d_secsize],
                           (int) d->d_bbsize - d->d_secsize);
    if (rc)
        goto done;

    /* check end of the bootstrap */
    for (p = dp; p < dp + sizeof(struct bsd_disklabel); p++) {
        if (!*p)
            continue;
        fdisk_warnx(cxt, _("Bootstrap overlaps with disklabel!"));
        return -EINVAL;
    }

    /* move disklabel back */
    memmove(dp, &dl, sizeof(struct bsd_disklabel));

    sector = 0;
    if (l->dos_part)
        sector = dos_partition_get_start(l->dos_part);
#if defined (__alpha__)
    alpha_bootblock_checksum(l->bsdbuffer);
#endif
    if (lseek(cxt->dev_fd, (off_t) sector * DEFAULT_SECTOR_SIZE, SEEK_SET) == -1) {
        fdisk_warn(cxt, _("seek on %s failed"), cxt->dev_path);
        rc = -errno;
        goto done;
    }
    if (write_all(cxt->dev_fd, l->bsdbuffer, BSD_BBSIZE)) {
        fdisk_warn(cxt, _("cannot write %s"), cxt->dev_path);
        rc = -errno;
        goto done;
    }

    fdisk_sinfo(cxt, FDISK_INFO_SUCCESS,
                _("Bootstrap installed on %s."), cxt->dev_path);
    sync_disks(cxt);

    rc = 0;
done:
    free(res);
    return rc;
}
Exemple #26
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;
}
Exemple #27
0
int main(int argc, char **argv)
{
	int i, c, act = ACT_FDISK;
	int colormode = UL_COLORMODE_AUTO;
	struct fdisk_context *cxt;

	setlocale(LC_ALL, "");
	bindtextdomain(PACKAGE, LOCALEDIR);
	textdomain(PACKAGE);
	atexit(close_stdout);

	fdisk_init_debug(0);
	cxt = fdisk_new_context();
	if (!cxt)
		err(EXIT_FAILURE, _("failed to allocate libfdisk context"));

	fdisk_context_set_ask(cxt, ask_callback, NULL);

	while ((c = getopt(argc, argv, "b:c::C:hH:lL::sS:t:u::vV")) != -1) {
		switch (c) {
		case 'b':
		{
			size_t sz = strtou32_or_err(optarg,
					_("invalid sector size argument"));
			if (sz != 512 && sz != 1024 && sz != 2048 && sz != 4096)
				usage(stderr);
			fdisk_save_user_sector_size(cxt, sz, sz);
			break;
		}
		case 'C':
			fdisk_save_user_geometry(cxt,
				strtou32_or_err(optarg,
						_("invalid cylinders argument")),
				0, 0);
			break;
		case 'c':
			if (optarg) {
				/* this setting is independent on the current
				 * actively used label */
				struct fdisk_label *lb = fdisk_context_get_label(cxt, "dos");
				if (!lb)
					err(EXIT_FAILURE, _("not found DOS label driver"));
				if (strcmp(optarg, "=dos") == 0)
					fdisk_dos_enable_compatible(lb, TRUE);
				else if (strcmp(optarg, "=nondos") == 0)
					fdisk_dos_enable_compatible(lb, FALSE);
				else
					usage(stderr);
			}
			/* use default if no optarg specified */
			break;
		case 'H':
			fdisk_save_user_geometry(cxt, 0,
				strtou32_or_err(optarg,
						_("invalid heads argument")),
				0);
			break;
		case 'S':
			fdisk_save_user_geometry(cxt, 0, 0,
				strtou32_or_err(optarg,
					_("invalid sectors argument")));
			break;
		case 'l':
			act = ACT_LIST;
			break;
		case 'L':
			if (optarg)
				colormode = colormode_or_err(optarg,
						_("unsupported color mode"));
			break;
		case 's':
			act = ACT_SHOWSIZE;
			break;
		case 't':
		{
			struct fdisk_label *lb = NULL;

			while (fdisk_context_next_label(cxt, &lb) == 0)
				fdisk_label_set_disabled(lb, 1);

			lb = fdisk_context_get_label(cxt, optarg);
			if (!lb)
				errx(EXIT_FAILURE, _("unsupported disklabel: %s"), optarg);
			fdisk_label_set_disabled(lb, 0);
		}
		case 'u':
			if (optarg && *optarg == '=')
				optarg++;
			if (fdisk_context_set_unit(cxt, optarg) != 0)
				usage(stderr);
			break;
		case 'V':
		case 'v':
			printf(UTIL_LINUX_VERSION);
			return EXIT_SUCCESS;
		case 'h':
			usage(stdout);
		default:
			usage(stderr);
		}
	}

	if (argc-optind != 1 && fdisk_has_user_device_properties(cxt))
		warnx(_("The device properties (sector size and geometry) should"
			" be used with one specified device only."));

	colors_init(colormode);

	switch (act) {
	case ACT_LIST:
		fdisk_context_enable_listonly(cxt, 1);

		if (argc > optind) {
			int k;
			for (k = optind; k < argc; k++)
				print_device_pt(cxt, argv[k]);
		} else
			print_all_devices_pt(cxt);
		break;

	case ACT_SHOWSIZE:
		/* deprecated */
		if (argc - optind <= 0)
			usage(stderr);

		for (i = optind; i < argc; i++) {
			if (argc - optind == 1)
				printf("%llu\n", get_dev_blocks(argv[i]));
			else
				printf("%s: %llu\n", argv[i], get_dev_blocks(argv[i]));
		}
		break;

	case ACT_FDISK:
		if (argc-optind != 1)
			usage(stderr);

		if (fdisk_context_assign_device(cxt, argv[optind], 0) != 0)
			err(EXIT_FAILURE, _("cannot open %s"), argv[optind]);

		/* Here starts interactive mode, use fdisk_{warn,info,..} functions */
		color_enable(UL_COLOR_GREEN);
		fdisk_info(cxt, _("Welcome to fdisk (%s)."), PACKAGE_STRING);
		color_disable();
		fdisk_info(cxt, _("Changes will remain in memory only, until you decide to write them.\n"
				  "Be careful before using the write command.\n"));
		fflush(stdout);

		if (!fdisk_dev_has_disklabel(cxt)) {
			fdisk_warnx(cxt, _("Device does not contain a recognized partition table."));
			fdisk_create_disklabel(cxt, NULL);
		}

		while (1)
			process_fdisk_menu(&cxt);
	}

	fdisk_free_context(cxt);
	return EXIT_SUCCESS;
}