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