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