2022-08-10 15:55:50 +03:00
/ *
2022-08-10 20:20:10 +03:00
* Copyright 2019 - 2022 Dmitry Isaenko
2022-08-10 15:55:50 +03:00
*
2022-08-10 20:20:10 +03:00
* This file is part of libKonogonka .
2022-08-10 15:55:50 +03:00
*
2022-08-10 20:20:10 +03:00
* libKonogonka is free software : you can redistribute it and / or modify
2022-08-10 15:55:50 +03:00
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
2022-08-10 20:20:10 +03:00
* libKonogonka is distributed in the hope that it will be useful ,
2022-08-10 15:55:50 +03:00
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
2022-08-10 20:20:10 +03:00
* along with libKonogonka . If not , see < https : //www.gnu.org/licenses/>.
2022-08-10 15:55:50 +03:00
* /
package libKonogonka.Tools.RomFs ;
2022-09-05 00:39:48 +03:00
import libKonogonka.Converter ;
import libKonogonka.Tools.RomFs.view.FileSystemTreeViewMaker ;
import org.apache.logging.log4j.LogManager ;
import org.apache.logging.log4j.Logger ;
2022-08-10 15:55:50 +03:00
import java.nio.charset.StandardCharsets ;
import java.util.ArrayList ;
import java.util.Arrays ;
import java.util.Comparator ;
import java.util.List ;
public class FileSystemEntry {
2022-12-07 04:22:23 +03:00
private final static Logger log = LogManager . getLogger ( FileSystemEntry . class ) ;
2022-09-05 00:39:48 +03:00
2022-08-10 15:55:50 +03:00
private boolean directoryFlag ;
private String name ;
2022-09-05 00:39:48 +03:00
private final List < FileSystemEntry > content ;
2022-08-10 15:55:50 +03:00
private static byte [ ] dirsMetadataTable ;
private static byte [ ] filesMetadataTable ;
2022-09-11 05:14:37 +03:00
private long offset ;
private long size ;
2022-08-10 15:55:50 +03:00
public FileSystemEntry ( byte [ ] dirsMetadataTable , byte [ ] filesMetadataTable ) throws Exception {
FileSystemEntry . dirsMetadataTable = dirsMetadataTable ;
FileSystemEntry . filesMetadataTable = filesMetadataTable ;
this . content = new ArrayList < > ( ) ;
this . directoryFlag = true ;
DirectoryMetaData rootDirectoryMetaData = new DirectoryMetaData ( ) ;
if ( rootDirectoryMetaData . dirName . isEmpty ( ) )
this . name = "ROOT" ;
else
this . name = rootDirectoryMetaData . dirName ;
if ( rootDirectoryMetaData . parentDirectoryOffset ! = 0 )
throw new Exception ( "Offset of Parent Directory is incorrect. Expected 0 for root, received value is " + rootDirectoryMetaData . parentDirectoryOffset ) ;
if ( rootDirectoryMetaData . nextSiblingDirectoryOffset ! = - 1 )
throw new Exception ( "Offset of next Sibling Directory is incorrect. Expected -1 for root, received value is " + rootDirectoryMetaData . nextSiblingDirectoryOffset ) ;
if ( rootDirectoryMetaData . firstSubdirectoryOffset ! = - 1 )
content . add ( getDirectory ( rootDirectoryMetaData . firstSubdirectoryOffset ) ) ;
if ( rootDirectoryMetaData . firstFileOffset ! = - 1 )
content . add ( getFile ( this , rootDirectoryMetaData . firstFileOffset ) ) ;
2022-09-11 05:14:37 +03:00
content . sort ( Comparator . comparingLong ( FileSystemEntry : : getOffset ) ) ;
2022-08-10 15:55:50 +03:00
}
private FileSystemEntry ( ) {
this . content = new ArrayList < > ( ) ;
}
private FileSystemEntry getDirectory ( int childDirMetaPosition ) {
FileSystemEntry fileSystemEntry = new FileSystemEntry ( ) ;
fileSystemEntry . directoryFlag = true ;
DirectoryMetaData directoryMetaData = new DirectoryMetaData ( childDirMetaPosition ) ;
fileSystemEntry . name = directoryMetaData . dirName ;
if ( directoryMetaData . nextSiblingDirectoryOffset ! = - 1 )
this . content . add ( getDirectory ( directoryMetaData . nextSiblingDirectoryOffset ) ) ;
if ( directoryMetaData . firstSubdirectoryOffset ! = - 1 )
fileSystemEntry . content . add ( getDirectory ( directoryMetaData . firstSubdirectoryOffset ) ) ;
if ( directoryMetaData . firstFileOffset ! = - 1 )
fileSystemEntry . content . add ( getFile ( fileSystemEntry , directoryMetaData . firstFileOffset ) ) ;
2022-09-11 05:14:37 +03:00
fileSystemEntry . content . sort ( Comparator . comparingLong ( FileSystemEntry : : getOffset ) ) ;
2022-08-10 15:55:50 +03:00
return fileSystemEntry ;
}
private FileSystemEntry getFile ( FileSystemEntry directoryContainer , int childFileMetaPosition ) {
FileSystemEntry fileSystemEntry = new FileSystemEntry ( ) ;
fileSystemEntry . directoryFlag = false ;
FileMetaData fileMetaData = new FileMetaData ( childFileMetaPosition ) ;
fileSystemEntry . name = fileMetaData . fileName ;
2022-09-11 05:14:37 +03:00
fileSystemEntry . offset = fileMetaData . fileDataRealOffset ;
fileSystemEntry . size = fileMetaData . fileDataRealLength ;
2022-08-10 15:55:50 +03:00
if ( fileMetaData . nextSiblingFileOffset ! = - 1 )
2022-09-05 00:39:48 +03:00
directoryContainer . content . add ( getFile ( directoryContainer , fileMetaData . nextSiblingFileOffset ) ) ;
2022-08-10 15:55:50 +03:00
return fileSystemEntry ;
}
public boolean isDirectory ( ) { return directoryFlag ; }
public boolean isFile ( ) { return ! directoryFlag ; }
2022-09-11 05:14:37 +03:00
public long getOffset ( ) { return offset ; }
public long getSize ( ) { return size ; }
2022-08-10 15:55:50 +03:00
public List < FileSystemEntry > getContent ( ) { return content ; }
public String getName ( ) { return name ; }
private static class DirectoryMetaData {
2022-09-05 00:39:48 +03:00
private final int parentDirectoryOffset ;
private final int nextSiblingDirectoryOffset ;
private final int firstSubdirectoryOffset ;
private final int firstFileOffset ;
private final int nextHashTableBucketDirectoryOffset ;
2022-08-10 15:55:50 +03:00
2022-09-05 00:39:48 +03:00
private final String dirName ;
2022-08-10 15:55:50 +03:00
private DirectoryMetaData ( ) {
this ( 0 ) ;
}
private DirectoryMetaData ( int childDirMetaPosition ) {
int i = childDirMetaPosition ;
2022-09-05 00:39:48 +03:00
parentDirectoryOffset = Converter . getLEint ( dirsMetadataTable , i ) ;
2022-08-10 15:55:50 +03:00
i + = 4 ;
2022-09-05 00:39:48 +03:00
nextSiblingDirectoryOffset = Converter . getLEint ( dirsMetadataTable , i ) ;
2022-08-10 15:55:50 +03:00
i + = 4 ;
2022-09-05 00:39:48 +03:00
firstSubdirectoryOffset = Converter . getLEint ( dirsMetadataTable , i ) ;
2022-08-10 15:55:50 +03:00
i + = 4 ;
2022-09-05 00:39:48 +03:00
firstFileOffset = Converter . getLEint ( dirsMetadataTable , i ) ;
2022-08-10 15:55:50 +03:00
i + = 4 ;
2022-09-05 00:39:48 +03:00
nextHashTableBucketDirectoryOffset = Converter . getLEint ( dirsMetadataTable , i ) ;
2022-09-11 05:14:37 +03:00
/ *
2022-09-05 00:39:48 +03:00
if ( nextHashTableBucketDirectoryOffset < 0 ) {
2022-12-07 04:22:23 +03:00
log . debug ( "nextHashTableBucketDirectoryOffset: " + nextHashTableBucketDirectoryOffset ) ;
2022-09-05 00:39:48 +03:00
}
//*/
2022-08-10 15:55:50 +03:00
i + = 4 ;
2022-09-05 00:39:48 +03:00
int dirNameLength = Converter . getLEint ( dirsMetadataTable , i ) ;
if ( dirNameLength > 0 ) {
i + = 4 ;
dirName = new String ( Arrays . copyOfRange ( dirsMetadataTable , i , i + dirNameLength ) , StandardCharsets . UTF_8 ) ;
}
else {
dirName = "" ;
2022-12-07 04:22:23 +03:00
// log.debug("Dir Name Length: "+dirNameLength);
2022-09-05 00:39:48 +03:00
}
2022-08-10 15:55:50 +03:00
//i += getRealNameSize(dirNameLength);
}
private int getRealNameSize ( int value ) {
if ( value % 4 = = 0 )
return value ;
return value + 4 - value % 4 ;
}
}
private static class FileMetaData {
2022-09-05 00:39:48 +03:00
private final int nextSiblingFileOffset ;
private final long fileDataRealOffset ;
private final long fileDataRealLength ;
private final int nextHashTableBucketFileOffset ;
2022-08-10 15:55:50 +03:00
private String fileName ;
private FileMetaData ( ) {
this ( 0 ) ;
}
private FileMetaData ( int childFileMetaPosition ) {
int i = childFileMetaPosition ;
// int containingDirectoryOffset = LoperConverter.getLEint(filesMetadataTable, i); // never used
i + = 4 ;
2022-09-05 00:39:48 +03:00
nextSiblingFileOffset = Converter . getLEint ( filesMetadataTable , i ) ;
2022-08-10 15:55:50 +03:00
i + = 4 ;
2022-09-05 00:39:48 +03:00
fileDataRealOffset = Converter . getLElong ( filesMetadataTable , i ) ;
2022-08-10 15:55:50 +03:00
i + = 8 ;
2022-09-05 00:39:48 +03:00
fileDataRealLength = Converter . getLElong ( filesMetadataTable , i ) ;
2022-08-10 15:55:50 +03:00
i + = 8 ;
2022-09-05 00:39:48 +03:00
nextHashTableBucketFileOffset = Converter . getLEint ( filesMetadataTable , i ) ;
2022-09-11 05:14:37 +03:00
/ *
2022-09-05 00:39:48 +03:00
if ( nextHashTableBucketFileOffset < 0 ) {
System . out . println ( "nextHashTableBucketFileOffset: " + nextHashTableBucketFileOffset ) ;
}
//*/
2022-08-10 15:55:50 +03:00
i + = 4 ;
2022-09-05 00:39:48 +03:00
int fileNameLength = Converter . getLEint ( filesMetadataTable , i ) ;
if ( fileNameLength > 0 ) {
i + = 4 ;
fileName = "" ;
try {
fileName = new String ( Arrays . copyOfRange ( filesMetadataTable , i , i + fileNameLength ) , StandardCharsets . UTF_8 ) ;
}
catch ( Exception e ) {
2022-12-07 04:22:23 +03:00
log . debug ( "fileName sizes are: " + filesMetadataTable . length + "\t" + i + "\t" + i + fileNameLength + "\t\t" + nextHashTableBucketFileOffset ) ;
2022-09-05 00:39:48 +03:00
}
}
else {
fileName = "" ;
2022-12-07 04:22:23 +03:00
//log.debug("File Name Length: "+fileNameLength);
2022-09-05 00:39:48 +03:00
}
2022-08-10 15:55:50 +03:00
//i += getRealNameSize(fileNameLength);
}
}
2022-09-05 00:39:48 +03:00
public void printTreeForDebug ( int spacerForSizes ) {
log . debug ( FileSystemTreeViewMaker . make ( content , spacerForSizes ) ) ;
2022-08-10 15:55:50 +03:00
}
2022-09-05 00:39:48 +03:00
public void printTreeForDebug ( ) {
log . debug ( FileSystemTreeViewMaker . make ( content , 100 ) ) ;
2022-08-10 15:55:50 +03:00
}
}