mirror of
https://git.proxmox.com/git/libgit2
synced 2025-11-03 20:12:03 +00:00
Redefine git_fread, git_fwrite to transfer the whole unit
We never want to accept a short read or a short write when transferring data to or from a local file. Either the entire read (or write) completes or the operation failed and we will not recover gracefully from it. Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
This commit is contained in:
parent
b7c891c629
commit
3e9e69098a
@ -54,58 +54,55 @@ typedef int git_file;
|
||||
* - O_WRONLY: Open the file for writing.
|
||||
* - O_RDWR: Open the file for both reading and writing.
|
||||
*
|
||||
* @param out descriptor storage to populate on success.
|
||||
* @param path path name of the file to open.
|
||||
* @param flags bitmask of access requested to the file.
|
||||
* @return the opened file descriptor; <0 if the open failed.
|
||||
* @return
|
||||
* - On success, GIT_SUCCESS.
|
||||
* - On error, <0.
|
||||
*/
|
||||
static inline git_file git_fopen(const char *path, int flags)
|
||||
{
|
||||
return open(path, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close an open file descriptor.
|
||||
* @param fd descriptor to close.
|
||||
* @return 0 on success; <0 if the descriptor close failed.
|
||||
*/
|
||||
static inline int git_fclose(git_file fd)
|
||||
{
|
||||
return close(fd);
|
||||
}
|
||||
GIT_EXTERN(int) git_fopen(git_file *out, const char *path, int flags);
|
||||
|
||||
/**
|
||||
* Read from an open file descriptor at the current position.
|
||||
*
|
||||
* Less than the number of requested bytes may be read. The
|
||||
* read is automatically restarted if it fails due to a signal
|
||||
* being delivered to the calling thread.
|
||||
* Exactly the requested number of bytes is read. If the stream
|
||||
* ends early, an error is indicated, and the exact number of bytes
|
||||
* transferred is unspecified.
|
||||
*
|
||||
* @param fd open descriptor.
|
||||
* @param buf buffer to store the read data into.
|
||||
* @param cnt number of bytes to transfer.
|
||||
* @return
|
||||
* - On success, actual number of bytes read.
|
||||
* - On EOF, 0.
|
||||
* - On failure, <0.
|
||||
* - On success, GIT_SUCCESS.
|
||||
* - On error, <0.
|
||||
*/
|
||||
GIT_EXTERN(ssize_t) git_fread(git_file fd, void *buf, size_t cnt);
|
||||
GIT_EXTERN(int) git_fread(git_file fd, void *buf, size_t cnt);
|
||||
|
||||
/**
|
||||
* Write to an open file descriptor at the current position.
|
||||
*
|
||||
* Less than the number of requested bytes may be written. The
|
||||
* write is automatically restarted if it fails due to a signal
|
||||
* being delivered to the calling thread.
|
||||
* Exactly the requested number of bytes is written. If the stream
|
||||
* ends early, an error is indicated, and the exact number of bytes
|
||||
* transferred is unspecified.
|
||||
*
|
||||
* @param fd open descriptor.
|
||||
* @param buf buffer to write data from.
|
||||
* @param cnt number of bytes to transfer.
|
||||
* @return
|
||||
* - On success, actual number of bytes written.
|
||||
* - On EOF, 0.
|
||||
* - On failure, <0.
|
||||
* - On success, GIT_SUCCESS.
|
||||
* - On error, <0.
|
||||
*/
|
||||
GIT_EXTERN(ssize_t) git_fwrite(git_file fd, void *buf, size_t cnt);
|
||||
GIT_EXTERN(int) git_fwrite(git_file fd, void *buf, size_t cnt);
|
||||
|
||||
/**
|
||||
* Close an open file descriptor.
|
||||
* @param fd descriptor to close.
|
||||
* @return
|
||||
* - On success, GIT_SUCCESS.
|
||||
* - On error, <0.
|
||||
*/
|
||||
#define git_fclose(fd) close(fd)
|
||||
|
||||
/** @} */
|
||||
GIT_END_DECL
|
||||
|
||||
@ -26,22 +26,51 @@
|
||||
#include <errno.h>
|
||||
#include "git/common.h"
|
||||
|
||||
ssize_t git_fread(git_file fd, void *buf, size_t cnt)
|
||||
int git_fopen(git_file *out, const char *path, int flags)
|
||||
{
|
||||
for (;;) {
|
||||
ssize_t r = read(fd, buf, cnt);
|
||||
if (r < 0 && (errno == EINTR || errno == EAGAIN))
|
||||
continue;
|
||||
return r;
|
||||
}
|
||||
int r = open(path, flags);
|
||||
if (r < 0)
|
||||
return -1;
|
||||
*out = r;
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
ssize_t git_fwrite(git_file fd, void *buf, size_t cnt)
|
||||
int git_fread(git_file fd, void *buf, size_t cnt)
|
||||
{
|
||||
for (;;) {
|
||||
ssize_t r = write(fd, buf, cnt);
|
||||
if (r < 0 && (errno == EINTR || errno == EAGAIN))
|
||||
continue;
|
||||
return r;
|
||||
char *b = buf;
|
||||
while (cnt) {
|
||||
ssize_t r = read(fd, b, cnt);
|
||||
if (r < 0) {
|
||||
if (errno == EINTR || errno == EAGAIN)
|
||||
continue;
|
||||
return -1;
|
||||
}
|
||||
if (!r) {
|
||||
errno = EPIPE;
|
||||
return -1;
|
||||
}
|
||||
cnt -= r;
|
||||
b += r;
|
||||
}
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
int git_fwrite(git_file fd, void *buf, size_t cnt)
|
||||
{
|
||||
char *b = buf;
|
||||
while (cnt) {
|
||||
ssize_t r = write(fd, b, cnt);
|
||||
if (r < 0) {
|
||||
if (errno == EINTR || errno == EAGAIN)
|
||||
continue;
|
||||
return -1;
|
||||
}
|
||||
if (!r) {
|
||||
errno = EPIPE;
|
||||
return -1;
|
||||
}
|
||||
cnt -= r;
|
||||
b += r;
|
||||
}
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user