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