diff options
author | Prashanth Pai <ppai@redhat.com> | 2015-06-14 23:57:42 +0530 |
---|---|---|
committer | Thiago da Silva <thiago@redhat.com> | 2015-06-18 05:52:33 -0700 |
commit | ddbd7b570d0a9f599b417a499c912c5b13a003c9 (patch) | |
tree | 2dca993a300775af2367978c94ac34d7e332e3a1 /gluster | |
parent | 509abefca5902e4f0decf40368a90265d1a598bd (diff) |
Add missing Path based operation APIs
* Added commonly used path based operations that were missing from
the Volume class.
* Fixed function prototypes at places where it should be ssize_t
and not size_t. This caused overflow error at times.
* Added doc strings wherever they were missing.
Change-Id: I6ce28038da3cd0f89ab075045bb4092dd95e21c4
Signed-off-by: Prashanth Pai <ppai@redhat.com>
Diffstat (limited to 'gluster')
-rwxr-xr-x | gluster/api.py | 27 | ||||
-rwxr-xr-x | gluster/gfapi.py | 182 |
2 files changed, 189 insertions, 20 deletions
diff --git a/gluster/api.py b/gluster/api.py index 560ede8..62135c5 100755 --- a/gluster/api.py +++ b/gluster/api.py @@ -320,26 +320,26 @@ glfs_fsync = ctypes.CFUNCTYPE( glfs_lseek = ctypes.CFUNCTYPE(ctypes.c_ulong, ctypes.c_void_p, ctypes.c_ulong, ctypes.c_int)(('glfs_lseek', client)) -glfs_read = ctypes.CFUNCTYPE(ctypes.c_size_t, +glfs_read = ctypes.CFUNCTYPE(ctypes.c_ssize_t, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_size_t, ctypes.c_int)(('glfs_read', client)) -glfs_write = ctypes.CFUNCTYPE(ctypes.c_size_t, +glfs_write = ctypes.CFUNCTYPE(ctypes.c_ssize_t, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_size_t, ctypes.c_int)(('glfs_write', client)) -glfs_getxattr = ctypes.CFUNCTYPE(ctypes.c_size_t, +glfs_getxattr = ctypes.CFUNCTYPE(ctypes.c_ssize_t, ctypes.c_void_p, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_void_p, ctypes.c_size_t)(('glfs_getxattr', client)) -glfs_listxattr = ctypes.CFUNCTYPE(ctypes.c_size_t, +glfs_listxattr = ctypes.CFUNCTYPE(ctypes.c_ssize_t, ctypes.c_void_p, ctypes.c_char_p, ctypes.c_void_p, @@ -423,6 +423,25 @@ glfs_flistxattr = ctypes.CFUNCTYPE(ctypes.c_ssize_t, ctypes.c_size_t)(('glfs_flistxattr', client)) +glfs_access = ctypes.CFUNCTYPE(ctypes.c_int, + ctypes.c_void_p, + ctypes.c_char_p, + ctypes.c_int)(('glfs_access', client)) + +glfs_readlink = ctypes.CFUNCTYPE(ctypes.c_int, + ctypes.c_void_p, + ctypes.c_char_p, + ctypes.c_char_p, + ctypes.c_size_t)(('glfs_readlink', client)) + +glfs_chdir = ctypes.CFUNCTYPE(ctypes.c_int, + ctypes.c_void_p, + ctypes.c_char_p)(('glfs_chdir', client)) + +glfs_getcwd = ctypes.CFUNCTYPE(ctypes.c_char_p, + ctypes.c_void_p, + ctypes.c_char_p, + ctypes.c_size_t)(('glfs_getcwd', client)) # TODO: creat and open fails on test_create_file_already_exists & test_open_file_not_exist functional testing, # noqa diff --git a/gluster/gfapi.py b/gluster/gfapi.py index 8ba7251..96088ff 100755 --- a/gluster/gfapi.py +++ b/gluster/gfapi.py @@ -499,6 +499,33 @@ class Volume(object): self.log_file = log_file self.log_level = log_level + def access(self, path, mode): + """ + Use the real uid/gid to test for access to path. + + :param path: Path to be checked. + :param mode: mode should be F_OK to test the existence of path, or + it can be the inclusive OR of one or more of R_OK, W_OK, + and X_OK to test permissions + :returns: True if access is allowed, False if not + """ + ret = api.glfs_access(self.fs, path, mode) + if ret == 0: + return True + else: + return False + + def chdir(self, path): + """ + Change the current working directory to the given path. + + :param path: Path to change current working directory to + """ + ret = api.glfs_chdir(self.fs, path) + if ret < 0: + err = ctypes.get_errno() + raise OSError(err, os.strerror(err)) + def chmod(self, path, mode): """ Change mode of path @@ -551,6 +578,18 @@ class Volume(object): """ return self.stat(path).st_ctime + def getcwd(self): + """ + Returns current working directory. + """ + PATH_MAX = 4096 + buf = ctypes.create_string_buffer(PATH_MAX) + ret = api.glfs_getcwd(self.fs, buf, PATH_MAX) + if ret < 0: + err = ctypes.get_errno() + raise OSError(err, os.strerror(err)) + return buf.value + def getmtime(self, path): """ Returns the time when changes were made to the content of the path @@ -564,12 +603,30 @@ class Volume(object): """ return self.stat(filename).st_size - def getxattr(self, path, key, maxlen): - buf = ctypes.create_string_buffer(maxlen) - rc = api.glfs_getxattr(self.fs, path, key, buf, maxlen) + def getxattr(self, path, key, size=0): + """ + Retrieve the value of the extended attribute identified by key + for path specified. + + :param path: Path to file or directory + :param key: Key of extended attribute + :param size: If size is specified as zero, we first determine the + size of xattr and then allocate a buffer accordingly. + If size is non-zero, it is assumed the caller knows + the size of xattr. + :returns: Value of extended attribute corresponding to key specified. + """ + if size == 0: + size = api.glfs_getxattr(self.fs, path, key, None, 0) + if size < 0: + err = ctypes.get_errno() + raise OSError(err, os.strerror(err)) + + buf = ctypes.create_string_buffer(size) + rc = api.glfs_getxattr(self.fs, path, key, buf, size) if rc < 0: err = ctypes.get_errno() - raise IOError(err, os.strerror(err)) + raise OSError(err, os.strerror(err)) return buf.value[:rc] def isdir(self, path): @@ -618,12 +675,28 @@ class Volume(object): dir_list.append(name) return dir_list - def listxattr(self, path): - buf = ctypes.create_string_buffer(512) - rc = api.glfs_listxattr(self.fs, path, buf, 512) + def listxattr(self, path, size=0): + """ + Retrieve list of extended attribute keys for the specified path. + + :param path: Path to file or directory. + :param size: If size is specified as zero, we first determine the + size of list and then allocate a buffer accordingly. + If size is non-zero, it is assumed the caller knows + the size of the list. + :returns: List of extended attribute keys. + """ + if size == 0: + size = api.glfs_listxattr(self.fs, path, None, 0) + if size < 0: + err = ctypes.get_errno() + raise OSError(err, os.strerror(err)) + + buf = ctypes.create_string_buffer(size) + rc = api.glfs_listxattr(self.fs, path, buf, size) if rc < 0: err = ctypes.get_errno() - raise IOError(err, os.strerror(err)) + raise OSError(err, os.strerror(err)) xattrs = [] # Parsing character by character is ugly, but it seems like the # easiest way to deal with the "strings separated by NUL in one @@ -643,6 +716,11 @@ class Volume(object): return xattrs def lstat(self, path): + """ + Return stat information of path. If path is a symbolic link, then it + returns information about the link itself, not the file that it refers + to. + """ s = api.Stat() rc = api.glfs_lstat(self.fs, path, ctypes.byref(s)) if rc < 0: @@ -668,6 +746,9 @@ class Volume(object): self.mkdir(name, mode) def mkdir(self, path, mode=0777): + """ + Create a directory + """ ret = api.glfs_mkdir(self.fs, path, mode) if ret < 0: err = ctypes.get_errno() @@ -732,25 +813,67 @@ class Volume(object): return fd def opendir(self, path): + """ + Open a directory. + + :param path: Path to the directory + :returns: Returns a instance of Dir class + """ fd = api.glfs_opendir(self.fs, path) if not fd: err = ctypes.get_errno() raise OSError(err, os.strerror(err)) return Dir(fd) + def readlink(self, path): + """ + Read contents of symbolic link path. + + :param path: Path of symbolic link + :returns: Contents of symlink + """ + PATH_MAX = 4096 + buf = ctypes.create_string_buffer(PATH_MAX) + ret = api.glfs_readlink(self.fs, path, buf, PATH_MAX) + if ret < 0: + err = ctypes.get_errno() + raise OSError(err, os.strerror(err)) + return buf.value[:ret] + + def remove(self, path): + """ + Remove (delete) the file path. If path is a directory, + OSError is raised. + """ + return self.unlink(path) + def removexattr(self, path, key): + """ + Remove a extended attribute of the file. + + :param path: Path to the file or directory. + :param key: The key of extended attribute. + """ ret = api.glfs_removexattr(self.fs, path, key) if ret < 0: err = ctypes.get_errno() - raise IOError(err, os.strerror(err)) + raise OSError(err, os.strerror(err)) - def rename(self, opath, npath): - ret = api.glfs_rename(self.fs, opath, npath) + def rename(self, src, dst): + """ + Rename the file or directory from src to dst. + """ + ret = api.glfs_rename(self.fs, src, dst) if ret < 0: err = ctypes.get_errno() raise OSError(err, os.strerror(err)) def rmdir(self, path): + """ + Remove (delete) the directory path. Only works when the directory is + empty, otherwise, OSError is raised. In order to remove whole + directory trees, rmtree() can be used. + """ ret = api.glfs_rmdir(self.fs, path) if ret < 0: err = ctypes.get_errno() @@ -798,24 +921,51 @@ class Volume(object): onerror(self.rmdir, path, e) def setfsuid(self, uid): + """ + setfsuid() changes the value of the caller's filesystem user ID-the + user ID that the Linux kernel uses to check for all accesses to the + filesystem. + """ ret = api.glfs_setfsuid(uid) if ret < 0: err = ctypes.get_errno() raise OSError(err, os.strerror(err)) def setfsgid(self, gid): + """ + setfsgid() changes the value of the caller's filesystem group ID-the + group ID that the Linux kernel uses to check for all accesses to the + filesystem. + """ ret = api.glfs_setfsgid(gid) if ret < 0: err = ctypes.get_errno() raise OSError(err, os.strerror(err)) - def setxattr(self, path, key, value, vlen): - ret = api.glfs_setxattr(self.fs, path, key, value, vlen, 0) + def setxattr(self, path, key, value, flags=0): + """ + Set extended attribute of the path. + + :param path: Path to file or directory. + :param key: The key of extended attribute. + :param value: The valiue of extended attribute. + :param flags: Possible values are 0 (default), 1 and 2 + 0: xattr will be created if it does not exist, or the + value will be replaced if the xattr exists. + 1: Perform a pure create, which fails if the named + attribute already exists. + 2: Perform a pure replace operation, which fails if the + named attribute does not already exist. + """ + ret = api.glfs_setxattr(self.fs, path, key, value, len(value), flags) if ret < 0: err = ctypes.get_errno() - raise IOError(err, os.strerror(err)) + raise OSError(err, os.strerror(err)) def stat(self, path): + """ + Returns stat information of path. + """ s = api.Stat() rc = api.glfs_stat(self.fs, path, ctypes.byref(s)) if rc < 0: @@ -825,8 +975,8 @@ class Volume(object): def statvfs(self, path): """ - To get status information about the file system that contains the file - named by the path argument. + Returns information about a mounted glusterfs volume. path is the + pathname of any file within the mounted filesystem. """ s = api.Statvfs() rc = api.glfs_statvfs(self.fs, path, ctypes.byref(s)) |