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