//ret copied length if successful, -1 if failed static int r_buf_cpy(RBuffer *b, ut64 addr, ut8 *dst, const ut8 *src, int len, int write) { int end; if (!b || b->empty) return 0; if (b->sparse) { if (write) { // create new with src + len if (sparse_write (b->sparse, addr, src, len) <0) return -1; } else { // read from sparse and write into dst memset (dst, 0xff, len); if (sparse_read (b->sparse, addr, dst, len) <0) return -1; } return len; } addr = (addr==R_BUF_CUR)? b->cur: addr-b->base; if (len<1 || dst == NULL || addr > b->length) return -1; end = (int)(addr+len); if (end > b->length) len -= end-b->length; if (write) dst += addr; else src += addr; memmove (dst, src, len); b->cur = addr + len; return len; }
//ret 0 or -1 if failed; ret copied length if success R_API int r_buf_write_at(RBuffer *b, ut64 addr, const ut8 *buf, int len) { if (!b || !buf || len < 1) { return 0; } if (b->fd != -1) { ut64 newlen = addr + len; if (r_sandbox_lseek (b->fd, addr, SEEK_SET) == -1) { return 0; } if (newlen > b->length) { b->length = newlen; #ifdef _MSC_VER _chsize (b->fd, newlen); #else ftruncate (b->fd, newlen); #endif } return r_sandbox_write (b->fd, buf, len); } if (b->sparse) { return (sparse_write (b->sparse, addr, buf, len) < 0) ? -1 : len; } if (b->empty) { b->empty = 0; free (b->buf); b->buf = (ut8 *) malloc (addr + len); } return r_buf_cpy (b, addr, b->buf, buf, len, true); }
// ret copied length if successful, -1 if failed static int r_buf_cpy(RBuffer *b, ut64 addr, ut8 *dst, const ut8 *src, int len, int write) { int end; if (!b || b->empty) { return 0; } if (b->fd != -1) { if (r_sandbox_lseek (b->fd, addr, SEEK_SET) == -1) { // seek failed - print error here? // return 0; } if (write) { return r_sandbox_write (b->fd, src, len); } memset (dst, 0, len); return r_sandbox_read (b->fd, dst, len); } if (b->sparse) { if (write) { // create new with src + len if (sparse_write (b->sparse, addr, src, len) < 0) { return -1; } } else { // read from sparse and write into dst memset (dst, 0xff, len); if (sparse_read (b->sparse, addr, dst, len) < 0) { return -1; } } return len; } addr = (addr == R_BUF_CUR) ? b->cur : addr - b->base; if (len < 1 || !dst || addr > b->length) { return -1; } end = (int)(addr + len); if (end > b->length) { len -= end-b->length; } if (write) { dst += addr; } else { src += addr; } memmove (dst, src, len); b->cur = addr + len; return len; }
static int vhd_fix_write(int fd) { struct vhd_footer footer; uint64_t imgsz; int error; error = image_copyout(fd); if (!error) { imgsz = image_get_size() * secsz; vhd_make_footer(&footer, imgsz, VHD_DISK_TYPE_FIXED, ~0ULL); if (sparse_write(fd, &footer, sizeof(footer)) < 0) error = errno; } return (error); }
static int raw_import_write(const void *p, size_t sz, void *userdata) { RawImport *i = userdata; ssize_t n; if (i->grow_machine_directory && i->written_since_last_grow >= GROW_INTERVAL_BYTES) { i->written_since_last_grow = 0; grow_machine_directory(); } n = sparse_write(i->output_fd, p, sz, 64); if (n < 0) return (int) n; if ((size_t) n < sz) return -EIO; i->written_uncompressed += sz; i->written_since_last_grow += sz; return 0; }
R_API bool r_buf_resize (RBuffer *b, ut64 newsize) { if (b->mmap) { return false; } if ((!b->sparse && !b->buf) || newsize < 1) { return false; } if (b->sparse) { ut64 last_addr = 0; sparse_limits (b->sparse, 0, &last_addr); int buf_len = newsize - last_addr; if (buf_len > 0) { ut8 *buf = malloc (buf_len); if (buf) { memset (buf, 0xff, buf_len); sparse_write (b->sparse, last_addr, buf, buf_len); free (buf); return true; } } eprintf ("Invalid resize for an sparse RBuffer\n"); return false; } ut8 *buf = calloc (newsize, 1); if (buf) { ut32 len = R_MIN (newsize, b->length); memcpy (buf, b->buf, len); memset (buf + len, 0xff, newsize - len); /* commit */ free (b->buf); b->buf = buf; b->length = newsize; return true; } return false; }
static int vhd_dyn_write(int fd) { struct vhd_footer footer; struct vhd_dyn_header header; uint64_t imgsz; lba_t blk, blkcnt, nblks; uint32_t *bat; void *bitmap; size_t batsz; uint32_t sector; int bat_entries, error, entry; imgsz = image_get_size() * secsz; bat_entries = imgsz / VHD_BLOCK_SIZE; vhd_make_footer(&footer, imgsz, VHD_DISK_TYPE_DYNAMIC, sizeof(footer)); if (sparse_write(fd, &footer, sizeof(footer)) < 0) return (errno); memset(&header, 0, sizeof(header)); be64enc(&header.cookie, VHD_HEADER_COOKIE); be64enc(&header.data_offset, ~0ULL); be64enc(&header.table_offset, sizeof(footer) + sizeof(header)); be32enc(&header.version, VHD_VERSION); be32enc(&header.max_entries, bat_entries); be32enc(&header.block_size, VHD_BLOCK_SIZE); be32enc(&header.checksum, vhd_checksum(&header, sizeof(header))); if (sparse_write(fd, &header, sizeof(header)) < 0) return (errno); batsz = bat_entries * sizeof(uint32_t); batsz = (batsz + VHD_SECTOR_SIZE - 1) & ~(VHD_SECTOR_SIZE - 1); bat = malloc(batsz); if (bat == NULL) return (errno); memset(bat, 0xff, batsz); blkcnt = VHD_BLOCK_SIZE / secsz; sector = (sizeof(footer) + sizeof(header) + batsz) / VHD_SECTOR_SIZE; for (entry = 0; entry < bat_entries; entry++) { blk = entry * blkcnt; if (image_data(blk, blkcnt)) { be32enc(&bat[entry], sector); sector += (VHD_BLOCK_SIZE / VHD_SECTOR_SIZE) + 1; } } if (sparse_write(fd, bat, batsz) < 0) { free(bat); return (errno); } free(bat); bitmap = malloc(VHD_SECTOR_SIZE); if (bitmap == NULL) return (errno); memset(bitmap, 0xff, VHD_SECTOR_SIZE); blk = 0; blkcnt = VHD_BLOCK_SIZE / secsz; error = 0; nblks = image_get_size(); while (blk < nblks) { if (!image_data(blk, blkcnt)) { blk += blkcnt; continue; } if (sparse_write(fd, bitmap, VHD_SECTOR_SIZE) < 0) { error = errno; break; } error = image_copyout_region(fd, blk, blkcnt); if (error) break; blk += blkcnt; } free(bitmap); if (blk != nblks) return (error); if (sparse_write(fd, &footer, sizeof(footer)) < 0) return (errno); return (0); }
static int vmdk_write(int fd) { struct vmdk_header hdr; uint32_t *gt, *gd, *rgd; char *buf, *desc; off_t cur, lim; uint64_t imagesz; lba_t blkofs, blkcnt; size_t gdsz, gtsz; uint32_t sec, cursec; int error, desc_len, n, ngrains, ngts; imagesz = (image_get_size() * secsz) / VMDK_SECTOR_SIZE; memset(&hdr, 0, sizeof(hdr)); le32enc(&hdr.magic, VMDK_MAGIC); le32enc(&hdr.version, VMDK_VERSION); le32enc(&hdr.flags, VMDK_FLAGS_NL_TEST | VMDK_FLAGS_RGT_USED); le64enc(&hdr.capacity, imagesz); le64enc(&hdr.grain_size, grainsz); n = asprintf(&desc, desc_fmt, 1 /*version*/, 0 /*CID*/, (uintmax_t)imagesz /*size*/, "" /*name*/, ncyls /*cylinders*/, nheads /*heads*/, nsecs /*sectors*/); if (n == -1) return (ENOMEM); desc_len = (n + VMDK_SECTOR_SIZE - 1) & ~(VMDK_SECTOR_SIZE - 1); desc = realloc(desc, desc_len); memset(desc + n, 0, desc_len - n); le64enc(&hdr.desc_offset, 1); le64enc(&hdr.desc_size, desc_len / VMDK_SECTOR_SIZE); le32enc(&hdr.ngtes, VMDK_NGTES); sec = desc_len / VMDK_SECTOR_SIZE + 1; ngrains = imagesz / grainsz; ngts = (ngrains + VMDK_NGTES - 1) / VMDK_NGTES; gdsz = (ngts * sizeof(uint32_t) + VMDK_SECTOR_SIZE - 1) & ~(VMDK_SECTOR_SIZE - 1); gd = calloc(1, gdsz); if (gd == NULL) { free(desc); return (ENOMEM); } le64enc(&hdr.gd_offset, sec); sec += gdsz / VMDK_SECTOR_SIZE; for (n = 0; n < ngts; n++) { le32enc(gd + n, sec); sec += VMDK_NGTES * sizeof(uint32_t) / VMDK_SECTOR_SIZE; } rgd = calloc(1, gdsz); if (rgd == NULL) { free(gd); free(desc); return (ENOMEM); } le64enc(&hdr.rgd_offset, sec); sec += gdsz / VMDK_SECTOR_SIZE; for (n = 0; n < ngts; n++) { le32enc(rgd + n, sec); sec += VMDK_NGTES * sizeof(uint32_t) / VMDK_SECTOR_SIZE; } sec = (sec + grainsz - 1) & ~(grainsz - 1); if (verbose) fprintf(stderr, "VMDK: overhead = %ju\n", (uintmax_t)(sec * VMDK_SECTOR_SIZE)); le64enc(&hdr.overhead, sec); be32enc(&hdr.nl_test, VMDK_NL_TEST); gt = calloc(ngts, VMDK_NGTES * sizeof(uint32_t)); if (gt == NULL) { free(rgd); free(gd); free(desc); return (ENOMEM); } gtsz = ngts * VMDK_NGTES * sizeof(uint32_t); cursec = sec; blkcnt = (grainsz * VMDK_SECTOR_SIZE) / secsz; for (n = 0; n < ngrains; n++) { blkofs = n * blkcnt; if (image_data(blkofs, blkcnt)) { le32enc(gt + n, cursec); cursec += grainsz; } } error = 0; if (!error && sparse_write(fd, &hdr, VMDK_SECTOR_SIZE) < 0) error = errno; if (!error && sparse_write(fd, desc, desc_len) < 0) error = errno; if (!error && sparse_write(fd, gd, gdsz) < 0) error = errno; if (!error && sparse_write(fd, gt, gtsz) < 0) error = errno; if (!error && sparse_write(fd, rgd, gdsz) < 0) error = errno; if (!error && sparse_write(fd, gt, gtsz) < 0) error = errno; free(gt); free(rgd); free(gd); free(desc); if (error) return (error); cur = VMDK_SECTOR_SIZE + desc_len + (gdsz + gtsz) * 2; lim = sec * VMDK_SECTOR_SIZE; if (cur < lim) { buf = calloc(1, VMDK_SECTOR_SIZE); if (buf == NULL) error = ENOMEM; while (!error && cur < lim) { if (sparse_write(fd, buf, VMDK_SECTOR_SIZE) < 0) error = errno; cur += VMDK_SECTOR_SIZE; } if (buf != NULL) free(buf); } if (error) return (error); blkcnt = (grainsz * VMDK_SECTOR_SIZE) / secsz; for (n = 0; n < ngrains; n++) { blkofs = n * blkcnt; if (image_data(blkofs, blkcnt)) { error = image_copyout_region(fd, blkofs, blkcnt); if (error) return (error); } } return (image_copyout_done(fd)); }