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