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