xref: /haiku/src/system/boot/loader/file_systems/amiga_ffs/Volume.cpp (revision f75a7bf508f3156d63a14f8fd77c5e0ca4d08c42)
1 /*
2 ** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3 ** Distributed under the terms of the OpenBeOS License.
4 */
5 
6 
7 #include "Volume.h"
8 #include "Directory.h"
9 
10 #include <boot/partitions.h>
11 #include <boot/platform.h>
12 #include <util/kernel_cpp.h>
13 
14 #include <string.h>
15 #include <unistd.h>
16 #include <fcntl.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 
20 
21 using namespace FFS;
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