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