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