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