diff --git a/libc/inc/readline.h b/libc/inc/readline.h new file mode 100644 index 0000000..586d031 --- /dev/null +++ b/libc/inc/readline.h @@ -0,0 +1,14 @@ +/// @file readline.h +/// @brief +/// @copyright (c) 2014-2023 This file is distributed under the MIT License. +/// See LICENSE.md for details. + +#include "stddef.h" + +/// @brief Reads a line from the file. +/// @param fd the file descriptor. +/// @param buffer the buffer where we place the line. +/// @param buflen the length of the buffer. +/// @param readlen the amount we read, if negative, we did not encounter a newline. +/// @return 0 if we are done reading, 1 if we encountered a newline, -1 if otherwise. +int readline(int fd, char *buffer, size_t buflen, ssize_t *read_len); diff --git a/libc/src/pwd.c b/libc/src/pwd.c index e6203ca..6012129 100644 --- a/libc/src/pwd.c +++ b/libc/src/pwd.c @@ -7,6 +7,7 @@ #include "assert.h" #include "fcntl.h" #include "io/debug.h" +#include "readline.h" #include "stdio.h" #include "string.h" #include "sys/errno.h" @@ -57,41 +58,6 @@ static inline void __parse_line(passwd_t *pwd, char *buf) } } -/// @brief Reads a line from the file. -/// @param fd the file descriptor. -/// @param buffer the buffer where we place the line. -/// @param buflen the length of the buffer. -/// @return the amount we read. -ssize_t __readline(int fd, char *buffer, size_t buflen) -{ - memset(buffer, 0, buflen); - long num_read = read(fd, buffer, buflen); - if (num_read == 0) { - return 0; - } - char *newline = strchr(buffer, '\n'); - if (newline == NULL) { - newline = strchr(buffer, EOF); - if (newline == NULL) { - newline = strchr(buffer, 0); - if (newline == NULL) { - return 0; - } - } - } - long newline_len = (newline - buffer); - if (newline_len <= 0) { - return 0; - } - buffer[newline_len] = 0; - long rollback = newline_len - num_read + 1; - if (rollback > 1) { - return 0; - } - lseek(fd, rollback, SEEK_CUR); - return newline_len; -} - /// @brief Searches for the given entry inside the buffer. /// @param fd the file descriptor of the file. /// @param buffer the support buffer we use to read the file. @@ -101,7 +67,7 @@ ssize_t __readline(int fd, char *buffer, size_t buflen) /// @return the buffer itself if we have found the entry, NULL otherwise. static inline char *__search_entry(int fd, char *buffer, int buflen, const char *name, uid_t uid) { - while (__readline(fd, buffer, buflen)) { + while (readline(fd, buffer, buflen, NULL) != 0) { if (name != NULL) { char *name_end = strchr(buffer, ':'); if (name_end) { diff --git a/libc/src/readline.c b/libc/src/readline.c new file mode 100644 index 0000000..b66ce2b --- /dev/null +++ b/libc/src/readline.c @@ -0,0 +1,57 @@ +/// @file readline.c +/// @author Enrico Fraccaroli (enry.frak@gmail.com) +/// @brief +/// @version 0.1 +/// @date 2023-08-30 +/// +/// @copyright Copyright (c) 2023 +/// + +#include "readline.h" + +#include "stdio.h" +#include "string.h" +#include "sys/unistd.h" + +int readline(int fd, char *buffer, size_t buflen, ssize_t *read_len) +{ + ssize_t length, rollback, num_read; + memset(buffer, 0, buflen); + unsigned char found_newline = 1; + // Read from the file. + num_read = read(fd, buffer, buflen); + if (num_read == 0) { + return 0; + } + // Search for termination character. + char *newline = strchr(buffer, '\n'); + if (newline == NULL) { + found_newline = 0; + newline = strchr(buffer, EOF); + if (newline == NULL) { + newline = strchr(buffer, 0); + if (newline == NULL) { + return 0; + } + } + } + // Compute the length of the string. + length = (newline - buffer); + if (length <= 0) { + return 0; + } + // Close the string. + buffer[length] = 0; + // Compute how much we need to rollback. + rollback = length - num_read + 1; + if (rollback > 1) { + return 0; + } + // Rollback the reading position in the file. + lseek(fd, rollback, SEEK_CUR); + // Set how much we were able to read from the file. + if (read_len) { + *read_len = length; + } + return (found_newline) ? 1 : -1; +}