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