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