xref: /haiku/src/add-ons/kernel/partitioning_systems/session/session.cpp (revision 9eb55bc1d104b8fda80898f8b25c94d8000c8255)
1 //----------------------------------------------------------------------
2 //  This software is part of the OpenBeOS distribution and is covered
3 //  by the OpenBeOS license.
4 //
5 //  Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net
6 //---------------------------------------------------------------------
7 /*!
8 	\file session.cpp
9 	\brief Disk device manager partition module for CD/DVD sessions.
10 */
11 
12 #include <ddm_modules.h>
13 #include <DiskDeviceTypes.h>
14 #include <KernelExport.h>
15 #include <unistd.h>
16 
17 #include "Debug.h"
18 #include "Disc.h"
19 
20 static const char *kSessionModuleName = "partitioning_systems/session/v1";
21 
22 static status_t standard_operations(int32 op, ...);
23 static float identify_partition(int fd, partition_data *partition,
24                                 void **cookie);
25 static status_t scan_partition(int fd, partition_data *partition,
26                                void *cookie);
27 static void free_identify_partition_cookie(partition_data *partition,
28                                            void *cookie);
29 static void free_partition_cookie(partition_data *partition);
30 static void free_partition_content_cookie(partition_data *partition);
31 
32 static partition_module_info session_module = {
33 	{
34 		kSessionModuleName,
35 		0,
36 		standard_operations
37 	},
38 	kPartitionTypeMultisession,			// pretty_name
39 	0,									// flags
40 
41 	// scanning
42 	identify_partition,					// identify_partition
43 	scan_partition,						// scan_partition
44 	free_identify_partition_cookie,		// free_identify_partition_cookie
45 	free_partition_cookie,				// free_partition_cookie
46 	free_partition_content_cookie,		// free_partition_content_cookie
47 
48 	// querying
49 	NULL,								// supports_repairing
50 	NULL,								// supports_resizing
51 	NULL,								// supports_resizing_child
52 	NULL,								// supports_moving
53 	NULL,								// supports_moving_child
54 	NULL,								// supports_setting_name
55 	NULL,								// supports_setting_content_name
56 	NULL,								// supports_setting_type
57 	NULL,								// supports_setting_parameters
58 	NULL,								// supports_setting_content_parameters
59 	NULL,								// supports_initializing
60 	NULL,								// supports_initializing_child
61 	NULL,								// supports_creating_child
62 	NULL,								// supports_deleting_child
63 	NULL,								// is_sub_system_for
64 
65 	NULL,								// validate_resize
66 	NULL,								// validate_resize_child
67 	NULL,								// validate_move
68 	NULL,								// validate_move_child
69 	NULL,								// validate_set_name
70 	NULL,								// validate_set_content_name
71 	NULL,								// validate_set_type
72 	NULL,								// validate_set_parameters
73 	NULL,								// validate_set_content_parameters
74 	NULL,								// validate_initialize
75 	NULL,								// validate_create_child
76 	NULL,								// get_partitionable_spaces
77 	NULL,								// get_next_supported_type
78 	NULL,								// get_type_for_content_type
79 
80 	// shadow partition modification
81 	NULL,								// shadow_changed
82 
83 	// writing
84 	NULL,								// repair
85 	NULL,								// resize
86 	NULL,								// resize_child
87 	NULL,								// move
88 	NULL,								// move_child
89 	NULL,								// set_name
90 	NULL,								// set_content_name
91 	NULL,								// set_type
92 	NULL,								// set_parameters
93 	NULL,								// set_content_parameters
94 	NULL,								// initialize
95 	NULL,								// create_child
96 	NULL,								// delete_child
97 };
98 
99 extern "C" partition_module_info *modules[];
100 _EXPORT partition_module_info *modules[] =
101 {
102 	&session_module,
103 	NULL
104 };
105 
106 static
107 status_t
108 standard_operations(int32 op, ...)
109 {
110 	status_t error = B_ERROR;
111 	switch(op) {
112 		case B_MODULE_INIT:
113 		case B_MODULE_UNINIT:
114 			error = B_OK;
115 			break;
116 	}
117 	return error;
118 }
119 
120 static
121 float
122 identify_partition(int fd, partition_data *partition, void **cookie)
123 {
124 	DEBUG_INIT_ETC(NULL, ("fd: %d, id: %ld, offset: %Ld, "
125 	       "size: %Ld, block_size: %ld, flags: 0x%lx", fd,
126 	       partition->id, partition->offset, partition->size,
127 	       partition->block_size, partition->flags));
128 	device_geometry geometry;
129 	float result = -1;
130 	if (partition->flags & B_PARTITION_IS_DEVICE
131 	    && partition->block_size == 2048
132 	    && ioctl(fd, B_GET_GEOMETRY, &geometry) == 0
133 	    && geometry.device_type == B_CD)
134 	{
135 		Disc *disc = new Disc(fd);
136 		if (disc && disc->InitCheck() == B_OK) {
137 			*cookie = static_cast<void*>(disc);
138 			result = 0.5;
139 		}
140 	}
141 	PRINT(("returning %4.2f\n", result));
142 	return result;
143 }
144 
145 static
146 status_t
147 scan_partition(int fd, partition_data *partition, void *cookie)
148 {
149 	DEBUG_INIT_ETC(NULL, ("fd: %d, id: %ld, offset: %Ld, size: %Ld, "
150 	               "block_size: %ld, cookie: %p", fd, partition->id, partition->offset,
151 	               partition->size, partition->block_size, cookie));
152 
153 	status_t error = fd >= 0 && partition && cookie ? B_OK : B_BAD_VALUE;
154 	if (!error) {
155 		Disc *disc = static_cast<Disc*>(cookie);
156 		partition->status = B_PARTITION_VALID;
157 		partition->flags |= B_PARTITION_PARTITIONING_SYSTEM
158 							| B_PARTITION_READ_ONLY;
159 		partition->content_size = partition->size;
160 		partition->content_cookie = disc;
161 
162 		Session *session = NULL;
163 		for (int i = 0; (session = disc->GetSession(i)); i++) {
164 			partition_data *child = create_child_partition(partition->id,
165 														   i, -1);
166 			if (!child) {
167 				PRINT(("Unable to create child at index %ld.\n", i));
168 				// something went wrong
169 				error = B_ERROR;
170 				break;
171 			}
172 			child->offset = partition->offset + session->Offset();
173 			child->size = session->Size();
174 			child->block_size = session->BlockSize();
175 			child->flags |= session->Flags();
176 			child->type = strdup(session->Type());
177 			if (!child->type) {
178 				error = B_NO_MEMORY;
179 				break;
180 			}
181 			child->parameters = NULL;
182 			child->cookie = session;
183 		}
184 	}
185 	// cleanup on error
186 	if (error) {
187 		delete static_cast<Disc*>(cookie);
188 		partition->content_cookie = NULL;
189 		for (int32 i = 0; i < partition->child_count; i++) {
190 			if (partition_data *child = get_child_partition(partition->id, i)) {
191 				delete child->cookie;
192 				child->cookie = NULL;
193 			}
194 		}
195 	}
196 	PRINT(("error: 0x%lx, `%s'\n", error, strerror(error)));
197 	RETURN(error);
198 }
199 
200 static
201 void
202 free_identify_partition_cookie(partition_data */*partition*/, void *cookie)
203 {
204 	if (cookie) {
205 		DEBUG_INIT_ETC(NULL, ("cookie: %p", cookie));
206 		delete cookie;
207 	}
208 }
209 
210 static
211 void
212 free_partition_cookie(partition_data *partition)
213 {
214 	if (partition && partition->cookie) {
215 		DEBUG_INIT_ETC(NULL, ("partition->cookie: %p", partition->cookie));
216 		delete partition->cookie;
217 		partition->cookie = NULL;
218 	}
219 }
220 
221 static
222 void
223 free_partition_content_cookie(partition_data *partition)
224 {
225 	if (partition && partition->content_cookie) {
226 		DEBUG_INIT_ETC(NULL, ("partition->content_cookie: %p", partition->content_cookie));
227 		delete partition->content_cookie;
228 		partition->content_cookie = NULL;
229 	}
230 }
231