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