Beispiel #1
0
/* Ask for a partition size, check bounds and do the needed roundups */
static uint32_t
getpartsize(uint32_t partstart, uint32_t defpartsize)
{
	char dsize[20], isize[20], maxpartc;
	const char *errmsg = "\n";
	uint32_t i, partend, localsizemult;
	uint32_t fsptend = pm->ptstart + pm->ptsize;
	int partn;

	maxpartc = 'a' + getmaxpartitions() - 1;
	for (;;) {
		snprintf(dsize, sizeof dsize, "%d", defpartsize/sizemult);
		msg_prompt_win(MSG_label_size, -1, 12, 70, 9,
		    (defpartsize != 0) ? dsize : 0, isize, sizeof isize,
		    errmsg, maxpartc, multname);
		if (strcmp(isize, dsize) == 0)
			return defpartsize;
		if (isize[1] == '\0' && isize[0] >= 'a' &&
		    isize[0] <= maxpartc) {
			partn = isize[0] - 'a';
			i = pm->bsdlabel[partn].pi_offset - partstart;
			localsizemult = 1;
		} else if (atoi(isize) == -1) {
			i = fsptend - partstart;
			localsizemult = 1;
		} else {
			if (atofsb(isize, &i, &localsizemult)) {
				errmsg = msg_string(MSG_invalid_sector_number);
				continue;
			}
		}
		/*
		 * partend is aligned to a cylinder if localsizemult
		 * is not 1 sector
		 */
		partend = NUMSEC((partstart + i) / localsizemult,
		    localsizemult, pm->dlcylsize);
		/* Align to end-of-disk or end-of-slice if close enough */
		if (partend > (pm->dlsize - localsizemult)
		    && partend < (pm->dlsize + localsizemult))
			partend = pm->dlsize;
		if (partend > (fsptend - localsizemult)
		    && partend < (fsptend + localsizemult))
			partend = fsptend;
		/* sanity checks */
		if (partend > pm->dlsize) {
			partend = pm->dlsize;
			msg_prompt_win(MSG_endoutsidedisk, -1, 13, 70, 6,
			    NULL, isize, 1,
			    (partend - partstart) / sizemult, multname);
		}
		if (partend < partstart)
			return 0;
		return (partend - partstart);
	}
	/* NOTREACHED */
}
Beispiel #2
0
static void
cmd_help(struct disklabel *lp, char *s, int fd)
{
	struct cmds *cmd;

	for (cmd = cmds; cmd->name != NULL; cmd++)
		printf("%s\t%s\n", cmd->name, cmd->help);
	printf("[a-%c]\tdefine named partition\n",
	    'a' + getmaxpartitions() - 1);
}
Beispiel #3
0
/*
 * Check a disklabel.
 * If there are overlapping active partitions,
 * Ask the user if they want to edit the partition or give up.
 */
int
edit_and_check_label(partinfo *lp, int nparts, int rawpart, int bsdpart)
{
	static struct menu_ent *menu;
	static int menu_no = -1;
	static struct ptn_menu_info pi;
	int maxpart = getmaxpartitions();

	if (menu == NULL) {
		menu = malloc((maxpart + 1) * sizeof *menu);
		if (!menu)
			return 1;
	}

	if (menu_no == -1) {
		menu_no = new_menu(NULL, menu, maxpart + 1,
			0, -1, maxpart + 2, 74,
			MC_ALWAYS_SCROLL | MC_NOBOX | MC_DFLTEXIT,
			set_label_texts, fmt_fspart, NULL, NULL,
			MSG_partition_sizes_ok);
	}

	if (menu_no < 0)
		return 1;

	pi.flags = 0;
	pm->current_cylsize = pm->dlcylsize;

	for (;;) {
		/* first give the user the option to edit the label... */
		process_menu(menu_no, &pi);

		/* User thinks the label is OK. */
		/* check we have a single root fs */
		if (check_one_root(lp, nparts) == 0 && partman_go == 0)
			msg_display(MSG_must_be_one_root);
		else 
			/* Check for overlaps */
			if (checkoverlap(lp, nparts, rawpart, bsdpart) == 0)
				return 1;

		/*XXX ???*/
		msg_display_add(MSG_edit_partitions_again);
		if (!ask_yesno(NULL))
			return(0);
	}

	/*NOTREACHED*/
}
Beispiel #4
0
static void
set_label_texts(menudesc *menu, void *arg)
{
	struct ptn_menu_info *pi = arg;
	menu_ent *m;
	int ptn, show_unused_ptn;
	int rawptn = getrawpartition();
	int maxpart = getmaxpartitions();

	msg_display(MSG_fspart);
	msg_table_add(MSG_fspart_header, multname, multname, multname);

	for (show_unused_ptn = 0, ptn = 0; ptn < maxpart; ptn++) {
		m = &menu->opts[ptn];
		m->opt_menu = OPT_NOMENU;
		m->opt_name = NULL;
		m->opt_action = edit_ptn;
		if (ptn == rawptn
#ifdef PART_BOOT
		    || ptn == PART_BOOT
#endif
		    || ptn == PART_C) {
			m->opt_flags = OPT_IGNORE;
		} else {
			m->opt_flags = 0;
			if (pm->bsdlabel[ptn].pi_fstype == FS_UNUSED)
				continue;
		}
		show_unused_ptn = ptn + 2;
	}

	if (!(pi->flags & PIF_SHOW_UNUSED) && ptn > show_unused_ptn) {
		ptn = show_unused_ptn;
		m = &menu->opts[ptn];
		m->opt_name = MSG_show_all_unused_partitions;
		m->opt_action = show_all_unused;
		ptn++;
	}

	m = &menu->opts[ptn];
	m->opt_menu = MENU_sizechoice; 
	m->opt_flags = OPT_SUB; 
	m->opt_action = NULL;
	m->opt_name = MSG_askunits;

	menu->numopts = ptn + 1;
}
Beispiel #5
0
/* Ask for a partition offset, check bounds and do the needed roundups */
static uint32_t
getpartoff(uint32_t defpartstart)
{
	char defsize[20], isize[20], maxpartc;
	uint32_t i;
	uint32_t localsizemult;
	int partn;
	const char *errmsg = "\n";

	maxpartc = 'a' + getmaxpartitions() - 1;
	for (;;) {
		snprintf(defsize, sizeof defsize, "%d", defpartstart/sizemult);
		msg_prompt_win(MSG_label_offset, -1, 13, 70, 9,
		    (defpartstart > 0) ? defsize : NULL, isize, sizeof isize,
		    errmsg, maxpartc, maxpartc, multname);
		if (strcmp(defsize, isize) == 0)
			/* Don't do rounding if default accepted */
			return defpartstart;
		if (isize[1] == '\0' && isize[0] >= 'a' &&
		    isize[0] <= maxpartc) {
			partn = isize[0] - 'a';
			i = pm->bsdlabel[partn].pi_size + pm->bsdlabel[partn].pi_offset;
			localsizemult = 1;
		} else if (atoi(isize) == -1) {
			i = pm->ptstart;
			localsizemult = 1;
		} else {
			if (atofsb(isize, &i, &localsizemult)) {
				errmsg = msg_string(MSG_invalid_sector_number);
				continue;
			}
		}
		/* round to cylinder size if localsizemult != 1 */
		i = NUMSEC(i/localsizemult, localsizemult, pm->dlcylsize);
		/* Adjust to start of slice if needed */
		if ((i < pm->ptstart && (pm->ptstart - i) < localsizemult) ||
		    (i > pm->ptstart && (i - pm->ptstart) < localsizemult)) {
			i = pm->ptstart;
		}
		if (i <= pm->dlsize)
			break;
		errmsg = msg_string(MSG_startoutsidedisk);
	}
	return i;
}
Beispiel #6
0
/*
 * Read a label from disk into a sysinst label structure.
 */
int
incorelabel(const char *dkname, partinfo *lp)
{
	struct disklabel lab;
	int i, maxpart;
	struct partition *pp;
	int fd;
	char buf[64];

	if (get_real_geom(dkname, &lab) == 0)
		return -1;

	touchwin(stdscr);
	maxpart = getmaxpartitions();
	if (maxpart > MAXPARTITIONS)
		maxpart = MAXPARTITIONS;
	if (maxpart > lab.d_npartitions)
		maxpart = lab.d_npartitions;

	/*
	 * Historically sysinst writes the name to d_typename rather
	 * than d_diskname.  Who knows why, but pull the value back here.
	 */
	if (lab.d_typename[0] != 0 && strcmp(lab.d_typename, "unknown") != 0)
		strlcpy(pm->bsddiskname, lab.d_typename, sizeof pm->bsddiskname);

	fd = opendisk(dkname, O_RDONLY, buf, sizeof buf, 0);
	pp = &lab.d_partitions[0];
	for (i = 0; i < maxpart; lp++, pp++, i++) {
		lp->pi_partition = *pp;
		if (lp->pi_fstype >= FSMAXTYPES)
			lp->pi_fstype = FS_OTHER;
		strlcpy(lp->pi_mount, get_last_mounted(fd, pp->p_offset, lp),
			sizeof lp->pi_mount);
	}
	if (fd != -1)
		close(fd);

	return 0;
}
Beispiel #7
0
static int
runcmd(struct disklabel *lp, char *line, int fd)
{
	struct cmds *cmd;

	for (cmd = cmds; cmd->name != NULL; cmd++)
		if (strncmp(line, cmd->name, strlen(cmd->name)) == 0) {
			if (cmd->func == NULL)
				return -1;
			(*cmd->func)(lp, line, fd);
			return 0;
		}

	if (line[1] == '\0' &&
	    line[0] >= 'a' && line[0] < 'a' + getmaxpartitions()) {
		cmd_part(lp, line, fd);
		return 0;
	}
		
	printf("Unknown command %s\n", line);
	return 1;
}
Beispiel #8
0
static void
cmd_part(struct disklabel *lp, char *s, int fd)
{
	int	i;
	intmax_t im;
	char	line[BUFSIZ];
	char	def[BUFSIZ];
	int	part;
	struct partition *p, ps;

	part = s[0] - 'a';
	p = &lp->d_partitions[part];
	if (part >= lp->d_npartitions)
		lp->d_npartitions = part + 1;

	(void)memcpy(&ps, p, sizeof(ps));

	for (;;) {
		i = p->p_fstype;
		if (i < 0 || i >= FSMAXTYPES)
			i = 0;
		i = getinput(line, "Filesystem type [%s]: ", fstypenames[i]);
		if (i == -1)
			return;
		else if (i == 0)
			break;
		if (!strcmp(line, "?")) {
			dumpnames("Supported file system types",
			    fstypenames, FSMAXTYPES);
			continue;
		}
		for (i = 0; i < FSMAXTYPES; i++)
			if (!strcasecmp(line, fstypenames[i])) {
				p->p_fstype = i;
				goto done_typename;
			}
		printf("Invalid file system typename `%s'\n", line);
		continue;
 done_typename:
		break;
	}
	for (;;) {
		defnum(lp, def, p->p_offset);
		i = getinput(line, "Start offset ('x' to start after partition"
		" 'x') [%s]: ", def);
		if (i == -1)
			return;
		else if (i == 0)
			break;
		if (line[1] == '\0' &&
	    		line[0] >= 'a' && line[0] < 'a' + getmaxpartitions()) {
			struct partition *cp = lp->d_partitions;

			if ((cp[line[0] - 'a'].p_offset +
			    cp[line[0] - 'a'].p_size) >= lp->d_secperunit) {
				printf("Bad offset `%s'\n", line);
				continue;
			} else {
				p->p_offset = cp[line[0] - 'a'].p_offset +
				    cp[line[0] - 'a'].p_size;
			}
		} else {
			if ((im = getnum(lp, line, 0)) == -1 || im < 0) {
				printf("Bad offset `%s'\n", line);
				continue;
			} else if (im > 0xffffffffLL ||
				   (uint32_t)im > lp->d_secperunit) {
				printf("Offset `%s' out of range\n", line);
				continue;
			}
			p->p_offset = (uint32_t)im;
		}
		break;
	}
	for (;;) {
		defnum(lp, def, p->p_size);
		i = getinput(line, "Partition size ('$' for all remaining) "
		    "[%s]: ", def);
		if (i == -1)
			return;
		else if (i == 0)
			break;
		if ((im = getnum(lp, line, lp->d_secperunit - p->p_offset))
		    == -1) {
			printf("Bad size `%s'\n", line);
			continue;
		} else if (im > 0xffffffffLL ||
			   (im + p->p_offset) > lp->d_secperunit) {
			printf("Size `%s' out of range\n", line);
			continue;
		}
		p->p_size = im;
		break;
	}

	if (memcmp(&ps, p, sizeof(ps)))
		showpartition(stdout, lp, part, Cflag);
	if (chaining) {
		int offs = -1;
		struct partition *cp = lp->d_partitions;
		for (i = 0; i < lp->d_npartitions; i++) {
			if (cp[i].p_fstype != FS_UNUSED) {
				if (offs != -1 && cp[i].p_offset != (uint32_t)offs) {
					cp[i].p_offset = offs;
					showpartition(stdout, lp, i, Cflag);
					}
				offs = cp[i].p_offset + cp[i].p_size;
			}
		}
	}
}
Beispiel #9
0
int
main(int argc, char *argv[])
{
	int ch;
	struct partition *pp;
	struct disklabel *lp;
	struct partition oldpartition;
	struct stat st;
	struct statfs *mp;
	struct rlimit rl;
	int fsi = -1, fso, len, n, maxpartitions;
	char *cp = NULL, *s1, *s2, *special, *opstring, *realdev;
	char *fstype = NULL;
	char **saveargv = argv;
	int ffsflag = 1;
	const char *errstr;
	long long fssize_input = 0;
	int fssize_usebytes = 0;
	u_int64_t nsecs;

	getphysmem();
	maxpartitions = getmaxpartitions();
	if (maxpartitions > 26)
		fatal("insane maxpartitions value %d", maxpartitions);

	opstring = "NO:S:T:b:c:e:f:g:h:i:m:o:qs:t:";
	while ((ch = getopt(argc, argv, opstring)) != -1) {
		switch (ch) {
		case 'N':
			Nflag = 1;
			break;
		case 'O':
			Oflag = strtonum(optarg, 0, 2, &errstr);
			if (errstr)
				fatal("%s: invalid ffs version", optarg);
			break;
		case 'S':
			if (scan_scaled(optarg, &sectorsize) == -1 ||
			    sectorsize <= 0 || (sectorsize % DEV_BSIZE))
				fatal("sector size invalid: %s", optarg);
			break;
		case 'T':
			disktype = optarg;
			break;
		case 'b':
			bsize = strtonum(optarg, MINBSIZE, MAXBSIZE, &errstr);
			if (errstr)
				fatal("block size is %s: %s", errstr, optarg);
			break;
		case 'c':
			maxfrgspercg = strtonum(optarg, 1, INT_MAX, &errstr);
			if (errstr)
				fatal("fragments per cylinder group is %s: %s",
				    errstr, optarg);
			break;
		case 'e':
			maxbpg = strtonum(optarg, 1, INT_MAX, &errstr);
			if (errstr)
				fatal("blocks per file in a cylinder group is"
				    " %s: %s", errstr, optarg);
			break;
		case 'f':
			fsize = strtonum(optarg, MINBSIZE / MAXFRAG, MAXBSIZE,
			    &errstr);
			if (errstr)
				fatal("fragment size is %s: %s",
				    errstr, optarg);
			break;
		case 'g':
			avgfilesize = strtonum(optarg, 1, INT_MAX, &errstr);
			if (errstr)
				fatal("average file size is %s: %s",
				    errstr, optarg);
			break;
		case 'h':
			avgfilesperdir = strtonum(optarg, 1, INT_MAX, &errstr);
			if (errstr)
				fatal("average files per dir is %s: %s",
				    errstr, optarg);
			break;
		case 'i':
			density = strtonum(optarg, 1, INT_MAX, &errstr);
			if (errstr)
				fatal("bytes per inode is %s: %s",
				    errstr, optarg);
			break;
		case 'm':
			minfree = strtonum(optarg, 0, 99, &errstr);
			if (errstr)
				fatal("free space %% is %s: %s",
				    errstr, optarg);
			break;
		case 'o':
			if (strcmp(optarg, "space") == 0)
				reqopt = opt = FS_OPTSPACE;
			else if (strcmp(optarg, "time") == 0)
				reqopt = opt = FS_OPTTIME;
			else
				fatal("%s: unknown optimization preference: "
				    "use `space' or `time'.", optarg);
			break;
		case 'q':
			quiet = 1;
			break;
		case 's':
			if (scan_scaled(optarg, &fssize_input) == -1 ||
			    fssize_input == 0)
				fatal("file system size invalid: %s", optarg);
			fssize_usebytes = 0;    /* in case of multiple -s */
			for (s1 = optarg; *s1 != '\0'; s1++)
				if (isalpha((unsigned char)*s1)) {
					fssize_usebytes = 1;
					break;
				}
			break;
		case 't':
			fstype = optarg;
			if (strcmp(fstype, "ffs"))
				ffsflag = 0;
			break;
		case '?':
		default:
			usage();
		}
		if (!ffsflag)
			break;
	}
	argc -= optind;
	argv += optind;

	if (ffsflag && argc != 1)
		usage();

	special = argv[0];

	char execname[MAXPATHLEN], name[MAXPATHLEN];

	if (fstype == NULL)
		fstype = readlabelfs(special, 0);
	if (fstype != NULL && strcmp(fstype, "ffs")) {
		snprintf(name, sizeof name, "newfs_%s", fstype);
		saveargv[0] = name;
		snprintf(execname, sizeof execname, "%s/newfs_%s", _PATH_SBIN,
		    fstype);
		(void)execv(execname, saveargv);
		snprintf(execname, sizeof execname, "%s/newfs_%s",
		    _PATH_USRSBIN, fstype);
		(void)execv(execname, saveargv);
		err(1, "%s not found", name);
	}

	if (Nflag) {
		fso = -1;
	} else {
		fso = opendev(special, O_WRONLY, 0, &realdev);
		if (fso < 0)
			fatal("%s: %s", special, strerror(errno));
		special = realdev;

		/* Bail if target special is mounted */
		n = getmntinfo(&mp, MNT_NOWAIT);
		if (n == 0)
			fatal("%s: getmntinfo: %s", special, strerror(errno));

		len = sizeof(_PATH_DEV) - 1;
		s1 = special;
		if (strncmp(_PATH_DEV, s1, len) == 0)
			s1 += len;

		while (--n >= 0) {
			s2 = mp->f_mntfromname;
			if (strncmp(_PATH_DEV, s2, len) == 0) {
				s2 += len - 1;
				*s2 = 'r';
			}
			if (strcmp(s1, s2) == 0 || strcmp(s1, &s2[1]) == 0)
				fatal("%s is mounted on %s",
				    special, mp->f_mntonname);
			++mp;
		}
	}
	fsi = opendev(special, O_RDONLY, 0, NULL);
	if (fsi < 0)
		fatal("%s: %s", special, strerror(errno));
	if (fstat(fsi, &st) < 0)
		fatal("%s: %s", special, strerror(errno));
	if (S_ISBLK(st.st_mode))
		fatal("%s: block device", special);
	if (!S_ISCHR(st.st_mode))
		warnx("%s: not a character-special device",
		    special);
	if (*argv[0] == '\0')
		fatal("empty partition name supplied");
	cp = argv[0] + strlen(argv[0]) - 1;
	if ((*cp < 'a' || *cp > ('a' + maxpartitions - 1))
	    && !isdigit((unsigned char)*cp))
		fatal("%s: can't figure out file system partition",
		    argv[0]);
	lp = getdisklabel(special, fsi);
	if (pledge("stdio disklabel tty", NULL) == -1)
		err(1, "pledge");
	if (isdigit((unsigned char)*cp))
		pp = &lp->d_partitions[0];
	else
		pp = &lp->d_partitions[*cp - 'a'];
	if (DL_GETPSIZE(pp) == 0)
		fatal("%s: `%c' partition is unavailable",
		    argv[0], *cp);
	if (pp->p_fstype == FS_BOOT)
		fatal("%s: `%c' partition overlaps boot program",
		      argv[0], *cp);
havelabel:
	if (sectorsize == 0) {
		sectorsize = lp->d_secsize;
		if (sectorsize <= 0)
			fatal("%s: no default sector size", argv[0]);
	}

	if (fssize_input < 0) {
#if 1
		fatal("-s < 0 not yet implemented");
#else
		long long gap; /* leave gap at the end of partition */
		fssize_input = -fssize_input;
		if (fssize_usebytes) {
			gap = (daddr_t)fssize_input / (daddr_t)sectorsize;
			if ((daddr_t)fssize_input % (daddr_t)sectorsize != 0)
				gap++;
		} else
			gap = fssize_input;
		if (gap >= DL_GETPSIZE(pp))
			fatal("%s: requested gap of %lld sectors on partition "
			    "'%c' is too big", argv[0], gap, *cp);
		nsecs = DL_GETPSIZE(pp) - gap;
#endif
	} else {
		if (fssize_usebytes) {
			nsecs = fssize_input / sectorsize;
			if (fssize_input % sectorsize != 0)
				nsecs++;
		} else if (fssize_input == 0)
			nsecs = DL_GETPSIZE(pp);
		else
			nsecs = fssize_input;
	}

	if (nsecs > DL_GETPSIZE(pp))
	       fatal("%s: maximum file system size on the `%c' partition is "
		   "%llu sectors", argv[0], *cp, DL_GETPSIZE(pp));

	/* Can't use DL_SECTOBLK() because sectorsize may not be from label! */
	fssize = nsecs * (sectorsize / DEV_BSIZE);
	if (fsize == 0) {
		fsize = DISKLABELV1_FFS_FSIZE(pp->p_fragblock);
		if (fsize <= 0)
			fsize = MAX(DFL_FRAGSIZE, lp->d_secsize);
	}
	if (bsize == 0) {
		bsize = DISKLABELV1_FFS_BSIZE(pp->p_fragblock);
		if (bsize <= 0)
			bsize = MIN(DFL_BLKSIZE, 8 * fsize);
	}
	if (density == 0)
		density = NFPI * fsize;
	if (minfree < MINFREE && opt != FS_OPTSPACE && reqopt == -1) {
		warnx("warning: changing optimization to space "
		    "because minfree is less than %d%%\n", MINFREE);
		opt = FS_OPTSPACE;
	}
	if (maxbpg == 0) {
		if (Oflag <= 1)
			maxbpg = MAXBLKPG_FFS1(bsize);
		else
			maxbpg = MAXBLKPG_FFS2(bsize);
	}
	oldpartition = *pp;

	mkfs(pp, special, fsi, fso);
	if (!Nflag && memcmp(pp, &oldpartition, sizeof(oldpartition)))
		rewritelabel(special, fso, lp);
	if (!Nflag)
		close(fso);
	close(fsi);
	exit(0);
}
Beispiel #10
0
/*
 * md back-end code for menu-driven BSD disklabel editor.
 */
int
md_make_bsd_partitions(void)
{
    int i;
    int part;
    int maxpart = getmaxpartitions();
    int partstart;
    int part_raw, part_bsd;
    int ptend;
    int no_swap = 0;
    partinfo *p;

    /*
     * Initialize global variables that track space used on this disk.
     * Standard 4.4BSD 8-partition labels always cover whole disk.
     */
    if (ptsize == 0)
        ptsize = dlsize - ptstart;
    if (dlsize == 0)
        dlsize = ptstart + ptsize;

    partstart = ptstart;
    ptend = ptstart + ptsize;

    /* Ask for layout type -- standard or special */
    msg_display(MSG_layout,
                ptsize / (MEG / sectorsize),
                DEFROOTSIZE + DEFSWAPSIZE + DEFUSRSIZE,
                DEFROOTSIZE + DEFSWAPSIZE + DEFUSRSIZE + XNEEDMB);

    process_menu(MENU_layout, NULL);

    /* Set so we use the 'real' geometry for rounding, input in MB */
    current_cylsize = dlcylsize;
    set_sizemultname_meg();

    /* Build standard partitions */
    memset(&bsdlabel, 0, sizeof bsdlabel);

    /* Set initial partition types to unused */
    for (part = 0 ; part < maxpart ; ++part)
        bsdlabel[part].pi_fstype = FS_UNUSED;

    /* Whole disk partition */
    part_raw = getrawpartition();
    if (part_raw == -1)
        part_raw = PART_C;	/* for sanity... */
    bsdlabel[part_raw].pi_offset = 0;
    bsdlabel[part_raw].pi_size = dlsize;

    if (part_raw == PART_D) {
        /* Probably a system that expects an i386 style mbr */
        part_bsd = PART_C;
        bsdlabel[PART_C].pi_offset = ptstart;
        bsdlabel[PART_C].pi_size = ptsize;
    } else {
        part_bsd = part_raw;
    }

    if (bootsize != 0) {
        bsdlabel[PART_BOOT_FAT12].pi_fstype = FS_MSDOS;
        bsdlabel[PART_BOOT_FAT12].pi_size = bootsize;
        bsdlabel[PART_BOOT_FAT12].pi_offset = bootstart;
        bsdlabel[PART_BOOT_FAT12].pi_flags |= PART_BOOT_FAT12_PI_FLAGS;
        strlcpy(bsdlabel[PART_BOOT_FAT12].pi_mount,
                PART_BOOT_FAT12_PI_MOUNT,
                sizeof bsdlabel[PART_BOOT_FAT12].pi_mount);
    }

#ifdef PART_REST
    bsdlabel[PART_REST].pi_offset = 0;
    bsdlabel[PART_REST].pi_size = ptstart;
#endif

    /*
     * Save any partitions that are outside the area we are
     * going to use.
     * In particular this saves details of the other MBR
     * partitions on a multiboot i386 system.
     */
    for (i = maxpart; i--;) {
        if (bsdlabel[i].pi_size != 0)
            /* Don't overwrite special partitions */
            continue;
        p = &oldlabel[i];
        if (p->pi_fstype == FS_UNUSED || p->pi_size == 0)
            continue;
        if (layoutkind == 4) {
            if (PI_ISBSDFS(p))
                p->pi_flags |= PIF_MOUNT;
        } else {
            if (p->pi_offset < ptstart + ptsize &&
                    p->pi_offset + p->pi_size > ptstart)
                /* Not outside area we are allocating */
                continue;
            if (p->pi_fstype == FS_SWAP)
                no_swap = 1;
        }
        bsdlabel[i] = oldlabel[i];
    }

    if (layoutkind == 4) {
        /* XXX Check we have a sensible layout */
        ;
    } else
        get_ptn_sizes(partstart, ptend - partstart, no_swap);

    /*
     * OK, we have a partition table. Give the user the chance to
     * edit it and verify it's OK, or abort altogether.
     */
edit_check:
    if (edit_and_check_label(bsdlabel, maxpart, part_raw, part_bsd) == 0) {
        msg_display(MSG_abort);
        return 0;
    }
    if (md_check_partitions() == 0)
        goto edit_check;

    /* Disk name */
    msg_prompt(MSG_packname, bsddiskname, bsddiskname, sizeof bsddiskname);

    /* save label to disk for MI code to update. */
    (void)savenewlabel(bsdlabel, maxpart);

    /* Everything looks OK. */
    return 1;
}
Beispiel #11
0
int
main(int argc, char *argv[])
{
	int ch;
	struct partition *pp;
	struct disklabel *lp;
	struct disklabel mfsfakelabel;
	struct partition oldpartition;
	struct stat st;
	struct statfs *mp;
	struct rlimit rl;
	int fsi = -1, oflagset = 0, fso, len, n, maxpartitions;
	char *cp = NULL, *s1, *s2, *special, *opstring, *realdev;
#ifdef MFS
	char mountfromname[BUFSIZ];
	char *pop = NULL, node[PATH_MAX];
	pid_t pid, res;
	struct statfs sf;
	struct stat mountpoint;
	int status;
#endif
	uid_t mfsuid = 0;
	gid_t mfsgid = 0;
	mode_t mfsmode = 0;
	char *fstype = NULL;
	char **saveargv = argv;
	int ffsflag = 1;
	const char *errstr;
	long long fssize_input = 0;
	int fssize_usebytes = 0;
	u_int64_t nsecs;

	if (strstr(__progname, "mfs"))
		mfs = Nflag = quiet = 1;

	getphysmem();
	maxpartitions = getmaxpartitions();
	if (maxpartitions > 26)
		fatal("insane maxpartitions value %d", maxpartitions);

	opstring = mfs ?
	    "P:T:b:c:e:f:i:m:o:s:" :
	    "NO:S:T:b:c:e:f:g:h:i:m:o:qs:t:";
	while ((ch = getopt(argc, argv, opstring)) != -1) {
		switch (ch) {
		case 'N':
			Nflag = 1;
			break;
		case 'O':
			Oflag = strtonum(optarg, 0, 2, &errstr);
			if (errstr)
				fatal("%s: invalid ffs version", optarg);
			oflagset = 1;
			break;
		case 'S':
			if (scan_scaled(optarg, &sectorsize) == -1 ||
			    sectorsize <= 0 || (sectorsize % DEV_BSIZE))
				fatal("sector size invalid: %s", optarg);
			break;
		case 'T':
			disktype = optarg;
			break;
		case 'b':
			bsize = strtonum(optarg, MINBSIZE, MAXBSIZE, &errstr);
			if (errstr)
				fatal("block size is %s: %s", errstr, optarg);
			break;
		case 'c':
			maxfrgspercg = strtonum(optarg, 1, INT_MAX, &errstr);
			if (errstr)
				fatal("fragments per cylinder group is %s: %s",
				    errstr, optarg);
			break;
		case 'e':
			maxbpg = strtonum(optarg, 1, INT_MAX, &errstr);
			if (errstr)
				fatal("blocks per file in a cylinder group is"
				    " %s: %s", errstr, optarg);
			break;
		case 'f':
			fsize = strtonum(optarg, MINBSIZE / MAXFRAG, MAXBSIZE,
			    &errstr);
			if (errstr)
				fatal("fragment size is %s: %s",
				    errstr, optarg);
			break;
		case 'g':
			avgfilesize = strtonum(optarg, 1, INT_MAX, &errstr);
			if (errstr)
				fatal("average file size is %s: %s",
				    errstr, optarg);
			break;
		case 'h':
			avgfilesperdir = strtonum(optarg, 1, INT_MAX, &errstr);
			if (errstr)
				fatal("average files per dir is %s: %s",
				    errstr, optarg);
			break;
		case 'i':
			density = strtonum(optarg, 1, INT_MAX, &errstr);
			if (errstr)
				fatal("bytes per inode is %s: %s",
				    errstr, optarg);
			break;
		case 'm':
			minfree = strtonum(optarg, 0, 99, &errstr);
			if (errstr)
				fatal("free space %% is %s: %s",
				    errstr, optarg);
			break;
		case 'o':
			if (mfs)
				getmntopts(optarg, mopts, &mntflags);
			else {
				if (strcmp(optarg, "space") == 0)
					reqopt = opt = FS_OPTSPACE;
				else if (strcmp(optarg, "time") == 0)
					reqopt = opt = FS_OPTTIME;
				else
					fatal("%s: unknown optimization "
					    "preference: use `space' or `time'.",
					    optarg);
			}
			break;
		case 'q':
			quiet = 1;
			break;
		case 's':
			if (scan_scaled(optarg, &fssize_input) == -1 ||
			    fssize_input <= 0)
				fatal("file system size invalid: %s", optarg);
			fssize_usebytes = 0;    /* in case of multiple -s */
			for (s1 = optarg; *s1 != '\0'; s1++)
				if (isalpha((unsigned char)*s1)) {
					fssize_usebytes = 1;
					break;
				}
			break;
		case 't':
			fstype = optarg;
			if (strcmp(fstype, "ffs"))
				ffsflag = 0;
			break;
#ifdef MFS
		case 'P':
			pop = optarg;
			break;
#endif
		case '?':
		default:
			usage();
		}
		if (!ffsflag)
			break;
	}
	argc -= optind;
	argv += optind;

	if (ffsflag && argc - mfs != 1)
		usage();

	if (mfs) {
		/* Increase our data size to the max */
		if (getrlimit(RLIMIT_DATA, &rl) == 0) {
			rl.rlim_cur = rl.rlim_max;
			(void)setrlimit(RLIMIT_DATA, &rl);
		}
	}

	special = argv[0];

	if (!mfs) {
		char execname[PATH_MAX], name[PATH_MAX];

		if (fstype == NULL)
			fstype = readlabelfs(special, 0);
		if (fstype != NULL && strcmp(fstype, "ffs")) {
			snprintf(name, sizeof name, "newfs_%s", fstype);
			saveargv[0] = name;
			snprintf(execname, sizeof execname, "%s/newfs_%s",
			    _PATH_SBIN, fstype);
			(void)execv(execname, saveargv);
			snprintf(execname, sizeof execname, "%s/newfs_%s",
			    _PATH_USRSBIN, fstype);
			(void)execv(execname, saveargv);
			err(1, "%s not found", name);
		}
	}

	if (mfs && !strcmp(special, "swap")) {
		/*
		 * it's an MFS, mounted on "swap."  fake up a label.
		 * XXX XXX XXX
		 */
		fso = -1;	/* XXX; normally done below. */

		memset(&mfsfakelabel, 0, sizeof(mfsfakelabel));
		mfsfakelabel.d_secsize = 512;
		mfsfakelabel.d_nsectors = 64;
		mfsfakelabel.d_ntracks = 16;
		mfsfakelabel.d_ncylinders = 16;
		mfsfakelabel.d_secpercyl = 1024;
		DL_SETDSIZE(&mfsfakelabel, 16384);
		mfsfakelabel.d_npartitions = 1;
		mfsfakelabel.d_version = 1;
		DL_SETPSIZE(&mfsfakelabel.d_partitions[0], 16384);
		mfsfakelabel.d_partitions[0].p_fragblock =
		    DISKLABELV1_FFS_FRAGBLOCK(1024, 8);
		mfsfakelabel.d_partitions[0].p_cpg = 16;

		lp = &mfsfakelabel;
		pp = &mfsfakelabel.d_partitions[0];

		goto havelabel;
	}
	if (Nflag) {
		fso = -1;
	} else {
		fso = opendev(special, O_WRONLY, 0, &realdev);
		if (fso < 0)
			fatal("%s: %s", special, strerror(errno));
		special = realdev;

		/* Bail if target special is mounted */
		n = getmntinfo(&mp, MNT_NOWAIT);
		if (n == 0)
			fatal("%s: getmntinfo: %s", special, strerror(errno));

		len = sizeof(_PATH_DEV) - 1;
		s1 = special;
		if (strncmp(_PATH_DEV, s1, len) == 0)
			s1 += len;

		while (--n >= 0) {
			s2 = mp->f_mntfromname;
			if (strncmp(_PATH_DEV, s2, len) == 0) {
				s2 += len - 1;
				*s2 = 'r';
			}
			if (strcmp(s1, s2) == 0 || strcmp(s1, &s2[1]) == 0)
				fatal("%s is mounted on %s",
				    special, mp->f_mntonname);
			++mp;
		}
	}
	if (mfs && disktype != NULL) {
		lp = (struct disklabel *)getdiskbyname(disktype);
		if (lp == NULL)
			fatal("%s: unknown disk type", disktype);
		pp = &lp->d_partitions[1];
	} else {
		fsi = opendev(special, O_RDONLY, 0, NULL);
		if (fsi < 0)
			fatal("%s: %s", special, strerror(errno));
		if (fstat(fsi, &st) < 0)
			fatal("%s: %s", special, strerror(errno));
		if (!mfs) {
			if (S_ISBLK(st.st_mode))
				fatal("%s: block device", special);
			if (!S_ISCHR(st.st_mode))
				warnx("%s: not a character-special device",
				    special);
		}
		if (*argv[0] == '\0')
			fatal("empty partition name supplied");
		cp = argv[0] + strlen(argv[0]) - 1;
		if ((*cp < 'a' || *cp > ('a' + maxpartitions - 1))
		    && !isdigit((unsigned char)*cp))
			fatal("%s: can't figure out file system partition",
			    argv[0]);
		lp = getdisklabel(special, fsi);
		if (!mfs) {
			if (pledge("stdio disklabel tty", NULL) == -1)
				err(1, "pledge");
		}
		if (isdigit((unsigned char)*cp))
			pp = &lp->d_partitions[0];
		else
			pp = &lp->d_partitions[*cp - 'a'];
		if (DL_GETPSIZE(pp) == 0)
			fatal("%s: `%c' partition is unavailable",
			    argv[0], *cp);
		if (pp->p_fstype == FS_BOOT)
			fatal("%s: `%c' partition overlaps boot program",
			      argv[0], *cp);
	}
havelabel:
	if (sectorsize == 0) {
		sectorsize = lp->d_secsize;
		if (sectorsize <= 0)
			fatal("%s: no default sector size", argv[0]);
	}

	if (fssize_usebytes) {
		nsecs = fssize_input / sectorsize;
		if (fssize_input % sectorsize != 0)
			nsecs++;
	} else if (fssize_input == 0)
		nsecs = DL_GETPSIZE(pp);
	else
		nsecs = fssize_input;

	if (nsecs > DL_GETPSIZE(pp) && !mfs)
	       fatal("%s: maximum file system size on the `%c' partition is "
		   "%llu sectors", argv[0], *cp, DL_GETPSIZE(pp));

	/* Can't use DL_SECTOBLK() because sectorsize may not be from label! */
	fssize = nsecs * (sectorsize / DEV_BSIZE);
	if (oflagset == 0 && fssize >= INT_MAX)
		Oflag = 2;	/* FFS2 */
	if (fsize == 0) {
		fsize = DISKLABELV1_FFS_FSIZE(pp->p_fragblock);
		if (fsize <= 0)
			fsize = MAXIMUM(DFL_FRAGSIZE, lp->d_secsize);
	}
	if (bsize == 0) {
		bsize = DISKLABELV1_FFS_BSIZE(pp->p_fragblock);
		if (bsize <= 0)
			bsize = MINIMUM(DFL_BLKSIZE, 8 * fsize);
	}
	if (density == 0)
		density = NFPI * fsize;
	if (minfree < MINFREE && opt != FS_OPTSPACE && reqopt == -1) {
		warnx("warning: changing optimization to space "
		    "because minfree is less than %d%%\n", MINFREE);
		opt = FS_OPTSPACE;
	}
	if (maxbpg == 0) {
		if (Oflag <= 1)
			maxbpg = MAXBLKPG_FFS1(bsize);
		else
			maxbpg = MAXBLKPG_FFS2(bsize);
	}
	oldpartition = *pp;
#ifdef MFS
	if (mfs) {
		if (realpath(argv[1], node) == NULL)
			err(1, "realpath %s", argv[1]);
		if (stat(node, &mountpoint) < 0)
			err(ECANCELED, "stat %s", node);
		mfsuid = mountpoint.st_uid;
		mfsgid = mountpoint.st_gid;
		mfsmode = mountpoint.st_mode & ALLPERMS;
	}
#endif

	mkfs(pp, special, fsi, fso, mfsmode, mfsuid, mfsgid);
	if (!Nflag && memcmp(pp, &oldpartition, sizeof(oldpartition)))
		rewritelabel(special, fso, lp);
	if (!Nflag)
		close(fso);
	close(fsi);
#ifdef MFS
	if (mfs) {
		struct mfs_args args;
		memset(&args, 0, sizeof(args));
		args.base = membase;
		args.size = fssize * DEV_BSIZE;
		args.export_info.ex_root = -2;
		if (mntflags & MNT_RDONLY)
			args.export_info.ex_flags = MNT_EXRDONLY;

		switch (pid = fork()) {
		case -1:
			err(10, "mfs");
		case 0:
			snprintf(mountfromname, sizeof(mountfromname),
			    "mfs:%d", getpid());
			break;
		default:
			snprintf(mountfromname, sizeof(mountfromname),
			    "mfs:%d", pid);
			for (;;) {
				/*
				 * spin until the mount succeeds
				 * or the child exits
				 */
				usleep(1);

				/*
				 * XXX Here is a race condition: another process
				 * can mount a filesystem which hides our
				 * ramdisk before we see the success.
				 */
				if (statfs(node, &sf) < 0)
					err(ECANCELED, "statfs %s", node);
				if (!strcmp(sf.f_mntfromname, mountfromname) &&
				    !strncmp(sf.f_mntonname, node,
					     MNAMELEN) &&
				    !strcmp(sf.f_fstypename, "mfs")) {
					if (pop != NULL)
						copy(pop, node, &args);
					exit(0);
				}
				res = waitpid(pid, &status, WNOHANG);
				if (res == -1)
					err(EDEADLK, "waitpid");
				if (res != pid)
					continue;
				if (WIFEXITED(status)) {
					if (WEXITSTATUS(status) == 0)
						exit(0);
					errx(1, "%s: mount: %s", node,
					     strerror(WEXITSTATUS(status)));
				} else
					errx(EDEADLK, "abnormal termination");
			}
			/* NOTREACHED */
		}

		(void) setsid();
		(void) close(0);
		(void) close(1);
		(void) close(2);
		(void) chdir("/");

		args.fspec = mountfromname;
		if (mntflags & MNT_RDONLY && pop != NULL)
			mntflags &= ~MNT_RDONLY;
		if (mount(MOUNT_MFS, node, mntflags, &args) < 0)
			exit(errno); /* parent prints message */
	}
#endif
	exit(0);
}
int
main(int argc, char *argv[])
{
	int	c, devfd;
	char	*protostore;
	long	protosize;
	struct stat disksb, bootsb;
	struct disklabel dl;
	daddr64_t partoffset;
#define BBPAD   0x1e0
	struct bb {
		char	bb_pad[BBPAD];	/* disklabel lives in here, actually */
		long	bb_secsize;	/* size of secondary boot block */
		long	bb_secstart;	/* start of secondary boot block */
		long	bb_flags;	/* unknown; always zero */
		long	bb_cksum;	/* checksum of the boot block, as longs. */
	} bb;
	long *lp, *ep;

	while ((c = getopt(argc, argv, "vns:e:")) != -1) {
		switch (c) {
		case 'n':
			/* Do not actually write the bootblock to disk */
			nowrite = 1;
			break;
		case 'v':
			/* Chat */
			verbose = 1;
			break;
		case 's':
			isofsblk = atoi(optarg);
			break;
		case 'e':
			isofseblk = atoi(optarg);
			break;
		default:
			usage();
		}
	}

	if (argc - optind < 3)
		usage();

	boot = argv[optind];
	proto = argv[optind + 1];
	dev = argv[optind + 2];

	if (verbose) {
		(void)printf("boot: %s\n", boot);
		(void)printf("proto: %s\n", proto);
		(void)printf("device: %s\n", dev);
	}

	/* Load proto blocks into core */
	if ((protostore = loadprotoblocks(proto, &protosize)) == NULL)
		exit(1);

	/* Open and check raw disk device */
	if ((devfd = opendev(dev, O_RDONLY, OPENDEV_PART, &dev)) < 0)
		err(1, "open: %s", dev);
	if (fstat(devfd, &disksb) == -1)
		err(1, "fstat: %s", dev);
	if (!S_ISCHR(disksb.st_mode))
		errx(1, "%s must be a character device node", dev);
	if ((minor(disksb.st_rdev) % getmaxpartitions()) != getrawpartition())
		errx(1, "%s must be the raw partition", dev);

	/* Extract and load block numbers */
	if (stat(boot, &bootsb) == -1)
		err(1, "stat: %s", boot);
	if (!S_ISREG(bootsb.st_mode))
		errx(1, "%s must be a regular file", boot);
	if ((minor(disksb.st_rdev) / getmaxpartitions()) !=
	    (minor(bootsb.st_dev) / getmaxpartitions()))
		errx(1, "%s must be somewhere on %s", boot, dev);

	/*
	 * Find the offset of the secondary boot block's partition
	 * into the disk.  If disklabels not supported, assume zero.
	 */
	if (ioctl(devfd, DIOCGDINFO, &dl) != -1) {
		partoffset = DL_GETPOFFSET(&dl.d_partitions[minor(bootsb.st_dev) %
		    getmaxpartitions()]);
	} else {
		if (errno != ENOTTY)
			err(1, "read disklabel: %s", dev);
		warnx("couldn't read label from %s, using part offset of 0",
		    dev);
		partoffset = 0;
	}
	if (verbose)
		(void)printf("%s partition offset = 0x%lx\n", boot, partoffset);

	/* Sync filesystems (make sure boot's block numbers are stable) */
	sync();
	sleep(2);
	sync();
	sleep(2);

	if (loadblocknums(boot, devfd, partoffset) != 0)
		exit(1);

	(void)close(devfd);

	if (nowrite)
		return 0;

#if 0
	/* Write patched proto bootblocks into the superblock */
	if (protosize > SBSIZE - DEV_BSIZE)
		errx(1, "proto bootblocks too big");
#endif

	if ((devfd = opendev(dev, O_RDWR, OPENDEV_PART, &dev)) < 0)
		err(1, "open: %s", dev);

	if (lseek(devfd, DEV_BSIZE, SEEK_SET) != DEV_BSIZE)
		err(1, "lseek bootstrap");

	if (write(devfd, protostore, protosize) != protosize)
		err(1, "write bootstrap");

	if (lseek(devfd, 0, SEEK_SET) != 0)
		err(1, "lseek label");

	if (read(devfd, &bb, sizeof (bb)) != sizeof (bb))
		err(1, "read label");

	bb.bb_secsize = 15;
	bb.bb_secstart = 1;
	bb.bb_flags = 0;
	bb.bb_cksum = 0;

	for (lp = (long *)&bb, ep = &bb.bb_cksum; lp < ep; lp++)
		bb.bb_cksum += *lp;

	if (lseek(devfd, 0, SEEK_SET) != 0)
		err(1, "lseek label 2");

	if (write(devfd, &bb, sizeof bb) != sizeof bb)
		err(1, "write label ");

	(void)close(devfd);
	return 0;
}