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