READE update the location of the tarballs
[deb_libnfs.git] / examples / nfs-cp.c
CommitLineData
a6bc1707
RS
1/*
2 Copyright (C) by Ronnie Sahlberg <ronniesahlberg@gmail.com> 2013
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, see <http://www.gnu.org/licenses/>.
16*/
17
18#define _FILE_OFFSET_BITS 64
19#define _GNU_SOURCE
20
21#ifdef HAVE_CONFIG_H
22#include "config.h"
23#endif
24
25#ifdef AROS
26#include "aros_compat.h"
27#endif
28
29
30#ifdef WIN32
31#include "win32_compat.h"
32#else
33#include <sys/stat.h>
34#include <string.h>
35#endif
36
37#ifdef HAVE_POLL_H
38#include <poll.h>
39#endif
40
41#ifdef HAVE_UNISTD_H
42#include <unistd.h>
43#endif
44
45#include <stdio.h>
46#include <stdlib.h>
47#include <stdint.h>
48#include <sys/types.h>
49#include <fcntl.h>
50#include "libnfs-zdr.h"
51#include "libnfs.h"
52#include "libnfs-raw.h"
53#include "libnfs-raw-mount.h"
54
55struct file_context {
56 int is_nfs;
57 int fd;
58 struct nfs_context *nfs;
59 struct nfsfh *nfsfh;
60};
61
62void usage(void)
63{
64 fprintf(stderr, "Usage: nfs-cp <src> <dst>\n");
65 fprintf(stderr, "<src>,<dst> can either be a local file or "
66 "an nfs URL.\n");
67 exit(0);
68}
69
70static void
71free_file_context(struct file_context *file_context)
72{
73 if (file_context->fd != -1) {
74 close(file_context->fd);
75 }
76 if (file_context->nfsfh != NULL) {
77 nfs_close(file_context->nfs, file_context->nfsfh);
78 }
79 if (file_context->nfs != NULL) {
80 nfs_destroy_context(file_context->nfs);
81 }
82 free(file_context);
83}
84
85static int
86fstat_file(struct file_context *fc, struct stat *st)
87{
88 if (fc->is_nfs == 0) {
89 return fstat(fc->fd, st);
90 } else {
91 return nfs_fstat(fc->nfs, fc->nfsfh, st);
92 }
93}
94
95static int64_t
96file_pread(struct file_context *fc, char *buf, int64_t count, uint64_t off)
97{
98 if (fc->is_nfs == 0) {
3d574b1e
RS
99 lseek(fc->fd, off, SEEK_SET);
100 return read(fc->fd, buf, count);
a6bc1707
RS
101 } else {
102 return nfs_pread(fc->nfs, fc->nfsfh, off, count, buf);
103 }
104}
105
106static int64_t
107file_pwrite(struct file_context *fc, char *buf, int64_t count, uint64_t off)
108{
109 if (fc->is_nfs == 0) {
3d574b1e
RS
110 lseek(fc->fd, off, SEEK_SET);
111 return write(fc->fd, buf, count);
a6bc1707
RS
112 } else {
113 return nfs_pwrite(fc->nfs, fc->nfsfh, off, count, buf);
114 }
115}
116
117static struct file_context *
118open_file(const char *url, int flags)
119{
120 struct file_context *file_context;
121 char *server = NULL, *path = NULL, *file = NULL, *strp;
122
123 file_context = malloc(sizeof(struct file_context));
124 if (file_context == NULL) {
125 fprintf(stderr, "Failed to malloc file_context\n");
126 return NULL;
127 }
128 file_context->is_nfs = 0;
129 file_context->fd = -1;
130 file_context->nfs = NULL;
131 file_context->nfsfh = NULL;
132
133
134 if (strncmp(url, "nfs://", 6)) {
135 file_context->is_nfs = 0;
136 file_context->fd = open(url, flags, 0660);
137 if (file_context->fd == -1) {
138 fprintf(stderr, "Failed to open %s\n", url);
139 free_file_context(file_context);
140 return NULL;
141 }
142 return file_context;
143 }
144
145 file_context->is_nfs = 1;
146
147 file_context->nfs = nfs_init_context();
148 if (file_context->nfs == NULL) {
149 fprintf(stderr, "failed to init context\n");
150 free_file_context(file_context);
151 return NULL;
152 }
153
154 server = strdup(url + 6);
155 if (server == NULL) {
156 fprintf(stderr, "Failed to strdup server string\n");
157 free_file_context(file_context);
158 return NULL;
159 }
160 if (server[0] == '/' || server[0] == '\0') {
161 fprintf(stderr, "Invalid server string.\n");
162 free(server);
163 free_file_context(file_context);
164 return NULL;
165 }
166 strp = strchr(server, '/');
167 path = strdup(strp);
168 *strp = 0;
169 if (path == NULL) {
170 fprintf(stderr, "Invalid URL specified.\n");
171 free(server);
172 free_file_context(file_context);
173 return NULL;
174 }
175
176 strp = strrchr(path, '/');
177 if (strp == NULL) {
178 fprintf(stderr, "Invalid URL specified.\n");
179 free(path);
180 free(server);
181 free_file_context(file_context);
182 return NULL;
183 }
184 file = strdup(strp);
185 *strp = 0;
186
187 if (nfs_mount(file_context->nfs, server, path) != 0) {
188 fprintf(stderr, "Failed to mount nfs share : %s\n",
189 nfs_get_error(file_context->nfs));
190 free(file);
191 free(path);
192 free(server);
193 free_file_context(file_context);
194 return NULL;
195 }
196
197 if (flags == O_RDONLY) {
198 if (nfs_open(file_context->nfs, file, flags,
199 &file_context->nfsfh) != 0) {
200 fprintf(stderr, "Failed to open file : %s\n",
201 nfs_get_error(file_context->nfs));
202 free(file);
203 free(path);
204 free(server);
205 free_file_context(file_context);
206 return NULL;
207 }
208 } else {
209 if (nfs_creat(file_context->nfs, file, 0660,
210 &file_context->nfsfh) != 0) {
211 fprintf(stderr, "Failed to creat file %s %s\n", file,
212 nfs_get_error(file_context->nfs));
213 free(file);
214 free(path);
215 free(server);
216 free_file_context(file_context);
217 return NULL;
218 }
219 }
220
221 free(file);
222 free(path);
223 free(server);
224
225 return file_context;
226}
227
228#define BUFSIZE 1024*1024
229static char buf[BUFSIZE];
230
231int main(int argc, char *argv[])
232{
233 int ret;
234 struct stat st;
235 struct file_context *src;
236 struct file_context *dst;
237 uint64_t off;
238 int64_t count;
239
240#ifdef WIN32
241 if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) {
242 printf("Failed to start Winsock2\n");
243 return 10;
244 }
245#endif
246
247#ifdef AROS
248 aros_init_socket();
249#endif
250
251 if (argc != 3) {
252 usage();
253 }
254
255 src = open_file(argv[1], O_RDONLY);
256 if (src == NULL) {
257 fprintf(stderr, "Failed to open %s\n", argv[1]);
258 return 10;
259 }
260
261 dst = open_file(argv[2], O_WRONLY|O_CREAT|O_TRUNC);
262 if (dst == NULL) {
263 fprintf(stderr, "Failed to open %s\n", argv[2]);
264 free_file_context(src);
265 return 10;
266 }
267
268 if (fstat_file(src, &st) != 0) {
269 fprintf(stderr, "Failed to fstat source file\n");
270 free_file_context(src);
271 free_file_context(dst);
272 return 10;
273 }
274
275 off = 0;
276 while (off < st.st_size) {
277 count = st.st_size - off;
278 if (count > BUFSIZE) {
279 count = BUFSIZE;
280 }
281 count = file_pread(src, buf, count, off);
282 if (count < 0) {
283 fprintf(stderr, "Failed to read from source file\n");
284 free_file_context(src);
285 free_file_context(dst);
286 return 10;
287 }
288 count = file_pwrite(dst, buf, count, off);
289 if (count < 0) {
290 fprintf(stderr, "Failed to write to dest file\n");
291 free_file_context(src);
292 free_file_context(dst);
293 return 10;
294 }
295
296 off += count;
297 }
298 printf("copied %d bytes\n", (int)count);
299
300 free_file_context(src);
301 free_file_context(dst);
302
303 return 0;
304}