Commit | Line | Data |
---|---|---|
84004dbf RS |
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 | ||
21 | #include <stdio.h> | |
22 | #include <stdlib.h> | |
23 | #include <string.h> | |
24 | #include <strings.h> | |
25 | #include <sys/types.h> | |
26 | #include <sys/stat.h> | |
27 | #include <sys/statvfs.h> | |
28 | #include <unistd.h> | |
29 | #include <fcntl.h> | |
30 | #include <errno.h> | |
31 | #include <poll.h> | |
32 | #include "libnfs.h" | |
33 | #include "libnfs-raw.h" | |
34 | #include "libnfs-raw-mount.h" | |
35 | #include "libnfs-raw-nfs.h" | |
1896d37b | 36 | #include "libnfs-private.h" |
84004dbf RS |
37 | |
38 | struct sync_cb_data { | |
39 | int is_finished; | |
40 | int status; | |
41 | off_t offset; | |
42 | void *return_data; | |
43 | int return_int; | |
44 | }; | |
45 | ||
46 | ||
df5af25f | 47 | static void wait_for_reply(struct rpc_context *rpc, struct sync_cb_data *cb_data) |
84004dbf RS |
48 | { |
49 | struct pollfd pfd; | |
50 | ||
51 | for (;;) { | |
52 | if (cb_data->is_finished) { | |
53 | break; | |
54 | } | |
df5af25f RS |
55 | pfd.fd = rpc_get_fd(rpc); |
56 | pfd.events = rpc_which_events(rpc); | |
84004dbf RS |
57 | |
58 | if (poll(&pfd, 1, -1) < 0) { | |
df5af25f | 59 | rpc_set_error(rpc, "Poll failed"); |
84004dbf RS |
60 | cb_data->status = -EIO; |
61 | break; | |
62 | } | |
df5af25f RS |
63 | if (rpc_service(rpc, pfd.revents) < 0) { |
64 | rpc_set_error(rpc, "rpc_service failed"); | |
84004dbf RS |
65 | cb_data->status = -EIO; |
66 | break; | |
67 | } | |
68 | } | |
69 | } | |
70 | ||
71 | ||
72 | ||
73 | ||
74 | ||
75 | ||
76 | /* | |
77 | * connect to the server and mount the export | |
78 | */ | |
1896d37b | 79 | static void mount_cb(int status, struct nfs_context *nfs, void *data, void *private_data) |
84004dbf RS |
80 | { |
81 | struct sync_cb_data *cb_data = private_data; | |
82 | ||
83 | cb_data->is_finished = 1; | |
84 | cb_data->status = status; | |
85 | ||
86 | if (status < 0) { | |
1896d37b | 87 | nfs_set_error(nfs, "mount/mnt call failed with \"%s\"", (char *)data); |
84004dbf RS |
88 | return; |
89 | } | |
90 | } | |
91 | ||
e2ba5764 | 92 | int nfs_mount(struct nfs_context *nfs, const char *server, const char *export) |
84004dbf RS |
93 | { |
94 | struct sync_cb_data cb_data; | |
95 | ||
96 | cb_data.is_finished = 0; | |
97 | ||
98 | if (nfs_mount_async(nfs, server, export, mount_cb, &cb_data) != 0) { | |
1896d37b | 99 | nfs_set_error(nfs, "nfs_mount_async failed"); |
84004dbf RS |
100 | return -1; |
101 | } | |
102 | ||
df5af25f | 103 | wait_for_reply(nfs_get_rpc_context(nfs), &cb_data); |
84004dbf RS |
104 | |
105 | return cb_data.status; | |
106 | } | |
107 | ||
108 | ||
109 | /* | |
110 | * stat() | |
111 | */ | |
1896d37b | 112 | static void stat_cb(int status, struct nfs_context *nfs, void *data, void *private_data) |
84004dbf RS |
113 | { |
114 | struct sync_cb_data *cb_data = private_data; | |
115 | ||
116 | cb_data->is_finished = 1; | |
117 | cb_data->status = status; | |
118 | ||
119 | if (status < 0) { | |
1896d37b | 120 | nfs_set_error(nfs, "stat call failed with \"%s\"", (char *)data); |
84004dbf RS |
121 | return; |
122 | } | |
123 | ||
124 | memcpy(cb_data->return_data, data, sizeof(struct stat)); | |
125 | } | |
126 | ||
e2ba5764 | 127 | int nfs_stat(struct nfs_context *nfs, const char *path, struct stat *st) |
84004dbf RS |
128 | { |
129 | struct sync_cb_data cb_data; | |
130 | ||
131 | cb_data.is_finished = 0; | |
132 | cb_data.return_data = st; | |
133 | ||
134 | if (nfs_stat_async(nfs, path, stat_cb, &cb_data) != 0) { | |
1896d37b | 135 | nfs_set_error(nfs, "nfs_stat_async failed"); |
84004dbf RS |
136 | return -1; |
137 | } | |
138 | ||
df5af25f | 139 | wait_for_reply(nfs_get_rpc_context(nfs), &cb_data); |
84004dbf RS |
140 | |
141 | return cb_data.status; | |
142 | } | |
143 | ||
144 | ||
145 | ||
146 | ||
147 | /* | |
148 | * open() | |
149 | */ | |
1896d37b | 150 | static void open_cb(int status, struct nfs_context *nfs, void *data, void *private_data) |
84004dbf RS |
151 | { |
152 | struct sync_cb_data *cb_data = private_data; | |
153 | struct nfsfh *fh, **nfsfh; | |
154 | ||
155 | cb_data->is_finished = 1; | |
156 | cb_data->status = status; | |
157 | ||
158 | if (status < 0) { | |
1896d37b | 159 | nfs_set_error(nfs, "open call failed with \"%s\"", (char *)data); |
84004dbf RS |
160 | return; |
161 | } | |
162 | ||
163 | fh = data; | |
164 | nfsfh = cb_data->return_data; | |
165 | *nfsfh = fh; | |
166 | } | |
167 | ||
e2ba5764 | 168 | int nfs_open(struct nfs_context *nfs, const char *path, int mode, struct nfsfh **nfsfh) |
84004dbf RS |
169 | { |
170 | struct sync_cb_data cb_data; | |
171 | ||
172 | cb_data.is_finished = 0; | |
173 | cb_data.return_data = nfsfh; | |
174 | ||
175 | if (nfs_open_async(nfs, path, mode, open_cb, &cb_data) != 0) { | |
1896d37b | 176 | nfs_set_error(nfs, "nfs_open_async failed"); |
84004dbf RS |
177 | return -1; |
178 | } | |
179 | ||
df5af25f | 180 | wait_for_reply(nfs_get_rpc_context(nfs), &cb_data); |
84004dbf RS |
181 | |
182 | return cb_data.status; | |
183 | } | |
184 | ||
185 | ||
186 | ||
187 | ||
188 | /* | |
189 | * pread() | |
190 | */ | |
1896d37b | 191 | static void pread_cb(int status, struct nfs_context *nfs, void *data, void *private_data) |
84004dbf RS |
192 | { |
193 | struct sync_cb_data *cb_data = private_data; | |
194 | char *buffer; | |
195 | cb_data->is_finished = 1; | |
196 | cb_data->status = status; | |
197 | ||
198 | if (status < 0) { | |
1896d37b | 199 | nfs_set_error(nfs, "pread call failed with \"%s\"", (char *)data); |
84004dbf RS |
200 | return; |
201 | } | |
202 | ||
203 | buffer = cb_data->return_data; | |
204 | memcpy(buffer, (char *)data, status); | |
205 | } | |
206 | ||
e2ba5764 | 207 | int nfs_pread(struct nfs_context *nfs, struct nfsfh *nfsfh, off_t offset, size_t count, char *buffer) |
84004dbf RS |
208 | { |
209 | struct sync_cb_data cb_data; | |
210 | ||
211 | cb_data.is_finished = 0; | |
212 | cb_data.return_data = buffer; | |
213 | ||
214 | if (nfs_pread_async(nfs, nfsfh, offset, count, pread_cb, &cb_data) != 0) { | |
1896d37b | 215 | nfs_set_error(nfs, "nfs_pread_async failed"); |
84004dbf RS |
216 | return -1; |
217 | } | |
218 | ||
df5af25f | 219 | wait_for_reply(nfs_get_rpc_context(nfs), &cb_data); |
84004dbf RS |
220 | |
221 | return cb_data.status; | |
222 | } | |
223 | ||
224 | /* | |
225 | * read() | |
226 | */ | |
e2ba5764 | 227 | int nfs_read(struct nfs_context *nfs, struct nfsfh *nfsfh, size_t count, char *buffer) |
84004dbf | 228 | { |
e2ba5764 | 229 | return nfs_pread(nfs, nfsfh, nfs_get_current_offset(nfsfh), count, buffer); |
84004dbf RS |
230 | } |
231 | ||
232 | /* | |
233 | * close() | |
234 | */ | |
1896d37b | 235 | static void close_cb(int status, struct nfs_context *nfs, void *data, void *private_data) |
84004dbf RS |
236 | { |
237 | struct sync_cb_data *cb_data = private_data; | |
238 | cb_data->is_finished = 1; | |
239 | cb_data->status = status; | |
240 | ||
241 | if (status < 0) { | |
1896d37b | 242 | nfs_set_error(nfs, "close call failed with \"%s\"", (char *)data); |
84004dbf RS |
243 | return; |
244 | } | |
245 | } | |
246 | ||
e2ba5764 | 247 | int nfs_close(struct nfs_context *nfs, struct nfsfh *nfsfh) |
84004dbf RS |
248 | { |
249 | struct sync_cb_data cb_data; | |
250 | ||
251 | cb_data.is_finished = 0; | |
252 | ||
253 | if (nfs_close_async(nfs, nfsfh, close_cb, &cb_data) != 0) { | |
1896d37b | 254 | nfs_set_error(nfs, "nfs_close_async failed"); |
84004dbf RS |
255 | return -1; |
256 | } | |
257 | ||
df5af25f | 258 | wait_for_reply(nfs_get_rpc_context(nfs), &cb_data); |
84004dbf RS |
259 | |
260 | return cb_data.status; | |
261 | } | |
262 | ||
263 | ||
264 | ||
265 | ||
266 | /* | |
267 | * fstat() | |
268 | */ | |
e2ba5764 | 269 | int nfs_fstat(struct nfs_context *nfs, struct nfsfh *nfsfh, struct stat *st) |
84004dbf RS |
270 | { |
271 | struct sync_cb_data cb_data; | |
272 | ||
273 | cb_data.is_finished = 0; | |
274 | cb_data.return_data = st; | |
275 | ||
276 | if (nfs_fstat_async(nfs, nfsfh, stat_cb, &cb_data) != 0) { | |
1896d37b | 277 | nfs_set_error(nfs, "nfs_fstat_async failed"); |
84004dbf RS |
278 | return -1; |
279 | } | |
280 | ||
df5af25f | 281 | wait_for_reply(nfs_get_rpc_context(nfs), &cb_data); |
84004dbf RS |
282 | |
283 | return cb_data.status; | |
284 | } | |
285 | ||
286 | ||
287 | /* | |
288 | * pwrite() | |
289 | */ | |
1896d37b | 290 | static void pwrite_cb(int status, struct nfs_context *nfs, void *data, void *private_data) |
84004dbf RS |
291 | { |
292 | struct sync_cb_data *cb_data = private_data; | |
293 | cb_data->is_finished = 1; | |
294 | cb_data->status = status; | |
295 | ||
296 | if (status < 0) { | |
1896d37b | 297 | nfs_set_error(nfs, "pwrite call failed with \"%s\"", (char *)data); |
84004dbf RS |
298 | return; |
299 | } | |
300 | } | |
301 | ||
e2ba5764 | 302 | int nfs_pwrite(struct nfs_context *nfs, struct nfsfh *nfsfh, off_t offset, size_t count, char *buf) |
84004dbf RS |
303 | { |
304 | struct sync_cb_data cb_data; | |
305 | ||
306 | cb_data.is_finished = 0; | |
307 | ||
308 | if (nfs_pwrite_async(nfs, nfsfh, offset, count, buf, pwrite_cb, &cb_data) != 0) { | |
1896d37b | 309 | nfs_set_error(nfs, "nfs_pwrite_async failed"); |
84004dbf RS |
310 | return -1; |
311 | } | |
312 | ||
df5af25f | 313 | wait_for_reply(nfs_get_rpc_context(nfs), &cb_data); |
84004dbf RS |
314 | |
315 | return cb_data.status; | |
316 | } | |
317 | ||
318 | /* | |
319 | * write() | |
320 | */ | |
e2ba5764 | 321 | int nfs_write(struct nfs_context *nfs, struct nfsfh *nfsfh, size_t count, char *buf) |
84004dbf | 322 | { |
e2ba5764 | 323 | return nfs_pwrite(nfs, nfsfh, nfs_get_current_offset(nfsfh), count, buf); |
84004dbf RS |
324 | } |
325 | ||
326 | ||
327 | /* | |
328 | * fsync() | |
329 | */ | |
1896d37b | 330 | static void fsync_cb(int status, struct nfs_context *nfs, void *data, void *private_data) |
84004dbf RS |
331 | { |
332 | struct sync_cb_data *cb_data = private_data; | |
333 | cb_data->is_finished = 1; | |
334 | cb_data->status = status; | |
335 | ||
336 | if (status < 0) { | |
1896d37b | 337 | nfs_set_error(nfs, "fsync call failed with \"%s\"", (char *)data); |
84004dbf RS |
338 | return; |
339 | } | |
340 | } | |
341 | ||
e2ba5764 | 342 | int nfs_fsync(struct nfs_context *nfs, struct nfsfh *nfsfh) |
84004dbf RS |
343 | { |
344 | struct sync_cb_data cb_data; | |
345 | ||
346 | cb_data.is_finished = 0; | |
347 | ||
348 | if (nfs_fsync_async(nfs, nfsfh, fsync_cb, &cb_data) != 0) { | |
1896d37b | 349 | nfs_set_error(nfs, "nfs_fsync_async failed"); |
84004dbf RS |
350 | return -1; |
351 | } | |
352 | ||
df5af25f | 353 | wait_for_reply(nfs_get_rpc_context(nfs), &cb_data); |
84004dbf RS |
354 | |
355 | return cb_data.status; | |
356 | } | |
357 | ||
358 | ||
359 | ||
360 | ||
361 | /* | |
362 | * ftruncate() | |
363 | */ | |
1896d37b | 364 | static void ftruncate_cb(int status, struct nfs_context *nfs, void *data, void *private_data) |
84004dbf RS |
365 | { |
366 | struct sync_cb_data *cb_data = private_data; | |
367 | cb_data->is_finished = 1; | |
368 | cb_data->status = status; | |
369 | ||
370 | if (status < 0) { | |
1896d37b | 371 | nfs_set_error(nfs, "ftruncate call failed with \"%s\"", (char *)data); |
84004dbf RS |
372 | return; |
373 | } | |
374 | } | |
375 | ||
e2ba5764 | 376 | int nfs_ftruncate(struct nfs_context *nfs, struct nfsfh *nfsfh, off_t length) |
84004dbf RS |
377 | { |
378 | struct sync_cb_data cb_data; | |
379 | ||
380 | cb_data.is_finished = 0; | |
381 | ||
382 | if (nfs_ftruncate_async(nfs, nfsfh, length, ftruncate_cb, &cb_data) != 0) { | |
1896d37b | 383 | nfs_set_error(nfs, "nfs_ftruncate_async failed"); |
84004dbf RS |
384 | return -1; |
385 | } | |
386 | ||
df5af25f | 387 | wait_for_reply(nfs_get_rpc_context(nfs), &cb_data); |
84004dbf RS |
388 | |
389 | return cb_data.status; | |
390 | } | |
391 | ||
392 | ||
393 | ||
394 | /* | |
395 | * truncate() | |
396 | */ | |
1896d37b | 397 | static void truncate_cb(int status, struct nfs_context *nfs, void *data, void *private_data) |
84004dbf RS |
398 | { |
399 | struct sync_cb_data *cb_data = private_data; | |
400 | cb_data->is_finished = 1; | |
401 | cb_data->status = status; | |
402 | ||
403 | if (status < 0) { | |
1896d37b | 404 | nfs_set_error(nfs, "truncate call failed with \"%s\"", (char *)data); |
84004dbf RS |
405 | return; |
406 | } | |
407 | } | |
408 | ||
e2ba5764 | 409 | int nfs_truncate(struct nfs_context *nfs, const char *path, off_t length) |
84004dbf RS |
410 | { |
411 | struct sync_cb_data cb_data; | |
412 | ||
413 | cb_data.is_finished = 0; | |
414 | ||
415 | if (nfs_truncate_async(nfs, path, length, truncate_cb, &cb_data) != 0) { | |
1896d37b | 416 | nfs_set_error(nfs, "nfs_ftruncate_async failed"); |
84004dbf RS |
417 | return -1; |
418 | } | |
419 | ||
df5af25f | 420 | wait_for_reply(nfs_get_rpc_context(nfs), &cb_data); |
84004dbf RS |
421 | |
422 | return cb_data.status; | |
423 | } | |
424 | ||
425 | ||
426 | ||
427 | ||
428 | ||
429 | /* | |
430 | * mkdir() | |
431 | */ | |
1896d37b | 432 | static void mkdir_cb(int status, struct nfs_context *nfs, void *data, void *private_data) |
84004dbf RS |
433 | { |
434 | struct sync_cb_data *cb_data = private_data; | |
435 | cb_data->is_finished = 1; | |
436 | cb_data->status = status; | |
437 | ||
438 | if (status < 0) { | |
1896d37b | 439 | nfs_set_error(nfs, "mkdir call failed with \"%s\"", (char *)data); |
84004dbf RS |
440 | return; |
441 | } | |
442 | } | |
443 | ||
e2ba5764 | 444 | int nfs_mkdir(struct nfs_context *nfs, const char *path) |
84004dbf RS |
445 | { |
446 | struct sync_cb_data cb_data; | |
447 | ||
448 | cb_data.is_finished = 0; | |
449 | ||
450 | if (nfs_mkdir_async(nfs, path, mkdir_cb, &cb_data) != 0) { | |
1896d37b | 451 | nfs_set_error(nfs, "nfs_mkdir_async failed"); |
84004dbf RS |
452 | return -1; |
453 | } | |
454 | ||
df5af25f | 455 | wait_for_reply(nfs_get_rpc_context(nfs), &cb_data); |
84004dbf RS |
456 | |
457 | return cb_data.status; | |
458 | } | |
459 | ||
460 | ||
461 | ||
462 | ||
463 | ||
464 | /* | |
465 | * rmdir() | |
466 | */ | |
1896d37b | 467 | static void rmdir_cb(int status, struct nfs_context *nfs, void *data, void *private_data) |
84004dbf RS |
468 | { |
469 | struct sync_cb_data *cb_data = private_data; | |
470 | cb_data->is_finished = 1; | |
471 | cb_data->status = status; | |
472 | ||
473 | if (status < 0) { | |
1896d37b | 474 | nfs_set_error(nfs, "rmdir call failed with \"%s\"", (char *)data); |
84004dbf RS |
475 | return; |
476 | } | |
477 | } | |
478 | ||
e2ba5764 | 479 | int nfs_rmdir(struct nfs_context *nfs, const char *path) |
84004dbf RS |
480 | { |
481 | struct sync_cb_data cb_data; | |
482 | ||
483 | cb_data.is_finished = 0; | |
484 | ||
485 | if (nfs_rmdir_async(nfs, path, rmdir_cb, &cb_data) != 0) { | |
1896d37b | 486 | nfs_set_error(nfs, "nfs_rmdir_async failed"); |
84004dbf RS |
487 | return -1; |
488 | } | |
489 | ||
df5af25f | 490 | wait_for_reply(nfs_get_rpc_context(nfs), &cb_data); |
84004dbf RS |
491 | |
492 | return cb_data.status; | |
493 | } | |
494 | ||
495 | ||
496 | ||
497 | /* | |
498 | * creat() | |
499 | */ | |
1896d37b | 500 | static void creat_cb(int status, struct nfs_context *nfs, void *data, void *private_data) |
84004dbf RS |
501 | { |
502 | struct sync_cb_data *cb_data = private_data; | |
503 | struct nfsfh *fh, **nfsfh; | |
504 | ||
505 | cb_data->is_finished = 1; | |
506 | cb_data->status = status; | |
507 | ||
508 | if (status < 0) { | |
1896d37b | 509 | nfs_set_error(nfs, "creat call failed with \"%s\"", (char *)data); |
84004dbf RS |
510 | return; |
511 | } | |
512 | ||
513 | fh = data; | |
514 | nfsfh = cb_data->return_data; | |
515 | *nfsfh = fh; | |
516 | } | |
517 | ||
e2ba5764 | 518 | int nfs_creat(struct nfs_context *nfs, const char *path, int mode, struct nfsfh **nfsfh) |
84004dbf RS |
519 | { |
520 | struct sync_cb_data cb_data; | |
521 | ||
522 | cb_data.is_finished = 0; | |
523 | cb_data.return_data = nfsfh; | |
524 | ||
525 | if (nfs_creat_async(nfs, path, mode, creat_cb, &cb_data) != 0) { | |
1896d37b | 526 | nfs_set_error(nfs, "nfs_creat_async failed"); |
84004dbf RS |
527 | return -1; |
528 | } | |
529 | ||
df5af25f | 530 | wait_for_reply(nfs_get_rpc_context(nfs), &cb_data); |
84004dbf RS |
531 | |
532 | return cb_data.status; | |
533 | } | |
534 | ||
535 | ||
536 | ||
537 | ||
538 | /* | |
539 | * unlink() | |
540 | */ | |
1896d37b | 541 | static void unlink_cb(int status, struct nfs_context *nfs, void *data, void *private_data) |
84004dbf RS |
542 | { |
543 | struct sync_cb_data *cb_data = private_data; | |
544 | ||
545 | cb_data->is_finished = 1; | |
546 | cb_data->status = status; | |
547 | ||
548 | if (status < 0) { | |
1896d37b | 549 | nfs_set_error(nfs, "unlink call failed with \"%s\"", (char *)data); |
84004dbf RS |
550 | return; |
551 | } | |
552 | } | |
553 | ||
e2ba5764 | 554 | int nfs_unlink(struct nfs_context *nfs, const char *path) |
84004dbf RS |
555 | { |
556 | struct sync_cb_data cb_data; | |
557 | ||
558 | cb_data.is_finished = 0; | |
559 | ||
560 | if (nfs_unlink_async(nfs, path, unlink_cb, &cb_data) != 0) { | |
1896d37b | 561 | nfs_set_error(nfs, "nfs_unlink_async failed"); |
84004dbf RS |
562 | return -1; |
563 | } | |
564 | ||
df5af25f | 565 | wait_for_reply(nfs_get_rpc_context(nfs), &cb_data); |
84004dbf RS |
566 | |
567 | return cb_data.status; | |
568 | } | |
569 | ||
570 | ||
571 | ||
572 | /* | |
573 | * opendir() | |
574 | */ | |
1896d37b | 575 | static void opendir_cb(int status, struct nfs_context *nfs, void *data, void *private_data) |
84004dbf RS |
576 | { |
577 | struct sync_cb_data *cb_data = private_data; | |
578 | struct nfsdir *dir, **nfsdir; | |
579 | ||
580 | cb_data->is_finished = 1; | |
581 | cb_data->status = status; | |
582 | ||
583 | if (status < 0) { | |
1896d37b | 584 | nfs_set_error(nfs, "opendir call failed with \"%s\"", (char *)data); |
84004dbf RS |
585 | return; |
586 | } | |
587 | ||
588 | dir = data; | |
589 | nfsdir = cb_data->return_data; | |
590 | *nfsdir = dir; | |
591 | } | |
592 | ||
e2ba5764 | 593 | int nfs_opendir(struct nfs_context *nfs, const char *path, struct nfsdir **nfsdir) |
84004dbf RS |
594 | { |
595 | struct sync_cb_data cb_data; | |
596 | ||
597 | cb_data.is_finished = 0; | |
598 | cb_data.return_data = nfsdir; | |
599 | ||
600 | if (nfs_opendir_async(nfs, path, opendir_cb, &cb_data) != 0) { | |
1896d37b | 601 | nfs_set_error(nfs, "nfs_opendir_async failed"); |
84004dbf RS |
602 | return -1; |
603 | } | |
604 | ||
df5af25f | 605 | wait_for_reply(nfs_get_rpc_context(nfs), &cb_data); |
84004dbf RS |
606 | |
607 | return cb_data.status; | |
608 | } | |
609 | ||
610 | ||
611 | /* | |
612 | * lseek() | |
613 | */ | |
1896d37b | 614 | static void lseek_cb(int status, struct nfs_context *nfs, void *data, void *private_data) |
84004dbf RS |
615 | { |
616 | struct sync_cb_data *cb_data = private_data; | |
617 | ||
618 | cb_data->is_finished = 1; | |
619 | cb_data->status = status; | |
620 | ||
621 | if (status < 0) { | |
1896d37b | 622 | nfs_set_error(nfs, "lseek call failed with \"%s\"", (char *)data); |
84004dbf RS |
623 | return; |
624 | } | |
625 | ||
626 | if (cb_data->return_data != NULL) { | |
627 | memcpy(cb_data->return_data, data, sizeof(off_t)); | |
628 | } | |
629 | } | |
630 | ||
e2ba5764 | 631 | int nfs_lseek(struct nfs_context *nfs, struct nfsfh *nfsfh, off_t offset, int whence, off_t *current_offset) |
84004dbf RS |
632 | { |
633 | struct sync_cb_data cb_data; | |
634 | ||
635 | cb_data.is_finished = 0; | |
636 | cb_data.return_data = current_offset; | |
637 | ||
638 | if (nfs_lseek_async(nfs, nfsfh, offset, whence, lseek_cb, &cb_data) != 0) { | |
1896d37b | 639 | nfs_set_error(nfs, "nfs_lseek_async failed"); |
84004dbf RS |
640 | return -1; |
641 | } | |
642 | ||
df5af25f | 643 | wait_for_reply(nfs_get_rpc_context(nfs), &cb_data); |
84004dbf RS |
644 | |
645 | return cb_data.status; | |
646 | } | |
647 | ||
648 | ||
649 | ||
650 | /* | |
651 | * statvfs() | |
652 | */ | |
1896d37b | 653 | static void statvfs_cb(int status, struct nfs_context *nfs, void *data, void *private_data) |
84004dbf RS |
654 | { |
655 | struct sync_cb_data *cb_data = private_data; | |
656 | ||
657 | cb_data->is_finished = 1; | |
658 | cb_data->status = status; | |
659 | ||
660 | if (status < 0) { | |
1896d37b | 661 | nfs_set_error(nfs, "statvfs call failed with \"%s\"", (char *)data); |
84004dbf RS |
662 | return; |
663 | } | |
664 | ||
665 | memcpy(cb_data->return_data, data, sizeof(struct statvfs)); | |
666 | } | |
667 | ||
e2ba5764 | 668 | int nfs_statvfs(struct nfs_context *nfs, const char *path, struct statvfs *svfs) |
84004dbf RS |
669 | { |
670 | struct sync_cb_data cb_data; | |
671 | ||
672 | cb_data.is_finished = 0; | |
673 | cb_data.return_data = svfs; | |
674 | ||
675 | if (nfs_statvfs_async(nfs, path, statvfs_cb, &cb_data) != 0) { | |
1896d37b | 676 | nfs_set_error(nfs, "nfs_statvfs_async failed"); |
84004dbf RS |
677 | return -1; |
678 | } | |
679 | ||
df5af25f | 680 | wait_for_reply(nfs_get_rpc_context(nfs), &cb_data); |
84004dbf RS |
681 | |
682 | return cb_data.status; | |
683 | } | |
684 | ||
685 | ||
686 | ||
687 | ||
688 | ||
689 | /* | |
690 | * readlink() | |
691 | */ | |
1896d37b | 692 | static void readlink_cb(int status, struct nfs_context *nfs, void *data, void *private_data) |
84004dbf RS |
693 | { |
694 | struct sync_cb_data *cb_data = private_data; | |
695 | ||
696 | cb_data->is_finished = 1; | |
697 | cb_data->status = status; | |
698 | ||
699 | if (status < 0) { | |
1896d37b | 700 | nfs_set_error(nfs, "readlink call failed with \"%s\"", (char *)data); |
84004dbf RS |
701 | return; |
702 | } | |
703 | ||
704 | if (strlen(data) > (size_t)cb_data->return_int) { | |
1896d37b | 705 | nfs_set_error(nfs, "Too small buffer for readlink"); |
84004dbf RS |
706 | cb_data->status = -ENAMETOOLONG; |
707 | return; | |
708 | } | |
709 | ||
710 | memcpy(cb_data->return_data, data, strlen(data)+1); | |
711 | } | |
712 | ||
e2ba5764 | 713 | int nfs_readlink(struct nfs_context *nfs, const char *path, char *buf, int bufsize) |
84004dbf RS |
714 | { |
715 | struct sync_cb_data cb_data; | |
716 | ||
717 | cb_data.is_finished = 0; | |
718 | cb_data.return_data = buf; | |
719 | cb_data.return_int = bufsize; | |
720 | ||
721 | if (nfs_readlink_async(nfs, path, readlink_cb, &cb_data) != 0) { | |
1896d37b | 722 | nfs_set_error(nfs, "nfs_readlink_async failed"); |
84004dbf RS |
723 | return -1; |
724 | } | |
725 | ||
df5af25f | 726 | wait_for_reply(nfs_get_rpc_context(nfs), &cb_data); |
84004dbf RS |
727 | |
728 | return cb_data.status; | |
729 | } | |
730 | ||
731 | ||
732 | ||
733 | /* | |
734 | * chmod() | |
735 | */ | |
1896d37b | 736 | static void chmod_cb(int status, struct nfs_context *nfs, void *data, void *private_data) |
84004dbf RS |
737 | { |
738 | struct sync_cb_data *cb_data = private_data; | |
739 | ||
740 | cb_data->is_finished = 1; | |
741 | cb_data->status = status; | |
742 | ||
743 | if (status < 0) { | |
1896d37b | 744 | nfs_set_error(nfs, "chmod call failed with \"%s\"", (char *)data); |
84004dbf RS |
745 | return; |
746 | } | |
747 | } | |
748 | ||
e2ba5764 | 749 | int nfs_chmod(struct nfs_context *nfs, const char *path, int mode) |
84004dbf RS |
750 | { |
751 | struct sync_cb_data cb_data; | |
752 | ||
753 | cb_data.is_finished = 0; | |
754 | ||
755 | if (nfs_chmod_async(nfs, path, mode, chmod_cb, &cb_data) != 0) { | |
1896d37b | 756 | nfs_set_error(nfs, "nfs_chmod_async failed"); |
84004dbf RS |
757 | return -1; |
758 | } | |
759 | ||
df5af25f | 760 | wait_for_reply(nfs_get_rpc_context(nfs), &cb_data); |
84004dbf RS |
761 | |
762 | return cb_data.status; | |
763 | } | |
764 | ||
765 | ||
766 | ||
767 | ||
768 | /* | |
769 | * fchmod() | |
770 | */ | |
1896d37b | 771 | static void fchmod_cb(int status, struct nfs_context *nfs, void *data, void *private_data) |
84004dbf RS |
772 | { |
773 | struct sync_cb_data *cb_data = private_data; | |
774 | ||
775 | cb_data->is_finished = 1; | |
776 | cb_data->status = status; | |
777 | ||
778 | if (status < 0) { | |
1896d37b | 779 | nfs_set_error(nfs, "fchmod call failed with \"%s\"", (char *)data); |
84004dbf RS |
780 | return; |
781 | } | |
782 | } | |
783 | ||
e2ba5764 | 784 | int nfs_fchmod(struct nfs_context *nfs, struct nfsfh *nfsfh, int mode) |
84004dbf RS |
785 | { |
786 | struct sync_cb_data cb_data; | |
787 | ||
788 | cb_data.is_finished = 0; | |
789 | ||
790 | if (nfs_fchmod_async(nfs, nfsfh, mode, fchmod_cb, &cb_data) != 0) { | |
1896d37b | 791 | nfs_set_error(nfs, "nfs_fchmod_async failed"); |
84004dbf RS |
792 | return -1; |
793 | } | |
794 | ||
df5af25f | 795 | wait_for_reply(nfs_get_rpc_context(nfs), &cb_data); |
84004dbf RS |
796 | |
797 | return cb_data.status; | |
798 | } | |
799 | ||
800 | ||
801 | ||
802 | ||
803 | /* | |
804 | * chown() | |
805 | */ | |
1896d37b | 806 | static void chown_cb(int status, struct nfs_context *nfs, void *data, void *private_data) |
84004dbf RS |
807 | { |
808 | struct sync_cb_data *cb_data = private_data; | |
809 | ||
810 | cb_data->is_finished = 1; | |
811 | cb_data->status = status; | |
812 | ||
813 | if (status < 0) { | |
1896d37b | 814 | nfs_set_error(nfs, "chown call failed with \"%s\"", (char *)data); |
84004dbf RS |
815 | return; |
816 | } | |
817 | } | |
818 | ||
e2ba5764 | 819 | int nfs_chown(struct nfs_context *nfs, const char *path, int uid, int gid) |
84004dbf RS |
820 | { |
821 | struct sync_cb_data cb_data; | |
822 | ||
823 | cb_data.is_finished = 0; | |
824 | ||
825 | if (nfs_chown_async(nfs, path, uid, gid, chown_cb, &cb_data) != 0) { | |
1896d37b | 826 | nfs_set_error(nfs, "nfs_chown_async failed"); |
84004dbf RS |
827 | return -1; |
828 | } | |
829 | ||
df5af25f | 830 | wait_for_reply(nfs_get_rpc_context(nfs), &cb_data); |
84004dbf RS |
831 | |
832 | return cb_data.status; | |
833 | } | |
834 | ||
835 | /* | |
836 | * fchown() | |
837 | */ | |
1896d37b | 838 | static void fchown_cb(int status, struct nfs_context *nfs, void *data, void *private_data) |
84004dbf RS |
839 | { |
840 | struct sync_cb_data *cb_data = private_data; | |
841 | ||
842 | cb_data->is_finished = 1; | |
843 | cb_data->status = status; | |
844 | ||
845 | if (status < 0) { | |
1896d37b | 846 | nfs_set_error(nfs, "fchown call failed with \"%s\"", (char *)data); |
84004dbf RS |
847 | return; |
848 | } | |
849 | } | |
850 | ||
e2ba5764 | 851 | int nfs_fchown(struct nfs_context *nfs, struct nfsfh *nfsfh, int uid, int gid) |
84004dbf RS |
852 | { |
853 | struct sync_cb_data cb_data; | |
854 | ||
855 | cb_data.is_finished = 0; | |
856 | ||
857 | if (nfs_fchown_async(nfs, nfsfh, uid, gid, fchown_cb, &cb_data) != 0) { | |
1896d37b | 858 | nfs_set_error(nfs, "nfs_fchown_async failed"); |
84004dbf RS |
859 | return -1; |
860 | } | |
861 | ||
df5af25f | 862 | wait_for_reply(nfs_get_rpc_context(nfs), &cb_data); |
84004dbf RS |
863 | |
864 | return cb_data.status; | |
865 | } | |
866 | ||
867 | ||
868 | ||
869 | /* | |
870 | * utimes() | |
871 | */ | |
1896d37b | 872 | static void utimes_cb(int status, struct nfs_context *nfs, void *data, void *private_data) |
84004dbf RS |
873 | { |
874 | struct sync_cb_data *cb_data = private_data; | |
875 | ||
876 | cb_data->is_finished = 1; | |
877 | cb_data->status = status; | |
878 | ||
879 | if (status < 0) { | |
1896d37b | 880 | nfs_set_error(nfs, "utimes call failed with \"%s\"", (char *)data); |
84004dbf RS |
881 | return; |
882 | } | |
883 | } | |
884 | ||
e2ba5764 | 885 | int nfs_utimes(struct nfs_context *nfs, const char *path, struct timeval *times) |
84004dbf RS |
886 | { |
887 | struct sync_cb_data cb_data; | |
888 | ||
889 | cb_data.is_finished = 0; | |
890 | ||
891 | if (nfs_utimes_async(nfs, path, times, utimes_cb, &cb_data) != 0) { | |
1896d37b | 892 | nfs_set_error(nfs, "nfs_utimes_async failed"); |
84004dbf RS |
893 | return -1; |
894 | } | |
895 | ||
df5af25f | 896 | wait_for_reply(nfs_get_rpc_context(nfs), &cb_data); |
84004dbf RS |
897 | |
898 | return cb_data.status; | |
899 | } | |
900 | ||
901 | ||
902 | ||
903 | /* | |
904 | * utime() | |
905 | */ | |
1896d37b | 906 | static void utime_cb(int status, struct nfs_context *nfs, void *data, void *private_data) |
84004dbf RS |
907 | { |
908 | struct sync_cb_data *cb_data = private_data; | |
909 | ||
910 | cb_data->is_finished = 1; | |
911 | cb_data->status = status; | |
912 | ||
913 | if (status < 0) { | |
1896d37b | 914 | nfs_set_error(nfs, "utime call failed with \"%s\"", (char *)data); |
84004dbf RS |
915 | return; |
916 | } | |
917 | } | |
918 | ||
e2ba5764 | 919 | int nfs_utime(struct nfs_context *nfs, const char *path, struct utimbuf *times) |
84004dbf RS |
920 | { |
921 | struct sync_cb_data cb_data; | |
922 | ||
923 | cb_data.is_finished = 0; | |
924 | ||
925 | if (nfs_utime_async(nfs, path, times, utime_cb, &cb_data) != 0) { | |
1896d37b | 926 | nfs_set_error(nfs, "nfs_utimes_async failed"); |
84004dbf RS |
927 | return -1; |
928 | } | |
929 | ||
df5af25f | 930 | wait_for_reply(nfs_get_rpc_context(nfs), &cb_data); |
84004dbf RS |
931 | |
932 | return cb_data.status; | |
933 | } | |
934 | ||
935 | ||
936 | ||
937 | ||
938 | /* | |
939 | * access() | |
940 | */ | |
1896d37b | 941 | static void access_cb(int status, struct nfs_context *nfs, void *data, void *private_data) |
84004dbf RS |
942 | { |
943 | struct sync_cb_data *cb_data = private_data; | |
944 | ||
945 | cb_data->is_finished = 1; | |
946 | cb_data->status = status; | |
947 | ||
948 | if (status < 0) { | |
1896d37b | 949 | nfs_set_error(nfs, "access call failed with \"%s\"", (char *)data); |
84004dbf RS |
950 | return; |
951 | } | |
952 | } | |
953 | ||
e2ba5764 | 954 | int nfs_access(struct nfs_context *nfs, const char *path, int mode) |
84004dbf RS |
955 | { |
956 | struct sync_cb_data cb_data; | |
957 | ||
958 | cb_data.is_finished = 0; | |
959 | ||
960 | if (nfs_access_async(nfs, path, mode, access_cb, &cb_data) != 0) { | |
1896d37b | 961 | nfs_set_error(nfs, "nfs_access_async failed"); |
84004dbf RS |
962 | return -1; |
963 | } | |
964 | ||
df5af25f | 965 | wait_for_reply(nfs_get_rpc_context(nfs), &cb_data); |
84004dbf RS |
966 | |
967 | return cb_data.status; | |
968 | } | |
969 | ||
970 | ||
971 | ||
972 | /* | |
973 | * symlink() | |
974 | */ | |
1896d37b | 975 | static void symlink_cb(int status, struct nfs_context *nfs, void *data, void *private_data) |
84004dbf RS |
976 | { |
977 | struct sync_cb_data *cb_data = private_data; | |
978 | ||
979 | cb_data->is_finished = 1; | |
980 | cb_data->status = status; | |
981 | ||
982 | if (status < 0) { | |
1896d37b | 983 | nfs_set_error(nfs, "symlink call failed with \"%s\"", (char *)data); |
84004dbf RS |
984 | return; |
985 | } | |
986 | } | |
987 | ||
e2ba5764 | 988 | int nfs_symlink(struct nfs_context *nfs, const char *oldpath, const char *newpath) |
84004dbf RS |
989 | { |
990 | struct sync_cb_data cb_data; | |
991 | ||
992 | cb_data.is_finished = 0; | |
993 | ||
994 | if (nfs_symlink_async(nfs, oldpath, newpath, symlink_cb, &cb_data) != 0) { | |
1896d37b | 995 | nfs_set_error(nfs, "nfs_symlink_async failed"); |
84004dbf RS |
996 | return -1; |
997 | } | |
998 | ||
df5af25f | 999 | wait_for_reply(nfs_get_rpc_context(nfs), &cb_data); |
84004dbf RS |
1000 | |
1001 | return cb_data.status; | |
1002 | } | |
1003 | ||
1004 | ||
1005 | ||
1006 | /* | |
1007 | * rename() | |
1008 | */ | |
1896d37b | 1009 | static void rename_cb(int status, struct nfs_context *nfs, void *data, void *private_data) |
84004dbf RS |
1010 | { |
1011 | struct sync_cb_data *cb_data = private_data; | |
1012 | ||
1013 | cb_data->is_finished = 1; | |
1014 | cb_data->status = status; | |
1015 | ||
1016 | if (status < 0) { | |
1896d37b | 1017 | nfs_set_error(nfs, "rename call failed with \"%s\"", (char *)data); |
84004dbf RS |
1018 | return; |
1019 | } | |
1020 | } | |
1021 | ||
e2ba5764 | 1022 | int nfs_rename(struct nfs_context *nfs, const char *oldpath, const char *newpath) |
84004dbf RS |
1023 | { |
1024 | struct sync_cb_data cb_data; | |
1025 | ||
1026 | cb_data.is_finished = 0; | |
1027 | ||
1028 | if (nfs_rename_async(nfs, oldpath, newpath, rename_cb, &cb_data) != 0) { | |
1896d37b | 1029 | nfs_set_error(nfs, "nfs_rename_async failed"); |
84004dbf RS |
1030 | return -1; |
1031 | } | |
1032 | ||
df5af25f | 1033 | wait_for_reply(nfs_get_rpc_context(nfs), &cb_data); |
84004dbf RS |
1034 | |
1035 | return cb_data.status; | |
1036 | } | |
1037 | ||
1038 | ||
1039 | ||
1040 | /* | |
1041 | * link() | |
1042 | */ | |
1896d37b | 1043 | static void link_cb(int status, struct nfs_context *nfs, void *data, void *private_data) |
84004dbf RS |
1044 | { |
1045 | struct sync_cb_data *cb_data = private_data; | |
1046 | ||
1047 | cb_data->is_finished = 1; | |
1048 | cb_data->status = status; | |
1049 | ||
1050 | if (status < 0) { | |
1896d37b | 1051 | nfs_set_error(nfs, "link call failed with \"%s\"", (char *)data); |
84004dbf RS |
1052 | return; |
1053 | } | |
1054 | } | |
1055 | ||
e2ba5764 | 1056 | int nfs_link(struct nfs_context *nfs, const char *oldpath, const char *newpath) |
84004dbf RS |
1057 | { |
1058 | struct sync_cb_data cb_data; | |
1059 | ||
1060 | cb_data.is_finished = 0; | |
1061 | ||
1062 | if (nfs_link_async(nfs, oldpath, newpath, link_cb, &cb_data) != 0) { | |
1896d37b | 1063 | nfs_set_error(nfs, "nfs_link_async failed"); |
84004dbf RS |
1064 | return -1; |
1065 | } | |
1066 | ||
df5af25f | 1067 | wait_for_reply(nfs_get_rpc_context(nfs), &cb_data); |
84004dbf RS |
1068 | |
1069 | return cb_data.status; | |
1070 | } | |
df5af25f | 1071 | |
739df145 | 1072 | void mount_getexports_cb(struct rpc_context *mount_context, int status, void *data, void *private_data) |
df5af25f RS |
1073 | { |
1074 | struct sync_cb_data *cb_data = private_data; | |
1075 | exports export = *(exports *)data; | |
1076 | ||
df5af25f RS |
1077 | cb_data->is_finished = 1; |
1078 | cb_data->status = status; | |
1079 | cb_data->return_data = NULL; | |
1080 | ||
739df145 RS |
1081 | if (status != 0) { |
1082 | rpc_set_error(mount_context, "mount/export call failed with \"%s\"", (char *)data); | |
1083 | return; | |
1084 | } | |
1085 | ||
df5af25f RS |
1086 | while (export != NULL) { |
1087 | exports new_export; | |
1088 | ||
1089 | new_export = malloc(sizeof(*new_export)); | |
1090 | memset(new_export, 0, sizeof(*new_export)); | |
1091 | new_export->ex_dir = strdup(export->ex_dir); | |
1092 | new_export->ex_next = cb_data->return_data; | |
1093 | ||
1094 | cb_data->return_data = new_export; | |
1095 | ||
1096 | export = export->ex_next; | |
1097 | } | |
1098 | } | |
1099 | ||
e210bd2a | 1100 | struct exportnode *mount_getexports(const char *server) |
df5af25f RS |
1101 | { |
1102 | struct sync_cb_data cb_data; | |
e210bd2a RS |
1103 | struct rpc_context *rpc; |
1104 | ||
df5af25f RS |
1105 | |
1106 | cb_data.is_finished = 0; | |
1107 | cb_data.return_data = NULL; | |
1108 | ||
e210bd2a | 1109 | rpc = rpc_init_context(); |
df5af25f | 1110 | if (mount_getexports_async(rpc, server, mount_getexports_cb, &cb_data) != 0) { |
e210bd2a | 1111 | rpc_destroy_context(rpc); |
df5af25f RS |
1112 | return NULL; |
1113 | } | |
1114 | ||
1115 | wait_for_reply(rpc, &cb_data); | |
e210bd2a | 1116 | rpc_destroy_context(rpc); |
df5af25f RS |
1117 | |
1118 | return cb_data.return_data; | |
1119 | } | |
1120 | ||
1121 | void mount_free_export_list(struct exportnode *exports) | |
1122 | { | |
1123 | struct exportnode *tmp; | |
1124 | ||
1125 | while ((tmp = exports)) { | |
1126 | exports = exports->ex_next; | |
1127 | free(tmp->ex_dir); | |
1128 | free(tmp); | |
1129 | } | |
1130 | } | |
1131 |