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