bump version to 1.8.90
[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"
67a9f57e
RS
32#pragma comment(lib, "ws2_32.lib")
33WSADATA wsaData;
a6bc1707
RS
34#else
35#include <sys/stat.h>
36#include <string.h>
37#endif
38
39#ifdef HAVE_POLL_H
40#include <poll.h>
41#endif
42
43#ifdef HAVE_UNISTD_H
44#include <unistd.h>
45#endif
46
47#include <stdio.h>
48#include <stdlib.h>
49#include <stdint.h>
50#include <sys/types.h>
51#include <fcntl.h>
52#include "libnfs-zdr.h"
53#include "libnfs.h"
54#include "libnfs-raw.h"
55#include "libnfs-raw-mount.h"
56
57struct file_context {
58 int is_nfs;
59 int fd;
60 struct nfs_context *nfs;
61 struct nfsfh *nfsfh;
82f5df21 62 struct nfs_url *url;
a6bc1707
RS
63};
64
65void usage(void)
66{
67 fprintf(stderr, "Usage: nfs-cp <src> <dst>\n");
68 fprintf(stderr, "<src>,<dst> can either be a local file or "
69 "an nfs URL.\n");
70 exit(0);
71}
72
73static void
74free_file_context(struct file_context *file_context)
75{
76 if (file_context->fd != -1) {
77 close(file_context->fd);
78 }
79 if (file_context->nfsfh != NULL) {
80 nfs_close(file_context->nfs, file_context->nfsfh);
81 }
82 if (file_context->nfs != NULL) {
83 nfs_destroy_context(file_context->nfs);
84 }
82f5df21 85 nfs_destroy_url(file_context->url);
a6bc1707
RS
86 free(file_context);
87}
88
89static int
90fstat_file(struct file_context *fc, struct stat *st)
91{
92 if (fc->is_nfs == 0) {
93 return fstat(fc->fd, st);
94 } else {
95 return nfs_fstat(fc->nfs, fc->nfsfh, st);
96 }
97}
98
99static int64_t
100file_pread(struct file_context *fc, char *buf, int64_t count, uint64_t off)
101{
102 if (fc->is_nfs == 0) {
3d574b1e
RS
103 lseek(fc->fd, off, SEEK_SET);
104 return read(fc->fd, buf, count);
a6bc1707
RS
105 } else {
106 return nfs_pread(fc->nfs, fc->nfsfh, off, count, buf);
107 }
108}
109
110static int64_t
111file_pwrite(struct file_context *fc, char *buf, int64_t count, uint64_t off)
112{
113 if (fc->is_nfs == 0) {
3d574b1e
RS
114 lseek(fc->fd, off, SEEK_SET);
115 return write(fc->fd, buf, count);
a6bc1707
RS
116 } else {
117 return nfs_pwrite(fc->nfs, fc->nfsfh, off, count, buf);
118 }
119}
120
121static struct file_context *
122open_file(const char *url, int flags)
123{
124 struct file_context *file_context;
a6bc1707
RS
125
126 file_context = malloc(sizeof(struct file_context));
127 if (file_context == NULL) {
128 fprintf(stderr, "Failed to malloc file_context\n");
129 return NULL;
130 }
131 file_context->is_nfs = 0;
132 file_context->fd = -1;
133 file_context->nfs = NULL;
134 file_context->nfsfh = NULL;
135
a6bc1707
RS
136 if (strncmp(url, "nfs://", 6)) {
137 file_context->is_nfs = 0;
138 file_context->fd = open(url, flags, 0660);
139 if (file_context->fd == -1) {
140 fprintf(stderr, "Failed to open %s\n", url);
141 free_file_context(file_context);
142 return NULL;
143 }
144 return file_context;
145 }
146
147 file_context->is_nfs = 1;
148
149 file_context->nfs = nfs_init_context();
150 if (file_context->nfs == NULL) {
151 fprintf(stderr, "failed to init context\n");
152 free_file_context(file_context);
153 return NULL;
154 }
155
82f5df21
PL
156 file_context->url = nfs_parse_url_full(file_context->nfs, url);
157 if (file_context->url == NULL) {
158 fprintf(stderr, "%s\n", nfs_get_error(file_context->nfs));
a6bc1707
RS
159 free_file_context(file_context);
160 return NULL;
161 }
162
82f5df21
PL
163 if (nfs_mount(file_context->nfs, file_context->url->server,
164 file_context->url->path) != 0) {
165 fprintf(stderr, "Failed to mount nfs share : %s\n",
a6bc1707 166 nfs_get_error(file_context->nfs));
a6bc1707
RS
167 free_file_context(file_context);
168 return NULL;
169 }
170
171 if (flags == O_RDONLY) {
82f5df21 172 if (nfs_open(file_context->nfs, file_context->url->file, flags,
a6bc1707 173 &file_context->nfsfh) != 0) {
82f5df21
PL
174 fprintf(stderr, "Failed to open file %s: %s\n",
175 file_context->url->file,
a6bc1707 176 nfs_get_error(file_context->nfs));
a6bc1707
RS
177 free_file_context(file_context);
178 return NULL;
179 }
180 } else {
82f5df21 181 if (nfs_creat(file_context->nfs, file_context->url->file, 0660,
a6bc1707 182 &file_context->nfsfh) != 0) {
82f5df21
PL
183 fprintf(stderr, "Failed to creat file %s: %s\n",
184 file_context->url->file,
a6bc1707 185 nfs_get_error(file_context->nfs));
a6bc1707
RS
186 free_file_context(file_context);
187 return NULL;
188 }
189 }
a6bc1707
RS
190 return file_context;
191}
192
193#define BUFSIZE 1024*1024
194static char buf[BUFSIZE];
195
196int main(int argc, char *argv[])
197{
198 int ret;
199 struct stat st;
200 struct file_context *src;
201 struct file_context *dst;
202 uint64_t off;
203 int64_t count;
204
205#ifdef WIN32
206 if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) {
207 printf("Failed to start Winsock2\n");
208 return 10;
209 }
210#endif
211
212#ifdef AROS
213 aros_init_socket();
214#endif
215
216 if (argc != 3) {
217 usage();
218 }
219
220 src = open_file(argv[1], O_RDONLY);
221 if (src == NULL) {
222 fprintf(stderr, "Failed to open %s\n", argv[1]);
223 return 10;
224 }
225
226 dst = open_file(argv[2], O_WRONLY|O_CREAT|O_TRUNC);
227 if (dst == NULL) {
228 fprintf(stderr, "Failed to open %s\n", argv[2]);
229 free_file_context(src);
230 return 10;
231 }
232
233 if (fstat_file(src, &st) != 0) {
234 fprintf(stderr, "Failed to fstat source file\n");
235 free_file_context(src);
236 free_file_context(dst);
237 return 10;
238 }
239
240 off = 0;
241 while (off < st.st_size) {
242 count = st.st_size - off;
243 if (count > BUFSIZE) {
244 count = BUFSIZE;
245 }
246 count = file_pread(src, buf, count, off);
247 if (count < 0) {
248 fprintf(stderr, "Failed to read from source file\n");
249 free_file_context(src);
250 free_file_context(dst);
251 return 10;
252 }
253 count = file_pwrite(dst, buf, count, off);
254 if (count < 0) {
255 fprintf(stderr, "Failed to write to dest file\n");
256 free_file_context(src);
257 free_file_context(dst);
258 return 10;
259 }
260
261 off += count;
262 }
767a479c 263 printf("copied %d bytes\n", (int)off);
a6bc1707
RS
264
265 free_file_context(src);
266 free_file_context(dst);
267
268 return 0;
269}