Remove all [s]size_t / off_t and replace with [u]int64_t making libnfs 64-bit pure
[deb_libnfs.git] / lib / libnfs-sync.c
1 /*
2 Copyright (C) 2010 by Ronnie Sahlberg <ronniesahlberg@gmail.com>
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 2.1 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program; if not, see <http://www.gnu.org/licenses/>.
16 */
17 /*
18 * High level api to nfs filesystems
19 */
20 #ifdef WIN32
21 #include "win32_compat.h"
22 #define DllExport
23 #else
24 #include <strings.h>
25 #include <unistd.h>
26 #include <sys/statvfs.h>
27 #include <poll.h>
28 #include <sys/ioctl.h>
29 #include <netdb.h>
30 #include <sys/socket.h>
31 #include <net/if.h>
32 #endif
33
34 #ifdef HAVE_CONFIG_H
35 #include "config.h"
36 #endif
37
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 #include <fcntl.h>
44 #include <errno.h>
45
46 #ifdef HAVE_SYS_SOCKIO_H
47 #include <sys/sockio.h>
48 #endif
49
50 #include "libnfs.h"
51 #include "libnfs-raw.h"
52 #include "libnfs-raw-mount.h"
53 #include "libnfs-raw-nfs.h"
54 #include "libnfs-private.h"
55
56 struct sync_cb_data {
57 int is_finished;
58 int status;
59 uint64_t offset;
60 void *return_data;
61 int return_int;
62 };
63
64
65 static 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
90 static 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 */
119 static 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
132 int 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 */
156 static 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
171 int 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 */
194 static 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
212 int 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 */
235 static 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
251 int nfs_pread(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, uint64_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 */
271 int nfs_read(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t count, char *buffer)
272 {
273 return nfs_pread(nfs, nfsfh, nfs_get_current_offset(nfsfh), count, buffer);
274 }
275
276 /*
277 * close()
278 */
279 static 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
291 int 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 */
313 int 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 */
334 static 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
346 int nfs_pwrite(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, uint64_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 */
365 int nfs_write(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_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 */
374 static 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
386 int 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 */
408 static 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
420 int nfs_ftruncate(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_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 */
441 static 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
453 int nfs_truncate(struct nfs_context *nfs, const char *path, uint64_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 */
476 static 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
488 int 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 */
511 static 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
523 int 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 */
544 static 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
562 int 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 * mknod()
581 */
582 static void mknod_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
583 {
584 struct sync_cb_data *cb_data = private_data;
585
586 cb_data->is_finished = 1;
587 cb_data->status = status;
588
589 if (status < 0) {
590 nfs_set_error(nfs, "mknod call failed with \"%s\"", (char *)data);
591 return;
592 }
593 }
594
595 int nfs_mknod(struct nfs_context *nfs, const char *path, int mode, int dev)
596 {
597 struct sync_cb_data cb_data;
598
599 cb_data.is_finished = 0;
600
601 if (nfs_mknod_async(nfs, path, mode, dev, mknod_cb, &cb_data) != 0) {
602 nfs_set_error(nfs, "nfs_creat_async failed");
603 return -1;
604 }
605
606 wait_for_nfs_reply(nfs, &cb_data);
607
608 return cb_data.status;
609 }
610
611
612 /*
613 * unlink()
614 */
615 static void unlink_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
616 {
617 struct sync_cb_data *cb_data = private_data;
618
619 cb_data->is_finished = 1;
620 cb_data->status = status;
621
622 if (status < 0) {
623 nfs_set_error(nfs, "unlink call failed with \"%s\"", (char *)data);
624 return;
625 }
626 }
627
628 int nfs_unlink(struct nfs_context *nfs, const char *path)
629 {
630 struct sync_cb_data cb_data;
631
632 cb_data.is_finished = 0;
633
634 if (nfs_unlink_async(nfs, path, unlink_cb, &cb_data) != 0) {
635 nfs_set_error(nfs, "nfs_unlink_async failed");
636 return -1;
637 }
638
639 wait_for_nfs_reply(nfs, &cb_data);
640
641 return cb_data.status;
642 }
643
644
645
646 /*
647 * opendir()
648 */
649 static void opendir_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
650 {
651 struct sync_cb_data *cb_data = private_data;
652 struct nfsdir *dir, **nfsdir;
653
654 cb_data->is_finished = 1;
655 cb_data->status = status;
656
657 if (status < 0) {
658 nfs_set_error(nfs, "opendir call failed with \"%s\"", (char *)data);
659 return;
660 }
661
662 dir = data;
663 nfsdir = cb_data->return_data;
664 *nfsdir = dir;
665 }
666
667 int nfs_opendir(struct nfs_context *nfs, const char *path, struct nfsdir **nfsdir)
668 {
669 struct sync_cb_data cb_data;
670
671 cb_data.is_finished = 0;
672 cb_data.return_data = nfsdir;
673
674 if (nfs_opendir_async(nfs, path, opendir_cb, &cb_data) != 0) {
675 nfs_set_error(nfs, "nfs_opendir_async failed");
676 return -1;
677 }
678
679 wait_for_nfs_reply(nfs, &cb_data);
680
681 return cb_data.status;
682 }
683
684
685 /*
686 * lseek()
687 */
688 static void lseek_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
689 {
690 struct sync_cb_data *cb_data = private_data;
691
692 cb_data->is_finished = 1;
693 cb_data->status = status;
694
695 if (status < 0) {
696 nfs_set_error(nfs, "lseek call failed with \"%s\"", (char *)data);
697 return;
698 }
699
700 if (cb_data->return_data != NULL) {
701 memcpy(cb_data->return_data, data, sizeof(uint64_t));
702 }
703 }
704
705 int nfs_lseek(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, int whence, uint64_t *current_offset)
706 {
707 struct sync_cb_data cb_data;
708
709 cb_data.is_finished = 0;
710 cb_data.return_data = current_offset;
711
712 if (nfs_lseek_async(nfs, nfsfh, offset, whence, lseek_cb, &cb_data) != 0) {
713 nfs_set_error(nfs, "nfs_lseek_async failed");
714 return -1;
715 }
716
717 wait_for_nfs_reply(nfs, &cb_data);
718
719 return cb_data.status;
720 }
721
722
723
724 /*
725 * statvfs()
726 */
727 static void statvfs_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
728 {
729 struct sync_cb_data *cb_data = private_data;
730
731 cb_data->is_finished = 1;
732 cb_data->status = status;
733
734 if (status < 0) {
735 nfs_set_error(nfs, "statvfs call failed with \"%s\"", (char *)data);
736 return;
737 }
738
739 memcpy(cb_data->return_data, data, sizeof(struct statvfs));
740 }
741
742 int nfs_statvfs(struct nfs_context *nfs, const char *path, struct statvfs *svfs)
743 {
744 struct sync_cb_data cb_data;
745
746 cb_data.is_finished = 0;
747 cb_data.return_data = svfs;
748
749 if (nfs_statvfs_async(nfs, path, statvfs_cb, &cb_data) != 0) {
750 nfs_set_error(nfs, "nfs_statvfs_async failed");
751 return -1;
752 }
753
754 wait_for_nfs_reply(nfs, &cb_data);
755
756 return cb_data.status;
757 }
758
759
760
761
762
763 /*
764 * readlink()
765 */
766 static void readlink_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
767 {
768 struct sync_cb_data *cb_data = private_data;
769
770 cb_data->is_finished = 1;
771 cb_data->status = status;
772
773 if (status < 0) {
774 nfs_set_error(nfs, "readlink call failed with \"%s\"", (char *)data);
775 return;
776 }
777
778 if (strlen(data) > (size_t)cb_data->return_int) {
779 nfs_set_error(nfs, "Too small buffer for readlink");
780 cb_data->status = -ENAMETOOLONG;
781 return;
782 }
783
784 memcpy(cb_data->return_data, data, strlen(data)+1);
785 }
786
787 int nfs_readlink(struct nfs_context *nfs, const char *path, char *buf, int bufsize)
788 {
789 struct sync_cb_data cb_data;
790
791 cb_data.is_finished = 0;
792 cb_data.return_data = buf;
793 cb_data.return_int = bufsize;
794
795 if (nfs_readlink_async(nfs, path, readlink_cb, &cb_data) != 0) {
796 nfs_set_error(nfs, "nfs_readlink_async failed");
797 return -1;
798 }
799
800 wait_for_nfs_reply(nfs, &cb_data);
801
802 return cb_data.status;
803 }
804
805
806
807 /*
808 * chmod()
809 */
810 static void chmod_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, "chmod call failed with \"%s\"", (char *)data);
819 return;
820 }
821 }
822
823 int nfs_chmod(struct nfs_context *nfs, const char *path, int mode)
824 {
825 struct sync_cb_data cb_data;
826
827 cb_data.is_finished = 0;
828
829 if (nfs_chmod_async(nfs, path, mode, chmod_cb, &cb_data) != 0) {
830 nfs_set_error(nfs, "nfs_chmod_async failed");
831 return -1;
832 }
833
834 wait_for_nfs_reply(nfs, &cb_data);
835
836 return cb_data.status;
837 }
838
839
840
841
842 /*
843 * fchmod()
844 */
845 static void fchmod_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
846 {
847 struct sync_cb_data *cb_data = private_data;
848
849 cb_data->is_finished = 1;
850 cb_data->status = status;
851
852 if (status < 0) {
853 nfs_set_error(nfs, "fchmod call failed with \"%s\"", (char *)data);
854 return;
855 }
856 }
857
858 int nfs_fchmod(struct nfs_context *nfs, struct nfsfh *nfsfh, int mode)
859 {
860 struct sync_cb_data cb_data;
861
862 cb_data.is_finished = 0;
863
864 if (nfs_fchmod_async(nfs, nfsfh, mode, fchmod_cb, &cb_data) != 0) {
865 nfs_set_error(nfs, "nfs_fchmod_async failed");
866 return -1;
867 }
868
869 wait_for_nfs_reply(nfs, &cb_data);
870
871 return cb_data.status;
872 }
873
874
875
876
877 /*
878 * chown()
879 */
880 static void chown_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
881 {
882 struct sync_cb_data *cb_data = private_data;
883
884 cb_data->is_finished = 1;
885 cb_data->status = status;
886
887 if (status < 0) {
888 nfs_set_error(nfs, "chown call failed with \"%s\"", (char *)data);
889 return;
890 }
891 }
892
893 int nfs_chown(struct nfs_context *nfs, const char *path, int uid, int gid)
894 {
895 struct sync_cb_data cb_data;
896
897 cb_data.is_finished = 0;
898
899 if (nfs_chown_async(nfs, path, uid, gid, chown_cb, &cb_data) != 0) {
900 nfs_set_error(nfs, "nfs_chown_async failed");
901 return -1;
902 }
903
904 wait_for_nfs_reply(nfs, &cb_data);
905
906 return cb_data.status;
907 }
908
909 /*
910 * fchown()
911 */
912 static void fchown_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
913 {
914 struct sync_cb_data *cb_data = private_data;
915
916 cb_data->is_finished = 1;
917 cb_data->status = status;
918
919 if (status < 0) {
920 nfs_set_error(nfs, "fchown call failed with \"%s\"", (char *)data);
921 return;
922 }
923 }
924
925 int nfs_fchown(struct nfs_context *nfs, struct nfsfh *nfsfh, int uid, int gid)
926 {
927 struct sync_cb_data cb_data;
928
929 cb_data.is_finished = 0;
930
931 if (nfs_fchown_async(nfs, nfsfh, uid, gid, fchown_cb, &cb_data) != 0) {
932 nfs_set_error(nfs, "nfs_fchown_async failed");
933 return -1;
934 }
935
936 wait_for_nfs_reply(nfs, &cb_data);
937
938 return cb_data.status;
939 }
940
941
942
943 /*
944 * utimes()
945 */
946 static void utimes_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
947 {
948 struct sync_cb_data *cb_data = private_data;
949
950 cb_data->is_finished = 1;
951 cb_data->status = status;
952
953 if (status < 0) {
954 nfs_set_error(nfs, "utimes call failed with \"%s\"", (char *)data);
955 return;
956 }
957 }
958
959 int nfs_utimes(struct nfs_context *nfs, const char *path, struct timeval *times)
960 {
961 struct sync_cb_data cb_data;
962
963 cb_data.is_finished = 0;
964
965 if (nfs_utimes_async(nfs, path, times, utimes_cb, &cb_data) != 0) {
966 nfs_set_error(nfs, "nfs_utimes_async failed");
967 return -1;
968 }
969
970 wait_for_nfs_reply(nfs, &cb_data);
971
972 return cb_data.status;
973 }
974
975
976
977 /*
978 * utime()
979 */
980 static void utime_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
981 {
982 struct sync_cb_data *cb_data = private_data;
983
984 cb_data->is_finished = 1;
985 cb_data->status = status;
986
987 if (status < 0) {
988 nfs_set_error(nfs, "utime call failed with \"%s\"", (char *)data);
989 return;
990 }
991 }
992
993 int nfs_utime(struct nfs_context *nfs, const char *path, struct utimbuf *times)
994 {
995 struct sync_cb_data cb_data;
996
997 cb_data.is_finished = 0;
998
999 if (nfs_utime_async(nfs, path, times, utime_cb, &cb_data) != 0) {
1000 nfs_set_error(nfs, "nfs_utimes_async failed");
1001 return -1;
1002 }
1003
1004 wait_for_nfs_reply(nfs, &cb_data);
1005
1006 return cb_data.status;
1007 }
1008
1009
1010
1011
1012 /*
1013 * access()
1014 */
1015 static void access_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
1016 {
1017 struct sync_cb_data *cb_data = private_data;
1018
1019 cb_data->is_finished = 1;
1020 cb_data->status = status;
1021
1022 if (status < 0) {
1023 nfs_set_error(nfs, "access call failed with \"%s\"", (char *)data);
1024 return;
1025 }
1026 }
1027
1028 int nfs_access(struct nfs_context *nfs, const char *path, int mode)
1029 {
1030 struct sync_cb_data cb_data;
1031
1032 cb_data.is_finished = 0;
1033
1034 if (nfs_access_async(nfs, path, mode, access_cb, &cb_data) != 0) {
1035 nfs_set_error(nfs, "nfs_access_async failed");
1036 return -1;
1037 }
1038
1039 wait_for_nfs_reply(nfs, &cb_data);
1040
1041 return cb_data.status;
1042 }
1043
1044
1045
1046 /*
1047 * symlink()
1048 */
1049 static void symlink_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
1050 {
1051 struct sync_cb_data *cb_data = private_data;
1052
1053 cb_data->is_finished = 1;
1054 cb_data->status = status;
1055
1056 if (status < 0) {
1057 nfs_set_error(nfs, "symlink call failed with \"%s\"", (char *)data);
1058 return;
1059 }
1060 }
1061
1062 int nfs_symlink(struct nfs_context *nfs, const char *oldpath, const char *newpath)
1063 {
1064 struct sync_cb_data cb_data;
1065
1066 cb_data.is_finished = 0;
1067
1068 if (nfs_symlink_async(nfs, oldpath, newpath, symlink_cb, &cb_data) != 0) {
1069 nfs_set_error(nfs, "nfs_symlink_async failed");
1070 return -1;
1071 }
1072
1073 wait_for_nfs_reply(nfs, &cb_data);
1074
1075 return cb_data.status;
1076 }
1077
1078
1079
1080 /*
1081 * rename()
1082 */
1083 static void rename_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
1084 {
1085 struct sync_cb_data *cb_data = private_data;
1086
1087 cb_data->is_finished = 1;
1088 cb_data->status = status;
1089
1090 if (status < 0) {
1091 nfs_set_error(nfs, "rename call failed with \"%s\"", (char *)data);
1092 return;
1093 }
1094 }
1095
1096 int nfs_rename(struct nfs_context *nfs, const char *oldpath, const char *newpath)
1097 {
1098 struct sync_cb_data cb_data;
1099
1100 cb_data.is_finished = 0;
1101
1102 if (nfs_rename_async(nfs, oldpath, newpath, rename_cb, &cb_data) != 0) {
1103 nfs_set_error(nfs, "nfs_rename_async failed");
1104 return -1;
1105 }
1106
1107 wait_for_nfs_reply(nfs, &cb_data);
1108
1109 return cb_data.status;
1110 }
1111
1112
1113
1114 /*
1115 * link()
1116 */
1117 static void link_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
1118 {
1119 struct sync_cb_data *cb_data = private_data;
1120
1121 cb_data->is_finished = 1;
1122 cb_data->status = status;
1123
1124 if (status < 0) {
1125 nfs_set_error(nfs, "link call failed with \"%s\"", (char *)data);
1126 return;
1127 }
1128 }
1129
1130 int nfs_link(struct nfs_context *nfs, const char *oldpath, const char *newpath)
1131 {
1132 struct sync_cb_data cb_data;
1133
1134 cb_data.is_finished = 0;
1135
1136 if (nfs_link_async(nfs, oldpath, newpath, link_cb, &cb_data) != 0) {
1137 nfs_set_error(nfs, "nfs_link_async failed");
1138 return -1;
1139 }
1140
1141 wait_for_nfs_reply(nfs, &cb_data);
1142
1143 return cb_data.status;
1144 }
1145
1146 void mount_getexports_cb(struct rpc_context *mount_context, int status, void *data, void *private_data)
1147 {
1148 struct sync_cb_data *cb_data = private_data;
1149 exports export = *(exports *)data;
1150
1151 cb_data->is_finished = 1;
1152 cb_data->status = status;
1153 cb_data->return_data = NULL;
1154
1155 if (status != 0) {
1156 rpc_set_error(mount_context, "mount/export call failed with \"%s\"", (char *)data);
1157 return;
1158 }
1159
1160 while (export != NULL) {
1161 exports new_export;
1162
1163 new_export = malloc(sizeof(*new_export));
1164 memset(new_export, 0, sizeof(*new_export));
1165 new_export->ex_dir = strdup(export->ex_dir);
1166 new_export->ex_next = cb_data->return_data;
1167
1168 cb_data->return_data = new_export;
1169
1170 export = export->ex_next;
1171 }
1172 }
1173
1174 struct exportnode *mount_getexports(const char *server)
1175 {
1176 struct sync_cb_data cb_data;
1177 struct rpc_context *rpc;
1178
1179
1180 cb_data.is_finished = 0;
1181 cb_data.return_data = NULL;
1182
1183 rpc = rpc_init_context();
1184 if (mount_getexports_async(rpc, server, mount_getexports_cb, &cb_data) != 0) {
1185 rpc_destroy_context(rpc);
1186 return NULL;
1187 }
1188
1189 wait_for_reply(rpc, &cb_data);
1190 rpc_destroy_context(rpc);
1191
1192 return cb_data.return_data;
1193 }
1194
1195 void mount_free_export_list(struct exportnode *exports)
1196 {
1197 struct exportnode *tmp;
1198
1199 while ((tmp = exports)) {
1200 exports = exports->ex_next;
1201 free(tmp->ex_dir);
1202 free(tmp);
1203 }
1204 }
1205
1206
1207
1208 void free_nfs_srvr_list(struct nfs_server_list *srv)
1209 {
1210 while (srv != NULL) {
1211 struct nfs_server_list *next = srv->next;
1212
1213 free(srv->addr);
1214 free(srv);
1215 srv = next;
1216 }
1217 }
1218
1219 struct nfs_list_data {
1220 int status;
1221 struct nfs_server_list *srvrs;
1222 };
1223
1224 void callit_cb(struct rpc_context *rpc, int status, void *data _U_, void *private_data)
1225 {
1226 struct nfs_list_data *srv_data = private_data;
1227 struct sockaddr *sin;
1228 char hostdd[16];
1229 struct nfs_server_list *srvr;
1230
1231 if (status == RPC_STATUS_CANCEL) {
1232 return;
1233 }
1234 if (status != 0) {
1235 srv_data->status = -1;
1236 return;
1237 }
1238
1239 sin = rpc_get_recv_sockaddr(rpc);
1240 if (sin == NULL) {
1241 rpc_set_error(rpc, "failed to get sockaddr in CALLIT callback");
1242 srv_data->status = -1;
1243 return;
1244 }
1245
1246 if (getnameinfo(sin, sizeof(struct sockaddr_in), &hostdd[0], sizeof(hostdd), NULL, 0, NI_NUMERICHOST) < 0) {
1247 rpc_set_error(rpc, "getnameinfo failed in CALLIT callback");
1248 srv_data->status = -1;
1249 return;
1250 }
1251
1252 /* check for dupes */
1253 for (srvr = srv_data->srvrs; srvr; srvr = srvr->next) {
1254 if (!strcmp(hostdd, srvr->addr)) {
1255 return;
1256 }
1257 }
1258
1259 srvr = malloc(sizeof(struct nfs_server_list));
1260 if (srvr == NULL) {
1261 rpc_set_error(rpc, "Malloc failed when allocating server structure");
1262 srv_data->status = -1;
1263 return;
1264 }
1265
1266 srvr->addr = strdup(hostdd);
1267 if (srvr->addr == NULL) {
1268 rpc_set_error(rpc, "Strdup failed when allocating server structure");
1269 free(srvr);
1270 srv_data->status = -1;
1271 return;
1272 }
1273
1274 srvr->next = srv_data->srvrs;
1275 srv_data->srvrs = srvr;
1276 }
1277
1278 #ifdef WIN32
1279
1280 static int send_nfsd_probes(struct rpc_context *rpc, INTERFACE_INFO *InterfaceList, int numIfs, struct nfs_list_data *data)
1281 {
1282 int i=0;
1283
1284 for(i = 0; i < numIfs; i++)
1285 {
1286 SOCKADDR *pAddress;
1287 char bcdd[16];
1288 unsigned long nFlags = 0;
1289
1290 pAddress = (SOCKADDR *) & (InterfaceList[i].iiBroadcastAddress);
1291
1292 if(pAddress->sa_family != AF_INET)
1293 continue;
1294
1295 nFlags = InterfaceList[i].iiFlags;
1296
1297 if (!(nFlags & IFF_UP))
1298 {
1299 continue;
1300 }
1301
1302 if (nFlags & IFF_LOOPBACK)
1303 {
1304 continue;
1305 }
1306
1307 if (!(nFlags & IFF_BROADCAST))
1308 {
1309 continue;
1310 }
1311
1312 if (getnameinfo(pAddress, sizeof(struct sockaddr_in), &bcdd[0], sizeof(bcdd), NULL, 0, NI_NUMERICHOST) < 0)
1313 {
1314 continue;
1315 }
1316
1317 if (rpc_set_udp_destination(rpc, bcdd, 111, 1) < 0)
1318 {
1319 return -1;
1320 }
1321
1322 if (rpc_pmap_callit_async(rpc, MOUNT_PROGRAM, 2, 0, NULL, 0, callit_cb, data) < 0)
1323 {
1324 return -1;
1325 }
1326 }
1327 return 0;
1328 }
1329
1330 struct nfs_server_list *nfs_find_local_servers(void)
1331 {
1332 struct rpc_context *rpc;
1333 struct nfs_list_data data = {0, NULL};
1334 struct timeval tv_start, tv_current;
1335 int loop;
1336 struct pollfd pfd;
1337 INTERFACE_INFO InterfaceList[20];
1338 unsigned long nBytesReturned;
1339 int nNumInterfaces = 0;
1340
1341 rpc = rpc_init_udp_context();
1342 if (rpc == NULL)
1343 {
1344 return NULL;
1345 }
1346
1347 if (rpc_bind_udp(rpc, "0.0.0.0", 0) < 0)
1348 {
1349 rpc_destroy_context(rpc);
1350 return NULL;
1351 }
1352
1353 if (WSAIoctl(rpc_get_fd(rpc), SIO_GET_INTERFACE_LIST, 0, 0, &InterfaceList, sizeof(InterfaceList), &nBytesReturned, 0, 0) == SOCKET_ERROR)
1354 {
1355 return NULL;
1356 }
1357
1358 nNumInterfaces = nBytesReturned / sizeof(INTERFACE_INFO);
1359
1360 for (loop=0; loop<3; loop++)
1361 {
1362 if (send_nfsd_probes(rpc, InterfaceList, nNumInterfaces, &data) != 0)
1363 {
1364 rpc_destroy_context(rpc);
1365 return NULL;
1366 }
1367
1368 win32_gettimeofday(&tv_start, NULL);
1369 for(;;)
1370 {
1371 int mpt;
1372
1373 pfd.fd = rpc_get_fd(rpc);
1374 pfd.events = rpc_which_events(rpc);
1375
1376 win32_gettimeofday(&tv_current, NULL);
1377 mpt = 1000
1378 - (tv_current.tv_sec *1000 + tv_current.tv_usec / 1000)
1379 + (tv_start.tv_sec *1000 + tv_start.tv_usec / 1000);
1380
1381 if (poll(&pfd, 1, mpt) < 0)
1382 {
1383 free_nfs_srvr_list(data.srvrs);
1384 rpc_destroy_context(rpc);
1385 return NULL;
1386 }
1387 if (pfd.revents == 0)
1388 {
1389 break;
1390 }
1391
1392 if (rpc_service(rpc, pfd.revents) < 0)
1393 {
1394 break;
1395 }
1396 }
1397 }
1398
1399 rpc_destroy_context(rpc);
1400
1401 if (data.status != 0)
1402 {
1403 free_nfs_srvr_list(data.srvrs);
1404 return NULL;
1405 }
1406 return data.srvrs;
1407 }
1408 #else
1409
1410 static int send_nfsd_probes(struct rpc_context *rpc, struct ifconf *ifc, struct nfs_list_data *data)
1411 {
1412 char *ptr;
1413
1414 for (ptr =(char *)(ifc->ifc_buf); ptr < (char *)(ifc->ifc_buf) + ifc->ifc_len; ) {
1415 struct ifreq *ifr;
1416 char bcdd[16];
1417
1418 ifr = (struct ifreq *)ptr;
1419 #ifdef HAVE_SOCKADDR_LEN
1420 if (ifr->ifr_addr.sa_len > sizeof(struct sockaddr)) {
1421 ptr += sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len;
1422 } else {
1423 ptr += sizeof(ifr->ifr_name) + sizeof(struct sockaddr);
1424 }
1425 #else
1426 ptr += sizeof(struct ifreq);
1427 #endif
1428
1429 if (ifr->ifr_addr.sa_family != AF_INET) {
1430 continue;
1431 }
1432 if (ioctl(rpc_get_fd(rpc), SIOCGIFFLAGS, ifr) < 0) {
1433 return -1;
1434 }
1435 if (!(ifr->ifr_flags & IFF_UP)) {
1436 continue;
1437 }
1438 if (ifr->ifr_flags & IFF_LOOPBACK) {
1439 continue;
1440 }
1441 if (!(ifr->ifr_flags & IFF_BROADCAST)) {
1442 continue;
1443 }
1444 if (ioctl(rpc_get_fd(rpc), SIOCGIFBRDADDR, ifr) < 0) {
1445 continue;
1446 }
1447 if (getnameinfo(&ifr->ifr_broadaddr, sizeof(struct sockaddr_in), &bcdd[0], sizeof(bcdd), NULL, 0, NI_NUMERICHOST) < 0) {
1448 continue;
1449 }
1450 if (rpc_set_udp_destination(rpc, bcdd, 111, 1) < 0) {
1451 return -1;
1452 }
1453
1454 if (rpc_pmap_callit_async(rpc, MOUNT_PROGRAM, 2, 0, NULL, 0, callit_cb, data) < 0) {
1455 return -1;
1456 }
1457 }
1458
1459 return 0;
1460 }
1461
1462 struct nfs_server_list *nfs_find_local_servers(void)
1463 {
1464 struct rpc_context *rpc;
1465 struct nfs_list_data data = {0, NULL};
1466 struct timeval tv_start, tv_current;
1467 struct ifconf ifc;
1468 int size, loop;
1469 struct pollfd pfd;
1470
1471 rpc = rpc_init_udp_context();
1472 if (rpc == NULL) {
1473 return NULL;
1474 }
1475
1476 if (rpc_bind_udp(rpc, "0.0.0.0", 0) < 0) {
1477 rpc_destroy_context(rpc);
1478 return NULL;
1479 }
1480
1481
1482 /* get list of all interfaces */
1483 size = sizeof(struct ifreq);
1484 ifc.ifc_buf = NULL;
1485 ifc.ifc_len = size;
1486
1487 while(ifc.ifc_len > (size - sizeof(struct ifreq))) {
1488 size *= 2;
1489
1490 free(ifc.ifc_buf);
1491 ifc.ifc_len = size;
1492 ifc.ifc_buf = malloc(size);
1493 memset(ifc.ifc_buf, 0, size);
1494 if (ioctl(rpc_get_fd(rpc), SIOCGIFCONF, (caddr_t)&ifc) < 0) {
1495 rpc_destroy_context(rpc);
1496 free(ifc.ifc_buf);
1497 return NULL;
1498 }
1499 }
1500
1501 for (loop=0; loop<3; loop++) {
1502 if (send_nfsd_probes(rpc, &ifc, &data) != 0) {
1503 rpc_destroy_context(rpc);
1504 free(ifc.ifc_buf);
1505 return NULL;
1506 }
1507
1508 gettimeofday(&tv_start, NULL);
1509 for(;;) {
1510 int mpt;
1511
1512 pfd.fd = rpc_get_fd(rpc);
1513 pfd.events = rpc_which_events(rpc);
1514
1515 gettimeofday(&tv_current, NULL);
1516 mpt = 1000
1517 - (tv_current.tv_sec *1000 + tv_current.tv_usec / 1000)
1518 + (tv_start.tv_sec *1000 + tv_start.tv_usec / 1000);
1519
1520 if (poll(&pfd, 1, mpt) < 0) {
1521 free_nfs_srvr_list(data.srvrs);
1522 rpc_destroy_context(rpc);
1523 return NULL;
1524 }
1525 if (pfd.revents == 0) {
1526 break;
1527 }
1528
1529 if (rpc_service(rpc, pfd.revents) < 0) {
1530 break;
1531 }
1532 }
1533 }
1534
1535 free(ifc.ifc_buf);
1536 rpc_destroy_context(rpc);
1537
1538 if (data.status != 0) {
1539 free_nfs_srvr_list(data.srvrs);
1540 return NULL;
1541 }
1542 return data.srvrs;
1543 }
1544 #endif//WIN32