Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

602 lines
17 KiB

  1. #----------------------------------------------------------------//
  2. # Script: comlib.pm
  3. #
  4. # (c) 2000 Microsoft Corporation. All rights reserved.
  5. #
  6. # Purpose: This script contains all the common perl routines.
  7. #
  8. # Version: <1.00> 07/28/2000 : Suemiao Rossognol
  9. #----------------------------------------------------------------//
  10. package comlib;
  11. $VERSION = '1.00';
  12. ###-----Require section and extern modual.----------------------//
  13. require 5.003;
  14. use strict;
  15. use lib $ENV{RazzleToolPath };
  16. use lib "$ENV{RazzleToolPath }\\sp";
  17. #no strict 'vars';
  18. #no strict 'subs';
  19. #no strict 'refs';
  20. use Logmsg;
  21. use cklang;
  22. use hashtext;
  23. use BuildName;
  24. use LockProc;
  25. use DfsMap;
  26. #----------------------------------------------------------------//
  27. #Function: globex
  28. #Parameter: (1) Search String
  29. #Retuen: (1) Array
  30. #----------------------------------------------------------------//
  31. sub globex ($)
  32. {
  33. my $match_criteria = shift;
  34. if ( !defined $match_criteria )
  35. {
  36. errmsg( "Must specify parameter for globex") ;
  37. return 0;
  38. }
  39. # Need to use '/' for UNC paths, so just convert to all '/''s
  40. $match_criteria =~ s/\\/\//g;
  41. # Return the results, converting back to '\'
  42. return grep { s/\//\\/g } glob( $match_criteria );
  43. }
  44. #----------------------------------------------------------------//
  45. #Function: LockProcess
  46. # Parameter: (1) Language
  47. # (2) Build Branch
  48. # (3) Lock Object
  49. #----------------------------------------------------------------//
  50. sub LockProcess
  51. {
  52. my ( $pLang, $pBranch, $pLockObj ) = @_;
  53. ##### Define Semaphore location
  54. my $lock_Location;
  55. if( !($lock_Location = &GetIniSetting::GetSettingEx( $pBranch, $pLang, "DFSSemaphore") ) )
  56. {
  57. errmsg( "[DFSSemaphore] is undefined in INI file." );
  58. return 0;
  59. }
  60. logmsg( "DFS Semaphore [$lock_Location]");
  61. ##### Acquire DFS Semaphore lock
  62. if( !(${$pLockObj} = new LockProc( $lock_Location, 60000) ) )
  63. {
  64. errmsg( "Problem acquiring lock using [$lock_Location]" );
  65. return 0;
  66. }
  67. logmsg( "Acquiring lock for exclusive DFS access..." );
  68. while ( !$$pLockObj->Lock() )
  69. {
  70. errmsg ("Failed to acquire semaphore lock.");
  71. return 0;
  72. }
  73. return 1;
  74. }
  75. #----------------------------------------------------------------//
  76. #Function: TieDfsView
  77. # Parameter: (1) Language
  78. # (2) Build Branch
  79. # (3) Tiehash Object
  80. #----------------------------------------------------------------//
  81. sub TieDfsView
  82. {
  83. my ( $pLang, $pBranch, $pTieObj ) = @_;
  84. ##### Get DFS Root name
  85. my $dfsRoot;
  86. if( !($dfsRoot = &GetIniSetting::GetSettingEx( $pBranch, $pLang,"DFSRootName" ) ) )
  87. {
  88. errmsg( "[DFSRootName] undefined in INI file." );
  89. return 0;
  90. }
  91. ##### Access DFS through a TIE hash
  92. logmsg( "Tie full DFS view [$dfsRoot] information." );
  93. if ( ! tie %$pTieObj, 'DfsMap', $dfsRoot )
  94. {
  95. errmsg( "Error accessing DFS." );
  96. return 0;
  97. }
  98. return 1;
  99. }
  100. #----------------------------------------------------------------//
  101. #Function: ParseDfsMapText
  102. # Parameter: (1) Sku (2) Build profile hash, key used:package
  103. #
  104. # Return: (1) Hash Array
  105. #----------------------------------------------------------------//
  106. sub ParseDfsMapText
  107. {
  108. my ( $pSkus, $pbldInfo ) = @_;
  109. my ( @theHash, @rtary, $theRootShare, $theSubShare, $theRootDir, $theLink );
  110. my $dfsMapFile = "$ENV{razzletoolpath}\\sp\\raiseall.txt";
  111. @theHash=();
  112. &HashText::Read_Text_Hash( 1, $dfsMapFile, \@theHash );
  113. my $extraLine;
  114. for my $line ( @theHash)
  115. {
  116. next if( $pbldInfo->{"package"} && lc $pbldInfo->{"package"} ne lc $line->{ Package } );
  117. next if( $pbldInfo->{"pkgtarget"} && lc $pbldInfo->{"pkgtarget"} ne "all" &&
  118. lc $line->{ Target } ne "all" && lc $pbldInfo->{"pkgtarget"} ne lc $line->{ Target } );
  119. next if( %$pSkus && !exists( $pSkus->{$line->{Sku}}) );
  120. #### Handle Micro replacement
  121. &ReplaceMicro( \$line->{ RootShare }, $line->{Sku}, $pbldInfo );
  122. &ReplaceMicro( \$line->{ SubShare }, $line->{Sku}, $pbldInfo );
  123. &ReplaceMicro( \$line->{ RootDir }, $line->{Sku}, $pbldInfo );
  124. &ReplaceMicro( \$line->{ Link }, $line->{Sku}, $pbldInfo );
  125. push( @rtary, $line );
  126. #### Add mapping for usa\<buildNO>\<archType>.cov links
  127. my %covUsaLine;
  128. if( $line->{Package} eq "OS" && lc $pbldInfo->{"lang"} eq "cov" )
  129. {
  130. %covUsaLine = %{$line};
  131. $covUsaLine{Link} =~ s/$pbldInfo->{"lang"}/usa/;
  132. $covUsaLine{Link} =~ s/$pbldInfo->{"arch"}$pbldInfo->{"type"}/$pbldInfo->{"arch"}$pbldInfo->{"type"}.cov/;
  133. push( @rtary, \%covUsaLine );
  134. }
  135. #### Add mapping for Neutral mui builds with misc links
  136. my %miscMuiLine;
  137. if( $line->{Package} eq "Neutral" )
  138. {
  139. %miscMuiLine = %{$line};
  140. $miscMuiLine{Link} =~ s/$pbldInfo->{"lang"}/misc/;
  141. push( @rtary, \%miscMuiLine );
  142. }
  143. }
  144. return ( @rtary );
  145. }
  146. #----------------------------------------------------------------//
  147. #Function: ReplaceMicro
  148. # Parameter: (1)String to be replaced (2)Sku (3)Build Profile Hash
  149. #
  150. # Return: none
  151. #----------------------------------------------------------------//
  152. sub ReplaceMicro
  153. {
  154. my ( $pStr, $pSku, $pbldInfo ) =@_;
  155. $pbldInfo->{shareno} = $pbldInfo->{no} if( !$pbldInfo->{shareno} );
  156. $$pStr =~ s/\$\(BLANK\)//g;
  157. $$pStr =~ s/\$\(SKU\)/$pSku/g;
  158. $$pStr =~ s/\$\(SERVER\)/\\\\$pbldInfo->{server}/g;
  159. $$pStr =~ s/\$\(BUILD\)/$pbldInfo->{basename}/g;
  160. $$pStr =~ s/\$\(LANG\)/$pbldInfo->{lang}/g;
  161. $$pStr =~ s/\$\(BLDNO\)/$pbldInfo->{no}/g;
  162. $$pStr =~ s/\$\(SHARENO\)/$pbldInfo->{shareno}/g;
  163. $$pStr =~ s/\$\(BRANCH\)/$pbldInfo->{branch}/g;
  164. $$pStr =~ s/\$\(RELEASE\)/$pbldInfo->{release}/g;
  165. $$pStr =~ s/\$\(SYMREL\)/$pbldInfo->{symshare}/g;
  166. $$pStr =~ s/\$\(DFSBRANCH\)/$pbldInfo->{dfsbranch}/g;
  167. $$pStr =~ s/\$\(ARCH\)/$pbldInfo->{arch}/g;
  168. $$pStr =~ s/\$\(TYPE\)/$pbldInfo->{type}/g;
  169. }
  170. #----------------------------------------------------------------//
  171. #Function: GetReleaseShareName
  172. # Parameter: (1) Build Branch
  173. # (2) Language
  174. #----------------------------------------------------------------//
  175. sub GetReleaseShareName
  176. {
  177. my ( $bldBranch, $lang ) = @_;
  178. my ($releaseShareName);
  179. my( @iniRequest ) = ( "AlternateReleaseDir", "ReleaseDir");
  180. for my $keyReleaseDir( @iniRequest )
  181. {
  182. $releaseShareName = &GetIniSetting::GetSettingEx( $bldBranch, $lang,$keyReleaseDir );
  183. last if( $releaseShareName );
  184. }
  185. $releaseShareName = "release" if( !$releaseShareName );
  186. return ( $releaseShareName );
  187. }
  188. #----------------------------------------------------------------//
  189. #Function: ParseNetShare
  190. #Parameter: (1) Share name
  191. # (2) Parsing String, such as "Path", "Permissions:"
  192. #
  193. # Return: Share Path or access ID and permission in hash array
  194. #----------------------------------------------------------------//
  195. sub ParseNetShare
  196. {
  197. my ( $pShareName, $pParseStr ) = @_;
  198. my ( @results, %shareInfo );
  199. if( $pShareName !~ /^\\\\(.+)\\(.+)$/ )
  200. {
  201. $pShareName = "\\\\$ENV{computername}\\$pShareName ";
  202. }
  203. my @tmpFile = `rmtshare $pShareName`;
  204. my $match;
  205. for my $theLine ( @tmpFile )
  206. {
  207. chomp $theLine;
  208. next if( !$theLine );
  209. last if( $theLine =~ "The command completed successfully." );
  210. if( $theLine =~ /$pParseStr/i )
  211. {
  212. if( $pParseStr =~ /Permissions:/i ){ $match = 1; next;}
  213. ### parse path, return path
  214. @results = split( /\s+/, $theLine );
  215. return $results[1];
  216. }
  217. push ( @results, $theLine ) if( $match );
  218. }
  219. #### Parse permissions, return key-Access ID, value-permission
  220. for my $line ( @results )
  221. {
  222. my @tmp = split( /\:/, $line );
  223. for( @tmp )
  224. {
  225. $_ =~ s/(\s+)?([^\s+]+)(\s+)?/$2/;
  226. }
  227. $shareInfo{$tmp[0]}=$tmp[1];
  228. }
  229. return ( %shareInfo );
  230. }
  231. #----------------------------------------------------------------//
  232. #Function: ParseSharePath
  233. #Parameter: (1) Share name
  234. #
  235. # Return: Share path
  236. #----------------------------------------------------------------//
  237. sub ParseSharePath
  238. {
  239. my ( $pShareName ) = @_;
  240. my ( $sharePath );
  241. if( $pShareName !~ /^\\\\(.+)\\(.+)$/ )
  242. {
  243. $pShareName = "\\\\$ENV{computername}\\$pShareName ";
  244. }
  245. my $tmp = "$ENV{temp}\\tmp.txt";
  246. if( !system ("rmtshare $pShareName > $tmp" ) )
  247. {
  248. my @tmpFile= &comlib::ReadFile( $tmp );
  249. for my $theLine ( @tmpFile )
  250. {
  251. my @mCols = split( /\s+/, $theLine );
  252. if( $mCols[0] eq "Path" )
  253. {
  254. $sharePath = $mCols[1];
  255. last;
  256. }
  257. }
  258. unlink( $tmp );
  259. }
  260. return ( $sharePath );
  261. }
  262. #----------------------------------------------------------------//
  263. #Function: ParseTable
  264. # Parameter: (1) Group (2) Language (3) Architecture (4) Debug type
  265. # Return: Hash Array Table
  266. #----------------------------------------------------------------//
  267. sub ParseTable
  268. {
  269. my ( $pGroup, $pLang, $pArch, $pType ) = @_;
  270. my @theHash=();
  271. &HashText::Read_Text_Hash( 1, "$ENV{RazzleToolPath}\\sp\\miscrel.txt", \@theHash );
  272. my @hashKey = qw( SourceDir DestDir );
  273. for (my $inx=0; $inx< @theHash ; $inx++)
  274. {
  275. my $theTarg = lc( $theHash[$inx]->{ Target } );
  276. my $theGroup = lc( $theHash[$inx]->{ Group } );
  277. my $theLang = lc( $theHash[$inx]->{ Lang } );
  278. my $theArch = lc( $theHash[$inx]->{ Arch } );
  279. my $theType = lc( $theHash[$inx]->{ Type } );
  280. if( $theGroup ne $pGroup )
  281. {
  282. splice( @theHash, $inx, 1);
  283. --$inx;
  284. next;
  285. }
  286. if( $theLang ne "all" )
  287. {
  288. if( !&cklang::CkLang( $pLang, $theLang ) )
  289. {
  290. splice( @theHash, $inx, 1);
  291. --$inx;
  292. next;
  293. }
  294. }
  295. if( $theArch ne "all" && $theArch ne $pArch )
  296. {
  297. splice( @theHash, $inx, 1);
  298. --$inx;
  299. next;
  300. }
  301. if( $theType ne "all" && $theType ne $pType )
  302. {
  303. splice( @theHash, $inx, 1);
  304. --$inx;
  305. next;
  306. }
  307. }
  308. return @theHash;
  309. }
  310. #----------------------------------------------------------------//
  311. #Function: CreateExcludeFile
  312. # Parameter: (1) String with path sepearated by ;
  313. # Return: Exclude file contains all the excluded dirs
  314. #----------------------------------------------------------------//
  315. sub CreateExcludeFile
  316. {
  317. my ( $pExcludeStr ) = @_;
  318. my $tmpfile = "$ENV{temp}\\tmpfile.$$";
  319. if( !open( TMP, ">$tmpfile" ) )
  320. {
  321. errmsg( "Fail to open [$tmpfile] for write." );
  322. return 0;
  323. }
  324. if( $pExcludeStr )
  325. {
  326. my @tDirs = split( /\;/, $pExcludeStr );
  327. for ( @tDirs ) { print TMP "\\$_\\\n"; }
  328. }
  329. close ( TMP );
  330. return $tmpfile;
  331. }
  332. #----------------------------------------------------------------//
  333. #Function: ParsePrsListFile
  334. # Parameter: (1) Language (2) Architecture (3) Debug type (4) Table File Name
  335. # Return: Hash Array Table
  336. #----------------------------------------------------------------//
  337. sub ParsePrsListFile
  338. {
  339. my ( $pLang, $pArch, $pType, $pListFile ) = @_;
  340. my ( @theHash );
  341. @theHash=();
  342. &HashText::Read_Text_Hash( 1, $pListFile, \@theHash );
  343. for (my $inx=0; $inx< @theHash; $inx++)
  344. {
  345. my $theFileName = lc( $theHash[$inx]->{ Filename } );
  346. my $theLang = lc( $theHash[$inx]->{ ValidLangs } );
  347. my $excludLang = lc( $theHash[$inx]->{ Exceptions} );
  348. my $theArch = lc( $theHash[$inx]->{ ValidArchs } );
  349. my $theType = lc( $theHash[$inx]->{ ValidDebug } );
  350. my $theAltName = lc( $theHash[$inx]->{ AltName } );
  351. if( &cklang::CkLang( $pLang, $excludLang ) )
  352. {
  353. splice( @theHash, $inx, 1);
  354. --$inx;
  355. next;
  356. }
  357. if( $theLang ne "all" )
  358. {
  359. if( !&cklang::CkLang( $pLang, $theLang ) )
  360. {
  361. splice( @theHash, $inx, 1);
  362. --$inx;
  363. next;
  364. }
  365. }
  366. if( $theArch ne "all" && $theArch ne lc($pArch) )
  367. {
  368. splice( @theHash, $inx, 1);
  369. --$inx;
  370. next;
  371. }
  372. if( $theType ne "all" && $theType ne lc($pType) )
  373. {
  374. splice( @theHash, $inx, 1);
  375. --$inx;
  376. next;
  377. }
  378. if( $theAltName eq "none" )
  379. {
  380. my @tmpFile = split( /\\/, $theFileName);
  381. $theHash[$inx]->{ AltName } = $tmpFile[$#tmpFile];
  382. }
  383. # Add to handle fusion special mui path
  384. # path with $(ARCH)
  385. my $tmpValue;
  386. while( $theHash[$inx]->{ Filename } =~ /^(.*)(\$\(ARCH)\)(.*)$/ )
  387. {
  388. if( lc($pArch) eq "x86" ) { $tmpValue = "i386"; } else { $tmpValue = "ia64"; }
  389. $theHash[$inx]->{ Filename }= $1.$tmpValue.$3;
  390. }
  391. # path with $(CD)
  392. my $stop=0;
  393. while( $theHash[$inx]->{ Filename } =~ /^(.*)(\$\(CD)\)(.*)$/ )
  394. {
  395. if( $tmpValue = &Which_MuiCD( $pLang ) )
  396. {
  397. $theHash[$inx]->{ Filename }= $1."CD$tmpValue".$3;
  398. next;
  399. }
  400. errmsg( "[$theHash[$inx]->{ Filename }] is not valid for parsing" );
  401. splice( @theHash, $inx, 1);
  402. $stop =1;
  403. last;
  404. }
  405. next if( $stop );
  406. # path with $(LANG)
  407. while( $theHash[$inx]->{ Filename } =~ /^(.*)(\$\(LANG)\)(.*)$/ )
  408. {
  409. $theHash[$inx]->{ Filename }= $1.$pLang.$3;
  410. }
  411. }
  412. return @theHash;
  413. }
  414. #----------------------------------------------------------------//
  415. #Function: ParsePrsSubmitLog
  416. #Parameter: (1) FileName (2) Parsing string
  417. #
  418. # Return: Match Value
  419. #----------------------------------------------------------------//
  420. sub ParsePrsSubmitLog
  421. {
  422. my ( $pSubmitLog, $pParseStr ) = @_;
  423. my $parseValue = 0;
  424. my @outfile = &ReadFile( $pSubmitLog );
  425. for my $theLine ( @outfile )
  426. {
  427. if( $theLine =~ /$pParseStr(.+)/ )
  428. {
  429. $parseValue = $1;
  430. last;
  431. }
  432. }
  433. return $parseValue;
  434. }
  435. #----------------------------------------------------------------//
  436. #Function: ReadFile
  437. # Parameter: (1) FileName
  438. #
  439. # Return: Array of file content
  440. #----------------------------------------------------------------//
  441. sub ReadFile
  442. {
  443. my ( $pFileName ) = @_;
  444. my ( @tmp );
  445. if( !open( TMP, $pFileName ) )
  446. {
  447. errmsg( "Fail on open [$pFileName] for read. Exit" );
  448. return 0;
  449. }
  450. chomp( @tmp = <TMP> );
  451. close( TMP );
  452. return @tmp;
  453. }
  454. #----------------------------------------------------------------//
  455. #Function: Which_MuiCD
  456. # Parameter: (1) Abbreviated language defined in the codes.txt
  457. # Return: (1) Number of CD - 0 is not found
  458. #----------------------------------------------------------------//
  459. sub Which_MuiCD
  460. {
  461. my ( $pLang ) = @_;
  462. my %muicdLayout =
  463. ( 1 => "CHS CHH FR GER JPN KOR",
  464. 2 => "ARA BR ES HEB IT NL SV",
  465. 3 => "CS DA FI NO RU",
  466. 4 => "EL HU PL PT TR",
  467. 5 => "SK SL" );
  468. for my $theCD( keys %muicdLayout )
  469. {
  470. my @tmp = split( /\s+/, $muicdLayout{$theCD} );
  471. for my $theLang ( @tmp )
  472. {
  473. if( $theLang eq uc($pLang) ) { return $theCD; }
  474. }
  475. }
  476. return 0;
  477. }
  478. #----------------------------------------------------------------//
  479. #Function: CheckError
  480. # Parameter: (1)$pErrFile - the Error File Name with full path
  481. # Return: (0) - File exists and is not empty
  482. # (1) - File not exists or is empty
  483. #----------------------------------------------------------------//
  484. sub CheckError
  485. {
  486. my( $pErrFile, $pSucessStr )=@_;
  487. if( (-e $pErrFile) && `wc -l $pErrFile`>0 )
  488. {
  489. logmsg("Please check error at $pErrFile\n");
  490. return 0;
  491. }
  492. logmsg("$pSucessStr\n");
  493. return 1;
  494. }
  495. #------------------------------------------------------------------//
  496. #Function: ExecuteSystemX
  497. #Parameter: (1) Command line for system call
  498. # (2) Extra string to be populated to error message
  499. #------------------------------------------------------------------//
  500. sub ExecuteSystemX
  501. {
  502. my ( $pCmdLine, $pPowerLess)=@_;
  503. if( $pPowerLess )
  504. {
  505. if( defined $ENV{LOGFILE} ) { logmsg( $pCmdLine ); }
  506. return 1;
  507. }
  508. my $retry;
  509. while( $retry < 3 )
  510. {
  511. return 1 if (&ExecuteSystem( $pCmdLine ));
  512. $retry++;
  513. }
  514. return 0;
  515. }
  516. #------------------------------------------------------------------//
  517. #Function: ExecuteSystem
  518. #Parameter: (1) Command line for system call
  519. # (2) Extra string to be populated to error message
  520. #------------------------------------------------------------------//
  521. sub ExecuteSystem {
  522. my ( $pCmdLine, $pExtraStr)=@_;
  523. if( defined $ENV{LOGFILE} ) { logmsg("$pExtraStr$pCmdLine"); }
  524. system( $pCmdLine );
  525. if( $? )
  526. {
  527. my $rc = $? >> 8;
  528. if( defined $ENV{ERRFILE} ) { errmsg( "$pExtraStr$pCmdLine ($rc)" ); }
  529. return 0;
  530. }
  531. return 1;
  532. }
  533. #----------------------------------------------------------------//
  534. sub ResetLogErrFile
  535. {
  536. my ( $pFileName ) = @_;
  537. # Reset logfile and errfile
  538. $ENV{temp} =~ /^(.*)\\([^\\]+)$/;
  539. $ENV{temp} .= "\\$ENV{lang}" if( lc $ENV{lang} ne lc $2 );
  540. system( "md $ENV{temp}" ) if( !(-e $ENV{temp} ) );
  541. $ENV{LOGFILE} = "$ENV{temp}\\$pFileName.log";
  542. $ENV{ERRFILE} = "$ENV{temp}\\$pFileName.err";
  543. if(-e $ENV{LOGFILE} )
  544. {
  545. system( "copy $ENV{LOGFILE} $ENV{LOGFILE}.old");
  546. system( "del $ENV{LOGFILE}" );
  547. }
  548. if(-e $ENV{ERRFILE} )
  549. {
  550. system( "copy $ENV{ERRFILE} $ENV{ERRFILE}.old") ;
  551. system( "del $ENV{ERRFILE}" );
  552. }
  553. }
  554. #---------------------------------------------------------------------//
  555. 1;