diff options
author | Sergey Bugaev <bugaevc@serenityos.org> | 2020-06-16 21:51:08 +0300 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-06-17 15:02:03 +0200 |
commit | 47d83800e1c27c0a26d3ee432973d49a3f83f299 (patch) | |
tree | d3dcf6565f6aa111a2013eb0b60ba2c99219262b /Kernel/Process.cpp | |
parent | 35329400b899f632866348c95c4bb04920ed6f58 (diff) | |
download | serenity-47d83800e1c27c0a26d3ee432973d49a3f83f299.zip |
Kernel+LibC: Do not return -ENAMETOOLONG from sys$readlink()
That's not how readlink() is supposed to work: it should copy as many bytes
as fit into the buffer, and return the number of bytes copied. So do that,
but add a twist: make sys$readlink() actually return the whole size, not
the number of bytes copied. We fix up this return value in userspace, to make
LibC's readlink() behave as expected, but this will also allow other code
to allocate a buffer of just the right size.
Also, avoid an extra copy of the link target.
Diffstat (limited to 'Kernel/Process.cpp')
-rw-r--r-- | Kernel/Process.cpp | 10 |
1 files changed, 5 insertions, 5 deletions
diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 568648401e..9c066baf95 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -1953,11 +1953,11 @@ int Process::sys$readlink(const Syscall::SC_readlink_params* user_params) if (contents.is_error()) return contents.error(); - auto link_target = String::copy(contents.value()); - if (link_target.length() > params.buffer.size) - return -ENAMETOOLONG; - copy_to_user(params.buffer.data, link_target.characters(), link_target.length()); - return link_target.length(); + auto& link_target = contents.value(); + auto size_to_copy = min(link_target.size(), params.buffer.size); + copy_to_user(params.buffer.data, link_target.data(), size_to_copy); + // Note: we return the whole size here, not the copied size. + return link_target.size(); } int Process::sys$chdir(const char* user_path, size_t path_length) |