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