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