1/* 2 * Copyright (C) 2014 The Android Open Source Project 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 express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17/* 18 * DESCRIPTION: 19 * The dm_tree_plugin_util.cc file contains helper functions 20 * for plug-in support 21 */ 22 23#include "xpl_Logger.h" 24#include "dmtTreeImpl.hpp" 25#include "dm_tree_plugin_root_node_class.H" 26#include "dm_tree_plugin_util.H" 27#include "dm_tree_util.h" 28#include "SyncML_DM_WBXMLArchive.H" 29#include "SyncML_PlugIn_WBXMLLog.H" 30#include "dm_uri_utils.h" 31 32#ifndef min 33#define min(a,b) (((a) < (b)) ? (a) : (b)) 34#endif 35 36SYNCML_DM_RET_STATUS_T 37DmCheckNodeConstraint(const PDMPlugin & pPlugin) ; 38 39SYNCML_DM_RET_STATUS_T 40DmCheckMultiNodeConstraint(const PDMPlugin & pPlugin, CPCHAR path, CPCHAR remain, const PDmtTree & tree); 41 42SYNCML_DM_RET_STATUS_T DmRemoveTempfile(DMString &dirName) 43{ 44 45 SYNCML_DM_RET_STATUS_T ret_code = SYNCML_DM_SUCCESS; 46 XPL_FS_SHANDLE_T search_handle; 47 DMString strFileNameBuffer; 48 char *file_name = strFileNameBuffer.AllocateBuffer(XPL_FS_MAX_FILE_NAME_LENGTH); 49 50 if (file_name == NULL) 51 return SYNCML_DM_DEVICE_FULL; 52 53 search_handle = XPL_FS_StartSearch(dirName, DMFileHandler::MIDDLE_FILE_EXTENSION, TRUE, NULL); 54 if ( search_handle == XPL_FS_SHANDLE_INVALID) 55 return SYNCML_DM_IO_FAILURE; 56 57 //Loop through all .temp files in the directory 58 memset(file_name,0,XPL_FS_MAX_FILE_NAME_LENGTH); 59 while ( XPL_FS_GetSearchResult(search_handle,file_name) != XPL_FS_RET_NOT_FOUND ) 60 { 61 62 DMFileHandler fileHandler(file_name); 63 ret_code = fileHandler.open(XPL_FS_FILE_RDWR); 64 // Remove temporary ESN file 65 if(ret_code == SYNCML_DM_SUCCESS) 66 fileHandler.deleteFile(); 67 } 68 XPL_FS_EndSearch(search_handle); 69 return ret_code; 70} 71 72SYNCML_DM_RET_STATUS_T DMTree::ReadCommandFromFile( DMFileHandler *fileHandle, 73 DMBuffer& cmdURI ) 74{ 75 SYNCML_DM_RET_STATUS_T ret_code = SYNCML_DM_FAIL; 76 SyncML_DM_WBXMLReader* reader = new SyncML_DM_WBXMLReader( fileHandle ); 77 78 if( reader ) for( ; ; ) 79 { 80 ret_code = SYNCML_DM_IO_FAILURE; 81 if(fileHandle->seek(XPL_FS_SEEK_SET, sizeof(INT32) + 2) != XPL_FS_RET_SUCCESS) break; 82 83 // Read URI 84 ret_code = reader->readOpaque( &cmdURI ); 85 if( SYNCML_DM_SUCCESS != ret_code ) break; 86 87 //Read END_TAG 88 UINT8 bYte = 0; 89 ret_code = reader->readByte( &bYte ); 90 if( SYNCML_DM_SUCCESS != ret_code ) break; 91 92 ret_code = SYNCML_DM_IO_FAILURE; 93 if( bYte != SyncML_DM_WBXMLArchive::END_TAG ) break; 94 95 ret_code = SYNCML_DM_SUCCESS; 96 break; 97 } 98 99 if( reader ) 100 { 101 delete reader; 102 reader = NULL; 103 } 104 105 return ret_code; 106} 107 108SYNCML_DM_RET_STATUS_T DMTree::RecoverPluginFromFile( const DMString& file_bak_name ) 109{ 110 SYNCML_DM_RET_STATUS_T ret_code = SYNCML_DM_FAIL; 111 DMFileHandler *fileHandle = new DMFileHandler( file_bak_name ); 112 113 if( fileHandle ) 114 { 115 BOOLEAN delete_file = FALSE; 116 117 if(fileHandle->open(XPL_FS_FILE_RDWR) != SYNCML_DM_SUCCESS) 118 { 119 // DM: Ignore files that cannot be opened ? 120 ret_code = SYNCML_DM_SUCCESS; 121 } 122 else 123 { 124 delete_file = TRUE; 125 126 DMBuffer cmdURI; 127 ret_code = ReadCommandFromFile( fileHandle, cmdURI ); 128 129 if( ret_code == SYNCML_DM_SUCCESS ) 130 { 131 PDMPlugin pPlugin = m_oPluginManager.FindPlugin(SYNCML_DM_DATA_PLUGIN, (CPCHAR)cmdURI.getBuffer()); 132 133 if (pPlugin != NULL) 134 { 135 PDmtAPIPluginTree pluginTree; 136 ret_code=pPlugin->GetTree((CPCHAR) cmdURI.getBuffer(), pluginTree); 137 138 if(ret_code == SYNCML_DM_SUCCESS) 139 { 140 PDmtRWPluginTree ptrRWTree = (DmtRWPluginTree *) ((DmtTree *)pluginTree); 141 ret_code = ptrRWTree->setLogFileHandle(fileHandle); 142 143 if( ret_code == SYNCML_DM_SUCCESS) 144 { 145 ret_code = ptrRWTree->Rollback(); 146 147 // DM: hands-off from file 148 fileHandle = NULL; 149 } 150 } 151 } 152 } 153 } 154 155 if( fileHandle ) 156 { 157 if( delete_file ) 158 { 159 fileHandle->deleteFile(); 160 } 161 162 delete fileHandle; 163 fileHandle = NULL; 164 } 165 } 166 167 return ret_code; 168} 169 170SYNCML_DM_RET_STATUS_T DMTree::RecoverPlugin() 171{ 172 173 SYNCML_DM_RET_STATUS_T ret_code = SYNCML_DM_SUCCESS; 174 DMString strFileNameBuffer; 175 DMString strFileBakNameBuffer; 176 177 char *file_name = strFileNameBuffer.AllocateBuffer(XPL_FS_MAX_FILE_NAME_LENGTH); 178 char *file_bak_name = strFileBakNameBuffer.AllocateBuffer(XPL_FS_MAX_FILE_NAME_LENGTH); 179 180 if ( !file_name || !file_bak_name ) 181 return SYNCML_DM_DEVICE_FULL; 182 183 DMString logtdir; 184 m_oEnv.GetWFSFullPath( NULL, logtdir ); 185 186 XPL_FS_SHANDLE_T search_handle = XPL_FS_StartSearch(logtdir, DMFileHandler::LOG_FILE_EXTENSION, TRUE, NULL); 187 if ( search_handle == XPL_FS_SHANDLE_INVALID) 188 return SYNCML_DM_IO_FAILURE; 189 190 //Loop through all .log files in the directory 191 memset(file_name, 0, XPL_FS_MAX_FILE_NAME_LENGTH ); 192 memset(file_bak_name, 0, XPL_FS_MAX_FILE_NAME_LENGTH ); 193 194 int nExtLength = DmStrlen( DMFileHandler::LOG_FILE_EXTENSION ); 195 196 while ( XPL_FS_GetSearchResult(search_handle, file_name) != XPL_FS_RET_NOT_FOUND ) 197 { 198 int nFileNameLen = DmStrlen(file_name); 199 200 if ( file_name[0] == 0 || nFileNameLen < 5 ) continue; 201 202 DmStrncpy(file_bak_name, file_name, nFileNameLen - nExtLength ); 203 DmStrcat(file_bak_name, DMFileHandler::MIDDLE_FILE_EXTENSION); 204 205 if( XPL_FS_RET_SUCCESS != XPL_FS_Rename( file_name, file_bak_name ) ) 206 { 207 ret_code = SYNCML_DM_IO_FAILURE; 208 continue; 209 } 210 211 ret_code = RecoverPluginFromFile( file_bak_name ); 212 // DM: continue even if there is an error ( exactly as in original version of code ) 213 } 214 215 XPL_FS_EndSearch(search_handle); 216 return ret_code; 217 218} 219 220SYNCML_DM_RET_STATUS_T 221DmExecutePlugin(CPCHAR path, 222 CPCHAR args, 223 CPCHAR szCorrelator, 224 DMString & oResult) 225{ 226 SYNCML_DM_RET_STATUS_T dm_stat = SYNCML_DM_FAIL; 227 DMPluginManager & oPluginManager = dmTreeObj.GetPluginManager(); 228 229 XPL_LOG_DM_TMN_Debug((" DmExecutePlugin find plugin\n")); 230 PDMPlugin pPlugin = oPluginManager.FindPlugin(SYNCML_DM_EXECUTE_PLUGIN, path); 231 232 if (pPlugin == NULL) 233 { 234 XPL_LOG_DM_TMN_Debug((" DmExecutePlugin plugin not found\n")); 235 return SYNCML_DM_FEATURE_NOT_SUPPORTED; 236 } 237 238 PDmtTree ptrTree( new DmtTreeImpl(FALSE) ); // readonly version of the tree 239 240 XPL_LOG_DM_TMN_Debug((" DmExecutePlugin plugin being executed...\n")); 241 return pPlugin->Execute(path,args,szCorrelator,ptrTree,oResult); 242} 243 244SYNCML_DM_RET_STATUS_T 245DmCallPluginFunction(CPCHAR szSessionRootURI, 246 FILESETTYPE nFileSet, 247 SYNCML_DM_COMMAND_T type) 248{ 249 SYNCML_DM_RET_STATUS_T dm_stat = SYNCML_DM_SUCCESS; 250 DMPluginManager & oPluginManager = dmTreeObj.GetPluginManager(); 251 252 DMPluginVector plugins; 253 PDmtAPIPluginTree pluginTree; 254 255 oPluginManager.GetPlugins(szSessionRootURI, SYNCML_DM_DATA_PLUGIN, plugins); 256 257 INT32 size = plugins.size(); 258 for ( INT32 i=0; i<size; i++ ) 259 { 260 PDMPlugin plugin = plugins[i]; 261 if(plugin->IsTreeEmpty()) 262 continue; 263 264 dm_stat=plugin->GetTree(plugin->GetPath(), pluginTree); 265 if(dm_stat == SYNCML_DM_SUCCESS) 266 { 267 switch(type) 268 { 269 case SYNCML_DM_RELEASE: 270 dm_stat = pluginTree->Flush(); 271 break; 272 273 case SYNCML_DM_ROLLBACK: 274 { 275 FILESETTYPE sets = 0; 276 277 SyncML_DM_Archiver& archiver = dmTreeObj.GetArchiver(); 278 sets = archiver.getArchivesByURI(plugin->GetPath()); 279 sets &= nFileSet; 280 281 if ( sets != 0 ) 282 { 283 dm_stat = pluginTree->Rollback(); 284 } 285 } 286 break; 287 288 case SYNCML_DM_COMMIT: 289 dm_stat = pluginTree->Commit(); 290 break; 291 292 case SYNCML_DM_ATOMIC: 293 dm_stat = pluginTree->Begin(); 294 break; 295 } 296 } 297 298 if (dm_stat != SYNCML_DM_SUCCESS) 299 { 300 if((dm_stat == SYNCML_DM_FEATURE_NOT_SUPPORTED)&&(type == SYNCML_DM_ATOMIC)) 301 return dm_stat; 302 else 303 dm_stat = SYNCML_DM_SUCCESS; 304 } 305 } 306 307 XPL_LOG_DM_TMN_Debug((" DmCallPluginFunction retStat=%d\n", dm_stat)); 308 return dm_stat; 309} 310 311SYNCML_DM_RET_STATUS_T 312DmCheckConstraint(CPCHAR szSessionRootURI, 313 FILESETTYPE * pFileSet, 314 FILESETTYPE * pFileSetToRollback) 315{ 316 SYNCML_DM_RET_STATUS_T dm_stat = SYNCML_DM_SUCCESS; 317 SYNCML_DM_RET_STATUS_T dm_const_stat = SYNCML_DM_SUCCESS; 318 319 SyncML_DM_Archiver& archiver = dmTreeObj.GetArchiver(); 320 FILESETTYPE numArchives = archiver.getNumArchives(); 321 FILESETTYPE i = 0; 322 FILESETTYPE set = 1; 323 324 325 if ( pFileSet == NULL || pFileSetToRollback == NULL ) 326 return SYNCML_DM_FAIL; 327 328 XPL_LOG_DM_TMN_Debug(("--- DmCheckConstraint for %s, pFileSet=0x%x, numArchives=%d\n", szSessionRootURI, *pFileSet, numArchives)); 329 330 if ( !archiver.IsDirty(pFileSet) ) 331 { 332 XPL_LOG_DM_TMN_Debug(("No archives are dirty\n")); 333 return dm_stat; 334 } 335 336 DMPluginVector aSessionPlugins; 337 338 DMPluginManager & oPluginManager = dmTreeObj.GetPluginManager(); 339 oPluginManager.GetPlugins(szSessionRootURI, SYNCML_DM_CONSTRAINT_PLUGIN, aSessionPlugins); 340 341 INT32 size = aSessionPlugins.size(); 342 for (INT32 index=0; index< size; index++) 343 { 344 FILESETTYPE sets = 0; 345 346 CPCHAR strRootPath=(aSessionPlugins[index])->GetPath(); 347 348 sets = archiver.getArchivesByURI(strRootPath); 349 sets = sets & (*pFileSet); 350 if ( sets ) 351 { 352 dm_stat = DmCheckNodeConstraint(aSessionPlugins[index]); 353 if ( dm_stat != SYNCML_DM_SUCCESS ) 354 { 355 for (i=0, set=1; i< numArchives; i++, set = set <<1) 356 { 357 if ( (sets & set) != 0 && ((*pFileSetToRollback) & set) == 0 ) 358 { 359 (*pFileSetToRollback) |= set; 360 (*pFileSet) &= ~ set; 361 } 362 } 363 dm_const_stat = dm_stat; 364 } 365 } 366 } 367 368 if ( dm_const_stat != SYNCML_DM_SUCCESS ) 369 dm_stat = dm_const_stat; 370 371 XPL_LOG_DM_TMN_Debug((" DmCheckConstraint retStat=%d\n", dm_stat)); 372 return dm_stat; 373} 374 375 376 377SYNCML_DM_RET_STATUS_T 378DmCheckNodeConstraint(const PDMPlugin & pPlugin) 379{ 380 SYNCML_DM_RET_STATUS_T dm_stat = SYNCML_DM_SUCCESS; 381 PDmtTree tree( new DmtTreeImpl(true) ); 382 383 CPCHAR strPluginPath=pPlugin->GetPath(); 384 385 if ( (DmStrchr(strPluginPath, '*')) == NULL) 386 { 387 dm_stat = (pPlugin)->CheckConstraint(strPluginPath,tree); 388 } 389 else 390 { 391 dm_stat = DmCheckMultiNodeConstraint(pPlugin,"",strPluginPath,tree); 392 } 393 394 if (dm_stat != SYNCML_DM_SUCCESS) 395 dm_stat = SYNCML_DM_CONSTRAINT_FAIL; 396 397 return dm_stat; 398 399} 400 401 402SYNCML_DM_RET_STATUS_T 403DmCheckMultiNodeConstraint(const PDMPlugin & pPlugin, 404 CPCHAR path, 405 CPCHAR remain, 406 const PDmtTree & tree) 407{ 408 SYNCML_DM_RET_STATUS_T dm_stat; 409 const char * ptr; //point to remaining stuff after * 410 411 XPL_LOG_DM_TMN_Debug(("CheckMultiNode %s:%s\n", path, remain)); 412 413 ptr=remain; 414 while ( * ptr != '*' && * ptr != '\0') 415 ptr ++; 416 417 if ( *ptr == '*' ) 418 { 419 DMString strPath=path; 420 strPath += DMString(remain, (int) ptr - (int)remain -1); 421 422 ptr++; 423 424 DMStringVector mapNodeNames; 425 dm_stat = tree->GetChildNodeNames(strPath.c_str(),mapNodeNames); 426 if ( dm_stat != SYNCML_DM_SUCCESS ) 427 return dm_stat; 428 429 for (INT32 i=0; i<mapNodeNames.size(); i++) 430 { 431 DMString childPath; 432 childPath =strPath; 433 childPath += "/"; 434 childPath += mapNodeNames[i]; 435 436 dm_stat = DmCheckMultiNodeConstraint(pPlugin,childPath.c_str(),ptr,tree); 437 if ( dm_stat != SYNCML_DM_SUCCESS) 438 return dm_stat; 439 } 440 } 441 else 442 { 443 DMString strPath=path; 444 strPath += remain; 445 dm_stat=(pPlugin)->CheckConstraint(strPath.c_str(),tree); 446 } 447 448 449 return dm_stat; 450} 451