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 6ae0426ac..a6e2f1744 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 6380cd2ae..8c9e356f9 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 c03c4154d..83667378e 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; +} +  | 
