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; }
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; }
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; }
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; }
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; }
/* * 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; }
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; }
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; }
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; }
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; }
/* * 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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
/* * 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; }
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; }
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; }
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; }
/* * 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); }
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; }
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; }
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; }