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