📄 fileattach.c
字号:
#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 + -