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