summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/examples/glfsxmp.c81
-rw-r--r--api/src/glfs-fops.c170
-rw-r--r--api/src/glfs-internal.h5
-rw-r--r--api/src/glfs-resolve.c30
-rw-r--r--api/src/glfs.c18
-rw-r--r--api/src/glfs.h8
6 files changed, 302 insertions, 10 deletions
diff --git a/api/examples/glfsxmp.c b/api/examples/glfsxmp.c
index b359cc7444..644793a4b1 100644
--- a/api/examples/glfsxmp.c
+++ b/api/examples/glfsxmp.c
@@ -60,6 +60,81 @@ test_xattr (glfs_t *fs)
int
+test_chdir (glfs_t *fs)
+{
+ int ret = -1;
+ ino_t ino = 0;
+ struct stat st;
+ char *topdir = "/topdir";
+ char *linkdir = "/linkdir";
+ char *subdir = "./subdir";
+ char *respath = NULL;
+ char pathbuf[4096];
+
+ ret = glfs_mkdir (fs, topdir, 0755);
+ if (ret) {
+ fprintf (stderr, "mkdir(%s): %s\n", topdir, strerror (errno));
+ return -1;
+ }
+
+ respath = glfs_getcwd (fs, pathbuf, 4096);
+ fprintf (stdout, "getcwd() = %s\n", respath);
+
+ ret = glfs_symlink (fs, topdir, linkdir);
+ if (ret) {
+ fprintf (stderr, "symlink(%s, %s): %s\n", topdir, linkdir, strerror (errno));
+ return -1;
+ }
+
+ ret = glfs_chdir (fs, linkdir);
+ if (ret) {
+ fprintf (stderr, "chdir(%s): %s\n", linkdir, strerror (errno));
+ return -1;
+ }
+
+ respath = glfs_getcwd (fs, pathbuf, 4096);
+ fprintf (stdout, "getcwd() = %s\n", respath);
+
+ respath = glfs_realpath (fs, subdir, pathbuf);
+ if (respath) {
+ fprintf (stderr, "realpath(%s) worked unexpectedly: %s\n", subdir, respath);
+ return -1;
+ }
+
+ ret = glfs_mkdir (fs, subdir, 0755);
+ if (ret) {
+ fprintf (stderr, "mkdir(%s): %s\n", subdir, strerror (errno));
+ return -1;
+ }
+
+ respath = glfs_realpath (fs, subdir, pathbuf);
+ if (!respath) {
+ fprintf (stderr, "realpath(%s): %s\n", subdir, strerror (errno));
+ } else {
+ fprintf (stdout, "realpath(%s) = %s\n", subdir, respath);
+ }
+
+ ret = glfs_chdir (fs, subdir);
+ if (ret) {
+ fprintf (stderr, "chdir(%s): %s\n", subdir, strerror (errno));
+ return -1;
+ }
+
+ respath = glfs_getcwd (fs, pathbuf, 4096);
+ fprintf (stdout, "getcwd() = %s\n", respath);
+
+ respath = glfs_realpath (fs, "/linkdir/subdir", pathbuf);
+ if (!respath) {
+ fprintf (stderr, "realpath(/linkdir/subdir): %s\n", strerror (errno));
+ } else {
+ fprintf (stdout, "realpath(/linkdir/subdir) = %s\n", respath);
+ }
+
+ return 0;
+}
+
+
+int
main (int argc, char *argv[])
{
glfs_t *fs = NULL;
@@ -73,7 +148,7 @@ main (int argc, char *argv[])
char *filename = "/filename2";
- fs = glfs_new ("iops");
+ fs = glfs_new ("fsync");
if (!fs) {
fprintf (stderr, "glfs_new: returned NULL\n");
return 1;
@@ -93,7 +168,7 @@ main (int argc, char *argv[])
sleep (2);
- fs2 = glfs_new ("iops");
+ fs2 = glfs_new ("fsync");
if (!fs2) {
fprintf (stderr, "glfs_new: returned NULL\n");
return 1;
@@ -161,6 +236,8 @@ main (int argc, char *argv[])
test_xattr (fs);
+ test_chdir (fs);
+
// done
glfs_fini (fs);
diff --git a/api/src/glfs-fops.c b/api/src/glfs-fops.c
index 84d364857f..74d0daf99a 100644
--- a/api/src/glfs-fops.c
+++ b/api/src/glfs-fops.c
@@ -33,7 +33,7 @@ glfs_open (struct glfs *fs, const char *path, int flags)
goto out;
}
- glfd = GF_CALLOC (1, sizeof (*glfd), glfs_mt_glfs_fd_t);
+ glfd = glfs_fd_new (fs);
if (!glfd)
goto out;
@@ -207,7 +207,7 @@ glfs_creat (struct glfs *fs, const char *path, int flags, mode_t mode)
goto out;
}
- glfd = GF_CALLOC (1, sizeof (*glfd), glfs_mt_glfs_fd_t);
+ glfd = glfs_fd_new (fs);
if (!glfd)
goto out;
@@ -1316,7 +1316,7 @@ glfs_opendir (struct glfs *fs, const char *path)
goto out;
}
- glfd = GF_CALLOC (1, sizeof (*glfd), glfs_mt_glfs_fd_t);
+ glfd = glfs_fd_new (fs);
if (!glfd)
goto out;
INIT_LIST_HEAD (&glfd->entries);
@@ -2136,3 +2136,167 @@ glfs_fremovexattr (struct glfs_fd *glfd, const char *name)
out:
return ret;
}
+
+
+void
+glfs_cwd_set (struct glfs *fs, inode_t *inode)
+{
+ if (fs->cwd) {
+ inode_unref (fs->cwd);
+ fs->cwd = NULL;
+ }
+
+ fs->cwd = inode_ref (inode);
+}
+
+
+int
+glfs_chdir (struct glfs *fs, const char *path)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ loc_t loc = {0, };
+ struct iatt iatt = {0, };
+
+ __glfs_entry_fs (fs);
+
+ subvol = glfs_active_subvol (fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ ret = glfs_resolve (fs, subvol, path, &loc, &iatt);
+ if (ret)
+ goto out;
+
+ if (!IA_ISDIR (iatt.ia_type)) {
+ ret = -1;
+ errno = ENOTDIR;
+ goto out;
+ }
+
+ glfs_cwd_set (fs, loc.inode);
+
+out:
+ loc_wipe (&loc);
+
+ return ret;
+}
+
+
+int
+glfs_fchdir (struct glfs_fd *glfd)
+{
+ int ret = -1;
+ inode_t *inode = NULL;
+
+ __glfs_entry_fd (glfd);
+
+ inode = glfd->fd->inode;
+
+ if (!IA_ISDIR (inode->ia_type)) {
+ ret = -1;
+ errno = ENOTDIR;
+ goto out;
+ }
+
+ glfs_cwd_set (glfd->fs, inode);
+ ret = 0;
+out:
+ return ret;
+}
+
+
+char *
+glfs_realpath (struct glfs *fs, const char *path, char *resolved_path)
+{
+ int ret = -1;
+ char *retpath = NULL;
+ char *allocpath = NULL;
+ xlator_t *subvol = NULL;
+ loc_t loc = {0, };
+ struct iatt iatt = {0, };
+
+ __glfs_entry_fs (fs);
+
+ if (resolved_path)
+ retpath = resolved_path;
+ else
+ retpath = allocpath = malloc (PATH_MAX + 1);
+
+ if (!retpath) {
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+
+ subvol = glfs_active_subvol (fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ ret = glfs_resolve (fs, subvol, path, &loc, &iatt);
+ if (ret)
+ goto out;
+
+ if (loc.path) {
+ strncpy (retpath, loc.path, PATH_MAX);
+ retpath[PATH_MAX] = 0;
+ }
+
+out:
+ loc_wipe (&loc);
+
+ if (ret == -1) {
+ if (allocpath)
+ free (allocpath);
+ retpath = NULL;
+ }
+
+ return retpath;
+}
+
+
+char *
+glfs_getcwd (struct glfs *fs, char *buf, size_t n)
+{
+ int ret = -1;
+ inode_t *inode = NULL;
+ char *path = NULL;
+
+ __glfs_entry_fs (fs);
+
+ if (!buf || n < 2) {
+ ret = -1;
+ errno = EINVAL;
+ goto out;
+ }
+
+ inode = fs->cwd;
+ if (!inode) {
+ strncpy (buf, "/", n);
+ ret = 0;
+ goto out;
+ }
+
+ ret = inode_path (inode, 0, &path);
+ if (n <= ret) {
+ ret = -1;
+ errno = ERANGE;
+ goto out;
+ }
+
+ strncpy (buf, path, n);
+ ret = 0;
+out:
+ GF_FREE (path);
+
+ if (ret < 0)
+ return NULL;
+
+ return buf;
+}
diff --git a/api/src/glfs-internal.h b/api/src/glfs-internal.h
index c2fc0ecc1e..082b8fa5c9 100644
--- a/api/src/glfs-internal.h
+++ b/api/src/glfs-internal.h
@@ -36,9 +36,12 @@ struct glfs {
char *oldvolfile;
ssize_t oldvollen;
+
+ inode_t *cwd;
};
struct glfs_fd {
+ struct glfs *fs;
off_t offset;
fd_t *fd;
struct list_head entries;
@@ -75,6 +78,8 @@ __glfs_entry_fd (struct glfs_fd *fd)
void glfs_fd_destroy (struct glfs_fd *glfd);
+struct glfs_fd *glfs_fd_new (struct glfs *fs);
+
xlator_t * glfs_fd_subvol (struct glfs_fd *glfd);
xlator_t * glfs_active_subvol (struct glfs *fs);
diff --git a/api/src/glfs-resolve.c b/api/src/glfs-resolve.c
index a9b9381863..8b654e4dbf 100644
--- a/api/src/glfs-resolve.c
+++ b/api/src/glfs-resolve.c
@@ -98,7 +98,7 @@ glfs_resolve_symlink (struct glfs *fs, xlator_t *subvol, inode_t *inode,
ret = syncop_readlink (subvol, &loc, &path, 4096);
- if (ret)
+ if (ret < 0)
goto out;
if (lpath)
@@ -161,7 +161,12 @@ glfs_resolve_component (struct glfs *fs, xlator_t *subvol, inode_t *parent,
goto out;
}
- loc.inode = inode_grep (parent->table, parent, component);
+ if (strcmp (component, ".") == 0)
+ loc.inode = inode_ref (parent);
+ else if (strcmp (component, "..") == 0)
+ loc.inode = inode_parent (parent, 0, 0);
+ else
+ loc.inode = inode_grep (parent->table, parent, component);
if (loc.inode) {
uuid_copy (loc.gfid, loc.inode->gfid);
@@ -335,12 +340,29 @@ out:
int
+glfs_resolve_path (struct glfs *fs, xlator_t *subvol, const char *origpath,
+ loc_t *loc, struct iatt *iatt, int follow)
+{
+ int ret = -1;
+
+ if (origpath[0] == '/')
+ ret = glfs_resolve_at (fs, subvol, NULL, origpath, loc, iatt,
+ follow);
+ else
+ ret = glfs_resolve_at (fs, subvol, fs->cwd, origpath, loc, iatt,
+ follow);
+
+ 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);
+ ret = glfs_resolve_path (fs, subvol, origpath, loc, iatt, 1);
return ret;
}
@@ -352,7 +374,7 @@ glfs_lresolve (struct glfs *fs, xlator_t *subvol, const char *origpath,
{
int ret = -1;
- ret = glfs_resolve_at (fs, subvol, NULL, origpath, loc, iatt, 0);
+ ret = glfs_resolve_path (fs, subvol, origpath, loc, iatt, 0);
return ret;
}
diff --git a/api/src/glfs.c b/api/src/glfs.c
index 705702d0da..21cded39c6 100644
--- a/api/src/glfs.c
+++ b/api/src/glfs.c
@@ -11,6 +11,7 @@
/*
TODO:
+ - refresh fs->cwd inode on graph switch
- set proper pid/lk_owner to call frames (currently buried in syncop)
- fix logging.c/h to store logfp and loglevel in glusterfs_ctx_t and
reach it via THIS.
@@ -280,7 +281,22 @@ out:
struct glfs *
glfs_from_glfd (struct glfs_fd *glfd)
{
- return ((xlator_t *)glfd->fd->inode->table->xl->ctx->master)->private;
+ return glfd->fs;
+}
+
+
+struct glfs_fd *
+glfs_fd_new (struct glfs *fs)
+{
+ struct glfs_fd *glfd = NULL;
+
+ glfd = GF_CALLOC (1, sizeof (*glfd), glfs_mt_glfs_fd_t);
+ if (!glfd)
+ return NULL;
+
+ glfd->fs = fs;
+
+ return glfd;
}
diff --git a/api/src/glfs.h b/api/src/glfs.h
index e19c1cd259..7ff31dd62e 100644
--- a/api/src/glfs.h
+++ b/api/src/glfs.h
@@ -442,6 +442,14 @@ int glfs_lremovexattr (glfs_t *fs, const char *path, const char *name);
int glfs_fremovexattr (glfs_fd_t *fd, const char *name);
+char *glfs_getcwd (glfs_t *fs, char *buf, size_t size);
+
+int glfs_chdir (glfs_t *fs, const char *path);
+
+int glfs_fchdir (glfs_fd_t *fd);
+
+char *glfs_realpath (glfs_t *fs, const char *path, char *resolved_path);
+
__END_DECLS
#endif /* !_GLFS_H */