예제 #1
0
/*
 * FTP - send single character
 *  wait for echo & handle timeout
 */
static void
send(char c)
{
	char cc;
	int retry = 0;

	cc = c;
	xpwrite(FD, &cc, 1);
	if (number(value(CDELAY)) > 0 && c != '\r')
		nap(number(value(CDELAY)));
	if (!boolean(value(ECHOCHECK))) {
		if (number(value(LDELAY)) > 0 && c == '\r')
			nap(number(value(LDELAY)));
		return;
	}
tryagain:
	timedout = 0;
	alarm(number(value(ETIMEOUT)));
	read(FD, &cc, 1);
	alarm(0);
	if (timedout) {
		printf("\r\ntimeout error (%s)\r\n", ctrl(c));
		if (retry++ > 3)
			return;
		xpwrite(FD, &null, 1); /* poke it */
		goto tryagain;
	}
}
예제 #2
0
static int update_epoch_from_v0_to_v1(uint32_t epoch)
{
	char path[PATH_MAX];
	struct sd_node_v0 nodes_v0[SD_MAX_NODES];
	struct sd_node_v1 nodes_v1[SD_MAX_NODES];
	size_t nr_nodes;
	time_t *t;
	int len, fd, ret;

	snprintf(path, sizeof(path), "%s%08u", epoch_path, epoch);
	fd = open(path, O_RDWR | O_DSYNC);
	if (fd < 0) {
		if (errno == ENOENT)
			return 0;

		sd_eprintf("failed to open epoch %"PRIu32" log", epoch);
		return -1;
	}

	ret = xread(fd, nodes_v0, sizeof(nodes_v0));
	if (ret < 0) {
		sd_eprintf("failed to read epoch %"PRIu32" log", epoch);
		close(fd);
		return ret;
	}

	nr_nodes = ret / sizeof(nodes_v0[0]);
	for (int i = 0; i < nr_nodes; i++) {
		memcpy(&nodes_v1[i].nid, &nodes_v0[i].nid,
		       sizeof(struct node_id_v1));
		nodes_v1[i].nr_vnodes = nodes_v0[i].nr_vnodes;
		nodes_v1[i].zone = nodes_v0[i].zone;
		nodes_v1[i].space = 0;
	}

	len = sizeof(nodes_v1[0]) * nr_nodes;
	ret = xpwrite(fd, nodes_v1, len, 0);
	if (ret != len) {
		sd_eprintf("failed to write epoch %"PRIu32" log",
			   epoch);
		close(fd);
		return -1;
	}

	t = (time_t *)&nodes_v0[nr_nodes];

	ret = xpwrite(fd, t, sizeof(*t), len);
	if (ret != sizeof(*t)) {
		sd_eprintf("failed to write time to epoch %"
			   PRIu32" log", epoch);
		close(fd);
		return -1;
	}

	close(fd);

	return 0;
}
예제 #3
0
파일: tip.c 프로젝트: wan721/DragonFlyBSD
/*
 * ****TIPIN   TIPIN****
 */
void
tipin(void)
{
	int i;
	char gch, bol = 1;

	atexit(killchild);

	/*
	 * Kinda klugey here...
	 *   check for scripting being turned on from the .tiprc file,
	 *   but be careful about just using setscript(), as we may
	 *   send a SIGEMT before tipout has a chance to set up catching
	 *   it; so wait a second, then setscript()
	 */
	if (boolean(value(SCRIPT))) {
		sleep(1);
		setscript();
	}

	while (1) {
		i = getchar();
		if (i == EOF)
			break;
		gch = i&0177;
		if ((gch == character(value(ESCAPE))) && bol) {
			if (!(gch = escape()))
				continue;
		} else if (!cumode && gch == character(value(RAISECHAR))) {
			boolean(value(RAISE)) = !boolean(value(RAISE));
			continue;
		} else if (gch == '\r') {
			bol = 1;
			xpwrite(FD, &gch, 1);
			if (boolean(value(HALFDUPLEX)))
				printf("\r\n");
			continue;
		} else if (!cumode && gch == character(value(FORCE))) {
			i = getchar();
			if (i == EOF)
				break;
			gch = i & 0177;
		}
		bol = any(gch, value(EOL));
		if (boolean(value(RAISE)) && islower(gch))
			gch = toupper(gch);
		xpwrite(FD, &gch, 1);
		if (boolean(value(HALFDUPLEX)))
			printf("%c", gch);
	}
}
예제 #4
0
int default_write(uint64_t oid, struct siocb *iocb)
{
	int flags = get_open_flags(oid, false), fd, ret = SD_RES_SUCCESS;
	char path[PATH_MAX];
	ssize_t size;

	if (iocb->epoch < sys_epoch()) {
		dprintf("%"PRIu32" sys %"PRIu32"\n", iocb->epoch, sys_epoch());
		return SD_RES_OLD_NODE_VER;
	}

	get_obj_path(oid, path);
	if (iocb->flags & SD_FLAG_CMD_CACHE && is_disk_cache_enabled())
		flags &= ~O_DSYNC;
	fd = open(path, flags, def_fmode);
	if (fd < 0)
		return err_to_sderr(oid, errno);

	size = xpwrite(fd, iocb->buf, iocb->length, iocb->offset);
	if (size != iocb->length) {
		eprintf("failed to write object %"PRIx64", path=%s, offset=%"
			PRId64", size=%"PRId32", result=%zd, %m\n", oid, path,
			iocb->offset, iocb->length, size);
		ret = err_to_sderr(oid, errno);
		goto out;
	}
out:
	close(fd);
	return ret;
}
예제 #5
0
파일: journal.c 프로젝트: Nexenta/sheepdog
static int jrnl_apply_to_target_object(struct jrnl_descriptor *jd)
{
	char *buf = NULL;
	int buf_len, res = 0;
	ssize_t retsize;

	/* FIXME: handle larger size */
	buf_len = (1 << 22);
	buf = zalloc(buf_len);
	if (!buf) {
		eprintf("failed to allocate memory\n");
		return SD_RES_NO_MEM;
	}

	/* Flush out journal to disk (VDI object) */
	retsize = xpread(jd->fd, &jd->head, sizeof(jd->head), 0);
	retsize = xpread(jd->fd, buf, jd->head.size, sizeof(jd->head));
	retsize = xpwrite(jd->target_fd, buf, jd->head.size, jd->head.offset);
	if (retsize != jd->head.size) {
		if (errno == ENOSPC)
			res = SD_RES_NO_SPACE;
		else
			res = SD_RES_EIO;
	}

	/* Clean up */
	free(buf);

	return res;
}
예제 #6
0
파일: initrd.c 프로젝트: manover/klibc
/*
 * Copy the initrd to /dev/ram0, copy from the end to the beginning
 * to avoid taking 2x the memory.
 */
static int rd_copy_uncompressed(int ffd, int dfd)
{
	char buffer[BUF_SIZE];
	off_t bytes;
	struct stat st;

	dprintf("kinit: uncompressed initrd\n");

	if (ffd < 0 || fstat(ffd, &st) || !S_ISREG(st.st_mode) ||
	    (bytes = st.st_size) == 0)
		return -1;

	while (bytes) {
		ssize_t blocksize = ((bytes - 1) & (BUF_SIZE - 1)) + 1;
		off_t offset = bytes - blocksize;

		dprintf("kinit: copying %zd bytes at offset %llu\n",
			blocksize, offset);

		if (xpread(ffd, buffer, blocksize, offset) != blocksize ||
		    xpwrite(dfd, buffer, blocksize, offset) != blocksize)
			return -1;

		ftruncate(ffd, offset);	/* Free up memory */
		bytes = offset;
	}
	return 0;
}
예제 #7
0
파일: tip.c 프로젝트: wan721/DragonFlyBSD
/*
 * Escape handler --
 *  called on recognition of ``escapec'' at the beginning of a line
 */
char
escape(void)
{
	char gch;
	esctable_t *p;
	char c = character(value(ESCAPE));
	int i;

	i = getchar();
	if (i == EOF)
		return 0;
	gch = (i&0177);
	for (p = etable; p->e_char; p++)
		if (p->e_char == gch) {
			if ((p->e_flags&PRIV) && uid)
				continue;
			printf("%s", ctrl(c));
			(*p->e_func)(gch);
			return (0);
		}
	/* ESCAPE ESCAPE forces ESCAPE */
	if (c != gch)
		xpwrite(FD, &c, 1);
	return (gch);
}
예제 #8
0
파일: plain_store.c 프로젝트: DLag/sheepdog
int default_write(uint64_t oid, const struct siocb *iocb)
{
	int flags = prepare_iocb(oid, iocb, false), fd,
	    ret = SD_RES_SUCCESS;
	char path[PATH_MAX];
	ssize_t size;
	uint32_t len = iocb->length;
	uint64_t offset = iocb->offset;
	static bool trim_is_supported = true;

	if (iocb->epoch < sys_epoch()) {
		sd_debug("%"PRIu32" sys %"PRIu32, iocb->epoch, sys_epoch());
		return SD_RES_OLD_NODE_VER;
	}

	if (uatomic_is_true(&sys->use_journal) &&
	    unlikely(journal_write_store(oid, iocb->buf, iocb->length,
					 iocb->offset, false))
	    != SD_RES_SUCCESS) {
		sd_err("turn off journaling");
		uatomic_set_false(&sys->use_journal);
		flags |= O_DSYNC;
		sync();
	}

	get_store_path(oid, iocb->ec_index, path);

	/*
	 * Make sure oid is in the right place because oid might be misplaced
	 * in a wrong place, due to 'shutdown/restart with less/more disks' or
	 * any bugs. We need call err_to_sderr() to return EIO if disk is broken
	 */
	if (!default_exist(oid, iocb->ec_index))
		return err_to_sderr(path, oid, ENOENT);

	fd = open(path, flags, sd_def_fmode);
	if (unlikely(fd < 0))
		return err_to_sderr(path, oid, errno);

	if (trim_is_supported && is_sparse_object(oid)) {
		if (default_trim(fd, oid, iocb, &offset, &len) < 0) {
			trim_is_supported = false;
			offset = iocb->offset;
			len = iocb->length;
		}
	}

	size = xpwrite(fd, iocb->buf, len, offset);
	if (unlikely(size != len)) {
		sd_err("failed to write object %"PRIx64", path=%s, offset=%"
		       PRId32", size=%"PRId32", result=%zd, %m", oid, path,
		       iocb->offset, iocb->length, size);
		ret = err_to_sderr(path, oid, errno);
		goto out;
	}
out:
	close(fd);
	return ret;
}
예제 #9
0
파일: farm.c 프로젝트: yaekumo/sheepdog
static int farm_write(uint64_t oid, struct siocb *iocb)
{
    ssize_t size = xpwrite(iocb->fd, iocb->buf, iocb->length, iocb->offset);

    if (size != iocb->length)
        return SD_RES_EIO;

    trunk_update_entry(oid);
    return SD_RES_SUCCESS;
}
예제 #10
0
파일: tip.c 프로젝트: ryo/netbsd-src
/*
 * ****TIPIN   TIPIN****
 */
static void
tipin(void)
{
	char gch, bol = 1;

	/*
	 * Kinda klugey here...
	 *   check for scripting being turned on from the .tiprc file,
	 *   but be careful about just using setscript(), as we may
	 *   send a SIGEMT before tipout has a chance to set up catching
	 *   it; so wait a second, then setscript()
	 */
	if (boolean(value(SCRIPT))) {
		(void)sleep(1);
		setscript();
	}

	for (;;) {
		gch = getchar()&STRIP_PAR;
		if ((gch == character(value(ESCAPE))) && bol) {
			if (!(gch = escape()))
				continue;
		} else if (!cumode &&
		    gch && gch == character(value(RAISECHAR))) {
			setboolean(value(RAISE), !boolean(value(RAISE)));
			continue;
		} else if (gch == '\r') {
			bol = 1;
			xpwrite(FD, &gch, 1);
			if (boolean(value(HALFDUPLEX)))
				(void)printf("\r\n");
			continue;
		} else if (!cumode && gch && gch == character(value(FORCE)))
			gch = getchar()&STRIP_PAR;
		bol = any(gch, value(EOL));
		if (boolean(value(RAISE)) && islower((unsigned char)gch))
			gch = toupper((unsigned char)gch);
		xpwrite(FD, &gch, 1);
		if (boolean(value(HALFDUPLEX)))
			(void)printf("%c", gch);
	}
}
예제 #11
0
파일: farm.c 프로젝트: yamt/sheepdog
static int farm_write(uint64_t oid, struct siocb *iocb, int create)
{
	int flags = def_open_flags, fd, ret = SD_RES_SUCCESS;
	char path[PATH_MAX];
	ssize_t size;

	if (iocb->epoch < sys_epoch()) {
		dprintf("%"PRIu32" sys %"PRIu32"\n", iocb->epoch, sys_epoch());
		return SD_RES_OLD_NODE_VER;
	}
	if (!is_data_obj(oid))
		flags &= ~O_DIRECT;

	if (create)
		flags |= O_CREAT | O_TRUNC;

	sprintf(path, "%s%016"PRIx64, obj_path, oid);
	fd = open(path, flags, def_fmode);
	if (fd < 0)
		return err_to_sderr(oid, errno);

	if (flock(fd, LOCK_EX) < 0) {
		ret = SD_RES_EIO;
		eprintf("%m\n");
		goto out;
	}
	if (create && !(iocb->flags & SD_FLAG_CMD_COW)) {
		ret = prealloc(fd, get_objsize(oid));
		if (ret != SD_RES_SUCCESS) {
			if (flock(fd, LOCK_UN) < 0) {
				ret = SD_RES_EIO;
				eprintf("%m\n");
				goto out;
			}
			goto out;
		}
	}
	size = xpwrite(fd, iocb->buf, iocb->length, iocb->offset);
	if (flock(fd, LOCK_UN) < 0) {
		ret = SD_RES_EIO;
		eprintf("%m\n");
		goto out;
	}
	if (size != iocb->length) {
		eprintf("%m\n");
		ret = SD_RES_EIO;
		goto out;
	}

	trunk_update_entry(oid);
out:
	close(fd);
	return ret;
}
예제 #12
0
int default_create_and_write(uint64_t oid, struct siocb *iocb)
{
	char path[PATH_MAX], tmp_path[PATH_MAX];
	int flags = get_open_flags(oid, true);
	int ret, fd;
	uint32_t len = iocb->length;

	get_obj_path(oid, path);
	get_tmp_obj_path(oid, tmp_path);

	fd = open(tmp_path, flags, def_fmode);
	if (fd < 0) {
		if (errno == EEXIST)
			/* This happens if node membership changes during object
			 * creation; while gateway retries a CREATE request,
			 * recovery process could also recover the object at the
			 * same time.  They should try to write the same date,
			 * so it is okay to simply return success here. */
			dprintf("%s exists\n", tmp_path);
			return SD_RES_SUCCESS;

		eprintf("failed to open %s: %m\n", tmp_path);
		return err_to_sderr(oid, errno);
	}

	if (iocb->offset != 0 || iocb->length != get_objsize(oid)) {
		ret = prealloc(fd, get_objsize(oid));
		if (ret != SD_RES_SUCCESS)
			goto out;
	}

	ret = xpwrite(fd, iocb->buf, len, iocb->offset);
	if (ret != len) {
		eprintf("failed to write object. %m\n");
		ret = err_to_sderr(oid, errno);
		goto out;
	}

	ret = rename(tmp_path, path);
	if (ret < 0) {
		eprintf("failed to rename %s to %s: %m\n", tmp_path, path);
		ret = err_to_sderr(oid, errno);
		goto out;
	}
	dprintf("%"PRIx64"\n", oid);
	ret = SD_RES_SUCCESS;
out:
	if (ret != SD_RES_SUCCESS)
		unlink(tmp_path);
	close(fd);
	return ret;
}
예제 #13
0
static int migrate_from_v0_to_v1(void)
{
	int ret, fd;
	struct sheepdog_config_v1 config;

	fd = open(config_path, O_RDWR);
	if (fd < 0) {
		sd_eprintf("failed to open config file, %m");
		return -1;
	}

	memset(&config, 0, sizeof(config));
	ret = xread(fd, &config, sizeof(config));
	if (ret < 0) {
		sd_eprintf("failed to read config file, %m");
		close(fd);
		return ret;
	}

	config.version = 1;
	ret = xpwrite(fd, &config, sizeof(config), 0);
	if (ret != sizeof(config)) {
		sd_eprintf("failed to write config data, %m");
		close(fd);
		return -1;
	}

	/* 0.5.1 could wrongly extend the config file, so truncate it here */
	ret = ftruncate(fd, sizeof(config));
	if (ret != 0) {
		sd_eprintf("failed to truncate config data, %m");
		close(fd);
		return -1;
	}

	close(fd);

	/*
	 * If the config file contains a space field, the store layout
	 * is compatible with v1.  In this case, what we need to do is
	 * only adding version number to the config file.
	 */
	if (config.space > 0)
		return 0;

	/* upgrade epoch log */
	for_each_epoch(update_epoch_from_v0_to_v1);

	return ret;
}
예제 #14
0
static int jrnl_write_header(struct jrnl_descriptor *jd)
{
	ssize_t ret;
	struct jrnl_head *head = (struct jrnl_head *) &jd->head;

	ret = xpwrite(jd->fd, head, sizeof(*head), 0);

	if (ret != sizeof(*head)) {
		if (errno == ENOSPC)
			ret = SD_RES_NO_SPACE;
		else
			ret = SD_RES_EIO;
	} else
		ret = SD_RES_SUCCESS;

	return ret;
}
예제 #15
0
static int jrnl_write_end_mark(struct jrnl_descriptor *jd)
{
	ssize_t retsize;
	int ret;
	uint32_t end_mark = JRNL_END_MARK;
	struct jrnl_head *head = (struct jrnl_head *) &jd->head;

	retsize = xpwrite(jd->fd, &end_mark, sizeof(end_mark),
			   sizeof(*head) + head->size);

	if (retsize != sizeof(end_mark)) {
		if (errno == ENOSPC)
			ret = SD_RES_NO_SPACE;
		else
			ret = SD_RES_EIO;
	} else
		ret = SD_RES_SUCCESS;

	return ret;
}
예제 #16
0
int default_write(uint64_t oid, const struct siocb *iocb)
{
	int flags = get_open_flags(oid, false, iocb->flags), fd,
	    ret = SD_RES_SUCCESS;
	char path[PATH_MAX];
	ssize_t size;

	if (iocb->epoch < sys_epoch()) {
		sd_dprintf("%"PRIu32" sys %"PRIu32"\n",
			iocb->epoch, sys_epoch());
		return SD_RES_OLD_NODE_VER;
	}

	get_obj_path(oid, path);

	if (uatomic_is_true(&sys->use_journal) &&
	    journal_file_write(oid, iocb->buf, iocb->length, iocb->offset,
			       false)
	    != SD_RES_SUCCESS) {
		sd_eprintf("turn off journaling\n");
		uatomic_set_false(&sys->use_journal);
		flags |= O_DSYNC;
		sync();
	}

	fd = open(path, flags, def_fmode);
	if (fd < 0)
		return err_to_sderr(oid, errno);

	size = xpwrite(fd, iocb->buf, iocb->length, iocb->offset);
	if (size != iocb->length) {
		sd_eprintf("failed to write object %"PRIx64", path=%s, offset=%"
			PRId64", size=%"PRId32", result=%zd, %m\n", oid, path,
			iocb->offset, iocb->length, size);
		ret = err_to_sderr(oid, errno);
		goto out;
	}
out:
	close(fd);
	return ret;
}
예제 #17
0
파일: tip.c 프로젝트: ryo/netbsd-src
/*
 * Escape handler --
 *  called on recognition of ``escapec'' at the beginning of a line
 */
int
escape(void)
{
	char gch;
	esctable_t *p;
	char c = character(value(ESCAPE));

	gch = (getchar()&STRIP_PAR);
	for (p = etable; p->e_char; p++)
		if (p->e_char == gch) {
			if ((p->e_flags&PRIV) && uid)
				continue;
			(void)printf("%s", ctrl(c));
			(*p->e_func)(gch);
			return (0);
		}
	/* ESCAPE ESCAPE forces ESCAPE */
	if (c != gch)
		xpwrite(FD, &c, 1);
	return (gch);
}
예제 #18
0
int default_write(uint64_t oid, const struct siocb *iocb)
{
	int flags = prepare_iocb(oid, iocb, false), fd,
	    ret = SD_RES_SUCCESS;
	char path[PATH_MAX];
	ssize_t size;

	if (iocb->epoch < sys_epoch()) {
		sd_debug("%"PRIu32" sys %"PRIu32, iocb->epoch, sys_epoch());
		return SD_RES_OLD_NODE_VER;
	}

	if (uatomic_is_true(&sys->use_journal) &&
	    unlikely(journal_write_store(oid, iocb->buf, iocb->length,
					 iocb->offset, false))
	    != SD_RES_SUCCESS) {
		sd_err("turn off journaling");
		uatomic_set_false(&sys->use_journal);
		flags |= O_DSYNC;
		sync();
	}

	get_obj_path(oid, path);

	fd = open(path, flags, sd_def_fmode);
	if (unlikely(fd < 0))
		return err_to_sderr(path, oid, errno);

	size = xpwrite(fd, iocb->buf, iocb->length, iocb->offset);
	if (unlikely(size != iocb->length)) {
		sd_err("failed to write object %"PRIx64", path=%s, offset=%"
		       PRId64", size=%"PRId32", result=%zd, %m", oid, path,
		       iocb->offset, iocb->length, size);
		ret = err_to_sderr(path, oid, errno);
		goto out;
	}
out:
	close(fd);
	return ret;
}
예제 #19
0
int default_write(uint64_t oid, const struct siocb *iocb)
{
	int flags = prepare_iocb(oid, iocb, false), fd,
	    ret = SD_RES_SUCCESS;
	char path[PATH_MAX];
	ssize_t size;

	if (iocb->epoch < sys_epoch()) {
		sd_debug("%"PRIu32" sys %"PRIu32, iocb->epoch, sys_epoch());
		return SD_RES_OLD_NODE_VER;
	}

	get_store_path(oid, iocb->ec_index, path);

	/*
	 * Make sure oid is in the right place because oid might be misplaced
	 * in a wrong place, due to 'shutdown/restart with less/more disks' or
	 * any bugs. We need call err_to_sderr() to return EIO if disk is broken
	 */
	if (!default_exist(oid, iocb->ec_index))
		return err_to_sderr(path, oid, errno);

	fd = open(path, flags, sd_def_fmode);
	if (unlikely(fd < 0))
		return err_to_sderr(path, oid, errno);

	size = xpwrite(fd, iocb->buf, iocb->length, iocb->offset);
	if (unlikely(size != iocb->length)) {
		sd_err("failed to write object %"PRIx64", path=%s, offset=%"
		       PRId32", size=%"PRId32", result=%zd, %m", oid, path,
		       iocb->offset, iocb->length, size);
		ret = err_to_sderr(path, oid, errno);
		goto out;
	}
out:
	close(fd);
	return ret;
}
예제 #20
0
static int write_last_sector(int fd, uint32_t length)
{
	const int size = SECTOR_SIZE;
	char *buf;
	int ret;
	off_t off = length - size;

	buf = valloc(size);
	if (!buf) {
		eprintf("failed to allocate memory\n");
		return SD_RES_NO_MEM;
	}
	memset(buf, 0, size);

	ret = xpwrite(fd, buf, size, off);
	if (ret != size)
		ret = err_to_sderr(0, errno); /* FIXME: set oid */
	else
		ret = SD_RES_SUCCESS;
	free(buf);

	return ret;
}
예제 #21
0
ssize_t pwrite_in_full(int fd, const void *buf, size_t count, off_t offset)
{
	const char *p = buf;
	ssize_t total = 0;

	while (count > 0) {
		ssize_t nr;

		nr = xpwrite(fd, p, count, offset);
		if (nr < 0)
			return -1;
		if (nr == 0) {
			errno = ENOSPC;
			return -1;
		}
		count -= nr;
		total += nr;
		p += nr;
		offset += nr;
	}

	return total;
}
예제 #22
0
static int jrnl_apply_to_target_object(struct jrnl_descriptor *jd)
{
	char *buf = NULL;
	int res = 0;
	ssize_t retsize;

	/* Flush out journal to disk (VDI object) */
	retsize = xpread(jd->fd, &jd->head, sizeof(jd->head), 0);
	buf = xzalloc(jd->head.size);
	retsize = xpread(jd->fd, buf, jd->head.size, sizeof(jd->head));
	retsize = xpwrite(jd->target_fd, buf, jd->head.size, jd->head.offset);
	if (retsize != jd->head.size) {
		if (errno == ENOSPC)
			res = SD_RES_NO_SPACE;
		else
			res = SD_RES_EIO;
	}

	/* Clean up */
	free(buf);

	return res;
}
예제 #23
0
int main(int argc, char *argv[])
{
  static unsigned char sectbuf[512];
  int dev_fd;
  struct stat st;
  int status;
  char **argp, *opt;
  char mtools_conf[] = "/tmp/syslinux-mtools-XXXXXX";
  const char *subdir = NULL;
  int mtc_fd;
  FILE *mtc, *mtp;
  struct libfat_filesystem *fs;
  libfat_sector_t s, *secp, sectors[65]; /* 65 is maximum possible */
  int32_t ldlinux_cluster;
  int nsectors;
  const char *errmsg;

  int force = 0;              /* -f (force) option */
  int stupid = 0;             /* -s (stupid) option */
  int raid_mode = 0;          /* -r (RAID) option */

  (void)argc;			/* Unused */

  mypid = getpid();
  program = argv[0];

  device = NULL;

  for ( argp = argv+1 ; *argp ; argp++ ) {
    if ( **argp == '-' ) {
      opt = *argp + 1;
      if ( !*opt )
	usage();

      while ( *opt ) {
	if ( *opt == 's' ) {
	  stupid = 1;
	} else if ( *opt == 'r' ) {
	  raid_mode = 1;
	} else if ( *opt == 'f' ) {
	  force = 1;		/* Force install */
	} else if ( *opt == 'd' && argp[1] ) {
	  subdir = *++argp;
	} else if ( *opt == 'o' && argp[1] ) {
	  filesystem_offset = (off_t)strtoull(*++argp, NULL, 0); /* Byte offset */
	} else {
	  usage();
	}
	opt++;
      }
    } else {
      if ( device )
	usage();
      device = *argp;
    }
  }

  if ( !device )
    usage();

  /*
   * First make sure we can open the device at all, and that we have
   * read/write permission.
   */
  dev_fd = open(device, O_RDWR);
  if ( dev_fd < 0 || fstat(dev_fd, &st) < 0 ) {
    perror(device);
    exit(1);
  }

  if ( !force && !S_ISBLK(st.st_mode) && !S_ISREG(st.st_mode) ) {
    fprintf(stderr, "%s: not a block device or regular file (use -f to override)\n", device);
    exit(1);
  }

  xpread(dev_fd, sectbuf, 512, filesystem_offset);

  /*
   * Check to see that what we got was indeed an MS-DOS boot sector/superblock
   */
  if( (errmsg = syslinux_check_bootsect(sectbuf)) ) {
    die(errmsg);
  }

  /*
   * Create an mtools configuration file
   */
  mtc_fd = mkstemp(mtools_conf);
  if ( mtc_fd < 0 || !(mtc = fdopen(mtc_fd, "w")) ) {
    perror(program);
    exit(1);
  }
  fprintf(mtc,
	  /* "MTOOLS_NO_VFAT=1\n" */
	  "MTOOLS_SKIP_CHECK=1\n" /* Needed for some flash memories */
	  "drive s:\n"
	  "  file=\"/proc/%lu/fd/%d\"\n"
	  "  offset=%llu\n",
	  (unsigned long)mypid,
	  dev_fd,
	  (unsigned long long)filesystem_offset);
  fclose(mtc);

  /*
   * Run mtools to create the LDLINUX.SYS file
   */
  if ( setenv("MTOOLSRC", mtools_conf, 1) ) {
    perror(program);
    exit(1);
  }

  /* This command may fail legitimately */
  system("mattrib -h -r -s s:/ldlinux.sys 2>/dev/null");

  mtp = popen("mcopy -D o -D O -o - s:/ldlinux.sys", "w");
  if ( !mtp ||
       (fwrite(syslinux_ldlinux, 1, syslinux_ldlinux_len, mtp)
	!= syslinux_ldlinux_len) ||
       (status = pclose(mtp), !WIFEXITED(status) || WEXITSTATUS(status)) ) {
    die("failed to create ldlinux.sys");
  }

  /*
   * Now, use libfat to create a block map
   */
  fs = libfat_open(libfat_xpread, dev_fd);
  ldlinux_cluster = libfat_searchdir(fs, 0, "LDLINUX SYS", NULL);
  secp = sectors;
  nsectors = 0;
  s = libfat_clustertosector(fs, ldlinux_cluster);
  while ( s && nsectors < 65 ) {
    *secp++ = s;
    nsectors++;
    s = libfat_nextsector(fs, s);
  }
  libfat_close(fs);

  /* Patch ldlinux.sys and the boot sector */
  syslinux_patch(sectors, nsectors, stupid, raid_mode);

  /* Write the now-patched first sector of ldlinux.sys */
  xpwrite(dev_fd, syslinux_ldlinux, 512,
	  filesystem_offset + ((off_t)sectors[0] << 9));

  /* Move ldlinux.sys to the desired location */
  if (subdir) {
    char target_file[4096], command[5120];
    char *cp = target_file, *ep = target_file+sizeof target_file-16;
    const char *sd;
    int slash = 1;

    cp += sprintf(cp, "'s:/");
    for (sd = subdir; *sd; sd++) {
      if (*sd == '/' || *sd == '\\') {
	if (slash)
	  continue;		/* Remove duplicated slashes */
	slash = 1;
      } else if (*sd == '\'' || *sd == '!') {
	slash = 0;
	if (cp < ep) *cp++ = '\'';
	if (cp < ep) *cp++ = '\\';
	if (cp < ep) *cp++ = *sd;
	if (cp < ep) *cp++ = '\'';
	continue;
      } else {
	slash = 0;
      }

      if (cp < ep)
	*cp++ = *sd;
    }
    if (!slash)
      *cp++ = '/';
    strcpy(cp, "ldlinux.sys'");

    /* This command may fail legitimately */
    sprintf(command, "mattrib -h -r -s %s 2>/dev/null", target_file);
    system(command);

    sprintf(command, "mmove -D o -D O s:/ldlinux.sys %s", target_file);
    status = system(command);

    if ( !WIFEXITED(status) || WEXITSTATUS(status) ) {
      fprintf(stderr,
	      "%s: warning: unable to move ldlinux.sys\n",
	    program);

      status = system("mattrib +r +h +s s:/ldlinux.sys");
    } else {
      sprintf(command, "mattrib +r +h +s %s", target_file);
      status = system(command);
    }
  } else {
    status = system("mattrib +r +h +s s:/ldlinux.sys");
  }

  if ( !WIFEXITED(status) || WEXITSTATUS(status) ) {
    fprintf(stderr,
	    "%s: warning: failed to set system bit on ldlinux.sys\n",
	    program);
  }


  /*
   * Cleanup
   */
  unlink(mtools_conf);

  /*
   * To finish up, write the boot sector
   */

  /* Read the superblock again since it might have changed while mounted */
  xpread(dev_fd, sectbuf, 512, filesystem_offset);

  /* Copy the syslinux code into the boot sector */
  syslinux_make_bootsect(sectbuf);

  /* Write new boot sector */
  xpwrite(dev_fd, sectbuf, 512, filesystem_offset);

  close(dev_fd);
  sync();

  /* Done! */

  return 0;
}
예제 #24
0
파일: plain_store.c 프로젝트: DLag/sheepdog
int default_create_and_write(uint64_t oid, const struct siocb *iocb)
{
	char path[PATH_MAX], tmp_path[PATH_MAX];
	int flags = prepare_iocb(oid, iocb, true);
	int ret, fd;
	uint32_t len = iocb->length;
	size_t obj_size;
	uint64_t offset = iocb->offset;

	sd_debug("%"PRIx64, oid);
	get_store_path(oid, iocb->ec_index, path);
	get_store_tmp_path(oid, iocb->ec_index, tmp_path);

	if (uatomic_is_true(&sys->use_journal) &&
	    journal_write_store(oid, iocb->buf, iocb->length,
				iocb->offset, true)
	    != SD_RES_SUCCESS) {
		sd_err("turn off journaling");
		uatomic_set_false(&sys->use_journal);
		flags |= O_DSYNC;
		sync();
	}

	fd = open(tmp_path, flags, sd_def_fmode);
	if (fd < 0) {
		if (errno == EEXIST) {
			/*
			 * This happens if node membership changes during object
			 * creation; while gateway retries a CREATE request,
			 * recovery process could also recover the object at the
			 * same time.  They should try to write the same date,
			 * so it is okay to simply return success here.
			 */
			sd_debug("%s exists", tmp_path);
			return SD_RES_SUCCESS;
		}

		sd_err("failed to open %s: %m", tmp_path);
		return err_to_sderr(path, oid, errno);
	}

	obj_size = get_store_objsize(oid);

	trim_zero_blocks(iocb->buf, &offset, &len);

	if (offset != 0 || len != get_objsize(oid)) {
		if (is_sparse_object(oid))
			ret = xftruncate(fd, obj_size);
		else
			ret = prealloc(fd, obj_size);
		if (ret < 0) {
			ret = err_to_sderr(path, oid, errno);
			goto out;
		}
	}

	ret = xpwrite(fd, iocb->buf, len, offset);
	if (ret != len) {
		sd_err("failed to write object. %m");
		ret = err_to_sderr(path, oid, errno);
		goto out;
	}

	ret = rename(tmp_path, path);
	if (ret < 0) {
		sd_err("failed to rename %s to %s: %m", tmp_path, path);
		ret = err_to_sderr(path, oid, errno);
		goto out;
	}

	ret = SD_RES_SUCCESS;
	objlist_cache_insert(oid);
out:
	if (ret != SD_RES_SUCCESS)
		unlink(tmp_path);
	close(fd);
	return ret;
}
예제 #25
0
int default_create_and_write(uint64_t oid, const struct siocb *iocb)
{
	char path[PATH_MAX], tmp_path[PATH_MAX];
	int flags = get_open_flags(oid, true, iocb->flags);
	int ret, fd;
	uint32_t len = iocb->length;

	get_obj_path(oid, path);
	get_tmp_obj_path(oid, tmp_path);

	if (uatomic_is_true(&sys->use_journal) &&
	    journal_file_write(oid, iocb->buf, iocb->length, iocb->offset, true)
	    != SD_RES_SUCCESS) {
		sd_eprintf("turn off journaling");
		uatomic_set_false(&sys->use_journal);
		flags |= O_DSYNC;
		sync();
	}

	fd = open(tmp_path, flags, def_fmode);
	if (fd < 0) {
		if (errno == EEXIST) {
			/*
			 * This happens if node membership changes during object
			 * creation; while gateway retries a CREATE request,
			 * recovery process could also recover the object at the
			 * same time.  They should try to write the same date,
			 * so it is okay to simply return success here.
			 */
			sd_dprintf("%s exists", tmp_path);
			return SD_RES_SUCCESS;
		}

		sd_eprintf("failed to open %s: %m", tmp_path);
		return err_to_sderr(oid, errno);
	}

	if (iocb->offset != 0 || iocb->length != get_objsize(oid)) {
		ret = prealloc(fd, get_objsize(oid));
		if (ret < 0) {
			ret = err_to_sderr(oid, errno);
			goto out;
		}
	}

	ret = xpwrite(fd, iocb->buf, len, iocb->offset);
	if (ret != len) {
		sd_eprintf("failed to write object. %m");
		ret = err_to_sderr(oid, errno);
		goto out;
	}

	ret = rename(tmp_path, path);
	if (ret < 0) {
		sd_eprintf("failed to rename %s to %s: %m", tmp_path, path);
		ret = err_to_sderr(oid, errno);
		goto out;
	}
	sd_dprintf("%"PRIx64, oid);
	ret = SD_RES_SUCCESS;
out:
	if (ret != SD_RES_SUCCESS)
		unlink(tmp_path);
	close(fd);
	return ret;
}
예제 #26
0
static int update_epoch_from_v1_to_v2(uint32_t epoch)
{
	char path[PATH_MAX];
	struct sd_node_v1 nodes_v1[SD_MAX_NODES];
	struct sd_node_v2 nodes_v2[SD_MAX_NODES];
	size_t nr_nodes;
	time_t *t;
	int len, fd, ret;

	snprintf(path, sizeof(path), "%s%08u", epoch_path, epoch);
	fd = open(path, O_RDWR | O_DSYNC);
	if (fd < 0) {
		if (errno == ENOENT)
			return 0;

		sd_eprintf("failed to open epoch %"PRIu32" log", epoch);
		return -1;
	}

	/*
	 * sheepdog 0.5.6 was released without incrementing the config version.
	 * We detect it by 1) checking the size of epoch file, and 2) checking
	 * the value of sd_node.nid.port
	 */
	if ((get_file_size(path) - sizeof(time_t)) % sizeof(nodes_v1[0]) != 0) {
		sd_dprintf("%s is not a v1 format", path);
		close(fd);
		return 0;
	}

	ret = xread(fd, nodes_v1, sizeof(nodes_v1));
	if (ret < 0) {
		sd_eprintf("failed to read epoch %"PRIu32" log", epoch);
		close(fd);
		return ret;
	}

	nr_nodes = ret / sizeof(nodes_v1[0]);
	for (int i = 0; i < nr_nodes; i++) {
		if (nodes_v1[i].nid.port == 0) {
			sd_dprintf("%s is not a v1 format", path);
			return 0;
		}
		memset(&nodes_v2[i].nid, 0, sizeof(nodes_v2[i].nid));
		memcpy(nodes_v2[i].nid.addr, nodes_v1[i].nid.addr,
		       sizeof(nodes_v2[i].nid.addr));
		nodes_v2[i].nid.port = nodes_v1[i].nid.port;
		nodes_v2[i].nr_vnodes = nodes_v1[i].nr_vnodes;
		nodes_v2[i].zone = nodes_v1[i].zone;
		nodes_v2[i].space = nodes_v1[i].space;
	}

	len = sizeof(nodes_v2[0]) * nr_nodes;
	ret = xpwrite(fd, nodes_v2, len, 0);
	if (ret != len) {
		sd_eprintf("failed to write epoch %"PRIu32" log",
			   epoch);
		close(fd);
		return -1;
	}

	t = (time_t *)&nodes_v1[nr_nodes];

	ret = xpwrite(fd, t, sizeof(*t), len);
	if (ret != sizeof(*t)) {
		sd_eprintf("failed to write time to epoch %"
			   PRIu32" log", epoch);
		close(fd);
		return -1;
	}

	close(fd);

	return 0;
}
예제 #27
0
int default_create_and_write(uint64_t oid, const struct siocb *iocb)
{
	char path[PATH_MAX], tmp_path[PATH_MAX];
	int flags = prepare_iocb(oid, iocb, true);
	int ret, fd;
	uint32_t len = iocb->length;
	size_t obj_size;

	sd_debug("%"PRIx64, oid);
	get_store_path(oid, iocb->ec_index, path);
	get_store_tmp_path(oid, iocb->ec_index, tmp_path);
	fd = open(tmp_path, flags, sd_def_fmode);
	if (fd < 0) {
		if (errno == EEXIST) {
			/*
			 * This happens if node membership changes during object
			 * creation; while gateway retries a CREATE request,
			 * recovery process could also recover the object at the
			 * same time.  They should try to write the same date,
			 * so it is okay to simply return success here.
			 */
			sd_debug("%s exists", tmp_path);
			return SD_RES_SUCCESS;
		}

		sd_err("failed to open %s: %m", tmp_path);
		return err_to_sderr(path, oid, errno);
	}

	obj_size = get_store_objsize(oid);
	ret = prealloc(fd, obj_size);
	if (ret < 0) {
	          ret = err_to_sderr(path, oid, errno);
		  goto out;
	}

	ret = xpwrite(fd, iocb->buf, len, iocb->offset);
	if (ret != len) {
		sd_err("failed to write object. %m");
		ret = err_to_sderr(path, oid, errno);
		goto out;
	}

	/*
	 * Modern FS like ext4, xfs defaults to automatic syncing of files after
	 * replace-via-rename and replace-via-truncate operations. So rename
	 * without fsync() is actually safe.
	 */
	ret = rename(tmp_path, path);
	if (ret < 0) {
		sd_err("failed to rename %s to %s: %m", tmp_path, path);
		ret = err_to_sderr(path, oid, errno);
		goto out;
	}

	ret = SD_RES_SUCCESS;
	objlist_cache_insert(oid);
out:
	if (ret != SD_RES_SUCCESS && unlink(tmp_path) != 0)
		sd_err("failed to unlink %s: %m", tmp_path);
	close(fd);
	return ret;
}
예제 #28
0
/*
 * Bulk transfer routine --
 *  used by getfl(), cu_take(), and pipefile()
 */
static void
transfer(char *buf, int fd, char *eofchars)
{
	register int ct;
	char c;
	register int cnt, eof, v;
	time_t start;
	sig_t f;
	char r;
	FILE *ff;

	v = boolean(value(VERBOSE));

	if ((ff = fdopen (fd, "w")) == NULL) {
		warn("file open");
		return;
	}
	if ((cnt = number(value(FRAMESIZE))) != BUFSIZ)
		if (setvbuf(ff, NULL, _IOFBF, cnt) != 0) {
			warn("file allocation");
			(void)fclose(ff);
			return;
		}

	xpwrite(FD, buf, size(buf));
	quit = 0;
	kill(pid, SIGIOT);
	read(repdes[0], (char *)&ccc, 1);  /* Wait until read process stops */

	/*
	 * finish command
	 */
	r = '\r';
	xpwrite(FD, &r, 1);
	do
		read(FD, &c, 1);
	while ((c&0177) != '\n');
	usedefchars ();
	(void) setjmp(intbuf);
	f = signal(SIGINT, intcopy);
	start = time(0);
	for (ct = 0; !quit;) {
		eof = read(FD, &c, 1) <= 0;
		c &= 0177;
		if (quit)
			continue;
		if (eof || any(c, eofchars))
			break;
		if (c == 0)
			continue;	/* ignore nulls */
		if (c == '\r')
			continue;
		if (c == '\n' && v)
			printf("\r%d", ++ct);
		fputc(c, ff);
	}
	if (v)
		prtime(" lines transferred in ", time(0)-start);
	usetchars ();
	write(fildes[1], (char *)&ccc, 1);
	signal(SIGINT, f);
	(void)fclose(ff);
}
예제 #29
0
파일: advio.c 프로젝트: emmericp/syslinux
/*
 * Update the ADV in an existing installation.
 */
int write_adv(const char *path, const char *cfg)
{
    unsigned char advtmp[2 * ADV_SIZE];
    char *file;
    int fd = -1;
    struct stat st, xst;
    int err = 0;
    int rv;

    rv = asprintf(&file, "%s%s%s", path,
		  path[0] && path[strlen(path) - 1] == '/' ? "" : "/", cfg);

    if (rv < 0 || !file) {
	perror(program);
	return -1;
    }

    fd = open(file, O_RDONLY);
    if (fd < 0) {
	err = -1;
    } else if (fstat(fd, &st)) {
	err = -1;
    } else if (st.st_size < 2 * ADV_SIZE) {
	/* Too small to be useful */
	err = -2;
    } else if (xpread(fd, advtmp, 2 * ADV_SIZE,
		      st.st_size - 2 * ADV_SIZE) != 2 * ADV_SIZE) {
	err = -1;
    } else {
	/* We got it... maybe? */
	err = syslinux_validate_adv(advtmp) ? -2 : 0;
	if (!err) {
	    /* Got a good one, write our own ADV here */
	    clear_attributes(fd);

	    /* Need to re-open read-write */
	    close(fd);
	    fd = open(file, O_RDWR | O_SYNC);
	    if (fd < 0) {
		fprintf(stderr, "Cannot open file '%s' in read/write mode !\nFatal error, exiting.\n", file);
		return -EACCES;
	    } else if (fstat(fd, &xst) || xst.st_ino != st.st_ino ||
		       xst.st_dev != st.st_dev || xst.st_size != st.st_size) {
		fprintf(stderr, "%s: race condition on write\n", file);
		err = -2;
	    }
	    /* Write our own version ... */
	    if (xpwrite(fd, syslinux_adv, 2 * ADV_SIZE,
			st.st_size - 2 * ADV_SIZE) != 2 * ADV_SIZE) {
		err = -1;
	    }

	    sync();
	    set_attributes(fd);
	}
    }

    if (err == -2)
	fprintf(stderr, "%s: cannot write auxiliary data (need --update)?\n",
		file);
    else if (err == -1)
	perror(file);

    if (fd >= 0)
	close(fd);
    if (file)
	free(file);

    return err;
}
예제 #30
0
int main(int argc, char *argv[])
{
  static unsigned char sectbuf[512];
  unsigned char *dp;
  const unsigned char *cdp;
  int dev_fd, fd;
  struct stat st;
  int nb, left;
  int err = 0;
  pid_t f, w;
  int status;
  char mntname[64], devfdname[64];
  char *ldlinux_name, **argp, *opt;
  int my_umask;
  int force = 0;		/* -f (force) option */
  int offset = 0;		/* -o (offset) option */

  program = argv[0];
  mypid = getpid();
  
  device = NULL;

  umask(077);

  for ( argp = argv+1 ; *argp ; argp++ ) {
    if ( **argp == '-' ) {
      opt = *argp + 1;
      if ( !*opt )
	usage();

      while ( *opt ) {
	if ( *opt == 's' ) {
	  syslinux_make_stupid();	/* Use "safe, slow and stupid" code */
	} else if ( *opt == 'f' ) {
	  force = 1;		/* Force install */
	} else if ( *opt == 'o' && argp[1] ) {
	  offset = strtoul(*++argp, NULL, 0); /* Byte offset */
	} else {
	  usage();
	}
	opt++;
      }
    } else {
      if ( device )
	usage();
      device = *argp;
    }
  }

  if ( !device )
    usage();

  /*
   * First make sure we can open the device at all, and that we have
   * read/write permission.
   */
  dev_fd = open(device, O_RDWR|O_LARGEFILE);
  if ( dev_fd < 0 || fstat(dev_fd, &st) < 0 ) {
    perror(device);
    exit(1);
  }

  if ( !force && !S_ISBLK(st.st_mode) && !S_ISREG(st.st_mode) ) {
    die("not a block device or regular file (use -f to override)");
  }

  if ( !force && offset != 0 && !S_ISREG(st.st_mode) ) {
    die("not a regular file and an offset specified (use -f to override)");
  }

  xpread(dev_fd, sectbuf, 512, offset);
  fsync(dev_fd);

  /*
   * Check to see that what we got was indeed an MS-DOS boot sector/superblock
   */
  if(!syslinux_check_bootsect(sectbuf,device)) {
    exit(1);
  }

  /*
   * Now mount the device.
   */
  if ( geteuid() ) {
    die("This program needs root privilege");
  } else {
    int i = 0;
    struct stat dst;
    int rv;

    /* We're root or at least setuid.
       Make a temp dir and pass all the gunky options to mount. */

    if ( chdir("/tmp") ) {
      perror(program);
      exit(1);
    }

#define TMP_MODE (S_IXUSR|S_IWUSR|S_IXGRP|S_IWGRP|S_IWOTH|S_IXOTH|S_ISVTX)

    if ( stat(".", &dst) || !S_ISDIR(dst.st_mode) ||
	 (dst.st_mode & TMP_MODE) != TMP_MODE ) {
      die("possibly unsafe /tmp permissions");
    }

    for ( i = 0 ; ; i++ ) {
      snprintf(mntname, sizeof mntname, "syslinux.mnt.%lu.%d",
	       (unsigned long)mypid, i);

      if ( lstat(mntname, &dst) != -1 || errno != ENOENT )
	continue;

      rv = mkdir(mntname, 0000);

      if ( rv == -1 ) {
	if ( errno == EEXIST || errno == EINTR )
	  continue;
	perror(program);
	exit(1);
      }

      if ( lstat(mntname, &dst) || dst.st_mode != (S_IFDIR|0000) ||
	   dst.st_uid != 0 ) {
	die("someone is trying to symlink race us!");
      }
      break;			/* OK, got something... */
    }

    mntpath = mntname;

#if DO_DIRECT_MOUNT
    if ( S_ISREG(st.st_mode) ) {
      /* It's file, need to mount it loopback */
      unsigned int n = 0;
      struct loop_info64 loopinfo;

      for ( n = 0 ; loop_fd < 0 ; n++ ) {
	snprintf(devfdname, sizeof devfdname, "/dev/loop%u", n);
	loop_fd = open(devfdname, O_RDWR);
	if ( loop_fd < 0 && errno == ENOENT ) {
	  die("no available loopback device!");
	}
	if ( ioctl(loop_fd, LOOP_SET_FD, (void *)dev_fd) ) {
	  close(loop_fd); loop_fd = -1;
	  if ( errno != EBUSY )
	    die("cannot set up loopback device");
	  else
	    continue;
	}
	
	if ( ioctl(loop_fd, LOOP_GET_STATUS64, &loopinfo) ||
	     (loopinfo.lo_offset = offset,
	      ioctl(loop_fd, LOOP_SET_STATUS64, &loopinfo)) )
	  die("cannot set up loopback device");
      }
    } else {
      snprintf(devfdname, sizeof devfdname, "/proc/%lu/fd/%d",
	       (unsigned long)mypid, dev_fd);
    }

    if ( mount(devfdname, mntpath, "msdos",
	       MS_NOEXEC|MS_NOSUID, "umask=077,quiet") )
      die("could not mount filesystem");

#else

    snprintf(devfdname, sizeof devfdname, "/proc/%lu/fd/%d",
	     (unsigned long)mypid, dev_fd);

    f = fork();
    if ( f < 0 ) {
      perror(program);
      rmdir(mntpath);
      exit(1);
    } else if ( f == 0 ) {
      char mnt_opts[128];
      if ( S_ISREG(st.st_mode) ) {
	snprintf(mnt_opts, sizeof mnt_opts, "rw,nodev,noexec,loop,offset=%llu,umask=077,quiet",
		 (unsigned long long)offset);
      } else {
	snprintf(mnt_opts, sizeof mnt_opts, "rw,nodev,noexec,umask=077,quiet");
      }
      execl(_PATH_MOUNT, _PATH_MOUNT, "-t", "msdos", "-o", mnt_opts,\
	    devfdname, mntpath, NULL);
      _exit(255);		/* execl failed */
    }

    w = waitpid(f, &status, 0);
    if ( w != f || status ) {
      rmdir(mntpath);
      exit(1);			/* Mount failed */
    }
    
#endif
  }
  
  ldlinux_name = alloca(strlen(mntpath)+13);
  if ( !ldlinux_name ) {
    perror(program);
    err = 1;
    goto umount;
  }
  sprintf(ldlinux_name, "%s/ldlinux.sys", mntpath);

  unlink(ldlinux_name);
  fd = open(ldlinux_name, O_WRONLY|O_CREAT|O_TRUNC, 0444);
  if ( fd < 0 ) {
    perror(device);
    err = 1;
    goto umount;
  }

  cdp = syslinux_ldlinux;
  left = syslinux_ldlinux_len;
  while ( left ) {
    nb = write(fd, cdp, left);
    if ( nb == -1 && errno == EINTR )
      continue;
    else if ( nb <= 0 ) {
      perror(device);
      err = 1;
      goto umount;
    }

    dp += nb;
    left -= nb;
  }

  /*
   * I don't understand why I need this.  Does the DOS filesystems
   * not honour the mode passed to open()?
   */
  fchmod(fd, 0400);

  close(fd);

umount:
#if DO_DIRECT_MOUNT

  if ( umount2(mntpath, 0) )
    die("could not umount path");

  if ( loop_fd != -1 ) {
    ioctl(loop_fd, LOOP_CLR_FD, 0); /* Free loop device */
    close(loop_fd);
    loop_fd = -1;
  }

#else

  f = fork();
  if ( f < 0 ) {
    perror("fork");
    exit(1);
  } else if ( f == 0 ) {
    execl(_PATH_UMOUNT, _PATH_UMOUNT, mntpath, NULL);
  }

  w = waitpid(f, &status, 0);
  if ( w != f || status ) {
    exit(1);
  }

#endif

  sync();
  rmdir(mntpath);

  if ( err )
    exit(err);

  /*
   * To finish up, write the boot sector
   */

  /* Read the superblock again since it might have changed while mounted */
  xpread(dev_fd, sectbuf, 512, offset);

  /* Copy the syslinux code into the boot sector */
  syslinux_make_bootsect(sectbuf);

  /* Write new boot sector */
  xpwrite(dev_fd, sectbuf, 512, offset);

  close(dev_fd);
  sync();

  /* Done! */

  return 0;
}