📄 btfiles.cpp
字号:
if( stat(pathname, &sb) < 0 ){ CONSOLE.Warning(1, "error, stat file \"%s\" failed: %s", pathname, strerror(errno)); return -1; } if( S_IFREG & sb.st_mode ){ pbf = _new_bfnode();#ifndef WINDOWS if( !pbf ) return -1;#endif pbf->bf_length = m_total_files_length = sb.st_size; pbf->bf_filename = new char[strlen(pathname) + 1];#ifndef WINDOWS if( !pbf->bf_filename ) return -1;#endif strcpy(pbf->bf_filename, pathname); m_btfhead = pbf; }else if( S_IFDIR & sb.st_mode ){ char wd[MAXPATHLEN]; if( !getcwd(wd,MAXPATHLEN) ) return -1; m_directory = new char[strlen(pathname) + 1];#ifndef WINDOWS if( !m_directory ) return -1;#endif strcpy(m_directory, pathname); if(chdir(m_directory) < 0){ CONSOLE.Warning(1, "error, change work directory to \"%s\" failed: %s", m_directory, strerror(errno)); return -1; } if(_btf_recurses_directory((const char*)0, &lastnode) < 0) return -1; if( chdir(wd) < 0) return -1; }else{ CONSOLE.Warning(1, "error, \"%s\" is not a directory or regular file.", pathname); return -1; } return 0;}int btFiles::BuildFromMI(const char *metabuf, const size_t metabuf_len, const char *saveas){ char path[MAXPATHLEN]; const char *s, *p; size_t r,q,n; int64_t t; int f_warned = 0; if( !decode_query(metabuf, metabuf_len, "info|name", &s, &q, (int64_t*)0, QUERY_STR) || MAXPATHLEN <= q ) return -1; memcpy(path, s, q); path[q] = '\0'; r = decode_query(metabuf, metabuf_len, "info|files", (const char**)0, &q, (int64_t*)0, QUERY_POS); if( r ){ BTFILE *pbf_last = (BTFILE*) 0; BTFILE *pbf = (BTFILE*) 0; size_t dl; if( decode_query(metabuf,metabuf_len,"info|length", (const char**) 0,(size_t*) 0,(int64_t*) 0,QUERY_LONG) ) return -1; if( saveas ){ m_directory = new char[strlen(saveas) + 1];#ifndef WINDOWS if(!m_directory) return -1;#endif strcpy(m_directory,saveas); }else{ int f_conv; char *tmpfn = new char[strlen(path)*2+5];#ifndef WINDOWS if( !tmpfn ) return -1;#endif if( f_conv = ConvertFilename(tmpfn, path, strlen(path)*2+5) ){ if( arg_flg_convert_filenames ){ m_directory = new char[strlen(tmpfn) + 1];#ifndef WINDOWS if( !m_directory ){ delete []tmpfn; return -1; }#endif strcpy(m_directory,tmpfn); }else{ CONSOLE.Warning(3, "Dir name contains non-printable characters; use -T to convert."); f_warned = 1; } } delete []tmpfn; if( !f_conv || !arg_flg_convert_filenames ){ m_directory = new char[strlen(path) + 1];#ifndef WINDOWS if( !m_directory ) return -1;#endif strcpy(m_directory,path); } } /* now r saved the pos of files list. q saved list length */ p = metabuf + r + 1; q--; for(; q && 'e' != *p; p += dl, q -= dl){ if(!(dl = decode_dict(p, q, (const char*) 0)) ) return -1; if( !decode_query(p, dl, "length", (const char**) 0, (size_t*) 0,&t,QUERY_LONG) ) return -1; pbf = _new_bfnode();#ifndef WINDOWS if( !pbf ) return -1;#endif pbf->bf_length = t; m_total_files_length += t; r = decode_query(p, dl, "path", (const char **)0, &n, (int64_t*)0, QUERY_POS); if( !r ) return -1; if(!decode_list2path(p + r, n, path)) return -1; int f_conv; char *tmpfn = new char[strlen(path)*2+5];#ifndef WINDOWS if( !tmpfn ) return -1;#endif if( f_conv = ConvertFilename(tmpfn, path, strlen(path)*2+5) ){ if( arg_flg_convert_filenames ){ pbf->bf_filename = new char[strlen(tmpfn) + 1];#ifndef WINDOWS if( !pbf->bf_filename ){ delete []tmpfn; return -1; }#endif strcpy(pbf->bf_filename, tmpfn); }else if(!f_warned){ CONSOLE.Warning(3, "Filename contains non-printable characters; use -T to convert."); f_warned = 1; } } delete []tmpfn; if( !f_conv || !arg_flg_convert_filenames ){ pbf->bf_filename = new char[strlen(path) + 1];#ifndef WINDOWS if( !pbf->bf_filename ) return -1;#endif strcpy(pbf->bf_filename, path); } if(pbf_last) pbf_last->bf_next = pbf; else m_btfhead = pbf; pbf_last = pbf; } }else{ if( !decode_query(metabuf,metabuf_len,"info|length", (const char**) 0,(size_t*) 0,&t,QUERY_LONG) ) return -1; m_btfhead = _new_bfnode();#ifndef WINDOWS if( !m_btfhead) return -1;#endif m_btfhead->bf_length = m_total_files_length = t; if( saveas ){ m_btfhead->bf_filename = new char[strlen(saveas) + 1];#ifndef WINDOWS if(!m_btfhead->bf_filename ) return -1;#endif strcpy(m_btfhead->bf_filename, saveas); }else if( arg_flg_convert_filenames ){ char *tmpfn = new char[strlen(path)*2+5];#ifndef WINDOWS if( !tmpfn ) return -1;#endif ConvertFilename(tmpfn, path, strlen(path)*2+5); m_btfhead->bf_filename = new char[strlen(tmpfn) + 1];#ifndef WINDOWS if( !m_btfhead->bf_filename ){ delete []tmpfn; return -1; }#endif strcpy(m_btfhead->bf_filename, tmpfn); delete []tmpfn; }else{ m_btfhead->bf_filename = new char[strlen(path) + 1];#ifndef WINDOWS if(!m_btfhead->bf_filename ) return -1;#endif strcpy(m_btfhead->bf_filename, path); } } return 0;}int btFiles::CreateFiles(){ int check_exist = 0; char fn[MAXPATHLEN]; BTFILE *pbt = m_btfhead; struct stat sb; int i = 0; for(; pbt; pbt = pbt->bf_next){ m_nfiles++; if( m_directory ){ if( MAXPATHLEN <= snprintf(fn, MAXPATHLEN, "%s%c%s", m_directory, PATH_SP, pbt->bf_filename) ){ errno = ENAMETOOLONG; return -1; } }else{ strcpy(fn, pbt->bf_filename); } if(stat(fn, &sb) < 0){ if(ENOENT == errno){ CONSOLE.Interact_n(""); CONSOLE.Interact_n("Creating file \"%s\"", fn); if( !_btf_creat_by_path(fn,pbt->bf_length)){ CONSOLE.Warning(1, "error, create file \"%s\" failed: %s", fn, strerror(errno)); return -1; } }else{ CONSOLE.Warning(1, "error, couldn't create file \"%s\": %s", fn, strerror(errno)); return -1; } }else{ if( !check_exist) check_exist = 1; if( !(S_IFREG & sb.st_mode) ){ CONSOLE.Warning(1, "error, file \"%s\" is not a regular file.", fn); return -1; } if(sb.st_size != pbt->bf_length){ CONSOLE.Warning(1,"error, file \"%s\" size doesn't match; must be %llu", fn, (unsigned long long)(pbt->bf_length)); return -1; } } } //end for m_file = new BTFILE *[m_nfiles]; if( !m_file ){ CONSOLE.Warning(1, "error, failed to allocate memory for files list"); return -1; } for( pbt = m_btfhead; pbt; pbt = pbt->bf_next ){ m_file[i++] = pbt; } return check_exist;}void btFiles::PrintOut(){ BTFILE *p = m_btfhead; size_t id = 0; CONSOLE.Print(""); CONSOLE.Print("FILES INFO"); BitField tmpBitField, tmpFilter; if(m_directory) CONSOLE.Print("Directory: %s", m_directory); for( ; p ; p = p->bf_next ){ ++id; CONSOLE.Print_n(""); CONSOLE.Print_n("<%d> %s%s [%llu]", (int)id, m_directory ? " " : "", p->bf_filename, (unsigned long long)(p->bf_length)); if( !arg_flg_exam_only ){ BTCONTENT.SetTmpFilter(id, &tmpFilter); tmpBitField = *BTCONTENT.pBF; tmpBitField.Except(tmpFilter); CONSOLE.Print_n(" %d/%d (%d%%)", (int)(tmpBitField.Count()), (int)(GetFilePieces(id)), GetFilePieces(id) ? (100 * tmpBitField.Count() / GetFilePieces(id)) : 100); } } CONSOLE.Print("Total: %lu MB", (unsigned long)(m_total_files_length/1024/1024));}size_t btFiles::FillMetaInfo(FILE* fp){ BTFILE *p; if( m_directory ){ // multi files if( bencode_str("files", fp) != 1 ) return 0; if( bencode_begin_list(fp) != 1) return 0; for( p = m_btfhead; p; p = p->bf_next){ if( bencode_begin_dict(fp) != 1) return 0; if( bencode_str("length", fp) != 1 ) return 0; if( bencode_int(p->bf_length, fp) != 1) return 0; if( bencode_str("path", fp) != 1) return 0; if( bencode_path2list(p->bf_filename, fp) != 1 ) return 0; if( bencode_end_dict_list(fp) != 1) return 0; } if(bencode_end_dict_list(fp) != 1 ) return 0; if(bencode_str("name", fp) != 1) return 0; return bencode_str(m_directory, fp); }else{ if( bencode_str("length", fp) != 1 ) return 0; if( bencode_int(m_btfhead->bf_length, fp) != 1) return 0; if( bencode_str("name", fp) != 1 ) return 0; return bencode_str(m_btfhead->bf_filename, fp); } return 1;}void btFiles::SetFilter(int nfile, BitField *pFilter, size_t pieceLength){ BTFILE *p = m_btfhead; size_t id = 0; uint64_t sizeBuffer=0; size_t index; if( nfile==0 || nfile>m_nfiles ){ pFilter->Clear(); return; } pFilter->SetAll(); for( ; p ; p = p->bf_next ){ if(++id == nfile){ if( 0 == p->bf_length ){ p->bf_npieces = 0; return; } size_t start, stop; start = sizeBuffer / pieceLength; stop = (sizeBuffer + p->bf_length) / pieceLength; // calculation is off if file ends on a piece boundary if(stop > start && 0 == (sizeBuffer + p->bf_length) % pieceLength) --stop; p->bf_npieces = stop - start + 1; for(index = start; index <= stop; index++) { pFilter->UnSet(index); } break; } sizeBuffer += p->bf_length; }}char *btFiles::GetFileName(size_t nfile) const{ if( nfile && nfile <= m_nfiles ) return m_file[nfile-1]->bf_filename; return (char *)0;}uint64_t btFiles::GetFileSize(size_t nfile) const{ if( nfile && nfile <= m_nfiles ) return m_file[nfile-1]->bf_length; return 0;}size_t btFiles::GetFilePieces(size_t nfile) const{ //returns the number of pieces in the file if( nfile && nfile <= m_nfiles ) return m_file[nfile-1]->bf_npieces; return 0;}int btFiles::ConvertFilename(char *dst, const char *src, int size){ int retval=0, i, j, f_print=0, f_punct=0; for(i=j=0; src[i] != '\0' && j < size-2; i++){ if( isprint(src[i]) ){ if( ispunct(src[i]) ) f_punct = 1; else f_punct = 0; if(j && !f_print && !f_punct){ sprintf(dst+j, "_"); j++; } dst[j++] = src[i]; f_print = 1; }else{ if(f_print && !f_punct){ sprintf(dst+j, "_"); j++; } snprintf(dst+j, 3, "%.2X", (unsigned char)(src[i])); j += 2; f_print = f_punct = 0; if( !retval ) retval = 1; } } dst[j] = '\0'; return retval;}char *btFiles::GetDataName() const{ return m_directory ? m_directory : m_btfhead->bf_filename;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -