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

📄 trash.c

📁 分布式文件系统
💻 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#include "glusterfs.h"#include "logging.h"#include "dict.h"#include "xlator.h"#include "defaults.h"#include <libgen.h>struct trash_struct {  inode_t *inode;  char origpath[4096];  char newpath[4096];  char oldpath[4096]; // used only in case of rename};typedef struct trash_struct trash_local_t;struct trash_priv {  char trash_dir[4096];};typedef struct trash_priv trash_private_t;int32_t trash_unlink_rename_cbk (call_frame_t *frame,			 void *cookie,			 xlator_t *this,			 int32_t op_ret,			 int32_t op_errno,			 struct stat *buf);int32_t trash_rename_rename_cbk (call_frame_t *frame,			 void *cookie,			 xlator_t *this,			 int32_t op_ret,			 int32_t op_errno,			 struct stat *buf);/** * trash_common_unwind_cbk -  */int32_t trash_common_unwind_cbk (call_frame_t *frame,			 void *cookie,			 xlator_t *this,			 int32_t op_ret,			 int32_t op_errno){  STACK_UNWIND (frame, op_ret, op_errno);  return 0;}/** * trash_common_unwind_buf_cbk -  */int32_t trash_common_unwind_buf_cbk (call_frame_t *frame,			     void *cookie,			     xlator_t *this,			     int32_t op_ret,			     int32_t op_errno,			     struct stat *buf){  STACK_UNWIND (frame, op_ret, op_errno, buf);  return 0;}int32_t trash_mkdir_bg_cbk (call_frame_t *frame,		    void *cookie,		    xlator_t *this,		    int32_t op_ret,		    int32_t op_errno,		    inode_t *inode,		    struct stat *stbuf){  STACK_DESTROY (frame->root);  return 0;}int32_t trash_mkdir_cbk (call_frame_t *frame,		 void *cookie,		 xlator_t *this,		 int32_t op_ret,		 int32_t op_errno,		 inode_t *inode,		 struct stat *stbuf){  trash_local_t *local = frame->local;  char *tmp_str = strdup (local->newpath);  if (op_ret == -1 && op_errno == ENOENT) {    int32_t count = 0;    char *tmp_path = NULL;    char *tmp_dirname = strchr (tmp_str, '/');        while (tmp_dirname) {      count = tmp_dirname - tmp_str;      if (count == 0)	count = 1;      tmp_path = calloc (1, count + 1);      memcpy (tmp_path, local->newpath, count);      loc_t tmp_loc = {	.inode = NULL,	.path = tmp_path,      };            /* TODO: create the directory with proper permissions */      STACK_WIND_COOKIE (frame,		   trash_mkdir_cbk,		   tmp_path,		   this->children->xlator,		   this->children->xlator->fops->mkdir,		   &tmp_loc,		   0777);      tmp_dirname = strchr (tmp_str + count + 1, '/');    }    free (cookie);    free (tmp_str);    return 0;  }  char *dir_name = dirname (tmp_str);  if (strcmp((char*)cookie, dir_name) == 0) {    loc_t loc = {      .inode = NULL,      .path = local->origpath,    };    loc_t new_loc = {      .inode = NULL,      .path = local->newpath    };    STACK_WIND (frame,		trash_unlink_rename_cbk,		this->children->xlator,		this->children->xlator->fops->rename,		&loc,		&new_loc);      }  free (cookie); /* strdup (dir_name) was sent here :) */  free (tmp_str);  return 0;}/** * trash_unlink_rename_cbk -  */int32_t trash_unlink_rename_cbk (call_frame_t *frame,			 void *cookie,			 xlator_t *this,			 int32_t op_ret,			 int32_t op_errno,			 struct stat *buf){  trash_local_t *local = frame->local;  if (op_ret == -1 && op_errno == ENOENT) {    /* check for the errno, if its ENOENT create directory and call      * rename later      */    char *tmp_str = strdup (local->newpath);    char *dir_name = dirname (tmp_str);    loc_t tmp_loc = {      .inode = NULL,      .path = dir_name,    };    /* TODO: create the directory with proper permissions */    STACK_WIND_COOKIE (frame,		 trash_mkdir_cbk,		 strdup (dir_name),		 this->children->xlator,		 this->children->xlator->fops->mkdir,		 &tmp_loc,		 0777);    free (tmp_str);  } else if (op_ret == -1 && op_errno == ENOTDIR) {    gf_log (this->name, 	    GF_LOG_WARNING, 	    "Target exists, cannot keep the copy, deleting");    loc_t tmp_loc = {      .inode = local->inode,      .path = local->origpath,    };    STACK_WIND (frame,		trash_common_unwind_cbk,		this->children->xlator,		this->children->xlator->fops->unlink,		&tmp_loc);  } else if (op_ret == -1 && op_errno == EISDIR) {    gf_log (this->name, 	    GF_LOG_WARNING, 	    "Target exists as a directory, cannot keep the copy, deleting");    loc_t tmp_loc = {      .inode = local->inode,      .path = local->origpath,      .ino = local->inode->ino    };    STACK_WIND (frame,		trash_common_unwind_cbk,		this->children->xlator,		this->children->xlator->fops->unlink,		&tmp_loc);  } else {    /* */    STACK_UNWIND (frame, 0, op_errno);  }    return 0;}/** * trash_unlink -  */int32_ttrash_unlink (call_frame_t *frame,	      xlator_t *this,	      loc_t *loc){  trash_private_t *priv = this->private;  if (strncmp (loc->path, priv->trash_dir, strlen(priv->trash_dir)) == 0) {    /* Trying to rename from the trash can dir, do the actual unlink */    STACK_WIND (frame,		trash_common_unwind_cbk,		this->children->xlator,		this->children->xlator->fops->unlink,		loc);  } else {    trash_local_t *local = calloc (1, sizeof (trash_local_t));    if (!local) {      STACK_UNWIND (frame, -1, ENOMEM);      return 0;    }    frame->local = local;    local->inode = loc->inode;    strcpy (local->origpath, loc->path);    strcpy (local->newpath, priv->trash_dir);    strcat (local->newpath, loc->path);    {      loc_t new_loc = {	.inode = NULL,	.ino = 0,	.path = local->newpath      };      STACK_WIND (frame,		  trash_unlink_rename_cbk,		  this->children->xlator,		  this->children->xlator->fops->rename,		  loc,		  &new_loc);    }  }  return 0;}/* */int32_t trash_rename_mkdir_cbk (call_frame_t *frame,			void *cookie,			xlator_t *this,			int32_t op_ret,			int32_t op_errno,			inode_t *inode,			struct stat *stbuf){  trash_local_t *local = frame->local;  char *tmp_str = strdup (local->newpath);  if (op_ret == -1 && op_errno == ENOENT) {    int32_t count = 0;    char *tmp_path = NULL;    char *tmp_dirname = strchr (tmp_str, '/');        while (tmp_dirname) {      count = tmp_dirname - tmp_str;      if (count == 0)	count = 1;      tmp_path = calloc (1, count + 1);      memcpy (tmp_path, local->newpath, count);      loc_t tmp_loc = {	.inode = NULL,	.path = tmp_path,      };            /* TODO: create the directory with proper permissions */      STACK_WIND_COOKIE (frame,		   trash_rename_mkdir_cbk,		   tmp_path,		   this->children->xlator,		   this->children->xlator->fops->mkdir,		   &tmp_loc,		   0777);      tmp_dirname = strchr (tmp_str + count + 1, '/');    }    free (cookie);    free (tmp_str);    return 0;  }  char *dir_name = dirname (tmp_str);  if (strcmp((char*)cookie, dir_name) == 0) {    loc_t loc = {      .inode = NULL,      .path = local->origpath,    };    loc_t new_loc = {      .inode = NULL,      .path = local->newpath    };    STACK_WIND (frame,		trash_rename_rename_cbk,		this->children->xlator,		this->children->xlator->fops->rename,		&loc,		&new_loc);      }  free (cookie); /* strdup (dir_name) was sent here :) */  free (tmp_str);  return 0;}/** * trash_unlink_rename_cbk -  */int32_t trash_rename_rename_cbk (call_frame_t *frame,			 void *cookie,			 xlator_t *this,			 int32_t op_ret,			 int32_t op_errno,			 struct stat *buf){  trash_local_t *local = frame->local;  if (op_ret == -1 && op_errno == ENOENT) {    /* check for the errno, if its ENOENT create directory and call      * rename later      */    char *tmp_str = strdup (local->newpath);    char *dir_name = dirname (tmp_str);    loc_t tmp_loc = {      .inode = NULL,      .path = dir_name,    };    /* TODO: create the directory with proper permissions */    STACK_WIND_COOKIE (frame,		 trash_rename_mkdir_cbk,		 strdup (dir_name),		 this->children->xlator,		 this->children->xlator->fops->mkdir,		 &tmp_loc,		 0777);    free (tmp_str);    return 0;  } else if (op_ret == -1 && op_errno == ENOTDIR) {    gf_log (this->name, 	    GF_LOG_WARNING, 	    "Target exists, cannot keep the dest entry %s, renaming",	    local->origpath);  } else if (op_ret == -1 && op_errno == EISDIR) {    gf_log (this->name, 	    GF_LOG_WARNING, 	    "Target exists as a directory, cannot keep the copy %s, renaming",	    local->origpath);  }  loc_t tmp_loc = {    .inode = local->inode,    .path = local->oldpath,  };  loc_t new_loc = {    .inode = NULL,    .path = local->origpath  };  STACK_WIND (frame,	      trash_common_unwind_buf_cbk,	      this->children->xlator,	      this->children->xlator->fops->rename,	      &tmp_loc,	      &new_loc);    return 0;}/** * trash_rename_lookup_cbk -  */int32_t trash_rename_lookup_cbk (call_frame_t *frame,			 void *cookie,			 xlator_t *this,			 int32_t op_ret,			 int32_t op_errno,			 inode_t *inode,			 struct stat *buf,			 dict_t *xattr){  trash_local_t *local = frame->local;  if (op_ret == -1) {    loc_t oldloc = {      .inode = local->inode,      .path = local->oldpath    };    loc_t newloc = {      .inode = NULL,      .path = local->origpath    };    STACK_WIND (frame,		trash_common_unwind_buf_cbk,		this->children->xlator,		this->children->xlator->fops->rename,		&oldloc,		&newloc);    return 0;  }  loc_t oldloc = {    .inode = inode,    .path = local->origpath  };  loc_t newloc = {    .inode = NULL,    .path = local->newpath  };  STACK_WIND (frame,	      trash_rename_rename_cbk,	      this->children->xlator,	      this->children->xlator->fops->rename,	      &oldloc,	      &newloc);  return 0;}/** * trash_rename -  */int32_t trash_rename (call_frame_t *frame,	      xlator_t *this,	      loc_t *oldloc,	      loc_t *newloc){  trash_private_t *priv = this->private;    if (strncmp (oldloc->path, priv->trash_dir, strlen(priv->trash_dir)) == 0) {    /* Trying to rename from the trash can dir, do the actual rename */    STACK_WIND (frame,		trash_common_unwind_buf_cbk,		this->children->xlator,		this->children->xlator->fops->rename,		oldloc,		newloc);  } else {    /* Trying to rename a regular file from GlusterFS */    trash_local_t *local = calloc (1, sizeof (trash_local_t));    if (!local) {      STACK_UNWIND (frame, -1, ENOMEM, NULL);      return 0;    }    frame->local = local;    local->inode = oldloc->inode;    strcpy (local->newpath, priv->trash_dir);    strcat (local->newpath, newloc->path);    strcpy (local->origpath, newloc->path);    strcpy (local->oldpath, oldloc->path);        /* Send a lookup call on newloc, to ensure we are not overwriting */    STACK_WIND (frame,		trash_rename_lookup_cbk,		this->children->xlator,		this->children->xlator->fops->lookup,		newloc,		0);  }  return 0;}int32_tnotify (xlator_t *this,        int32_t event,        void *data,        ...){  trash_private_t *priv = this->private;  switch (event)     {    case GF_EVENT_CHILD_UP:      {	/* mkdir (priv->trash_dir); */	call_ctx_t *cctx;	call_pool_t *pool = this->ctx->pool;	cctx = calloc (1, sizeof (*cctx));	cctx->frames.root  = cctx;	cctx->frames.this  = this;	cctx->pool = pool;	LOCK (&pool->lock);	{	  list_add (&cctx->all_frames, &pool->all_frames);	}	UNLOCK (&pool->lock);	{	  loc_t tmp_loc = {	    .ino = 0,	    .inode = NULL,	    .path = priv->trash_dir	  };	  /* TODO: create the directory with proper permissions */	  STACK_WIND ((&cctx->frames),		      trash_mkdir_bg_cbk,		      this->children->xlator,		      this->children->xlator->fops->mkdir,		      &tmp_loc,		      0777); 	}      }    }  default_notify (this, event, data);  return 0;}/** * trash_init - */int32_t init (xlator_t *this){  data_t *trash_dir = NULL;  trash_private_t *_priv = NULL;  /* Create .trashcan directory in init */  if (!this->children || this->children->next) {    gf_log (this->name,	    GF_LOG_ERROR,	    "Not configured with exactly one child. exiting",	    this->name);    return -1;  }  _priv = calloc (1, sizeof (*_priv));      trash_dir = dict_get (this->options, "trash-dir");  if (!trash_dir) {    gf_log (this->name, 	    GF_LOG_WARNING,	    "No option specified for trash-dir, using \"/.trash/\"");    strcpy (_priv->trash_dir, "/.trashcan");  } else {    /* Need a path with '/' as the first char, if not given, append it */    if (trash_dir->data[0] == '/') {      strcpy (_priv->trash_dir, trash_dir->data);    } else {      strcpy (_priv->trash_dir, "/");      strcat (_priv->trash_dir, trash_dir->data);    }  }  this->private = (void *)_priv;  return 0;}voidfini (xlator_t *this){  trash_private_t *priv = this->private;  free (priv);  return;}struct xlator_fops fops = {  .unlink = trash_unlink,  .rename = trash_rename,};struct xlator_mops mops = {};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -