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