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