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