libnfs: Add lchown
[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
3e020c15
RL
456/*
457 * fstat64()
458 */
459int nfs_fstat64(struct nfs_context *nfs, struct nfsfh *nfsfh, struct nfs_stat_64 *st)
460{
461 struct sync_cb_data cb_data;
462
463 cb_data.is_finished = 0;
464 cb_data.return_data = st;
465
466 if (nfs_fstat64_async(nfs, nfsfh, stat64_cb, &cb_data) != 0) {
467 nfs_set_error(nfs, "nfs_fstat64_async failed");
468 return -1;
469 }
470
471 wait_for_nfs_reply(nfs, &cb_data);
472
473 return cb_data.status;
474}
475
84004dbf
RS
476
477/*
478 * pwrite()
479 */
1896d37b 480static void pwrite_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
84004dbf
RS
481{
482 struct sync_cb_data *cb_data = private_data;
483 cb_data->is_finished = 1;
484 cb_data->status = status;
485
9e6ac3d4
AR
486 if (status < 0)
487 nfs_set_error(nfs, "%s call failed with \"%s\"", cb_data->call, (char *)data);
84004dbf
RS
488}
489
183451cf 490int nfs_pwrite(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, uint64_t count, char *buf)
84004dbf
RS
491{
492 struct sync_cb_data cb_data;
493
494 cb_data.is_finished = 0;
9e6ac3d4 495 cb_data.call = "pwrite";
84004dbf
RS
496
497 if (nfs_pwrite_async(nfs, nfsfh, offset, count, buf, pwrite_cb, &cb_data) != 0) {
1896d37b 498 nfs_set_error(nfs, "nfs_pwrite_async failed");
84004dbf
RS
499 return -1;
500 }
501
b077fdeb 502 wait_for_nfs_reply(nfs, &cb_data);
84004dbf
RS
503
504 return cb_data.status;
505}
506
507/*
508 * write()
509 */
183451cf 510int nfs_write(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t count, char *buf)
84004dbf 511{
9e6ac3d4
AR
512 struct sync_cb_data cb_data;
513
514 cb_data.is_finished = 0;
515 cb_data.call = "write";
516
517 if (nfs_write_async(nfs, nfsfh, count, buf, pwrite_cb, &cb_data) != 0) {
518 nfs_set_error(nfs, "nfs_write_async failed");
519 return -1;
520 }
521
522 wait_for_nfs_reply(nfs, &cb_data);
523
524 return cb_data.status;
84004dbf
RS
525}
526
527
528/*
529 * fsync()
530 */
1896d37b 531static void fsync_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
84004dbf
RS
532{
533 struct sync_cb_data *cb_data = private_data;
534 cb_data->is_finished = 1;
535 cb_data->status = status;
536
537 if (status < 0) {
1896d37b 538 nfs_set_error(nfs, "fsync call failed with \"%s\"", (char *)data);
84004dbf
RS
539 return;
540 }
541}
542
e2ba5764 543int nfs_fsync(struct nfs_context *nfs, struct nfsfh *nfsfh)
84004dbf
RS
544{
545 struct sync_cb_data cb_data;
546
547 cb_data.is_finished = 0;
548
549 if (nfs_fsync_async(nfs, nfsfh, fsync_cb, &cb_data) != 0) {
1896d37b 550 nfs_set_error(nfs, "nfs_fsync_async failed");
84004dbf
RS
551 return -1;
552 }
553
b077fdeb 554 wait_for_nfs_reply(nfs, &cb_data);
84004dbf
RS
555
556 return cb_data.status;
557}
558
559
560
561
562/*
563 * ftruncate()
564 */
1896d37b 565static void ftruncate_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
84004dbf
RS
566{
567 struct sync_cb_data *cb_data = private_data;
568 cb_data->is_finished = 1;
569 cb_data->status = status;
570
571 if (status < 0) {
1896d37b 572 nfs_set_error(nfs, "ftruncate call failed with \"%s\"", (char *)data);
84004dbf
RS
573 return;
574 }
575}
576
183451cf 577int nfs_ftruncate(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t length)
84004dbf
RS
578{
579 struct sync_cb_data cb_data;
580
581 cb_data.is_finished = 0;
582
583 if (nfs_ftruncate_async(nfs, nfsfh, length, ftruncate_cb, &cb_data) != 0) {
1896d37b 584 nfs_set_error(nfs, "nfs_ftruncate_async failed");
84004dbf
RS
585 return -1;
586 }
587
b077fdeb 588 wait_for_nfs_reply(nfs, &cb_data);
84004dbf
RS
589
590 return cb_data.status;
591}
592
593
594
595/*
596 * truncate()
597 */
1896d37b 598static void truncate_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
84004dbf
RS
599{
600 struct sync_cb_data *cb_data = private_data;
601 cb_data->is_finished = 1;
602 cb_data->status = status;
603
604 if (status < 0) {
1896d37b 605 nfs_set_error(nfs, "truncate call failed with \"%s\"", (char *)data);
84004dbf
RS
606 return;
607 }
608}
609
183451cf 610int nfs_truncate(struct nfs_context *nfs, const char *path, uint64_t length)
84004dbf
RS
611{
612 struct sync_cb_data cb_data;
613
614 cb_data.is_finished = 0;
615
616 if (nfs_truncate_async(nfs, path, length, truncate_cb, &cb_data) != 0) {
1896d37b 617 nfs_set_error(nfs, "nfs_ftruncate_async failed");
84004dbf
RS
618 return -1;
619 }
620
b077fdeb 621 wait_for_nfs_reply(nfs, &cb_data);
84004dbf
RS
622
623 return cb_data.status;
624}
625
626
627
628
629
630/*
631 * mkdir()
632 */
1896d37b 633static void mkdir_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
84004dbf
RS
634{
635 struct sync_cb_data *cb_data = private_data;
636 cb_data->is_finished = 1;
637 cb_data->status = status;
638
639 if (status < 0) {
1896d37b 640 nfs_set_error(nfs, "mkdir call failed with \"%s\"", (char *)data);
84004dbf
RS
641 return;
642 }
643}
644
e2ba5764 645int nfs_mkdir(struct nfs_context *nfs, const char *path)
84004dbf
RS
646{
647 struct sync_cb_data cb_data;
648
649 cb_data.is_finished = 0;
650
651 if (nfs_mkdir_async(nfs, path, mkdir_cb, &cb_data) != 0) {
1896d37b 652 nfs_set_error(nfs, "nfs_mkdir_async failed");
84004dbf
RS
653 return -1;
654 }
655
b077fdeb 656 wait_for_nfs_reply(nfs, &cb_data);
84004dbf
RS
657
658 return cb_data.status;
659}
660
661
662
663
664
665/*
666 * rmdir()
667 */
1896d37b 668static void rmdir_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
84004dbf
RS
669{
670 struct sync_cb_data *cb_data = private_data;
671 cb_data->is_finished = 1;
672 cb_data->status = status;
673
674 if (status < 0) {
1896d37b 675 nfs_set_error(nfs, "rmdir call failed with \"%s\"", (char *)data);
84004dbf
RS
676 return;
677 }
678}
679
e2ba5764 680int nfs_rmdir(struct nfs_context *nfs, const char *path)
84004dbf
RS
681{
682 struct sync_cb_data cb_data;
683
684 cb_data.is_finished = 0;
685
686 if (nfs_rmdir_async(nfs, path, rmdir_cb, &cb_data) != 0) {
1896d37b 687 nfs_set_error(nfs, "nfs_rmdir_async failed");
84004dbf
RS
688 return -1;
689 }
690
b077fdeb 691 wait_for_nfs_reply(nfs, &cb_data);
84004dbf
RS
692
693 return cb_data.status;
694}
695
696
697
698/*
699 * creat()
700 */
1896d37b 701static void creat_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
84004dbf
RS
702{
703 struct sync_cb_data *cb_data = private_data;
704 struct nfsfh *fh, **nfsfh;
705
706 cb_data->is_finished = 1;
707 cb_data->status = status;
708
709 if (status < 0) {
1896d37b 710 nfs_set_error(nfs, "creat call failed with \"%s\"", (char *)data);
84004dbf
RS
711 return;
712 }
713
714 fh = data;
715 nfsfh = cb_data->return_data;
716 *nfsfh = fh;
717}
718
037a1061 719int nfs_create(struct nfs_context *nfs, const char *path, int flags, int mode, struct nfsfh **nfsfh)
84004dbf
RS
720{
721 struct sync_cb_data cb_data;
722
723 cb_data.is_finished = 0;
724 cb_data.return_data = nfsfh;
725
037a1061
RL
726 if (nfs_create_async(nfs, path, flags, mode, creat_cb, &cb_data) != 0) {
727 nfs_set_error(nfs, "nfs_create_async failed");
84004dbf
RS
728 return -1;
729 }
730
b077fdeb 731 wait_for_nfs_reply(nfs, &cb_data);
84004dbf
RS
732
733 return cb_data.status;
734}
735
037a1061
RL
736int nfs_creat(struct nfs_context *nfs, const char *path, int mode, struct nfsfh **nfsfh)
737{
738 return nfs_create(nfs, path, 0, mode, nfsfh);
739}
740
1ec6b50a
RS
741/*
742 * mknod()
743 */
744static void mknod_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
745{
746 struct sync_cb_data *cb_data = private_data;
747
748 cb_data->is_finished = 1;
749 cb_data->status = status;
84004dbf 750
1ec6b50a
RS
751 if (status < 0) {
752 nfs_set_error(nfs, "mknod call failed with \"%s\"", (char *)data);
753 return;
754 }
755}
756
757int nfs_mknod(struct nfs_context *nfs, const char *path, int mode, int dev)
758{
759 struct sync_cb_data cb_data;
760
761 cb_data.is_finished = 0;
762
763 if (nfs_mknod_async(nfs, path, mode, dev, mknod_cb, &cb_data) != 0) {
764 nfs_set_error(nfs, "nfs_creat_async failed");
765 return -1;
766 }
767
768 wait_for_nfs_reply(nfs, &cb_data);
769
770 return cb_data.status;
771}
84004dbf
RS
772
773
774/*
775 * unlink()
776 */
1896d37b 777static void unlink_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
84004dbf
RS
778{
779 struct sync_cb_data *cb_data = private_data;
780
781 cb_data->is_finished = 1;
782 cb_data->status = status;
783
784 if (status < 0) {
1896d37b 785 nfs_set_error(nfs, "unlink call failed with \"%s\"", (char *)data);
84004dbf
RS
786 return;
787 }
788}
789
e2ba5764 790int nfs_unlink(struct nfs_context *nfs, const char *path)
84004dbf
RS
791{
792 struct sync_cb_data cb_data;
793
794 cb_data.is_finished = 0;
795
796 if (nfs_unlink_async(nfs, path, unlink_cb, &cb_data) != 0) {
1896d37b 797 nfs_set_error(nfs, "nfs_unlink_async failed");
84004dbf
RS
798 return -1;
799 }
800
b077fdeb 801 wait_for_nfs_reply(nfs, &cb_data);
84004dbf
RS
802
803 return cb_data.status;
804}
805
806
807
808/*
809 * opendir()
810 */
1896d37b 811static void opendir_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
84004dbf
RS
812{
813 struct sync_cb_data *cb_data = private_data;
814 struct nfsdir *dir, **nfsdir;
815
816 cb_data->is_finished = 1;
817 cb_data->status = status;
818
819 if (status < 0) {
1896d37b 820 nfs_set_error(nfs, "opendir call failed with \"%s\"", (char *)data);
84004dbf
RS
821 return;
822 }
823
824 dir = data;
825 nfsdir = cb_data->return_data;
826 *nfsdir = dir;
827}
828
e2ba5764 829int nfs_opendir(struct nfs_context *nfs, const char *path, struct nfsdir **nfsdir)
84004dbf
RS
830{
831 struct sync_cb_data cb_data;
832
833 cb_data.is_finished = 0;
834 cb_data.return_data = nfsdir;
835
836 if (nfs_opendir_async(nfs, path, opendir_cb, &cb_data) != 0) {
1896d37b 837 nfs_set_error(nfs, "nfs_opendir_async failed");
84004dbf
RS
838 return -1;
839 }
840
b077fdeb 841 wait_for_nfs_reply(nfs, &cb_data);
84004dbf
RS
842
843 return cb_data.status;
844}
845
846
847/*
848 * lseek()
849 */
1896d37b 850static void lseek_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
84004dbf
RS
851{
852 struct sync_cb_data *cb_data = private_data;
853
854 cb_data->is_finished = 1;
855 cb_data->status = status;
856
857 if (status < 0) {
1896d37b 858 nfs_set_error(nfs, "lseek call failed with \"%s\"", (char *)data);
84004dbf
RS
859 return;
860 }
861
862 if (cb_data->return_data != NULL) {
183451cf 863 memcpy(cb_data->return_data, data, sizeof(uint64_t));
84004dbf
RS
864 }
865}
866
1f1b6cb0 867int nfs_lseek(struct nfs_context *nfs, struct nfsfh *nfsfh, int64_t offset, int whence, uint64_t *current_offset)
84004dbf
RS
868{
869 struct sync_cb_data cb_data;
870
871 cb_data.is_finished = 0;
872 cb_data.return_data = current_offset;
873
874 if (nfs_lseek_async(nfs, nfsfh, offset, whence, lseek_cb, &cb_data) != 0) {
1896d37b 875 nfs_set_error(nfs, "nfs_lseek_async failed");
84004dbf
RS
876 return -1;
877 }
878
b077fdeb 879 wait_for_nfs_reply(nfs, &cb_data);
84004dbf
RS
880
881 return cb_data.status;
882}
883
884
885
886/*
887 * statvfs()
888 */
1896d37b 889static void statvfs_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
84004dbf
RS
890{
891 struct sync_cb_data *cb_data = private_data;
892
893 cb_data->is_finished = 1;
894 cb_data->status = status;
895
896 if (status < 0) {
1896d37b 897 nfs_set_error(nfs, "statvfs call failed with \"%s\"", (char *)data);
84004dbf
RS
898 return;
899 }
fcc42bfe 900
84004dbf
RS
901 memcpy(cb_data->return_data, data, sizeof(struct statvfs));
902}
903
e2ba5764 904int nfs_statvfs(struct nfs_context *nfs, const char *path, struct statvfs *svfs)
84004dbf
RS
905{
906 struct sync_cb_data cb_data;
907
908 cb_data.is_finished = 0;
909 cb_data.return_data = svfs;
910
911 if (nfs_statvfs_async(nfs, path, statvfs_cb, &cb_data) != 0) {
1896d37b 912 nfs_set_error(nfs, "nfs_statvfs_async failed");
84004dbf
RS
913 return -1;
914 }
915
b077fdeb 916 wait_for_nfs_reply(nfs, &cb_data);
84004dbf
RS
917
918 return cb_data.status;
919}
920
921
922
923
924
925/*
926 * readlink()
927 */
1896d37b 928static void readlink_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
84004dbf
RS
929{
930 struct sync_cb_data *cb_data = private_data;
931
932 cb_data->is_finished = 1;
933 cb_data->status = status;
934
935 if (status < 0) {
1896d37b 936 nfs_set_error(nfs, "readlink call failed with \"%s\"", (char *)data);
84004dbf
RS
937 return;
938 }
939
940 if (strlen(data) > (size_t)cb_data->return_int) {
1896d37b 941 nfs_set_error(nfs, "Too small buffer for readlink");
84004dbf
RS
942 cb_data->status = -ENAMETOOLONG;
943 return;
944 }
945
946 memcpy(cb_data->return_data, data, strlen(data)+1);
947}
948
e2ba5764 949int nfs_readlink(struct nfs_context *nfs, const char *path, char *buf, int bufsize)
84004dbf
RS
950{
951 struct sync_cb_data cb_data;
952
953 cb_data.is_finished = 0;
954 cb_data.return_data = buf;
955 cb_data.return_int = bufsize;
956
957 if (nfs_readlink_async(nfs, path, readlink_cb, &cb_data) != 0) {
1896d37b 958 nfs_set_error(nfs, "nfs_readlink_async failed");
84004dbf
RS
959 return -1;
960 }
961
b077fdeb 962 wait_for_nfs_reply(nfs, &cb_data);
84004dbf
RS
963
964 return cb_data.status;
965}
966
967
968
969/*
970 * chmod()
971 */
1896d37b 972static void chmod_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
84004dbf
RS
973{
974 struct sync_cb_data *cb_data = private_data;
975
976 cb_data->is_finished = 1;
977 cb_data->status = status;
978
979 if (status < 0) {
1896d37b 980 nfs_set_error(nfs, "chmod call failed with \"%s\"", (char *)data);
84004dbf
RS
981 return;
982 }
983}
984
e2ba5764 985int nfs_chmod(struct nfs_context *nfs, const char *path, int mode)
84004dbf
RS
986{
987 struct sync_cb_data cb_data;
988
989 cb_data.is_finished = 0;
990
991 if (nfs_chmod_async(nfs, path, mode, chmod_cb, &cb_data) != 0) {
1896d37b 992 nfs_set_error(nfs, "nfs_chmod_async failed");
84004dbf
RS
993 return -1;
994 }
995
b077fdeb 996 wait_for_nfs_reply(nfs, &cb_data);
84004dbf
RS
997
998 return cb_data.status;
999}
1000
1001
1002
1003
1004/*
1005 * fchmod()
1006 */
1896d37b 1007static void fchmod_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
84004dbf
RS
1008{
1009 struct sync_cb_data *cb_data = private_data;
1010
1011 cb_data->is_finished = 1;
1012 cb_data->status = status;
1013
1014 if (status < 0) {
1896d37b 1015 nfs_set_error(nfs, "fchmod call failed with \"%s\"", (char *)data);
84004dbf
RS
1016 return;
1017 }
1018}
1019
e2ba5764 1020int nfs_fchmod(struct nfs_context *nfs, struct nfsfh *nfsfh, int mode)
84004dbf
RS
1021{
1022 struct sync_cb_data cb_data;
1023
1024 cb_data.is_finished = 0;
1025
1026 if (nfs_fchmod_async(nfs, nfsfh, mode, fchmod_cb, &cb_data) != 0) {
1896d37b 1027 nfs_set_error(nfs, "nfs_fchmod_async failed");
84004dbf
RS
1028 return -1;
1029 }
1030
b077fdeb 1031 wait_for_nfs_reply(nfs, &cb_data);
84004dbf
RS
1032
1033 return cb_data.status;
1034}
1035
1036
1037
1038
1039/*
1040 * chown()
1041 */
1896d37b 1042static void chown_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
84004dbf
RS
1043{
1044 struct sync_cb_data *cb_data = private_data;
1045
1046 cb_data->is_finished = 1;
1047 cb_data->status = status;
1048
1049 if (status < 0) {
1896d37b 1050 nfs_set_error(nfs, "chown call failed with \"%s\"", (char *)data);
84004dbf
RS
1051 return;
1052 }
1053}
1054
e2ba5764 1055int nfs_chown(struct nfs_context *nfs, const char *path, int uid, int gid)
84004dbf
RS
1056{
1057 struct sync_cb_data cb_data;
1058
1059 cb_data.is_finished = 0;
1060
1061 if (nfs_chown_async(nfs, path, uid, gid, chown_cb, &cb_data) != 0) {
1896d37b 1062 nfs_set_error(nfs, "nfs_chown_async failed");
84004dbf
RS
1063 return -1;
1064 }
1065
b077fdeb 1066 wait_for_nfs_reply(nfs, &cb_data);
84004dbf
RS
1067
1068 return cb_data.status;
1069}
1070
5935a28a
RL
1071/*
1072 * lchown()
1073 */
1074int nfs_lchown(struct nfs_context *nfs, const char *path, int uid, int gid)
1075{
1076 struct sync_cb_data cb_data;
1077
1078 cb_data.is_finished = 0;
1079
1080 if (nfs_lchown_async(nfs, path, uid, gid, chown_cb, &cb_data) != 0) {
1081 nfs_set_error(nfs, "nfs_lchown_async failed");
1082 return -1;
1083 }
1084
1085 wait_for_nfs_reply(nfs, &cb_data);
1086
1087 return cb_data.status;
1088}
1089
84004dbf
RS
1090/*
1091 * fchown()
1092 */
1896d37b 1093static void fchown_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
84004dbf
RS
1094{
1095 struct sync_cb_data *cb_data = private_data;
1096
1097 cb_data->is_finished = 1;
1098 cb_data->status = status;
1099
1100 if (status < 0) {
1896d37b 1101 nfs_set_error(nfs, "fchown call failed with \"%s\"", (char *)data);
84004dbf
RS
1102 return;
1103 }
1104}
1105
e2ba5764 1106int nfs_fchown(struct nfs_context *nfs, struct nfsfh *nfsfh, int uid, int gid)
84004dbf
RS
1107{
1108 struct sync_cb_data cb_data;
1109
1110 cb_data.is_finished = 0;
1111
1112 if (nfs_fchown_async(nfs, nfsfh, uid, gid, fchown_cb, &cb_data) != 0) {
1896d37b 1113 nfs_set_error(nfs, "nfs_fchown_async failed");
84004dbf
RS
1114 return -1;
1115 }
1116
b077fdeb 1117 wait_for_nfs_reply(nfs, &cb_data);
84004dbf
RS
1118
1119 return cb_data.status;
1120}
1121
1122
1123
1124/*
1125 * utimes()
1126 */
1896d37b 1127static void utimes_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
84004dbf
RS
1128{
1129 struct sync_cb_data *cb_data = private_data;
1130
1131 cb_data->is_finished = 1;
1132 cb_data->status = status;
1133
1134 if (status < 0) {
1896d37b 1135 nfs_set_error(nfs, "utimes call failed with \"%s\"", (char *)data);
84004dbf
RS
1136 return;
1137 }
1138}
1139
e2ba5764 1140int nfs_utimes(struct nfs_context *nfs, const char *path, struct timeval *times)
84004dbf
RS
1141{
1142 struct sync_cb_data cb_data;
1143
1144 cb_data.is_finished = 0;
1145
1146 if (nfs_utimes_async(nfs, path, times, utimes_cb, &cb_data) != 0) {
1896d37b 1147 nfs_set_error(nfs, "nfs_utimes_async failed");
84004dbf
RS
1148 return -1;
1149 }
1150
b077fdeb 1151 wait_for_nfs_reply(nfs, &cb_data);
84004dbf
RS
1152
1153 return cb_data.status;
1154}
1155
1156
1157
1158/*
1159 * utime()
1160 */
1896d37b 1161static void utime_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
84004dbf
RS
1162{
1163 struct sync_cb_data *cb_data = private_data;
1164
1165 cb_data->is_finished = 1;
1166 cb_data->status = status;
1167
1168 if (status < 0) {
1896d37b 1169 nfs_set_error(nfs, "utime call failed with \"%s\"", (char *)data);
84004dbf
RS
1170 return;
1171 }
1172}
1173
e2ba5764 1174int nfs_utime(struct nfs_context *nfs, const char *path, struct utimbuf *times)
84004dbf
RS
1175{
1176 struct sync_cb_data cb_data;
1177
1178 cb_data.is_finished = 0;
1179
1180 if (nfs_utime_async(nfs, path, times, utime_cb, &cb_data) != 0) {
1896d37b 1181 nfs_set_error(nfs, "nfs_utimes_async failed");
84004dbf
RS
1182 return -1;
1183 }
1184
b077fdeb 1185 wait_for_nfs_reply(nfs, &cb_data);
84004dbf
RS
1186
1187 return cb_data.status;
1188}
1189
1190
1191
1192
1193/*
1194 * access()
1195 */
1896d37b 1196static void access_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
84004dbf
RS
1197{
1198 struct sync_cb_data *cb_data = private_data;
1199
1200 cb_data->is_finished = 1;
1201 cb_data->status = status;
1202
1203 if (status < 0) {
1896d37b 1204 nfs_set_error(nfs, "access call failed with \"%s\"", (char *)data);
84004dbf
RS
1205 return;
1206 }
1207}
1208
e2ba5764 1209int nfs_access(struct nfs_context *nfs, const char *path, int mode)
84004dbf
RS
1210{
1211 struct sync_cb_data cb_data;
1212
1213 cb_data.is_finished = 0;
1214
1215 if (nfs_access_async(nfs, path, mode, access_cb, &cb_data) != 0) {
1896d37b 1216 nfs_set_error(nfs, "nfs_access_async failed");
84004dbf
RS
1217 return -1;
1218 }
1219
b077fdeb 1220 wait_for_nfs_reply(nfs, &cb_data);
84004dbf
RS
1221
1222 return cb_data.status;
1223}
1224
1225
1226
1227/*
1228 * symlink()
1229 */
1896d37b 1230static void symlink_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
84004dbf
RS
1231{
1232 struct sync_cb_data *cb_data = private_data;
1233
1234 cb_data->is_finished = 1;
1235 cb_data->status = status;
1236
1237 if (status < 0) {
1896d37b 1238 nfs_set_error(nfs, "symlink call failed with \"%s\"", (char *)data);
84004dbf
RS
1239 return;
1240 }
1241}
1242
e2ba5764 1243int nfs_symlink(struct nfs_context *nfs, const char *oldpath, const char *newpath)
84004dbf
RS
1244{
1245 struct sync_cb_data cb_data;
1246
1247 cb_data.is_finished = 0;
1248
1249 if (nfs_symlink_async(nfs, oldpath, newpath, symlink_cb, &cb_data) != 0) {
1896d37b 1250 nfs_set_error(nfs, "nfs_symlink_async failed");
84004dbf
RS
1251 return -1;
1252 }
1253
b077fdeb 1254 wait_for_nfs_reply(nfs, &cb_data);
84004dbf
RS
1255
1256 return cb_data.status;
1257}
1258
1259
1260
1261/*
1262 * rename()
1263 */
1896d37b 1264static void rename_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
84004dbf
RS
1265{
1266 struct sync_cb_data *cb_data = private_data;
1267
1268 cb_data->is_finished = 1;
1269 cb_data->status = status;
1270
1271 if (status < 0) {
1896d37b 1272 nfs_set_error(nfs, "rename call failed with \"%s\"", (char *)data);
84004dbf
RS
1273 return;
1274 }
1275}
1276
e2ba5764 1277int nfs_rename(struct nfs_context *nfs, const char *oldpath, const char *newpath)
84004dbf
RS
1278{
1279 struct sync_cb_data cb_data;
1280
1281 cb_data.is_finished = 0;
1282
1283 if (nfs_rename_async(nfs, oldpath, newpath, rename_cb, &cb_data) != 0) {
1896d37b 1284 nfs_set_error(nfs, "nfs_rename_async failed");
84004dbf
RS
1285 return -1;
1286 }
1287
b077fdeb 1288 wait_for_nfs_reply(nfs, &cb_data);
84004dbf
RS
1289
1290 return cb_data.status;
1291}
1292
1293
1294
1295/*
1296 * link()
1297 */
1896d37b 1298static void link_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
84004dbf
RS
1299{
1300 struct sync_cb_data *cb_data = private_data;
1301
1302 cb_data->is_finished = 1;
1303 cb_data->status = status;
1304
1305 if (status < 0) {
1896d37b 1306 nfs_set_error(nfs, "link call failed with \"%s\"", (char *)data);
84004dbf
RS
1307 return;
1308 }
1309}
1310
e2ba5764 1311int nfs_link(struct nfs_context *nfs, const char *oldpath, const char *newpath)
84004dbf
RS
1312{
1313 struct sync_cb_data cb_data;
1314
1315 cb_data.is_finished = 0;
1316
1317 if (nfs_link_async(nfs, oldpath, newpath, link_cb, &cb_data) != 0) {
1896d37b 1318 nfs_set_error(nfs, "nfs_link_async failed");
84004dbf
RS
1319 return -1;
1320 }
1321
b077fdeb 1322 wait_for_nfs_reply(nfs, &cb_data);
84004dbf
RS
1323
1324 return cb_data.status;
1325}
df5af25f 1326
739df145 1327void mount_getexports_cb(struct rpc_context *mount_context, int status, void *data, void *private_data)
df5af25f
RS
1328{
1329 struct sync_cb_data *cb_data = private_data;
9b6d1064 1330 exports export;
df5af25f 1331
f3a75078
RS
1332 assert(mount_context->magic == RPC_CONTEXT_MAGIC);
1333
df5af25f
RS
1334 cb_data->is_finished = 1;
1335 cb_data->status = status;
1336 cb_data->return_data = NULL;
1337
739df145
RS
1338 if (status != 0) {
1339 rpc_set_error(mount_context, "mount/export call failed with \"%s\"", (char *)data);
1340 return;
1341 }
1342
9b6d1064 1343 export = *(exports *)data;
df5af25f
RS
1344 while (export != NULL) {
1345 exports new_export;
1346
1347 new_export = malloc(sizeof(*new_export));
1348 memset(new_export, 0, sizeof(*new_export));
1349 new_export->ex_dir = strdup(export->ex_dir);
1350 new_export->ex_next = cb_data->return_data;
1351
1352 cb_data->return_data = new_export;
1353
1354 export = export->ex_next;
1355 }
1356}
1357
e210bd2a 1358struct exportnode *mount_getexports(const char *server)
df5af25f
RS
1359{
1360 struct sync_cb_data cb_data;
e210bd2a
RS
1361 struct rpc_context *rpc;
1362
df5af25f
RS
1363
1364 cb_data.is_finished = 0;
1365 cb_data.return_data = NULL;
1366
e210bd2a 1367 rpc = rpc_init_context();
df5af25f 1368 if (mount_getexports_async(rpc, server, mount_getexports_cb, &cb_data) != 0) {
e210bd2a 1369 rpc_destroy_context(rpc);
df5af25f
RS
1370 return NULL;
1371 }
1372
1373 wait_for_reply(rpc, &cb_data);
e210bd2a 1374 rpc_destroy_context(rpc);
df5af25f
RS
1375
1376 return cb_data.return_data;
1377}
1378
1379void mount_free_export_list(struct exportnode *exports)
1380{
1381 struct exportnode *tmp;
1382
1383 while ((tmp = exports)) {
1384 exports = exports->ex_next;
1385 free(tmp->ex_dir);
1386 free(tmp);
1387 }
1388}
1389
552c7665
RS
1390
1391
552c7665
RS
1392void free_nfs_srvr_list(struct nfs_server_list *srv)
1393{
1394 while (srv != NULL) {
1395 struct nfs_server_list *next = srv->next;
1396
1397 free(srv->addr);
1398 free(srv);
1399 srv = next;
1400 }
1f1b6cb0 1401}
552c7665
RS
1402
1403struct nfs_list_data {
1404 int status;
1405 struct nfs_server_list *srvrs;
1406};
1407
1408void callit_cb(struct rpc_context *rpc, int status, void *data _U_, void *private_data)
1409{
1410 struct nfs_list_data *srv_data = private_data;
1411 struct sockaddr *sin;
1412 char hostdd[16];
1413 struct nfs_server_list *srvr;
1414
f3a75078
RS
1415 assert(rpc->magic == RPC_CONTEXT_MAGIC);
1416
552c7665
RS
1417 if (status == RPC_STATUS_CANCEL) {
1418 return;
1419 }
1420 if (status != 0) {
1421 srv_data->status = -1;
1422 return;
1423 }
1424
1425 sin = rpc_get_recv_sockaddr(rpc);
1426 if (sin == NULL) {
1427 rpc_set_error(rpc, "failed to get sockaddr in CALLIT callback");
1428 srv_data->status = -1;
1429 return;
1430 }
1431
1432 if (getnameinfo(sin, sizeof(struct sockaddr_in), &hostdd[0], sizeof(hostdd), NULL, 0, NI_NUMERICHOST) < 0) {
1433 rpc_set_error(rpc, "getnameinfo failed in CALLIT callback");
1434 srv_data->status = -1;
1435 return;
1436 }
1f1b6cb0 1437
8c27363e
RS
1438 /* check for dupes */
1439 for (srvr = srv_data->srvrs; srvr; srvr = srvr->next) {
1440 if (!strcmp(hostdd, srvr->addr)) {
11ef53a2 1441 return;
8c27363e
RS
1442 }
1443 }
1444
552c7665
RS
1445 srvr = malloc(sizeof(struct nfs_server_list));
1446 if (srvr == NULL) {
1f1b6cb0 1447 rpc_set_error(rpc, "Malloc failed when allocating server structure");
552c7665
RS
1448 srv_data->status = -1;
1449 return;
1450 }
1451
1452 srvr->addr = strdup(hostdd);
1453 if (srvr->addr == NULL) {
1454 rpc_set_error(rpc, "Strdup failed when allocating server structure");
1455 free(srvr);
1456 srv_data->status = -1;
1457 return;
1458 }
1459
1460 srvr->next = srv_data->srvrs;
1461 srv_data->srvrs = srvr;
1462}
1463
fcc42bfe
M
1464#ifdef WIN32
1465
1466static int send_nfsd_probes(struct rpc_context *rpc, INTERFACE_INFO *InterfaceList, int numIfs, struct nfs_list_data *data)
1467{
1468 int i=0;
1469
f3a75078
RS
1470 assert(rpc->magic == RPC_CONTEXT_MAGIC);
1471
1f1b6cb0 1472 for(i = 0; i < numIfs; i++)
fcc42bfe
M
1473 {
1474 SOCKADDR *pAddress;
1475 char bcdd[16];
1476 unsigned long nFlags = 0;
1477
1478 pAddress = (SOCKADDR *) & (InterfaceList[i].iiBroadcastAddress);
1479
1480 if(pAddress->sa_family != AF_INET)
1481 continue;
1f1b6cb0 1482
fcc42bfe
M
1483 nFlags = InterfaceList[i].iiFlags;
1484
1f1b6cb0 1485 if (!(nFlags & IFF_UP))
fcc42bfe
M
1486 {
1487 continue;
1488 }
1489
1f1b6cb0 1490 if (nFlags & IFF_LOOPBACK)
fcc42bfe
M
1491 {
1492 continue;
1493 }
1494
1f1b6cb0 1495 if (!(nFlags & IFF_BROADCAST))
fcc42bfe
M
1496 {
1497 continue;
1498 }
1499
1f1b6cb0 1500 if (getnameinfo(pAddress, sizeof(struct sockaddr_in), &bcdd[0], sizeof(bcdd), NULL, 0, NI_NUMERICHOST) < 0)
fcc42bfe
M
1501 {
1502 continue;
1503 }
1504
1f1b6cb0 1505 if (rpc_set_udp_destination(rpc, bcdd, 111, 1) < 0)
fcc42bfe
M
1506 {
1507 return -1;
1508 }
1509
1f1b6cb0 1510 if (rpc_pmap2_callit_async(rpc, MOUNT_PROGRAM, 2, 0, NULL, 0, callit_cb, data) < 0)
fcc42bfe
M
1511 {
1512 return -1;
1513 }
1514 }
1515 return 0;
1516}
1517
1518struct nfs_server_list *nfs_find_local_servers(void)
1519{
1520 struct rpc_context *rpc;
1521 struct nfs_list_data data = {0, NULL};
1522 struct timeval tv_start, tv_current;
1523 int loop;
1524 struct pollfd pfd;
1525 INTERFACE_INFO InterfaceList[20];
1526 unsigned long nBytesReturned;
1527 int nNumInterfaces = 0;
1528
1529 rpc = rpc_init_udp_context();
1f1b6cb0 1530 if (rpc == NULL)
fcc42bfe
M
1531 {
1532 return NULL;
1533 }
1534
1f1b6cb0 1535 if (rpc_bind_udp(rpc, "0.0.0.0", 0) < 0)
fcc42bfe
M
1536 {
1537 rpc_destroy_context(rpc);
1538 return NULL;
1539 }
1540
1f1b6cb0 1541 if (WSAIoctl(rpc_get_fd(rpc), SIO_GET_INTERFACE_LIST, 0, 0, &InterfaceList, sizeof(InterfaceList), &nBytesReturned, 0, 0) == SOCKET_ERROR)
fcc42bfe
M
1542 {
1543 return NULL;
1544 }
1545
1546 nNumInterfaces = nBytesReturned / sizeof(INTERFACE_INFO);
1547
1f1b6cb0 1548 for (loop=0; loop<3; loop++)
fcc42bfe 1549 {
1f1b6cb0 1550 if (send_nfsd_probes(rpc, InterfaceList, nNumInterfaces, &data) != 0)
fcc42bfe
M
1551 {
1552 rpc_destroy_context(rpc);
1553 return NULL;
1554 }
1555
1556 win32_gettimeofday(&tv_start, NULL);
1f1b6cb0 1557 for(;;)
fcc42bfe
M
1558 {
1559 int mpt;
1560
1561 pfd.fd = rpc_get_fd(rpc);
1562 pfd.events = rpc_which_events(rpc);
1563
1564 win32_gettimeofday(&tv_current, NULL);
1565 mpt = 1000
1566 - (tv_current.tv_sec *1000 + tv_current.tv_usec / 1000)
1567 + (tv_start.tv_sec *1000 + tv_start.tv_usec / 1000);
1568
1f1b6cb0 1569 if (poll(&pfd, 1, mpt) < 0)
fcc42bfe
M
1570 {
1571 free_nfs_srvr_list(data.srvrs);
1572 rpc_destroy_context(rpc);
1573 return NULL;
1574 }
1f1b6cb0 1575 if (pfd.revents == 0)
fcc42bfe
M
1576 {
1577 break;
1578 }
1f1b6cb0
AR
1579
1580 if (rpc_service(rpc, pfd.revents) < 0)
fcc42bfe
M
1581 {
1582 break;
1583 }
1584 }
1585 }
1586
1587 rpc_destroy_context(rpc);
1588
1f1b6cb0 1589 if (data.status != 0)
fcc42bfe
M
1590 {
1591 free_nfs_srvr_list(data.srvrs);
1592 return NULL;
1593 }
1594 return data.srvrs;
1595}
1596#else
1597
e5964ef9 1598static int send_nfsd_probes(struct rpc_context *rpc, struct ifconf *ifc, struct nfs_list_data *data)
552c7665 1599{
1be803ce 1600 char *ptr;
552c7665 1601
f3a75078
RS
1602 assert(rpc->magic == RPC_CONTEXT_MAGIC);
1603
e5964ef9 1604 for (ptr =(char *)(ifc->ifc_buf); ptr < (char *)(ifc->ifc_buf) + ifc->ifc_len; ) {
1be803ce 1605 struct ifreq *ifr;
552c7665
RS
1606 char bcdd[16];
1607
1be803ce 1608 ifr = (struct ifreq *)ptr;
9a96dd46 1609#ifdef HAVE_SOCKADDR_LEN
1be803ce
RS
1610 if (ifr->ifr_addr.sa_len > sizeof(struct sockaddr)) {
1611 ptr += sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len;
1612 } else {
1613 ptr += sizeof(ifr->ifr_name) + sizeof(struct sockaddr);
1614 }
1615#else
1616 ptr += sizeof(struct ifreq);
1617#endif
1618
1619 if (ifr->ifr_addr.sa_family != AF_INET) {
552c7665
RS
1620 continue;
1621 }
1be803ce 1622 if (ioctl(rpc_get_fd(rpc), SIOCGIFFLAGS, ifr) < 0) {
e5964ef9 1623 return -1;
552c7665 1624 }
1be803ce 1625 if (!(ifr->ifr_flags & IFF_UP)) {
552c7665
RS
1626 continue;
1627 }
1be803ce 1628 if (ifr->ifr_flags & IFF_LOOPBACK) {
552c7665
RS
1629 continue;
1630 }
1be803ce 1631 if (!(ifr->ifr_flags & IFF_BROADCAST)) {
552c7665
RS
1632 continue;
1633 }
1be803ce 1634 if (ioctl(rpc_get_fd(rpc), SIOCGIFBRDADDR, ifr) < 0) {
1ad6f931 1635 continue;
552c7665 1636 }
1be803ce 1637 if (getnameinfo(&ifr->ifr_broadaddr, sizeof(struct sockaddr_in), &bcdd[0], sizeof(bcdd), NULL, 0, NI_NUMERICHOST) < 0) {
1ad6f931 1638 continue;
552c7665
RS
1639 }
1640 if (rpc_set_udp_destination(rpc, bcdd, 111, 1) < 0) {
e5964ef9
RS
1641 return -1;
1642 }
1643
0f0e352f 1644 if (rpc_pmap2_callit_async(rpc, MOUNT_PROGRAM, 2, 0, NULL, 0, callit_cb, data) < 0) {
e5964ef9 1645 return -1;
552c7665 1646 }
e5964ef9
RS
1647 }
1648
1649 return 0;
1650}
1651
1652struct nfs_server_list *nfs_find_local_servers(void)
1653{
1654 struct rpc_context *rpc;
1655 struct nfs_list_data data = {0, NULL};
1656 struct timeval tv_start, tv_current;
1657 struct ifconf ifc;
8c27363e 1658 int size, loop;
e5964ef9
RS
1659 struct pollfd pfd;
1660
1661 rpc = rpc_init_udp_context();
1662 if (rpc == NULL) {
1663 return NULL;
1664 }
1665
1666 if (rpc_bind_udp(rpc, "0.0.0.0", 0) < 0) {
1667 rpc_destroy_context(rpc);
1668 return NULL;
1669 }
1670
552c7665 1671
e5964ef9
RS
1672 /* get list of all interfaces */
1673 size = sizeof(struct ifreq);
1674 ifc.ifc_buf = NULL;
1675 ifc.ifc_len = size;
1676
1677 while(ifc.ifc_len > (size - sizeof(struct ifreq))) {
1678 size *= 2;
1679
1f1b6cb0 1680 free(ifc.ifc_buf);
e5964ef9
RS
1681 ifc.ifc_len = size;
1682 ifc.ifc_buf = malloc(size);
1683 memset(ifc.ifc_buf, 0, size);
1684 if (ioctl(rpc_get_fd(rpc), SIOCGIFCONF, (caddr_t)&ifc) < 0) {
552c7665 1685 rpc_destroy_context(rpc);
1f1b6cb0 1686 free(ifc.ifc_buf);
552c7665
RS
1687 return NULL;
1688 }
1f1b6cb0 1689 }
e5964ef9 1690
8c27363e
RS
1691 for (loop=0; loop<3; loop++) {
1692 if (send_nfsd_probes(rpc, &ifc, &data) != 0) {
552c7665 1693 rpc_destroy_context(rpc);
1f1b6cb0 1694 free(ifc.ifc_buf);
552c7665
RS
1695 return NULL;
1696 }
8c27363e
RS
1697
1698 gettimeofday(&tv_start, NULL);
1699 for(;;) {
1700 int mpt;
1701
1702 pfd.fd = rpc_get_fd(rpc);
1703 pfd.events = rpc_which_events(rpc);
1704
1705 gettimeofday(&tv_current, NULL);
1706 mpt = 1000
1707 - (tv_current.tv_sec *1000 + tv_current.tv_usec / 1000)
1708 + (tv_start.tv_sec *1000 + tv_start.tv_usec / 1000);
1709
1710 if (poll(&pfd, 1, mpt) < 0) {
1711 free_nfs_srvr_list(data.srvrs);
1712 rpc_destroy_context(rpc);
1713 return NULL;
1714 }
1715 if (pfd.revents == 0) {
1716 break;
1717 }
1f1b6cb0 1718
8c27363e
RS
1719 if (rpc_service(rpc, pfd.revents) < 0) {
1720 break;
1721 }
552c7665
RS
1722 }
1723 }
1724
1f1b6cb0 1725 free(ifc.ifc_buf);
552c7665
RS
1726 rpc_destroy_context(rpc);
1727
1728 if (data.status != 0) {
1729 free_nfs_srvr_list(data.srvrs);
1730 return NULL;
1731 }
552c7665
RS
1732 return data.srvrs;
1733}
fcc42bfe 1734#endif//WIN32