mirror of
https://git.libssh.org/projects/libssh.git
synced 2025-11-26 01:03:15 +03:00
misc.c : Introduce ssh_readn()
A call to read() may peform a short read from a local file even when sufficient data is present in the file. ssh_readn() can be used instead of read() to avoid such short reads. Signed-off-by: Eshan Kelkar <eshankelkar@galorithm.com> Reviewed-by: Jakub Jelen <jjelen@redhat.com> Reviewed-by: Norbert Pocs <npocs@redhat.com>
This commit is contained in:
committed by
Jakub Jelen
parent
33cdc4e3e4
commit
9c8486aafb
@@ -21,6 +21,21 @@
|
|||||||
#ifndef MISC_H_
|
#ifndef MISC_H_
|
||||||
#define MISC_H_
|
#define MISC_H_
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
# ifdef _MSC_VER
|
||||||
|
# ifndef _SSIZE_T_DEFINED
|
||||||
|
# undef ssize_t
|
||||||
|
# include <BaseTsd.h>
|
||||||
|
typedef _W64 SSIZE_T ssize_t;
|
||||||
|
# define _SSIZE_T_DEFINED
|
||||||
|
# endif /* _SSIZE_T_DEFINED */
|
||||||
|
# endif /* _MSC_VER */
|
||||||
|
|
||||||
|
#else
|
||||||
|
# include <sys/types.h>
|
||||||
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
@@ -103,6 +118,9 @@ int ssh_newline_vis(const char *string, char *buf, size_t buf_len);
|
|||||||
int ssh_tmpname(char *name);
|
int ssh_tmpname(char *name);
|
||||||
|
|
||||||
char *ssh_strreplace(const char *src, const char *pattern, const char *repl);
|
char *ssh_strreplace(const char *src, const char *pattern, const char *repl);
|
||||||
|
|
||||||
|
ssize_t ssh_readn(int fd, void *buf, size_t nbytes);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
60
src/misc.c
60
src/misc.c
@@ -1976,4 +1976,64 @@ char *ssh_strerror(int err_num, char *buf, size_t buflen)
|
|||||||
#endif /* defined(__linux__) && defined(__GLIBC__) && defined(_GNU_SOURCE) */
|
#endif /* defined(__linux__) && defined(__GLIBC__) && defined(_GNU_SOURCE) */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read the requested number of bytes from a local file.
|
||||||
|
*
|
||||||
|
* A call to read() may perform a short read even when sufficient data is
|
||||||
|
* present in the file. This function can be used to avoid such short reads.
|
||||||
|
*
|
||||||
|
* This function tries to read the requested number of bytes from the file
|
||||||
|
* until one of the following occurs :
|
||||||
|
* - Requested number of bytes are read.
|
||||||
|
* - EOF is encountered before reading the requested number of bytes.
|
||||||
|
* - An error occurs.
|
||||||
|
*
|
||||||
|
* On encountering an error due to an interrupt, this function ignores that
|
||||||
|
* error and continues trying to read the data.
|
||||||
|
*
|
||||||
|
* @param[in] fd The file descriptor of the local file to read from.
|
||||||
|
*
|
||||||
|
* @param[out] buf Pointer to a buffer in which read data will be
|
||||||
|
* stored.
|
||||||
|
*
|
||||||
|
* @param[in] nbytes Number of bytes to read.
|
||||||
|
*
|
||||||
|
* @returns Number of bytes read on success,
|
||||||
|
* SSH_ERROR on error with errno set to indicate the
|
||||||
|
* error.
|
||||||
|
*/
|
||||||
|
ssize_t ssh_readn(int fd, void *buf, size_t nbytes)
|
||||||
|
{
|
||||||
|
size_t total_bytes_read = 0;
|
||||||
|
ssize_t bytes_read;
|
||||||
|
|
||||||
|
if (fd < 0 || buf == NULL || nbytes == 0) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
bytes_read = read(fd,
|
||||||
|
((char *)buf) + total_bytes_read,
|
||||||
|
nbytes - total_bytes_read);
|
||||||
|
if (bytes_read == -1) {
|
||||||
|
if (errno == EINTR) {
|
||||||
|
/* Ignoring errors due to signal interrupts */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bytes_read == 0) {
|
||||||
|
/* EOF encountered on the local file before reading nbytes */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
total_bytes_read += (size_t)bytes_read;
|
||||||
|
} while (total_bytes_read < nbytes);
|
||||||
|
|
||||||
|
return total_bytes_read;
|
||||||
|
}
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|||||||
Reference in New Issue
Block a user