librsync  2.3.4
fileutil.c
1/*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*-
2 *
3 * librsync -- library for network deltas
4 *
5 * Copyright (C) 1999, 2000, 2001 by Martin Pool <mbp@sourcefrog.net>
6 * Copyright (C) 1999 by Andrew Tridgell <tridge@samba.org>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23/* This provides a compatiblity layer for file operations on different
24 platforms. We need to tell IWYU to keep some headers because they are
25 required on some platforms but not others. */
26#include "config.h" /* IWYU pragma: keep */
27#include <stdlib.h>
28#include <stdio.h>
29#include <string.h>
30#include <errno.h>
31#ifdef HAVE_UNISTD_H
32# include <unistd.h> /* IWYU pragma: keep */
33#endif
34#ifdef HAVE_FCNTL_H
35# include <fcntl.h> /* IWYU pragma: keep */
36#endif
37#ifdef HAVE_SYS_TYPES_H
38# include <sys/types.h> /* IWYU pragma: keep */
39#endif
40#ifdef HAVE_SYS_FILE_H
41# include <sys/file.h> /* IWYU pragma: keep */
42#endif
43#ifdef HAVE_SYS_STAT_H
44# include <sys/stat.h> /* IWYU pragma: keep */
45#endif
46#ifdef HAVE_IO_H
47# include <io.h> /* IWYU pragma: keep */
48#endif
49#include "librsync.h"
50#include "trace.h"
51
52/* Use fseeko64, _fseeki64, or fseeko for long files if they exist. */
53#if defined(HAVE_FSEEKO64) && (SIZEOF_OFF_T < 8)
54# define fopen(f, m) fopen64((f), (m))
55# define fseek(f, o, w) fseeko64((f), (o), (w))
56#elif defined(HAVE__FSEEKI64)
57# define fseek(f, o, w) _fseeki64((f), (o), (w))
58#elif defined(HAVE_FSEEKO)
59# define fseek(f, o, w) fseeko((f), (o), (w))
60#endif
61
62/* Use fstat64 or _fstati64 for long file fstat if they exist. */
63#if defined(HAVE_FSTAT64) && (SIZEOF_OFF_T < 8)
64# define stat stat64
65# define fstat(f,s) fstat64((f), (s))
66#elif defined(HAVE__FSTATI64)
67# define stat _stati64
68# define fstat(f,s) _fstati64((f), (s))
69#endif
70
71/* Make sure S_ISREG is defined. */
72#ifndef S_ISREG
73# define S_ISREG(x) ((x) & _S_IFREG)
74#endif
75
76/* Use and prefer _fileno if it exists. */
77#ifdef HAVE__FILENO
78# define fileno(f) _fileno((f))
79#endif
80
81FILE *rs_file_open(char const *filename, char const *mode, int force)
82{
83 FILE *f;
84 int is_write;
85
86 is_write = mode[0] == 'w';
87
88 if (!filename || !strcmp("-", filename)) {
89 if (is_write) {
90#if _WIN32
91 _setmode(_fileno(stdout), _O_BINARY);
92#endif
93 return stdout;
94 } else {
95#if _WIN32
96 _setmode(_fileno(stdin), _O_BINARY);
97#endif
98 return stdin;
99 }
100 }
101
102 if (!force && is_write) {
103 if ((f = fopen(filename, "rb"))) {
104 // File exists
105 rs_error("File exists \"%s\", aborting!", filename);
106 fclose(f);
107 exit(RS_IO_ERROR);
108 }
109 }
110
111 if (!(f = fopen(filename, mode))) {
112 rs_error("Error opening \"%s\" for %s: %s", filename,
113 is_write ? "write" : "read", strerror(errno));
114 exit(RS_IO_ERROR);
115 }
116
117 return f;
118}
119
120int rs_file_close(FILE *f)
121{
122 if ((f == stdin) || (f == stdout))
123 return 0;
124 return fclose(f);
125}
126
127rs_long_t rs_file_size(FILE *f)
128{
129 struct stat st;
130 if ((fstat(fileno(f), &st) == 0) && (S_ISREG(st.st_mode)))
131 return st.st_size;
132 return -1;
133}
134
135rs_result rs_file_copy_cb(void *arg, rs_long_t pos, size_t *len, void **buf)
136{
137 FILE *f = (FILE *)arg;
138
139 if (fseek(f, pos, SEEK_SET)) {
140 rs_error("seek failed: %s", strerror(errno));
141 return RS_IO_ERROR;
142 }
143 *len = fread(*buf, 1, *len, f);
144 if (*len) {
145 return RS_DONE;
146 } else if (ferror(f)) {
147 rs_error("read error: %s", strerror(errno));
148 return RS_IO_ERROR;
149 } else {
150 rs_error("unexpected eof on fd%d", fileno(f));
151 return RS_INPUT_ENDED;
152 }
153}
Public header for librsync.
LIBRSYNC_EXPORT int rs_file_close(FILE *file)
Close a file with special handling for stdin or stdout.
Definition: fileutil.c:120
LIBRSYNC_EXPORT FILE * rs_file_open(char const *filename, char const *mode, int force)
Open a file with special handling for stdin or stdout.
Definition: fileutil.c:81
LIBRSYNC_EXPORT rs_long_t rs_file_size(FILE *file)
Get the size of a file.
Definition: fileutil.c:127
rs_result
Return codes from nonblocking rsync operations.
Definition: librsync.h:180
@ RS_DONE
Completed successfully.
Definition: librsync.h:181
@ RS_INPUT_ENDED
Unexpected end of input file, perhaps due to a truncated file or dropped network connection.
Definition: librsync.h:190
@ RS_IO_ERROR
Error in file or network IO.
Definition: librsync.h:187
LIBRSYNC_EXPORT rs_result rs_file_copy_cb(void *arg, rs_long_t pos, size_t *len, void **buf)
rs_copy_cb that reads from a stdio file.
Definition: fileutil.c:135
logging functions.