Example #1
0
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;
}
Example #2
0
static int farm_read(uint64_t oid, struct siocb *iocb)
{
    int i;

    if (iocb->epoch < sys->epoch) {
        void *buffer;
        buffer = read_working_object(oid, iocb->length);
        if (!buffer) {
            /* Here if read the object from the targeted epoch failed,
             * we need to read from the later epoch, because at some epoch
             * we doesn't write the object to the snapshot, we assume
             * it in the current local object directory, but maybe
             * in the next epoch we removed it from the local directory.
             * in this case, we should try to retrieve object upwards, since.
             * when the object is to be removed, it will get written to the
             * snapshot at later epoch. */
            for (i = iocb->epoch; i < sys->epoch; i++) {
                buffer = retrieve_object_from_snap(oid, i);
                if (buffer)
                    break;
            }
        }
        if (!buffer)
            return SD_RES_NO_OBJ;
        memcpy(iocb->buf, buffer, iocb->length);
        free(buffer);
    } else {
        ssize_t size = xpread(iocb->fd, iocb->buf, iocb->length, iocb->offset);

        if (size != iocb->length)
            return SD_RES_EIO;
    }
    return SD_RES_SUCCESS;
}
Example #3
0
int init_config_file(void)
{
	int fd, ret;

	check_tmp_config();

	fd = open(config_path, O_RDONLY);
	if (fd < 0) {
		if (errno != ENOENT) {
			sd_eprintf("failed to read config file, %m");
			return -1;
		}
		goto create;
	}

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

	if (config.version != SD_FORMAT_VERSION) {
		sd_eprintf("This sheep version is not compatible with"
			   " the existing data layout, %d", config.version);
		if (sys->upgrade) {
			/* upgrade sheep store */
			ret = sd_migrate_store(config.version, SD_FORMAT_VERSION);
			if (ret == 0) {
				/* reload config file */
				ret = xpread(fd, &config, sizeof(config), 0);
				if (ret != sizeof(config)) {
					sd_eprintf("failed to reload config"
						   " file, %m");
					ret = -1;
				} else
					ret = 0;
			}
			goto out;
		}

		sd_eprintf("use '-u' option to upgrade sheep store");
		ret = -1;
		goto out;
	}
	ret = 0;
out:
	close(fd);

	return ret;
create:
	config.version = SD_FORMAT_VERSION;
	if (write_config() != SD_RES_SUCCESS)
		return -1;

	return 0;
}
Example #4
0
static int rd_copy_image(const char *path)
{
	int ffd = open(path, O_RDONLY);
	int rv = -1;
	unsigned char gzip_magic[2];

	if (ffd < 0)
		goto barf;

	if (xpread(ffd, gzip_magic, 2, 0) == 2 &&
	    gzip_magic[0] == 037 && gzip_magic[1] == 0213) {
		FILE *wfd = fopen("/dev/ram0", "w");
		if (!wfd)
			goto barf;
		rv = load_ramdisk_compressed(path, wfd, 0);
		fclose(wfd);
	} else {
		int dfd = open("/dev/ram0", O_WRONLY);
		if (dfd < 0)
			goto barf;
		rv = rd_copy_uncompressed(ffd, dfd);
		close(dfd);
	}

barf:
	if (ffd >= 0)
		close(ffd);
	return rv;
}
Example #5
0
static int init_vdi_copy_number(uint64_t oid)
{
	char path[PATH_MAX];
	int fd, flags = get_open_flags(oid, false), ret;
	struct sheepdog_inode *inode = xzalloc(sizeof(*inode));

	snprintf(path, sizeof(path), "%s%016" PRIx64, obj_path, oid);

	fd = open(path, flags);
	if (fd < 0) {
		eprintf("failed to open %s, %m\n", path);
		ret = SD_RES_EIO;
		goto out;
	}

	ret = xpread(fd, inode, SD_INODE_HEADER_SIZE, 0);
	if (ret != SD_INODE_HEADER_SIZE) {
		eprintf("failed to read inode header, path=%s, %m\n", path);
		ret = SD_RES_EIO;
		goto out;
	}

	add_vdi_copy_number(oid_to_vid(oid), inode->nr_copies);

	ret = SD_RES_SUCCESS;
out:
	free(inode);
	return SD_RES_SUCCESS;
}
Example #6
0
/*
 * 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;
}
Example #7
0
static int default_read_from_path(uint64_t oid, const char *path,
				  const struct siocb *iocb)
{
	int flags = prepare_iocb(oid, iocb, false), fd,
	    ret = SD_RES_SUCCESS;
	ssize_t size;

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

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

	size = xpread(fd, iocb->buf, iocb->length, iocb->offset);
	if (unlikely(size != iocb->length)) {
		sd_err("failed to read 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);
	}
	close(fd);
	return ret;
}
Example #8
0
static void *read_working_object(uint64_t oid, uint64_t offset,
				 uint32_t length)
{
	void *buf = NULL;
	char path[PATH_MAX];
	int fd, flags = def_open_flags;
	size_t size;

	snprintf(path, sizeof(path), "%s%016" PRIx64, obj_path, oid);

	if (!is_data_obj(oid))
		flags &= ~O_DIRECT;

	fd = open(path, flags);
	if (fd < 0) {
		dprintf("object %"PRIx64" not found\n", oid);
		goto out;
	}

	buf = valloc(length);
	if (!buf) {
		eprintf("no memory to allocate buffer.\n");
		goto out;
	}

	if (flock(fd, LOCK_SH) < 0) {
		eprintf("%m\n");
		goto err;
	}

	size = xpread(fd, buf, length, offset);
	if (flock(fd, LOCK_UN) < 0) {
		eprintf("%m\n");
		goto err;
	}

	if (length != size) {
		eprintf("size %zu len %"PRIu32" off %"PRIu64" %m\n", size,
			length, offset);
		goto err;
	}

out:
	if (fd > 0)
		close(fd);
	return buf;
err:
	free(buf);
	close(fd);
	return NULL;
}
Example #9
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;
}
Example #10
0
int shadow_file_read(const char *path, char *buf, size_t size, off_t offset)
{
	char p[PATH_MAX];
	int fd, len;

	snprintf(p, sizeof(p), "%s%s", sheepfs_shadow, path);
	fd = open(p, O_RDONLY);
	if (fd < 0) {
		sheepfs_pr("%m\n");
		return -errno;
	}
	len = xpread(fd, buf, size, offset);
	close(fd);
	return len;
}
Example #11
0
/*
 * Read the ADV from an existing instance, or initialize if invalid.
 * Returns -1 on fatal errors, 0 if ADV is okay, 1 if the ADV is
 * invalid, and 2 if the file does not exist.
 */
int read_adv(const char *path, const char *cfg)
{
    char *file;
    int fd = -1;
    struct stat st;
    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) {
	if (errno != ENOENT) {
	    err = -1;
	} else {
	    syslinux_reset_adv(syslinux_adv);
	    err = 2;		/* Nonexistence is not a fatal error */
	}
    } else if (fstat(fd, &st)) {
	err = -1;
    } else if (st.st_size < 2 * ADV_SIZE) {
	/* Too small to be useful */
	syslinux_reset_adv(syslinux_adv);
	err = 0;		/* Nothing to read... */
    } else if (xpread(fd, syslinux_adv, 2 * ADV_SIZE,
		      st.st_size - 2 * ADV_SIZE) != 2 * ADV_SIZE) {
	err = -1;
    } else {
	/* We got it... maybe? */
	err = syslinux_validate_adv(syslinux_adv) ? 1 : 0;
    }

    if (err < 0)
	perror(file);

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

    free(file);

    return err;
}
Example #12
0
ssize_t pread_in_full(int fd, void *buf, size_t count, off_t offset)
{
	char *p = buf;
	ssize_t total = 0;

	while (count > 0) {
		ssize_t loaded = xpread(fd, p, count, offset);
		if (loaded < 0)
			return -1;
		if (loaded == 0)
			return total;
		count -= loaded;
		p += loaded;
		total += loaded;
		offset += loaded;
	}

	return total;
}
Example #13
0
static int default_read_from_path(uint64_t oid, char *path,
				  const struct siocb *iocb)
{
	int flags = prepare_iocb(oid, iocb, false), fd,
	    ret = SD_RES_SUCCESS;
	ssize_t size;

	fd = open(path, flags);

	if (fd < 0)
		return err_to_sderr(path, oid, errno);

	size = xpread(fd, iocb->buf, iocb->length, iocb->offset);
	if (unlikely(size != iocb->length)) {
		sd_err("failed to read 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);
	}
	close(fd);
	return ret;
}
Example #14
0
static int default_read_from_path(uint64_t oid, char *path,
				       struct siocb *iocb)
{
	int flags = get_open_flags(oid, false), fd, ret = SD_RES_SUCCESS;
	ssize_t size;

	fd = open(path, flags);

	if (fd < 0)
		return err_to_sderr(oid, errno);

	size = xpread(fd, iocb->buf, iocb->length, iocb->offset);
	if (size != iocb->length) {
		eprintf("failed to read 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);
	}

	close(fd);

	return ret;
}
Example #15
0
static int default_read_from_path(uint64_t oid, const char *path,
				  const struct siocb *iocb)
{
	int flags = prepare_iocb(oid, iocb, false), fd,
	    ret = SD_RES_SUCCESS;
	ssize_t size;

	fd = open(path, flags);

	if (fd < 0)
		return err_to_sderr(path, oid, errno);

	if (is_erasure_oid(oid) && iocb->ec_index <= SD_MAX_COPIES) {
		uint8_t idx;

		if (get_erasure_index(path, &idx) < 0) {
			close(fd);
			return err_to_sderr(path, oid, errno);
		}
		/* We pretend NO-OBJ to read old object in the stale dir */
		if (idx != iocb->ec_index) {
			sd_debug("ec_index %d != %d", iocb->ec_index, idx);
			close(fd);
			return SD_RES_NO_OBJ;
		}
	}

	size = xpread(fd, iocb->buf, iocb->length, iocb->offset);
	if (unlikely(size != iocb->length)) {
		sd_err("failed to read 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);
	}
	close(fd);
	return ret;
}
Example #16
0
ssize_t pread_in_full(int fd, void *buf, size_t count, off_t offset)
{
	ssize_t total = 0;
	char *p = buf;

	while (count > 0) {
		ssize_t nr;

		nr = xpread(fd, p, count, offset);
		if (nr <= 0) {
			if (total > 0)
				return total;

			return -1;
		}

		count -= nr;
		total += nr;
		p += nr;
		offset += nr;
	}

	return total;
}
Example #17
0
int jrnl_recover(const char *jrnl_dir)
{
	DIR *dir;
	struct dirent *d;
	char jrnl_file_path[PATH_MAX];

	sd_eprintf("opening the directory %s", jrnl_dir);
	dir = opendir(jrnl_dir);
	if (!dir)
		return -1;

	sd_printf(SDOG_NOTICE, "starting journal recovery");
	while ((d = readdir(dir))) {
		struct jrnl_descriptor jd;
		uint32_t end_mark = 0;
		int ret;

		if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
			continue;

		snprintf(jrnl_file_path, sizeof(jrnl_file_path), "%s%s",
			 jrnl_dir, d->d_name);
		ret = jrnl_open(&jd, jrnl_file_path);
		if (ret) {
			sd_eprintf("unable to open the journal file %s for"
				   " reading", jrnl_file_path);
			goto end_while_3;
		}

		ret = xpread(jd.fd, &jd.head, sizeof(jd.head), 0);
		if (ret != sizeof(jd.head)) {
			sd_eprintf("can't read journal head");
			goto end_while_2;
		}

		ret = xpread(jd.fd, &end_mark, sizeof(end_mark),
				sizeof(jd.head) + jd.head.size);
		if (ret != sizeof(end_mark)) {
			sd_eprintf("can't read journal end mark for object %s",
				   jd.head.target_path);
			goto end_while_2;
		}

		if (end_mark != JRNL_END_MARK)
			goto end_while_2;

		jd.target_fd = open(jd.head.target_path, O_DSYNC | O_RDWR);
		if (jd.target_fd < 0) {
			sd_eprintf("unable to open the object file %s for"
				   " recovery", jd.head.target_path);
			goto end_while_2;
		}
		ret = jrnl_apply_to_target_object(&jd);
		if (ret)
			sd_eprintf("unable to recover the object %s",
				   jd.head.target_path);

		close(jd.target_fd);
		jd.target_fd = -1;
end_while_2:
		jrnl_close(&jd);
end_while_3:
		sd_printf(SDOG_INFO, "recovered the object %s from the journal",
			  jrnl_file_path);
		jrnl_remove(&jd);
	}
	closedir(dir);
	sd_printf(SDOG_NOTICE, "journal recovery complete");

	return 0;
}
Example #18
0
int main(int argc, char *argv[])
{
    static unsigned char sectbuf[SECTOR_SIZE];
    int dev_fd;
    struct stat st;
    int status;
    const char *tmpdir;
    char *mtools_conf;
    int mtc_fd;
    FILE *mtc, *mtp;
    struct libfat_filesystem *fs;
    libfat_sector_t s, *secp;
    libfat_sector_t *sectors;
    int32_t ldlinux_cluster;
    int nsectors;
    const char *errmsg;
    int ldlinux_sectors, patch_sectors;
    int i;

    (void)argc;			/* Unused */

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

    parse_options(argc, argv, MODE_SYSLINUX);

    if (!opt.device)
	usage(EX_USAGE, MODE_SYSLINUX);

    if (opt.sectors || opt.heads || opt.reset_adv || opt.set_once
	|| (opt.update_only > 0) || opt.menu_save) {
	fprintf(stderr,
		"At least one specified option not yet implemented"
		" for this installer.\n");
	exit(1);
    }

    /*
     * Temp directory of choice...
     */
    tmpdir = getenv("TMPDIR");
    if (!tmpdir) {
#ifdef P_tmpdir
	tmpdir = P_tmpdir;
#elif defined(_PATH_TMP)
	tmpdir = _PATH_TMP;
#else
	tmpdir = "/tmp";
#endif
    }

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

    if (!opt.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",
		opt.device);
	exit(1);
    }

    xpread(dev_fd, sectbuf, SECTOR_SIZE, opt.offset);

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

    /*
     * Create an mtools configuration file
     */
    if (asprintf(&mtools_conf, "%s//syslinux-mtools-XXXXXX", tmpdir) < 0 ||
	!mtools_conf)
	die_err(tmpdir);

    mtc_fd = mkstemp(mtools_conf);
    if (mtc_fd < 0 || !(mtc = fdopen(mtc_fd, "w")))
	die_err(mtools_conf);

    fprintf(mtc,
	    /* These are needed for some flash memories */
	    "MTOOLS_SKIP_CHECK=1\n"
	    "MTOOLS_FAT_COMPATIBILITY=1\n"
	    "drive s:\n"
	    "  file=\"/proc/%lu/fd/%d\"\n"
	    "  offset=%llu\n",
	    (unsigned long)mypid,
	    dev_fd, (unsigned long long)opt.offset);

    if (ferror(mtc) || fclose(mtc))
	die_err(mtools_conf);

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

    /*
     * Create a vacuous ADV in memory.  This should be smarter.
     */
    syslinux_reset_adv(syslinux_adv);

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

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

    /*
     * Now, use libfat to create a block map
     */
    ldlinux_sectors = (syslinux_ldlinux_len + 2 * ADV_SIZE
		       + SECTOR_SIZE - 1) >> SECTOR_SHIFT;
    sectors = calloc(ldlinux_sectors, sizeof *sectors);
    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 < ldlinux_sectors) {
	*secp++ = s;
	nsectors++;
	s = libfat_nextsector(fs, s);
    }
    libfat_close(fs);

    /* Patch ldlinux.sys and the boot sector */
    i = syslinux_patch(sectors, nsectors, opt.stupid_mode, opt.raid_mode,
		       opt.directory, NULL);
    patch_sectors = (i + SECTOR_SIZE - 1) >> SECTOR_SHIFT;

    /* Write the now-patched first sectors of ldlinux.sys */
    for (i = 0; i < patch_sectors; i++) {
	xpwrite(dev_fd, (const char _force *)syslinux_ldlinux
		+ i * SECTOR_SIZE, SECTOR_SIZE,
		opt.offset + ((off_t) sectors[i] << SECTOR_SHIFT));
    }

    /* Move ldlinux.sys to the desired location */
    if (opt.directory) {
	status = move_file("ldlinux.sys");
    } 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);
    }

    /* This command may fail legitimately */
    status = system("mattrib -h -r -s s:/ldlinux.c32 2>/dev/null");
    (void)status;		/* Keep _FORTIFY_SOURCE happy */

    mtp = popen("mcopy -D o -D O -o - s:/ldlinux.c32", "w");
    if (!mtp ||	fwrite((const char _force *)syslinux_ldlinuxc32,
		       1, syslinux_ldlinuxc32_len, mtp)
	!= syslinux_ldlinuxc32_len ||
	(status = pclose(mtp), !WIFEXITED(status) || WEXITSTATUS(status))) {
	die("failed to create ldlinux.c32");
    }

    /* Move ldlinux.c32 to the desired location */
    if (opt.directory) {
	status = move_file("ldlinux.c32");
    } else {
	status = system("mattrib +r +h +s s:/ldlinux.c32");
    }

    if (!WIFEXITED(status) || WEXITSTATUS(status)) {
	fprintf(stderr,
		"%s: warning: failed to set system bit on ldlinux.c32\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, SECTOR_SIZE, opt.offset);

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

    /* Write new boot sector */
    xpwrite(dev_fd, sectbuf, SECTOR_SIZE, opt.offset);

    close(dev_fd);
    sync();

    /* Done! */

    return 0;
}
Example #19
0
int main(int argc, char *argv[])
{
    static unsigned char sectbuf[SECTOR_SIZE];
    int dev_fd, fd;
    struct stat st;
    int err = 0;
    char mntname[128];
    char *ldlinux_name;
    char *ldlinux_path;
    char *subdir;
    //sector_t *sectors = NULL;
    libfat_sector_t *sectors = NULL;
    int ldlinux_sectors = (boot_image_len + SECTOR_SIZE - 1) >> SECTOR_SHIFT;
    const char *errmsg;
    int mnt_cookie;
    int patch_sectors;
    int i;
    
    printf("syslinux for Mac OS X; created by Geza Kovacs for UNetbootin unetbootin.sf.net\n");

    mypid = getpid();
    umask(077);
    parse_options(argc, argv, MODE_SYSLINUX);

    /* Note: subdir is guaranteed to start and end in / */
    if (opt.directory && opt.directory[0]) {
	int len = strlen(opt.directory);
	int rv = asprintf(&subdir, "%s%s%s",
			  opt.directory[0] == '/' ? "" : "/",
			  opt.directory,
			  opt.directory[len-1] == '/' ? "" : "/");
	if (rv < 0 || !subdir) {
	    perror(program);
	    exit(1);
	}
    } else {
	subdir = "/";
    }

    if (!opt.device || opt.install_mbr || opt.activate_partition)
	usage(EX_USAGE, MODE_SYSLINUX);

    /*
     * First make sure we can open the device at all, and that we have
     * read/write permission.
     */

    if (geteuid()) {
	die("This program needs root privilege");
    }
    char umountCommand[4096];
    memset(umountCommand, 0, 4096);
    strcat(umountCommand, "hdiutil unmount ");
    strcat(umountCommand, opt.device);
    system(umountCommand);
    
    dev_fd = open(opt.device, O_RDWR);
    if (dev_fd < 0 || fstat(dev_fd, &st) < 0) {
	perror("couldn't open device");
	exit(1);
    }

    if (!S_ISBLK(st.st_mode) && !S_ISREG(st.st_mode) && !S_ISCHR(st.st_mode)) {
	die("not a device or regular file");
    }

    if (opt.offset && S_ISBLK(st.st_mode)) {
	die("can't combine an offset with a block device");
    }

    fs_type = VFAT;
    xpread(dev_fd, sectbuf, SECTOR_SIZE, opt.offset);
    fsync(dev_fd);
    close(dev_fd);

    /*
     * Check to see that what we got was indeed an MS-DOS boot sector/superblock
     */
    if ((errmsg = syslinux_check_bootsect(sectbuf))) {
	fprintf(stderr, "%s: %s\n", opt.device, errmsg);
	exit(1);
    }

    /*
     * Now mount the device.
     */
    if (geteuid()) {
	die("This program needs root privilege");
    }
#if 0
    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(_PATH_TMP)) {
	    fprintf(stderr, "%s: Cannot access the %s directory.\n",
		    program, _PATH_TMP);
	    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 " _PATH_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_mount(dev_fd, &mnt_cookie, mntpath, "vfat") &&
	do_mount(dev_fd, &mnt_cookie, mntpath, "msdos")) {
	rmdir(mntpath);
	die("mount failed");
    }

#endif

    char mountCmd[4096];
    memset(mountCmd, 0, 4096);
    strcat(mountCmd, "hdiutil mount ");
    strcat(mountCmd, opt.device);
    system(mountCmd);
    
    char mountGrepCmd[4096];
    memset(mountGrepCmd, 0, 4096);
    strcat(mountGrepCmd, "echo `mount | grep ");
    strcat(mountGrepCmd, opt.device);
    strcat(mountGrepCmd, " | sed 's/ on /$/' | tr '$' '\n' | head -n 2 | tail -n 1 | tr '(' '\n' | head -n 1`");
    char mountPoint[4096];
    memset(mountPoint, 0, 4096);
    FILE *mountCmdOutput = popen(mountGrepCmd, "r");
    fgets(mountPoint, 4096, mountCmdOutput);
    mountPoint[strlen(mountPoint)-1] = 0; // removes trailing newline
    printf("mountpoint is %s\n", mountPoint);
    
    mntpath = mountPoint;
    ldlinux_path = alloca(strlen(mntpath) + strlen(subdir) + 1);
    sprintf(ldlinux_path, "%s%s", mntpath, subdir);

    ldlinux_name = alloca(strlen(ldlinux_path) + 14);
    if (!ldlinux_name) {
	perror(program);
	err = 1;
	goto umount;
    }
    sprintf(ldlinux_name, "%sldlinux.sys", ldlinux_path);

    /* update ADV only ? */
    if (opt.update_only == -1) {
	if (opt.reset_adv || opt.set_once) {
	    modify_existing_adv(ldlinux_path);
	    //do_umount(mntpath, mnt_cookie);
	    sync();
	    //rmdir(mntpath);
	    exit(0);
	} else {
	    fprintf(stderr, "%s: please specify --install or --update for the future\n", argv[0]);
	    opt.update_only = 0;
	}
    }

    printf("checkpoint1\n");

    /* Read a pre-existing ADV, if already installed */
    if (opt.reset_adv)
	syslinux_reset_adv(syslinux_adv);
    else if (read_adv(ldlinux_path, "ldlinux.sys") < 0)
	syslinux_reset_adv(syslinux_adv);
    if (modify_adv() < 0)
	exit(1);
	
	printf("checkpoint1.5\n");

    if ((fd = open(ldlinux_name, O_RDONLY)) >= 0) {
	uint32_t zero_attr = 0;
	//ioctl(fd, FAT_IOCTL_SET_ATTRIBUTES, &zero_attr);
	printf("checkpoint1.55bad\n");
	close(fd);
    }
    
    printf("checkpoint1.6\n");

    unlink(ldlinux_name);
    printf(ldlinux_name);
    printf(" ldlinuxname\n");
    fd = open(ldlinux_name, O_WRONLY | O_CREAT | O_TRUNC, 0444);
    if (fd < 0) {
	perror(opt.device);
	err = 1;
	goto umount;
    }
    
    printf("checkpoint2\n");

    /* Write it the first time */
    if (xpwrite(fd, boot_image, boot_image_len, 0) != (int)boot_image_len ||
	xpwrite(fd, syslinux_adv, 2 * ADV_SIZE,
		boot_image_len) != 2 * ADV_SIZE) {
	fprintf(stderr, "%s: write failure on %s\n", program, ldlinux_name);
	exit(1);
    }

    fsync(fd);
    /*
     * Set the attributes
     */
    {
	uint32_t attr = 0x07;	/* Hidden+System+Readonly */
	//ioctl(fd, FAT_IOCTL_SET_ATTRIBUTES, &attr);
    }
    
    printf("checkpoint3\n");

    /*
     * Create a block map.
     */
    
    ldlinux_sectors += 2; /* 2 ADV sectors */
    
    close(fd);
    sync();
    /*
    sectors = calloc(ldlinux_sectors, sizeof *sectors);
    if (sectmap(fd, sectors, ldlinux_sectors)) {
	perror("bmap");
	exit(1);
    }
    close(fd);
    sync();
    printf("checkpoint4\n");
    */
    
    /* Map the file (is there a better way to do this?) */
    //ldlinux_sectors = (syslinux_ldlinux_len + 2 * ADV_SIZE + SECTOR_SIZE - 1) >> SECTOR_SHIFT;
    struct libfat_filesystem *fs;
    libfat_sector_t s;
    libfat_sector_t *secp;
    //libfat_sector_t *sectors;
    uint32_t ldlinux_cluster;
    
    sectors = calloc(ldlinux_sectors, sizeof *sectors);
    //fs = libfat_open(libfat_readfile, (intptr_t) d_handle);
    system(umountCommand);
    dev_fd = open(opt.device, O_RDWR);
    if (dev_fd < 0 || fstat(dev_fd, &st) < 0) {
	perror("couldn't open device");
	exit(1);
    }
    fs = libfat_open(libfat_readfile, dev_fd);
    if (fs == NULL) printf("null fs struct\n");
    ldlinux_cluster = libfat_searchdir(fs, 0, "LDLINUX SYS", NULL);
    
    printf("checkpoint4\n");
    
    secp = sectors;
    int nsectors;
    nsectors  = 0;
    s = libfat_clustertosector(fs, ldlinux_cluster);
    while (s && nsectors < ldlinux_sectors) {
	*secp++ = s;
	nsectors++;
	s = libfat_nextsector(fs, s);
    }
    libfat_close(fs);
    printf("checkpoint5\n");

umount:
    //do_umount(mntpath, mnt_cookie);
    sync();
    //rmdir(mntpath);

    if (err)
	exit(err);
	
	printf("checkpoint6\n");

    /*
     * Patch ldlinux.sys and the boot sector
     */
    i = syslinux_patch(sectors, ldlinux_sectors, opt.stupid_mode,
		       opt.raid_mode, subdir, NULL);
    patch_sectors = (i + SECTOR_SIZE - 1) >> SECTOR_SHIFT;

    /*
     * Write the now-patched first sectors of ldlinux.sys
     */
    for (i = 0; i < patch_sectors; i++) {
	xpwrite(dev_fd, boot_image + i * SECTOR_SIZE, SECTOR_SIZE,
		opt.offset + ((off_t) sectors[i] << SECTOR_SHIFT));
    }
    
    printf("checkpoint7\n");

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

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

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

    /* Write new boot sector */
    xpwrite(dev_fd, sectbuf, SECTOR_SIZE, opt.offset);
    
    printf("checkpoint8\n");

    close(dev_fd);
    sync();
    system(mountCmd);

    /* Done! */

    return 0;
}
Example #20
0
/*
 * 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;
}
Example #21
0
File: farm.c Project: yamt/sheepdog
static int farm_read(uint64_t oid, struct siocb *iocb)
{
	int flags = def_open_flags, fd, ret = SD_RES_SUCCESS;
	uint32_t epoch = sys_epoch();
	char path[PATH_MAX];
	ssize_t size;
	int i;
	void *buffer;

	if (iocb->epoch < epoch) {

		buffer = read_working_object(oid, iocb->offset, iocb->length);
		if (!buffer) {
			/* Here if read the object from the targeted epoch failed,
			 * we need to read from the later epoch, because at some epoch
			 * we doesn't write the object to the snapshot, we assume
			 * it in the current local object directory, but maybe
			 * in the next epoch we removed it from the local directory.
			 * in this case, we should try to retrieve object upwards, since.
			 * when the object is to be removed, it will get written to the
			 * snapshot at later epoch.
			 */
			for (i = iocb->epoch; i < epoch; i++) {
				buffer = retrieve_object_from_snap(oid, i);
				if (buffer)
					break;
			}
		}
		if (!buffer)
			return SD_RES_NO_OBJ;
		memcpy(iocb->buf, buffer, iocb->length);
		free(buffer);

		return SD_RES_SUCCESS;
	}

	if (!is_data_obj(oid))
		flags &= ~O_DIRECT;

	sprintf(path, "%s%016"PRIx64, obj_path, oid);
	fd = open(path, flags);

	if (fd < 0)
		return err_to_sderr(oid, errno);

	if (flock(fd, LOCK_SH) < 0) {
		ret = SD_RES_EIO;
		eprintf("%m\n");
		goto out;
	}
	size = xpread(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) {
		ret = SD_RES_EIO;
		goto out;
	}
out:
	close(fd);
	return ret;
}
Example #22
0
int init_config_file(void)
{
	int fd, ret = 0;

	check_tmp_config();

	fd = open(config_path, O_RDONLY);
	if (fd < 0) {
		if (errno != ENOENT) {
			sd_err("failed to read config file, %m");
			return -1;
		}
		goto create;
	}

	ret = xread(fd, &config, sizeof(config));
	if (ret == 0) {
		close(fd);
		goto create;
	}
	if (ret < 0) {
		sd_err("failed to read config file, %m");
		goto out;
	}

	if (config.version != SD_FORMAT_VERSION) {
		sd_err("This sheep version is not compatible with"
		       " the existing data layout, %d", config.version);
		if (sys->upgrade) {
			/* upgrade sheep store */
			ret = sd_migrate_store(config.version, SD_FORMAT_VERSION);
			if (ret == 0) {
				/* reload config file */
				ret = xpread(fd, &config, sizeof(config), 0);
				if (ret != sizeof(config)) {
					sd_err("failed to reload config file,"
					       " %m");
					ret = -1;
				} else {
					ret = 0;
					goto reload;
				}
			}
			goto out;
		}

		sd_err("use '-u' option to upgrade sheep store");
		ret = -1;
		goto out;
	}

reload:
	if ((config.flags & SD_CLUSTER_FLAG_AUTO_VNODES) !=
			(sys->cinfo.flags & SD_CLUSTER_FLAG_AUTO_VNODES)
		&& !sys->gateway_only
		&& config.ctime > 0) {
		sd_err("Designation of before a restart and a vnodes option is different.");
		return -1;
	}

	ret = 0;
	get_cluster_config(&sys->cinfo);
	if ((config.flags & SD_CLUSTER_FLAG_DISKMODE) !=
	    (sys->cinfo.flags & SD_CLUSTER_FLAG_DISKMODE)) {
		sd_err("This sheep can't run because "
		       "exists data format mismatch");
		return -1;
	}

create:
	config.version = SD_FORMAT_VERSION;
	if (write_config() != SD_RES_SUCCESS)
		return -1;

out:
	close(fd);

	return ret;
}
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;
}
Example #24
0
static void *copy_thread_hashmap(void *_me)
{
	struct worker_thread *me = _me;

	while (1) {
		uint8_t buf[block_size];
		uint8_t hash[hash_size];
		off_t off;
		int ret;

		xsem_wait(&me->sem0);

		for (off = fd_off; off < sizeblocks; off++) {
			if (memcmp(srchashmap + off * hash_size,
				   dsthashmap + off * hash_size, hash_size)) {
				break;
			}
		}

		if (off == sizeblocks || check_signal()) {
			fd_off = sizeblocks;
			xsem_post(&me->next->sem0);
			break;
		}

		if (should_report_progress()) {
			char str[256];
			int ret;

			ret = sprintf(str, "%Ld/%Ld (%Ld/%Ld mismatches)",
				      (long long)off,
				      (long long)sizeblocks,
				      (long long)mismatch_idx,
				      (long long)mismatch_cnt);
			memset(str + ret, '\b', ret);
			str[2 * ret] = 0;

			fputs(str, stderr);
		}

		ret = xpread(fd_src, buf, block_size, off * block_size);

		fd_off = off + 1;
		mismatch_idx++;

		xsem_post(&me->next->sem0);

		if (ret < block_size && off != sizeblocks - 1) {
			fprintf(stderr, "short read\n");
			break;
		}

		gcry_md_hash_buffer(hash_algo, hash, buf, ret);

		if (memcmp(hash, srchashmap + off * hash_size, hash_size)) {
			fprintf(stderr, "warning: source image inconsistent "
					"with its hashmap at block %Ld\n",
				(long long)off);
		}

		xsem_wait(&me->sem1);

		xpwrite(fd_dst, buf, ret, off * block_size);

		memcpy(dsthashmap + off * hash_size, hash, hash_size);
		xpwrite(fd_dsthashmap, hash, hash_size, off * hash_size);

		xsem_post(&me->next->sem1);
	}

	return NULL;
}
Example #25
0
/*
 * Version of the read function suitable for libfat
 */
int libfat_xpread(intptr_t pp, void *buf, size_t secsize, libfat_sector_t sector)
{
  off_t offset = (off_t)sector * secsize + filesystem_offset;
  return xpread(pp, buf, secsize, offset);
}
Example #26
0
int init_config_path(const char *base_path)
{
	int fd, ret;

	config_path = zalloc(strlen(base_path) + strlen(CONFIG_PATH) + 1);
	sprintf(config_path, "%s" CONFIG_PATH, base_path);

	fd = open(config_path, O_RDONLY);
	if (fd < 0) {
		if (errno != ENOENT) {
			eprintf("failed to read config file, %m\n");
			return -1;
		}
		goto create;
	}

	ret = xread(fd, &config, sizeof(config));
	if (ret == 0) {
		close(fd);
		goto create;
	}
	if (ret < 0) {
		eprintf("failed to read config file, %m\n");
		goto out;
	}

	if (config.version != SD_FORMAT_VERSION) {
		eprintf("This sheep version is not compatible with the existing "
			"data layout, %d\n", config.version);
		if (sys->upgrade) {
			/* upgrade sheep store */
			ret = sd_migrate_store(config.version, SD_FORMAT_VERSION);
			if (ret == 0) {
				/* reload config file */
				ret = xpread(fd, &config, sizeof(config), 0);
				if (ret != sizeof(config)) {
					eprintf("failed to reload config file,"
						" %m\n");
					ret = -1;
				} else
					ret = 0;
			}
			goto out;
		}

		eprintf("use '-u' option to upgrade sheep store\n");
		ret = -1;
		goto out;
	}
	ret = 0;
out:
	close(fd);

	return ret;
create:
	config.version = SD_FORMAT_VERSION;
	if (write_config() != SD_RES_SUCCESS)
		return -1;

	return 0;
}
Example #27
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;
}
Example #28
0
static void *copy_thread_no_hashmap(void *_me)
{
	struct worker_thread *me = _me;

	while (1) {
		uint8_t buf[block_size];
		uint8_t hash[hash_size];
		off_t off;
		int ret;

		xsem_wait(&me->sem0);

		off = fd_off;
		if (off == sizeblocks) {
			xsem_post(&me->next->sem0);
			break;
		}

		if (check_signal()) {
			fd_off = sizeblocks;
			xsem_post(&me->next->sem0);
			break;
		}

		fd_off++;

		posix_fadvise(fd_src, off * block_size, 4 * block_size,
				POSIX_FADV_WILLNEED);

		ret = xpread(fd_src, buf, block_size, off * block_size);

		xsem_post(&me->next->sem0);

		if (ret < block_size && off != sizeblocks - 1) {
			fprintf(stderr, "short read\n");
			break;
		}

		gcry_md_hash_buffer(hash_algo, hash, buf, ret);

		xsem_wait(&me->sem1);

		if (memcmp(dsthashmap + off * hash_size, hash, hash_size)) {
			xpwrite(fd_dst, buf, ret, off * block_size);
			xpwrite(fd_dsthashmap, hash,
				hash_size, off * hash_size);
			memcpy(dsthashmap + off * hash_size, hash, hash_size);

			fprintf(stderr, "%Ld ", (long long)off);
			progress_reported();

			again = 1;
		} else if (should_report_progress()) {
			char str[256];

			ret = sprintf(str, "%Ld/%Ld", (long long)off,
				      (long long)sizeblocks);
			memset(str + ret, '\b', ret);
			str[2 * ret] = 0;

			fputs(str, stderr);
		}

		xsem_post(&me->next->sem1);
	}

	return NULL;
}