2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU Library General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 // Created by: Kent Gustavsson <nedo80@gmail.com>
22 // Created on: Mon Mar 6 21:41:03 2006
25 #include "fileblock.h"
30 /* MS-DOS time/date conversion routines derived from: */
33 * linux/fs/msdos/misc.c
35 * Written 1992,1993 by Werner Almesberger
38 /* Convert a MS-DOS time/date pair (unspecified local time zones) to a UNIX
41 time_t date_dos2unix(unsigned short time
,unsigned short date
)
44 tm
.tm_year
= 1980 + (date
>> 9) - 1900,
45 tm
.tm_mon
= ((date
>> 5) & 15) - 1,
46 tm
.tm_mday
= date
& 31,
47 tm
.tm_hour
= time
>> 11,
48 tm
.tm_min
= (time
>> 5) & 63,
49 tm
.tm_sec
= (time
& 31)*2,
50 tm
.tm_isdst
= -1; /* unknown; mktime will guess */
54 FileBlock::FileBlock(std::istream
&in
) : RARBlock(in
),
57 unsigned int end
= in
.tellg();
58 start
= end
- size
- headsize
;
60 in
.seekg(end
+ 20-size
-headsize
);
64 time
+= in
.get() *256;
66 date
+= in
.get() *256;
67 filedate
.tv_sec
=date_dos2unix(time
,date
);
69 in
.seekg(end
+ 25-size
-headsize
);
76 unsigned int filenamesize
= in
.get();
77 filenamesize
+= in
.get() * 256;
79 in
.seekg(4, std::ios::cur
);
80 char m
[filenamesize
+1];
84 unsigned long high_pack_size
= in
.get();
85 high_pack_size
|= in
.get() << 8;
86 high_pack_size
|= in
.get() << 16;
87 high_pack_size
|= in
.get() << 24;
90 std::cerr
<< "Packed file size >= 4 GiB not "
91 "implemented" << std::endl
;
94 in
.seekg(4, std::ios::cur
);
97 in
.read(m
, filenamesize
);
101 if ( flags
& 0x0400 ) /* Salt field present */
103 in
.seekg(min(in
.tellg() + std::streamoff(8),
104 std::streampos(start
+ headsize
)));
107 /* Extended time stamp field present */
108 if ( flags
& 0x1000 &&
109 in
.tellg() + std::streamoff(2) <= start
+ headsize
)
116 if ( ( flags
& 0xE0 ) == 0xE0 )
122 /* Derived from _parse_ext_time function in "rarfile" Python module.
123 http://rarfile.berlios.de/ */
125 FileBlock::ParseXtime()
127 unsigned int flags
= in
.get();
128 flags
+= in
.get() * 256;
132 unsigned int field_flags
= flags
>> field
* 4 & 0xF;
134 unsigned long frac
= 0; /* 100 ns units; 24 bits */
135 if ( field_flags
& 8 ) /* mtime field present */
137 filedate
.tv_sec
+= field_flags
>> 2 & 1;
139 for ( unsigned int i
= 0; i
< (field_flags
& 3); ++i
)
142 frac
+= in
.get() << 16;
145 filedate
.tv_nsec
= frac
* 100;
147 /* Not interested in the three other time fields */
151 field_flags
= flags
>> field
* 4 & 0xF;
152 if ( 0 != (field_flags
& 8) )
154 in
.seekg(field_flags
& 3, std::ios::cur
);
160 FileBlock::GetFileDate(struct timespec
* tp
)
162 tp
->tv_sec
= filedate
.tv_sec
;
163 tp
->tv_nsec
= filedate
.tv_nsec
;
166 FileBlock::~FileBlock()
172 FileBlock::isFolder()
178 FileBlock::isCompressed()
184 FileBlock::GetDataSize()
190 FileBlock::GetFileName()
196 FileBlock::GetData(char *buf
, unsigned int offset
, unsigned int len
)
198 std::streampos old
= in
.tellg();
200 in
.seekg(start
+ headsize
+ offset
);
202 if ( offset
> size
|| !len
)
204 if ( offset
+ len
> size
)