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