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