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:
Kovid Goyal 2017-09-28 17:09:57 +05:30
parent 898136dbdc
commit dbd7ec5b27
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
5 changed files with 20 additions and 17 deletions

View file

@ -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;

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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)