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