1 /* 2 * Copyright (c) 2006-2018, RT-Thread Development Team 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 * 6 * Change Logs: 7 * Date Author Notes 8 */ 9 10 #include <stdio.h> 11 #include <rtthread.h> 12 #include <dfs_fs.h> 13 #include <dfs.h> 14 #include <dfs_file.h> 15 16 #include <rpc/rpc.h> 17 18 #include "mount.h" 19 #include "nfs.h" 20 21 #define NAME_MAX 64 22 #define DFS_NFS_MAX_MTU 1024 23 24 #ifdef _WIN32 25 #define strtok_r strtok_s 26 #endif 27 28 struct nfs_file 29 { 30 nfs_fh3 handle; /* handle */ 31 size_t offset; /* current offset */ 32 33 size_t size; /* total size */ 34 bool_t eof; /* end of file */ 35 }; 36 37 struct nfs_dir 38 { 39 nfs_fh3 handle; 40 cookie3 cookie; 41 cookieverf3 cookieverf; 42 entry3 *entry; 43 bool_t eof; 44 READDIR3res res; 45 }; 46 47 #define HOST_LENGTH 32 48 #define EXPORT_PATH_LENGTH 32 49 50 struct nfs_filesystem 51 { 52 nfs_fh3 root_handle; 53 nfs_fh3 current_handle; 54 CLIENT *nfs_client; 55 CLIENT *mount_client; 56 57 char host[HOST_LENGTH]; 58 char export[EXPORT_PATH_LENGTH]; 59 void *data; /* nfs_file or nfs_dir */ 60 }; 61 62 typedef struct nfs_filesystem nfs_filesystem; 63 typedef struct nfs_file nfs_file; 64 typedef struct nfs_dir nfs_dir; 65 66 nfs_dir *nfs_opendir(nfs_filesystem *nfs, const char *path); 67 68 static int nfs_parse_host_export(const char *host_export, 69 char *host, 70 size_t host_len, 71 char *export, 72 size_t export_len) 73 { 74 int index; 75 76 for (index = 0; index < host_len; index ++) 77 { 78 /* it's end of string, failed */ 79 if (host_export[index] == 0) 80 return -1; 81 82 /* copy to host buffer */ 83 if (host_export[index] != ':') 84 host[index] = host_export[index]; 85 else 86 break; 87 } 88 89 /* host buffer is not enough, failed */ 90 if (index == host_len) 91 return -1; 92 93 /* make NULL */ 94 host_len = index; 95 host[host_len] = '\0'; 96 97 host_len ++; 98 99 /* copy export path */ 100 for (index = host_len; index < host_len + export_len; index ++) 101 { 102 if (host_export[index] == 0) 103 { 104 export[index - host_len] = '\0'; 105 106 return 0; 107 } 108 109 export[index - host_len] = host_export[index]; 110 } 111 112 return -1; 113 } 114 115 static void copy_handle(nfs_fh3 *dest, const nfs_fh3 *source) 116 { 117 dest->data.data_len = source->data.data_len; 118 dest->data.data_val = rt_malloc(dest->data.data_len); 119 if (dest->data.data_val == NULL) 120 { 121 dest->data.data_len = 0; 122 123 return; 124 } 125 126 memcpy(dest->data.data_val, source->data.data_val, dest->data.data_len); 127 } 128 129 static nfs_fh3 *get_handle(nfs_filesystem *nfs, const char *name) 130 { 131 nfs_fh3 *handle = NULL; 132 char *file; 133 char *path; 134 char *init; 135 136 init = path = rt_malloc(strlen(name)+1); 137 if (init == NULL) 138 return NULL; 139 140 memcpy(init, name, strlen(name)+1); 141 142 handle = rt_malloc(sizeof(nfs_fh3)); 143 if (handle == NULL) 144 { 145 rt_free(init); 146 147 return NULL; 148 } 149 150 if (path[0] == '/') 151 { 152 path ++; 153 copy_handle(handle, &nfs->root_handle); 154 } 155 else 156 { 157 copy_handle(handle, &nfs->current_handle); 158 } 159 160 while ((file = strtok_r(NULL, "/", &path)) != NULL) 161 { 162 LOOKUP3args args; 163 LOOKUP3res res; 164 memset(&res, 0, sizeof(res)); 165 copy_handle(&args.what.dir, handle); 166 xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)handle); 167 args.what.name = file; 168 169 if (nfsproc3_lookup_3(args, &res, nfs->nfs_client) != RPC_SUCCESS) 170 { 171 rt_kprintf("Lookup failed\n"); 172 rt_free(init); 173 rt_free(handle); 174 xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)&args.what.dir); 175 176 return NULL; 177 } 178 else if (res.status != NFS3_OK) 179 { 180 rt_kprintf("Lookup failed: %d\n", res.status); 181 rt_free(init); 182 rt_free(handle); 183 xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)&args.what.dir); 184 xdr_free((xdrproc_t)xdr_LOOKUP3res, (char *)&res); 185 186 return NULL; 187 } 188 copy_handle(handle, &res.LOOKUP3res_u.resok.object); 189 xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)&args.what.dir); 190 xdr_free((xdrproc_t)xdr_LOOKUP3res, (char *)&res); 191 } 192 193 rt_free(init); 194 195 return handle; 196 } 197 198 static nfs_fh3 *get_dir_handle(nfs_filesystem *nfs, const char *name) 199 { 200 nfs_fh3 *handle = NULL; 201 char *file; 202 char *path; 203 char *init; 204 205 init = path = rt_malloc(strlen(name)+1); 206 if (init == NULL) 207 return NULL; 208 memcpy(init, name, strlen(name)+1); 209 210 handle = rt_malloc(sizeof(nfs_fh3)); 211 if (handle == NULL) 212 { 213 rt_free(init); 214 215 return NULL; 216 } 217 218 if (path[0] == '/') 219 { 220 path ++; 221 copy_handle(handle, &nfs->root_handle); 222 } 223 else 224 { 225 copy_handle(handle, &nfs->current_handle); 226 } 227 228 while ((file = strtok_r(NULL, "/", &path)) != NULL && path[0] != 0) 229 { 230 LOOKUP3args args; 231 LOOKUP3res res; 232 memset(&res, 0, sizeof(res)); 233 copy_handle(&args.what.dir, handle); 234 xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)handle); 235 args.what.name = file; 236 237 if (nfsproc3_lookup_3(args, &res, nfs->nfs_client) != RPC_SUCCESS) 238 { 239 rt_kprintf("Lookup failed\n"); 240 rt_free(init); 241 rt_free(handle); 242 xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)&args.what.dir); 243 244 return NULL; 245 } 246 else if (res.status != NFS3_OK) 247 { 248 rt_kprintf("Lookup failed: %d\n", res.status); 249 rt_free(init); 250 rt_free(handle); 251 xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)&args.what.dir); 252 xdr_free((xdrproc_t)xdr_LOOKUP3res, (char *)&res); 253 254 return NULL; 255 } 256 copy_handle(handle, &res.LOOKUP3res_u.resok.object); 257 xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)&args.what.dir); 258 xdr_free((xdrproc_t)xdr_LOOKUP3res, (char *)&res); 259 } 260 261 rt_free(init); 262 263 return handle; 264 } 265 266 static size_t nfs_get_filesize(nfs_filesystem *nfs, nfs_fh3 *handle) 267 { 268 GETATTR3args args; 269 GETATTR3res res; 270 fattr3 *info; 271 size_t size; 272 273 args.object = *handle; 274 275 memset(&res, '\0', sizeof(res)); 276 277 if ((nfsproc3_getattr_3(args, &res, nfs->nfs_client)!=RPC_SUCCESS) || 278 res.status != NFS3_OK) 279 { 280 rt_kprintf("GetAttr failed: %d\n", res.status); 281 282 return 0; 283 } 284 285 info = &res.GETATTR3res_u.resok.obj_attributes; 286 size = info->size; 287 xdr_free((xdrproc_t)xdr_GETATTR3res, (char *)&res); 288 289 return size; 290 } 291 292 rt_bool_t nfs_is_directory(nfs_filesystem *nfs, const char *name) 293 { 294 GETATTR3args args; 295 GETATTR3res res; 296 fattr3 *info; 297 nfs_fh3 *handle; 298 rt_bool_t result; 299 300 result = RT_FALSE; 301 handle = get_handle(nfs, name); 302 if (handle == NULL) 303 return RT_FALSE; 304 305 args.object = *handle; 306 307 memset(&res, '\0', sizeof(res)); 308 309 if (nfsproc3_getattr_3(args, &res, nfs->nfs_client) != RPC_SUCCESS) 310 { 311 rt_kprintf("GetAttr failed\n"); 312 313 return RT_FALSE; 314 } 315 else if (res.status != NFS3_OK) 316 { 317 rt_kprintf("Getattr failed: %d\n", res.status); 318 319 return RT_FALSE; 320 } 321 322 info=&res.GETATTR3res_u.resok.obj_attributes; 323 324 if (info->type == NFS3DIR) 325 result = RT_TRUE; 326 327 xdr_free((xdrproc_t)xdr_GETATTR3res, (char *)&res); 328 xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)handle); 329 rt_free(handle); 330 331 return result; 332 } 333 334 int nfs_create(nfs_filesystem *nfs, const char *name, mode_t mode) 335 { 336 CREATE3args args; 337 CREATE3res res; 338 int ret = 0; 339 nfs_fh3 *handle; 340 341 if (nfs->nfs_client == NULL) 342 { 343 return -1; 344 } 345 346 handle = get_dir_handle(nfs, name); 347 if (handle == NULL) 348 { 349 return -1; 350 } 351 args.where.dir = *handle; 352 args.where.name = strrchr(name, '/') + 1; 353 if (args.where.name == NULL) 354 { 355 args.where.name = (char *)name; 356 } 357 args.how.mode = GUARDED; 358 359 args.how.createhow3_u.obj_attributes.mode.set_it = TRUE; 360 args.how.createhow3_u.obj_attributes.mode.set_mode3_u.mode = mode; 361 args.how.createhow3_u.obj_attributes.uid.set_it = FALSE; 362 args.how.createhow3_u.obj_attributes.gid.set_it = FALSE; 363 args.how.createhow3_u.obj_attributes.size.set_it = FALSE; 364 args.how.createhow3_u.obj_attributes.atime.set_it = DONT_CHANGE; 365 args.how.createhow3_u.obj_attributes.mtime.set_it = DONT_CHANGE; 366 367 memset(&res, 0, sizeof(res)); 368 369 if (nfsproc3_create_3(args, &res, nfs->nfs_client) != RPC_SUCCESS) 370 { 371 rt_kprintf("Create failed\n"); 372 ret = -1; 373 } 374 else if (res.status != NFS3_OK) 375 { 376 rt_kprintf("Create failed: %d\n", res.status); 377 ret = -1; 378 } 379 xdr_free((xdrproc_t)xdr_CREATE3res, (char *)&res); 380 xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)handle); 381 rt_free(handle); 382 383 return ret; 384 } 385 386 int nfs_mkdir(nfs_filesystem *nfs, const char *name, mode_t mode) 387 { 388 MKDIR3args args; 389 MKDIR3res res; 390 int ret = 0; 391 nfs_fh3 *handle; 392 393 if (nfs->nfs_client == NULL) 394 return -1; 395 396 handle = get_dir_handle(nfs, name); 397 if (handle == NULL) 398 return -1; 399 400 args.where.dir = *handle; 401 args.where.name = strrchr(name, '/') + 1; 402 if (args.where.name == NULL) 403 { 404 args.where.name = (char *)name; 405 } 406 407 args.attributes.mode.set_it = TRUE; 408 args.attributes.mode.set_mode3_u.mode = mode; 409 args.attributes.uid.set_it = FALSE; 410 args.attributes.gid.set_it = FALSE; 411 args.attributes.size.set_it = FALSE; 412 args.attributes.atime.set_it = DONT_CHANGE; 413 args.attributes.mtime.set_it = DONT_CHANGE; 414 415 memset(&res, 0, sizeof(res)); 416 417 if (nfsproc3_mkdir_3(args, &res, nfs->nfs_client) != RPC_SUCCESS) 418 { 419 rt_kprintf("Mkdir failed\n"); 420 ret = -1; 421 } 422 else if (res.status != NFS3_OK) 423 { 424 rt_kprintf("Mkdir failed: %d\n", res.status); 425 ret = -1; 426 } 427 xdr_free((xdrproc_t)xdr_MKDIR3res, (char *)&res); 428 xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)handle); 429 rt_free(handle); 430 431 return ret; 432 } 433 434 /* mount(NULL, "/mnt", "nfs", 0, "192.168.1.1:/export") */ 435 int nfs_mount(struct dfs_filesystem *fs, unsigned long rwflag, const void *data) 436 { 437 mountres3 res; 438 nfs_filesystem *nfs; 439 440 nfs = (nfs_filesystem *)rt_malloc(sizeof(nfs_filesystem)); 441 memset(nfs, 0, sizeof(nfs_filesystem)); 442 443 if (nfs_parse_host_export((const char *)data, nfs->host, HOST_LENGTH, 444 nfs->export, EXPORT_PATH_LENGTH) < 0) 445 { 446 rt_kprintf("host or export path error\n"); 447 goto __return; 448 } 449 450 nfs->mount_client=clnt_create((char *)nfs->host, MOUNT_PROGRAM, MOUNT_V3, "udp"); 451 if (nfs->mount_client == NULL) 452 { 453 rt_kprintf("create mount client failed\n"); 454 goto __return; 455 } 456 457 memset(&res, '\0', sizeof(mountres3)); 458 if (mountproc3_mnt_3((char *)nfs->export, &res, nfs->mount_client) != RPC_SUCCESS) 459 { 460 rt_kprintf("nfs mount failed\n"); 461 goto __return; 462 } 463 else if (res.fhs_status != MNT3_OK) 464 { 465 rt_kprintf("nfs mount failed\n"); 466 goto __return; 467 } 468 nfs->nfs_client=clnt_create((char *)nfs->host, NFS_PROGRAM, NFS_V3, "udp"); 469 if (nfs->nfs_client == NULL) 470 { 471 rt_kprintf("creat nfs client failed\n"); 472 goto __return; 473 } 474 copy_handle(&nfs->root_handle, (nfs_fh3 *)&res.mountres3_u.mountinfo.fhandle); 475 copy_handle(&nfs->current_handle, &nfs->root_handle); 476 477 nfs->nfs_client->cl_auth = authnone_create(); 478 fs->data = nfs; 479 480 return 0; 481 482 __return: 483 if (nfs != NULL) 484 { 485 if (nfs->mount_client != NULL) 486 { 487 clnt_destroy(nfs->mount_client); 488 } 489 if (nfs->nfs_client != NULL) 490 { 491 if (nfs->nfs_client->cl_auth != NULL) 492 { 493 auth_destroy(nfs->nfs_client->cl_auth); 494 } 495 clnt_destroy(nfs->nfs_client); 496 } 497 rt_free(nfs); 498 } 499 500 return -1; 501 } 502 503 int nfs_unmount(struct dfs_filesystem *fs) 504 { 505 nfs_filesystem *nfs; 506 507 RT_ASSERT(fs != NULL); 508 RT_ASSERT(fs->data != NULL); 509 nfs = (nfs_filesystem *)fs->data; 510 511 if (nfs->mount_client != NULL && 512 mountproc3_umnt_3((char *)nfs->export, NULL, nfs->mount_client) != RPC_SUCCESS) 513 { 514 rt_kprintf("unmount failed\n"); 515 516 return -1; 517 } 518 519 /* destroy nfs client */ 520 if (nfs->nfs_client != NULL) 521 { 522 if (nfs->nfs_client->cl_auth != NULL) 523 { 524 auth_destroy(nfs->nfs_client->cl_auth); 525 nfs->nfs_client->cl_auth = NULL; 526 } 527 clnt_destroy(nfs->nfs_client); 528 nfs->nfs_client = NULL; 529 } 530 531 /* destroy mount client */ 532 if (nfs->mount_client != NULL) 533 { 534 if (nfs->mount_client->cl_auth != NULL) 535 { 536 auth_destroy(nfs->mount_client->cl_auth); 537 nfs->mount_client->cl_auth = NULL; 538 } 539 clnt_destroy(nfs->mount_client); 540 nfs->mount_client = NULL; 541 } 542 543 rt_free(nfs); 544 fs->data = NULL; 545 546 return 0; 547 } 548 549 int nfs_ioctl(struct dfs_fd *file, int cmd, void *args) 550 { 551 return -ENOSYS; 552 } 553 554 int nfs_read(struct dfs_fd *file, void *buf, size_t count) 555 { 556 READ3args args; 557 READ3res res; 558 ssize_t bytes, total=0; 559 nfs_file *fd; 560 nfs_filesystem *nfs; 561 562 if (file->type == FT_DIRECTORY) 563 return -EISDIR; 564 565 566 RT_ASSERT(file->data != NULL); 567 struct dfs_filesystem *dfs_nfs = ((struct dfs_filesystem*)(file->data)); 568 nfs = (struct nfs_filesystem *)(dfs_nfs->data); 569 fd = (nfs_file *)(nfs->data); 570 RT_ASSERT(fd != NULL); 571 572 if (nfs->nfs_client == NULL) 573 return -1; 574 575 /* end of file */ 576 if (fd->eof == TRUE) 577 return 0; 578 579 args.file = fd->handle; 580 do { 581 args.offset = fd->offset; 582 args.count = count > DFS_NFS_MAX_MTU ? DFS_NFS_MAX_MTU : count; 583 count -= args.count; 584 585 memset(&res, 0, sizeof(res)); 586 if (nfsproc3_read_3(args, &res, nfs->nfs_client) != RPC_SUCCESS) 587 { 588 rt_kprintf("Read failed\n"); 589 total = 0; 590 break; 591 } 592 else if (res.status != NFS3_OK) 593 { 594 rt_kprintf("Read failed: %d\n", res.status); 595 total = 0; 596 break; 597 } 598 else 599 { 600 bytes = res.READ3res_u.resok.count; 601 total += bytes; 602 fd->offset += bytes; 603 /* update current position */ 604 file->pos = fd->offset; 605 memcpy(buf, res.READ3res_u.resok.data.data_val, bytes); 606 buf = (void *)((char *)buf + args.count); 607 if (res.READ3res_u.resok.eof) 608 { 609 /* something should probably be here */ 610 fd->eof = TRUE; 611 break; 612 } 613 } 614 xdr_free((xdrproc_t)xdr_READ3res, (char *)&res); 615 } while(count > 0); 616 617 xdr_free((xdrproc_t)xdr_READ3res, (char *)&res); 618 619 return total; 620 } 621 622 int nfs_write(struct dfs_fd *file, const void *buf, size_t count) 623 { 624 WRITE3args args; 625 WRITE3res res; 626 ssize_t bytes, total=0; 627 nfs_file *fd; 628 nfs_filesystem *nfs; 629 630 if (file->type == FT_DIRECTORY) 631 return -EISDIR; 632 633 RT_ASSERT(file->data != NULL); 634 struct dfs_filesystem *dfs_nfs = ((struct dfs_filesystem*)(file->data)); 635 nfs = (struct nfs_filesystem *)(dfs_nfs->data); 636 fd = (nfs_file *)(nfs->data); 637 RT_ASSERT(fd != NULL); 638 639 if (nfs->nfs_client == NULL) 640 return -1; 641 642 args.file = fd->handle; 643 args.stable = FILE_SYNC; 644 645 do { 646 args.offset = fd->offset; 647 648 memset(&res, 0, sizeof(res)); 649 args.data.data_val=(void *)buf; 650 args.count = count > DFS_NFS_MAX_MTU ? DFS_NFS_MAX_MTU : count; 651 args.data.data_len = args.count; 652 count -= args.count; 653 buf = (const void *)((char *)buf + args.count); 654 655 if (nfsproc3_write_3(args, &res, nfs->nfs_client) != RPC_SUCCESS) 656 { 657 rt_kprintf("Write failed\n"); 658 total = 0; 659 break; 660 } 661 else if (res.status != NFS3_OK) 662 { 663 rt_kprintf("Write failed: %d\n", res.status); 664 total = 0; 665 break; 666 } 667 else 668 { 669 bytes = res.WRITE3res_u.resok.count; 670 fd->offset += bytes; 671 total += bytes; 672 /* update current position */ 673 file->pos = fd->offset; 674 /* update file size */ 675 if (fd->size < fd->offset) fd->size = fd->offset; 676 file->size = fd->size; 677 } 678 xdr_free((xdrproc_t)xdr_WRITE3res, (char *)&res); 679 } while (count > 0); 680 681 xdr_free((xdrproc_t)xdr_WRITE3res, (char *)&res); 682 683 return total; 684 } 685 686 int nfs_lseek(struct dfs_fd *file, off_t offset) 687 { 688 nfs_file *fd; 689 nfs_filesystem *nfs; 690 691 if (file->type == FT_DIRECTORY) 692 return -EISDIR; 693 694 RT_ASSERT(file->data != NULL); 695 struct dfs_filesystem *dfs_nfs = ((struct dfs_filesystem*)(file->data)); 696 nfs = (struct nfs_filesystem *)(dfs_nfs->data); 697 fd = (nfs_file *)(nfs->data); 698 RT_ASSERT(fd != NULL); 699 700 if (offset <= fd->size) 701 { 702 fd->offset = offset; 703 704 return offset; 705 } 706 707 return -EIO; 708 } 709 710 int nfs_close(struct dfs_fd *file) 711 { 712 nfs_filesystem *nfs; 713 RT_ASSERT(file->data != NULL); 714 struct dfs_filesystem *dfs_nfs = ((struct dfs_filesystem*)(file->data)); 715 nfs = (struct nfs_filesystem *)(dfs_nfs->data); 716 717 if (file->type == FT_DIRECTORY) 718 { 719 struct nfs_dir *dir; 720 721 dir = (struct nfs_dir *)nfs->data; 722 xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)&dir->handle); 723 xdr_free((xdrproc_t)xdr_READDIR3res, (char *)&dir->res); 724 rt_free(dir); 725 } 726 else if (file->type == FT_REGULAR) 727 { 728 struct nfs_file *fd; 729 730 fd = (struct nfs_file *)nfs->data; 731 732 xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)&fd->handle); 733 rt_free(fd); 734 } 735 736 nfs->data = NULL; 737 return 0; 738 } 739 740 int nfs_open(struct dfs_fd *file) 741 { 742 nfs_filesystem *nfs; 743 RT_ASSERT(file->data != NULL); 744 struct dfs_filesystem *dfs_nfs = ((struct dfs_filesystem*)(file->data)); 745 nfs = (struct nfs_filesystem *)(dfs_nfs->data); 746 747 748 if (file->flags & O_DIRECTORY) 749 { 750 nfs_dir *dir; 751 752 if (file->flags & O_CREAT) 753 { 754 if (nfs_mkdir(nfs, file->path, 0755) < 0) 755 return -EAGAIN; 756 } 757 758 /* open directory */ 759 dir = nfs_opendir(nfs, file->path); 760 if (dir == NULL) return -ENOENT; 761 nfs->data = dir; 762 } 763 else 764 { 765 nfs_file *fp; 766 nfs_fh3 *handle; 767 768 /* create file */ 769 if (file->flags & O_CREAT) 770 { 771 if (nfs_create(nfs, file->path, 0664) < 0) 772 return -EAGAIN; 773 } 774 775 /* open file (get file handle ) */ 776 fp = rt_malloc(sizeof(nfs_file)); 777 if (fp == NULL) 778 return -ENOMEM; 779 780 handle = get_handle(nfs, file->path); 781 if (handle == NULL) 782 { 783 rt_free(fp); 784 785 return -ENOENT; 786 } 787 788 /* get size of file */ 789 fp->size = nfs_get_filesize(nfs, handle); 790 fp->offset = 0; 791 fp->eof = FALSE; 792 793 copy_handle(&fp->handle, handle); 794 xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)handle); 795 rt_free(handle); 796 797 if (file->flags & O_APPEND) 798 { 799 fp->offset = fp->size; 800 } 801 802 /* set private file */ 803 nfs->data = fp; 804 file->size = fp->size; 805 } 806 807 return 0; 808 } 809 810 int nfs_stat(struct dfs_filesystem *fs, const char *path, struct stat *st) 811 { 812 GETATTR3args args; 813 GETATTR3res res; 814 fattr3 *info; 815 nfs_fh3 *handle; 816 nfs_filesystem *nfs; 817 818 RT_ASSERT(fs != NULL); 819 RT_ASSERT(fs->data != NULL); 820 nfs = (nfs_filesystem *)fs->data; 821 822 handle = get_handle(nfs, path); 823 if (handle == NULL) 824 return -1; 825 826 args.object = *handle; 827 828 memset(&res, '\0', sizeof(res)); 829 830 if (nfsproc3_getattr_3(args, &res, nfs->nfs_client) != RPC_SUCCESS) 831 { 832 rt_kprintf("GetAttr failed\n"); 833 return -1; 834 } 835 else if (res.status != NFS3_OK) 836 { 837 rt_kprintf("Getattr failed: %d\n", res.status); 838 return -1; 839 } 840 841 info = &res.GETATTR3res_u.resok.obj_attributes; 842 843 st->st_dev = 0; 844 845 st->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH; 846 if (info->type == NFS3DIR) 847 { 848 st->st_mode &= ~S_IFREG; 849 st->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH; 850 } 851 852 st->st_size = info->size; 853 st->st_mtime = info->mtime.seconds; 854 855 xdr_free((xdrproc_t)xdr_GETATTR3res, (char *)&res); 856 xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)handle); 857 rt_free(handle); 858 859 return 0; 860 } 861 862 nfs_dir *nfs_opendir(nfs_filesystem *nfs, const char *path) 863 { 864 nfs_dir *dir; 865 nfs_fh3 *handle; 866 867 dir = rt_malloc(sizeof(nfs_dir)); 868 if (dir == NULL) 869 { 870 return NULL; 871 } 872 873 handle = get_handle(nfs, path); 874 if (handle == NULL) 875 { 876 rt_free(dir); 877 return NULL; 878 } 879 880 copy_handle(&dir->handle, handle); 881 xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)handle); 882 rt_free(handle); 883 884 dir->cookie = 0; 885 memset(&dir->cookieverf, '\0', sizeof(cookieverf3)); 886 dir->entry = NULL; 887 dir->eof = FALSE; 888 memset(&dir->res, '\0', sizeof(dir->res)); 889 890 return dir; 891 } 892 893 char *nfs_readdir(nfs_filesystem *nfs, nfs_dir *dir) 894 { 895 static char name[NAME_MAX]; 896 897 if (nfs->nfs_client == NULL || dir == NULL) 898 return NULL; 899 900 if (dir->entry == NULL) 901 { 902 READDIR3args args; 903 904 xdr_free((xdrproc_t)xdr_READDIR3res, (char *)&dir->res); 905 memset(&dir->res, '\0', sizeof(dir->res)); 906 907 args.dir = dir->handle; 908 args.cookie = dir->cookie; 909 memcpy(&args.cookieverf, &dir->cookieverf, sizeof(cookieverf3)); 910 args.count = 1024; 911 912 if (nfsproc3_readdir_3(args, &dir->res, nfs->nfs_client) != RPC_SUCCESS) 913 { 914 rt_kprintf("Readdir failed\n"); 915 916 return NULL; 917 } 918 else if (dir->res.status != NFS3_OK) 919 { 920 rt_kprintf("Readdir failed: %d\n", dir->res.status); 921 922 return NULL; 923 } 924 925 memcpy(&dir->cookieverf, &dir->res.READDIR3res_u.resok.cookieverf, sizeof(cookieverf3)); 926 dir->eof = dir->res.READDIR3res_u.resok.reply.eof; 927 dir->entry = dir->res.READDIR3res_u.resok.reply.entries; 928 } 929 if (dir->eof == TRUE && dir->entry == NULL) 930 return NULL; 931 932 dir->cookie = dir->entry->cookie; 933 strncpy(name, dir->entry->name, NAME_MAX-1); 934 dir->entry = dir->entry->nextentry; 935 name[NAME_MAX - 1] = '\0'; 936 937 return name; 938 } 939 940 int nfs_unlink(struct dfs_filesystem *fs, const char *path) 941 { 942 int ret = 0; 943 nfs_filesystem *nfs; 944 945 RT_ASSERT(fs != NULL); 946 RT_ASSERT(fs->data != NULL); 947 nfs = (nfs_filesystem *)fs->data; 948 949 if (nfs_is_directory(nfs, path) == RT_FALSE) 950 { 951 /* remove file */ 952 REMOVE3args args; 953 REMOVE3res res; 954 nfs_fh3 *handle; 955 956 handle = get_dir_handle(nfs, path); 957 if (handle == NULL) 958 return -1; 959 960 args.object.dir = *handle; 961 args.object.name = strrchr(path, '/') + 1; 962 if (args.object.name == NULL) 963 { 964 args.object.name = (char *)path; 965 } 966 967 memset(&res, 0, sizeof(res)); 968 969 if (nfsproc3_remove_3(args, &res, nfs->nfs_client) != RPC_SUCCESS) 970 { 971 rt_kprintf("Remove failed\n"); 972 ret = -1; 973 } 974 else if (res.status != NFS3_OK) 975 { 976 rt_kprintf("Remove failed: %d\n", res.status); 977 ret = -1; 978 } 979 xdr_free((xdrproc_t)xdr_REMOVE3res, (char *)&res); 980 xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)handle); 981 rt_free(handle); 982 } 983 else 984 { 985 /* remove directory */ 986 RMDIR3args args; 987 RMDIR3res res; 988 nfs_fh3 *handle; 989 990 handle = get_dir_handle(nfs, path); 991 if (handle == NULL) 992 return -1; 993 994 args.object.dir = *handle; 995 args.object.name = strrchr(path, '/') + 1; 996 if (args.object.name == NULL) 997 { 998 args.object.name = (char *)path; 999 } 1000 1001 memset(&res, 0, sizeof(res)); 1002 1003 if (nfsproc3_rmdir_3(args, &res, nfs->nfs_client) != RPC_SUCCESS) 1004 { 1005 rt_kprintf("Rmdir failed\n"); 1006 ret = -1; 1007 } 1008 else if (res.status != NFS3_OK) 1009 { 1010 rt_kprintf("Rmdir failed: %d\n", res.status); 1011 ret = -1; 1012 } 1013 1014 xdr_free((xdrproc_t)xdr_RMDIR3res, (char *)&res); 1015 xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)handle); 1016 rt_free(handle); 1017 } 1018 1019 return ret; 1020 } 1021 1022 int nfs_rename(struct dfs_filesystem *fs, const char *src, const char *dest) 1023 { 1024 RENAME3args args; 1025 RENAME3res res; 1026 nfs_fh3 *sHandle; 1027 nfs_fh3 *dHandle; 1028 int ret = 0; 1029 nfs_filesystem *nfs; 1030 1031 RT_ASSERT(fs != NULL); 1032 RT_ASSERT(fs->data != NULL); 1033 nfs = (nfs_filesystem *)fs->data; 1034 1035 if (nfs->nfs_client == NULL) 1036 return -1; 1037 1038 sHandle = get_dir_handle(nfs, src); 1039 if (sHandle == NULL) 1040 return -1; 1041 1042 dHandle = get_dir_handle(nfs, dest); 1043 if (dHandle == NULL) 1044 return -1; 1045 1046 args.from.dir = *sHandle; 1047 args.from.name = strrchr(src, '/') + 1; 1048 if (args.from.name == NULL) 1049 args.from.name = (char *)src; 1050 1051 args.to.dir = *dHandle; 1052 args.to.name = strrchr(src, '/') + 1; 1053 if (args.to.name == NULL) 1054 args.to.name = (char *)dest; 1055 1056 memset(&res, '\0', sizeof(res)); 1057 1058 if (nfsproc3_rename_3(args, &res, nfs->nfs_client) != RPC_SUCCESS) 1059 { 1060 rt_kprintf("Rename failed\n"); 1061 ret = -1; 1062 } 1063 else if (res.status != NFS3_OK) 1064 { 1065 rt_kprintf("Rename failed: %d\n", res.status); 1066 ret = -1; 1067 } 1068 1069 xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)sHandle); 1070 xdr_free((xdrproc_t)xdr_nfs_fh3, (char *)dHandle); 1071 xdr_free((xdrproc_t)xdr_RENAME3res, (char *)&res); 1072 1073 return ret; 1074 } 1075 1076 int nfs_getdents(struct dfs_fd *file, struct dirent *dirp, uint32_t count) 1077 { 1078 nfs_dir *dir; 1079 rt_uint32_t index; 1080 struct dirent *d; 1081 nfs_filesystem *nfs; 1082 char *name; 1083 1084 1085 RT_ASSERT(file->data != NULL); 1086 struct dfs_filesystem *dfs_nfs = ((struct dfs_filesystem*)(file->data)); 1087 nfs = (struct nfs_filesystem *)(dfs_nfs->data); 1088 dir = (nfs_dir *)(nfs->data); 1089 RT_ASSERT(dir != NULL); 1090 1091 /* make integer count */ 1092 count = (count / sizeof(struct dirent)) * sizeof(struct dirent); 1093 if (count == 0) 1094 return -EINVAL; 1095 1096 index = 0; 1097 while (1) 1098 { 1099 d = dirp + index; 1100 1101 name = nfs_readdir(nfs, dir); 1102 if (name == NULL) 1103 break; 1104 1105 d->d_type = DT_REG; 1106 1107 d->d_namlen = rt_strlen(name); 1108 d->d_reclen = (rt_uint16_t)sizeof(struct dirent); 1109 rt_strncpy(d->d_name, name, rt_strlen(name) + 1); 1110 1111 index ++; 1112 if (index * sizeof(struct dirent) >= count) 1113 break; 1114 } 1115 1116 return index * sizeof(struct dirent); 1117 } 1118 1119 static const struct dfs_file_ops nfs_fops = 1120 { 1121 nfs_open, 1122 nfs_close, 1123 nfs_ioctl, 1124 nfs_read, 1125 nfs_write, 1126 NULL, /* flush */ 1127 nfs_lseek, 1128 nfs_getdents, 1129 NULL, /* poll */ 1130 }; 1131 1132 static const struct dfs_filesystem_ops _nfs = 1133 { 1134 "nfs", 1135 DFS_FS_FLAG_DEFAULT, 1136 &nfs_fops, 1137 nfs_mount, 1138 nfs_unmount, 1139 NULL, /* mkfs */ 1140 NULL, /* statfs */ 1141 nfs_unlink, 1142 nfs_stat, 1143 nfs_rename, 1144 }; 1145 1146 int nfs_init(void) 1147 { 1148 /* register nfs file system */ 1149 dfs_register(&_nfs); 1150 1151 return RT_EOK; 1152 } 1153 INIT_COMPONENT_EXPORT(nfs_init); 1154 1155