Allow specifying the offset and size for reading data from files
Also require size to be specified for SHM objects to support platforms such as macOS that have no way to get the size from the fd.
This commit is contained in:
parent
898136dbdc
commit
dbd7ec5b27
5 changed files with 20 additions and 17 deletions
|
|
@ -134,13 +134,16 @@ set_add_response(const char *code, const char *fmt, ...) {
|
|||
#define ABRT(code, ...) { set_add_response(#code, __VA_ARGS__); goto err; }
|
||||
|
||||
static inline bool
|
||||
mmap_img_file(GraphicsManager UNUSED *self, Image *img) {
|
||||
struct stat s;
|
||||
if (fstat(img->load_data.fd, &s) != 0) ABRT(EBADF, "Failed to fstat() SHM file with error: [%d] %s", errno, strerror(errno));
|
||||
void *addr = mmap(0, s.st_size, PROT_READ, MAP_PRIVATE, img->load_data.fd, 0);
|
||||
mmap_img_file(GraphicsManager UNUSED *self, Image *img, size_t sz, off_t offset) {
|
||||
if (!sz) {
|
||||
struct stat s;
|
||||
if (fstat(img->load_data.fd, &s) != 0) ABRT(EBADF, "Failed to fstat() file with error: [%d] %s", errno, strerror(errno));
|
||||
sz = s.st_size;
|
||||
}
|
||||
void *addr = mmap(0, sz, PROT_READ, MAP_PRIVATE, img->load_data.fd, offset);
|
||||
if (addr == MAP_FAILED) ABRT(EBADF, "Failed to map image file with error: [%d] %s", errno, strerror(errno));
|
||||
img->load_data.mapped_file = addr;
|
||||
img->load_data.mapped_file_sz = s.st_size;
|
||||
img->load_data.mapped_file_sz = sz;
|
||||
return true;
|
||||
err:
|
||||
return false;
|
||||
|
|
@ -332,11 +335,10 @@ handle_add_command(GraphicsManager *self, const GraphicsCommand *g, const uint8_
|
|||
snprintf(fname, sizeof(fname)/sizeof(fname[0]), "%.*s", (int)g->payload_sz, payload);
|
||||
if (tt == 's') fd = shm_open(fname, O_RDONLY, 0);
|
||||
else fd = open(fname, O_CLOEXEC | O_RDONLY);
|
||||
if (fd == -1) {
|
||||
ABRT(EBADF, "Failed to open file %s for graphics transmission with error: [%d] %s", fname, errno, strerror(errno));
|
||||
}
|
||||
if (fd == -1) ABRT(EBADF, "Failed to open file %s for graphics transmission with error: [%d] %s", fname, errno, strerror(errno));
|
||||
img->load_data.fd = fd;
|
||||
img->data_loaded = mmap_img_file(self, img);
|
||||
if (tt == 's' && !g->data_sz) ABRT(EINVAL, "data size required for shared memory object");
|
||||
img->data_loaded = mmap_img_file(self, img, g->data_sz, g->data_offset);
|
||||
if (tt == 't') unlink(fname);
|
||||
else if (tt == 's') shm_unlink(fname);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
typedef struct {
|
||||
unsigned char action, transmission_type, compressed;
|
||||
uint32_t format, more, id, data_sz;
|
||||
uint32_t format, more, id, data_sz, data_offset;
|
||||
uint32_t width, height, x_offset, y_offset, data_height, data_width, num_cells, num_lines;
|
||||
int32_t z_index;
|
||||
size_t payload_sz;
|
||||
|
|
|
|||
|
|
@ -552,6 +552,7 @@ parse_graphics_code(Screen *screen, PyObject UNUSED *dump_callback) {
|
|||
data_height = 'v',
|
||||
data_width = 's',
|
||||
data_sz = 'S',
|
||||
data_offset = 'O',
|
||||
num_cells = 'c',
|
||||
num_lines = 'r',
|
||||
z_index = 'z'
|
||||
|
|
@ -575,7 +576,7 @@ parse_graphics_code(Screen *screen, PyObject UNUSED *dump_callback) {
|
|||
#define KS(n, vs) case n: state = EQUAL; value_state = vs; break
|
||||
#define U(x) KS(x, UINT)
|
||||
KS(action, FLAG); KS(transmission_type, FLAG); KS(compressed, FLAG); KS(z_index, INT);
|
||||
U(format); U(more); U(id); U(data_sz); U(width); U(height); U(x_offset); U(y_offset); U(data_height); U(data_width); U(num_cells); U(num_lines);
|
||||
U(format); U(more); U(id); U(data_sz); U(data_offset); U(width); U(height); U(x_offset); U(y_offset); U(data_height); U(data_width); U(num_cells); U(num_lines);
|
||||
#undef U
|
||||
#undef KS
|
||||
default:
|
||||
|
|
@ -628,7 +629,7 @@ parse_graphics_code(Screen *screen, PyObject UNUSED *dump_callback) {
|
|||
READ_UINT;
|
||||
#define U(x) case x: g.x = code; break
|
||||
switch(key) {
|
||||
U(format); U(more); U(id); U(data_sz); U(width); U(height); U(x_offset); U(y_offset); U(data_height); U(data_width); U(num_cells); U(num_lines);
|
||||
U(format); U(more); U(id); U(data_sz); U(data_offset); U(width); U(height); U(x_offset); U(y_offset); U(data_height); U(data_width); U(num_cells); U(num_lines);
|
||||
default: break;
|
||||
}
|
||||
state = AFTER_VALUE;
|
||||
|
|
@ -672,9 +673,9 @@ parse_graphics_code(Screen *screen, PyObject UNUSED *dump_callback) {
|
|||
#define A(x) #x, g.x
|
||||
#define U(x) #x, (unsigned int)(g.x)
|
||||
#define I(x) #x, (int)(g.x)
|
||||
REPORT_VA_COMMAND("s {sc sc sc sI sI sI sI sI sI sI sI sI sI sI sI sI si} y#", "graphics_command",
|
||||
REPORT_VA_COMMAND("s {sc sc sc sI sI sI sI sI sI sI sI sI sI sI sI sI sI si} y#", "graphics_command",
|
||||
A(action), A(transmission_type), A(compressed),
|
||||
U(format), U(more), U(id), U(data_sz),
|
||||
U(format), U(more), U(id), U(data_sz), U(data_offset),
|
||||
U(width), U(height), U(x_offset), U(y_offset), U(data_height), U(data_width), U(num_cells), U(num_lines),
|
||||
U(payload_sz), I(z_index),
|
||||
payload, g.payload_sz
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ def l(payload, **kw):
|
|||
res = send_command(s, cmd, payload)
|
||||
if not res:
|
||||
return
|
||||
return res.decode('ascii').partition(';')[2].partition(':')[0].partition('\033')[0]
|
||||
return res.decode('ascii').partition(';')[2].partition('\033')[0]
|
||||
|
||||
def sl(payload, **kw):
|
||||
if isinstance(payload, str):
|
||||
|
|
@ -90,5 +90,5 @@ def sl(payload, **kw):
|
|||
# Test loading from POSIX SHM
|
||||
name = '/kitty-test-shm'
|
||||
g.shm_write(name, random_data)
|
||||
sl(name, s=24, v=32, t='s', expecting_data=random_data)
|
||||
sl(name, s=24, v=32, t='s', S=len(random_data), expecting_data=random_data)
|
||||
self.assertRaises(FileNotFoundError, g.shm_unlink, name) # check that file was deleted
|
||||
|
|
|
|||
|
|
@ -204,7 +204,7 @@ def c(**k):
|
|||
k[p] = v.encode('ascii')
|
||||
for f in 'action transmission_type compressed'.split():
|
||||
k.setdefault(f, b'\0')
|
||||
for f in 'format more id data_sz width height x_offset y_offset data_height data_width num_cells num_lines z_index'.split():
|
||||
for f in 'format more id data_sz data_offset width height x_offset y_offset data_height data_width num_cells num_lines z_index'.split():
|
||||
k.setdefault(f, 0)
|
||||
p = k.pop('payload', '').encode('utf-8')
|
||||
k['payload_sz'] = len(p)
|
||||
|
|
|
|||
Loading…
Reference in a new issue