130 lines
2.8 KiB
C
130 lines
2.8 KiB
C
// SPDX-FileCopyrightText: 2015-2016 pancake <pancake@nopcode.org>
|
|
// SPDX-License-Identifier: LGPL-3.0-only
|
|
|
|
#include "rz_io.h"
|
|
#include "rz_lib.h"
|
|
#include "rz_util.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <sys/types.h>
|
|
|
|
typedef struct {
|
|
int fd;
|
|
RzBuffer *buf;
|
|
ut64 offset;
|
|
} RzIOSparse;
|
|
|
|
#define RzIOSPARSE_FD(x) (((RzIOSparse *)(x)->data)->fd)
|
|
#define RzIOSPARSE_BUF(x) (((RzIOSparse *)(x)->data)->buf)
|
|
#define RzIOSPARSE_OFF(x) (((RzIOSparse *)(x)->data)->offset)
|
|
|
|
static int __write(RzIO *io, RzIODesc *fd, const ut8 *buf, int count) {
|
|
ut64 o;
|
|
RzBuffer *b;
|
|
if (!fd || !fd->data) {
|
|
return -1;
|
|
}
|
|
b = RzIOSPARSE_BUF(fd);
|
|
o = RzIOSPARSE_OFF(fd);
|
|
int r = rz_buf_write_at(b, o, buf, count);
|
|
if (r >= 0) {
|
|
rz_buf_seek(b, r, RZ_BUF_CUR);
|
|
}
|
|
return r;
|
|
}
|
|
|
|
static int __read(RzIO *io, RzIODesc *fd, ut8 *buf, int count) {
|
|
ut64 o;
|
|
RzBuffer *b;
|
|
if (!fd || !fd->data) {
|
|
return -1;
|
|
}
|
|
b = RzIOSPARSE_BUF(fd);
|
|
o = RzIOSPARSE_OFF(fd);
|
|
int r = rz_buf_read_at(b, o, buf, count);
|
|
if (r >= 0) {
|
|
rz_buf_seek(b, count, RZ_BUF_CUR);
|
|
}
|
|
return count;
|
|
}
|
|
|
|
static int __close(RzIODesc *fd) {
|
|
RzIOSparse *riom;
|
|
if (!fd || !fd->data) {
|
|
return -1;
|
|
}
|
|
riom = fd->data;
|
|
RZ_FREE(riom->buf);
|
|
RZ_FREE(fd->data);
|
|
return 0;
|
|
}
|
|
|
|
static ut64 __lseek(RzIO *io, RzIODesc *fd, ut64 offset, int whence) {
|
|
RzBuffer *b;
|
|
ut64 rz_offset = offset;
|
|
if (!fd->data) {
|
|
return offset;
|
|
}
|
|
b = RzIOSPARSE_BUF(fd);
|
|
rz_offset = rz_buf_seek(b, offset, whence);
|
|
// if (rz_offset != UT64_MAX)
|
|
RzIOSPARSE_OFF(fd) = rz_offset;
|
|
return rz_offset;
|
|
}
|
|
|
|
static bool __plugin_open(struct rz_io_t *io, const char *pathname, bool many) {
|
|
return (!strncmp(pathname, "sparse://", 9));
|
|
}
|
|
|
|
static RzIODesc *__open(RzIO *io, const char *pathname, int rw, int mode) {
|
|
if (__plugin_open(io, pathname, 0)) {
|
|
RzIOSparse *mal = RZ_NEW0(RzIOSparse);
|
|
int size = (int)rz_num_math(NULL, pathname + 9);
|
|
mal->buf = rz_buf_new_sparse(io->Oxff);
|
|
if (!mal->buf) {
|
|
free(mal);
|
|
return NULL;
|
|
}
|
|
if (size > 0) {
|
|
ut8 *data = malloc(size);
|
|
if (!data) {
|
|
eprintf("Cannot allocate (%s) %d byte(s)\n",
|
|
pathname + 9, size);
|
|
mal->offset = 0;
|
|
} else {
|
|
memset(data, 0x00, size);
|
|
rz_buf_write_at(mal->buf, 0, data, size);
|
|
free(data);
|
|
}
|
|
}
|
|
if (mal->buf) {
|
|
return rz_io_desc_new(io, &rz_io_plugin_sparse,
|
|
pathname, rw, mode, mal);
|
|
}
|
|
rz_buf_free(mal->buf);
|
|
free(mal);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
RzIOPlugin rz_io_plugin_sparse = {
|
|
.name = "sparse",
|
|
.desc = "Sparse buffer allocation plugin",
|
|
.uris = "sparse://",
|
|
.license = "LGPL3",
|
|
.open = __open,
|
|
.close = __close,
|
|
.read = __read,
|
|
.check = __plugin_open,
|
|
.lseek = __lseek,
|
|
.write = __write,
|
|
.resize = NULL,
|
|
};
|
|
|
|
#ifndef RZ_PLUGIN_INCORE
|
|
RZ_API RzLibStruct rizin_plugin = {
|
|
.type = RZ_LIB_TYPE_IO,
|
|
.data = &rz_io_plugin_sparse,
|
|
.version = RZ_VERSION
|
|
};
|
|
#endif
|