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