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