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