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