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