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