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