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