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.

1097 lines
32 KiB

  1. @REM ------------------------------------------------------------------
  2. @REM <<dfs.cmd>>
  3. @REM Issue the appropriate DFS commands to lower or raise builds
  4. @REM to a specific quality.
  5. @REM
  6. @REM Copyright (c) Microsoft Corporation. All rights reserved.
  7. @REM
  8. @REM Version: < 1.0 > 05/15/2002 Suemiao Rossignol
  9. @REM ------------------------------------------------------------------
  10. @perl -x "%~f0" %*
  11. @set RETURNVALUE=%errorlevel%
  12. @goto :endperl
  13. #!perl
  14. use strict;
  15. use lib $ENV{RAZZLETOOLPATH} . "\\PostBuildScripts";
  16. use lib $ENV{RAZZLETOOLPATH};
  17. use Logmsg;
  18. use ParseArgs;
  19. use Win32::File qw(GetAttributes SetAttributes);
  20. use File::Basename;
  21. use Carp;
  22. use BuildName;
  23. use GetIniSetting;
  24. use comlib;
  25. use cksku;
  26. use cklang;
  27. use RelQuality;
  28. use DfsMap;
  29. use LockProc;
  30. $ENV{script_name} = basename( $0 );
  31. sub Usage {
  32. print<<USAGE;
  33. Issue the appropriate DFS commands to raise/lower builds to a specific quality.
  34. Usage:
  35. $ENV{script_name}: -l:<Language> -n:<BuildNo> -q:<RaiseQuality>||-lower
  36. [-r:<Target Server>]
  37. [-a:<Architecture>] [-t:DebugType] [-replacelatest]
  38. [-replacenumber] [-d] [-p] [-?]
  39. -l:lang Language.
  40. Default is "usa".
  41. -n:# Build number.
  42. -r:server Serevr with build to be raised.
  43. Default is %computername%.
  44. -a:arch Architecture. Ex: "x86", "ia64" or "amd64".
  45. Default is applied to all architectures.
  46. -t:type Debug Type. EX: "fre" or "chk".
  47. Default is applied to all build types.
  48. -q:qly Raise quality. EX: "bvt", "tst", "idw"...
  49. -lower Remove build from dfs mapping.
  50. -replacelatest Force replace latest links with an older build when raise.
  51. -replacenumber Force replace numbered links with an older build when raise.
  52. -d Debug mode.
  53. -p Display key variables only.
  54. -? Display Usage.
  55. Example:
  56. $ENV{script_name} -l:ger -n:2600 -a:ia64 -lower
  57. $ENV{script_name} -l:ger -n:2600 -t:chk -q:tst -d
  58. USAGE
  59. exit(1)
  60. }
  61. my ( $buildNo, %bldInfo, $raiseServer, $isLower, $powerLess );
  62. my ( $fReplaceLatestLink, $fReplaceNumberLink );
  63. my ( %ntPkg, %validPlatform, $iniFile, $dash );
  64. my ( @linkNode, %dfsMap, $dfsLock, @accessMembers );
  65. my ( @dfsInfo, @latestDfsInfo, @osDfsInfo );
  66. if( !&GetParams() ){ exit(1); }
  67. timemsg( "Start $ENV{script_name}" );
  68. if( !&InitVars() ){ exit (1); }
  69. if( $powerLess ) { exit(0); }
  70. if( !&GetDfsAccess( \%dfsMap, \$dfsLock ) ){ exit(1); }
  71. if( !&MainProc() ){ $dfsLock->Unlock(); exit (1); }
  72. $dfsLock->Unlock();
  73. logmsg( $dash );
  74. timemsg( "Complete successfully!" );
  75. exit(0);
  76. #-----------------------------------------------------------------------------
  77. sub GetParams
  78. {
  79. parseargs('?' => \&Usage, 'l:' => \$ENV{lang}, 'n:' => \$buildNo, 'r:' =>\$raiseServer,
  80. 'a:' => \$bldInfo{arch}, 't:' => \$bldInfo{type},
  81. 'q:' => \$bldInfo{qly}, 'lower' =>\$isLower,
  82. 'replacenumber' => \$fReplaceNumberLink, 'replacelatest' =>\$fReplaceLatestLink,
  83. 'd' => \$Logmsg::DEBUG, 'p' =>\$powerLess );
  84. $ENV{lang}="usa" if( !$ENV{lang} );
  85. if( !$buildNo )
  86. {
  87. errmsg( "Please specify build number" );
  88. return 0;
  89. }
  90. $raiseServer = $ENV{computername} if( !$raiseServer );
  91. my %validArch = ( "x86" => "1", "ia64" => "1", "amd64" =>"1" );
  92. my %validType = ( "fre" => "1", "chk" => "1" );
  93. if( $bldInfo{arch} && !exists $validArch{ $bldInfo{arch}} )
  94. {
  95. errmsg( "Invalid architecture [$bldInfo{arch}]." );
  96. return
  97. }
  98. if( $bldInfo{type} && !exists $validType{ $bldInfo{type}} )
  99. {
  100. errmsg( "Invalid debug type [$bldInfo{type}]." );
  101. return 0;
  102. }
  103. for my $arch ( keys %validArch )
  104. {
  105. for my $type ( keys %validType )
  106. {
  107. $validPlatform{"$arch$type"} = length( $arch )<< 4 | length ( $type );
  108. }
  109. }
  110. if( $isLower )
  111. {
  112. wrnmsg( "Quality flag [$bldInfo{qly}] ignored for lower operation" ) if( $bldInfo{qly});
  113. $isLower = 1;
  114. }
  115. else
  116. {
  117. if( !$bldInfo{qly} )
  118. {
  119. errmsg( "Please sepcify raise quality" );
  120. return;
  121. }
  122. $isLower = 0;
  123. if ( !&RelQuality::IsValid( $bldInfo{qly} ) )
  124. {
  125. errmsg( "Invalid Raise qualyity [$bldInfo{qly}]." );
  126. return 0;
  127. }
  128. }
  129. if( $fReplaceNumberLink ){ $fReplaceNumberLink = 1; } else { $fReplaceNumberLink =0;}
  130. if( $fReplaceLatestLink ){ $fReplaceLatestLink = 1; } else { $fReplaceLatestLink =0;}
  131. &comlib::ResetLogErrFile( "raiseall.$buildNo.$bldInfo{arch}$bldInfo{type}.$raiseServer" );
  132. return 1;
  133. }
  134. #-----------------------------------------------------------------------------
  135. sub InitVars
  136. {
  137. ### Set vars
  138. $bldInfo{lang} = $ENV{lang};
  139. $bldInfo{no} = $buildNo;
  140. $bldInfo{server} = $raiseServer;
  141. $bldInfo{branch} = $ENV{_BuildBranch};
  142. $bldInfo{platform}="$bldInfo{arch}$bldInfo{type}";
  143. $iniFile = "xpsp1.ini";
  144. $dash = '-' x 60;
  145. %ntPkg = ( 1 => "os", 2 => "conglomerator", 3 => "neutral" );
  146. ### Define the available target to be raised
  147. my $searchDir = "\\\\$raiseServer\\release\\$buildNo\\$bldInfo{lang}";
  148. my (@myNode, %myBld);
  149. chomp( @myNode = `dir $searchDir /ad /b` );
  150. for my $platform ( keys %validPlatform )
  151. {
  152. for ( my $i=0; $i< @myNode; $i++ )
  153. {
  154. if( $myNode[$i] =~ /$platform/i )
  155. {
  156. if( $bldInfo{arch} && $myNode[$i] !~ /$bldInfo{arch}/i)
  157. {
  158. splice( @myNode, $i, 1);
  159. next;
  160. }
  161. if( $bldInfo{type} && $myNode[$i] !~ /$bldInfo{type}/i)
  162. {
  163. splice( @myNode, $i, 1);
  164. next;
  165. }
  166. }
  167. }
  168. }
  169. for my $node( @myNode )
  170. {
  171. if( exists $validPlatform{$node} )
  172. {
  173. $myBld{ $ntPkg{1} } .= "$node ";
  174. }
  175. elsif( $node =~ /mui/i )
  176. {
  177. $myBld{$ntPkg{3}} = $node;
  178. }
  179. else
  180. {
  181. $myBld{$ntPkg{2}} .= "$node ";
  182. }
  183. }
  184. for my $pkg ( sort keys %ntPkg )
  185. {
  186. if( $myBld{$ntPkg{$pkg}} =~ /^(.+)\s$/ )
  187. {
  188. my @tmp = split( /\s/, $1 );
  189. push( @linkNode, $_ )for ( @tmp ) ;
  190. }
  191. }
  192. ### Define share access members
  193. my ($parseStr, $accessMemberStr);
  194. if ( lc $bldInfo{qly} eq "pre" || lc $bldInfo{qly} eq "bvt" )
  195. {
  196. $parseStr = "BVTMembers";
  197. }
  198. else
  199. {
  200. $parseStr = "ReleaseAccess";
  201. }
  202. if( !( $accessMemberStr = &GetIniSetting::GetSettingEx( $ENV{_buildBranch},$bldInfo{lang},$parseStr ) ))
  203. {
  204. errmsg( "[$parseStr] is undefined in $iniFile.");
  205. return 0;
  206. }
  207. @accessMembers = split( '\s+', $accessMemberStr );
  208. ### Define DFS branch name
  209. $bldInfo{dfsbranch} = &GetIniSetting::GetSettingQuietEx( $ENV{_buildBranch}, $bldInfo{lang}, "DFSAlternateBranchName" );
  210. $bldInfo{dfsbranch} = $ENV{_buildBranch} if( !$bldInfo{dfsbranch} );
  211. ### Get DFS Root name
  212. if( !($bldInfo{dfsroot} = &GetIniSetting::GetSettingEx( $ENV{_buildBranch}, $bldInfo{lang},"DFSRootName" ) ) )
  213. {
  214. errmsg( "[DFSRootName] undefined in $iniFile." );
  215. return 0;
  216. }
  217. ### Set release Share Drive
  218. my @iniRequest = ("ReleaseDrive::$raiseServer");
  219. my $releaseDrive = &GetIniSetting::GetSettingEx( $ENV{_buildBranch},$bldInfo{lang},@iniRequest );
  220. if ( !$releaseDrive )
  221. {
  222. $ENV{_ntdrive} =~ /(.*)\:/;
  223. $releaseDrive = $1;
  224. }
  225. $bldInfo{release} = "$releaseDrive:\\release";
  226. logmsg( "Ini File ....................[$iniFile]" );
  227. logmsg( "Raise Server ................[$raiseServer]" );
  228. logmsg( "Lauguage ...................[$bldInfo{lang}]" );
  229. logmsg( "Build Number ................[$buildNo]" );
  230. logmsg( "Build Architecture ..........[$bldInfo{arch}]" );
  231. logmsg( "Build Type...................[$bldInfo{type}]" );
  232. logmsg( "Link Points ......[ $myBld{$ntPkg{1}}]") if ( $myBld{$ntPkg{1}} );
  233. logmsg( "..................[ $myBld{$ntPkg{2}}]") if ( $myBld{$ntPkg{2}} );
  234. logmsg( "..................[ $myBld{$ntPkg{3}}]") if ( $myBld{$ntPkg{3}} );
  235. logmsg( "Is Lowering dfs links........[$isLower]" );
  236. logmsg( "Raise Quality................[$bldInfo{qly}]" );
  237. logmsg( "Force Replacing Numbered Link[$fReplaceNumberLink]" );
  238. logmsg( "Force Replacing Latest Link .[$fReplaceLatestLink]" );
  239. logmsg( "Release root path ...........[$bldInfo{release}]" );
  240. logmsg( "DFS root ....................[$bldInfo{dfsroot}]" );
  241. logmsg( "Share access members ........[@accessMembers]");
  242. logmsg( "DFS Branch Name .............[$bldInfo{dfsbranch}]" );
  243. logmsg( "Log file ...................[$ENV{LOGFILE}]" );
  244. logmsg( "Error file .................[$ENV{ERRFILE}]" );
  245. logmsg( $dash );
  246. }
  247. #-----------------------------------------------------------------------------
  248. sub MainProc
  249. {
  250. return 1 if( $powerLess );
  251. for my $node ( @linkNode )
  252. {
  253. # Set Platform
  254. if( exists $validPlatform{$node} )
  255. {
  256. my $archLen = ($validPlatform{ $node } >> 4) & 15;
  257. my $typeLen = $validPlatform{ $node } & 15;
  258. $bldInfo{arch} = substr ( $node, 0, $archLen);
  259. $bldInfo{type} = substr ( $node, $archLen, $typeLen );
  260. $bldInfo{package}=$ntPkg{1};
  261. }
  262. else
  263. {
  264. $bldInfo{arch} = "";
  265. $bldInfo{type} = "";
  266. if( $node =~ /mui/i){ $bldInfo{package}=$ntPkg{3};}
  267. else{ $bldInfo{package}=$ntPkg{2};}
  268. }
  269. $bldInfo{platform}="$bldInfo{arch}$bldInfo{type}";
  270. # (2-1) Define valid array of hash with numberlink-share mapping from raisemap.txt
  271. my %curSku;
  272. my $myUc = uc $node;
  273. my $myLc = lc $node;
  274. $curSku{ $myUc } = 1;
  275. $curSku{ $myLc } = 1;
  276. if( !( @dfsInfo = &comlib::ParseDfsMapText( \%curSku, \%bldInfo )) )
  277. {
  278. wrnmsg( "No valid mapping found for [$node]." );
  279. next;
  280. }
  281. # (2-2)Duplicate array of hash with number mapping
  282. # and replace build number with latest.quality
  283. my $latestStr = "latest.$bldInfo{qly}";
  284. $#latestDfsInfo = $#dfsInfo;
  285. for ( my $inx=0;$inx<=$#dfsInfo; $inx++ )
  286. {
  287. %{$latestDfsInfo[$inx]} = %{$dfsInfo[$inx]};
  288. }
  289. for my $line ( @latestDfsInfo )
  290. {
  291. $line->{Link} =~ s/$bldInfo{no}/$latestStr/;
  292. }
  293. # (4)Verify symbol server share when it is os build
  294. #return 0 if( $keyPKG == 1 && !&SetSymbolServer( \@dfsInfo ) );
  295. # (3) Start Raise/Lower process
  296. if( !$isLower )
  297. {
  298. return 0 if( !&RaiseAll() );
  299. }
  300. else
  301. {
  302. # Duplicate OS hash array data to be used for
  303. # checking if the links share with the other builds
  304. if( $bldInfo{package} eq $ntPkg{1} )
  305. {
  306. $#osDfsInfo = $#dfsInfo;
  307. for ( my $inx=0;$inx<=$#dfsInfo; $inx++ )
  308. {
  309. %{$osDfsInfo[$inx]} = %{$dfsInfo[$inx]}
  310. }
  311. }
  312. return 0 if( !&LowerAll() );
  313. }
  314. }
  315. return 1;
  316. }
  317. #-----------------------------------------------------------------------------
  318. sub RaiseAll
  319. {
  320. my $latestStr = "latest.$bldInfo{qly}";
  321. # (1) Raise release share permission for current package
  322. my ( %svRootShare );
  323. for my $line ( @dfsInfo )
  324. {
  325. ### No need to create share in symServer
  326. next if( lc $line->{Sku} eq "sym" );
  327. next if( exists $svRootShare{ $line->{RootShare} } );
  328. $svRootShare{ $line->{RootShare} } = 1;
  329. dbgmsg( "Grant share permission..." );
  330. return 0 if( !&GrantSharePermission( $line->{RootShare}, $line->{RootDir} ) );
  331. dbgmsg( "Remove Unauthorized user from the share ..." );
  332. return 0 if(! &RemoveUnauthorizedUserFromShare( $line->{RootShare} ));
  333. }
  334. # (2) Raise DFS mapping For number and latest links
  335. my $needLatestLink;
  336. # (2-1) Unlink the same numberd shares for older timestamps
  337. dbgmsg( "Checking/Unmapping numbered shares for older timestamps..." );
  338. return 0 if( !&UnmapExistingNumberedLinks( \@dfsInfo ) );
  339. # (2-2) Remove old latest.qly dfs links
  340. dbgmsg( "Finding/lowering any old latest DFS links at same quality..." );
  341. $bldInfo{no} = $latestStr;
  342. return 0 if( !&RemoveOldLatestDotQlyLinks( \@latestDfsInfo, \$needLatestLink ) );
  343. $bldInfo{no} = $buildNo;
  344. # (2-3) Create DFS numbered links
  345. return 0 if( !&CreateDFSMapping( \@dfsInfo ) );
  346. # (3-4) Create DFS latest.qly links
  347. if( $needLatestLink )
  348. {
  349. $bldInfo{no} = $latestStr;
  350. ### Skip misc\latest link
  351. if( $bldInfo{package} eq $ntPkg{3} && $needLatestLink == 1 )
  352. {
  353. for ( my $i=0; $i<@latestDfsInfo; $i++)
  354. {
  355. if( $latestDfsInfo[$i]->{Link} =~ /misc/i )
  356. {
  357. splice( @latestDfsInfo, $i, 1);
  358. --$i;
  359. }
  360. }
  361. }
  362. return 0 if( !&CreateDFSMapping( \@latestDfsInfo ) );
  363. $bldInfo{no} = $buildNo;
  364. }
  365. # (4)dbgmsg( "Flushing outstanding DFS operations..." );
  366. if( !( tied %dfsMap ) -> Flush() )
  367. {
  368. $dfsLock->Unlock();
  369. return 0;
  370. }
  371. # (5) Unlock Process
  372. $dfsLock->Unlock();
  373. # (6) Update Qulity file when it is os link
  374. if( $bldInfo{package} eq $ntPkg{1} )
  375. {
  376. logmsg( "Update quality file..." );
  377. my $qlyFilePath = "\\\\$raiseServer\\release\\$bldInfo{no}\\$ENV{lang}";
  378. $qlyFilePath .= "\\$bldInfo{arch}$bldInfo{type}\\bin\\build_logs";
  379. &RelQuality::Update( $qlyFilePath, $bldInfo{no}, $bldInfo{qly} );
  380. logmsg($dash);
  381. }
  382. return 1;
  383. }
  384. #-----------------------------------------------------------------------------
  385. sub LowerAll
  386. {
  387. # Verify if the action is required for non-os builds
  388. return 1 if( $bldInfo{package} ne $ntPkg{1} && &FoundSameLangNoLink(\@osDfsInfo) );
  389. # (2) Lower release share permission for current package
  390. my ( %svRootShare );
  391. for my $line ( @dfsInfo )
  392. {
  393. ### No need to create share in symServer
  394. next if( lc $line->{Sku} eq "sym" );
  395. next if( exists $svRootShare{ $line->{RootShare} } );
  396. $svRootShare{ $line->{RootShare} } = 1;
  397. dbgmsg( "Lower build share..." );
  398. return 0 if( !&LowerBuildShare( $line->{RootShare} ) );
  399. }
  400. # (3) Lower DFS mapping For number and latest links
  401. # (3-1) Remove DFS numbered/latest links
  402. my $needLatestLink;
  403. return 0 if( !&RemoveDFSMapping( \@dfsInfo, \$needLatestLink ) );
  404. # (3-2) Replace latest.tst to an older links
  405. #todo ?
  406. my $replaceLinkNo;
  407. if( $needLatestLink )
  408. {
  409. #if( $replaceLinkNo = &FindOlderShareLink( \@latestDfsInfo ) )
  410. #{
  411. # &ReplaceLatestTstLink( \@latestDfsInfo, $replaceLinkNo, $needLatestLink );
  412. #}
  413. }
  414. # (4)dbgmsg( "Flushing outstanding DFS operations..." );
  415. if( !( tied %dfsMap ) -> Flush() )
  416. {
  417. $dfsLock->Unlock();
  418. return 0;
  419. }
  420. # (5) Unlock Process
  421. $dfsLock->Unlock();
  422. if( $bldInfo{package} eq $ntPkg{1} )
  423. {
  424. logmsg( "Update quality file..." );
  425. my $qlyFilePath = "\\\\$raiseServer\\release\\$bldInfo{no}\\$ENV{lang}";
  426. $qlyFilePath .= "\\$bldInfo{arch}$bldInfo{type}\\bin\\build_logs";
  427. &RelQuality::Delete( $qlyFilePath, "*" );
  428. logmsg($dash);
  429. }
  430. return 1;
  431. }
  432. #-----------------------------------------------------------------------------
  433. sub RemoveDFSMapping
  434. {
  435. my ( $pDfsInfo, $pNeedLatestLink ) = @_;
  436. $$pNeedLatestLink=0;
  437. my %svShare;
  438. for my $line ( @$pDfsInfo )
  439. {
  440. ### Get all the Links that is link to the share currently
  441. my $curShare = "$line->{RootShare}$line->{SubShare}";
  442. next if( exists $svShare{$curShare} );
  443. $svShare{$curShare} = 1;
  444. my @allLinks = @{$dfsMap{$curShare}} if( exists $dfsMap{$curShare} );
  445. ### remove links to $curShare
  446. for ( my $loop=0; $loop<3; $loop++)
  447. {
  448. for my $theLink ( @allLinks )
  449. {
  450. chomp $theLink;
  451. ### Process in the order of non-misc, misc\number and misc\latest.
  452. next if( $loop == 0 && $theLink =~ /misc/i );
  453. next if( $loop == 1 && !($theLink =~ /misc/i && $theLink !~ /$bldInfo{no}/i ) );
  454. next if( $loop == 2 && !($theLink =~ /misc/i && $theLink !~ /latest/i ));
  455. ### Decide if we need to delete the link
  456. my $continue;
  457. if( $theLink !~ /misc/i )
  458. {
  459. next if( $theLink !~ /$bldInfo{lang}/i );
  460. }
  461. ### Special handle for misc and latest links
  462. ### Do not delete misc link if number links exist
  463. else
  464. {
  465. my @netLinks = @{$dfsMap{$curShare}};
  466. for my $link ( @netLinks )
  467. {
  468. next if( $link =~ /latest\.([^\\]+)/i && $link =~ /misc/i);
  469. next if( $link =~ /$bldInfo{no}/ && $link =~ /misc/i);
  470. $continue=1;
  471. last;
  472. }
  473. }
  474. next if ($continue );
  475. ### Decide if we need to replace latest links
  476. my $isLatestTst=1 if( $theLink =~ /latest\.([^\\]+)/i && $1 =~ /tst/i );
  477. if( $isLatestTst && $theLink !~ /sym/i )
  478. {
  479. $$pNeedLatestLink=1;
  480. my @allShares = @{$dfsMap{$theLink}} if( exists $dfsMap{$theLink} );
  481. if( @allShares > 1 ){ $$pNeedLatestLink = 0; }
  482. else
  483. {
  484. if( $bldInfo{pacakge} ne $ntPkg{1} )
  485. {
  486. my @netLinks = @{$dfsMap{$allShares[0]}};
  487. for my $link ( @netLinks )
  488. {
  489. if( $link !~ /$bldInfo{lang}/i && $theLink !~ /misc/i )
  490. {
  491. $$pNeedLatestLink = 0;
  492. last;
  493. }
  494. }
  495. if( $$pNeedLatestLink && $theLink =~ /misc/i )
  496. {
  497. $$pNeedLatestLink |=2;
  498. }
  499. }
  500. }
  501. }
  502. ### Remove/Unmap dfs link
  503. logmsg( "Lowering [$theLink]" );
  504. return 0 if( !&RemoveShareFromMapping( $theLink, $curShare) );
  505. }
  506. }
  507. }
  508. return 1;
  509. }
  510. #-----------------------------------------------------------------------------
  511. sub RemoveShareFromMapping
  512. {
  513. my ( $pLink, $pShare ) = @_;
  514. dbgmsg( "Removing [$pLink]" );
  515. return 0 if ( !( tied %dfsMap)->RemoveShareFromLink($pLink, $pShare) );
  516. &BldfileSetting( $pLink, "del" );
  517. ### Remove <build>.Bld / <build>.SRV file for OS build only
  518. if( &IsLastLinkUnderParent($pLink, $pShare) )
  519. {
  520. ### Delete <platform> Dirs In Replica Servers
  521. if( !&ReplicaDirsSetting( $pLink, "del" ) )
  522. {
  523. #wrnmsg( "Fail on removing dirs in Replica server");
  524. }
  525. }
  526. return 1;
  527. }
  528. #-----------------------------------------------------------------------------
  529. sub CreateDFSMapping
  530. {
  531. my ( $pDfsInfo ) = @_;
  532. for my $line ( @$pDfsInfo )
  533. {
  534. logmsg( "Creating [$line->{Link}]" );
  535. my $curShare = "$line->{RootShare}$line->{SubShare}";
  536. return 0 if( !&ReplicaDirsSetting( $line->{Link}, "update" ) );
  537. ### Create Logical dfs Link
  538. return 0 if ( !( $dfsMap{$line->{Link}}=$curShare ) );
  539. if( $bldInfo{package} eq $ntPkg{1} )
  540. {
  541. return 0 if(!&MagicDFSSettings( $line ) );
  542. }
  543. }
  544. return 1;
  545. }
  546. #-----------------------------------------------------------------------------
  547. sub MagicDFSSettings
  548. {
  549. my ( $pLine ) = @_;
  550. ### We need all new DFS links to exist in order to find
  551. ### new paths, so flush any outstanding commands here
  552. if ( !(tied %dfsMap)->Flush() )
  553. {
  554. errmsg( "Problem Flush DFS commands." );
  555. return 0;
  556. }
  557. my ( $pLine ) = @_;
  558. ### Parse DFS path up to buildNo or latest.qly
  559. ### Hide the dirs if request qulity is pre/bvt.
  560. ### Otherwise, unhide the dirs.
  561. my @hideDirs = &GetDFSFilePath( $pLine->{Link}, $bldInfo{lang} );
  562. for my $theHideDir ( @hideDirs )
  563. {
  564. ### set to avoid warning / actually first used to get return value
  565. my $attribs = 0;
  566. my $tobeHidden= ( $bldInfo{qly} =~/^(bvt|pre)$/i)?1:0;
  567. if ( !GetAttributes( $theHideDir, $attribs ) )
  568. {
  569. wrnmsg( "Unable to get current hidden/unhidden status of $_ ($^E) -- skipping." );
  570. }
  571. my $isHidden = ( $attribs & 2 );
  572. if( $tobeHidden && !$isHidden )
  573. {
  574. wrnmsg( "Could not hide $theHideDir ($^E)." ) if(!SetAttributes( $theHideDir, $attribs | 2) );
  575. }
  576. elsif( !$tobeHidden && $isHidden )
  577. {
  578. wrnmsg( "Could not unhide $theHideDir ($^E)." ) if(!SetAttributes( $theHideDir, $attribs & ~2) );
  579. }
  580. }
  581. ### ???Create <build>.BLD / <build>.SRV file
  582. ### ???except the latest link with -safe is specified
  583. return 0 if( !&BldfileSetting( $pLine->{Link}, "update" ) );
  584. return 1;
  585. }
  586. #-----------------------------------------------------------------------------
  587. sub ReplicaDirsSetting
  588. {
  589. my ( $pLink, $pAct ) = @_;
  590. ### Parse the path up to lang: xpsp1\<build_id>\<lang>
  591. my $lastStr = $bldInfo{lang};
  592. $lastStr .= ".cov" if( $pLink =~ /usa/i && lc $bldInfo{lang} eq "cov" );
  593. for my $theDir( &GetDFSFilePath( $pLink, $lastStr ))
  594. {
  595. if( $pAct =~ /del/i && (-e $theDir) )
  596. {
  597. dbgmsg( "rd /q $theDir" );
  598. return 0 if( system("rd /q $theDir >nul 2>nul") );
  599. }
  600. elsif( !(-e $theDir ))
  601. {
  602. return 0 if( system("md $theDir") );
  603. }
  604. }
  605. return 1;
  606. }
  607. #-----------------------------------------------------------------------------
  608. sub BldfileSetting
  609. {
  610. my( $pLink, $pAction ) = @_;
  611. ###Parse the path up to platform: main\usa\<build_id>\<platform>
  612. my $lastStr = $bldInfo{lang};
  613. $lastStr .= ".cov" if( $pLink =~ /usa/i && lc $bldInfo{lang} eq "cov" );
  614. my @bldFileDir = &GetDFSFilePath( $pLink, $lastStr );
  615. for my $theDir ( @bldFileDir )
  616. {
  617. my @bldFiles = &comlib::globex( "$theDir\\*.$bldInfo{branch}.$bldInfo{platform}.BLD");
  618. if( lc $pAction eq "del" )
  619. {
  620. if(@bldFiles && !unlink @bldFiles ){wrnmsg( "Unable to unlink bldfile [$theDir\\$_]" );}
  621. next;
  622. }
  623. my $found;
  624. for my $file ( @bldFiles )
  625. {
  626. my $tmp= basename( $file );
  627. if( $tmp =~ /([^\\.]+)\..*\.$bldInfo{platform}/i )
  628. {
  629. if( $1 != $bldInfo{no} ){ unlink $file;next; }
  630. my @curQuality = &comlib::ReadFile( $file );
  631. if( lc $curQuality[0] eq lc $bldInfo{qly} ){ $found=1; last;}
  632. wrnmsg( "Unable delete [$file]." ) if( !unlink $file );
  633. }
  634. }
  635. next if( $found );
  636. if( !open ( BLDFILE, ">$theDir\\$buildNo.$bldInfo{branch}.$bldInfo{platform}.BLD" ) )
  637. {
  638. errmsg( "Unable to open [$theDir\\$buildNo$bldInfo{branch}.$bldInfo{platform}] for write." );
  639. return 0;
  640. }
  641. print BLDFILE "$bldInfo{qly}\n";
  642. close BLDFILE;
  643. }
  644. return 1;
  645. }
  646. #-----------------------------------------------------------------------------
  647. sub UnmapExistingNumberedLinks
  648. {
  649. my ( $pDfsInfo ) = @_;
  650. return 1 if( lc $bldInfo{qly} eq "sav" );
  651. for my $line ( @$pDfsInfo )
  652. {
  653. my @allShares = @{$dfsMap{$line->{Link}}} if ( exists $dfsMap{$line->{Link}} );
  654. @allShares = sort {lc($a) cmp lc($b) } @allShares;
  655. for my $theShare ( @allShares )
  656. {
  657. my( $shareNo ) = &ParseBuildNoFromShare( $theShare, $line->{Sku} );
  658. $shareNo =~ /^(\d+)(-\d+)?$/;
  659. my $no = $1;
  660. if( $no != $bldInfo{no} )
  661. {
  662. errmsg( "Invalid Share [$theShare] link to [$line->{Link}]." );
  663. return 0;
  664. }
  665. if( $bldInfo{shareno} lt $shareNo)
  666. {
  667. if( $fReplaceNumberLink )
  668. {
  669. dbgmsg( "Lowering [$line->{Link}] link to replace $shareNo with $bldInfo{shareno}" );
  670. return 0 if( !&RemoveShareFromMapping( $line->{Link}, $theShare ) );
  671. last;
  672. }
  673. errmsg( "Won't replace $shareNo with $bldInfo{shareno}" );
  674. return 0;
  675. }
  676. elsif( $bldInfo{shareno} gt $shareNo)
  677. {
  678. dbgmsg( "Lowering [$line->{Link}] link for $shareNo < $bldInfo{shareno}" );
  679. return 0 if( !&RemoveShareFromMapping( $line->{Link}, $theShare ) );
  680. }
  681. }
  682. }
  683. return 1;
  684. }
  685. #-----------------------------------------------------------------------------
  686. sub RemoveOldLatestDotQlyLinks
  687. {
  688. my ( $pLatestDfsInfo, $pNeedLatestLink ) = @_;
  689. return 1 if( lc $bldInfo{qly} eq "sav" );
  690. my ( @allLinks, @bldID );
  691. my $latestStr = "latest.$bldInfo{qly}";
  692. $$pNeedLatestLink = 2;
  693. for my $line ( @$pLatestDfsInfo )
  694. {
  695. ### (1)Examine all the links mapped to the current share
  696. my $curShare = "$line->{RootShare}$line->{SubShare}";
  697. my @allLinks = @{$dfsMap{$curShare}} if ( exists $dfsMap{$curShare} );
  698. ### Special rules for BVT and PRE:
  699. ### If we are currently at latest.bvt or latest.pre
  700. ### and are moving to another quality,
  701. ### remove latest.<bvt/pre>
  702. for( @allLinks )
  703. {
  704. if ( /latest\.(bvt|pre)/i && lc $1 ne lc $bldInfo{qly} )
  705. {
  706. my $holdLink = $line->{Link};
  707. $line->{Link} = $_;
  708. return 0 if( !&RemoveShareFromMapping($line->{Link}, $curShare) );
  709. $line->{Link} = $holdLink;
  710. next;
  711. }
  712. ### Enforce rule that you cannot move from a release quality
  713. ### latest.* (tst, idw, ids) to a non-release quality (pre, bvt)
  714. elsif( /latest\.([^\\]+)/i )
  715. {
  716. my $existQly = $1;
  717. if( !&RelQuality::AllowQualityTransition( $existQly, $bldInfo{qly} ) )
  718. {
  719. if ( !$fReplaceLatestLink )
  720. {
  721. errmsg( "Not allowed to move from [$1] to [$bldInfo{qly}] quality." );
  722. return 0;
  723. }
  724. wrnmsg( "Forcibly moving from [$1] to [$bldInfo{qly}] quality." );
  725. }
  726. }
  727. }
  728. ### (2)Examine all the shares mapped to the current link
  729. my @allShares = @{$dfsMap{$line->{Link}}} if ( exists $dfsMap{$line->{Link}} );
  730. for( my $i=0; $i<@allShares; $i++ )
  731. {
  732. my ( $shareNo ) = &ParseBuildNoFromShare( $allShares[$i], $line->{Sku} );
  733. ### (2-1)compare the existing share no/time with current share
  734. if ( $shareNo && ( $shareNo gt $bldInfo{shareno} ) )
  735. {
  736. if( $fReplaceLatestLink )
  737. {
  738. wrnmsg( "Forcibly moving latest.$bldInfo{qly} from $shareNo to $bldInfo{shareno}($bldInfo{time})." );
  739. return 0 if( !&RemoveShareFromMapping($line->{Link},$allShares[$i]) );
  740. }
  741. else
  742. {
  743. logmsg( "Found latest link [$line->{Link} is $shareNo, use '-replacelatest' to force replace." );
  744. if( $bldInfo{package} ne $ntPkg{3} )
  745. {
  746. $$pNeedLatestLink = 0;
  747. }
  748. else
  749. {
  750. if( $line->{Link} !~ /misc/i) { $$pNeedLatestLink &= (~1);}
  751. else { $$pNeedLatestLink &= (~2);}
  752. }
  753. }
  754. }
  755. elsif ( $shareNo && $shareNo ne $bldInfo{shareno} )
  756. {
  757. dbgmsg( "Lowering [$line->{Link}] link for $shareNo != $bldInfo{shareno}" );
  758. return 0 if( !&RemoveShareFromMapping($line->{Link}, $allShares[$i]) );
  759. }
  760. }
  761. ### (3) Also need to lower the current numbered share if we are the
  762. ### first entry in our latest.* link, as we don't want other
  763. ### shares that are not up at our quality to be accessible
  764. ### through the same number as ourselves
  765. if( !exists $dfsMap{ $line->{Link}} )
  766. {
  767. my $tLink = $line->{Link};
  768. $tLink =~ s/latest.$bldInfo{qly}/$buildNo/i;
  769. my @shares = @{$dfsMap{$tLink}} if ( exists $dfsMap{$tLink} );
  770. &RemoveShareFromMapping($tLink, $_ ) for ( @shares );
  771. }
  772. }
  773. return 1;
  774. }
  775. #-----------------------------------------------------------------------------
  776. sub IsLastLinkUnderParent
  777. {
  778. my ( $pLink, $pShare ) = @_;
  779. ### Verify if the link map to one share only
  780. my @allShares = @{$dfsMap{$pLink}} if( ( tied %dfsMap)->EXISTS( $pLink ) );
  781. return 0 if ( @allShares > 1 || ( @allShares && lc $pShare ne lc $allShares[0] ) );
  782. ### Check if this is the only link in the same dir
  783. ### Ignore test link
  784. ### Parse link to get parent dir and current entry
  785. $pLink =~ /^(.*)\\(.*)$/;
  786. my $parentDir = "$bldInfo{dfsroot}\\$1";
  787. my $curEntry = $2;
  788. my @allEntries = grep {$_ if ( -d $_ )} &comlib::globex( "$parentDir\\*") ;
  789. return 0 if( @allEntries > 2 );
  790. for( @allEntries )
  791. {
  792. my $existingEntry = basename($_);
  793. next if( $existingEntry =~ /$curEntry/i );
  794. next if( $existingEntry =~ /test/i );
  795. next if( $existingEntry =~ /$bldInfo{no}/i );
  796. return 0;
  797. }
  798. return 1;
  799. }
  800. #-----------------------------------------------------------------------------
  801. sub ParseBuildNoFromShare
  802. {
  803. my ( $pShare, $pSku ) = @_;
  804. if( lc $pSku eq "sym" )
  805. {
  806. return (build_number( $pShare ), build_date( $pShare ) );
  807. }
  808. if( $pShare =~ /^\\\\[^\\]+\\(\d+(?:-\d+)?)\.$bldInfo{branch}\.$bldInfo{platform}\.$bldInfo{lang}/i)
  809. {
  810. return( $1 || 0 );
  811. }
  812. if( $pShare =~ /^\\\\[^\\]+\\(\d+(?:-\d+)?)\.$bldInfo{branch}\.$pSku\.$bldInfo{lang}/i )
  813. {
  814. return( $1 || 0);
  815. }
  816. errmsg( "Unregnize share [$pShare]" );
  817. return( 0 );
  818. }
  819. #-----------------------------------------------------------------------------
  820. sub LowerBuildShare
  821. {
  822. my ( $pShareName ) = @_;
  823. ### lower release share
  824. if( !system( "rmtshare $pShareName >nul 2>nul" ) )
  825. {
  826. return 0 if( system( "rmtshare.exe $pShareName /DELETE >nul 2>nul" ));
  827. }
  828. return 1;
  829. }
  830. #-----------------------------------------------------------------------------
  831. sub GrantSharePermission
  832. {
  833. my ( $pShareName, $pPath ) = @_;
  834. ### Raise and Grant release share permission
  835. my $cmdLine;
  836. if( system( "rmtshare $pShareName >nul 2>nul" ) )
  837. {
  838. $cmdLine = "rmtshare $pShareName = $pPath";
  839. }
  840. else
  841. {
  842. $cmdLine = "rmtshare $pShareName";
  843. }
  844. for my $ID ( @accessMembers )
  845. {
  846. $cmdLine .= " /grant $ID:read";
  847. }
  848. my $retry;
  849. while( $retry < 3 )
  850. {
  851. my @output = `$cmdLine`;
  852. my $rc = $? >> 8;
  853. for( @output )
  854. {
  855. chomp;
  856. logmsg( "RMTSHARE: $_" );
  857. }
  858. logmsg( "Exit code: $rc" );
  859. return 1 if ( !$rc );
  860. logmsg( "Retry granting share permission..." );
  861. ++$retry;
  862. }
  863. wrnmsg( "Failed on Granting share permission as the following." );
  864. wrnmsg( "$cmdLine" );
  865. wrnmsg( "It might be a false system failure." );
  866. wrnmsg( "Please check it by issuing the following." );
  867. wrnmsg( "rmtshare $pShareName" );
  868. wrnmsg ( "The right user for [$bldInfo{qly}] is [@accessMembers]" );
  869. return 1;
  870. }
  871. #-----------------------------------------------------------------------------
  872. sub RemoveUnauthorizedUserFromShare
  873. {
  874. my ( $pShareName ) = @_;
  875. my $i;
  876. my %shareAccessIdPerm = &comlib::ParseNetShare( $pShareName, "Permissions:" );
  877. for my $oldId ( keys %shareAccessIdPerm )
  878. {
  879. for ( $i=0; $i < @accessMembers; $i++ )
  880. {
  881. last if( lc $oldId eq lc $accessMembers[$i] );
  882. }
  883. next if( $i < @accessMembers );
  884. my $cmdLine = "rmtshare $pShareName /remove $oldId >nul 2>nul";
  885. system( $cmdLine );
  886. }
  887. return 1;
  888. }
  889. #-----------------------------------------------------------------------------
  890. sub GetDfsAccess
  891. {
  892. my ( $pDfsMap, $pDfsLock ) = @_;
  893. logmsg( "Acquiring lock for exclusive DFS access..." );
  894. ### Define Semaphore location
  895. my $lock_Location;
  896. if( !($lock_Location = &GetIniSetting::GetSettingEx( $ENV{_BuildBranch}, $bldInfo{lang}, "DFSSemaphore") ))
  897. {
  898. errmsg( "[DFSSemaphore] is undefined in [$iniFile]." );
  899. return 0;
  900. }
  901. dbgmsg( "DFS Semaphore ........[$lock_Location]");
  902. ### Acquire DFS Semaphore lock
  903. if( !(${$pDfsLock} = new LockProc( $lock_Location, 60000) ) )
  904. {
  905. errmsg( "Problem acquiring lock using [$lock_Location]" );
  906. return 0;
  907. }
  908. dbgmsg( "Acquiring lock for exclusive DFS access..." );
  909. while ( !$$pDfsLock->Lock() )
  910. {
  911. errmsg ("Failed to acquire semaphore lock.");
  912. return 0;
  913. }
  914. ### Access DFS through a TIE hash
  915. logmsg( "Tie full DFS view [$bldInfo{dfsroot}] information." );
  916. if ( ! tie %$pDfsMap, 'DfsMap', $bldInfo{dfsroot} )
  917. {
  918. errmsg( "Error accessing DFS." );
  919. $$pDfsLock->Unlock();
  920. return 0;
  921. }
  922. return 1;
  923. }
  924. #-----------------------------------------------------------------------------
  925. sub GetDFSFilePath
  926. {
  927. my ( $pLink, $pLastStr)= @_;
  928. ### All known branches use the same writeable share format
  929. return 0 if( !$bldInfo{dfsbranch} );
  930. ### Get writeable DFS share for current branch
  931. my @dfsServerShare = &GetWriteableDfsShares;
  932. if( !@dfsServerShare )
  933. {
  934. errmsg( "Unknown writeable DFS share for $bldInfo{dfsbranch}." );
  935. return 0;
  936. }
  937. ### Trim the link up to $pLastStr
  938. my $dfsLink = $pLink;
  939. $dfsLink =~ s/^(.*$pLastStr)\\.*$/$1/;
  940. return map {"$_\\$dfsLink"} @dfsServerShare;
  941. }
  942. #-----------------------------------------------------------------------------
  943. sub GetWriteableDfsShares
  944. {
  945. ### All known branches use the same writeable share format
  946. return 0 if ( !$bldInfo{dfsbranch} );
  947. ### Get DFS host servers
  948. my @dfsServersShare = (tied %dfsMap)->GetDfsHosts();
  949. if ( !@dfsServersShare )
  950. {
  951. errmsg( "Unable to retrieve hosting servers for DFS root ". (tied %dfsMap)->GetDfsRoot(). "." );
  952. return 0;
  953. }
  954. s/(\\\\[^\\]+).*/$1\\writer\$\\release/ foreach ( @dfsServersShare );
  955. return @dfsServersShare;
  956. }
  957. #-----------------------------------------------------------------------------
  958. sub FoundSameLangNoLink
  959. {
  960. my ( $pDfsInfo ) = @_;
  961. ### Checking if there is same lang\number links with different
  962. ### <Arch><Type> as the current build
  963. ### If found, do not remove Conglomertaor and neutral mui links.
  964. for my $platform ( keys %validPlatform )
  965. {
  966. my $skip;
  967. for ( @linkNode ){ if( $_ =~ /$platform/ ){$skip=1;last; } }
  968. next if($skip);
  969. for my $line ( @$pDfsInfo )
  970. {
  971. $line->{Link} =~ s/(.+\\)([^\\]+)$/$1$platform/;
  972. return 1 if( ( tied %dfsMap)->EXISTS( $line->{Link} ) );
  973. }
  974. }
  975. return 0;
  976. }
  977. #-----------------------------------------------------------------------------
  978. 1;
  979. __END__
  980. :endperl
  981. @echo off
  982. if not defined seterror (
  983. set seterror=
  984. for %%a in ( seterror.exe ) do set seterror=%%~$PATH:a
  985. )
  986. @%seterror% %RETURNVALUE%