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