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