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