From cacda425202793a421618e6fed8cd97552a4bcb3 Mon Sep 17 00:00:00 2001 From: CruxBox Date: Wed, 19 Aug 2020 00:15:09 +0530 Subject: [PATCH] fs_shell: Fixed cat command This patch fixes the following issues: The cat command in fs_shell only printed 10 bytes instead of the entire file. Also, when the number of bytes to be read from file was large it would cause segmentation fault because of stackoverflow. This was noticed while testing xfs and ufs filesystems and has now been fixed. Change-Id: I3891f2834c5b76330f666ebee97b20bd5529742a Reviewed-on: https://review.haiku-os.org/c/haiku/+/3157 Reviewed-by: Adrien Destugues --- src/tools/fs_shell/fssh.cpp | 44 +++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/src/tools/fs_shell/fssh.cpp b/src/tools/fs_shell/fssh.cpp index 7a6f87734c..e5fc26cc74 100644 --- a/src/tools/fs_shell/fssh.cpp +++ b/src/tools/fs_shell/fssh.cpp @@ -691,7 +691,7 @@ command_chmod(int argc, const char* const* argv) static fssh_status_t command_cat(int argc, const char* const* argv) { - size_t numBytes = 10; + size_t numBytes = 4096; int fileStart = 1; if (argc < 2 || strcmp(argv[1], "--help") == 0) { printf("Usage: %s [ -n ] [FILE]...\n" @@ -700,9 +700,11 @@ command_cat(int argc, const char* const* argv) return FSSH_B_OK; } + bool isReadLengthGiven = false; if (argc > 3 && strcmp(argv[1], "-n") == 0) { fileStart += 2; numBytes = strtol(argv[2], NULL, 10); + isReadLengthGiven = true; } const char* const* files = argv + fileStart; @@ -713,23 +715,37 @@ command_cat(int argc, const char* const* argv) fprintf(stderr, "error: %s\n", fssh_strerror(fd)); return FSSH_B_BAD_VALUE; } + struct fssh_stat st; + fssh_status_t error = _kern_read_stat(-1, file, false, &st, sizeof(st)); + if (error != FSSH_B_OK) { + fprintf(stderr, "Error: Failed to stat() \"%s\": %s\n", file, + fssh_strerror(error)); + return error; + } + size_t fileLengthToRead; + if (!isReadLengthGiven) { + fileLengthToRead = st.fssh_st_size; + numBytes = 4096; + } else + fileLengthToRead = numBytes; + size_t pos = 0; char buffer[numBytes + 1]; - if (buffer == NULL) { - fprintf(stderr, "error: No memory\n"); - _kern_close(fd); - return FSSH_B_NO_MEMORY; + while (fileLengthToRead > 0) { + if (fileLengthToRead < numBytes) + numBytes = fileLengthToRead; + if (_kern_read(fd, pos, buffer, numBytes) != (ssize_t)numBytes) { + fprintf(stderr, "error reading: %s\n", fssh_strerror(fd)); + _kern_close(fd); + return FSSH_B_BAD_VALUE; + } + buffer[numBytes] = '\0'; + printf("%s", buffer); + pos += numBytes; + fileLengthToRead -= numBytes; } - - if (_kern_read(fd, 0, buffer, numBytes) != (ssize_t)numBytes) { - fprintf(stderr, "error reading: %s\n", fssh_strerror(fd)); - _kern_close(fd); - return FSSH_B_BAD_VALUE; - } - + printf("\n"); _kern_close(fd); - buffer[numBytes] = '\0'; - printf("%s\n", buffer); } return FSSH_B_OK;