* @brief Open a file which specified by path with specified oflags. * * This function opens or creates a file with given path and flags. It handles: * - Path normalization and resolution (including symbolic links) * - File creation when O_CREAT is specified * - Permission checking * - Directory vs regular file validation * - Symbolic link following (unless O_NOFOLLOW is set) * * @param[in
| 563 | * -EISDIR if path is directory when opening as regular file |
| 564 | */ |
| 565 | int dfs_file_open(struct dfs_file *file, const char *path, int oflags, mode_t mode) |
| 566 | { |
| 567 | int ret = -RT_ERROR; |
| 568 | char *fullpath = RT_NULL; |
| 569 | struct dfs_dentry *dentry = RT_NULL; |
| 570 | int fflags = dfs_fflags(oflags); |
| 571 | |
| 572 | if (mode == 0) |
| 573 | { |
| 574 | mode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); /* 0666 */ |
| 575 | } |
| 576 | |
| 577 | if (file && path) |
| 578 | { |
| 579 | fullpath = dfs_normalize_path(NULL, path); |
| 580 | if (fullpath) |
| 581 | { |
| 582 | struct dfs_mnt *mnt = RT_NULL; |
| 583 | |
| 584 | DLOG(msg, "dfs_file", "mnt", DLOG_MSG, "dfs_mnt_lookup(%s)", fullpath); |
| 585 | mnt = dfs_mnt_lookup(fullpath); |
| 586 | if (mnt) |
| 587 | { |
| 588 | char *tmp = dfs_file_realpath(&mnt, fullpath, DFS_REALPATH_EXCEPT_LAST); |
| 589 | if (tmp) |
| 590 | { |
| 591 | rt_free(fullpath); |
| 592 | fullpath = tmp; |
| 593 | } |
| 594 | |
| 595 | DLOG(msg, "dfs_file", "dentry", DLOG_MSG, "dfs_dentry_lookup(mnt, %s)", fullpath); |
| 596 | dentry = dfs_dentry_lookup(mnt, fullpath, oflags); |
| 597 | if (dentry && dentry->vnode->type == FT_SYMLINK) |
| 598 | { |
| 599 | /* it's a symbol link but not follow */ |
| 600 | if (oflags & O_NOFOLLOW) |
| 601 | { |
| 602 | /* no follow symbol link */ |
| 603 | dfs_dentry_unref(dentry); |
| 604 | dentry = RT_NULL; |
| 605 | } |
| 606 | else |
| 607 | { |
| 608 | struct dfs_dentry *target_dentry = RT_NULL; |
| 609 | char *path = dfs_file_realpath(&mnt, fullpath, DFS_REALPATH_ONLY_LAST); |
| 610 | if (path) |
| 611 | { |
| 612 | target_dentry = dfs_dentry_lookup(mnt, path, oflags); |
| 613 | rt_free(path); |
| 614 | } |
| 615 | dfs_dentry_unref(dentry); |
| 616 | dentry = target_dentry; |
| 617 | } |
| 618 | } |
| 619 | |
| 620 | if (dentry) |
| 621 | { |
| 622 | if (oflags & O_DIRECTORY) |
no test coverage detected