readdir() ends a directory's name by writing a terminator at the
directory separator's index, which is past the end of d_name for a
directory name that long. Only shorten the name to the directory where
that falls within the name as copied.
readdir() copied the name with strncpy(), which leaves it unterminated
when it fills d_name, so anything reading it as a string - GCS_FTP's
listing among them - could run off the end of it.
Truncate to leave room for the terminator, as the FATFS backend does.
Co-authored-by: David Buzz <davidbuzz@gmail.com>
Lua opens scripts to load them into memory, then the logger opens them
after to stream them into the dataflash log. When loading multiple large
Lua scripts from ROMFS, decompression takes a significant amount of
time. This creates the opportunity for the Lua interpreter and logging
threads to both be inside `AP_Filesystem_ROMFS::open()` decompressing a
file.
If this happens, the function can return the same `fd` for two different
calls as the `fd` is chosen before decompression starts, but only marked
as being used after that finishes. The read pointers then stomp on each
other, so Lua loads garbled scripts (usually resulting in a syntax
error) and the logger dumps garbled data.
Fix the issue by locking before searching for a free record (or marking
a record as free). Apply the same fix to directories as well. This
doesn't protect against using the same `fd`/`dirp` from multiple
threads, but that behavior is to be discouraged anyway and is not the
root cause here.
Improves safety of use and clarity of users. Termination is not
included in the reported size to avoid changing user behavior or
misrepresenting the file contents.