1 /***************************************************************************
2 * Copyright (C) 2006-2008 Kent Gustavsson <nedo80@gmail.com>
3 ****************************************************************************/
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Library General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 // Created by: Kent Gustavsson <nedo80@gmail.com>
25 // Created on: Sun Mar 5 00:40:27 2006
28 #include "rararchive.h"
31 #include <sys/types.h>
38 RARArchive::RARArchive()
44 RARArchive::~RARArchive()
46 std::vector
<std::ifstream
*>::iterator iter
;
48 for( iter
= streams
.begin() ; iter
!= streams
.end() ; iter
++)
55 RARArchive::Init(std::string filename
)
58 stat(filename
.c_str(), &st
);
59 default_date
= st
.st_mtime
;
62 this->filename
= filename
;
66 std::string numprefix
;
69 offset
= volsuffix
.size();
70 if ( offset
<= filename
.size() &&
71 filename
.substr(filename
.size()-offset
) == volsuffix
)
73 /* Ends in ".rar"; check for "part<N>.rar" */
85 offset
= voldigits
+volsuffix
.size();
86 if ( offset
>= filename
.size() ||
87 !isdigit(filename
[filename
.size()-offset
-1]))
97 offset
= numprefix
.size() + voldigits
+ volsuffix
.size();
98 if ( offset
<= filename
.size() && filename
.substr(
99 filename
.size() - offset
, numprefix
.size()) == numprefix
)
101 offset
= volsuffix
.size()+voldigits
;
102 volprefix
= filename
.substr(0, filename
.size()-offset
);
103 firstfile
= atoi( filename
.substr(
104 filename
.size()-offset
, voldigits
).c_str() );
113 RARArchive::GetFileName(int n
)
120 if ( voldigits
== 0 )
122 /* n=0 => .rar (see above), n=1 => .r00, n=2 => .r01, etc */
124 f
<< filename
.substr(0,filename
.size()-2) << 0 << n
-1;
126 f
<< filename
.substr(0,filename
.size()-2) << n
-1;
147 RARArchive::HasFile(std::string f
)
149 if( fileblocks
.find(f
) == fileblocks
.end() )
156 RARArchive::HasFolder(std::string f
)
158 if( folderblocks
.find(f
) == folderblocks
.end() )
163 unsigned long long int
164 RARArchive::GetFileSize(std::string file
)
166 unsigned long long int size
= 0;
167 if( fileblocks
.find(file
) == fileblocks
.end() )
170 std::vector
<FileBlock
*>::iterator i
;
171 for(i
= fileblocks
[file
].begin() ; i
!= fileblocks
[file
].end() ; i
++ )
173 size
+= (*i
)->GetDataSize();
180 RARArchive::Parse(bool showcompressed
)
185 std::ifstream
*file
= new std::ifstream(GetFileName(n
++).c_str());
188 streams
.push_back(file
);
197 //for some rar files there are seeks past file end, then directly to file end
198 //which makes file->good() return true, but there is nothing to read
199 //so with file->gcount() we check if we actually read something
200 //otherwise we use old bufer and crash somewhere
201 if(file
->gcount()==0)
204 file
->seekg (-3, std::ios::cur
);
211 blocks
.push_back( new MarkerBlock(*file
) );
214 blocks
.push_back( new ArchiveBlock(*file
) );
218 f
= new FileBlock(*file
);
220 if ( showcompressed
|| !f
->isCompressed() )
223 folderblocks
[f
->GetFileName()].push_back(f
);
226 fileblocks
[f
->GetFileName()].push_back(f
);
228 for ( int pos
= 0 ; ( pos
= f
->GetFileName().find("\\", pos
) ) != std::string::npos
; pos
++)
230 if( folderblocks
.find(f
->GetFileName().substr(0,pos
)) == folderblocks
.end())
231 folderblocks
[f
->GetFileName().substr(0,pos
)].push_back(NULL
);
236 blocks
.push_back( f
);
240 blocks
.push_back( new RARBlock(*file
) );
243 if ( buf
[2] == 0 || buf
[2] == 0x7B || buf
[2] == 0x78 )
256 RARArchive::Read(const char *path
, char *buf
, size_t size
, off_t offset
)
258 unsigned int pos
= 0;
259 if ( fileblocks
.find(path
) == fileblocks
.end() )
263 std::vector
<FileBlock
*>::iterator i
;
264 for(i
= fileblocks
[path
].begin() ; i
!= fileblocks
[path
].end() ; i
++ )
266 if ( (*i
)->GetDataSize() > offset
)
268 unsigned int len
= (*i
)->GetData(buf
+ pos
, offset
, size
);
275 offset
-= (*i
)->GetDataSize();
281 std::vector
< std::string
>
282 RARArchive::GetFolders()
284 std::vector
<std::string
> retdata
;
286 std::map
<std::string
, std::vector
<FileBlock
*> >::iterator iter
;
288 for( iter
= folderblocks
.begin() ; iter
!= folderblocks
.end() ; iter
++)
289 retdata
.push_back(iter
->first
);
295 std::vector
< std::string
>
296 RARArchive::GetFiles()
298 std::vector
<std::string
> retdata
;
299 std::map
<std::string
, std::vector
<FileBlock
* > >::iterator iter
;
301 for( iter
= fileblocks
.begin() ; iter
!= fileblocks
.end() ; iter
++)
303 retdata
.push_back(iter
->first
);
310 RARArchive::PrintFiles()
314 std::map
<std::string
, std::vector
<FileBlock
* > >::iterator iter
;
316 for( iter
= fileblocks
.begin() ; iter
!= fileblocks
.end() ; iter
++)
318 unsigned long long int s
= 0;
319 std::vector
<FileBlock
*>::iterator i
;
320 for(i
= iter
->second
.begin() ; i
!= iter
->second
.end() ; i
++ )
322 s
+= (*i
)->GetDataSize();
325 std::cout
<< iter
->first
<< " blocks: " << iter
->second
.size() << " size: " << s
<< std::endl
;
330 RARArchive::GetDate(std::string file
, struct timespec
* tp
)
332 if( fileblocks
.find(file
) == fileblocks
.end() )
334 tp
->tv_sec
= default_date
;
339 std::vector
<FileBlock
*>::iterator i
;
340 i
= fileblocks
[file
].begin();
341 (*i
)->GetFileDate(tp
);
345 RARArchive::PrintFolders()
347 std::map
<std::string
, std::vector
<FileBlock
* > >::iterator iter
;
349 for( iter
= folderblocks
.begin() ; iter
!= folderblocks
.end() ; iter
++)
351 unsigned long long int s
= 0;
352 std::vector
<FileBlock
*>::iterator i
;
353 for(i
= iter
->second
.begin() ; i
!= iter
->second
.end() ; i
++ )
354 s
+= (*i
)->GetDataSize();
356 std::cout
<< iter
->first
<< " blocks: " << iter
->second
.size() << " size: " << s
<< std::endl
;