⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 posix.c

📁 分布式文件系统
💻 C
📖 第 1 页 / 共 4 页
字号:
/*   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 + -