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