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