📄 posix.c
字号:
/* Copyright (c) 2006, 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.com> This file is part of GlusterFS. GlusterFS 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. GlusterFS 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 <http://www.gnu.org/licenses/>.*/#ifndef _CONFIG_H#define _CONFIG_H#include "config.h"#endif#define __XOPEN_SOURCE 500#include <stdint.h>#include <sys/time.h>#include <errno.h>#include <ftw.h>#ifndef GF_BSD_HOST_OS#include <alloca.h>#endif#include <sys/resource.h>#include "glusterfs.h"#include "dict.h"#include "logging.h"#include "posix.h"#include "xlator.h"#include "lock.h"#include "defaults.h"#include "common-utils.h"#undef HAVE_SET_FSID#ifdef HAVE_SET_FSID#define DECLARE_OLD_FS_UID_VAR int32_t old_fsuid /*, old_fsgid */#define SET_FS_UID(uid, gid) do { \ old_fsuid = setfsuid (uid); \} while (0)#define SET_TO_OLD_FS_UID() do { \ setfsuid (old_fsuid); \ /* setfsgid (old_fsgid); */ \} while (0);#else#define DECLARE_OLD_FS_UID_VAR#define SET_FS_UID(uid, gid)#define SET_TO_OLD_FS_UID()#endif#define MAKE_REAL_PATH(var, this, path) do { \ int base_len = ((struct posix_private *)this->private)->base_path_length; \ var = alloca (strlen (path) + base_len + 2); \ strcpy (var, ((struct posix_private *)this->private)->base_path); \ strcpy (&var[base_len], path); \} while (0)int32_tposix_lookup (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t need_xattr){ struct stat buf = {0, }; char *real_path; int32_t op_ret; int32_t op_errno; dict_t *xattr = NULL; char version[50], ctime[50]; /* do #define the size */ MAKE_REAL_PATH (real_path, this, loc->path); op_ret = lstat (real_path, &buf); op_errno = errno; if (op_ret == -1 && op_errno != ENOENT) { gf_log (this->name, GF_LOG_WARNING, "lstat on %s: %s", loc->path, strerror (op_errno)); } if (need_xattr) { xattr = get_new_dict(); int32_t size = lgetxattr (real_path, GLUSTERFS_VERSION, version, 50); /* should size be put into the data_t ? */ if (size != -1) { version[size] = '\0'; dict_set (xattr, GLUSTERFS_VERSION, data_from_uint32 (strtoll(version, NULL, 10))); } size = lgetxattr (real_path, GLUSTERFS_CREATETIME, ctime, 50); if (size != -1) { ctime[size] = '\0'; dict_set (xattr, GLUSTERFS_CREATETIME, data_from_uint32 (strtoll(ctime, NULL, 10))); } } frame->root->rsp_refs = NULL; if (xattr) dict_ref (xattr); STACK_UNWIND (frame, op_ret, op_errno, loc->inode, &buf, xattr); if (xattr) dict_unref (xattr); return 0;}int32_tposix_forget (call_frame_t *frame, xlator_t *this, inode_t *inode){ if (dict_get (inode->ctx, this->name)) { int32_t _fd = data_to_int32 (dict_get (inode->ctx, this->name)); close (_fd); } return 0;}int32_tposix_stat (call_frame_t *frame, xlator_t *this, loc_t *loc){ struct stat buf; char *real_path; int32_t op_ret; int32_t op_errno; DECLARE_OLD_FS_UID_VAR; MAKE_REAL_PATH (real_path, this, loc->path); SET_FS_UID (frame->root->uid, frame->root->gid); op_ret = lstat (real_path, &buf); op_errno = errno; if (op_ret == -1) { gf_log (this->name, GF_LOG_WARNING, "lstat on %s: %s", loc->path, strerror (op_errno)); } SET_TO_OLD_FS_UID(); frame->root->rsp_refs = NULL; STACK_UNWIND (frame, op_ret, op_errno, &buf); return 0;}int32_t posix_opendir (call_frame_t *frame, xlator_t *this, loc_t *loc, fd_t *fd){ char *real_path; int32_t op_ret; int32_t op_errno; DIR *dir; DECLARE_OLD_FS_UID_VAR; MAKE_REAL_PATH (real_path, this, loc->path); SET_FS_UID (frame->root->uid, frame->root->gid); dir = opendir (real_path); op_errno = errno; op_ret = (dir == NULL) ? -1 : dirfd (dir); if (op_ret == -1) { gf_log (this->name, GF_LOG_WARNING, "opendir on %s: %s", loc->path, strerror (op_errno)); } SET_TO_OLD_FS_UID (); if (dir) { struct posix_fd *pfd = calloc (1, sizeof (*fd)); if (!pfd) { closedir (dir); STACK_UNWIND (frame, -1, ENOMEM, NULL); } pfd->dir = dir; pfd->fd = dirfd (dir); pfd->path = strdup (real_path); dict_set (fd->ctx, this->name, data_from_static_ptr (pfd)); } frame->root->rsp_refs = NULL; STACK_UNWIND (frame, op_ret, op_errno, fd); return 0;}int32_tposix_getdents (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, off_t off, int32_t flag){ int32_t op_ret; int32_t op_errno; char *real_path; dir_entry_t entries = {0, }; dir_entry_t *tmp; DIR *dir; struct dirent *dirent; int real_path_len; int entry_path_len; char *entry_path; int count = 0; data_t *pfd_data = NULL; struct posix_fd *pfd; DECLARE_OLD_FS_UID_VAR ; if (fd && fd->ctx) { pfd_data = dict_get (fd->ctx, this->name); if (!pfd_data) { frame->root->rsp_refs = NULL; gf_log (this->name, GF_LOG_ERROR, "fd %p does not have context in %s", fd, this->name); STACK_UNWIND (frame, -1, EBADFD, &entries, 0); return 0; } } else { gf_log (this->name, GF_LOG_ERROR, "fd or fd->ctx is NULL (fd=%p)", fd); frame->root->rsp_refs = NULL; STACK_UNWIND (frame, -1, EBADFD, &entries, 0); return 0; } pfd = data_to_ptr (pfd_data); if (!pfd) { gf_log (this->name, GF_LOG_ERROR, "pfd from fd->ctx for %s is NULL", fd); STACK_UNWIND (frame, -1, EBADFD, NULL, 0); return 0; } if (!pfd->path) { gf_log (this->name, GF_LOG_ERROR, "pfd does not have path set (possibly file fd, fd=%p)", fd); STACK_UNWIND (frame, -1, EBADFD, NULL, 0); return 0; } real_path = pfd->path; real_path_len = strlen (real_path); entry_path_len = real_path_len + 1024; entry_path = calloc (1, entry_path_len); strcpy (entry_path, real_path); entry_path[real_path_len] = '/'; SET_FS_UID (frame->root->uid, frame->root->gid); dir = pfd->dir; if (!dir) { gf_log (this->name, GF_LOG_ERROR, "pfd does not have dir set (possibly file fd, fd=%p, path=`%s'", fd, real_path); SET_TO_OLD_FS_UID (); frame->root->rsp_refs = NULL; STACK_UNWIND (frame, -1, errno, &entries, 0); freee (entry_path); return 0; } else { op_ret = 0; op_errno = 0; } // seekdir (dir, 0); /* TODO: check for all the type of flag, and behave appropriately */ while ((dirent = readdir (dir))) { if (!dirent) break; /* This helps in self-heal, when only directories needs to be replicated */ /* This is to reduce the network traffic, in case only directory is needed from posix */ struct stat buf; int ret = -1; char tmp_real_path[4096]; strcpy(tmp_real_path, real_path); strcat (tmp_real_path, "/"); strcat(tmp_real_path, dirent->d_name); ret = lstat (tmp_real_path, &buf); if ((flag == GF_GET_DIR_ONLY) && (ret != -1 && !S_ISDIR(buf.st_mode))) { continue; } tmp = calloc (1, sizeof (*tmp)); tmp->name = strdup (dirent->d_name); if (entry_path_len < real_path_len + 1 + strlen (tmp->name) + 1) { entry_path_len = real_path_len + strlen (tmp->name) + 1024; entry_path = realloc (entry_path, entry_path_len); } strcpy (&entry_path[real_path_len+1], tmp->name); lstat (entry_path, &tmp->buf); if (S_ISLNK(tmp->buf.st_mode)) { char linkpath[PATH_MAX]; ret = readlink (entry_path, linkpath, PATH_MAX); if (ret != -1) { linkpath[ret] = '\0'; tmp->link = strdup (linkpath); } } else { tmp->link = ""; } count++; tmp->next = entries.next; entries.next = tmp; /* if size is 0, count can never be = size, so entire dir is read */ if (count == size) break; } freee (entry_path); SET_TO_OLD_FS_UID (); frame->root->rsp_refs = NULL; STACK_UNWIND (frame, op_ret, op_errno, &entries, count); while (entries.next) { tmp = entries.next; entries.next = entries.next->next; freee (tmp->name); freee (tmp); } return 0;}int32_t posix_closedir (call_frame_t *frame, xlator_t *this, fd_t *fd){ int32_t op_ret; int32_t op_errno; data_t *pfd_data; struct posix_fd *pfd; op_ret = 0; op_errno = errno; frame->root->rsp_refs = NULL; if (!fd) { gf_log (this->name, GF_LOG_ERROR, "fd is NULL"); STACK_UNWIND (frame, -1, EINVAL); return 0; } if (!fd->ctx) { gf_log (this->name, GF_LOG_ERROR, "fd->ctx is NULL for fd=%p", fd); STACK_UNWIND (frame, -1, EINVAL); return 0; } pfd_data = dict_get (fd->ctx, this->name); if (!pfd_data) { gf_log (this->name, GF_LOG_ERROR, "pfd_data from fd=%p is NULL", fd); STACK_UNWIND (frame, -1, EINVAL); return 0; } pfd = data_to_ptr (pfd_data); if (!pfd) { gf_log (this->name, GF_LOG_ERROR, "pfd is NULL from fd=%p", fd); STACK_UNWIND (frame, -1, EINVAL); return 0; } if (pfd->dir) { closedir (pfd->dir); pfd->dir = NULL; } else { gf_log (this->name, GF_LOG_ERROR, "pfd->dir is NULL for fd=%p path=%s", fd, pfd->path ? pfd->path : "<NULL>"); } if (pfd->path) { free (pfd->path); } else { gf_log (this->name, GF_LOG_ERROR, "pfd->path was NULL. fd=%p pfd=%p", fd, pfd); } dict_del (fd->ctx, this->name); free (pfd); STACK_UNWIND (frame, op_ret, op_errno); return 0;}int32_t posix_readlink (call_frame_t *frame, xlator_t *this, loc_t *loc, size_t size){ char *dest = alloca (size + 1); int32_t op_ret; int32_t op_errno; char *real_path; DECLARE_OLD_FS_UID_VAR; MAKE_REAL_PATH (real_path, this, loc->path); SET_FS_UID (frame->root->uid, frame->root->gid); op_ret = readlink (real_path, dest, size); if (op_ret > 0) dest[op_ret] = 0; op_errno = errno; if (op_ret == -1) { gf_log (this->name, GF_LOG_WARNING, "readlink on %s: %s", loc->path, strerror (op_errno)); } SET_TO_OLD_FS_UID (); frame->root->rsp_refs = NULL; STACK_UNWIND (frame, op_ret, op_errno, dest); return 0;}int32_t posix_mknod (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, dev_t dev){ int32_t op_ret; int32_t op_errno; char *real_path; struct stat stbuf = { 0, }; DECLARE_OLD_FS_UID_VAR; MAKE_REAL_PATH (real_path, this, loc->path); SET_FS_UID (frame->root->uid, frame->root->gid); op_ret = mknod (real_path, mode, dev); op_errno = errno; if (op_ret == -1) { gf_log (this->name, GF_LOG_WARNING, "mknod on %s: %s", loc->path, strerror (op_errno)); } if (op_ret == 0) {#ifndef HAVE_SET_FSID lchown (real_path, frame->root->uid, frame->root->gid);#endif lstat (real_path, &stbuf); } SET_TO_OLD_FS_UID (); frame->root->rsp_refs = NULL; STACK_UNWIND (frame, op_ret, op_errno, loc->inode, &stbuf); return 0;}int32_t posix_mkdir (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode){ int32_t op_ret; int32_t op_errno; char *real_path; struct stat stbuf = {0, }; DECLARE_OLD_FS_UID_VAR; MAKE_REAL_PATH (real_path, this, loc->path); SET_FS_UID (frame->root->uid, frame->root->gid); op_ret = mkdir (real_path, mode); op_errno = errno; if (op_ret == -1) { gf_log (this->name, GF_LOG_WARNING, "mkdir of %s: %s", loc->path, strerror (op_errno)); } if (op_ret == 0) {#ifndef HAVE_SET_FSID chown (real_path, frame->root->uid, frame->root->gid);#endif lstat (real_path, &stbuf); } SET_TO_OLD_FS_UID (); frame->root->rsp_refs = NULL; STACK_UNWIND (frame, op_ret, op_errno, loc->inode, &stbuf); return 0;}int32_t posix_unlink (call_frame_t *frame, xlator_t *this, loc_t *loc){ int32_t op_ret; int32_t op_errno; char *real_path; DECLARE_OLD_FS_UID_VAR; MAKE_REAL_PATH (real_path, this, loc->path); /* _fd = open (real_path, O_RDWR); */ SET_FS_UID (frame->root->uid, frame->root->gid); op_ret = unlink (real_path); op_errno = errno; if (op_ret == -1) { gf_log (this->name, GF_LOG_WARNING, "unlink of %s: %s", loc->path, strerror (op_errno)); } SET_TO_OLD_FS_UID (); /* if (op_ret == -1) { close (_fd); } else { dict_set (loc->inode->ctx, this->name, data_from_int32 (_fd)); } */ frame->root->rsp_refs = NULL; STACK_UNWIND (frame, op_ret, op_errno); return 0;}int32_t posix_remove (const char *path, const struct stat *stat, int32_t typeflag, struct FTW *ftw){ return remove (path);}int32_tposix_rmelem (call_frame_t *frame, xlator_t *this, const char *path){ int32_t op_ret, op_errno; char *real_path; MAKE_REAL_PATH (real_path, this, path); op_ret = nftw (real_path, posix_remove, 20, FTW_DEPTH|FTW_PHYS); op_errno = errno; if (op_ret == -1) { gf_log (this->name, GF_LOG_WARNING, "nftw on %s: %s", path, strerror (op_errno)); } /* FTW_DEPTH = traverse subdirs first before calling posix_remove * on real_path * FTW_PHYS = do not follow symlinks */ frame->root->rsp_refs = NULL; STACK_UNWIND (frame, op_ret, op_errno); return 0;}int32_t posix_rmdir (call_frame_t *frame, xlator_t *this, loc_t *loc){ int32_t op_ret; int32_t op_errno;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -