1 /* 2 * Copyright 2003 Tyler Akidau, haiku@akidau.net 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 /*! \file session.cpp 8 \brief Disk device manager partition module for CD/DVD sessions. 9 */ 10 11 12 #include <unistd.h> 13 14 #include <disk_device_manager/ddm_modules.h> 15 #include <disk_device_types.h> 16 #include <DiskDeviceTypes.h> 17 #include <KernelExport.h> 18 19 #include "Debug.h" 20 #include "Disc.h" 21 22 23 #define SESSION_PARTITION_MODULE_NAME "partitioning_systems/session/v1" 24 25 26 static status_t 27 standard_operations(int32 op, ...) 28 { 29 switch (op) { 30 case B_MODULE_INIT: 31 case B_MODULE_UNINIT: 32 return B_OK; 33 } 34 35 return B_ERROR; 36 } 37 38 39 static float 40 identify_partition(int fd, partition_data *partition, void **cookie) 41 { 42 DEBUG_INIT_ETC(NULL, ("fd: %d, id: %ld, offset: %Ld, " 43 "size: %Ld, block_size: %ld, flags: 0x%lx", fd, 44 partition->id, partition->offset, partition->size, 45 partition->block_size, partition->flags)); 46 47 device_geometry geometry; 48 float result = -1; 49 if ((partition->flags & B_PARTITION_IS_DEVICE) != 0 50 && partition->block_size == 2048 51 && ioctl(fd, B_GET_GEOMETRY, &geometry) == 0 52 && geometry.device_type == B_CD) { 53 Disc *disc = new(std::nothrow) Disc(fd); 54 if (disc != NULL && disc->InitCheck() == B_OK) { 55 // If we have only a single session then we can let the file system 56 // drivers play directly with the device. 57 Session *session = disc->GetSession(1); 58 if (session != NULL) { 59 result = 0.9f; 60 delete session; 61 } else 62 result = 0.1f; 63 64 *cookie = static_cast<void*>(disc); 65 } else 66 delete disc; 67 } 68 PRINT(("returning %g\n", result)); 69 return result; 70 } 71 72 73 static status_t 74 scan_partition(int fd, partition_data *partition, void *cookie) 75 { 76 DEBUG_INIT_ETC(NULL, ("fd: %d, id: %ld, offset: %Ld, size: %Ld, " 77 "block_size: %ld, cookie: %p", fd, partition->id, partition->offset, 78 partition->size, partition->block_size, cookie)); 79 80 Disc *disc = static_cast<Disc*>(cookie); 81 partition->status = B_PARTITION_VALID; 82 partition->flags |= B_PARTITION_PARTITIONING_SYSTEM 83 | B_PARTITION_READ_ONLY; 84 partition->content_size = partition->size; 85 86 Session *session = NULL; 87 status_t error = B_OK; 88 for (int i = 0; (session = disc->GetSession(i)); i++) { 89 partition_data *child = create_child_partition(partition->id, 90 i, partition->offset + session->Offset(), session->Size(), -1); 91 if (!child) { 92 PRINT(("Unable to create child at index %d.\n", i)); 93 // something went wrong 94 error = B_ERROR; 95 break; 96 } 97 child->block_size = session->BlockSize(); 98 child->flags |= session->Flags(); 99 child->type = strdup(session->Type()); 100 delete session; 101 if (!child->type) { 102 error = B_NO_MEMORY; 103 break; 104 } 105 child->parameters = NULL; 106 } 107 PRINT(("error: 0x%lx, `%s'\n", error, strerror(error))); 108 RETURN(error); 109 } 110 111 112 static void 113 free_identify_partition_cookie(partition_data */*partition*/, void *cookie) 114 { 115 DEBUG_INIT_ETC(NULL, ("cookie: %p", cookie)); 116 delete static_cast<Disc*>(cookie); 117 } 118 119 120 static partition_module_info sSessionModule = { 121 { 122 SESSION_PARTITION_MODULE_NAME, 123 0, 124 standard_operations 125 }, 126 "session", // short_name 127 MULTISESSION_PARTITION_NAME, // pretty_name 128 0, // flags 129 130 // scanning 131 identify_partition, // identify_partition 132 scan_partition, // scan_partition 133 free_identify_partition_cookie, // free_identify_partition_cookie 134 NULL, // free_partition_cookie 135 NULL, // free_partition_content_cookie 136 }; 137 138 partition_module_info *modules[] = { 139 &sSessionModule, 140 NULL 141 }; 142