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