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