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