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