mirror of
https://github.com/kovidgoyal/kitty
synced 2026-06-08 14:18:26 +02:00
Have top level symlink behavior match for local and remote drops
This commit is contained in:
@@ -171,15 +171,12 @@ MIME type is not present in the drop, the terminal must reply with
|
|||||||
If the client requests an entry that is not a supported URI type the
|
If the client requests an entry that is not a supported URI type the
|
||||||
terminal must reply with ``EUNKNOWN``.
|
terminal must reply with ``EUNKNOWN``.
|
||||||
|
|
||||||
Terminals must ONLY send data for regular files or directories. Symbolic links must be
|
Terminals must ONLY send data for regular files, symbolic links and directories.
|
||||||
resolved and the corresponding file or directory read. Only if the symbolic
|
See below for more details about sending symlinks.
|
||||||
link cannot be resolved must it be transmitted as a symbolic link (in which
|
|
||||||
case ``X=1`` and the payload is the base64 encoded target of the symlink. See
|
|
||||||
below for more details about sending symlinks.
|
|
||||||
|
|
||||||
If the terminal does not have permission to read the file it must reply with
|
If the terminal does not have permission to read the file it must reply with
|
||||||
``EPERM``. Terminals must respond with ``EINVAL`` if the file is not a regular
|
``EPERM``. Terminals must respond with ``EINVAL`` if the file is not a regular
|
||||||
file after resolving symlinks and ``ENOENT`` if the file does not exist. If an
|
file or symlink or directory and ``ENOENT`` if the file does not exist. If an
|
||||||
I/O error occurs the terminal must send ``EIO``.
|
I/O error occurs the terminal must send ``EIO``.
|
||||||
|
|
||||||
For security reasons, terminals must reply with ``EPERM`` if the drag
|
For security reasons, terminals must reply with ``EPERM`` if the drag
|
||||||
|
|||||||
19
kitty/dnd.c
19
kitty/dnd.c
@@ -947,12 +947,14 @@ drop_send_dir_listing(Window *w, const char *path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
drop_send_symlink(Window *w, const char *target, size_t sz) {
|
drop_send_symlink(Window *w, const char *path) {
|
||||||
|
char target[PATH_MAX]; ssize_t tgtsz;
|
||||||
|
if ((tgtsz = readlink(path, target, sizeof(target)-1)) < 0) { drop_send_error(w, EIO); return; }
|
||||||
char hdr[128];
|
char hdr[128];
|
||||||
int hdr_sz = snprintf(hdr, sizeof(hdr), "\x1b]%d;t=r", DND_CODE);
|
int hdr_sz = snprintf(hdr, sizeof(hdr), "\x1b]%d;t=r", DND_CODE);
|
||||||
hdr_sz += drop_append_request_keys(w, hdr + hdr_sz, sizeof(hdr) - hdr_sz);
|
hdr_sz += drop_append_request_keys(w, hdr + hdr_sz, sizeof(hdr) - hdr_sz);
|
||||||
hdr_sz += snprintf(hdr + hdr_sz, sizeof(hdr) - hdr_sz, ":X=1");
|
hdr_sz += snprintf(hdr + hdr_sz, sizeof(hdr) - hdr_sz, ":X=1");
|
||||||
queue_payload_to_child(w->id, w->drop.client_id, &w->drop.pending, hdr, hdr_sz, target, sz, true);
|
queue_payload_to_child(w->id, w->drop.client_id, &w->drop.pending, hdr, hdr_sz, target, tgtsz, true);
|
||||||
queue_payload_to_child(w->id, w->drop.client_id, &w->drop.pending, hdr, hdr_sz, NULL, 0, true);
|
queue_payload_to_child(w->id, w->drop.client_id, &w->drop.pending, hdr, hdr_sz, NULL, 0, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -985,7 +987,6 @@ do_drop_request_uri_data(Window *w, int32_t mime_idx, int32_t file_idx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (stat(path, &st) < 0) {
|
|
||||||
if (lstat(path, &st) < 0) {
|
if (lstat(path, &st) < 0) {
|
||||||
switch (errno) {
|
switch (errno) {
|
||||||
case ENOENT: case ENOTDIR: drop_send_error(w, ENOENT); break;
|
case ENOENT: case ENOTDIR: drop_send_error(w, ENOENT); break;
|
||||||
@@ -994,22 +995,16 @@ do_drop_request_uri_data(Window *w, int32_t mime_idx, int32_t file_idx) {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// We have a broken symlink
|
|
||||||
char target[PATH_MAX]; ssize_t tgtsz;
|
|
||||||
if ((tgtsz = readlink(path, target, sizeof(target)-1)) < 0) drop_send_error(w, ENOENT);
|
|
||||||
drop_send_symlink(w, target, tgtsz);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool sync;
|
bool sync = true;
|
||||||
if (S_ISDIR(st.st_mode)) {
|
if (S_ISDIR(st.st_mode)) {
|
||||||
drop_send_dir_listing(w, path);
|
drop_send_dir_listing(w, path);
|
||||||
sync = true;
|
|
||||||
} else if (S_ISREG(st.st_mode)) {
|
} else if (S_ISREG(st.st_mode)) {
|
||||||
sync = drop_send_file_data(w, path);
|
sync = drop_send_file_data(w, path);
|
||||||
|
} else if (S_ISLNK(st.st_mode)) {
|
||||||
|
drop_send_symlink(w, path);
|
||||||
} else {
|
} else {
|
||||||
drop_send_error(w, EINVAL);
|
drop_send_error(w, EINVAL);
|
||||||
sync = true;
|
|
||||||
}
|
}
|
||||||
return sync;
|
return sync;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ class Capture(WriteCapture):
|
|||||||
self.pty.write_to_child(data)
|
self.pty.write_to_child(data)
|
||||||
|
|
||||||
|
|
||||||
def create_fs(base, include_toplevel_working_symlink=False):
|
def create_fs(base, include_toplevel_working_symlink=True):
|
||||||
join = partial(os.path.join, base)
|
join = partial(os.path.join, base)
|
||||||
def w(sz, *path):
|
def w(sz, *path):
|
||||||
if sz == 0:
|
if sz == 0:
|
||||||
@@ -232,7 +232,7 @@ class TestDnDKitten(BaseTest):
|
|||||||
self.assertEqual('text/uri-list\x00image/png', self.probe_state('drop_mimes').rstrip('\x00'))
|
self.assertEqual('text/uri-list\x00image/png', self.probe_state('drop_mimes').rstrip('\x00'))
|
||||||
self.wait_for_state('drop_data_requests', ((1,0,0), (4,0,0)))
|
self.wait_for_state('drop_data_requests', ((1,0,0), (4,0,0)))
|
||||||
self.assertEqual('text/uri-list', self.probe_state('drop_getting_data_for_mime'))
|
self.assertEqual('text/uri-list', self.probe_state('drop_getting_data_for_mime'))
|
||||||
create_fs(self.src_data_dir, include_toplevel_working_symlink=not remote_client)
|
create_fs(self.src_data_dir)
|
||||||
uri_list, path_list = [], []
|
uri_list, path_list = [], []
|
||||||
for x in sorted(os.listdir(self.src_data_dir)):
|
for x in sorted(os.listdir(self.src_data_dir)):
|
||||||
uri_list.append(as_file_url(self.src_data_dir, x))
|
uri_list.append(as_file_url(self.src_data_dir, x))
|
||||||
|
|||||||
Reference in New Issue
Block a user