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