Add an assert to track if we try to use an rpc_context after it has been destroyed
[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 <assert.h>
42 #include <sys/types.h>
43 #include <sys/stat.h>
44 #include <fcntl.h>
45 #include <errno.h>
46
47 #ifdef HAVE_SYS_SOCKIO_H
48 #include <sys/sockio.h>
49 #endif
50
51 #include "libnfs.h"
52 #include "libnfs-raw.h"
53 #include "libnfs-raw-mount.h"
54 #include "libnfs-raw-nfs.h"
55 #include "libnfs-private.h"
56
57 struct sync_cb_data {
58 int is_finished;
59 int status;
60 uint64_t offset;
61 void *return_data;
62 int return_int;
63 };
64
65
66 static void wait_for_reply(struct rpc_context *rpc, struct sync_cb_data *cb_data)
67 {
68 struct pollfd pfd;
69
70 assert(rpc->magic == RPC_CONTEXT_MAGIC);
71
72 while (!cb_data->is_finished) {
73
74 pfd.fd = rpc_get_fd(rpc);
75 pfd.events = rpc_which_events(rpc);
76 if (poll(&pfd, 1, -1) < 0) {
77 rpc_set_error(rpc, "Poll failed");
78 cb_data->status = -EIO;
79 break;
80 }
81 if (rpc_service(rpc, pfd.revents) < 0) {
82 rpc_set_error(rpc, "rpc_service failed");
83 cb_data->status = -EIO;
84 break;
85 }
86 if (rpc_get_fd(rpc) == -1) {
87 rpc_set_error(rpc, "Socket closed\n");
88 break;
89 }
90 }
91 }
92
93 static void wait_for_nfs_reply(struct nfs_context *nfs, struct sync_cb_data *cb_data)
94 {
95 struct pollfd pfd;
96
97 while (!cb_data->is_finished) {
98
99 pfd.fd = nfs_get_fd(nfs);
100 pfd.events = nfs_which_events(nfs);
101 if (poll(&pfd, 1, -1) < 0) {
102 nfs_set_error(nfs, "Poll failed");
103 cb_data->status = -EIO;
104 break;
105 }
106 if (nfs_service(nfs, pfd.revents) < 0) {
107 nfs_set_error(nfs, "nfs_service failed");
108 cb_data->status = -EIO;
109 break;
110 }
111 }
112 }
113
114
115
116
117
118
119 /*
120 * connect to the server and mount the export
121 */
122 static void mount_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
123 {
124 struct sync_cb_data *cb_data = private_data;
125
126 cb_data->is_finished = 1;
127 cb_data->status = status;
128
129 if (status < 0) {
130 nfs_set_error(nfs, "mount/mnt call failed with \"%s\"", (char *)data);
131 return;
132 }
133 }
134
135 int nfs_mount(struct nfs_context *nfs, const char *server, const char *export)
136 {
137 struct sync_cb_data cb_data;
138 struct rpc_context *rpc = nfs_get_rpc_context(nfs);
139
140 assert(rpc->magic == RPC_CONTEXT_MAGIC);
141
142 cb_data.is_finished = 0;
143
144 if (nfs_mount_async(nfs, server, export, mount_cb, &cb_data) != 0) {
145 nfs_set_error(nfs, "nfs_mount_async failed");
146 return -1;
147 }
148
149 wait_for_nfs_reply(nfs, &cb_data);
150
151 /* Dont want any more callbacks even if the socket is closed */
152 rpc->connect_cb = NULL;
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, uint64_t offset, uint64_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, uint64_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, uint64_t offset, uint64_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, uint64_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, uint64_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, uint64_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 * mknod()
586 */
587 static void mknod_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
588 {
589 struct sync_cb_data *cb_data = private_data;
590
591 cb_data->is_finished = 1;
592 cb_data->status = status;
593
594 if (status < 0) {
595 nfs_set_error(nfs, "mknod call failed with \"%s\"", (char *)data);
596 return;
597 }
598 }
599
600 int nfs_mknod(struct nfs_context *nfs, const char *path, int mode, int dev)
601 {
602 struct sync_cb_data cb_data;
603
604 cb_data.is_finished = 0;
605
606 if (nfs_mknod_async(nfs, path, mode, dev, mknod_cb, &cb_data) != 0) {
607 nfs_set_error(nfs, "nfs_creat_async failed");
608 return -1;
609 }
610
611 wait_for_nfs_reply(nfs, &cb_data);
612
613 return cb_data.status;
614 }
615
616
617 /*
618 * unlink()
619 */
620 static void unlink_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
621 {
622 struct sync_cb_data *cb_data = private_data;
623
624 cb_data->is_finished = 1;
625 cb_data->status = status;
626
627 if (status < 0) {
628 nfs_set_error(nfs, "unlink call failed with \"%s\"", (char *)data);
629 return;
630 }
631 }
632
633 int nfs_unlink(struct nfs_context *nfs, const char *path)
634 {
635 struct sync_cb_data cb_data;
636
637 cb_data.is_finished = 0;
638
639 if (nfs_unlink_async(nfs, path, unlink_cb, &cb_data) != 0) {
640 nfs_set_error(nfs, "nfs_unlink_async failed");
641 return -1;
642 }
643
644 wait_for_nfs_reply(nfs, &cb_data);
645
646 return cb_data.status;
647 }
648
649
650
651 /*
652 * opendir()
653 */
654 static void opendir_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
655 {
656 struct sync_cb_data *cb_data = private_data;
657 struct nfsdir *dir, **nfsdir;
658
659 cb_data->is_finished = 1;
660 cb_data->status = status;
661
662 if (status < 0) {
663 nfs_set_error(nfs, "opendir call failed with \"%s\"", (char *)data);
664 return;
665 }
666
667 dir = data;
668 nfsdir = cb_data->return_data;
669 *nfsdir = dir;
670 }
671
672 int nfs_opendir(struct nfs_context *nfs, const char *path, struct nfsdir **nfsdir)
673 {
674 struct sync_cb_data cb_data;
675
676 cb_data.is_finished = 0;
677 cb_data.return_data = nfsdir;
678
679 if (nfs_opendir_async(nfs, path, opendir_cb, &cb_data) != 0) {
680 nfs_set_error(nfs, "nfs_opendir_async failed");
681 return -1;
682 }
683
684 wait_for_nfs_reply(nfs, &cb_data);
685
686 return cb_data.status;
687 }
688
689
690 /*
691 * lseek()
692 */
693 static void lseek_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
694 {
695 struct sync_cb_data *cb_data = private_data;
696
697 cb_data->is_finished = 1;
698 cb_data->status = status;
699
700 if (status < 0) {
701 nfs_set_error(nfs, "lseek call failed with \"%s\"", (char *)data);
702 return;
703 }
704
705 if (cb_data->return_data != NULL) {
706 memcpy(cb_data->return_data, data, sizeof(uint64_t));
707 }
708 }
709
710 int nfs_lseek(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, int whence, uint64_t *current_offset)
711 {
712 struct sync_cb_data cb_data;
713
714 cb_data.is_finished = 0;
715 cb_data.return_data = current_offset;
716
717 if (nfs_lseek_async(nfs, nfsfh, offset, whence, lseek_cb, &cb_data) != 0) {
718 nfs_set_error(nfs, "nfs_lseek_async failed");
719 return -1;
720 }
721
722 wait_for_nfs_reply(nfs, &cb_data);
723
724 return cb_data.status;
725 }
726
727
728
729 /*
730 * statvfs()
731 */
732 static void statvfs_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
733 {
734 struct sync_cb_data *cb_data = private_data;
735
736 cb_data->is_finished = 1;
737 cb_data->status = status;
738
739 if (status < 0) {
740 nfs_set_error(nfs, "statvfs call failed with \"%s\"", (char *)data);
741 return;
742 }
743
744 memcpy(cb_data->return_data, data, sizeof(struct statvfs));
745 }
746
747 int nfs_statvfs(struct nfs_context *nfs, const char *path, struct statvfs *svfs)
748 {
749 struct sync_cb_data cb_data;
750
751 cb_data.is_finished = 0;
752 cb_data.return_data = svfs;
753
754 if (nfs_statvfs_async(nfs, path, statvfs_cb, &cb_data) != 0) {
755 nfs_set_error(nfs, "nfs_statvfs_async failed");
756 return -1;
757 }
758
759 wait_for_nfs_reply(nfs, &cb_data);
760
761 return cb_data.status;
762 }
763
764
765
766
767
768 /*
769 * readlink()
770 */
771 static void readlink_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
772 {
773 struct sync_cb_data *cb_data = private_data;
774
775 cb_data->is_finished = 1;
776 cb_data->status = status;
777
778 if (status < 0) {
779 nfs_set_error(nfs, "readlink call failed with \"%s\"", (char *)data);
780 return;
781 }
782
783 if (strlen(data) > (size_t)cb_data->return_int) {
784 nfs_set_error(nfs, "Too small buffer for readlink");
785 cb_data->status = -ENAMETOOLONG;
786 return;
787 }
788
789 memcpy(cb_data->return_data, data, strlen(data)+1);
790 }
791
792 int nfs_readlink(struct nfs_context *nfs, const char *path, char *buf, int bufsize)
793 {
794 struct sync_cb_data cb_data;
795
796 cb_data.is_finished = 0;
797 cb_data.return_data = buf;
798 cb_data.return_int = bufsize;
799
800 if (nfs_readlink_async(nfs, path, readlink_cb, &cb_data) != 0) {
801 nfs_set_error(nfs, "nfs_readlink_async failed");
802 return -1;
803 }
804
805 wait_for_nfs_reply(nfs, &cb_data);
806
807 return cb_data.status;
808 }
809
810
811
812 /*
813 * chmod()
814 */
815 static void chmod_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
816 {
817 struct sync_cb_data *cb_data = private_data;
818
819 cb_data->is_finished = 1;
820 cb_data->status = status;
821
822 if (status < 0) {
823 nfs_set_error(nfs, "chmod call failed with \"%s\"", (char *)data);
824 return;
825 }
826 }
827
828 int nfs_chmod(struct nfs_context *nfs, const char *path, int mode)
829 {
830 struct sync_cb_data cb_data;
831
832 cb_data.is_finished = 0;
833
834 if (nfs_chmod_async(nfs, path, mode, chmod_cb, &cb_data) != 0) {
835 nfs_set_error(nfs, "nfs_chmod_async failed");
836 return -1;
837 }
838
839 wait_for_nfs_reply(nfs, &cb_data);
840
841 return cb_data.status;
842 }
843
844
845
846
847 /*
848 * fchmod()
849 */
850 static void fchmod_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
851 {
852 struct sync_cb_data *cb_data = private_data;
853
854 cb_data->is_finished = 1;
855 cb_data->status = status;
856
857 if (status < 0) {
858 nfs_set_error(nfs, "fchmod call failed with \"%s\"", (char *)data);
859 return;
860 }
861 }
862
863 int nfs_fchmod(struct nfs_context *nfs, struct nfsfh *nfsfh, int mode)
864 {
865 struct sync_cb_data cb_data;
866
867 cb_data.is_finished = 0;
868
869 if (nfs_fchmod_async(nfs, nfsfh, mode, fchmod_cb, &cb_data) != 0) {
870 nfs_set_error(nfs, "nfs_fchmod_async failed");
871 return -1;
872 }
873
874 wait_for_nfs_reply(nfs, &cb_data);
875
876 return cb_data.status;
877 }
878
879
880
881
882 /*
883 * chown()
884 */
885 static void chown_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
886 {
887 struct sync_cb_data *cb_data = private_data;
888
889 cb_data->is_finished = 1;
890 cb_data->status = status;
891
892 if (status < 0) {
893 nfs_set_error(nfs, "chown call failed with \"%s\"", (char *)data);
894 return;
895 }
896 }
897
898 int nfs_chown(struct nfs_context *nfs, const char *path, int uid, int gid)
899 {
900 struct sync_cb_data cb_data;
901
902 cb_data.is_finished = 0;
903
904 if (nfs_chown_async(nfs, path, uid, gid, chown_cb, &cb_data) != 0) {
905 nfs_set_error(nfs, "nfs_chown_async failed");
906 return -1;
907 }
908
909 wait_for_nfs_reply(nfs, &cb_data);
910
911 return cb_data.status;
912 }
913
914 /*
915 * fchown()
916 */
917 static void fchown_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
918 {
919 struct sync_cb_data *cb_data = private_data;
920
921 cb_data->is_finished = 1;
922 cb_data->status = status;
923
924 if (status < 0) {
925 nfs_set_error(nfs, "fchown call failed with \"%s\"", (char *)data);
926 return;
927 }
928 }
929
930 int nfs_fchown(struct nfs_context *nfs, struct nfsfh *nfsfh, int uid, int gid)
931 {
932 struct sync_cb_data cb_data;
933
934 cb_data.is_finished = 0;
935
936 if (nfs_fchown_async(nfs, nfsfh, uid, gid, fchown_cb, &cb_data) != 0) {
937 nfs_set_error(nfs, "nfs_fchown_async failed");
938 return -1;
939 }
940
941 wait_for_nfs_reply(nfs, &cb_data);
942
943 return cb_data.status;
944 }
945
946
947
948 /*
949 * utimes()
950 */
951 static void utimes_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
952 {
953 struct sync_cb_data *cb_data = private_data;
954
955 cb_data->is_finished = 1;
956 cb_data->status = status;
957
958 if (status < 0) {
959 nfs_set_error(nfs, "utimes call failed with \"%s\"", (char *)data);
960 return;
961 }
962 }
963
964 int nfs_utimes(struct nfs_context *nfs, const char *path, struct timeval *times)
965 {
966 struct sync_cb_data cb_data;
967
968 cb_data.is_finished = 0;
969
970 if (nfs_utimes_async(nfs, path, times, utimes_cb, &cb_data) != 0) {
971 nfs_set_error(nfs, "nfs_utimes_async failed");
972 return -1;
973 }
974
975 wait_for_nfs_reply(nfs, &cb_data);
976
977 return cb_data.status;
978 }
979
980
981
982 /*
983 * utime()
984 */
985 static void utime_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
986 {
987 struct sync_cb_data *cb_data = private_data;
988
989 cb_data->is_finished = 1;
990 cb_data->status = status;
991
992 if (status < 0) {
993 nfs_set_error(nfs, "utime call failed with \"%s\"", (char *)data);
994 return;
995 }
996 }
997
998 int nfs_utime(struct nfs_context *nfs, const char *path, struct utimbuf *times)
999 {
1000 struct sync_cb_data cb_data;
1001
1002 cb_data.is_finished = 0;
1003
1004 if (nfs_utime_async(nfs, path, times, utime_cb, &cb_data) != 0) {
1005 nfs_set_error(nfs, "nfs_utimes_async failed");
1006 return -1;
1007 }
1008
1009 wait_for_nfs_reply(nfs, &cb_data);
1010
1011 return cb_data.status;
1012 }
1013
1014
1015
1016
1017 /*
1018 * access()
1019 */
1020 static void access_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
1021 {
1022 struct sync_cb_data *cb_data = private_data;
1023
1024 cb_data->is_finished = 1;
1025 cb_data->status = status;
1026
1027 if (status < 0) {
1028 nfs_set_error(nfs, "access call failed with \"%s\"", (char *)data);
1029 return;
1030 }
1031 }
1032
1033 int nfs_access(struct nfs_context *nfs, const char *path, int mode)
1034 {
1035 struct sync_cb_data cb_data;
1036
1037 cb_data.is_finished = 0;
1038
1039 if (nfs_access_async(nfs, path, mode, access_cb, &cb_data) != 0) {
1040 nfs_set_error(nfs, "nfs_access_async failed");
1041 return -1;
1042 }
1043
1044 wait_for_nfs_reply(nfs, &cb_data);
1045
1046 return cb_data.status;
1047 }
1048
1049
1050
1051 /*
1052 * symlink()
1053 */
1054 static void symlink_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
1055 {
1056 struct sync_cb_data *cb_data = private_data;
1057
1058 cb_data->is_finished = 1;
1059 cb_data->status = status;
1060
1061 if (status < 0) {
1062 nfs_set_error(nfs, "symlink call failed with \"%s\"", (char *)data);
1063 return;
1064 }
1065 }
1066
1067 int nfs_symlink(struct nfs_context *nfs, const char *oldpath, const char *newpath)
1068 {
1069 struct sync_cb_data cb_data;
1070
1071 cb_data.is_finished = 0;
1072
1073 if (nfs_symlink_async(nfs, oldpath, newpath, symlink_cb, &cb_data) != 0) {
1074 nfs_set_error(nfs, "nfs_symlink_async failed");
1075 return -1;
1076 }
1077
1078 wait_for_nfs_reply(nfs, &cb_data);
1079
1080 return cb_data.status;
1081 }
1082
1083
1084
1085 /*
1086 * rename()
1087 */
1088 static void rename_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
1089 {
1090 struct sync_cb_data *cb_data = private_data;
1091
1092 cb_data->is_finished = 1;
1093 cb_data->status = status;
1094
1095 if (status < 0) {
1096 nfs_set_error(nfs, "rename call failed with \"%s\"", (char *)data);
1097 return;
1098 }
1099 }
1100
1101 int nfs_rename(struct nfs_context *nfs, const char *oldpath, const char *newpath)
1102 {
1103 struct sync_cb_data cb_data;
1104
1105 cb_data.is_finished = 0;
1106
1107 if (nfs_rename_async(nfs, oldpath, newpath, rename_cb, &cb_data) != 0) {
1108 nfs_set_error(nfs, "nfs_rename_async failed");
1109 return -1;
1110 }
1111
1112 wait_for_nfs_reply(nfs, &cb_data);
1113
1114 return cb_data.status;
1115 }
1116
1117
1118
1119 /*
1120 * link()
1121 */
1122 static void link_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
1123 {
1124 struct sync_cb_data *cb_data = private_data;
1125
1126 cb_data->is_finished = 1;
1127 cb_data->status = status;
1128
1129 if (status < 0) {
1130 nfs_set_error(nfs, "link call failed with \"%s\"", (char *)data);
1131 return;
1132 }
1133 }
1134
1135 int nfs_link(struct nfs_context *nfs, const char *oldpath, const char *newpath)
1136 {
1137 struct sync_cb_data cb_data;
1138
1139 cb_data.is_finished = 0;
1140
1141 if (nfs_link_async(nfs, oldpath, newpath, link_cb, &cb_data) != 0) {
1142 nfs_set_error(nfs, "nfs_link_async failed");
1143 return -1;
1144 }
1145
1146 wait_for_nfs_reply(nfs, &cb_data);
1147
1148 return cb_data.status;
1149 }
1150
1151 void mount_getexports_cb(struct rpc_context *mount_context, int status, void *data, void *private_data)
1152 {
1153 struct sync_cb_data *cb_data = private_data;
1154 exports export;
1155
1156 assert(mount_context->magic == RPC_CONTEXT_MAGIC);
1157
1158 cb_data->is_finished = 1;
1159 cb_data->status = status;
1160 cb_data->return_data = NULL;
1161
1162 if (status != 0) {
1163 rpc_set_error(mount_context, "mount/export call failed with \"%s\"", (char *)data);
1164 return;
1165 }
1166
1167 export = *(exports *)data;
1168 while (export != NULL) {
1169 exports new_export;
1170
1171 new_export = malloc(sizeof(*new_export));
1172 memset(new_export, 0, sizeof(*new_export));
1173 new_export->ex_dir = strdup(export->ex_dir);
1174 new_export->ex_next = cb_data->return_data;
1175
1176 cb_data->return_data = new_export;
1177
1178 export = export->ex_next;
1179 }
1180 }
1181
1182 struct exportnode *mount_getexports(const char *server)
1183 {
1184 struct sync_cb_data cb_data;
1185 struct rpc_context *rpc;
1186
1187
1188 cb_data.is_finished = 0;
1189 cb_data.return_data = NULL;
1190
1191 rpc = rpc_init_context();
1192 if (mount_getexports_async(rpc, server, mount_getexports_cb, &cb_data) != 0) {
1193 rpc_destroy_context(rpc);
1194 return NULL;
1195 }
1196
1197 wait_for_reply(rpc, &cb_data);
1198 rpc_destroy_context(rpc);
1199
1200 return cb_data.return_data;
1201 }
1202
1203 void mount_free_export_list(struct exportnode *exports)
1204 {
1205 struct exportnode *tmp;
1206
1207 while ((tmp = exports)) {
1208 exports = exports->ex_next;
1209 free(tmp->ex_dir);
1210 free(tmp);
1211 }
1212 }
1213
1214
1215
1216 void free_nfs_srvr_list(struct nfs_server_list *srv)
1217 {
1218 while (srv != NULL) {
1219 struct nfs_server_list *next = srv->next;
1220
1221 free(srv->addr);
1222 free(srv);
1223 srv = next;
1224 }
1225 }
1226
1227 struct nfs_list_data {
1228 int status;
1229 struct nfs_server_list *srvrs;
1230 };
1231
1232 void callit_cb(struct rpc_context *rpc, int status, void *data _U_, void *private_data)
1233 {
1234 struct nfs_list_data *srv_data = private_data;
1235 struct sockaddr *sin;
1236 char hostdd[16];
1237 struct nfs_server_list *srvr;
1238
1239 assert(rpc->magic == RPC_CONTEXT_MAGIC);
1240
1241 if (status == RPC_STATUS_CANCEL) {
1242 return;
1243 }
1244 if (status != 0) {
1245 srv_data->status = -1;
1246 return;
1247 }
1248
1249 sin = rpc_get_recv_sockaddr(rpc);
1250 if (sin == NULL) {
1251 rpc_set_error(rpc, "failed to get sockaddr in CALLIT callback");
1252 srv_data->status = -1;
1253 return;
1254 }
1255
1256 if (getnameinfo(sin, sizeof(struct sockaddr_in), &hostdd[0], sizeof(hostdd), NULL, 0, NI_NUMERICHOST) < 0) {
1257 rpc_set_error(rpc, "getnameinfo failed in CALLIT callback");
1258 srv_data->status = -1;
1259 return;
1260 }
1261
1262 /* check for dupes */
1263 for (srvr = srv_data->srvrs; srvr; srvr = srvr->next) {
1264 if (!strcmp(hostdd, srvr->addr)) {
1265 return;
1266 }
1267 }
1268
1269 srvr = malloc(sizeof(struct nfs_server_list));
1270 if (srvr == NULL) {
1271 rpc_set_error(rpc, "Malloc failed when allocating server structure");
1272 srv_data->status = -1;
1273 return;
1274 }
1275
1276 srvr->addr = strdup(hostdd);
1277 if (srvr->addr == NULL) {
1278 rpc_set_error(rpc, "Strdup failed when allocating server structure");
1279 free(srvr);
1280 srv_data->status = -1;
1281 return;
1282 }
1283
1284 srvr->next = srv_data->srvrs;
1285 srv_data->srvrs = srvr;
1286 }
1287
1288 #ifdef WIN32
1289
1290 static int send_nfsd_probes(struct rpc_context *rpc, INTERFACE_INFO *InterfaceList, int numIfs, struct nfs_list_data *data)
1291 {
1292 int i=0;
1293
1294 assert(rpc->magic == RPC_CONTEXT_MAGIC);
1295
1296 for(i = 0; i < numIfs; i++)
1297 {
1298 SOCKADDR *pAddress;
1299 char bcdd[16];
1300 unsigned long nFlags = 0;
1301
1302 pAddress = (SOCKADDR *) & (InterfaceList[i].iiBroadcastAddress);
1303
1304 if(pAddress->sa_family != AF_INET)
1305 continue;
1306
1307 nFlags = InterfaceList[i].iiFlags;
1308
1309 if (!(nFlags & IFF_UP))
1310 {
1311 continue;
1312 }
1313
1314 if (nFlags & IFF_LOOPBACK)
1315 {
1316 continue;
1317 }
1318
1319 if (!(nFlags & IFF_BROADCAST))
1320 {
1321 continue;
1322 }
1323
1324 if (getnameinfo(pAddress, sizeof(struct sockaddr_in), &bcdd[0], sizeof(bcdd), NULL, 0, NI_NUMERICHOST) < 0)
1325 {
1326 continue;
1327 }
1328
1329 if (rpc_set_udp_destination(rpc, bcdd, 111, 1) < 0)
1330 {
1331 return -1;
1332 }
1333
1334 if (rpc_pmap_callit_async(rpc, MOUNT_PROGRAM, 2, 0, NULL, 0, callit_cb, data) < 0)
1335 {
1336 return -1;
1337 }
1338 }
1339 return 0;
1340 }
1341
1342 struct nfs_server_list *nfs_find_local_servers(void)
1343 {
1344 struct rpc_context *rpc;
1345 struct nfs_list_data data = {0, NULL};
1346 struct timeval tv_start, tv_current;
1347 int loop;
1348 struct pollfd pfd;
1349 INTERFACE_INFO InterfaceList[20];
1350 unsigned long nBytesReturned;
1351 int nNumInterfaces = 0;
1352
1353 rpc = rpc_init_udp_context();
1354 if (rpc == NULL)
1355 {
1356 return NULL;
1357 }
1358
1359 if (rpc_bind_udp(rpc, "0.0.0.0", 0) < 0)
1360 {
1361 rpc_destroy_context(rpc);
1362 return NULL;
1363 }
1364
1365 if (WSAIoctl(rpc_get_fd(rpc), SIO_GET_INTERFACE_LIST, 0, 0, &InterfaceList, sizeof(InterfaceList), &nBytesReturned, 0, 0) == SOCKET_ERROR)
1366 {
1367 return NULL;
1368 }
1369
1370 nNumInterfaces = nBytesReturned / sizeof(INTERFACE_INFO);
1371
1372 for (loop=0; loop<3; loop++)
1373 {
1374 if (send_nfsd_probes(rpc, InterfaceList, nNumInterfaces, &data) != 0)
1375 {
1376 rpc_destroy_context(rpc);
1377 return NULL;
1378 }
1379
1380 win32_gettimeofday(&tv_start, NULL);
1381 for(;;)
1382 {
1383 int mpt;
1384
1385 pfd.fd = rpc_get_fd(rpc);
1386 pfd.events = rpc_which_events(rpc);
1387
1388 win32_gettimeofday(&tv_current, NULL);
1389 mpt = 1000
1390 - (tv_current.tv_sec *1000 + tv_current.tv_usec / 1000)
1391 + (tv_start.tv_sec *1000 + tv_start.tv_usec / 1000);
1392
1393 if (poll(&pfd, 1, mpt) < 0)
1394 {
1395 free_nfs_srvr_list(data.srvrs);
1396 rpc_destroy_context(rpc);
1397 return NULL;
1398 }
1399 if (pfd.revents == 0)
1400 {
1401 break;
1402 }
1403
1404 if (rpc_service(rpc, pfd.revents) < 0)
1405 {
1406 break;
1407 }
1408 }
1409 }
1410
1411 rpc_destroy_context(rpc);
1412
1413 if (data.status != 0)
1414 {
1415 free_nfs_srvr_list(data.srvrs);
1416 return NULL;
1417 }
1418 return data.srvrs;
1419 }
1420 #else
1421
1422 static int send_nfsd_probes(struct rpc_context *rpc, struct ifconf *ifc, struct nfs_list_data *data)
1423 {
1424 char *ptr;
1425
1426 assert(rpc->magic == RPC_CONTEXT_MAGIC);
1427
1428 for (ptr =(char *)(ifc->ifc_buf); ptr < (char *)(ifc->ifc_buf) + ifc->ifc_len; ) {
1429 struct ifreq *ifr;
1430 char bcdd[16];
1431
1432 ifr = (struct ifreq *)ptr;
1433 #ifdef HAVE_SOCKADDR_LEN
1434 if (ifr->ifr_addr.sa_len > sizeof(struct sockaddr)) {
1435 ptr += sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len;
1436 } else {
1437 ptr += sizeof(ifr->ifr_name) + sizeof(struct sockaddr);
1438 }
1439 #else
1440 ptr += sizeof(struct ifreq);
1441 #endif
1442
1443 if (ifr->ifr_addr.sa_family != AF_INET) {
1444 continue;
1445 }
1446 if (ioctl(rpc_get_fd(rpc), SIOCGIFFLAGS, ifr) < 0) {
1447 return -1;
1448 }
1449 if (!(ifr->ifr_flags & IFF_UP)) {
1450 continue;
1451 }
1452 if (ifr->ifr_flags & IFF_LOOPBACK) {
1453 continue;
1454 }
1455 if (!(ifr->ifr_flags & IFF_BROADCAST)) {
1456 continue;
1457 }
1458 if (ioctl(rpc_get_fd(rpc), SIOCGIFBRDADDR, ifr) < 0) {
1459 continue;
1460 }
1461 if (getnameinfo(&ifr->ifr_broadaddr, sizeof(struct sockaddr_in), &bcdd[0], sizeof(bcdd), NULL, 0, NI_NUMERICHOST) < 0) {
1462 continue;
1463 }
1464 if (rpc_set_udp_destination(rpc, bcdd, 111, 1) < 0) {
1465 return -1;
1466 }
1467
1468 if (rpc_pmap_callit_async(rpc, MOUNT_PROGRAM, 2, 0, NULL, 0, callit_cb, data) < 0) {
1469 return -1;
1470 }
1471 }
1472
1473 return 0;
1474 }
1475
1476 struct nfs_server_list *nfs_find_local_servers(void)
1477 {
1478 struct rpc_context *rpc;
1479 struct nfs_list_data data = {0, NULL};
1480 struct timeval tv_start, tv_current;
1481 struct ifconf ifc;
1482 int size, loop;
1483 struct pollfd pfd;
1484
1485 rpc = rpc_init_udp_context();
1486 if (rpc == NULL) {
1487 return NULL;
1488 }
1489
1490 if (rpc_bind_udp(rpc, "0.0.0.0", 0) < 0) {
1491 rpc_destroy_context(rpc);
1492 return NULL;
1493 }
1494
1495
1496 /* get list of all interfaces */
1497 size = sizeof(struct ifreq);
1498 ifc.ifc_buf = NULL;
1499 ifc.ifc_len = size;
1500
1501 while(ifc.ifc_len > (size - sizeof(struct ifreq))) {
1502 size *= 2;
1503
1504 free(ifc.ifc_buf);
1505 ifc.ifc_len = size;
1506 ifc.ifc_buf = malloc(size);
1507 memset(ifc.ifc_buf, 0, size);
1508 if (ioctl(rpc_get_fd(rpc), SIOCGIFCONF, (caddr_t)&ifc) < 0) {
1509 rpc_destroy_context(rpc);
1510 free(ifc.ifc_buf);
1511 return NULL;
1512 }
1513 }
1514
1515 for (loop=0; loop<3; loop++) {
1516 if (send_nfsd_probes(rpc, &ifc, &data) != 0) {
1517 rpc_destroy_context(rpc);
1518 free(ifc.ifc_buf);
1519 return NULL;
1520 }
1521
1522 gettimeofday(&tv_start, NULL);
1523 for(;;) {
1524 int mpt;
1525
1526 pfd.fd = rpc_get_fd(rpc);
1527 pfd.events = rpc_which_events(rpc);
1528
1529 gettimeofday(&tv_current, NULL);
1530 mpt = 1000
1531 - (tv_current.tv_sec *1000 + tv_current.tv_usec / 1000)
1532 + (tv_start.tv_sec *1000 + tv_start.tv_usec / 1000);
1533
1534 if (poll(&pfd, 1, mpt) < 0) {
1535 free_nfs_srvr_list(data.srvrs);
1536 rpc_destroy_context(rpc);
1537 return NULL;
1538 }
1539 if (pfd.revents == 0) {
1540 break;
1541 }
1542
1543 if (rpc_service(rpc, pfd.revents) < 0) {
1544 break;
1545 }
1546 }
1547 }
1548
1549 free(ifc.ifc_buf);
1550 rpc_destroy_context(rpc);
1551
1552 if (data.status != 0) {
1553 free_nfs_srvr_list(data.srvrs);
1554 return NULL;
1555 }
1556 return data.srvrs;
1557 }
1558 #endif//WIN32