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