?? downloads.c
字號:
/* * Copyright (C) 2006 Takeharu KATO * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#ifdef HAVE_CONFIG_H# include <config.h>#endif#include <gnome.h>#include <glib.h>#include <gconf/gconf-client.h>#include "callbacks.h"#include "interface.h"#include "support.h"#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <stdio.h>#include <sys/socket.h>#include <netinet/in.h>#include <sys/time.h>#include <errno.h>#include <libgnomevfs/gnome-vfs.h>#include <libgnomevfs/gnome-vfs-utils.h>#include <libgnomevfs/gnome-vfs-mime-handlers.h>#include "common.h"/* static */static intrelease_dir_info_contents(dir_request_t *info){ if (info->filename) g_free(info->filename); return 0;}static intparse_dir_request(const char *message,dir_request_t *ret,size_t max_len){ int rc; char *buff; char *token; long int_val; char *sp=NULL; char *ep=NULL; char *basename; char *filename; ssize_t remains; if ( (!message) || (!ret) || (!max_len) ) return -EINVAL; buff=g_malloc(max_len+1); /* 最終パケットは\0終端されていないことに注意 */ if (!buff) return -ENOMEM; memset(ret,0,sizeof(dir_request_t)); /* 念のため */ memcpy(buff,message,max_len); buff[max_len]='\0'; dbg_out("buff(len:%d):%s\n",strlen(buff),buff); remains=max_len; /*書式: header-size:filename:file-size:fileattr:*/ /* * ヘッダサイズ */ sp=buff; ep=memchr(sp, ':', remains); if (!ep) { rc=-EINVAL; goto error_out; } *ep='\0'; remains =max_len - ((unsigned long)ep-(unsigned long)buff); if (remains<=0) { rc=-EINVAL; goto error_out; } ++ep; int_val=strtol(sp, (char **)NULL, 16); ret->header_size=int_val; dbg_out("header size:%d(%x)\n",ret->header_size,ret->header_size); sp=ep; /* * ファイル名 */ ep=memchr(sp, ':', remains); if (!ep) { rc=-EINVAL; goto error_out; } *ep='\0'; remains =max_len - ((unsigned long)ep-(unsigned long)buff); if (remains<=0) { rc=-EINVAL; goto error_out; } ++ep; rc=-ENOMEM; basename=g_path_get_basename(sp); if (!basename) goto error_out; rc=convert_string_internal(basename,(const gchar **)&filename); if (rc<0) { err_out("Can not convert this request:%s\n",sp); err_out("Can not convert file name:%s\n",basename); g_free(basename); goto error_out; } g_free(basename); ret->filename=filename; dbg_out("filename:%s\n",ret->filename); sp=ep; /* * ファイルサイズ */ ep=memchr(sp, ':', remains); if (!ep) { rc=-EINVAL; goto error_out; } *ep='\0'; remains =max_len - ((unsigned long)ep-(unsigned long)buff); if (remains<=0) { rc=-EINVAL; goto error_out; } ++ep; int_val=strtol(sp, (char **)NULL, 16); ret->file_size=int_val; dbg_out("file size:%d(%x)\n",ret->file_size,ret->file_size); sp=ep; /* * ファイル種別 */ ep=memchr(sp, ':', remains); if (!ep) { rc=-EINVAL; goto error_out; } *ep='\0'; remains =max_len - ((unsigned long)ep-(unsigned long)buff); if (remains<=0) { rc=-EINVAL; goto error_out; } ++ep; int_val=strtol(sp, (char **)NULL, 16); ret->ipmsg_fattr=int_val; dbg_out("ipmsg file attr:%d(%x)\n",ret->ipmsg_fattr,ret->ipmsg_fattr); sp=ep; if (download_base_cmd(ret->ipmsg_fattr) != IPMSG_FILE_RETPARENT) { rc=-EPERM; if (!strcmp(G_DIR_SEPARATOR_S,basename)) { g_free(basename); goto error_out; } if (!strcmp(basename,"..")){ g_free(basename); /* 上位への移動は禁止 */ goto error_out; } if (!strcmp(basename,".")){ g_free(basename); /* コマンド以外でのカレントへの移動は禁止 */ goto error_out; } } rc=0; error_out: g_free(buff); return rc;}static intemulate_chdir(const char *current_dir,char *subdir,char **new_dir){ int rc; char *buff; gchar *dir_uri; GnomeVFSResult result; if ( (!current_dir) || (!subdir) || (!new_dir) ) return -EINVAL; if (!strcmp(subdir,"..")) return -EINVAL; /* コマンド以外で上位には移動しない */ if (!strcmp(subdir,".")) return -EINVAL; /* コマンド以外でカレントには移動しない */ if (!g_path_is_absolute(current_dir)) return -EINVAL; buff=g_build_filename(current_dir,subdir,NULL); if (!buff) return -ENOMEM; rc=-ENOMEM; dir_uri=gnome_vfs_get_uri_from_local_path(buff); if (!dir_uri) goto error_out; result=gnome_vfs_make_directory(dir_uri,GNOME_VFS_PERM_USER_ALL); if ( (result != GNOME_VFS_OK) && (result != GNOME_VFS_ERROR_FILE_EXISTS) ) { err_out("Can not create directory:%s\n",gnome_vfs_result_to_string(result)); rc=-result; goto error_out; } if ( (result == GNOME_VFS_ERROR_FILE_EXISTS) && (download_overwrite_confirm_generic(buff)) ) { rc=-result; goto error_out; } *new_dir=buff; return 0; error_out: g_free(buff); return rc;}static intcreate_parent_dir(const char *current_dir,char **parent){ int rc; char *buff; char *new_dir; gchar *ep; if ( (!current_dir) || (!parent) ) return -EINVAL; buff=g_strdup(current_dir); if (!buff) return -ENOMEM; rc=-ENOENT; ep=g_strrstr(buff,G_DIR_SEPARATOR_S); if ( (!ep) || (buff == ep) ) goto error_out; *ep='\0'; rc=-ENOMEM; new_dir=g_strdup(buff); if (!new_dir) goto error_out; *parent=new_dir; rc=0; error_out: g_free(buff); return rc;}static intcheck_end_condition(const char *top_dir,const char *current_dir,gboolean *is_cont){ size_t top_len; size_t dir_len; if ( (!top_dir) || (!current_dir) || (!is_cont) ) return -EINVAL; *is_cont=TRUE; top_len=strlen(top_dir); dir_len=strlen(current_dir); if (top_len >= dir_len) *is_cont=FALSE; return 0;}static intupdate_file_display(unsigned long filetype,const char *filename,size_t size,GtkTreeModel *model,GtkTreeIter *iter){ if ( (!filename) || (!model) || (!iter) ) return -EINVAL; if (!GTK_IS_LIST_STORE (model)) { war_out("Download window is destroyed.\n"); return -EFAULT; /* 仮にEFAULTを返す */ } gtk_list_store_set(GTK_LIST_STORE(model), iter, 1, filename, 2, 0, 3, size, 4, 0, 5, filetype, 6, get_file_type_name(filetype), -1); ipmsg_update_ui(); return 0;}intdo_download(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data){ int rc; tcp_con_t con; GtkWidget *window; GtkWidget *entry; GtkWidget *all_check; ipmsg_recvmsg_private_t *sender_info; ipmsg_private_data_t *priv; long pkt_no; int fileid; size_t total_write; size_t may_read; char filepath[PATH_MAX]; char *filename; char *dirname; char *req_message=NULL; int is_retry; int ftype; gboolean is_interactive; char *basename; window=GTK_WIDGET(data); if (!GTK_IS_WINDOW(window)) return -EFAULT; entry=lookup_widget(GTK_WIDGET(window),"DownLoadDirectoryEntry"); if (!GTK_IS_ENTRY(entry)) return -EFAULT; all_check=lookup_widget(GTK_WIDGET(window),"DownLoadAllCheckBtn"); if (!GTK_IS_CHECK_BUTTON(all_check)) return -EFAULT; priv=(ipmsg_private_data_t *)lookup_widget(GTK_WIDGET(window),"senderInfo"); g_assert(priv); sender_info=priv->data; g_assert(sender_info->ipaddr); pkt_no=sender_info->pktno; gtk_tree_model_get (model, iter, 0, &fileid, 1, &filename, 3, &may_read, 5, &ftype, -1); basename=g_path_get_basename(filename); g_free(filename); if (!basename) { return -ENOMEM; } dirname=(char *)gtk_entry_get_text(GTK_ENTRY(entry)); snprintf(filepath,PATH_MAX-1,"%s/%s",dirname,basename); filepath[PATH_MAX-1]='\0'; g_free(basename); dbg_out("download %d th element of %ld from %s into %s\n",fileid,pkt_no,sender_info->ipaddr,filepath); retry_this_file: memset(&con,0,sizeof(tcp_con_t)); rc=tcp_setup_client(hostinfo_get_ipmsg_system_addr_family(),sender_info->ipaddr,hostinfo_refer_ipmsg_port(),&con); if (rc<0) { rc=-errno; goto error_out; } /* * ロックアップ対策のためのタイムアウト設定 */ rc=sock_recv_time_out(con.soc,TCP_CLIENT_TMOUT_MS); if (rc<0) { rc=-errno; goto error_out; } /* リクエスト送信 */ send_download_request(&con, ftype,pkt_no,fileid); is_interactive= ((gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(all_check)))? (FALSE):(TRUE) ); switch(download_base_cmd(ftype)) { case IPMSG_FILE_DIR: /* 階層ディレクトリ受信 */ ipmsg_update_ui(); dbg_out("This is directory ignored.\n"); rc=do_download_directory(&con, dirname,model,iter); if ( (!rc) && (is_interactive) ) rc=download_dir_open_operation(dirname); break; case IPMSG_FILE_REGULAR: /* 通常ファイル受信 */ rc=do_download_regular_file(&con,filepath,may_read,&total_write,model,iter); dbg_out("Retry:rc=%d file:%s write:%d expected read :%d dir:%s\n", rc,filepath,total_write,may_read,dirname); is_retry=post_download_operation(rc, filepath, total_write, may_read, dirname, is_interactive); if ( (rc) && (is_retry == -EAGAIN) ) { /* 0リセット */ gtk_list_store_set(GTK_LIST_STORE(model), iter, 2, 0, -1); ipmsg_update_ui(); close(con.soc); goto retry_this_file; } break; default: err_out("Unknown file type:%d\n",ftype); break; } close(con.soc); /* 端點のクローズは, 受信側で行うのがipmsgの仕様 */ error_out: return rc;}static voidprogress_cell_data_func(GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data){ GtkTreeView *view; GtkEntry *entry; GtkWidget *window; int fd; gint sent; gint size; int fattr_num; gint persent; gchar size_string[32]; gchar path_string[PATH_MAX]; gchar *filename; gboolean is_exist=FALSE; g_assert(user_data); view=(GtkTreeView *)user_data; window=lookup_widget(GTK_WIDGET(view),"downloadWindow"); g_assert(window); entry=GTK_ENTRY(lookup_widget(GTK_WIDGET(view),"DownLoadDirectoryEntry")); g_assert(entry); gtk_tree_model_get(model, iter, DOWNLOAD_FILENAME_NUM, &filename, DOWNLOAD_RECVSIZE_NUM, &sent, DOWNLOAD_FILESIZE_NUM, &size, DOWNLOAD_FILEATTR_NUM, &fattr_num, -1); snprintf(path_string,PATH_MAX-1,"%s/%s",gtk_entry_get_text(GTK_ENTRY(entry)),filename); path_string[PATH_MAX-1]='\0'; dbg_out("Check path:%s\n",path_string);/* if ( (fattr_num != IPMSG_FILE_REGULAR) && (!size) ) *//* return; */ switch(fattr_num) { default: case IPMSG_FILE_REGULAR: break; case IPMSG_FILE_DIR: /* ディレクトリのダウンロードが完了したら * 親ディレクトリへの復帰になるはずなので * 0として扱う. */ persent=0; goto output_out; break; case IPMSG_FILE_RETPARENT: /* ディレクトリの完了通知なので, 100%とみなす. * 厳密にいえば手抜きだが, * 中途のディレクトリも同様にあつかう */ persent=100; goto output_out; break; } if (size>0) persent=(gint)((sent/(double)size)*100); else { /* 0バイトファイル対策 */ persent=0;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -