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

📄 fileattach.c

📁 飞鸽传书的linux源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include <string.h>#include <glib.h>#include <errno.h>#include <time.h>#include "common.h"GList *uploads=NULL;GList *downloads=NULL;GStaticMutex upload_queue_mutex = G_STATIC_MUTEX_INIT;GStaticMutex download_queue_mutex = G_STATIC_MUTEX_INIT;/* utils *//* basic operations */static intcreate_file_info(file_info_t **file_info) {  int rc;  file_info_t *new_info;  if (!file_info)    return -EINVAL;  rc=-ENOMEM;  new_info=g_slice_new(file_info_t);  if (!new_info)    return rc;  memset(new_info,0,sizeof(file_info_t));  new_info->mutex=g_mutex_new();  if (!(new_info->mutex))    goto free_info_out;  *file_info=new_info;  return 0; free_info_out:  dbg_out("Free: %x\n",(unsigned int)new_info);  g_slice_free(file_info_t,new_info);    return rc;}static intdestroy_file_info(file_info_t *file_info) {  GList *entry,*xattr_list;  if (!file_info)    return -EINVAL;  if (!g_mutex_trylock(file_info->mutex))    return -EBUSY;  xattr_list=file_info->xattrs;  for(entry=g_list_first(xattr_list);entry;entry=g_list_next(entry)) {    if (entry->data)       g_free(entry->data);  }  g_list_free(xattr_list);  g_assert(file_info->xattrs==NULL);  g_mutex_unlock(file_info->mutex);  dbg_out("Destroy :%x\n",(unsigned int)file_info);  g_mutex_free (file_info->mutex);  if (file_info->filepath)    g_free(file_info->filepath);  if (file_info->filename)    g_free(file_info->filename);  dbg_out("Free: %x\n",(unsigned int)file_info);  g_slice_free(file_info_t,file_info);  return 0;}static gintcheck_duplicate_attach(gconstpointer a,gconstpointer b){  file_info_t *info_a,*info_b;  if ( (!a) || (!b) )    return -EINVAL;  info_a=(file_info_t *)a;  info_b=(file_info_t *)b;    if ( (!(info_a->filepath)) ||  (!(info_b->filepath)) )        return -EINVAL;  return strcmp(info_a->filepath,info_b->filepath);}static intsetup_file_info(int newid,file_info_t *new_info,const gchar *path){  int rc;  char *filename;  char *fname_sp;  char *new_path;  size_t this_size;  time_t this_mtime;  int    this_type;  if ( (!path) || (!new_info) )    return -EINVAL;  rc=get_file_info(path,&this_size,&this_mtime,&this_type);  if (rc<0)    return rc;  rc=-ENOMEM;  fname_sp=strrchr((const char *)path,'/');  if (fname_sp) {    filename=strdup(fname_sp+1);    if (!(filename))      return rc;  }else{    filename=strdup(path);    if (!(filename))      return rc;  }  new_path=strdup(path);  if (!new_path)    goto free_filename_out;  rc=-EBUSY;  if (!g_mutex_trylock(new_info->mutex)) {    goto free_filepath_out;      }  new_info->fileid=newid;  new_info->filename=filename;  new_info->filepath=new_path;  new_info->size=this_size;  new_info->m_time=this_mtime;  new_info->ipmsg_fattr=this_type;  dbg_out("New attached file:id=%d,name=%s,path=%s,size=0x%x,mtime=%x\n",	  new_info->fileid,	  new_info->filename,	  new_info->filepath,	  new_info->size,	  (unsigned int)new_info->m_time);  g_mutex_unlock(new_info->mutex);  rc=0;  return rc; free_filepath_out:  free(new_path); free_filename_out:  free(filename);  return rc;}/* public */int get_file_info(const gchar *path,size_t *size,time_t *mtime,int *ipmsg_type){  int rc;  int fd;  struct stat stat_buf;  int ftype;  time_t fmtime;  size_t fsize;    if ( (!path) || (!size) || (!mtime) || (!ipmsg_type) )    return -EINVAL;  fd=open(path,O_RDONLY);  if (fd<0)    return -errno;  rc=fstat(fd, &stat_buf);  if (rc<0) {    close(fd);    return -errno;  }  fmtime=stat_buf.st_mtime;  fsize=stat_buf.st_size;  if (S_ISREG(stat_buf.st_mode))     ftype=IPMSG_FILE_REGULAR;  else if (S_ISDIR(stat_buf.st_mode))    ftype=IPMSG_FILE_DIR;  else if (S_ISCHR(stat_buf.st_mode))    ftype=IPMSG_FILE_CDEV;  else if (S_ISFIFO(stat_buf.st_mode))    ftype=IPMSG_FILE_FIFO;  else    ftype=0;  rc=lstat(path, &stat_buf);  if (rc<0) {    close(fd);    return -errno;  }  if (S_ISLNK(stat_buf.st_mode))    ftype=IPMSG_FILE_SYMLINK;  close(fd);  *size=fsize;  *mtime=fmtime;  *ipmsg_type=ftype;    return 0;}int create_attach_file_block(attach_file_block_t **afcb){  int rc;  attach_file_block_t *new_block;  if (!afcb)    return -EINVAL;  rc=-ENOMEM;  new_block=g_slice_new(attach_file_block_t);  if (!new_block)    return rc;  memset(new_block,0,sizeof(attach_file_block_t));  new_block->mutex=g_mutex_new();  if (!(new_block->mutex))    goto free_block_out;  new_block->count=0;  *afcb=new_block;    return 0; free_block_out:  dbg_out("Free: %x\n",(unsigned int)new_block);  g_slice_free(attach_file_block_t,new_block);    return rc;}int set_attch_file_block_pktno(attach_file_block_t *afcb,const long pktno){  if (!afcb)    return -EINVAL;  if (!g_mutex_trylock(afcb->mutex)) {    return -EBUSY;  }  g_mutex_unlock(afcb->mutex);  return 0;}int destroy_attach_file_block(attach_file_block_t **afcb){  int rc;  attach_file_block_t *removed_block;  GList *entry,*file_list;  if ( (!afcb) || (!(*afcb)) )    return -EINVAL;  removed_block=*afcb;  if (!g_mutex_trylock(removed_block->mutex))    return -EBUSY;  if (removed_block->ipaddr) {    g_free(removed_block->ipaddr);    removed_block->ipaddr=NULL;  }  /* files */  file_list=removed_block->files;  for(entry=g_list_first(file_list);entry;entry=g_list_next(entry)) {    if (entry->data) {      file_info_t *file_info;      file_info=entry->data;      rc=destroy_file_info(file_info);      g_assert(rc==0);      entry->data=NULL;    }  }  g_list_free(file_list);  g_mutex_unlock(removed_block->mutex);  /* mutex */  g_mutex_free (removed_block->mutex);  dbg_out("Destroy :%x\n",(unsigned int)removed_block);  dbg_out("Free: %x\n",(unsigned int)removed_block);  g_slice_free(attach_file_block_t,removed_block);  *afcb=NULL;  return 0;}int add_attach_file(attach_file_block_t *afcb,const gchar *path){  int rc;  int new_id;  file_info_t *new_info;  dbg_out("here\n");  if ( (!afcb) || (!path) )    return -EINVAL;  rc=create_file_info(&new_info);  if (rc<0)    return rc;  new_id=afcb->max_id;  rc=setup_file_info(new_id,new_info,path);  if (rc<0)    goto destroy_new_item_out;  rc=-EBUSY;  if (!g_mutex_trylock(afcb->mutex)) {    goto destroy_new_item_out;  }  rc=-EEXIST;  if (g_list_find_custom(afcb->files,new_info,check_duplicate_attach)) {    g_mutex_unlock(afcb->mutex);    dbg_out("Already exist:%s\n",path);    goto destroy_new_item_out;  }  afcb->files=g_list_append(afcb->files,new_info);  ++afcb->max_id;  new_info->main_info_ref=afcb;  g_mutex_unlock(afcb->mutex);  dbg_out("new state:\n");  show_file_list(afcb);  return 0; destroy_new_item_out:  destroy_file_info(new_info);  return rc;}int remove_attach_file(attach_file_block_t *afcb,const gchar *path){  file_info_t check_info;  GList *node;  if ( (!afcb) || (!path) )    return -EINVAL;  memset(&check_info,0,sizeof(file_info_t));  check_info.filepath=(gchar *)path;  node=g_list_find_custom(afcb->files,&check_info,check_duplicate_attach);  if (!node) {    dbg_out("No such file:%s\n",path);    return -ENOENT;  }  if (!g_mutex_trylock(afcb->mutex)) {    return -EBUSY;  }  destroy_file_info(node->data);  afcb->files=g_list_remove(afcb->files,node);  g_mutex_unlock(afcb->mutex);  return 0;}static intcreate_one_file_string(file_info_t *info,const gchar **string){  int rc;  char buff[FILE_ATTCH_ONE_EXT_SIZE];  attach_file_block_t *afcb;  char *new_string;  gchar *ext_file_encoding;  if ( (!info) || (!string) )    return -EINVAL;  if (!g_mutex_trylock(info->mutex)) {    return -EBUSY;  }  afcb=info->main_info_ref;  rc=-EINVAL;  if (!afcb)     goto error_out;  rc=-ENOMEM;  ext_file_encoding=NULL;  convert_string_ipmsg_proto(info->filename,(const gchar **)&ext_file_encoding);  if (!ext_file_encoding)    goto error_out;  memset(buff,0,FILE_ATTCH_ONE_EXT_SIZE);  snprintf(buff,FILE_ATTCH_ONE_EXT_SIZE-2,"%d:%s:%x:%x:%x:%c",	   info->fileid,	   ext_file_encoding,	   (unsigned int)info->size,	   (unsigned int)info->m_time,	   (unsigned int)IPMSG_FILE_REGULAR,FILELIST_SEPARATOR);  buff[FILE_ATTCH_ONE_EXT_SIZE-1]='\0';  dbg_out("attach-file:%s=%s\n",info->filepath,buff);  new_string=strdup(buff);  g_free(ext_file_encoding);  if (!new_string)     goto error_out; /* -ENOMEM */  *string=new_string;  rc=0; error_out:  g_mutex_unlock(info->mutex);  return rc;}int get_attach_file_extention(attach_file_block_t *afcb,const gchar **ext_string){  int rc;  gchar *all_files=NULL;  size_t len,total_len,buff_len;  file_info_t *info;  GList *file_list,*entry;  if ( (!afcb) || (!ext_string) )    return -EINVAL;  all_files=malloc(FATTACH_BUFF_LEN);  if (!all_files)    return -ENOMEM;  memset(all_files,0,FATTACH_BUFF_LEN);  buff_len=FATTACH_BUFF_LEN;  total_len=0;  file_list=afcb->files;  for(entry=g_list_first(file_list);entry;entry=g_list_next(entry)) {    gchar *string;    info=entry->data;    rc=create_one_file_string(info,(const gchar **)&string);    if (rc<0)      goto free_all_files;    len=strlen(string);    while(buff_len <= (total_len+len)) { /* null終端を考慮して=を入れている */      if (internal_extend_memory(&all_files,(buff_len + FATTACH_BUFF_LEN),buff_len,TRUE)){	rc=-ENOMEM;	free(string);	goto free_all_files;      }      buff_len += FATTACH_BUFF_LEN;    }    strncat(all_files,string,len);    dbg_out("New string state:%s(addr:0x%x)\n",	    all_files,	    (unsigned int)all_files);    free(string);    total_len+=len;    all_files[total_len]='\0';  }  len=strlen(all_files);  while ( (len>1) && (all_files[len-1] == FILELIST_SEPARATOR) ) {    all_files[len-1]='\0';    --len;  }  *ext_string=all_files;  dbg_out("attach-file-ext:%s\n",*ext_string);  return 0; free_all_files:  if (all_files)    free(all_files);  return rc;}static gintfind_attach_file_block(gconstpointer a,gconstpointer b){  attach_file_block_t *blk_a,*blk_b;  if ( (!a) || (!b) )    return -EINVAL;  blk_a=(attach_file_block_t *)a;  blk_b=(attach_file_block_t *)b;    return (!(blk_a->pkt_no == blk_b->pkt_no));}intref_attach_file_block(long pktno,const char *ipaddr) {  GList *node;  attach_file_block_t chk_blk;  attach_file_block_t *updated_afcb;  int rc;  if ( (!pktno) || (!ipaddr) )    return -EINVAL;  chk_blk.pkt_no=pktno;    g_static_mutex_lock(&upload_queue_mutex);  rc=-ENOENT;  node=g_list_find_custom(uploads,&chk_blk,find_attach_file_block);  if (!node)    goto unlock_out;  g_assert(node->data);  updated_afcb=node->data;  dbg_out("Ref afcb:%ld %s\n",pktno,ipaddr);  if (!(updated_afcb->ipaddr))    updated_afcb->ipaddr=strdup(ipaddr);  ++(updated_afcb->count);  dbg_out("ref update count:pktno=%ld current count:%d\n",pktno,updated_afcb->count);  rc=0; unlock_out:  g_static_mutex_unlock(&upload_queue_mutex);  if (!rc)    download_monitor_update_state();  return rc;}intunref_attach_file_block(long pktno) {  GList *node;  attach_file_block_t chk_blk;  attach_file_block_t *updated_afcb;  int rc;  chk_blk.pkt_no=pktno;    g_static_mutex_lock(&upload_queue_mutex);  rc=-ENOENT;  node=g_list_find_custom(uploads,&chk_blk,find_attach_file_block);  if (!node)    goto unlock_out;  g_assert(node->data);  updated_afcb=node->data;  /*  強制的なカウントの減算を行う場合は, どこかでカウンタを   *  インクリメントしているはず   */  g_assert (updated_afcb->count>0);   --(updated_afcb->count);  dbg_out("unref update count:pktno=%ld current count:%d\n",pktno,updated_afcb->count); unlock_out:  g_static_mutex_unlock(&upload_queue_mutex);  return rc;}voidshow_file_list(attach_file_block_t *afcb) {  GList *file_list,*node;  g_assert(afcb);  g_mutex_lock(afcb->mutex);  file_list=afcb->files;  for(node=g_list_first (file_list);node;node=g_list_next(node)) {    file_info_t *info;    if (node) {      info=node->data;      if (info) {	g_mutex_lock(info->mutex);	dbg_out("\t owner:0x%x id:%d type:%d path:%s filename:%s size:%d(0x%x) mtime:%s(0x%x)\n",		(unsigned int)info->main_info_ref,		info->fileid,		info->ipmsg_fattr,		info->filepath,		info->filename,		info->size,		info->size,		ctime(&(info->m_time)),		(unsigned int)info->m_time);	g_mutex_unlock(info->mutex);      }    }  }    g_mutex_unlock(afcb->mutex);}voidshow_upload_queue(void) {  GList *node;  int count=0;  attach_file_block_t *blk;  g_static_mutex_lock(&upload_queue_mutex);  for(node=g_list_first (uploads);node;node=g_list_next(node),++count) {    blk=node->data;    if (blk)      dbg_out("%d: pktno:%ld\n",count,blk->pkt_no);    else      g_assert_not_reached();  }  g_static_mutex_unlock(&upload_queue_mutex);}intadd_upload_queue(long pktno,attach_file_block_t *afcb) {  if (!afcb)    return -EINVAL;  afcb->pkt_no=pktno;  g_static_mutex_lock(&upload_queue_mutex);  uploads=g_list_append(uploads,afcb);  g_static_mutex_unlock(&upload_queue_mutex);  show_upload_queue();

⌨️ 快捷键说明

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