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