1 /* ------------------------------------------------------------------ 2 * Copyright (C) 1998-2009 PacketVideo 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 * express or implied. 14 * See the License for the specific language governing permissions 15 * and limitations under the License. 16 * ------------------------------------------------------------------- 17 */ 18 #include "oscl_library_list.h" 19 #include "oscl_string.h" 20 #include "oscl_file_io.h" 21 #include "oscl_file_types.h" 22 #include "pvlogger.h" 23 #include "oscl_uuid.h" 24 25 #define HASH '#' 26 #define NEWLINE '\n' 27 #define OPEN_PAREN '(' 28 #define CLOSE_PAREN ')' 29 #define QUOTE '"' 30 #define COMMA ',' 31 #define OSCL_NUMBER_OF_SHARED_LIBS 16 32 #define BUFFER_SIZE 256 33 34 35 OSCL_EXPORT_REF OsclLibraryList::OsclLibraryList() 36 { 37 ipLogger = PVLogger::GetLoggerObject("oscllib"); 38 #if OSCL_LIBRARY_PERF_LOGGING 39 iDiagnosticsLogger = PVLogger::GetLoggerObject("pvplayerdiagnostics.oscllib.oscllibrarylist"); 40 iLinesRead = 0; 41 iLibHit = 0; 42 #endif 43 int32 err = 0; 44 OSCL_TRY(err, 45 iLibList.reserve(OSCL_NUMBER_OF_SHARED_LIBS); 46 ); 47 if (err) 48 { 49 iLibList.clear(); 50 OSCL_LEAVE(err); 51 } 52 53 } 54 55 OSCL_EXPORT_REF OsclLibraryList::~OsclLibraryList() 56 { 57 #if OSCL_LIBRARY_PERF_LOGGING 58 iDiagnosticsLogger = NULL; 59 #endif 60 ipLogger = NULL; 61 iLibList.clear(); 62 } 63 64 // This method actually parses through a dll config file, retrieving the paths 65 // of dlls which implement a specific OsclUuid 66 OSCL_EXPORT_REF OsclLibStatus OsclLibraryList::Populate(const OsclUuid& aInterfaceId, const OSCL_String& aConfigFile) 67 { 68 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, ipLogger, PVLOGMSG_DEBUG, 69 (0, "OsclLibraryList::Populate '%s' IN", aConfigFile.get_cstr())); 70 71 // Open config file 72 Oscl_FileServer fileserver; 73 if (0 != fileserver.Connect()) 74 { 75 // Failed to connect to file server, return failure 76 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, ipLogger, PVLOGMSG_ERR, 77 (0, "OsclLibraryList::Populate - Unable to connect to fileserver")); 78 return OsclLibFail; 79 } 80 Oscl_File configFile; 81 if (0 != configFile.Open(aConfigFile.get_cstr(), Oscl_File::MODE_READ, fileserver)) 82 { 83 // Failed to open config file, return failure 84 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, ipLogger, PVLOGMSG_ERR, 85 (0, "OsclLibraryList::Populate - Unable to open configFile %s", aConfigFile.get_cstr())); 86 return OsclLibFail; 87 } 88 89 #if OSCL_LIBRARY_PERF_LOGGING 90 // Start collecting stats for current config file 91 iLinesRead = 0; 92 iLibHit = 0; 93 TICK starttime; 94 SET_TICK(starttime); 95 #endif 96 97 // Read in a byte at a time 98 uint8 buf[1]; 99 while (1 == configFile.Read(buf, 1, 1)) 100 { 101 if (HASH == buf[0]) 102 { 103 #if OSCL_LIBRARY_PERF_LOGGING 104 iLinesRead++; 105 #endif 106 // Ignore comments - begin with '#' 107 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, ipLogger, PVLOGMSG_DEBUG, 108 (0, "OsclLibraryList::Populate - Found a comment, skipping")); 109 // Advance to end of line 110 while (1 == configFile.Read(buf, 1, 1) && buf[0] != NEWLINE) 111 { 112 // ignore 113 } 114 } 115 else if (OPEN_PAREN == buf[0]) 116 { 117 // Parse UUID from line - begins with "(" 118 uint8 uuidBuf[BUFFER_SIZE]; 119 int i = 0; 120 uuidBuf[i++] = buf[0]; 121 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, ipLogger, PVLOGMSG_DEBUG, 122 (0, "OsclLibraryList::Populate - Found a (, reading uuid")); 123 // Read a character at a time - stop if newline or eof is reached or buffer is filled 124 while (i < BUFFER_SIZE && 1 == configFile.Read(buf, 1, 1) && buf[0] != NEWLINE) 125 { 126 uuidBuf[i++] = buf[0]; 127 if (CLOSE_PAREN == buf[0]) 128 { 129 break; 130 } 131 } 132 uuidBuf[i] = '\0'; 133 if (NEWLINE == buf[0]) 134 { 135 #if OSCL_LIBRARY_PERF_LOGGING 136 iLinesRead++; 137 #endif 138 // Reached the end of line but did not find the closing parentheses 139 // Skip this malformed line 140 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, ipLogger, PVLOGMSG_WARNING, 141 (0, "OsclLibraryList::Populate - incomplete uuid, skipping line")); 142 } 143 else if (BUFFER_SIZE == i && CLOSE_PAREN != buf[0]) 144 { 145 // Buffer is filled but did not reach the end of UUID - skip this malformed line 146 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, ipLogger, PVLOGMSG_WARNING, 147 (0, "OsclLibraryList::Populate - uuid too long, skipping line")); 148 // Advance to end of line 149 while (1 == configFile.Read(buf, 1, 1) && buf[0] != NEWLINE) 150 { 151 // ignore 152 } 153 } 154 else 155 { 156 // Create an instance of OsclUuid 157 OsclUuid tempUuidStr((char*)uuidBuf); 158 if (tempUuidStr == aInterfaceId) 159 { 160 // Parse path from line 161 bool commaFound = false; 162 bool quoteFound = false; 163 while (!(commaFound && quoteFound) && 1 == configFile.Read(buf, 1, 1) && buf[0] != NEWLINE) 164 { 165 // Advance past ',' and '"' 166 if (COMMA == buf[0]) 167 { 168 // If already found a comma, break and skip this malformed line 169 if (commaFound) break; 170 commaFound = true; 171 } 172 else if (QUOTE == buf[0]) 173 { 174 // If already found a quote, break and skip this malformed line 175 if (quoteFound) break; 176 quoteFound = true; 177 } 178 } 179 if (!(commaFound && quoteFound) || NEWLINE == buf[0]) 180 { 181 #if OSCL_LIBRARY_PERF_LOGGING 182 iLinesRead++; 183 #endif 184 // Did not find both ',' and '"' - Skip this malformed line 185 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, ipLogger, PVLOGMSG_WARNING, 186 (0, "OsclLibraryList::Populate - missing ' or \", skipping line")); 187 } 188 else 189 { 190 uint8 pathBuf[BUFFER_SIZE]; 191 i = 0; 192 // Read a character at a time - stop if newline is reached, ending quote is reached, or buffer is filled 193 // - leave room for terminating null character in buffer 194 while (1 == configFile.Read(buf, 1, 1) && buf[0] != QUOTE && buf[0] != NEWLINE && i < (BUFFER_SIZE - 1)) 195 { 196 pathBuf[i++] = buf[0]; 197 } 198 if (NEWLINE == buf[0]) 199 { 200 #if OSCL_LIBRARY_PERF_LOGGING 201 iLinesRead++; 202 #endif 203 // Reached the end of line but did not find the closing quote 204 // Skip this malformed line 205 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, ipLogger, PVLOGMSG_WARNING, 206 (0, "OsclLibraryList::Populate - incomplete path, skipping line")); 207 } 208 else if ((BUFFER_SIZE - 1) == i && QUOTE != buf[0]) 209 { 210 // Buffer is filled but did not reach the end of path - skip this malformed line 211 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, ipLogger, PVLOGMSG_WARNING, 212 (0, "OsclLibraryList::Populate - path too long, skipping line")); 213 #if OSCL_LIBRARY_PERF_LOGGING 214 iLinesRead++; 215 #endif 216 // Advance to end of line 217 while (1 == configFile.Read(buf, 1, 1) && buf[0] != NEWLINE) 218 { 219 // ignore 220 } 221 } 222 else 223 { 224 // Read in the path, end with terminating character 225 pathBuf[i] = NULL_TERM_CHAR; 226 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, ipLogger, PVLOGMSG_INFO, 227 (0, "OsclLibraryList::Populate - found a match, adding to list: %s", 228 (char*)pathBuf)); 229 // Add path to library list 230 iLibList.push_back((char*)pathBuf); 231 #if OSCL_LIBRARY_PERF_LOGGING 232 iLibHit++; 233 iLinesRead++; 234 #endif 235 } 236 } 237 } 238 else 239 { 240 // The UUID from this line does not match aInterfaceId - Advance to end of line 241 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, ipLogger, PVLOGMSG_INFO, 242 (0, "OsclLibraryList::Populate - uuid not a match, skipping line")); 243 #if OSCL_LIBRARY_PERF_LOGGING 244 iLinesRead++; 245 #endif 246 while (1 == configFile.Read(buf, 1, 1) && buf[0] != NEWLINE) 247 { 248 // ignore 249 } 250 } 251 } 252 } 253 // else continue on to next byte 254 }; 255 256 #if OSCL_LIBRARY_PERF_LOGGING 257 // End stats for current config file 258 uint32 difftime; 259 DIFF_TICK(starttime, difftime); 260 PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iDiagnosticsLogger, PVLOGMSG_INFO, 261 (0, "OsclLibraryList::Populate - Parsing configFile %s ...", aConfigFile.get_cstr())); 262 PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iDiagnosticsLogger, PVLOGMSG_INFO, 263 (0, " Time taken = %d ticks", difftime)); 264 PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iDiagnosticsLogger, PVLOGMSG_INFO, 265 (0, " Lines read = %d", iLinesRead)); 266 PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iDiagnosticsLogger, PVLOGMSG_INFO, 267 (0, " Libraries found = %d", iLibHit)); 268 #endif 269 270 //If there's atleast one library path name loaded in the vector, 271 //it means the parsing is successful for at least a particular OsclUuid 272 273 if (iLibList.size() > 0) 274 { 275 return OsclLibSuccess; 276 } 277 else 278 { 279 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, ipLogger, PVLOGMSG_WARNING, 280 (0, "OsclLibraryList::Populate, Didn't find any DLL for the OsclUuid")); 281 return OsclLibFail; 282 } 283 } 284 285 OSCL_EXPORT_REF uint32 OsclLibraryList::Size() 286 { 287 return iLibList.size(); 288 } 289 290 OSCL_EXPORT_REF const OSCL_String& OsclLibraryList::GetLibraryPathAt(uint32 n) 291 { 292 return iLibList[n]; 293 } 294 295