Skip to content

Commit b898504

Browse files
committed
add ability to extract resource fork
1 parent d891b7e commit b898504

File tree

5 files changed

+82
-17
lines changed

5 files changed

+82
-17
lines changed

orbisFSTool/OrbisFSFile.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ uint8_t *OrbisFSFile::getDataForOffset(uint64_t offset){
9393
}
9494

9595
#pragma mark OrbisFSFile public
96+
#pragma mark IO operations
9697
uint64_t OrbisFSFile::size(){
9798
return _node->filesize;
9899
}
@@ -126,3 +127,37 @@ size_t OrbisFSFile::pread(void *buf, size_t len, uint64_t offset){
126127
size_t OrbisFSFile::pwrite(const void *buf, size_t len, uint64_t offset){
127128
reterror("TODO");
128129
}
130+
131+
#pragma mark resource IO
132+
uint64_t OrbisFSFile::resource_size(){
133+
/*
134+
This is wrong, but idk how to get the actual size :(
135+
*/
136+
uint64_t ret = 0;
137+
for (int i=0; i<ARRAYOF(_node->resourceLnk); i++) {
138+
if (_node->resourceLnk[i].type != ORBIS_FS_CHAINLINK_TYPE_LINK) break;
139+
ret += _blockSize;
140+
}
141+
return ret;
142+
}
143+
144+
size_t OrbisFSFile::resource_pread(void *buf, size_t len, uint64_t offset){
145+
size_t rs = resource_size();
146+
147+
if (offset >= rs) return 0;
148+
if (offset + len > rs) len = rs - offset;
149+
if (!len) return 0;
150+
151+
uint32_t resouceBlockIdx = (uint32_t)(offset / _blockSize);
152+
uint32_t resouceBlockOffset = offset & (_blockSize-1); //expected to be a power of 2
153+
154+
retassure(resouceBlockIdx < ARRAYOF(_node->resourceLnk), "resouceBlockIdx is out of bounds");
155+
156+
OrbisFSChainLink_t *rl = &_node->resourceLnk[resouceBlockIdx];
157+
retassure(rl->type == ORBIS_FS_CHAINLINK_TYPE_LINK, "tgt resouce chain link has bad type 0x%02x",rl->type);
158+
159+
uint8_t *block = _parent->getBlock(rl->blk);
160+
memcpy(buf, &block[resouceBlockOffset], len);
161+
return len;
162+
}
163+

orbisFSTool/OrbisFSFile.hpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,19 @@ class OrbisFSFile {
3131
OrbisFSFile(OrbisFSImage *parent, OrbisFSInode_t *node, bool noFilemodeChecks = false);
3232
~OrbisFSFile();
3333

34-
#pragma IO operations
34+
#pragma mark IO operations
3535
uint64_t size();
3636
size_t read(void *buf, size_t len);
3737
size_t write(const void *buf, size_t len);
3838

3939
size_t pread(void *buf, size_t len, uint64_t offset);
4040
size_t pwrite(const void *buf, size_t len, uint64_t offset);
4141

42+
#pragma mark resource IO
43+
uint64_t resource_size();
44+
size_t resource_pread(void *buf, size_t len, uint64_t offset);
45+
46+
4247
#pragma mark friends
4348
friend OrbisFSInodeDirectory;
4449
};

orbisFSTool/OrbisFSFormat.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,9 @@ typedef struct {
9393
uint64_t _pad3; //should be zero
9494
uint64_t modOrAccessData;
9595
uint64_t _pad4; //should be zero
96-
OrbisFSChainLink_t resourceLnkMaybe;
97-
uint32_t unk13;
98-
uint64_t unk14;
99-
OrbisFSChainLink_t dataLnk[0x20];
96+
OrbisFSChainLink_t resourceLnk[4];
97+
OrbisFSChainLink_t dataLnk[4];
98+
uint8_t _pad5[0x70];
10099
} ATTRIBUTE_PACKED OrbisFSInode_t;
101100

102101
typedef struct {

orbisFSTool/OrbisFSInodeDirectory.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ OrbisFSInode_t *OrbisFSInodeDirectory::findInode(uint32_t inodeNum){
127127
retassure(memvcmp(&ret->_pad2, sizeof(ret->_pad2), 0x00), "inode %d entry _pad2 is not zero",inodeNum);
128128
retassure(memvcmp(&ret->_pad3, sizeof(ret->_pad3), 0x00), "inode %d entry _pad3 is not zero",inodeNum);
129129
retassure(memvcmp(&ret->_pad4, sizeof(ret->_pad4), 0x00), "inode %d entry _pad4 is not zero",inodeNum);
130+
retassure(memvcmp(&ret->_pad5, sizeof(ret->_pad5), 0x00), "inode %d entry _pad5 is not zero",inodeNum);
130131
return ret;
131132
}
132133

orbisFSTool/main.cpp

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ static struct option longopts[] = {
3636
{ "verbose", no_argument, NULL, 'v' },
3737
{ "writeable", no_argument, NULL, 'w' },
3838

39+
{ "extract-resource", no_argument, NULL, 0 },
3940
{ "inode", required_argument, NULL, 0 },
4041
{ "mount", required_argument, NULL, 0 },
4142
{ "offset", required_argument, NULL, 0 },
@@ -58,6 +59,7 @@ void cmd_help(){
5859
" -r, --recursive\t\tperform operation recursively\n"
5960
" -v, --verbose\t\t\tincrease logging output\n"
6061
" -w, --writeable\t\topen image in write mode\n"
62+
" --extract-resource\textract file resource instead of file contents\n"
6163
" --inode <num>\t\tspecify file by Inode instead of path\n"
6264
" --mount <path>\t\tpath to mount\n"
6365
" --offset <cnt>\t\toffset inside image\n"
@@ -127,6 +129,7 @@ int main_r(int argc, const char * argv[]) {
127129

128130
bool doList = false;
129131
bool doExtract = false;
132+
bool doExtractResource = false;
130133

131134
bool dumpInode = false;
132135

@@ -136,7 +139,9 @@ int main_r(int argc, const char * argv[]) {
136139
{
137140
std::string curopt = longopts[optindex].name;
138141

139-
if (curopt == "inode") {
142+
if (curopt == "extract-resource") {
143+
doExtractResource = true;
144+
}else if (curopt == "inode"){
140145
iNode = atoi(optarg);
141146
}else if (curopt == "mount"){
142147
mountPath = optarg;
@@ -229,18 +234,35 @@ int main_r(int argc, const char * argv[]) {
229234
size_t bufSize = img->getBlocksize();
230235

231236
auto f = img->openFilAtPath(imagePath);
232-
uint64_t size = f->size();
233-
if (bufSize > size) bufSize = size;
234-
assure(buf = (uint8_t*)calloc(1, bufSize));
237+
235238
retassure((fd = open(outfile, O_CREAT | O_WRONLY, 0644)) != -1, "Failed to create output file '%s' errno=%d (%s)",outfile,errno,strerror(errno));
236-
237-
while (size) {
238-
size_t didread = 0;
239-
retassure(didread = f->read(buf, bufSize), "Failed to read file");
240-
retassure(write(fd, buf, bufSize) == bufSize, "Failed to write data to file '%s'",outfile);
241-
size -= didread;
239+
240+
uint64_t size = doExtractResource ? f->resource_size() : f->size();
241+
if (size) {
242+
if (bufSize > size) bufSize = size;
243+
assure(buf = (uint8_t*)calloc(1, bufSize));
244+
245+
246+
if (doExtractResource){
247+
uint64_t offset = 0;
248+
while (size) {
249+
size_t didread = 0;
250+
retassure(didread = f->resource_pread(buf, bufSize, offset), "Failed to pread file resource");
251+
retassure(write(fd, buf, bufSize) == bufSize, "Failed to write data to file '%s'",outfile);
252+
offset += didread;
253+
size -= didread;
254+
}
255+
info("Extracted resource of '%s' to '%s'",imagePath.c_str(),outfile);
256+
}else{
257+
while (size) {
258+
size_t didread = 0;
259+
retassure(didread = f->read(buf, bufSize), "Failed to read file");
260+
retassure(write(fd, buf, bufSize) == bufSize, "Failed to write data to file '%s'",outfile);
261+
size -= didread;
262+
}
263+
info("Extracted '%s' to '%s'",imagePath.c_str(),outfile);
264+
}
242265
}
243-
info("Extracted '%s' to '%s'",imagePath.c_str(),outfile);
244266
} else if (doList) {
245267
if (!imagePath.size()) imagePath = "/";
246268
img->iterateOverFilesInFolder(imagePath, recursive, [&](std::string path, OrbisFSInode_t node){
@@ -299,7 +321,10 @@ int main_r(int argc, const char * argv[]) {
299321
printf("\tcreateDate : %10lld (%s)\n",node.createDate,strForDate(node.createDate).c_str());
300322
printf("\taccessOrModDate : %10lld (%s)\n",node.accessOrModDate,strForDate(node.accessOrModDate).c_str());
301323
printf("\tmodOrAccessData : %10lld (%s)\n",node.modOrAccessData,strForDate(node.modOrAccessData).c_str());
302-
printf("\tresourceLnkMaybe : type: 0x%02x blk: %d\n",node.resourceLnkMaybe.type,node.resourceLnkMaybe.blk);
324+
for (int i=0; i<ARRAYOF(node.resourceLnk); i++) {
325+
if (node.resourceLnk[i].type != ORBIS_FS_CHAINLINK_TYPE_LINK) break;
326+
printf("\tresourceLnk[%2d] : type: 0x%02x blk: %d\n",i,node.resourceLnk[i].type,node.resourceLnk[i].blk);
327+
}
303328
for (int i=0; i<ARRAYOF(node.dataLnk); i++) {
304329
if (node.dataLnk[i].type != ORBIS_FS_CHAINLINK_TYPE_LINK) break;
305330
printf("\tdataLnk[%2d] : type: 0x%02x blk: %d\n",i,node.dataLnk[i].type,node.dataLnk[i].blk);

0 commit comments

Comments
 (0)