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