home *** CD-ROM | disk | FTP | other *** search
/ DOS/V Power Report 2003 November / VPR0311.ISO / OLS / TAR32223 / tar32223.lzh / tar32_2 / src / tar32.cpp < prev    next >
C/C++ Source or Header  |  2003-01-17  |  18KB  |  583 lines

  1. /*
  2.     tar32.cpp
  3.         tar/tgz/tbz/bz/gz archive manipulation class.
  4.         by Yoshioka Tsuneo(QWF00133@nifty.ne.jp)
  5. */
  6. /*    
  7.     このファイルの利用条件:
  8.         このソースファイルの利用制限は一切ありません。
  9.         ソースの一部、全部を商用、非商用など目的に
  10.         かかわりなく他のプログラムで自由に使用できます。
  11.         パブリック・ドメイン・ソフトウェアと同様に扱えます。
  12.     
  13.     プログラマ向けの要望(制限ではありません):
  14.         ソース中に改善すべき点があればお知らせください。
  15.         ソースコード中にバグを見つけた場合は報告してください。
  16.         直した部分などありましたら教えてください。
  17.         断片的な情報でも結構です。
  18.         このファイルを利用した場合はなるべく教えてください。
  19. */
  20. /*
  21.     LICENSE of this file:
  22.         There is no restriction for using this file.
  23.         You can use this file in your software for any purpose.
  24.         In other words, you can use this file as Public Domain Software.
  25.  
  26.     RECOMMENDATION for Programmer(not restriction):
  27.         If you find points to improve code, please report me.
  28.         If you find bug in source code, please report me.
  29.         If you fixed bug, please teach me.
  30.         I want any trivial information.
  31.         If you use this file, please report me.
  32. */
  33. #include "tar.h"
  34. #include "cpio.h"
  35. #include "ar.h"
  36.  
  37. #include "tar32.h"
  38. #include "util.h"
  39. #include "tar32dll.h" // CTar32Exception
  40. #include "tar32api.h" // API ERROR codes
  41. #include <stdio.h>
  42. #include <sys/types.h>
  43. #include <sys/stat.h> 
  44. #include <mbstring.h>
  45.  
  46. #include <algorithm>
  47. #include <string>
  48. #include <memory>
  49. #include <fstream>
  50. using namespace std;
  51.  
  52. CTar32::CTar32()
  53. {
  54.     m_pfile = NULL;
  55.     m_archive_type = 0;
  56.     m_filecount = 0;
  57.     m_write_mode = false;
  58.     m_error_code = 0;
  59.     longfilenames_buf = NULL;
  60. }
  61. CTar32::~CTar32()
  62. {
  63.     close();
  64. }
  65. int CTar32::s_get_archive_type(const char *arcfile)
  66. {
  67.     auto_ptr<ITarArcFile> pfile(ITarArcFile::s_open(arcfile,"rb",ARCHIVETYPE_AUTO));
  68.     if(pfile.get()==NULL){return -1;}
  69.  
  70.     //int archive_type = ITarArcFile::s_get_archive_type();
  71.     //if(archive_type == -1){return -1;}
  72.     
  73.     // HEADER tar_header;
  74.     int ret;
  75.  
  76.     int archive_type = pfile->get_archive_type();
  77.  
  78.     union archive_header{
  79.         HEADER tar;
  80.         new_cpio_header cpio;
  81.         ar_first_hdr ar;
  82.     };
  83.     archive_header arc_header;
  84.     ret = pfile->read(&arc_header,sizeof(arc_header));
  85.     if(ret >= sizeof(arc_header.tar)
  86.         && arc_header.tar.compsum() == strtol(arc_header.tar.dbuf.chksum, NULL, 8)){
  87.         switch(archive_type){
  88.         case ARCHIVETYPE_NORMAL:
  89.             archive_type = ARCHIVETYPE_TAR;break;
  90.         case ARCHIVETYPE_GZ:
  91.             archive_type = ARCHIVETYPE_TARGZ;break;
  92.         case ARCHIVETYPE_Z:
  93.             archive_type = ARCHIVETYPE_TARZ;break;
  94.         case ARCHIVETYPE_BZ2:
  95.             archive_type = ARCHIVETYPE_TARBZ2;break;
  96.         }
  97.     }else if(ret >= sizeof(arc_header.cpio)
  98.         && arc_header.cpio.magic_check()){
  99.         switch(archive_type){
  100.         case ARCHIVETYPE_NORMAL:
  101.             archive_type = ARCHIVETYPE_CPIO;break;
  102.         case ARCHIVETYPE_GZ:
  103.             archive_type = ARCHIVETYPE_CPIOGZ;break;
  104.         case ARCHIVETYPE_Z:
  105.             archive_type = ARCHIVETYPE_CPIOZ;break;
  106.         case ARCHIVETYPE_BZ2:
  107.             archive_type = ARCHIVETYPE_CPIOBZ2;break;
  108.         }
  109.     }else if(ret >= sizeof(arc_header.ar)
  110.         && (memcmp(arc_header.ar.magic,"!<arch>\012",8) == 0  || memcmp(arc_header.ar.magic,"!<bout>\012",8) == 0)
  111.         && arc_header.ar.hdr.magic_check()){
  112.         switch(archive_type){
  113.         case ARCHIVETYPE_NORMAL:
  114.             archive_type = ARCHIVETYPE_AR;break;
  115.         case ARCHIVETYPE_GZ:
  116.             archive_type = ARCHIVETYPE_ARGZ;break;
  117.         case ARCHIVETYPE_Z:
  118.             archive_type = ARCHIVETYPE_ARZ;break;
  119.         case ARCHIVETYPE_BZ2:
  120.             archive_type = ARCHIVETYPE_ARBZ2;break;
  121.         }
  122.     }
  123.     return archive_type;
  124. }
  125. bool CTar32::open(const char *arcfile,const char *mode,int archive_type /*= ARCHIVETYPE_AUTO*/)
  126. {
  127.     m_archive_type = archive_type;
  128.     m_write_mode = (strchr(mode,'w') != NULL);
  129.     if((!strchr(mode,'w')) && archive_type == ARCHIVETYPE_AUTO){ // if read mode
  130.         m_archive_type = s_get_archive_type(arcfile);
  131.         if(m_archive_type == -1 || m_archive_type == ARCHIVETYPE_NORMAL){
  132.             return false;
  133.         }
  134.     }
  135.     m_pfile = ITarArcFile::s_open(arcfile,mode,m_archive_type);
  136.     if(!m_pfile){return false;}
  137.     return true;
  138. }
  139. bool CTar32::close()
  140. {
  141.     if(m_write_mode && m_pfile && m_error_code==0){
  142.         if(m_archive_type == ARCHIVETYPE_TAR 
  143.             || m_archive_type == ARCHIVETYPE_TARGZ 
  144.             || m_archive_type == ARCHIVETYPE_TARZ 
  145.             || m_archive_type == ARCHIVETYPE_TARBZ2){
  146.             // If success to create tar file, append 1024(512*2) byte null block to the end of file.
  147.             char buf[1024/*512 * 2*/]; memset(buf,0,sizeof(buf));
  148.             m_pfile->write(buf,sizeof(buf));
  149.         }
  150.     }
  151.     if(m_pfile){
  152.         m_pfile->close();
  153.         delete m_pfile;
  154.         m_pfile = NULL;
  155.     }
  156.     if(longfilenames_buf){
  157.         delete [] longfilenames_buf;
  158.         longfilenames_buf = NULL;
  159.     }
  160.     return true;
  161. }
  162. bool CTar32::readdir(CTar32FileStatus *pstat)
  163. {
  164.     HEADER tar_header;
  165.     int ret;
  166.     CTar32FileStatus stat;
  167.  
  168.     
  169.     if(m_archive_type == ARCHIVETYPE_TAR 
  170.         || m_archive_type == ARCHIVETYPE_TARGZ 
  171.         || m_archive_type == ARCHIVETYPE_TARZ 
  172.         || m_archive_type == ARCHIVETYPE_TARBZ2){
  173.         {
  174.             ret = m_pfile->read(&tar_header,sizeof(tar_header));
  175.             if(ret == 0){return false;}
  176.             if(ret != sizeof(tar_header)){
  177.                 throw CTar32Exception("can't read tar header",ERROR_HEADER_BROKEN);
  178.             }
  179.             HEADER zero_header;
  180.             memset(&zero_header,0,sizeof(zero_header));
  181.             if(memcmp(&tar_header,&zero_header,sizeof(tar_header)) == 0){
  182.                 return false;
  183.             }
  184.             if((unsigned long)tar_header.compsum() != (unsigned long)strtol(tar_header.dbuf.chksum , NULL, 8)){
  185.                 throw CTar32Exception("tar header checksum error.",ERROR_HEADER_CRC);
  186.             }
  187.         }
  188.         stat.filename    =    tar_header.dbuf.name;
  189.         stat.original_size        =    strtol(tar_header.dbuf.size, NULL, 8);
  190.         stat.blocksize  =   512;
  191.         if(tar_header.dbuf.typeflag == LONGLINK){    // tar_header.dbuf.name == "././@LongLink"
  192.             char longfilename[2000] = "";
  193.             int readsize = ((stat.original_size-1)/512+1)*512;
  194.             ret = m_pfile->read(longfilename, readsize);
  195.             if(ret == 0){
  196.                 throw CTar32Exception("can't get filename(LongLink)",ERROR_HEADER_BROKEN);
  197.             }
  198.             longfilename[stat.original_size]='\0';
  199.             {
  200.                 ret = m_pfile->read(&tar_header,sizeof(tar_header));
  201.                 if(ret == 0){return false;}
  202.                 if(ret != sizeof(tar_header)){
  203.                     throw CTar32Exception("can't read tar header(LongLink)",ERROR_HEADER_BROKEN);
  204.                 }
  205.                 HEADER zero_header;
  206.                 memset(&zero_header,0,sizeof(zero_header));
  207.                 if(memcmp(&tar_header,&zero_header,sizeof(tar_header)) == 0){
  208.                     return false;
  209.                 }
  210.                 if((unsigned long)tar_header.compsum() != (unsigned long)strtol(tar_header.dbuf.chksum , NULL, 8)){
  211.                     throw CTar32Exception("tar header checksum error.(LongLink)",ERROR_HEADER_CRC);
  212.                 }
  213.             }
  214.             stat.filename = longfilename;
  215.             stat.original_size        =    strtol(tar_header.dbuf.size, NULL, 8);
  216.         }
  217.         
  218.         stat.mode        =   strtol(tar_header.dbuf.mode, NULL, 8);
  219.         stat.uid        =   strtol(tar_header.dbuf.uid , NULL, 8);
  220.         stat.gid        =   strtol(tar_header.dbuf.gid , NULL, 8);
  221.         stat.mtime        =   strtol(tar_header.dbuf.mtime , NULL, 8);
  222.         stat.chksum        =   strtol(tar_header.dbuf.chksum , NULL, 8);
  223.         stat.typeflag    =   tar_header.dbuf.typeflag;
  224.         stat.linkname    =    tar_header.dbuf.linkname;
  225.         strncpy(stat.magic_version, tar_header.dbuf.magic,8);
  226.         strncpy(stat.uname, tar_header.dbuf.uname, 32);
  227.         strncpy(stat.gname, tar_header.dbuf.gname, 32);
  228.         stat.devmajor    =   strtol(tar_header.dbuf.devmajor , NULL, 8);
  229.         stat.devminor    =   strtol(tar_header.dbuf.devminor , NULL, 8);
  230.         stat.atime        =   strtol(tar_header.dbuf.atime , NULL, 8);
  231.         stat.ctime        =   strtol(tar_header.dbuf.ctime , NULL, 8);
  232.         stat.offset        =   strtol(tar_header.dbuf.offset , NULL, 8);
  233.         if(stat.typeflag == DIRTYPE){
  234.             stat.mode &= ~_S_IFMT;
  235.             stat.mode |= _S_IFDIR;
  236.         }
  237.         if((stat.mode & _S_IFMT) == _S_IFDIR){
  238.             const char * f = stat.filename.c_str();
  239.             if((char*)max(_mbsrchr((unsigned char*)f, '/'), _mbsrchr((unsigned char*)f,'\\')) != f+strlen(f)-1){
  240.                 stat.filename = stat.filename + "/";
  241.             }
  242.         }
  243.     }else if(m_archive_type == ARCHIVETYPE_CPIO
  244.         || m_archive_type == ARCHIVETYPE_CPIOGZ
  245.         || m_archive_type == ARCHIVETYPE_CPIOZ
  246.         || m_archive_type == ARCHIVETYPE_CPIOBZ2){
  247.         new_cpio_header cpio_header;
  248.         {
  249.             ret = m_pfile->read(&cpio_header,sizeof(cpio_header));
  250.             if(ret == 0){return false;}
  251.             if(ret != sizeof(cpio_header)){
  252.                 throw CTar32Exception("can't read tar header",ERROR_HEADER_BROKEN);
  253.             }
  254.             new_cpio_header zero_header;
  255.             memset(&zero_header,0,sizeof(zero_header));
  256.             if(! cpio_header.magic_check()){
  257.                 throw CTar32Exception("tar header checksum error.",ERROR_HEADER_CRC);
  258.             }
  259.         }
  260.         int fnamelen;
  261.         int dum;
  262.         int nret = sscanf(((char*)&cpio_header)+6, "%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx"
  263.             ,&dum, &stat.mode, &stat.uid, &stat.gid, &dum, &stat.mtime
  264.             ,&stat.original_size,&stat.devmajor, &stat.devminor, &dum, &dum
  265.             ,&fnamelen, &stat.chksum);
  266.         if(nret != 13){
  267.                 throw CTar32Exception("can't read tar header",ERROR_HEADER_BROKEN);
  268.         }
  269.  
  270.         if(fnamelen<=0 || fnamelen>=1000){return false;}
  271.         char fname[1000];
  272.         int fnamelen2 = (((fnamelen+sizeof(new_cpio_header) -1)/4)+1)*4 - sizeof(new_cpio_header);    /* 4 byte padding for ("new cpio header" + "filename") */
  273.         m_pfile->read(fname,fnamelen2);
  274.         stat.filename    =    fname;
  275.         stat.blocksize        = 4;
  276.         if(stat.filename == "TRAILER!!!"){
  277.             return false;
  278.         }
  279.         if((stat.mode & _S_IFMT) == _S_IFDIR){
  280.             stat.filename = stat.filename + "/";
  281.         }
  282.     }else if(m_archive_type == ARCHIVETYPE_AR
  283.         || m_archive_type == ARCHIVETYPE_ARGZ
  284.         || m_archive_type == ARCHIVETYPE_ARZ
  285.         || m_archive_type == ARCHIVETYPE_ARBZ2){
  286.         if(m_filecount == 0){
  287.             char magic[8];
  288.             ret = m_pfile->read(magic,8);    /* skip "!<arch>\012" */
  289.         }
  290.         ar_hdr header;
  291.         {
  292.             ret = m_pfile->read(&header,sizeof(header));
  293.             if(ret == 0){return false;}
  294.             if(ret != sizeof(header)){
  295.                 throw CTar32Exception("can't read tar header",ERROR_HEADER_BROKEN);
  296.             }
  297.             ar_hdr zero_header;
  298.             memset(&zero_header,0,sizeof(zero_header));
  299.             if(! header.magic_check()){
  300.                 throw CTar32Exception("tar header checksum error.",ERROR_HEADER_CRC);
  301.             }
  302.         }
  303.         char *p = strchr(header.name,' '); *p = '\0';            // cut from ' '
  304.         if(strcmp(header.name,"//")!=0 && p-1 > header.name && strrchr(header.name,'/') == p-1){ *(p-1) = '\0';}    // cut last '/'
  305.         stat.filename = header.name;
  306.         stat.mtime = strtol(header.date,NULL,10);
  307.         stat.uid = strtol(header.uid,NULL,10);
  308.         stat.gid = strtol(header.gid,NULL,10);
  309.         stat.mode = strtol(header.mode,NULL,8);
  310.         stat.original_size = strtol(header.size,NULL,10);
  311.         stat.blocksize        = 2;
  312.  
  313.         if(stat.filename == "/"){
  314.             char buf[1000];
  315.             sprintf(buf,"root%d",m_filecount);
  316.             stat.filename = buf;
  317.         }
  318.         if(stat.filename == "//"){
  319.             /* long file name support */
  320.             CTar32InternalFile file;
  321.             m_currentfile_status = stat;
  322.             if(!file.open(this)){throw CTar32Exception("can't read tar header",ERROR_HEADER_BROKEN);}
  323.             longfilenames_buf = new char[stat.original_size]; // (char*)malloc(stat.original_size);
  324.             int n = file.read(longfilenames_buf,stat.original_size);
  325.             if(n!=stat.original_size){throw CTar32Exception("can't read tar header",ERROR_HEADER_BROKEN);}
  326.             file.close();
  327.             CTar32FileStatus nextstat;
  328.             bool bRet = readdir(&nextstat); m_filecount --;
  329.             stat = nextstat;
  330.             //if(!bRet || stat.filename != "/0"){
  331.             //    throw CTar32Exception("can't read tar header",ERROR_HEADER_BROKEN);
  332.             //}
  333.             //stat.filename = longfilename;
  334.         }
  335.         {
  336.             /* if use longfilename, substitute "/\d+" to filename */
  337.             int bytes; int num;
  338.             int n = sscanf(stat.filename.c_str(), "/%d%n", &bytes, &num);
  339.             int len = stat.filename.length();
  340.             if(n == 1 && num == len && longfilenames_buf){
  341.                 stat.filename = longfilenames_buf+bytes;
  342.             }
  343.         }
  344.  
  345.     }else{
  346.         if(m_filecount != 0){return false;}
  347.         stat.filename        = m_pfile->get_orig_filename();
  348.         stat.original_size    = m_pfile->get_orig_size();
  349.         stat.mtime            = m_pfile->get_mtime();
  350.         stat.blocksize        = 1;
  351.     }
  352.     m_filecount ++;
  353.     *pstat = stat;
  354.     m_currentfile_status = stat;
  355.     return true;
  356. }
  357. bool CTar32::readskip()
  358. {
  359.     CTar32InternalFile file;
  360.     if(! file.open(this)){
  361.         return false;
  362.     }
  363.     if(! file.close()){
  364.         return false;
  365.     }
  366. #if 0
  367.     int size;
  368.     int ret;
  369.  
  370.     if(m_currentfile_status.size == 0){return true;}
  371.  
  372.     size = (((m_currentfile_status.size-1)/512)+1)*512;
  373.     ret = m_pfile->seek(size, SEEK_CUR);
  374.     if(ret == -1){return false;}
  375. #endif
  376.     return true;
  377. }
  378. bool CTar32::extract(const char *fname_extract_to)
  379. {
  380.     string fname;
  381.     if(fname_extract_to){
  382.         fname = fname_extract_to;
  383.     }else{
  384.         fname = m_currentfile_status.filename;
  385.     }
  386.     int filesize = m_currentfile_status.original_size;
  387.     const int buf_size = 4096;
  388.     char buf[buf_size];
  389.  
  390.     CTar32InternalFile file;
  391.     file.open(this);
  392.  
  393.     //string dirname = get_dirname(fname.c_str());
  394.     //mkdir_recursive(dirname.c_str());
  395.     mkdir_recursive(get_dirname(fname.c_str()).c_str());
  396.  
  397.     ofstream fs_w;
  398.     fs_w.open(fname.c_str(), ios::out|ios::binary);
  399.     if(fs_w.fail()){return false;}
  400.     //FILE *fp_w = fopen(fname.c_str(), "wb");
  401.     //if(fp_w == NULL){
  402.     //    return false;
  403.     //}
  404.     int readsize = 0;
  405.     while(readsize<filesize){
  406.         int nextreadsize = min((int)filesize-readsize,(int)sizeof(buf));
  407.         int n = file.read(buf,nextreadsize);
  408.         fs_w.write(buf,nextreadsize);
  409.         if(fs_w.fail()){return false;}
  410.         //fwrite(buf,1,ret,fp_w);
  411.         readsize += n;
  412.         if(n != nextreadsize){/*fclose(fp_w);*/return false;}
  413.     }
  414.     //fclose(fp_w);
  415.     return true;
  416. }
  417.  
  418. bool CTar32::addheader(const CTar32FileStatus &stat)
  419. {
  420.     int ret;
  421.     int blocksize = 1;
  422.     if(m_archive_type == ARCHIVETYPE_TAR 
  423.         || m_archive_type == ARCHIVETYPE_TARGZ 
  424.         || m_archive_type == ARCHIVETYPE_TARZ 
  425.         || m_archive_type == ARCHIVETYPE_TARBZ2){
  426.         blocksize = 512;
  427.         HEADER tar_header;
  428.         {
  429.             HEADER *pblock = &tar_header;
  430.             memset(pblock, 0, sizeof(*pblock));
  431.             const CTar32FileStatus *p = &stat;
  432.             string fname = p->filename;
  433.  
  434.             if(fname.length() >= sizeof(pblock->dbuf.name)/*100*/){
  435.                 CTar32FileStatus tmpstat = stat;
  436.                 tmpstat.filename = "././@LongLink";
  437.                 tmpstat.typeflag = LONGLINK;
  438.                 tmpstat.original_size = fname.length();
  439.                 bool bret = addheader(tmpstat);
  440.                 char filename[2000];
  441.                 strcpy(filename, fname.c_str());
  442.                 int writesize = ((fname.length() - 1)/512+1)*512;
  443.                 ret = m_pfile->write(filename, writesize);
  444.                 if(ret != writesize){
  445.                     throw CTar32Exception("LongLink filename write error", ERROR_CANNOT_WRITE);
  446.                 }
  447.             }
  448.             strncpy(pblock->dbuf.name, fname.c_str(),NAMSIZ-1); /* tarnt 0.96->0.97 */
  449.             sprintf(pblock->dbuf.mode, "%6o ", (unsigned int)p->mode);
  450.             sprintf(pblock->dbuf.uid, "%06o ",p->uid);
  451.             sprintf(pblock->dbuf.gid, "%06o ",p->gid);
  452.             sprintf(pblock->dbuf.size, "%11lo ", p->original_size);
  453.             sprintf(pblock->dbuf.mtime, "%11lo ", p->mtime);
  454.             pblock->dbuf.typeflag = p->typeflag;
  455.             memcpy(pblock->dbuf.magic, p->magic_version, sizeof(p->magic_version));
  456.             strncpy(pblock->dbuf.uname, p->uname, sizeof pblock->dbuf.uname);
  457.             sprintf(pblock->dbuf.chksum, "%6o ", pblock->compsum());
  458.         }
  459.  
  460.         ret = m_pfile->write(&tar_header,sizeof(tar_header));
  461.         if(ret != sizeof(tar_header)){
  462.             throw CTar32Exception("header write error", ERROR_CANNOT_WRITE);
  463.         }
  464.     }else{
  465.         ;
  466.     }
  467.     m_currentfile_status = stat;
  468.     m_currentfile_status.blocksize = blocksize;
  469.     return true;
  470. }
  471. bool CTar32::addbody(const char *file)
  472. {
  473.     struct _stat st;
  474.     if(_stat(file, &st) == -1){
  475.         char msg[1000];
  476.         sprintf(msg, "can't read file[%s]", file);
  477.         throw CTar32Exception(msg, ERROR_CANNOT_READ);
  478.     }
  479.     if(st.st_size == 0){return true;}
  480.     //FILE *fp_r;
  481.     //fp_r = fopen(file, "rb");
  482.     ifstream fs_r;
  483.     fs_r.open(file,ios::in|ios::binary);
  484.     //if(!fp_r){
  485.     if(fs_r.fail()){
  486.         throw CTar32Exception("can't read file", ERROR_CANNOT_READ);
  487.     }
  488.     int size = 0;
  489.  
  490.     int n;
  491.     char buf[4096];
  492.     //while((n = fread(buf,1,sizeof(buf),fp_r))>0){
  493.     while(fs_r.read(buf,sizeof(buf)),(n=fs_r.gcount())>0){
  494.         int m = m_pfile->write(buf, n);
  495.         if(m>0){size += m;}
  496.         if(n!=m){
  497.             throw CTar32Exception("can't write to arcfile", ERROR_CANNOT_WRITE);
  498.         }
  499.     }
  500.  
  501.     if(m_archive_type == ARCHIVETYPE_TAR 
  502.         || m_archive_type == ARCHIVETYPE_TARGZ 
  503.         || m_archive_type == ARCHIVETYPE_TARZ 
  504.         || m_archive_type == ARCHIVETYPE_TARBZ2){
  505.         /* padding 512-byte block */
  506.         int writesize;
  507.         if(size%512 == 0){
  508.             writesize = 0;
  509.         }else{
  510.             writesize = 512 - size%512;
  511.         }
  512.         memset(buf,0,writesize);
  513.         m_pfile->write(buf, writesize);
  514.     }
  515.     return true;
  516. }
  517.  
  518.  
  519.  
  520.  
  521.  
  522.  
  523.  
  524. //
  525. //  CTar32InternalFile
  526. //
  527. //
  528. CTar32InternalFile::CTar32InternalFile(){
  529.     m_pfile = NULL;
  530. }
  531. CTar32InternalFile::~CTar32InternalFile(){
  532.     if(m_pfile)close();
  533. }
  534. // open after CTar32::readdir() or CTar32()::addheader()
  535. bool CTar32InternalFile::open(CTar32 *pTar32, bool bWrite){
  536.     m_pfile = pTar32->m_pfile;
  537.     m_size = pTar32->m_currentfile_status.original_size;
  538.     m_readsize = 0;
  539.     m_blocksize = pTar32->m_currentfile_status.blocksize;
  540.     m_write = bWrite;
  541.     return true;
  542. }
  543. int  CTar32InternalFile::write(void *buf, int size){
  544.     int n = m_pfile->write(buf, size);
  545.     if(n>0){m_readsize += n;}
  546.     return n;
  547. }
  548. int  CTar32InternalFile::read(void *buf, int size){
  549.     int n = m_pfile->read(buf, m_size==-1 ? size : min(size, m_size-m_readsize));
  550.     if(n>0){m_readsize += n;}
  551.     return n;
  552. }
  553. bool CTar32InternalFile::close(){
  554.     int size;
  555.     if(m_write){
  556.         size = m_readsize;
  557.     }else{
  558.         size = m_size;
  559.     }
  560.     bool bret = true;
  561.     if(size != -1 && size!=0){
  562.         size = (((size-1)/m_blocksize)+1) * m_blocksize;
  563.         size = size - m_readsize;
  564.         if(m_write){
  565.             char buf[512];
  566.  
  567.             memset(buf,0,sizeof(buf));
  568.             while(size>0){
  569.                 int s;
  570.                 if(size>sizeof(buf)){s=sizeof(buf);}else{s=size;}
  571.                 int ret = this->write(buf, s);
  572.                 if(ret>0){size -= ret;}
  573.                 if(ret != s){bret=false;break;}
  574.             }
  575.         }else{
  576.             int ret = m_pfile->seek(size, SEEK_CUR);
  577.             bret = (ret != -1);
  578.         }
  579.     }
  580.     m_pfile = NULL;
  581.     return bret;
  582. }
  583.