[win32] - fixed bad number casting when using libnfs on 64bit win8 systems - force...
[deb_libnfs.git] / lib / libnfs-sync.c
... / ...
CommitLineData
1/*
2 Copyright (C) 2010 by Ronnie Sahlberg <ronniesahlberg@gmail.com>
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program; if not, see <http://www.gnu.org/licenses/>.
16*/
17/*
18 * High level api to nfs filesystems
19 */
20#ifdef HAVE_CONFIG_H
21#include "config.h"
22#endif
23
24#ifdef AROS
25#include "aros_compat.h"
26#endif
27
28#ifdef WIN32
29#include "win32_compat.h"
30#endif
31
32#ifdef HAVE_NET_IF_H
33#include <net/if.h>
34#endif
35
36#ifdef ANDROID
37#define statvfs statfs
38#endif
39
40#ifdef HAVE_SYS_VFS_H
41#include <sys/vfs.h>
42#endif
43
44#ifdef HAVE_SYS_STATVFS_H
45#include <sys/statvfs.h>
46#endif
47
48#ifdef HAVE_SYS_IOCTL_H
49#include <sys/ioctl.h>
50#endif
51
52#ifdef HAVE_SYS_SOCKET_H
53#include <sys/socket.h>
54#endif
55
56#ifdef HAVE_POLL_H
57#include <poll.h>
58#endif
59
60#ifdef HAVE_NETDB_H
61#include <netdb.h>
62#endif
63
64#ifdef HAVE_UNISTD_H
65#include <unistd.h>
66#endif
67
68#ifdef HAVE_NETINET_IN_H
69#include <netinet/in.h>
70#endif
71
72#ifdef HAVE_STRINGS_H
73#include <strings.h>
74#endif
75
76#include <stdio.h>
77#include <stdlib.h>
78#include <string.h>
79#include <assert.h>
80#include <sys/types.h>
81#include <sys/stat.h>
82#include <fcntl.h>
83#include <errno.h>
84
85#ifdef HAVE_SYS_SOCKIO_H
86#include <sys/sockio.h>
87#endif
88
89#include "libnfs-zdr.h"
90#include "libnfs.h"
91#include "libnfs-raw.h"
92#include "libnfs-raw-mount.h"
93#include "libnfs-raw-nfs.h"
94#include "libnfs-private.h"
95
96struct sync_cb_data {
97 int is_finished;
98 int status;
99 uint64_t offset;
100 void *return_data;
101 int return_int;
102};
103
104
105static void wait_for_reply(struct rpc_context *rpc, struct sync_cb_data *cb_data)
106{
107 struct pollfd pfd;
108
109 assert(rpc->magic == RPC_CONTEXT_MAGIC);
110
111 while (!cb_data->is_finished) {
112
113 pfd.fd = rpc_get_fd(rpc);
114 pfd.events = rpc_which_events(rpc);
115 if (poll(&pfd, 1, -1) < 0) {
116 rpc_set_error(rpc, "Poll failed");
117 cb_data->status = -EIO;
118 break;
119 }
120 if (rpc_service(rpc, pfd.revents) < 0) {
121 rpc_set_error(rpc, "rpc_service failed");
122 cb_data->status = -EIO;
123 break;
124 }
125 if (rpc_get_fd(rpc) == -1) {
126 rpc_set_error(rpc, "Socket closed\n");
127 break;
128 }
129 }
130}
131
132static void wait_for_nfs_reply(struct nfs_context *nfs, struct sync_cb_data *cb_data)
133{
134 struct pollfd pfd;
135
136 while (!cb_data->is_finished) {
137
138 pfd.fd = nfs_get_fd(nfs);
139 pfd.events = nfs_which_events(nfs);
140 if (poll(&pfd, 1, -1) < 0) {
141 nfs_set_error(nfs, "Poll failed");
142 cb_data->status = -EIO;
143 break;
144 }
145 if (nfs_service(nfs, pfd.revents) < 0) {
146 nfs_set_error(nfs, "nfs_service failed");
147 cb_data->status = -EIO;
148 break;
149 }
150 }
151}
152
153
154
155
156
157
158/*
159 * connect to the server and mount the export
160 */
161static void mount_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
162{
163 struct sync_cb_data *cb_data = private_data;
164
165 cb_data->is_finished = 1;
166 cb_data->status = status;
167
168 if (status < 0) {
169 nfs_set_error(nfs, "mount/mnt call failed with \"%s\"", (char *)data);
170 return;
171 }
172}
173
174int nfs_mount(struct nfs_context *nfs, const char *server, const char *export)
175{
176 struct sync_cb_data cb_data;
177 struct rpc_context *rpc = nfs_get_rpc_context(nfs);
178
179 assert(rpc->magic == RPC_CONTEXT_MAGIC);
180
181 cb_data.is_finished = 0;
182
183 if (nfs_mount_async(nfs, server, export, mount_cb, &cb_data) != 0) {
184 nfs_set_error(nfs, "nfs_mount_async failed");
185 return -1;
186 }
187
188 wait_for_nfs_reply(nfs, &cb_data);
189
190 /* Dont want any more callbacks even if the socket is closed */
191 rpc->connect_cb = NULL;
192
193 return cb_data.status;
194}
195
196
197/*
198 * stat()
199 */
200static void stat_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
201{
202 struct sync_cb_data *cb_data = private_data;
203
204 cb_data->is_finished = 1;
205 cb_data->status = status;
206
207 if (status < 0) {
208 nfs_set_error(nfs, "stat call failed with \"%s\"", (char *)data);
209 return;
210 }
211#ifdef WIN32
212 memcpy(cb_data->return_data, data, sizeof(struct __stat64));
213#else
214 memcpy(cb_data->return_data, data, sizeof(struct stat));
215#endif
216}
217
218#ifdef WIN32
219int nfs_stat(struct nfs_context *nfs, const char *path, struct __stat64 *st)
220#else
221int nfs_stat(struct nfs_context *nfs, const char *path, struct stat *st)
222#endif
223{
224 struct sync_cb_data cb_data;
225
226 cb_data.is_finished = 0;
227 cb_data.return_data = st;
228
229 if (nfs_stat_async(nfs, path, stat_cb, &cb_data) != 0) {
230 nfs_set_error(nfs, "nfs_stat_async failed");
231 return -1;
232 }
233
234 wait_for_nfs_reply(nfs, &cb_data);
235
236 return cb_data.status;
237}
238
239
240
241
242/*
243 * open()
244 */
245static void open_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
246{
247 struct sync_cb_data *cb_data = private_data;
248 struct nfsfh *fh, **nfsfh;
249
250 cb_data->is_finished = 1;
251 cb_data->status = status;
252
253 if (status < 0) {
254 nfs_set_error(nfs, "open call failed with \"%s\"", (char *)data);
255 return;
256 }
257
258 fh = data;
259 nfsfh = cb_data->return_data;
260 *nfsfh = fh;
261}
262
263int nfs_open(struct nfs_context *nfs, const char *path, int mode, struct nfsfh **nfsfh)
264{
265 struct sync_cb_data cb_data;
266
267 cb_data.is_finished = 0;
268 cb_data.return_data = nfsfh;
269
270 if (nfs_open_async(nfs, path, mode, open_cb, &cb_data) != 0) {
271 nfs_set_error(nfs, "nfs_open_async failed");
272 return -1;
273 }
274
275 wait_for_nfs_reply(nfs, &cb_data);
276
277 return cb_data.status;
278}
279
280
281
282
283/*
284 * pread()
285 */
286static void pread_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
287{
288 struct sync_cb_data *cb_data = private_data;
289 char *buffer;
290 cb_data->is_finished = 1;
291 cb_data->status = status;
292
293 if (status < 0) {
294 nfs_set_error(nfs, "pread call failed with \"%s\"", (char *)data);
295 return;
296 }
297
298 buffer = cb_data->return_data;
299 memcpy(buffer, (char *)data, status);
300}
301
302int nfs_pread(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, uint64_t count, char *buffer)
303{
304 struct sync_cb_data cb_data;
305
306 cb_data.is_finished = 0;
307 cb_data.return_data = buffer;
308
309 if (nfs_pread_async(nfs, nfsfh, offset, count, pread_cb, &cb_data) != 0) {
310 nfs_set_error(nfs, "nfs_pread_async failed");
311 return -1;
312 }
313
314 wait_for_nfs_reply(nfs, &cb_data);
315
316 return cb_data.status;
317}
318
319/*
320 * read()
321 */
322int nfs_read(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t count, char *buffer)
323{
324 return nfs_pread(nfs, nfsfh, nfs_get_current_offset(nfsfh), count, buffer);
325}
326
327/*
328 * close()
329 */
330static void close_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
331{
332 struct sync_cb_data *cb_data = private_data;
333 cb_data->is_finished = 1;
334 cb_data->status = status;
335
336 if (status < 0) {
337 nfs_set_error(nfs, "close call failed with \"%s\"", (char *)data);
338 return;
339 }
340}
341
342int nfs_close(struct nfs_context *nfs, struct nfsfh *nfsfh)
343{
344 struct sync_cb_data cb_data;
345
346 cb_data.is_finished = 0;
347
348 if (nfs_close_async(nfs, nfsfh, close_cb, &cb_data) != 0) {
349 nfs_set_error(nfs, "nfs_close_async failed");
350 return -1;
351 }
352
353 wait_for_nfs_reply(nfs, &cb_data);
354
355 return cb_data.status;
356}
357
358
359
360
361/*
362 * fstat()
363 */
364int nfs_fstat(struct nfs_context *nfs, struct nfsfh *nfsfh, struct stat *st)
365{
366 struct sync_cb_data cb_data;
367
368 cb_data.is_finished = 0;
369 cb_data.return_data = st;
370
371 if (nfs_fstat_async(nfs, nfsfh, stat_cb, &cb_data) != 0) {
372 nfs_set_error(nfs, "nfs_fstat_async failed");
373 return -1;
374 }
375
376 wait_for_nfs_reply(nfs, &cb_data);
377
378 return cb_data.status;
379}
380
381
382/*
383 * pwrite()
384 */
385static void pwrite_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
386{
387 struct sync_cb_data *cb_data = private_data;
388 cb_data->is_finished = 1;
389 cb_data->status = status;
390
391 if (status < 0) {
392 nfs_set_error(nfs, "pwrite call failed with \"%s\"", (char *)data);
393 return;
394 }
395}
396
397int nfs_pwrite(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, uint64_t count, char *buf)
398{
399 struct sync_cb_data cb_data;
400
401 cb_data.is_finished = 0;
402
403 if (nfs_pwrite_async(nfs, nfsfh, offset, count, buf, pwrite_cb, &cb_data) != 0) {
404 nfs_set_error(nfs, "nfs_pwrite_async failed");
405 return -1;
406 }
407
408 wait_for_nfs_reply(nfs, &cb_data);
409
410 return cb_data.status;
411}
412
413/*
414 * write()
415 */
416int nfs_write(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t count, char *buf)
417{
418 return nfs_pwrite(nfs, nfsfh, nfs_get_current_offset(nfsfh), count, buf);
419}
420
421
422/*
423 * fsync()
424 */
425static void fsync_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
426{
427 struct sync_cb_data *cb_data = private_data;
428 cb_data->is_finished = 1;
429 cb_data->status = status;
430
431 if (status < 0) {
432 nfs_set_error(nfs, "fsync call failed with \"%s\"", (char *)data);
433 return;
434 }
435}
436
437int nfs_fsync(struct nfs_context *nfs, struct nfsfh *nfsfh)
438{
439 struct sync_cb_data cb_data;
440
441 cb_data.is_finished = 0;
442
443 if (nfs_fsync_async(nfs, nfsfh, fsync_cb, &cb_data) != 0) {
444 nfs_set_error(nfs, "nfs_fsync_async failed");
445 return -1;
446 }
447
448 wait_for_nfs_reply(nfs, &cb_data);
449
450 return cb_data.status;
451}
452
453
454
455
456/*
457 * ftruncate()
458 */
459static void ftruncate_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
460{
461 struct sync_cb_data *cb_data = private_data;
462 cb_data->is_finished = 1;
463 cb_data->status = status;
464
465 if (status < 0) {
466 nfs_set_error(nfs, "ftruncate call failed with \"%s\"", (char *)data);
467 return;
468 }
469}
470
471int nfs_ftruncate(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t length)
472{
473 struct sync_cb_data cb_data;
474
475 cb_data.is_finished = 0;
476
477 if (nfs_ftruncate_async(nfs, nfsfh, length, ftruncate_cb, &cb_data) != 0) {
478 nfs_set_error(nfs, "nfs_ftruncate_async failed");
479 return -1;
480 }
481
482 wait_for_nfs_reply(nfs, &cb_data);
483
484 return cb_data.status;
485}
486
487
488
489/*
490 * truncate()
491 */
492static void truncate_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
493{
494 struct sync_cb_data *cb_data = private_data;
495 cb_data->is_finished = 1;
496 cb_data->status = status;
497
498 if (status < 0) {
499 nfs_set_error(nfs, "truncate call failed with \"%s\"", (char *)data);
500 return;
501 }
502}
503
504int nfs_truncate(struct nfs_context *nfs, const char *path, uint64_t length)
505{
506 struct sync_cb_data cb_data;
507
508 cb_data.is_finished = 0;
509
510 if (nfs_truncate_async(nfs, path, length, truncate_cb, &cb_data) != 0) {
511 nfs_set_error(nfs, "nfs_ftruncate_async failed");
512 return -1;
513 }
514
515 wait_for_nfs_reply(nfs, &cb_data);
516
517 return cb_data.status;
518}
519
520
521
522
523
524/*
525 * mkdir()
526 */
527static void mkdir_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
528{
529 struct sync_cb_data *cb_data = private_data;
530 cb_data->is_finished = 1;
531 cb_data->status = status;
532
533 if (status < 0) {
534 nfs_set_error(nfs, "mkdir call failed with \"%s\"", (char *)data);
535 return;
536 }
537}
538
539int nfs_mkdir(struct nfs_context *nfs, const char *path)
540{
541 struct sync_cb_data cb_data;
542
543 cb_data.is_finished = 0;
544
545 if (nfs_mkdir_async(nfs, path, mkdir_cb, &cb_data) != 0) {
546 nfs_set_error(nfs, "nfs_mkdir_async failed");
547 return -1;
548 }
549
550 wait_for_nfs_reply(nfs, &cb_data);
551
552 return cb_data.status;
553}
554
555
556
557
558
559/*
560 * rmdir()
561 */
562static void rmdir_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
563{
564 struct sync_cb_data *cb_data = private_data;
565 cb_data->is_finished = 1;
566 cb_data->status = status;
567
568 if (status < 0) {
569 nfs_set_error(nfs, "rmdir call failed with \"%s\"", (char *)data);
570 return;
571 }
572}
573
574int nfs_rmdir(struct nfs_context *nfs, const char *path)
575{
576 struct sync_cb_data cb_data;
577
578 cb_data.is_finished = 0;
579
580 if (nfs_rmdir_async(nfs, path, rmdir_cb, &cb_data) != 0) {
581 nfs_set_error(nfs, "nfs_rmdir_async failed");
582 return -1;
583 }
584
585 wait_for_nfs_reply(nfs, &cb_data);
586
587 return cb_data.status;
588}
589
590
591
592/*
593 * creat()
594 */
595static void creat_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
596{
597 struct sync_cb_data *cb_data = private_data;
598 struct nfsfh *fh, **nfsfh;
599
600 cb_data->is_finished = 1;
601 cb_data->status = status;
602
603 if (status < 0) {
604 nfs_set_error(nfs, "creat call failed with \"%s\"", (char *)data);
605 return;
606 }
607
608 fh = data;
609 nfsfh = cb_data->return_data;
610 *nfsfh = fh;
611}
612
613int nfs_creat(struct nfs_context *nfs, const char *path, int mode, struct nfsfh **nfsfh)
614{
615 struct sync_cb_data cb_data;
616
617 cb_data.is_finished = 0;
618 cb_data.return_data = nfsfh;
619
620 if (nfs_creat_async(nfs, path, mode, creat_cb, &cb_data) != 0) {
621 nfs_set_error(nfs, "nfs_creat_async failed");
622 return -1;
623 }
624
625 wait_for_nfs_reply(nfs, &cb_data);
626
627 return cb_data.status;
628}
629
630/*
631 * mknod()
632 */
633static void mknod_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
634{
635 struct sync_cb_data *cb_data = private_data;
636
637 cb_data->is_finished = 1;
638 cb_data->status = status;
639
640 if (status < 0) {
641 nfs_set_error(nfs, "mknod call failed with \"%s\"", (char *)data);
642 return;
643 }
644}
645
646int nfs_mknod(struct nfs_context *nfs, const char *path, int mode, int dev)
647{
648 struct sync_cb_data cb_data;
649
650 cb_data.is_finished = 0;
651
652 if (nfs_mknod_async(nfs, path, mode, dev, mknod_cb, &cb_data) != 0) {
653 nfs_set_error(nfs, "nfs_creat_async failed");
654 return -1;
655 }
656
657 wait_for_nfs_reply(nfs, &cb_data);
658
659 return cb_data.status;
660}
661
662
663/*
664 * unlink()
665 */
666static void unlink_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
667{
668 struct sync_cb_data *cb_data = private_data;
669
670 cb_data->is_finished = 1;
671 cb_data->status = status;
672
673 if (status < 0) {
674 nfs_set_error(nfs, "unlink call failed with \"%s\"", (char *)data);
675 return;
676 }
677}
678
679int nfs_unlink(struct nfs_context *nfs, const char *path)
680{
681 struct sync_cb_data cb_data;
682
683 cb_data.is_finished = 0;
684
685 if (nfs_unlink_async(nfs, path, unlink_cb, &cb_data) != 0) {
686 nfs_set_error(nfs, "nfs_unlink_async failed");
687 return -1;
688 }
689
690 wait_for_nfs_reply(nfs, &cb_data);
691
692 return cb_data.status;
693}
694
695
696
697/*
698 * opendir()
699 */
700static void opendir_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
701{
702 struct sync_cb_data *cb_data = private_data;
703 struct nfsdir *dir, **nfsdir;
704
705 cb_data->is_finished = 1;
706 cb_data->status = status;
707
708 if (status < 0) {
709 nfs_set_error(nfs, "opendir call failed with \"%s\"", (char *)data);
710 return;
711 }
712
713 dir = data;
714 nfsdir = cb_data->return_data;
715 *nfsdir = dir;
716}
717
718int nfs_opendir(struct nfs_context *nfs, const char *path, struct nfsdir **nfsdir)
719{
720 struct sync_cb_data cb_data;
721
722 cb_data.is_finished = 0;
723 cb_data.return_data = nfsdir;
724
725 if (nfs_opendir_async(nfs, path, opendir_cb, &cb_data) != 0) {
726 nfs_set_error(nfs, "nfs_opendir_async failed");
727 return -1;
728 }
729
730 wait_for_nfs_reply(nfs, &cb_data);
731
732 return cb_data.status;
733}
734
735
736/*
737 * lseek()
738 */
739static void lseek_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
740{
741 struct sync_cb_data *cb_data = private_data;
742
743 cb_data->is_finished = 1;
744 cb_data->status = status;
745
746 if (status < 0) {
747 nfs_set_error(nfs, "lseek call failed with \"%s\"", (char *)data);
748 return;
749 }
750
751 if (cb_data->return_data != NULL) {
752 memcpy(cb_data->return_data, data, sizeof(uint64_t));
753 }
754}
755
756int nfs_lseek(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, int whence, uint64_t *current_offset)
757{
758 struct sync_cb_data cb_data;
759
760 cb_data.is_finished = 0;
761 cb_data.return_data = current_offset;
762
763 if (nfs_lseek_async(nfs, nfsfh, offset, whence, lseek_cb, &cb_data) != 0) {
764 nfs_set_error(nfs, "nfs_lseek_async failed");
765 return -1;
766 }
767
768 wait_for_nfs_reply(nfs, &cb_data);
769
770 return cb_data.status;
771}
772
773
774
775/*
776 * statvfs()
777 */
778static void statvfs_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
779{
780 struct sync_cb_data *cb_data = private_data;
781
782 cb_data->is_finished = 1;
783 cb_data->status = status;
784
785 if (status < 0) {
786 nfs_set_error(nfs, "statvfs call failed with \"%s\"", (char *)data);
787 return;
788 }
789
790 memcpy(cb_data->return_data, data, sizeof(struct statvfs));
791}
792
793int nfs_statvfs(struct nfs_context *nfs, const char *path, struct statvfs *svfs)
794{
795 struct sync_cb_data cb_data;
796
797 cb_data.is_finished = 0;
798 cb_data.return_data = svfs;
799
800 if (nfs_statvfs_async(nfs, path, statvfs_cb, &cb_data) != 0) {
801 nfs_set_error(nfs, "nfs_statvfs_async failed");
802 return -1;
803 }
804
805 wait_for_nfs_reply(nfs, &cb_data);
806
807 return cb_data.status;
808}
809
810
811
812
813
814/*
815 * readlink()
816 */
817static void readlink_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
818{
819 struct sync_cb_data *cb_data = private_data;
820
821 cb_data->is_finished = 1;
822 cb_data->status = status;
823
824 if (status < 0) {
825 nfs_set_error(nfs, "readlink call failed with \"%s\"", (char *)data);
826 return;
827 }
828
829 if (strlen(data) > (size_t)cb_data->return_int) {
830 nfs_set_error(nfs, "Too small buffer for readlink");
831 cb_data->status = -ENAMETOOLONG;
832 return;
833 }
834
835 memcpy(cb_data->return_data, data, strlen(data)+1);
836}
837
838int nfs_readlink(struct nfs_context *nfs, const char *path, char *buf, int bufsize)
839{
840 struct sync_cb_data cb_data;
841
842 cb_data.is_finished = 0;
843 cb_data.return_data = buf;
844 cb_data.return_int = bufsize;
845
846 if (nfs_readlink_async(nfs, path, readlink_cb, &cb_data) != 0) {
847 nfs_set_error(nfs, "nfs_readlink_async failed");
848 return -1;
849 }
850
851 wait_for_nfs_reply(nfs, &cb_data);
852
853 return cb_data.status;
854}
855
856
857
858/*
859 * chmod()
860 */
861static void chmod_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
862{
863 struct sync_cb_data *cb_data = private_data;
864
865 cb_data->is_finished = 1;
866 cb_data->status = status;
867
868 if (status < 0) {
869 nfs_set_error(nfs, "chmod call failed with \"%s\"", (char *)data);
870 return;
871 }
872}
873
874int nfs_chmod(struct nfs_context *nfs, const char *path, int mode)
875{
876 struct sync_cb_data cb_data;
877
878 cb_data.is_finished = 0;
879
880 if (nfs_chmod_async(nfs, path, mode, chmod_cb, &cb_data) != 0) {
881 nfs_set_error(nfs, "nfs_chmod_async failed");
882 return -1;
883 }
884
885 wait_for_nfs_reply(nfs, &cb_data);
886
887 return cb_data.status;
888}
889
890
891
892
893/*
894 * fchmod()
895 */
896static void fchmod_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
897{
898 struct sync_cb_data *cb_data = private_data;
899
900 cb_data->is_finished = 1;
901 cb_data->status = status;
902
903 if (status < 0) {
904 nfs_set_error(nfs, "fchmod call failed with \"%s\"", (char *)data);
905 return;
906 }
907}
908
909int nfs_fchmod(struct nfs_context *nfs, struct nfsfh *nfsfh, int mode)
910{
911 struct sync_cb_data cb_data;
912
913 cb_data.is_finished = 0;
914
915 if (nfs_fchmod_async(nfs, nfsfh, mode, fchmod_cb, &cb_data) != 0) {
916 nfs_set_error(nfs, "nfs_fchmod_async failed");
917 return -1;
918 }
919
920 wait_for_nfs_reply(nfs, &cb_data);
921
922 return cb_data.status;
923}
924
925
926
927
928/*
929 * chown()
930 */
931static void chown_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
932{
933 struct sync_cb_data *cb_data = private_data;
934
935 cb_data->is_finished = 1;
936 cb_data->status = status;
937
938 if (status < 0) {
939 nfs_set_error(nfs, "chown call failed with \"%s\"", (char *)data);
940 return;
941 }
942}
943
944int nfs_chown(struct nfs_context *nfs, const char *path, int uid, int gid)
945{
946 struct sync_cb_data cb_data;
947
948 cb_data.is_finished = 0;
949
950 if (nfs_chown_async(nfs, path, uid, gid, chown_cb, &cb_data) != 0) {
951 nfs_set_error(nfs, "nfs_chown_async failed");
952 return -1;
953 }
954
955 wait_for_nfs_reply(nfs, &cb_data);
956
957 return cb_data.status;
958}
959
960/*
961 * fchown()
962 */
963static void fchown_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
964{
965 struct sync_cb_data *cb_data = private_data;
966
967 cb_data->is_finished = 1;
968 cb_data->status = status;
969
970 if (status < 0) {
971 nfs_set_error(nfs, "fchown call failed with \"%s\"", (char *)data);
972 return;
973 }
974}
975
976int nfs_fchown(struct nfs_context *nfs, struct nfsfh *nfsfh, int uid, int gid)
977{
978 struct sync_cb_data cb_data;
979
980 cb_data.is_finished = 0;
981
982 if (nfs_fchown_async(nfs, nfsfh, uid, gid, fchown_cb, &cb_data) != 0) {
983 nfs_set_error(nfs, "nfs_fchown_async failed");
984 return -1;
985 }
986
987 wait_for_nfs_reply(nfs, &cb_data);
988
989 return cb_data.status;
990}
991
992
993
994/*
995 * utimes()
996 */
997static void utimes_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
998{
999 struct sync_cb_data *cb_data = private_data;
1000
1001 cb_data->is_finished = 1;
1002 cb_data->status = status;
1003
1004 if (status < 0) {
1005 nfs_set_error(nfs, "utimes call failed with \"%s\"", (char *)data);
1006 return;
1007 }
1008}
1009
1010int nfs_utimes(struct nfs_context *nfs, const char *path, struct timeval *times)
1011{
1012 struct sync_cb_data cb_data;
1013
1014 cb_data.is_finished = 0;
1015
1016 if (nfs_utimes_async(nfs, path, times, utimes_cb, &cb_data) != 0) {
1017 nfs_set_error(nfs, "nfs_utimes_async failed");
1018 return -1;
1019 }
1020
1021 wait_for_nfs_reply(nfs, &cb_data);
1022
1023 return cb_data.status;
1024}
1025
1026
1027
1028/*
1029 * utime()
1030 */
1031static void utime_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
1032{
1033 struct sync_cb_data *cb_data = private_data;
1034
1035 cb_data->is_finished = 1;
1036 cb_data->status = status;
1037
1038 if (status < 0) {
1039 nfs_set_error(nfs, "utime call failed with \"%s\"", (char *)data);
1040 return;
1041 }
1042}
1043
1044int nfs_utime(struct nfs_context *nfs, const char *path, struct utimbuf *times)
1045{
1046 struct sync_cb_data cb_data;
1047
1048 cb_data.is_finished = 0;
1049
1050 if (nfs_utime_async(nfs, path, times, utime_cb, &cb_data) != 0) {
1051 nfs_set_error(nfs, "nfs_utimes_async failed");
1052 return -1;
1053 }
1054
1055 wait_for_nfs_reply(nfs, &cb_data);
1056
1057 return cb_data.status;
1058}
1059
1060
1061
1062
1063/*
1064 * access()
1065 */
1066static void access_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
1067{
1068 struct sync_cb_data *cb_data = private_data;
1069
1070 cb_data->is_finished = 1;
1071 cb_data->status = status;
1072
1073 if (status < 0) {
1074 nfs_set_error(nfs, "access call failed with \"%s\"", (char *)data);
1075 return;
1076 }
1077}
1078
1079int nfs_access(struct nfs_context *nfs, const char *path, int mode)
1080{
1081 struct sync_cb_data cb_data;
1082
1083 cb_data.is_finished = 0;
1084
1085 if (nfs_access_async(nfs, path, mode, access_cb, &cb_data) != 0) {
1086 nfs_set_error(nfs, "nfs_access_async failed");
1087 return -1;
1088 }
1089
1090 wait_for_nfs_reply(nfs, &cb_data);
1091
1092 return cb_data.status;
1093}
1094
1095
1096
1097/*
1098 * symlink()
1099 */
1100static void symlink_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
1101{
1102 struct sync_cb_data *cb_data = private_data;
1103
1104 cb_data->is_finished = 1;
1105 cb_data->status = status;
1106
1107 if (status < 0) {
1108 nfs_set_error(nfs, "symlink call failed with \"%s\"", (char *)data);
1109 return;
1110 }
1111}
1112
1113int nfs_symlink(struct nfs_context *nfs, const char *oldpath, const char *newpath)
1114{
1115 struct sync_cb_data cb_data;
1116
1117 cb_data.is_finished = 0;
1118
1119 if (nfs_symlink_async(nfs, oldpath, newpath, symlink_cb, &cb_data) != 0) {
1120 nfs_set_error(nfs, "nfs_symlink_async failed");
1121 return -1;
1122 }
1123
1124 wait_for_nfs_reply(nfs, &cb_data);
1125
1126 return cb_data.status;
1127}
1128
1129
1130
1131/*
1132 * rename()
1133 */
1134static void rename_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
1135{
1136 struct sync_cb_data *cb_data = private_data;
1137
1138 cb_data->is_finished = 1;
1139 cb_data->status = status;
1140
1141 if (status < 0) {
1142 nfs_set_error(nfs, "rename call failed with \"%s\"", (char *)data);
1143 return;
1144 }
1145}
1146
1147int nfs_rename(struct nfs_context *nfs, const char *oldpath, const char *newpath)
1148{
1149 struct sync_cb_data cb_data;
1150
1151 cb_data.is_finished = 0;
1152
1153 if (nfs_rename_async(nfs, oldpath, newpath, rename_cb, &cb_data) != 0) {
1154 nfs_set_error(nfs, "nfs_rename_async failed");
1155 return -1;
1156 }
1157
1158 wait_for_nfs_reply(nfs, &cb_data);
1159
1160 return cb_data.status;
1161}
1162
1163
1164
1165/*
1166 * link()
1167 */
1168static void link_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
1169{
1170 struct sync_cb_data *cb_data = private_data;
1171
1172 cb_data->is_finished = 1;
1173 cb_data->status = status;
1174
1175 if (status < 0) {
1176 nfs_set_error(nfs, "link call failed with \"%s\"", (char *)data);
1177 return;
1178 }
1179}
1180
1181int nfs_link(struct nfs_context *nfs, const char *oldpath, const char *newpath)
1182{
1183 struct sync_cb_data cb_data;
1184
1185 cb_data.is_finished = 0;
1186
1187 if (nfs_link_async(nfs, oldpath, newpath, link_cb, &cb_data) != 0) {
1188 nfs_set_error(nfs, "nfs_link_async failed");
1189 return -1;
1190 }
1191
1192 wait_for_nfs_reply(nfs, &cb_data);
1193
1194 return cb_data.status;
1195}
1196
1197void mount_getexports_cb(struct rpc_context *mount_context, int status, void *data, void *private_data)
1198{
1199 struct sync_cb_data *cb_data = private_data;
1200 exports export;
1201
1202 assert(mount_context->magic == RPC_CONTEXT_MAGIC);
1203
1204 cb_data->is_finished = 1;
1205 cb_data->status = status;
1206 cb_data->return_data = NULL;
1207
1208 if (status != 0) {
1209 rpc_set_error(mount_context, "mount/export call failed with \"%s\"", (char *)data);
1210 return;
1211 }
1212
1213 export = *(exports *)data;
1214 while (export != NULL) {
1215 exports new_export;
1216
1217 new_export = malloc(sizeof(*new_export));
1218 memset(new_export, 0, sizeof(*new_export));
1219 new_export->ex_dir = strdup(export->ex_dir);
1220 new_export->ex_next = cb_data->return_data;
1221
1222 cb_data->return_data = new_export;
1223
1224 export = export->ex_next;
1225 }
1226}
1227
1228struct exportnode *mount_getexports(const char *server)
1229{
1230 struct sync_cb_data cb_data;
1231 struct rpc_context *rpc;
1232
1233
1234 cb_data.is_finished = 0;
1235 cb_data.return_data = NULL;
1236
1237 rpc = rpc_init_context();
1238 if (mount_getexports_async(rpc, server, mount_getexports_cb, &cb_data) != 0) {
1239 rpc_destroy_context(rpc);
1240 return NULL;
1241 }
1242
1243 wait_for_reply(rpc, &cb_data);
1244 rpc_destroy_context(rpc);
1245
1246 return cb_data.return_data;
1247}
1248
1249void mount_free_export_list(struct exportnode *exports)
1250{
1251 struct exportnode *tmp;
1252
1253 while ((tmp = exports)) {
1254 exports = exports->ex_next;
1255 free(tmp->ex_dir);
1256 free(tmp);
1257 }
1258}
1259
1260
1261
1262void free_nfs_srvr_list(struct nfs_server_list *srv)
1263{
1264 while (srv != NULL) {
1265 struct nfs_server_list *next = srv->next;
1266
1267 free(srv->addr);
1268 free(srv);
1269 srv = next;
1270 }
1271}
1272
1273struct nfs_list_data {
1274 int status;
1275 struct nfs_server_list *srvrs;
1276};
1277
1278void callit_cb(struct rpc_context *rpc, int status, void *data _U_, void *private_data)
1279{
1280 struct nfs_list_data *srv_data = private_data;
1281 struct sockaddr *sin;
1282 char hostdd[16];
1283 struct nfs_server_list *srvr;
1284
1285 assert(rpc->magic == RPC_CONTEXT_MAGIC);
1286
1287 if (status == RPC_STATUS_CANCEL) {
1288 return;
1289 }
1290 if (status != 0) {
1291 srv_data->status = -1;
1292 return;
1293 }
1294
1295 sin = rpc_get_recv_sockaddr(rpc);
1296 if (sin == NULL) {
1297 rpc_set_error(rpc, "failed to get sockaddr in CALLIT callback");
1298 srv_data->status = -1;
1299 return;
1300 }
1301
1302 if (getnameinfo(sin, sizeof(struct sockaddr_in), &hostdd[0], sizeof(hostdd), NULL, 0, NI_NUMERICHOST) < 0) {
1303 rpc_set_error(rpc, "getnameinfo failed in CALLIT callback");
1304 srv_data->status = -1;
1305 return;
1306 }
1307
1308 /* check for dupes */
1309 for (srvr = srv_data->srvrs; srvr; srvr = srvr->next) {
1310 if (!strcmp(hostdd, srvr->addr)) {
1311 return;
1312 }
1313 }
1314
1315 srvr = malloc(sizeof(struct nfs_server_list));
1316 if (srvr == NULL) {
1317 rpc_set_error(rpc, "Malloc failed when allocating server structure");
1318 srv_data->status = -1;
1319 return;
1320 }
1321
1322 srvr->addr = strdup(hostdd);
1323 if (srvr->addr == NULL) {
1324 rpc_set_error(rpc, "Strdup failed when allocating server structure");
1325 free(srvr);
1326 srv_data->status = -1;
1327 return;
1328 }
1329
1330 srvr->next = srv_data->srvrs;
1331 srv_data->srvrs = srvr;
1332}
1333
1334#ifdef WIN32
1335
1336static int send_nfsd_probes(struct rpc_context *rpc, INTERFACE_INFO *InterfaceList, int numIfs, struct nfs_list_data *data)
1337{
1338 int i=0;
1339
1340 assert(rpc->magic == RPC_CONTEXT_MAGIC);
1341
1342 for(i = 0; i < numIfs; i++)
1343 {
1344 SOCKADDR *pAddress;
1345 char bcdd[16];
1346 unsigned long nFlags = 0;
1347
1348 pAddress = (SOCKADDR *) & (InterfaceList[i].iiBroadcastAddress);
1349
1350 if(pAddress->sa_family != AF_INET)
1351 continue;
1352
1353 nFlags = InterfaceList[i].iiFlags;
1354
1355 if (!(nFlags & IFF_UP))
1356 {
1357 continue;
1358 }
1359
1360 if (nFlags & IFF_LOOPBACK)
1361 {
1362 continue;
1363 }
1364
1365 if (!(nFlags & IFF_BROADCAST))
1366 {
1367 continue;
1368 }
1369
1370 if (getnameinfo(pAddress, sizeof(struct sockaddr_in), &bcdd[0], sizeof(bcdd), NULL, 0, NI_NUMERICHOST) < 0)
1371 {
1372 continue;
1373 }
1374
1375 if (rpc_set_udp_destination(rpc, bcdd, 111, 1) < 0)
1376 {
1377 return -1;
1378 }
1379
1380 if (rpc_pmap_callit_async(rpc, MOUNT_PROGRAM, 2, 0, NULL, 0, callit_cb, data) < 0)
1381 {
1382 return -1;
1383 }
1384 }
1385 return 0;
1386}
1387
1388struct nfs_server_list *nfs_find_local_servers(void)
1389{
1390 struct rpc_context *rpc;
1391 struct nfs_list_data data = {0, NULL};
1392 struct timeval tv_start, tv_current;
1393 int loop;
1394 struct pollfd pfd;
1395 INTERFACE_INFO InterfaceList[20];
1396 unsigned long nBytesReturned;
1397 int nNumInterfaces = 0;
1398
1399 rpc = rpc_init_udp_context();
1400 if (rpc == NULL)
1401 {
1402 return NULL;
1403 }
1404
1405 if (rpc_bind_udp(rpc, "0.0.0.0", 0) < 0)
1406 {
1407 rpc_destroy_context(rpc);
1408 return NULL;
1409 }
1410
1411 if (WSAIoctl(rpc_get_fd(rpc), SIO_GET_INTERFACE_LIST, 0, 0, &InterfaceList, sizeof(InterfaceList), &nBytesReturned, 0, 0) == SOCKET_ERROR)
1412 {
1413 return NULL;
1414 }
1415
1416 nNumInterfaces = nBytesReturned / sizeof(INTERFACE_INFO);
1417
1418 for (loop=0; loop<3; loop++)
1419 {
1420 if (send_nfsd_probes(rpc, InterfaceList, nNumInterfaces, &data) != 0)
1421 {
1422 rpc_destroy_context(rpc);
1423 return NULL;
1424 }
1425
1426 win32_gettimeofday(&tv_start, NULL);
1427 for(;;)
1428 {
1429 int mpt;
1430
1431 pfd.fd = rpc_get_fd(rpc);
1432 pfd.events = rpc_which_events(rpc);
1433
1434 win32_gettimeofday(&tv_current, NULL);
1435 mpt = 1000
1436 - (tv_current.tv_sec *1000 + tv_current.tv_usec / 1000)
1437 + (tv_start.tv_sec *1000 + tv_start.tv_usec / 1000);
1438
1439 if (poll(&pfd, 1, mpt) < 0)
1440 {
1441 free_nfs_srvr_list(data.srvrs);
1442 rpc_destroy_context(rpc);
1443 return NULL;
1444 }
1445 if (pfd.revents == 0)
1446 {
1447 break;
1448 }
1449
1450 if (rpc_service(rpc, pfd.revents) < 0)
1451 {
1452 break;
1453 }
1454 }
1455 }
1456
1457 rpc_destroy_context(rpc);
1458
1459 if (data.status != 0)
1460 {
1461 free_nfs_srvr_list(data.srvrs);
1462 return NULL;
1463 }
1464 return data.srvrs;
1465}
1466#else
1467
1468static int send_nfsd_probes(struct rpc_context *rpc, struct ifconf *ifc, struct nfs_list_data *data)
1469{
1470 char *ptr;
1471
1472 assert(rpc->magic == RPC_CONTEXT_MAGIC);
1473
1474 for (ptr =(char *)(ifc->ifc_buf); ptr < (char *)(ifc->ifc_buf) + ifc->ifc_len; ) {
1475 struct ifreq *ifr;
1476 char bcdd[16];
1477
1478 ifr = (struct ifreq *)ptr;
1479#ifdef HAVE_SOCKADDR_LEN
1480 if (ifr->ifr_addr.sa_len > sizeof(struct sockaddr)) {
1481 ptr += sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len;
1482 } else {
1483 ptr += sizeof(ifr->ifr_name) + sizeof(struct sockaddr);
1484 }
1485#else
1486 ptr += sizeof(struct ifreq);
1487#endif
1488
1489 if (ifr->ifr_addr.sa_family != AF_INET) {
1490 continue;
1491 }
1492 if (ioctl(rpc_get_fd(rpc), SIOCGIFFLAGS, ifr) < 0) {
1493 return -1;
1494 }
1495 if (!(ifr->ifr_flags & IFF_UP)) {
1496 continue;
1497 }
1498 if (ifr->ifr_flags & IFF_LOOPBACK) {
1499 continue;
1500 }
1501 if (!(ifr->ifr_flags & IFF_BROADCAST)) {
1502 continue;
1503 }
1504 if (ioctl(rpc_get_fd(rpc), SIOCGIFBRDADDR, ifr) < 0) {
1505 continue;
1506 }
1507 if (getnameinfo(&ifr->ifr_broadaddr, sizeof(struct sockaddr_in), &bcdd[0], sizeof(bcdd), NULL, 0, NI_NUMERICHOST) < 0) {
1508 continue;
1509 }
1510 if (rpc_set_udp_destination(rpc, bcdd, 111, 1) < 0) {
1511 return -1;
1512 }
1513
1514 if (rpc_pmap_callit_async(rpc, MOUNT_PROGRAM, 2, 0, NULL, 0, callit_cb, data) < 0) {
1515 return -1;
1516 }
1517 }
1518
1519 return 0;
1520}
1521
1522struct nfs_server_list *nfs_find_local_servers(void)
1523{
1524 struct rpc_context *rpc;
1525 struct nfs_list_data data = {0, NULL};
1526 struct timeval tv_start, tv_current;
1527 struct ifconf ifc;
1528 int size, loop;
1529 struct pollfd pfd;
1530
1531 rpc = rpc_init_udp_context();
1532 if (rpc == NULL) {
1533 return NULL;
1534 }
1535
1536 if (rpc_bind_udp(rpc, "0.0.0.0", 0) < 0) {
1537 rpc_destroy_context(rpc);
1538 return NULL;
1539 }
1540
1541
1542 /* get list of all interfaces */
1543 size = sizeof(struct ifreq);
1544 ifc.ifc_buf = NULL;
1545 ifc.ifc_len = size;
1546
1547 while(ifc.ifc_len > (size - sizeof(struct ifreq))) {
1548 size *= 2;
1549
1550 free(ifc.ifc_buf);
1551 ifc.ifc_len = size;
1552 ifc.ifc_buf = malloc(size);
1553 memset(ifc.ifc_buf, 0, size);
1554 if (ioctl(rpc_get_fd(rpc), SIOCGIFCONF, (caddr_t)&ifc) < 0) {
1555 rpc_destroy_context(rpc);
1556 free(ifc.ifc_buf);
1557 return NULL;
1558 }
1559 }
1560
1561 for (loop=0; loop<3; loop++) {
1562 if (send_nfsd_probes(rpc, &ifc, &data) != 0) {
1563 rpc_destroy_context(rpc);
1564 free(ifc.ifc_buf);
1565 return NULL;
1566 }
1567
1568 gettimeofday(&tv_start, NULL);
1569 for(;;) {
1570 int mpt;
1571
1572 pfd.fd = rpc_get_fd(rpc);
1573 pfd.events = rpc_which_events(rpc);
1574
1575 gettimeofday(&tv_current, NULL);
1576 mpt = 1000
1577 - (tv_current.tv_sec *1000 + tv_current.tv_usec / 1000)
1578 + (tv_start.tv_sec *1000 + tv_start.tv_usec / 1000);
1579
1580 if (poll(&pfd, 1, mpt) < 0) {
1581 free_nfs_srvr_list(data.srvrs);
1582 rpc_destroy_context(rpc);
1583 return NULL;
1584 }
1585 if (pfd.revents == 0) {
1586 break;
1587 }
1588
1589 if (rpc_service(rpc, pfd.revents) < 0) {
1590 break;
1591 }
1592 }
1593 }
1594
1595 free(ifc.ifc_buf);
1596 rpc_destroy_context(rpc);
1597
1598 if (data.status != 0) {
1599 free_nfs_srvr_list(data.srvrs);
1600 return NULL;
1601 }
1602 return data.srvrs;
1603}
1604#endif//WIN32