/* Unix SMB/CIFS implementation. Wrap VxFS xattr calls. Copyright (C) Veritas Technologies LLC 2016 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "includes.h" #include "smbd/smbd.h" #include "system/filesys.h" #include "string.h" #include "vfs_vxfs.h" /* * Available under GPL at * http://www.veritas.com/community/downloads/vxfsmisc-library */ #define LIBVXFS "/usr/lib64/vxfsmisc.so" static int (*vxfs_setxattr_fd_func) (int fd, const char *name, const void *value, size_t len, int flags); static int (*vxfs_getxattr_fd_func) (int fd, const char *name, void *value, size_t *len); static int (*vxfs_removexattr_fd_func) (int fd, const char *name); static int (*vxfs_listxattr_fd_func) (int fd, void *value, size_t *len); static int (*vxfs_setwxattr_fd_func) (int fd); static int (*vxfs_checkwxattr_fd_func) (int fd); int vxfs_setxattr_fd(int fd, const char *name, const void *value, size_t len, int flags) { int ret = -1; DBG_DEBUG("In vxfs_setxattr_fd fd %d name %s len %zu flags %d\n", fd, name, len, flags); if (vxfs_setxattr_fd_func == NULL) { errno = ENOSYS; return ret; } DBG_DEBUG("Calling vxfs_setxattr_fd\n"); ret = vxfs_setxattr_fd_func(fd, name, value, len, flags); DBG_DEBUG("vxfs_setxattr_fd ret = %d \n", ret); if (ret) { errno = ret; ret = -1; } return ret; } int vxfs_getxattr_fd(int fd, const char *name, void *value, size_t len) { int ret; size_t size = len; DBG_DEBUG("In vxfs_getxattr_fd fd %d name %s len %zu\n", fd, name, len); if (vxfs_getxattr_fd_func == NULL) { errno = ENOSYS; return -1; } DBG_DEBUG("Calling vxfs_getxattr_fd with %s\n", name); ret = vxfs_getxattr_fd_func(fd, name, value, &size); DBG_DEBUG("vxfs_getxattr_fd ret = %d\n", ret); if (ret) { errno = ret; if (ret == EFBIG) { errno = ERANGE; } return -1; } DBG_DEBUG("vxfs_getxattr_fd done with size %zu\n", size); return size; } int vxfs_getxattr_path(const char *path, const char *name, void *value, size_t len) { int ret, fd = -1; DBG_DEBUG("In vxfs_getxattr_path path %s name %s len %zu\n", path, name, len); fd = open(path, O_RDONLY); if (fd == -1) { DBG_DEBUG("file not opened: vxfs_getxattr_path for %s\n", path); return -1; } ret = vxfs_getxattr_fd(fd, name, value, len); close(fd); return ret; } int vxfs_removexattr_fd(int fd, const char *name) { int ret = 0; DBG_DEBUG("In vxfs_removexattr_fd fd %d name %s\n", fd, name); if (vxfs_removexattr_fd_func == NULL) { errno = ENOSYS; return -1; } DBG_DEBUG("Calling vxfs_removexattr_fd with %s\n", name); ret = vxfs_removexattr_fd_func(fd, name); if (ret) { errno = ret; ret = -1; } return ret; } int vxfs_listxattr_fd(int fd, char *list, size_t size) { int ret; size_t len = size; DBG_DEBUG("In vxfs_listxattr_fd fd %d list %s size %zu\n", fd, list, size); if (vxfs_listxattr_fd_func == NULL) { errno = ENOSYS; return -1; } ret = vxfs_listxattr_fd_func(fd, list, &len); DBG_DEBUG("vxfs_listxattr_fd: returned ret = %d\n", ret); DBG_DEBUG("In vxfs_listxattr_fd done with len %zu\n", len); if (ret) { errno = ret; if (ret == EFBIG) { errno = ERANGE; } return -1; } return len; } int vxfs_setwxattr_fd(int fd) { int ret = 0; DBG_DEBUG("In vxfs_setwxattr_fd fd %d\n", fd); if (vxfs_setwxattr_fd_func == NULL) { errno = ENOSYS; return -1; } ret = vxfs_setwxattr_fd_func(fd); DBG_DEBUG("ret = %d\n", ret); if (ret != 0) { errno = ret; ret = -1; } return ret; } int vxfs_setwxattr_path(const char *path, bool is_dir) { int ret, fd = -1; DBG_DEBUG("In vxfs_setwxattr_path path %s is_dir %d\n", path, is_dir); if (is_dir) { fd = open(path, O_RDONLY|O_DIRECTORY); } else { fd = open(path, O_WRONLY); } if (fd == -1) { DBG_DEBUG("file %s not opened, errno:%s\n", path, strerror(errno)); return -1; } ret = vxfs_setwxattr_fd(fd); DBG_DEBUG("ret = %d\n", ret); close(fd); return ret; } int vxfs_checkwxattr_fd(int fd) { int ret; DBG_DEBUG("In vxfs_checkwxattr_fd fd %d\n", fd); if (vxfs_checkwxattr_fd_func == NULL) { errno = ENOSYS; return -1; } ret = vxfs_checkwxattr_fd_func(fd); DBG_DEBUG("ret = %d\n", ret); if (ret != 0) { errno = ret; ret = -1; } return ret; } int vxfs_checkwxattr_path(const char *path) { int ret, fd = -1; DBG_DEBUG("In vxfs_checkwxattr_path path %s\n", path); fd = open(path, O_RDONLY); if (fd == -1) { DBG_DEBUG("file %s not opened, errno:%s\n", path, strerror(errno)); return -1; } ret = vxfs_checkwxattr_fd(fd); close(fd); return ret; } static bool load_lib_vxfs_function(void *lib_handle, void *fn_ptr, const char *fnc_name) { void **vlib_handle = (void **)lib_handle; void **fn_pointer = (void **)fn_ptr; *fn_pointer = dlsym(*vlib_handle, fnc_name); if (*fn_pointer == NULL) { DEBUG(10, ("Cannot find symbol for %s\n", fnc_name)); return true; } return false; } void vxfs_init() { static void *lib_handle = NULL; if (lib_handle != NULL ) { return; } lib_handle = dlopen(LIBVXFS, RTLD_LAZY); if (lib_handle == NULL) { DEBUG(10, ("Cannot get lib handle\n")); return; } DEBUG(10, ("Calling vxfs_init\n")); load_lib_vxfs_function(&lib_handle, &vxfs_setxattr_fd_func, "vxfs_nxattr_set"); load_lib_vxfs_function(&lib_handle, &vxfs_getxattr_fd_func, "vxfs_nxattr_get"); load_lib_vxfs_function(&lib_handle, &vxfs_removexattr_fd_func, "vxfs_nxattr_remove"); load_lib_vxfs_function(&lib_handle, &vxfs_listxattr_fd_func, "vxfs_nxattr_list"); load_lib_vxfs_function(&lib_handle, &vxfs_setwxattr_fd_func, "vxfs_wattr_set"); load_lib_vxfs_function(&lib_handle, &vxfs_checkwxattr_fd_func, "vxfs_wattr_check"); }