bool CTar32::addheader(const CTar32FileStatus &stat) { int blocksize = 1; if(m_archive_type == ARCHIVETYPE_TAR || m_archive_type == ARCHIVETYPE_TARGZ || m_archive_type == ARCHIVETYPE_TARZ || m_archive_type == ARCHIVETYPE_TARBZ2 || m_archive_type == ARCHIVETYPE_TARLZMA || m_archive_type == ARCHIVETYPE_TARXZ){ blocksize = 512; HEADER tar_header; { HEADER *pblock = &tar_header; memset(pblock, 0, sizeof(*pblock)); const CTar32FileStatus *p = &stat; std::string fname = p->filename; if(fname.length() >= sizeof(pblock->dbuf.name)/*100*/){ CTar32FileStatus tmpstat = stat; tmpstat.filename = "././@LongLink"; tmpstat.typeflag = LONGLINK; tmpstat.original_size = fname.length(); bool bret = addheader(tmpstat); char filename[2000]; strcpy(filename, fname.c_str()); size64 writesize = ((fname.length() - 1)/512+1)*512; size64 ret = m_pfile->write(filename, writesize); if(ret != writesize){ throw CTar32Exception("LongLink filename write error", ERROR_CANNOT_WRITE); } } strncpy(pblock->dbuf.name, fname.c_str(),NAMSIZ-1); /* tarnt 0.96->0.97 */ sprintf(pblock->dbuf.mode, "%6o ", (unsigned int)p->mode); sprintf(pblock->dbuf.uid, "%06o ",p->uid); sprintf(pblock->dbuf.gid, "%06o ",p->gid); sprintf(pblock->dbuf.size, "%11I64o ", p->original_size); sprintf(pblock->dbuf.mtime, "%11lo ", p->mtime); pblock->dbuf.typeflag = p->typeflag; memcpy(pblock->dbuf.magic, p->magic_version, sizeof(p->magic_version)); strncpy(pblock->dbuf.uname, p->uname, sizeof pblock->dbuf.uname); sprintf(pblock->dbuf.chksum, "%6o ", pblock->compsum()); } size64 ret = m_pfile->write(&tar_header,sizeof(tar_header)); if(ret != sizeof(tar_header)){ throw CTar32Exception("header write error", ERROR_CANNOT_WRITE); } }else{ ; } m_currentfile_status = stat; m_currentfile_status.blocksize = blocksize; return true; }
bool CTar32::addbody(const char *file) { struct _stat st; if(_stat(file, &st) == -1){ char msg[1000]; sprintf(msg, "can't read file[%s]", file); throw CTar32Exception(msg, ERROR_CANNOT_READ); } if(st.st_size == 0){return true;} //FILE *fp_r; //fp_r = fopen(file, "rb"); //std::ifstream fs_r; fast_fstream fs_r; fs_r.open(file,std::ios::in|std::ios::binary); //if(!fp_r){ if(fs_r.fail()){ throw CTar32Exception("can't read file", ERROR_CANNOT_READ); } size64 size = 0; size64 n; char buf[4096]; //while((n = fread(buf,1,sizeof(buf),fp_r))>0){ while(fs_r.read(buf,sizeof(buf)),(n=fs_r.gcount())>0){ size64 m = m_pfile->write(buf, n); if(m>0){size += m;} if(n!=m){ throw CTar32Exception("can't write to arcfile", ERROR_CANNOT_WRITE); } } if(m_archive_type == ARCHIVETYPE_TAR || m_archive_type == ARCHIVETYPE_TARGZ || m_archive_type == ARCHIVETYPE_TARZ || m_archive_type == ARCHIVETYPE_TARBZ2 || m_archive_type == ARCHIVETYPE_TARLZMA || m_archive_type == ARCHIVETYPE_TARXZ){ /* padding 512-byte block */ size64 writesize; if(size%512 == 0){ writesize = 0; }else{ writesize = 512 - size%512; } memset(buf,0,(size_t)writesize); //TODO:size lost m_pfile->write(buf, writesize); } return true; }
bool CTar32::readTarHeader(HEADER &tar_header) { size64 ret = m_pfile->read(&tar_header,sizeof(tar_header)); if(ret == 0){return false;} if(ret != sizeof(tar_header)){ throw CTar32Exception("can't read tar header",ERROR_HEADER_BROKEN); } { //is zero header? int nIdx; for(nIdx=0;nIdx<sizeof(tar_header);nIdx++){ if(((const char*)&tar_header)[nIdx]!=0)break; } if(nIdx==sizeof(tar_header))return false; //EOF } int checksum=(int)parseOctNum(tar_header.dbuf.chksum , COUNTOF(tar_header.dbuf.chksum)); if(tar_header.compsum() != checksum && tar_header.compsum_oldtar() != checksum){ throw CTar32Exception("tar header checksum error.",ERROR_HEADER_CRC); } return true; }
bool CTar32::readdir_CPIO(CTar32FileStatus &stat) { new_cpio_header cpio_header; { size64 ret = m_pfile->read(&cpio_header,sizeof(cpio_header)); if(ret == 0){return false;} if(ret != sizeof(cpio_header)){ throw CTar32Exception("can't read tar header",ERROR_HEADER_BROKEN); } if(! cpio_header.magic_check()){ throw CTar32Exception("tar header checksum error.",ERROR_HEADER_CRC); } } int fnamelen; int dum; int nret = sscanf(((char*)&cpio_header)+6, "%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx" ,&dum, &stat.mode, &stat.uid, &stat.gid, &dum, &stat.mtime ,&stat.original_size,&stat.devmajor, &stat.devminor, &dum, &dum ,&fnamelen, &stat.chksum); if(nret != 13){ throw CTar32Exception("can't read tar header",ERROR_HEADER_BROKEN); } if(fnamelen<=0 || fnamelen>=1000){return false;} char fname[1000]; int fnamelen2 = (((fnamelen+sizeof(new_cpio_header) -1)/4)+1)*4 - sizeof(new_cpio_header); /* 4 byte padding for ("new cpio header" + "filename") */ m_pfile->read(fname,fnamelen2); stat.filename = fname; stat.blocksize = 4; if(stat.filename == "TRAILER!!!"){ return false; } if((stat.mode & _S_IFMT) == _S_IFDIR){ stat.filename = stat.filename + "/"; } return true; }
static bool add_file(CTar32CmdInfo &cmdinfo, CTar32 *pTarfile, const char *fname,std::vector<char> &buffer) { CTar32FileStatus &stat = pTarfile->m_currentfile_status; std::string fname2 = fname; EXTRACTINGINFOEX extractinfo; EXTRACTINGINFOEX64 exinfo64; MakeExtractingInfo(pTarfile,fname2.c_str(),extractinfo,exinfo64); { int ret = SendArcMessage(cmdinfo, ARCEXTRACT_BEGIN, &extractinfo,&exinfo64); if(ret){throw CTar32Exception("Cancel button was pushed.",ERROR_USER_CANCEL);} // fname2 = extractinfo.exinfo.szDestFileName; } size64 filesize = pTarfile->m_currentfile_status.original_size; if(filesize == 0){return true;} CTar32InternalFile file; file.open(pTarfile, /*write*/true); //std::ifstream fs_r; fast_fstream fs_r; fs_r.open(fname2.c_str(), std::ios::in|std::ios::binary); if(fs_r.fail()){throw CTar32Exception("can't read file", ERROR_CANNOT_READ);return false;} size64 readsize = 0; size64 n; while(fs_r.read(&buffer[0],buffer.size()),(n=fs_r.gcount())>0){ size64 m = file.write(&buffer[0], n); if(m>0){readsize += m;} if(n!=m){ throw CTar32Exception("can't write to arcfile", ERROR_CANNOT_WRITE); } // if(cmdinfo.hTar32StatusDialog){ extractinfo.exinfo.dwWriteSize = (DWORD)readsize; exinfo64.exinfo.dwWriteSize = (DWORD)readsize; exinfo64.llWriteSize = readsize; int ret = SendArcMessage(cmdinfo, ARCEXTRACT_INPROCESS, &extractinfo,&exinfo64); if(ret){throw CTar32Exception("Cancel button was pushed.",ERROR_USER_CANCEL);} // } } bool bret = file.close(); if(!bret){throw CTar32Exception("can't write to arcfile", ERROR_CANNOT_WRITE);} // if(cmdinfo.hTar32StatusDialog){ extractinfo.exinfo.dwWriteSize = (DWORD)readsize; exinfo64.exinfo.dwWriteSize = (DWORD)readsize; exinfo64.llWriteSize = readsize; int ret = SendArcMessage(cmdinfo, 6, &extractinfo,&exinfo64); if(ret){throw CTar32Exception("Cancel button was pushed.",ERROR_USER_CANCEL);} // } return true; }
static void cmd_list(CTar32CmdInfo &cmdinfo) { CTar32 tarfile; bool bret; bret = tarfile.open(cmdinfo.arcfile.c_str(), "rb",-1,ARCHIVETYPE_AUTO,cmdinfo.archive_charset); if(!bret){ throw CTar32Exception("can't open archive file", ERROR_ARC_FILE_OPEN); } CTar32FileStatus stat; bret = true; cmdinfo.output << "filename" << "\t" << "filesize" << "\n"; while(1){ bret = tarfile.readdir(&stat); if(!bret){break;} bret = tarfile.readskip(); if(!bret){break;} cmdinfo.output << stat.filename << "\t" << stat.original_size << "\n"; } }
static void _cdecl tar_cmd_main_thread(LPVOID param) { CTar32CmdInfo *pCmdInfo = (CTar32CmdInfo*)param; CTar32CmdInfo &cmdinfo = *pCmdInfo; CTar32StatusDialog dlg; try{ if(cmdinfo.b_display_dialog){ cmdinfo.hTar32StatusDialog = dlg.Create(cmdinfo.hParentWnd); } switch(cmdinfo.command){ case 'x': cmd_extract(cmdinfo); break; case 'c': cmd_create(cmdinfo); break; case 'l': cmd_list(cmdinfo); break; default: throw CTar32Exception("Command not specified.", ERROR_COMMAND_NAME); } // メッセージループの終了前にダイアログを閉じる! 2000/03/03 by tsuneo dlg.Destroy(); if(pCmdInfo->wm_main_thread_end)PostThreadMessage(pCmdInfo->idMessageThread, pCmdInfo->wm_main_thread_end, 0, 0); }catch(CTar32Exception &e){ dlg.Destroy(); if(pCmdInfo->wm_main_thread_end)PostThreadMessage(pCmdInfo->idMessageThread, pCmdInfo->wm_main_thread_end, 0, 0); cmdinfo.exception = e; // throw e; }catch(...){ dlg.Destroy(); } //return 0; }
static void cmd_create(CTar32CmdInfo &cmdinfo) { { EXTRACTINGINFOEX extractinfo; memset(&extractinfo,0,sizeof(extractinfo)); EXTRACTINGINFOEX64 exinfo64; memset(&exinfo64,0,sizeof(exinfo64)); exinfo64.dwStructSize=sizeof(exinfo64); strncpy(extractinfo.exinfo.szSourceFileName, cmdinfo.arcfile.c_str() ,FNAME_MAX32+1); exinfo64.exinfo=extractinfo.exinfo; strncpy(exinfo64.szSourceFileName, extractinfo.exinfo.szSourceFileName ,FNAME_MAX32+1); int ret = SendArcMessage(cmdinfo, ARCEXTRACT_OPEN, &extractinfo,&exinfo64); if(ret){throw CTar32Exception("Cancel button was pushed.",ERROR_USER_CANCEL);} } CTar32 tarfile; int ret; bool bret; int filenum = 0; //char mode[10]; //sprintf(mode, "wb%d", cmdinfo.compress_level); ret = tarfile.open(cmdinfo.arcfile.c_str(), "wb",cmdinfo.compress_level, cmdinfo.archive_type,cmdinfo.archive_charset); if(!ret){ throw CTar32Exception("can't open archive file", ERROR_ARC_FILE_OPEN); } std::vector<char> buffer; buffer.resize(1024*1024); // const list<string> &files = cmdinfo.files; const std::list<CTar32CmdInfo::CArgs> &args = cmdinfo.argfiles; std::list<CTar32CmdInfo::CArgs>::const_iterator filei; //enumerate files std::vector<FILE_TO_ADD> files_to_add; for(filei = args.begin();filei!=args.end();filei++){ std::vector<std::string> files_enumed; { std::string file_internal = (*filei).file; std::string file_external = make_pathname((*filei).current_dir.c_str(), (*filei).file.c_str()); find_files(file_external.c_str(),files_enumed); if(_mbsrchr((const unsigned char*)file_external.c_str(),'*')==0 && files_enumed.empty()){ // fixed by tsuneo. 2001.05.15 throw CTar32Exception((std::string("can't find file [") + file_external + "]").c_str(), ERROR_FILE_OPEN); } } for(std::vector<std::string>::iterator files2i = files_enumed.begin(); files2i != files_enumed.end(); files2i++){ std::string file_path = *files2i; std::string file_relative; if(cmdinfo.b_use_directory){ file_relative = file_path.substr((*filei).current_dir.length()); }else{ file_relative = get_filename(file_path.c_str()); } // FILE_TO_ADD file_entry; file_entry.fullPath=file_path; file_entry.relativePath=file_relative; files_to_add.push_back(file_entry); } } //sort? : by filepath or by extension if(cmdinfo.b_sort_by_ext){ struct SORTER_BY_EXT{ bool operator()(const FILE_TO_ADD& a,const FILE_TO_ADD& b){ //sort by ext int ret=stricmp(PathFindExtension(a.relativePath.c_str()),PathFindExtension(b.relativePath.c_str())); if(ret==0){ //sort by path if ext is same return stricmp(a.relativePath.c_str(),b.relativePath.c_str())<0; }else{ return ret<0; } } }; std::sort(files_to_add.begin(),files_to_add.end(),SORTER_BY_EXT()); }else if(cmdinfo.b_sort_by_path){ struct SORTER_BY_PATH{ bool operator()(const FILE_TO_ADD& a,const FILE_TO_ADD& b){ return stricmp(a.relativePath.c_str(),b.relativePath.c_str())<0; } }; std::sort(files_to_add.begin(),files_to_add.end(),SORTER_BY_PATH()); } //compression { for(std::vector<FILE_TO_ADD>::const_iterator ite=files_to_add.begin();ite!=files_to_add.end();++ite){ const FILE_TO_ADD &file_entry=*ite; CTar32FileStatus stat; if(!stat.SetFromFile(file_entry.fullPath.c_str())){ continue; } std::string filepath_to_store=file_entry.relativePath; convert_yen_to_slash(filepath_to_store); { // if file is directory, add '/' to the tail of filename. struct _stat st; if(_stat(file_entry.fullPath.c_str(), &st)!=-1 && st.st_mode & _S_IFDIR){ char const*f = filepath_to_store.c_str(); if((char*)max(_mbsrchr((unsigned char*)f, '/'), _mbsrchr((unsigned char*)f,'\\')) != f+strlen(f)-1){ filepath_to_store.append(1,'/'); } } } stat.filename = filepath_to_store; bret = tarfile.addheader(stat); // bret = tarfile.addbody(file_external2.c_str()); bool bret2 = add_file(cmdinfo,&tarfile,file_entry.fullPath.c_str(),buffer); filenum ++; } } { EXTRACTINGINFOEX extractinfo; memset(&extractinfo,0,sizeof(extractinfo)); EXTRACTINGINFOEX64 exinfo64; memset(&exinfo64,0,sizeof(exinfo64)); exinfo64.dwStructSize=sizeof(exinfo64); int ret = SendArcMessage(cmdinfo, ARCEXTRACT_END, &extractinfo,&exinfo64); if(ret){throw CTar32Exception("Cancel button was pushed.",ERROR_USER_CANCEL);} } if(filenum == 0){ // fixed by tsuneo. 2001.05.14 throw CTar32Exception("There is no file to archive. ", ERROR_FILE_OPEN); } }
static void cmd_extract(CTar32CmdInfo &cmdinfo) { { EXTRACTINGINFOEX extractinfo; memset(&extractinfo,0,sizeof(extractinfo)); EXTRACTINGINFOEX64 exinfo64; memset(&exinfo64,0,sizeof(exinfo64)); exinfo64.dwStructSize=sizeof(exinfo64); strncpy(extractinfo.exinfo.szSourceFileName, cmdinfo.arcfile.c_str() ,FNAME_MAX32+1); exinfo64.exinfo=extractinfo.exinfo; strncpy(exinfo64.szSourceFileName, extractinfo.exinfo.szSourceFileName ,FNAME_MAX32+1); int ret = SendArcMessage(cmdinfo, ARCEXTRACT_OPEN, &extractinfo,&exinfo64); if(ret){throw CTar32Exception("Cancel button was pushed.",ERROR_USER_CANCEL);} } CTar32 tarfile; int ret; ret = tarfile.open(cmdinfo.arcfile.c_str(), "rb",-1,ARCHIVETYPE_AUTO,cmdinfo.archive_charset); if(!ret){ throw CTar32Exception("can't open archive file", ERROR_ARC_FILE_OPEN); } CTar32FileStatus stat; std::vector<char> buffer; buffer.resize(1024*1024); while(true){ bool bret = tarfile.readdir(&stat); if(!bret){break;} std::string file_internal = stat.filename; std::string file_external; { const std::list<CTar32CmdInfo::CArgs> &args = cmdinfo.argfiles; std::list<CTar32CmdInfo::CArgs>::const_iterator filei; for(filei = args.begin();filei!=args.end();filei++){ if(::is_regexp_match_dbcs(filei->file.c_str(), file_internal.c_str())){ std::string file_internal2 = file_internal; if(! cmdinfo.b_absolute_paths){ file_internal2 = escape_absolute_paths(file_internal2.c_str()); } if(!cmdinfo.b_use_directory){ file_internal2 = get_filename(file_internal2.c_str()); } file_external = make_pathname(filei->current_dir.c_str(), file_internal2.c_str()); break; } } } if(file_external.empty()){ bret = tarfile.readskip(); }else{ bool bret2 = extract_file(cmdinfo,&tarfile,file_external.c_str(),buffer); } } { EXTRACTINGINFOEX extractinfo; memset(&extractinfo,0,sizeof(extractinfo)); EXTRACTINGINFOEX64 exinfo64; memset(&exinfo64,0,sizeof(exinfo64)); exinfo64.dwStructSize=sizeof(exinfo64); int ret = SendArcMessage(cmdinfo, ARCEXTRACT_END, &extractinfo,&exinfo64); if(ret){throw CTar32Exception("Cancel button was pushed.",ERROR_USER_CANCEL);} } }
bool extract_file(CTar32CmdInfo &cmdinfo, CTar32 *pTarfile, const char *fname,std::vector<char> &buffer) { CTar32FileStatus &stat = pTarfile->m_currentfile_status; std::string fname2 = fname; EXTRACTINGINFOEX extractinfo; EXTRACTINGINFOEX64 exinfo64; MakeExtractingInfo(pTarfile,fname2.c_str(),extractinfo,exinfo64); { int ret = SendArcMessage(cmdinfo, ARCEXTRACT_BEGIN, &extractinfo,&exinfo64); if(ret){throw CTar32Exception("Cancel button was pushed.",ERROR_USER_CANCEL);} fname2 = extractinfo.exinfo.szDestFileName; } //上書き確認 if(cmdinfo.b_confirm_overwrite){ switch(ConfirmOverwrite(cmdinfo, exinfo64)){ case -1://cancel(abort) throw CTar32Exception("Cancel button was pushed.",ERROR_USER_CANCEL); break; case 1: //yes to all cmdinfo.b_confirm_overwrite=false; break; } } size64 filesize = pTarfile->m_currentfile_status.original_size; CTar32InternalFile file; file.open(pTarfile); //std::ofstream fs_w; fast_fstream fs_w; if(!cmdinfo.b_print){ mkdir_recursive(get_dirname(fname2.c_str()).c_str()); fs_w.open(fname2.c_str(), std::ios::out|std::ios::binary); if(fs_w.fail()){return false;} } size64 readsize = 0; //static std::vector<char> buf; //const int bufsize=512*1024; //buf.resize(bufsize); const size_t bufsize=buffer.size(); while(filesize ==-1 || readsize<filesize){ size64 nextreadsize; if(filesize == -1){ // case ".gz",".Z",".bz2" //nextreadsize = sizeof(buf); nextreadsize=bufsize; }else{ size64 nextreadsize64 = filesize-readsize; if(nextreadsize64 > bufsize){nextreadsize64 = bufsize;} nextreadsize = nextreadsize64; if(nextreadsize==0){ Sleep(0); } // nextreadsize = (int)min(filesize-readsize, sizeof(buf)); } if(nextreadsize==0){ Sleep(0); } size64 n = file.read(&buffer[0],nextreadsize); readsize += n; if(cmdinfo.b_print){ cmdinfo.output.write(&buffer[0],(size_t)n); //TODO:size lost }else{ fs_w.write(&buffer[0],n); if(fs_w.fail()){return false;} } if(n != nextreadsize){ if(filesize == -1){ // case .gz/.Z/.bz2" break; }else{ return false; } } // if(cmdinfo.hTar32StatusDialog){ extractinfo.exinfo.dwWriteSize = (DWORD)readsize; exinfo64.exinfo.dwWriteSize = (DWORD)readsize; exinfo64.llWriteSize = readsize; int ret = SendArcMessage(cmdinfo, ARCEXTRACT_INPROCESS, &extractinfo,&exinfo64); if(ret){throw CTar32Exception("Cancel button was pushed.",ERROR_USER_CANCEL);} // } } if(!cmdinfo.b_print){ fs_w.close(); struct _utimbuf ut; ut.actime = (stat.atime ? stat.atime : time(NULL)); ut.modtime = (stat.mtime ? stat.mtime : time(NULL)); int ret; ret = _utime(fname2.c_str(), &ut); ret = _chmod(fname2.c_str(), stat.mode); } // if(cmdinfo.hTar32StatusDialog){ extractinfo.exinfo.dwWriteSize = (DWORD)readsize; exinfo64.exinfo.dwWriteSize = (DWORD)readsize; exinfo64.llWriteSize = readsize; int ret = SendArcMessage(cmdinfo, 6, &extractinfo,&exinfo64); if(ret){throw CTar32Exception("Cancel button was pushed.",ERROR_USER_CANCEL);} // } return true; }
static int tar_cmd_itr(const HWND hwnd, LPCSTR szCmdLine,LPSTR szOutput, const DWORD dwSize,CTar32CmdInfo &cmdinfo) { if(cmdinfo.arcfile.empty()){ throw CTar32Exception("Archive File is not specified.", ERROR_NOT_ARC_FILE); } if(cmdinfo.argfiles.empty()){ if(cmdinfo.command == 'x' || cmdinfo.command == 'l'){ // If no file to extract/create is specified, I assume as all file is specified. cmdinfo.argfiles.push_back(CTar32CmdInfo::CArgs("*",cmdinfo.current_directory)); }else{ throw CTar32Exception("no file to archive is specified.", ERROR_NOT_ARC_FILE); } } if(cmdinfo.b_archive_tar){ switch(cmdinfo.archive_type){ case ARCHIVETYPE_NORMAL: cmdinfo.archive_type = ARCHIVETYPE_TAR;break; case ARCHIVETYPE_GZ: cmdinfo.archive_type = ARCHIVETYPE_TARGZ;break; case ARCHIVETYPE_Z: cmdinfo.archive_type = ARCHIVETYPE_TARZ;break; case ARCHIVETYPE_BZ2: cmdinfo.archive_type = ARCHIVETYPE_TARBZ2;break; case ARCHIVETYPE_LZMA: cmdinfo.archive_type = ARCHIVETYPE_TARLZMA;break; case ARCHIVETYPE_XZ: cmdinfo.archive_type = ARCHIVETYPE_TARXZ;break; } } //string arcfile = *argi++; //list<string> files(argi,args.end()); //CTar32CmdInfo cmdinfo; //cmdinfo.arcfile = arcfile; //cmdinfo.files = files; /* CTar32StatusDialog dlg; if(cmdinfo.b_display_dialog){ cmdinfo.hTar32StatusDialog = dlg.Create(hwnd); } switch(command){ case 'x': cmd_extract(cmdinfo); break; case 'c': cmd_create(cmdinfo); break; case 'l': cmd_list(cmdinfo); break; default: throw CTar32Exception("Command not specified.", ERROR_COMMAND_NAME); } */ //cmdinfo.command = command; cmdinfo.hParentWnd = hwnd; int func_ret = 0; // extern static void _cdecl tar_cmd_main_thread(LPVOID param); //DWORD process_id,thread_id; //thread_id = GetWindowThreadProcessId(hwnd,&process_id); if(cmdinfo.b_message_loop && cmdinfo.hParentWnd /*&& process_id == GetCurrentProcessId() && thread_id == GetCurrentThreadId()*/){ cmdinfo.wm_main_thread_end = RegisterWindowMessage("wm_main_thread_end"); cmdinfo.idMessageThread = GetCurrentThreadId(); MSG msg; HANDLE hThread = (HANDLE)_beginthread(tar_cmd_main_thread,0,(void*)&cmdinfo); while(GetMessage(&msg,NULL,0,0)){ if(msg.message == cmdinfo.wm_main_thread_end){ unsigned long exitcode; while(GetExitCodeThread(hThread,&exitcode) && (exitcode==STILL_ACTIVE)){ Sleep(1); } break; } if(!IsDialogMessage(cmdinfo.hTar32StatusDialog,&msg)){ TranslateMessage(&msg); DispatchMessage(&msg); } } }else{ /*func_ret =*/ tar_cmd_main_thread((LPVOID)&cmdinfo); } if(cmdinfo.exception.m_code != 0){ throw cmdinfo.exception; } return func_ret; }
void tar_cmd_parser(LPCSTR szCmdLine,CTar32CmdInfo &cmdinfo) { std::vector<std::string> args; // command line array if(!split_cmdline_with_response(szCmdLine,args)){ throw CTar32Exception("commandline split error", ERROR_COMMAND_NAME); } char command = 0; // main command. ('x','c','l') //std::string current_directory; -> into CTar32CmdInfo std::vector<std::string>::iterator argi = args.begin(); bool option_end = false; while(argi != args.end()){ //string::iterator stri = (*argi).begin(); const char *stri = (*argi).c_str(); if(argi==args.begin() || (*stri == '-' && *(stri+1) != '\0' && option_end == false)){ if(*stri == '-'){ stri++; } if(*stri == '-' && *(stri+1) != '\0'){ stri++; const std::string long_option = (*argi).substr(stri - (*argi).c_str()); std::string key = long_option; std::string val; int len; if((len = long_option.find('=')) != std::string::npos){ key = long_option.substr(0, len); val = long_option.substr(len + 1); } if(key == "use-directory"){ cmdinfo.b_use_directory = ((val=="") ? true : (0!=atoi(val.c_str()))); }else if(key == "absolute-paths"){ cmdinfo.b_absolute_paths = ((val=="") ? true : (0!=atoi(val.c_str()))); }else if(key == "display-dialog"){ cmdinfo.b_display_dialog = ((val=="") ? true : (0!=atoi(val.c_str()))); }else if(key == "message-loop"){ cmdinfo.b_message_loop = ((val=="") ? true : (0!=atoi(val.c_str()))); }else if(key == "inverse-procresult"){ cmdinfo.b_inverse_procresult = ((val=="") ? true : (0!=atoi(val.c_str()))); }else if(key == "bzip2" || key == "bzip"){ cmdinfo.archive_type = ARCHIVETYPE_BZ2; cmdinfo.compress_level = atoi(val.c_str()); if(cmdinfo.compress_level<1) cmdinfo.compress_level = 9; if(cmdinfo.compress_level>9) cmdinfo.compress_level = 9; }else if(key == "gzip"){ cmdinfo.archive_type = ARCHIVETYPE_GZ; cmdinfo.compress_level = atoi(val.c_str()); if(cmdinfo.compress_level<1) cmdinfo.compress_level = 5; if(cmdinfo.compress_level>9) cmdinfo.compress_level = 5; }else if(key == "lzma"){ cmdinfo.archive_type = ARCHIVETYPE_LZMA; cmdinfo.compress_level = atoi(val.c_str()); if(cmdinfo.compress_level<0) cmdinfo.compress_level = 6; if(cmdinfo.compress_level>9) cmdinfo.compress_level = 6; }else if(key == "xz"){ cmdinfo.archive_type = ARCHIVETYPE_XZ; cmdinfo.compress_level = atoi(val.c_str()); if(cmdinfo.compress_level<0) cmdinfo.compress_level = 6; if(cmdinfo.compress_level>9) cmdinfo.compress_level = 6; }else if(key == "confirm-overwrite"){ cmdinfo.b_confirm_overwrite = ((val=="") ? true : (0!=atoi(val.c_str()))); }else if(key == "convert-charset"){ if(val=="")cmdinfo.archive_charset = CHARSET_UNKNOWN; else if(stricmp(val.c_str(),"none")==0)cmdinfo.archive_charset = CHARSET_DONTCARE; else if(stricmp(val.c_str(),"auto")==0)cmdinfo.archive_charset = CHARSET_UNKNOWN; else if(stricmp(val.c_str(),"sjis")==0)cmdinfo.archive_charset = CHARSET_SJIS; else if(stricmp(val.c_str(),"eucjp")==0)cmdinfo.archive_charset = CHARSET_EUCJP; else if(stricmp(val.c_str(),"utf8")==0)cmdinfo.archive_charset = CHARSET_UTF8; else cmdinfo.archive_charset = CHARSET_DONTCARE; }else if(key == "sort-by-ext"){ cmdinfo.b_sort_by_ext = ((val=="") ? true : (0!=atoi(val.c_str()))); }else if(key == "sort-by-path"){ cmdinfo.b_sort_by_path = ((val=="") ? true : (0!=atoi(val.c_str()))); }else{ /* igonore */; } argi++; continue; } std::vector<std::string>::iterator cur_argi = argi; //while(stri != (*cur_argi).end()){ while(stri != (*cur_argi).c_str()+(*cur_argi).length()){ switch(*stri){ case 'x': command = 'x';break; case 'c': command = 'c';break; case 'l': case 't': // どんぞ:追加 command = 'l';break; case 'p': command = 'x'; cmdinfo.b_print = true; break; case 'f': if(++argi == args.end()){ throw CTar32Exception("'f' follow no directory name", ERROR_COMMAND_NAME); } cmdinfo.arcfile = *argi; break; case 'o': if(++argi == args.end()){ throw CTar32Exception("'o' follow no directory name", ERROR_COMMAND_NAME); } cmdinfo.current_directory = *argi; // stri = argi->end()-1; break; case 'z': cmdinfo.archive_type = ARCHIVETYPE_GZ; if(isdigit(*(stri+1))){ stri++; cmdinfo.compress_level = ((char)*stri) - '0'; }else{ cmdinfo.compress_level = 6; } break; case 'B': case 'j': cmdinfo.archive_type = ARCHIVETYPE_BZ2; if(isdigit(*(stri+1))){ stri++; cmdinfo.compress_level = ((char)*stri) - '0'; }else{ cmdinfo.compress_level = 9; } break; case 'J': cmdinfo.archive_type = ARCHIVETYPE_XZ; if(isdigit(*(stri+1))){ stri++; cmdinfo.compress_level = ((char)*stri) - '0'; }else{ cmdinfo.compress_level = 6; } break; case 'Z': cmdinfo.archive_type = ARCHIVETYPE_Z; if(isdigit(*(stri+1))){ stri++; cmdinfo.compress_level = ((char)*stri) - '0'; }else{ cmdinfo.compress_level = 6; } break; case 'G': cmdinfo.b_archive_tar = false; if(cmdinfo.archive_type == ARCHIVETYPE_NORMAL){ cmdinfo.archive_type = ARCHIVETYPE_GZ; cmdinfo.compress_level = 6; } break; case 'P': cmdinfo.b_absolute_paths = true; break; case 'a': case 'v': case 'V': case 'I': case 'i': case 'e': case 'g': case 'S': case 'R': // added by tsuneo 2001.05.14 /*ignore*/ break; case 'A': stri++; /*ignore*/ break; case 'b': case 'N': argi++; //stri = argi->end()-1; stri = (*argi).c_str()+(*argi).length()-1; /*ignore*/ break; case 'U': if(isdigit(*(stri+1))){ stri++; } /*ignore*/ break; case '-': // added by tsuneo on 2006/08/04. Patch is provided by Niiyama(HEROPA)-san. Special Thanks to Niiyama(HEROPA)-san. option_end = true; break; default: throw CTar32Exception("Invalid Arguments", ERROR_COMMAND_NAME); } stri++; } argi++; }else{ const char *file = (*argi).c_str(); if(*file && ((char*)_mbsrchr((const unsigned char*)file, '\\') == file + strlen(file) - 1)){ cmdinfo.current_directory = (char*)file; }else if(cmdinfo.arcfile.length() == 0){ cmdinfo.arcfile = *argi; }else{ std::string file = *argi; cmdinfo.argfiles.push_back(CTar32CmdInfo::CArgs(file,cmdinfo.current_directory)); } argi++; } } cmdinfo.command = command; }
bool CTar32::readdir_AR(CTar32FileStatus &stat) { if(m_filecount == 0){ char magic[8]; /*size64 ret = */m_pfile->read(magic,8); /* skip "!<arch>\012" */ } ar_hdr header; { size64 ret = m_pfile->read(&header,sizeof(header)); if(ret == 0){return false;} if(ret != sizeof(header)){ throw CTar32Exception("can't read tar header",ERROR_HEADER_BROKEN); } if(! header.magic_check()){ throw CTar32Exception("tar header checksum error.",ERROR_HEADER_CRC); } } char *p = strchr(header.name,' '); *p = '\0'; // cut from ' ' if(strcmp(header.name,"//")!=0 && p-1 > header.name && strrchr(header.name,'/') == p-1){ *(p-1) = '\0';} // cut last '/' stat.filename = header.name; stat.mtime = strtol(header.date,NULL,10); stat.uid = strtol(header.uid,NULL,10); stat.gid = strtol(header.gid,NULL,10); stat.mode = strtol(header.mode,NULL,8); //TODO:ここは10進数解釈? stat.original_size = strtol(header.size,NULL,10); stat.blocksize = 2; if(stat.filename == "/"){ char buf[1000]; sprintf(buf,"root%d",m_filecount); stat.filename = buf; } if(stat.filename == "//"){ /* long file name support */ CTar32InternalFile file; m_currentfile_status = stat; if(!file.open(this)){throw CTar32Exception("can't read tar header",ERROR_HEADER_BROKEN);} //longfilenames_buf = new char[stat.original_size]; // (char*)malloc(stat.original_size); longfilenames_buf.resize((unsigned int)stat.original_size+1); //TODO:size lost size64 n = file.read(&longfilenames_buf[0],stat.original_size); if(n!=stat.original_size){throw CTar32Exception("can't read tar header",ERROR_HEADER_BROKEN);} file.close(); longfilenames_buf[(unsigned int)stat.original_size]='\0'; CTar32FileStatus nextstat; bool bRet = readdir(&nextstat); m_filecount --; stat = nextstat; //if(!bRet || stat.filename != "/0"){ // throw CTar32Exception("can't read tar header",ERROR_HEADER_BROKEN); //} //stat.filename = longfilename; } { /* if use longfilename, substitute "/\d+" to filename */ int bytes; int num; int n = sscanf(stat.filename.c_str(), "/%d%n", &bytes, &num); int len = stat.filename.length(); if(n == 1 && num == len && !longfilenames_buf.empty()){ stat.filename = &longfilenames_buf[0]+bytes; } } return true; }
bool CTar32::readdir_TAR(CTar32FileStatus &stat) { HEADER tar_header; if(!readTarHeader(tar_header))return false; //get tar format : GNU or POSIX int tar_format=tar_header.getFormat(); // HP-UX's tar command create 100chars filename part. fixed on 2003.12.19 char tmp_name[COUNTOF(tar_header.dbuf.name)+1]; strncpy(tmp_name, tar_header.dbuf.name, COUNTOF(tar_header.dbuf.name)); tmp_name[COUNTOF(tar_header.dbuf.name)] = '\0'; stat.filename = tmp_name; /* tar_header.dbuf.name; */ stat.original_size = parseOctNum(tar_header.dbuf.size,COUNTOF(tar_header.dbuf.size)); if(tar_header.dbuf.typeflag == LNKTYPE){ // Fixed on 2003/11/28. For "spencer_pwb.tar.gz". Thanks to rollo-san. stat.original_size = 0; } stat.blocksize = 512; if(tar_header.dbuf.typeflag == LONGLINK){ // tar_header.dbuf.name == "././@LongLink" //NOTE:TAR32.DLL earlier than 2.33 makes LONGLINK entry with POSIX header tar_format=TAR_FORMAT_GNU; //char longfilename[2000] = ""; std::vector<char> longfilename; size64 readsize = (size_t(stat.original_size-1)/512+1)*512; longfilename.resize((size_t)readsize+1); //TODO:size lost size64 ret = m_pfile->read(&longfilename[0], readsize); if(ret == 0){ throw CTar32Exception("can't get filename(LongLink)",ERROR_HEADER_BROKEN); } longfilename[(size_t)stat.original_size]='\0'; //TODO:size lost if(!readTarHeader(tar_header))return false; stat.filename = &longfilename[0]; stat.original_size = parseOctNum(tar_header.dbuf.size, COUNTOF(tar_header.dbuf.size)); } bool bPaxFilenameSupplied=false; time_t pax_atime=0,pax_ctime=0,pax_mtime=0; if(tar_header.dbuf.typeflag == PAX_GLOBAL || tar_header.dbuf.typeflag == PAX_ENTRTY){ std::vector<char> content; size64 readsize = (size_t(stat.original_size-1)/512+1)*512; content.resize((size_t)readsize+1); //TODO:size lost size64 ret = m_pfile->read(&content[0], readsize); if(ret == 0){ throw CTar32Exception("can't get PAX Extended Global Header",ERROR_HEADER_BROKEN); } content[(size_t)stat.original_size]='\0'; //TODO:size lost if(!readTarHeader(tar_header))return false; stat.original_size = parseOctNum(tar_header.dbuf.size, COUNTOF(tar_header.dbuf.size)); strncpy(tmp_name, tar_header.dbuf.name, COUNTOF(tar_header.dbuf.name)); tmp_name[COUNTOF(tar_header.dbuf.name)] = '\0'; stat.filename = tmp_name; /* tar_header.dbuf.name; */ std::string extFilename; size64 filesize; if(!parsePaxExtHeader(&content[0],content.size(),extFilename,filesize,pax_atime,pax_ctime,pax_mtime)){ if(tar_header.dbuf.typeflag == PAX_GLOBAL){ throw CTar32Exception("Broken PAX Extended Global Header",ERROR_HEADER_BROKEN); }else{ throw CTar32Exception("Broken PAX Extended Header",ERROR_HEADER_BROKEN); } } if(tar_header.dbuf.typeflag == PAX_GLOBAL){ //global header //TODO:need test //if(filesize!=-1)m_currentfile_status.original_size=filesize; }else{ //entry header //TODO:need test //if(filesize!=-1)stat.original_size=filesize; if(!extFilename.empty()){ bPaxFilenameSupplied=true; stat.filename=extFilename; } } } //charset conversion if(m_archive_charset!=CHARSET_DONTCARE && !bPaxFilenameSupplied){ if(m_archive_charset==CHARSET_UNKNOWN){ //detect charset m_archive_charset=detect_charset(stat.filename.c_str()); } switch(m_archive_charset){ case CHARSET_EUCJP: stat.filename=CConvertCharsetHelper::getInstance().eucjp_to_sjis(stat.filename.c_str(),stat.filename.size()); break; case CHARSET_UTF8N: //FALLTHROUGH case CHARSET_UTF8: stat.filename=CConvertCharsetHelper::getInstance().utf8_to_sjis(stat.filename.c_str(),stat.filename.size()); break; case CHARSET_JIS: //FALLTHROUGH /* force to extract even if charset is not supported. */ //throw CTar32Exception("tar header charset error.",ERROR_NOT_SUPPORT); //break; case CHARSET_SJIS: //FALLTHROUGH default: //nothing to do break; } } stat.mode = strtol(tar_header.dbuf.mode, NULL, 8); stat.uid = strtol(tar_header.dbuf.uid , NULL, 8); stat.gid = strtol(tar_header.dbuf.gid , NULL, 8); stat.mtime = strtol(tar_header.dbuf.mtime , NULL, 8); stat.chksum = strtol(tar_header.dbuf.chksum , NULL, 8); stat.typeflag = tar_header.dbuf.typeflag; stat.linkname = tar_header.dbuf.linkname; strncpy(stat.magic_version, tar_header.dbuf.magic,8); strncpy(stat.uname, tar_header.dbuf.uname, 32); strncpy(stat.gname, tar_header.dbuf.gname, 32); stat.devmajor = strtol(tar_header.dbuf.devmajor , NULL, 8); stat.devminor = strtol(tar_header.dbuf.devminor , NULL, 8); if(tar_format==TAR_FORMAT_GNU){ stat.atime = strtol(tar_header.dbuf.exthead.gnu.atime , NULL, 8); stat.ctime = strtol(tar_header.dbuf.exthead.gnu.ctime , NULL, 8); stat.offset = parseOctNum(tar_header.dbuf.exthead.gnu.offset , COUNTOF(tar_header.dbuf.exthead.gnu.offset)); }else{ //POSIX int length=min(COUNTOF(tar_header.dbuf.exthead.posix.prefix),strlen(tar_header.dbuf.exthead.posix.prefix)); if(length>0){ std::string prefix(tar_header.dbuf.exthead.posix.prefix,tar_header.dbuf.exthead.posix.prefix+length); stat.filename= prefix + '/' + stat.filename; } } if(pax_atime!=0)stat.atime=pax_atime; if(pax_ctime!=0)stat.ctime=pax_ctime; if(pax_mtime!=0)stat.mtime=pax_mtime; if(stat.typeflag == DIRTYPE){ stat.mode &= ~_S_IFMT; stat.mode |= _S_IFDIR; } if((stat.mode & _S_IFMT) == _S_IFDIR){ const char * f = stat.filename.c_str(); if((char*)max(_mbsrchr((unsigned char*)f, '/'), _mbsrchr((unsigned char*)f,'\\')) != f+strlen(f)-1){ stat.filename = stat.filename + "/"; } } return true; }