#include "config.h"
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#endif
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#ifdef HAVE_SYS_FILE_H
# include <sys/file.h>
#endif
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#include "librsync.h"
#include "trace.h"
#if defined(HAVE_FSEEKO64) && (SIZEOF_OFF_T < 8)
# define fopen(f, m) fopen64((f), (m))
# define fseek(f, o, w) fseeko64((f), (o), (w))
#elif defined(HAVE__FSEEKI64)
# define fseek(f, o, w) _fseeki64((f), (o), (w))
#elif defined(HAVE_FSEEKO)
# define fseek(f, o, w) fseeko((f), (o), (w))
#endif
#if defined(HAVE_FSTAT64) && (SIZEOF_OFF_T < 8)
# define stat stat64
# define fstat(f,s) fstat64((f), (s))
#elif defined(HAVE__FSTATI64)
# define stat _stati64
# define fstat(f,s) _fstati64((f), (s))
#endif
#ifndef S_ISREG
# define S_ISREG(x) ((x) & _S_IFREG)
#endif
#if !defined(HAVE_FILENO) && defined(HAVE__FILENO)
# define fileno(f) _fileno((f))
#endif
FILE *rs_file_open(char const *filename, char const *mode, int force)
{
FILE *f;
int is_write;
is_write = mode[0] == 'w';
if (!filename || !strcmp("-", filename)) {
if (is_write) {
#if _WIN32
_setmode(_fileno(stdout), _O_BINARY);
#endif
return stdout;
} else {
#if _WIN32
_setmode(_fileno(stdin), _O_BINARY);
#endif
return stdin;
}
}
if (!force && is_write) {
if ((f = fopen(filename, "rb"))) {
rs_error("File exists \"%s\", aborting!", filename);
fclose(f);
exit(RS_IO_ERROR);
}
}
if (!(f = fopen(filename, mode))) {
rs_error("Error opening \"%s\" for %s: %s", filename,
is_write ? "write" : "read", strerror(errno));
exit(RS_IO_ERROR);
}
return f;
}
int rs_file_close(FILE *f)
{
if ((f == stdin) || (f == stdout))
return 0;
return fclose(f);
}
rs_long_t rs_file_size(FILE *f)
{
struct stat st;
if ((fstat(fileno(f), &st) == 0) && (S_ISREG(st.st_mode)))
return st.st_size;
return -1;
}
rs_result rs_file_copy_cb(void *arg, rs_long_t pos, size_t *len, void **buf)
{
int got;
FILE *f = (FILE *)arg;
if (fseek(f, pos, SEEK_SET)) {
rs_error("seek failed: %s", strerror(errno));
return RS_IO_ERROR;
}
got = fread(*buf, 1, *len, f);
if (got == -1) {
rs_error("read error: %s", strerror(errno));
return RS_IO_ERROR;
} else if (got == 0) {
rs_error("unexpected eof on fd%d", fileno(f));
return RS_INPUT_ENDED;
} else {
*len = got;
return RS_DONE;
}
}