diff options
Diffstat (limited to 'api')
-rw-r--r-- | api/src/glfs-fops.c | 2 | ||||
-rw-r--r-- | api/src/glfs-internal.h | 2 | ||||
-rw-r--r-- | api/src/glfs-resolve.c | 96 |
3 files changed, 96 insertions, 4 deletions
diff --git a/api/src/glfs-fops.c b/api/src/glfs-fops.c index 6ae0426ac8..a6e2f1744e 100644 --- a/api/src/glfs-fops.c +++ b/api/src/glfs-fops.c @@ -108,7 +108,7 @@ glfs_lstat (struct glfs *fs, const char *path, struct stat *stat) goto out; } - ret = glfs_resolve (fs, subvol, path, &loc, &iatt); + ret = glfs_lresolve (fs, subvol, path, &loc, &iatt); if (ret == 0 && stat) iatt_to_stat (&iatt, stat); diff --git a/api/src/glfs-internal.h b/api/src/glfs-internal.h index 6380cd2ae2..8c9e356f9c 100644 --- a/api/src/glfs-internal.h +++ b/api/src/glfs-internal.h @@ -53,6 +53,8 @@ void glfs_init_done (struct glfs *fs, int ret); int glfs_process_volfp (struct glfs *fs, FILE *fp); int glfs_resolve (struct glfs *fs, xlator_t *subvol, const char *path, loc_t *loc, struct iatt *iatt); +int glfs_lresolve (struct glfs *fs, xlator_t *subvol, const char *path, loc_t *loc, + struct iatt *iatt); void glfs_first_lookup (xlator_t *subvol); static inline void diff --git a/api/src/glfs-resolve.c b/api/src/glfs-resolve.c index c03c4154db..83667378e2 100644 --- a/api/src/glfs-resolve.c +++ b/api/src/glfs-resolve.c @@ -80,6 +80,35 @@ out: } +int +glfs_resolve_symlink (struct glfs *fs, xlator_t *subvol, inode_t *inode, + char **lpath) +{ + loc_t loc = {0, }; + char *path = NULL; + char *rpath = NULL; + int ret = -1; + + loc.inode = inode_ref (inode); + uuid_copy (loc.gfid, inode->gfid); + ret = inode_path (inode, NULL, &rpath); + if (ret < 0) + goto out; + loc.path = rpath; + + ret = syncop_readlink (subvol, &loc, &path, 4096); + + if (ret) + goto out; + + if (lpath) + *lpath = path; +out: + loc_wipe (&loc); + return ret; +} + + inode_t * glfs_resolve_component (struct glfs *fs, xlator_t *subvol, inode_t *parent, const char *component, struct iatt *iatt) @@ -159,8 +188,9 @@ out: int -glfs_resolve (struct glfs *fs, xlator_t *subvol, const char *origpath, - loc_t *loc, struct iatt *iatt) +glfs_resolve_at (struct glfs *fs, xlator_t *subvol, inode_t *at, + const char *origpath, loc_t *loc, struct iatt *iatt, + int follow) { inode_t *inode = NULL; inode_t *parent = NULL; @@ -178,7 +208,13 @@ glfs_resolve (struct glfs *fs, xlator_t *subvol, const char *origpath, } parent = NULL; - inode = inode_ref (subvol->itable->root); + if (at && path[0] != '/') + /* A relative resolution of a path which starts with '/' + is equal to an absolute path resolution. + */ + inode = inode_ref (at); + else + inode = inode_ref (subvol->itable->root); for (component = strtok_r (path, "/", &saveptr); component; component = next_component) { @@ -195,6 +231,36 @@ glfs_resolve (struct glfs *fs, xlator_t *subvol, const char *origpath, if (!inode) break; + if (!IA_ISLNK (ciatt.ia_type) && (next_component || follow)) { + /* If the component is not the last piece, + then following it is necessary even if + not requested by the caller + */ + char *lpath = NULL; + loc_t sym_loc = {0,}; + + ret = glfs_resolve_symlink (fs, subvol, inode, &lpath); + inode_unref (inode); + inode = NULL; + if (ret < 0) + break; + + ret = glfs_resolve_at (fs, subvol, parent, lpath, + &sym_loc, + /* followed iatt becomes the + component iatt + */ + &ciatt, + /* always recurisvely follow while + following symlink + */ + 1); + if (ret == 0) + inode = inode_ref (sym_loc.inode); + loc_wipe (&sym_loc); + GF_FREE (lpath); + } + if (!next_component) break; @@ -242,3 +308,27 @@ out: return ret; } + +int +glfs_resolve (struct glfs *fs, xlator_t *subvol, const char *origpath, + loc_t *loc, struct iatt *iatt) +{ + int ret = -1; + + ret = glfs_resolve_at (fs, subvol, NULL, origpath, loc, iatt, 1); + + return ret; +} + + +int +glfs_lresolve (struct glfs *fs, xlator_t *subvol, const char *origpath, + loc_t *loc, struct iatt *iatt) +{ + int ret = -1; + + ret = glfs_resolve_at (fs, subvol, NULL, origpath, loc, iatt, 0); + + return ret; +} + |