45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
-
+
-
+
-
+
-
+
-
+
-
+
-
-
+
+
|
if (value > max)
@throw [OFOutOfRangeException exception];
return value;
}
@implementation OFTarArchiveEntry
@synthesize name = _name, mode = _mode, size = _size;
@synthesize fileName = _fileName, mode = _mode, size = _size;
@synthesize modificationDate = _modificationDate, type = _type;
@synthesize targetName = _targetName;
@synthesize targetFileName = _targetFileName;
- (instancetype)OF_initWithHeader: (char[512])header
stream: (OFStream*)stream
{
self = [super init];
@try {
void *pool = objc_autoreleasePoolPush();
_stream = [stream retain];
_name = [stringFromBuffer(header, 100) copy];
_fileName = [stringFromBuffer(header, 100) copy];
_mode = (uint32_t)octalValueFromBuffer(
header + 100, 8, UINT32_MAX);
_size = _toRead = (size_t)octalValueFromBuffer(
header + 124, 12, UINT64_MAX);
_modificationDate = [[OFDate alloc]
initWithTimeIntervalSince1970:
(of_time_interval_t)octalValueFromBuffer(
header + 136, 12, UINTMAX_MAX)];
_type = header[156];
_targetName = [stringFromBuffer(header + 157, 100) copy];
_targetFileName = [stringFromBuffer(header + 157, 100) copy];
if (_type == '\0')
_type = OF_TAR_ARCHIVE_ENTRY_TYPE_FILE;
objc_autoreleasePoolPop(pool);
} @catch (id e) {
[self release];
@throw e;
}
return self;
}
- (void)dealloc
{
[_stream release];
[_name release];
[_fileName release];
[_modificationDate release];
[_targetName release];
[_targetFileName release];
[super dealloc];
}
- (size_t)lowlevelReadIntoBuffer: (void*)buffer
length: (size_t)length
{
size_t ret;
if (_atEndOfStream)
@throw [OFReadFailedException exceptionWithObject: self
requestedLength: length];
if ((uint64_t)length > _toRead)
length = (size_t)_toRead;
ret = [_stream readIntoBuffer: buffer
length: length];
_toRead -= ret;
if (ret == 0)
_atEndOfStream = true;
_toRead -= ret;
return ret;
}
- (bool)lowlevelIsAtEndOfStream
{
return _atEndOfStream;
|