xref: /haiku/src/system/boot/loader/file_systems/amiga_ffs/Volume.cpp (revision 2b76973fa2401f7a5edf68e6470f3d3210cbcff3)
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