[win32] - fixed bad number casting when using libnfs on 64bit win8 systems - force...
[deb_libnfs.git] / lib / libnfs-sync.c
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
96 struct 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
105 static 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
132 static 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 */
161 static 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
174 int 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 */
200 static 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
219 int nfs_stat(struct nfs_context *nfs, const char *path, struct __stat64 *st)
220 #else
221 int 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 */
245 static 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
263 int 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 */
286 static 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
302 int 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 */
322 int 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 */
330 static 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
342 int 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 */
364 int 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 */
385 static 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
397 int 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 */
416 int 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 */
425 static 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
437 int 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 */
459 static 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
471 int 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 */
492 static 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
504 int 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 */
527 static 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
539 int 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 */
562 static 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
574 int 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 */
595 static 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
613 int 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 */
633 static 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
646 int 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 */
666 static 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
679 int 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 */
700 static 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
718 int 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 */
739 static 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
756 int 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 */
778 static 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
793 int 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 */
817 static 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
838 int 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 */
861 static 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
874 int 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 */
896 static 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
909 int 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 */
931 static 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
944 int 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 */
963 static 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
976 int 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 */
997 static 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
1010 int 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 */
1031 static 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
1044 int 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 */
1066 static 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
1079 int 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 */
1100 static 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
1113 int 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 */
1134 static 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
1147 int 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 */
1168 static 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
1181 int 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
1197 void 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
1228 struct 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
1249 void 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
1262 void 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
1273 struct nfs_list_data {
1274 int status;
1275 struct nfs_server_list *srvrs;
1276 };
1277
1278 void 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
1336 static 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
1388 struct 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
1468 static 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
1522 struct 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