diff options
Diffstat (limited to 'libglusterfsclient')
-rwxr-xr-x | libglusterfsclient/src/libglusterfsclient-internals.h | 2 | ||||
-rwxr-xr-x | libglusterfsclient/src/libglusterfsclient.c | 133 | ||||
-rwxr-xr-x | libglusterfsclient/src/libglusterfsclient.h | 10 |
3 files changed, 140 insertions, 5 deletions
diff --git a/libglusterfsclient/src/libglusterfsclient-internals.h b/libglusterfsclient/src/libglusterfsclient-internals.h index d623e3d7e..200c25c2c 100755 --- a/libglusterfsclient/src/libglusterfsclient-internals.h +++ b/libglusterfsclient/src/libglusterfsclient-internals.h @@ -130,7 +130,7 @@ typedef struct { */ struct dirent dirp; struct direntcache *dcache; - + char vpath[PATH_MAX]; } libglusterfs_client_fd_ctx_t; typedef struct libglusterfs_client_async_local { diff --git a/libglusterfsclient/src/libglusterfsclient.c b/libglusterfsclient/src/libglusterfsclient.c index a6f09e996..58803e893 100755 --- a/libglusterfsclient/src/libglusterfsclient.c +++ b/libglusterfsclient/src/libglusterfsclient.c @@ -189,7 +189,7 @@ out: } libglusterfs_client_fd_ctx_t * -libgf_alloc_fd_ctx (libglusterfs_client_ctx_t *ctx, fd_t *fd) +libgf_alloc_fd_ctx (libglusterfs_client_ctx_t *ctx, fd_t *fd, char *vpath) { libglusterfs_client_fd_ctx_t *fdctx = NULL; uint64_t ctxaddr = 0; @@ -217,6 +217,14 @@ libgf_alloc_fd_ctx (libglusterfs_client_ctx_t *ctx, fd_t *fd) */ } } + + if (vpath != NULL) { + strcpy (fdctx->vpath, vpath); + if (vpath[strlen(vpath) - 1] != '/') { + strcat (fdctx->vpath, "/"); + } + } + fd_ctx_set (fd, libgf_inode_to_xlator (fd->inode), ctxaddr); out: return fdctx; @@ -1575,6 +1583,48 @@ libgf_vmp_entry_match (struct vmp_entry *entry, char *path) #define LIBGF_VMP_EXACT 1 #define LIBGF_VMP_LONGESTPREFIX 0 + + +/* copies vmp from the vmp-entry having glusterfs handle @handle, into @vmp */ +char * +libgf_vmp_search_vmp (glusterfs_handle_t handle, char *vmp, size_t vmp_size) +{ + char *res = NULL; + struct vmp_entry *entry = NULL; + + if (handle == NULL) { + goto out; + } + + pthread_mutex_lock (&vmplock); + { + if (vmplist.entries == 0) { + gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "Virtual Mount Point " + "list is empty."); + goto unlock; + } + + list_for_each_entry(entry, &vmplist.list, list) { + if (entry->handle == handle) { + if ((vmp_size) < (strlen (entry->vmp) + 1)) { + errno = ENAMETOOLONG; + goto unlock; + } + + strcpy (vmp, entry->vmp); + res = vmp; + break; + } + } + } +unlock: + pthread_mutex_unlock (&vmplock); + +out: + return res; +} + + struct vmp_entry * _libgf_vmp_search_entry (char *path, int searchtype) { @@ -2889,6 +2939,7 @@ glusterfs_glh_open (glusterfs_handle_t handle, const char *path, int flags,...) mode_t mode = 0; va_list ap; char *pathres = NULL; + char *vpath = NULL; GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, ctx, out); GF_VALIDATE_ABSOLUTE_PATH_OR_GOTO (LIBGF_XL_NAME, path, out); @@ -2974,8 +3025,13 @@ op_over: goto out; } + vpath = NULL; + if (S_ISDIR (loc.inode->st_mode)) { + vpath = (char *)path; + } + if (!libgf_get_fd_ctx (fd)) { - if (!libgf_alloc_fd_ctx (ctx, fd)) { + if (!libgf_alloc_fd_ctx (ctx, fd, vpath)) { gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "Failed to" " allocate fd context"); errno = EINVAL; @@ -2985,7 +3041,7 @@ op_over: } if ((flags & O_TRUNC) && (((flags & O_ACCMODE) == O_RDWR) - || ((flags & O_ACCMODE) == O_WRONLY))) { + || ((flags & O_ACCMODE) == O_WRONLY))) { inode_ctx = libgf_get_inode_ctx (fd->inode); if (S_ISREG (inode_ctx->stbuf.st_mode)) { inode_ctx->stbuf.st_size = 0; @@ -5495,7 +5551,7 @@ glusterfs_glh_opendir (glusterfs_handle_t handle, const char *path) } if (!libgf_get_fd_ctx (dirfd)) { - if (!(libgf_alloc_fd_ctx (ctx, dirfd))) { + if (!(libgf_alloc_fd_ctx (ctx, dirfd, (char *)path))) { gf_log (LIBGF_XL_NAME, GF_LOG_ERROR, "Context " "allocation failed"); op_ret = -1; @@ -7689,6 +7745,75 @@ unlock: int +glusterfs_fchdir (glusterfs_file_t fd) +{ + int op_ret = -1; + char vpath[PATH_MAX]; + char vmp[PATH_MAX]; + char *res = NULL; + libglusterfs_client_fd_ctx_t *fd_ctx = NULL; + glusterfs_handle_t handle = NULL; + + GF_VALIDATE_OR_GOTO (LIBGF_XL_NAME, fd, out); + + /* FIXME: there is a race-condition between glusterfs_fchdir and + glusterfs_close. If two threads of application call glusterfs_fchdir + and glusterfs_close on the same fd, there is a possibility of + glusterfs_fchdir accessing freed memory of fd_ctx. + */ + + fd_ctx = libgf_get_fd_ctx (fd); + if (!fd_ctx) { + errno = EBADF; + goto out; + } + + pthread_mutex_lock (&fd_ctx->lock); + { + handle = fd_ctx->ctx; + strcpy (vpath, fd_ctx->vpath); + } + pthread_mutex_unlock (&fd_ctx->lock); + + if (vpath[0] == '\0') { + errno = ENOTDIR; + goto out; + } + + res = libgf_vmp_search_vmp (handle, vmp, PATH_MAX); + if (res == NULL) { + errno = EBADF; + goto out; + } + + /* both vmp and vpath are terminated with '/'. Also path starts with a + '/'. Hence the extra '/' amounts to NULL character at the end of the + string. + */ + if ((strlen (vmp) + strlen (vpath)) > PATH_MAX) { + errno = ENAMETOOLONG; + goto out; + } + + pthread_mutex_lock (&cwdlock); + { + strcpy (cwd, vmp); + res = vpath; + if (res[0] == '/') { + res++; + } + + strcat (cwd, res); + } + pthread_mutex_unlock (&cwdlock); + + op_ret = 0; +out: + return op_ret; +} + + +int glusterfs_chdir (const char *path) { int32_t op_ret = -1; diff --git a/libglusterfsclient/src/libglusterfsclient.h b/libglusterfsclient/src/libglusterfsclient.h index 2486dd754..74575fa61 100755 --- a/libglusterfsclient/src/libglusterfsclient.h +++ b/libglusterfsclient/src/libglusterfsclient.h @@ -1315,6 +1315,16 @@ glusterfs_fcntl (glusterfs_file_t fd, int cmd, ...); int glusterfs_chdir (const char *path); +/* + * Change the current working directory to the path @fd is opened on. + * + * @fd : current working directory will be changed to path @fd is opened on. + * + * Returns 0 on success and -1 on with errno set appropriately. + */ +int +glusterfs_fchdir (glusterfs_file_t fd); + /* FIXME: review the need for these apis */ /* added for log related initialization in booster fork implementation */ void |