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