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:
@@ -134,13 +134,16 @@ set_add_response(const char *code, const char *fmt, ...) {
|
|||||||
#define ABRT(code, ...) { set_add_response(#code, __VA_ARGS__); goto err; }
|
#define ABRT(code, ...) { set_add_response(#code, __VA_ARGS__); goto err; }
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
mmap_img_file(GraphicsManager UNUSED *self, Image *img) {
|
mmap_img_file(GraphicsManager UNUSED *self, Image *img, size_t sz, off_t offset) {
|
||||||
struct stat s;
|
if (!sz) {
|
||||||
if (fstat(img->load_data.fd, &s) != 0) ABRT(EBADF, "Failed to fstat() SHM file with error: [%d] %s", errno, strerror(errno));
|
struct stat s;
|
||||||
void *addr = mmap(0, s.st_size, PROT_READ, MAP_PRIVATE, img->load_data.fd, 0);
|
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));
|
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 = addr;
|
||||||
img->load_data.mapped_file_sz = s.st_size;
|
img->load_data.mapped_file_sz = sz;
|
||||||
return true;
|
return true;
|
||||||
err:
|
err:
|
||||||
return false;
|
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);
|
snprintf(fname, sizeof(fname)/sizeof(fname[0]), "%.*s", (int)g->payload_sz, payload);
|
||||||
if (tt == 's') fd = shm_open(fname, O_RDONLY, 0);
|
if (tt == 's') fd = shm_open(fname, O_RDONLY, 0);
|
||||||
else fd = open(fname, O_CLOEXEC | O_RDONLY);
|
else fd = open(fname, O_CLOEXEC | O_RDONLY);
|
||||||
if (fd == -1) {
|
if (fd == -1) ABRT(EBADF, "Failed to open file %s for graphics transmission with error: [%d] %s", fname, errno, strerror(errno));
|
||||||
ABRT(EBADF, "Failed to open file %s for graphics transmission with error: [%d] %s", fname, errno, strerror(errno));
|
|
||||||
}
|
|
||||||
img->load_data.fd = fd;
|
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);
|
if (tt == 't') unlink(fname);
|
||||||
else if (tt == 's') shm_unlink(fname);
|
else if (tt == 's') shm_unlink(fname);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned char action, transmission_type, compressed;
|
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;
|
uint32_t width, height, x_offset, y_offset, data_height, data_width, num_cells, num_lines;
|
||||||
int32_t z_index;
|
int32_t z_index;
|
||||||
size_t payload_sz;
|
size_t payload_sz;
|
||||||
|
|||||||
@@ -552,6 +552,7 @@ parse_graphics_code(Screen *screen, PyObject UNUSED *dump_callback) {
|
|||||||
data_height = 'v',
|
data_height = 'v',
|
||||||
data_width = 's',
|
data_width = 's',
|
||||||
data_sz = 'S',
|
data_sz = 'S',
|
||||||
|
data_offset = 'O',
|
||||||
num_cells = 'c',
|
num_cells = 'c',
|
||||||
num_lines = 'r',
|
num_lines = 'r',
|
||||||
z_index = 'z'
|
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 KS(n, vs) case n: state = EQUAL; value_state = vs; break
|
||||||
#define U(x) KS(x, UINT)
|
#define U(x) KS(x, UINT)
|
||||||
KS(action, FLAG); KS(transmission_type, FLAG); KS(compressed, FLAG); KS(z_index, INT);
|
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 U
|
||||||
#undef KS
|
#undef KS
|
||||||
default:
|
default:
|
||||||
@@ -628,7 +629,7 @@ parse_graphics_code(Screen *screen, PyObject UNUSED *dump_callback) {
|
|||||||
READ_UINT;
|
READ_UINT;
|
||||||
#define U(x) case x: g.x = code; break
|
#define U(x) case x: g.x = code; break
|
||||||
switch(key) {
|
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;
|
default: break;
|
||||||
}
|
}
|
||||||
state = AFTER_VALUE;
|
state = AFTER_VALUE;
|
||||||
@@ -672,9 +673,9 @@ parse_graphics_code(Screen *screen, PyObject UNUSED *dump_callback) {
|
|||||||
#define A(x) #x, g.x
|
#define A(x) #x, g.x
|
||||||
#define U(x) #x, (unsigned int)(g.x)
|
#define U(x) #x, (unsigned int)(g.x)
|
||||||
#define I(x) #x, (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),
|
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(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),
|
U(payload_sz), I(z_index),
|
||||||
payload, g.payload_sz
|
payload, g.payload_sz
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ class TestGraphics(BaseTest):
|
|||||||
res = send_command(s, cmd, payload)
|
res = send_command(s, cmd, payload)
|
||||||
if not res:
|
if not res:
|
||||||
return
|
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):
|
def sl(payload, **kw):
|
||||||
if isinstance(payload, str):
|
if isinstance(payload, str):
|
||||||
@@ -90,5 +90,5 @@ class TestGraphics(BaseTest):
|
|||||||
# Test loading from POSIX SHM
|
# Test loading from POSIX SHM
|
||||||
name = '/kitty-test-shm'
|
name = '/kitty-test-shm'
|
||||||
g.shm_write(name, random_data)
|
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
|
self.assertRaises(FileNotFoundError, g.shm_unlink, name) # check that file was deleted
|
||||||
|
|||||||
@@ -204,7 +204,7 @@ class TestParser(BaseTest):
|
|||||||
k[p] = v.encode('ascii')
|
k[p] = v.encode('ascii')
|
||||||
for f in 'action transmission_type compressed'.split():
|
for f in 'action transmission_type compressed'.split():
|
||||||
k.setdefault(f, b'\0')
|
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)
|
k.setdefault(f, 0)
|
||||||
p = k.pop('payload', '').encode('utf-8')
|
p = k.pop('payload', '').encode('utf-8')
|
||||||
k['payload_sz'] = len(p)
|
k['payload_sz'] = len(p)
|
||||||
|
|||||||
Reference in New Issue
Block a user