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