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