librsync  2.0.2
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 #include "config.h"
24 
25 #include <assert.h>
26 #include <stdlib.h>
27 #ifdef HAVE_UNISTD_H
28 # include <unistd.h>
29 #endif
30 #include <stdio.h>
31 #ifdef HAVE_FCNTL_H
32 # include <fcntl.h>
33 #endif
34 #ifdef HAVE_SYS_FILE_H
35 # include <sys/file.h>
36 #endif
37 #ifdef HAVE_SYS_STAT_H
38 # include <sys/stat.h>
39 #endif
40 #include <string.h>
41 #include <errno.h>
42 
43 #include "librsync.h"
44 #include "fileutil.h"
45 #include "trace.h"
46 
47 /* Use fseeko64, _fseeki64, or fseeko for long files if they exist. */
48 #if defined(HAVE_FSEEKO64) && (SIZEOF_OFF_T < 8)
49 # define fopen(f, m) fopen64((f), (m))
50 # define fseek(f, o, w) fseeko64((f), (o), (w))
51 #elif defined(HAVE__FSEEKI64)
52 # define fseek(f, o, w) _fseeki64((f), (o), (w))
53 #elif defined(HAVE_FSEEKO)
54 # define fseek(f, o, w) fseeko((f), (o), (w))
55 #endif
56 
57 /* Use fstat64 or _fstati64 for long file fstat if they exist. */
58 #if defined(HAVE_FSTAT64) && (SIZEOF_OFF_T < 8)
59 # define stat stat64
60 # define fstat(f,s) fstat64((f), (s))
61 #elif defined(HAVE__FSTATI64)
62 # define stat _stati64
63 # define fstat(f,s) _fstati64((f), (s))
64 #endif
65 
66 /* Make sure S_ISREG is defined. */
67 #ifndef S_ISREG
68 # define S_ISREG(x) ((x) & _S_IFREG)
69 #endif
70 
71 /* Use _fileno if it exists and fileno doesn't. */
72 #if !defined(HAVE_FILENO) && defined(HAVE__FILENO)
73 # define fileno(f) _fileno((f))
74 #endif
75 
76 /** Open a file with special handling for '-' or unspecified filenames.
77  *
78  * \param filename - The filename to open.
79  *
80  * \param mode - fopen style mode string.
81  *
82  * \param force - bool to force overwriting of existing files. */
83 FILE *rs_file_open(char const *filename, char const *mode, int force)
84 {
85  FILE *f;
86  int is_write;
87 
88  is_write = mode[0] == 'w';
89 
90  if (!filename || !strcmp("-", filename)) {
91  if (is_write) {
92 #if _WIN32
93  _setmode(_fileno(stdout), _O_BINARY);
94 #endif
95  return stdout;
96  } else {
97 #if _WIN32
98  _setmode(_fileno(stdin), _O_BINARY);
99 #endif
100  return stdin;
101  }
102  }
103 
104  if (!force && is_write) {
105  if ((f = fopen(filename, "rb"))) {
106  // File exists
107  rs_error("File exists \"%s\", aborting!", filename);
108  fclose(f);
109  exit(RS_IO_ERROR);
110  }
111  }
112 
113  if (!(f = fopen(filename, mode))) {
114  rs_error("Error opening \"%s\" for %s: %s", filename,
115  is_write ? "write" : "read", strerror(errno));
116  exit(RS_IO_ERROR);
117  }
118 
119  return f;
120 }
121 
122 int rs_file_close(FILE *f)
123 {
124  if ((f == stdin) || (f == stdout))
125  return 0;
126  return fclose(f);
127 }
128 
129 void rs_get_filesize(FILE *f, rs_long_t *size)
130 {
131  struct stat st;
132  if (size && (fstat(fileno(f), &st) == 0) && (S_ISREG(st.st_mode))) {
133  *size = st.st_size;
134  }
135 }
136 
137 rs_result rs_file_copy_cb(void *arg, rs_long_t pos, size_t *len, void **buf)
138 {
139  int got;
140  FILE *f = (FILE *)arg;
141 
142  if (fseek(f, pos, SEEK_SET)) {
143  rs_error("seek failed: %s", strerror(errno));
144  return RS_IO_ERROR;
145  }
146 
147  got = fread(*buf, 1, *len, f);
148  if (got == -1) {
149  rs_error("read error: %s", strerror(errno));
150  return RS_IO_ERROR;
151  } else if (got == 0) {
152  rs_error("unexpected eof on fd%d", fileno(f));
153  return RS_INPUT_ENDED;
154  } else {
155  *len = got;
156  return RS_DONE;
157  }
158 }
rs_result
rs_result
Definition: librsync.h:161
trace.h
rs_file_copy_cb
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:137
RS_DONE
@ RS_DONE
Completed successfully.
Definition: librsync.h:162
librsync.h
RS_INPUT_ENDED
@ RS_INPUT_ENDED
Unexpected end of input file, perhaps due to a truncated file or dropped network connection.
Definition: librsync.h:171
RS_IO_ERROR
@ RS_IO_ERROR
Error in file or network IO.
Definition: librsync.h:168