1 /* 2 * Copyright 2003-2013, Axel Dörfler, axeld@pinc-software.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include "Volume.h" 8 #include "Directory.h" 9 10 #include <boot/partitions.h> 11 #include <boot/platform.h> 12 13 #include <string.h> 14 #include <unistd.h> 15 #include <fcntl.h> 16 #include <stdio.h> 17 #include <stdlib.h> 18 19 20 using namespace FFS; 21 using std::nothrow; 22 23 24 Volume::Volume(boot::Partition *partition) 25 : 26 fRoot(NULL) 27 { 28 if ((fDevice = open_node(partition, O_RDONLY)) < B_OK) 29 return; 30 31 if (read_pos(fDevice, 0, &fType, sizeof(int32)) < B_OK) 32 return; 33 34 fType = B_BENDIAN_TO_HOST_INT32(fType); 35 36 switch (fType) { 37 case DT_AMIGA_FFS: 38 case DT_AMIGA_FFS_INTL: 39 case DT_AMIGA_FFS_DCACHE: 40 break; 41 42 case DT_AMIGA_OFS: 43 printf("The Amiga OFS is not yet supported.\n"); 44 return; 45 default: 46 // unsupported file system 47 //printf("amiga_ffs: unsupported: %08lx\n", fType); 48 return; 49 } 50 51 char *buffer = (char *)malloc(4096); 52 if (buffer == NULL) 53 return; 54 55 int32 blockSize = partition->block_size; 56 if (get_root_block(fDevice, buffer, blockSize, partition->size) != B_OK) { 57 // try to get the root block at different sizes, if the 58 // block size was incorrectly passed from the partitioning 59 // system 60 for (int32 size = 512; size <= 4096; size <<= 1) { 61 if (get_root_block(fDevice, buffer, size, partition->size) == B_OK) { 62 blockSize = size; 63 break; 64 } else if (size >= 4096) { 65 puts("Could not find root block\n"); 66 free(buffer); 67 return; 68 } 69 } 70 } 71 72 char *newBuffer = (char *)realloc(buffer, blockSize); 73 // if reallocation fails, we keep the old buffer 74 if (newBuffer != NULL) 75 buffer = newBuffer; 76 77 fRootNode.SetTo(buffer, blockSize); 78 fRoot = new(nothrow) Directory(*this, fRootNode); 79 // fRoot will free the buffer for us upon destruction 80 } 81 82 83 Volume::~Volume() 84 { 85 delete fRoot; 86 close(fDevice); 87 } 88 89 90 status_t 91 Volume::InitCheck() 92 { 93 if (fRoot != NULL) 94 return fRootNode.ValidateCheckSum(); 95 96 return B_ERROR; 97 } 98 99 100 // #pragma mark - 101 102 103 float 104 amiga_ffs_identify_file_system(boot::Partition *partition) 105 { 106 Volume volume(partition); 107 108 return volume.InitCheck() < B_OK ? 0 : 0.8; 109 } 110 111 112 static status_t 113 amiga_ffs_get_file_system(boot::Partition *partition, ::Directory **_root) 114 { 115 Volume *volume = new(nothrow) Volume(partition); 116 if (volume == NULL) 117 return B_NO_MEMORY; 118 119 if (volume->InitCheck() < B_OK) { 120 delete volume; 121 return B_ERROR; 122 } 123 124 *_root = volume->Root(); 125 return B_OK; 126 } 127 128 129 file_system_module_info gAmigaFFSFileSystemModule = { 130 "file_systems/amiga_ffs/v1", 131 kPartitionTypeAmigaFFS, 132 amiga_ffs_identify_file_system, 133 amiga_ffs_get_file_system 134 }; 135 136