diff options
author | Anand Avati <avati@redhat.com> | 2012-08-28 23:23:52 -0700 |
---|---|---|
committer | Anand Avati <avati@redhat.com> | 2012-09-17 19:25:01 -0700 |
commit | 8f9e94c65516662ff49926203a73b3a0166c087e (patch) | |
tree | e9fba03e9a97a97dd0411a5009ac8147bb2bcd2f /api/src/glfs-resolve.c | |
parent | 0d3bec589748b4cc8295d9ed109d21c94e3d8854 (diff) |
gfapi: add symlink (auto resolution) support in resolver
- new internal API glfs_lresolve() for usage with APIs
like glfs_lXXXX() (e.g. glfs_lstat())
Change-Id: I61c60af6bda3072f189684ad8ac9815d59f455fc
BUG: 839950
Signed-off-by: Anand Avati <avati@redhat.com>
Reviewed-on: http://review.gluster.org/3866
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Amar Tumballi <amarts@redhat.com>
Diffstat (limited to 'api/src/glfs-resolve.c')
-rw-r--r-- | api/src/glfs-resolve.c | 96 |
1 files changed, 93 insertions, 3 deletions
diff --git a/api/src/glfs-resolve.c b/api/src/glfs-resolve.c index c03c4154db0..83667378e2c 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; +} + |