Advertisement
Guest User

Untitled

a guest
Oct 20th, 2018
441
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. using namespace System.IO
  2. using namespace System.Xml.Linq
  3. [Reflection.Assembly]::LoadWithPartialName("System.Xml.Linq") | Out-Null
  4. $ErrorActionPreference = "Stop"
  5.  
  6. function Reserve-WritePermissions
  7. {
  8.     Param
  9.     (
  10.         [Parameter(Mandatory)]
  11.         [Alias("LockfilePath")]
  12.         [PSObject]$lockfile_path
  13.     )
  14.  
  15.     #Attempt to create the lock file.  If this fails, someone else is already updating.
  16.     try
  17.     {
  18.         $lock_stream = [System.IO.File]::Open($lockfile_path, [FileMode]"CreateNew", [FileAccess]"ReadWrite")
  19.         $lock_writer = [System.IO.StreamWriter]::new($lock_stream)
  20.         $lock_writer.WriteLine([Environment]::UserName)
  21.         $lock_writer.WriteLine([DateTime]::Now.ToString())
  22.         return $true #We were able to reserve write permissions
  23.     }
  24.     catch
  25.     {
  26.         $permissions = Check-WritePermissions -LockfilePath $lockfile_path
  27.         if($permissions -eq $null)
  28.         {
  29.             Write-Host "When you first attempted to reserve write permissions, a reservation already existed." -ForegroundColor Red
  30.             Write-Host "By the time we checked to see who had reserved it, the reservation had already cleared." -ForegroundColor Red
  31.             Write-Host "Please try again." -ForegroundColor Red
  32.         }
  33.         else
  34.         {
  35.             Notify-NoWritePermissions -PermissionsObject $permissions -LockfilePath $lockfile_path
  36.         }
  37.     }
  38.     finally
  39.     {
  40.         if($lock_writer -ne $null)
  41.         { $lock_writer.Dispose() }
  42.         if($lock_stream -ne $null)
  43.         { $lock_stream.Dispose() }
  44.     }
  45.     return $false
  46. }
  47.  
  48. function Check-WritePermissions
  49. {
  50.     Param
  51.     (
  52.         [Parameter(Mandatory)]
  53.         [Alias("LockfilePath")]
  54.         [string]$lockfile_path
  55.     )
  56.  
  57.     if((Test-Path $lockfile_path) -eq $false)
  58.     { return $null }
  59.  
  60.     try
  61.     {
  62.         $lock_contents = Get-Content $lockfile_path
  63.         return Create-WritePermissionsObject -LockfileContents $lock_contents
  64.     }
  65.     catch [System.Management.Automation.ItemNotFoundException]
  66.     {
  67.         # We *HAD* a lock file, but it was deleted in between our previous test, and this one
  68.         # So, return $null indicating that we SHOULD have permissions
  69.         return $null
  70.     }
  71. }
  72.  
  73. function Notify-NoWritePermissions
  74. {
  75.     Param
  76.     (
  77.         [Parameter(Mandatory)]
  78.         [Alias("PermissionsObject")]
  79.         [PSObject]$permissions_object,
  80.         [Parameter(Mandatory)]
  81.         [Alias("LockfilePath")]
  82.         [PSObject]$lockfile_path
  83.     )
  84.  
  85.     if($permissions_object -eq $null)
  86.     { $permissions_object = Check-WritePermissions -LockfilePath $lockfile_path }
  87.  
  88.     if(($permissions_object -eq $null) -or ($permissions_object.DateTime -eq [DateTime]::MinValue))
  89.     {
  90.         Write-Host "There was a problem checking for an existing reservation." -ForegroundColor Red
  91.         Write-Host "Please ensure there is no one updating the database, then delete the file located at $lockfile" -ForegroundColor Red
  92.         return
  93.     }
  94.  
  95.     Write-Host "$($permissions_object.Username) has been updating the database since $($permissions_object.DateTime)." -ForegroundColor Red
  96.     Write-Host "Please wait for $($permissions_object.Username) to complete their work." -ForegroundColor Red
  97.     Write-Host "If you would like to cancel the session, and discard their changes:" -ForegroundColor Red
  98.     Write-Host "`tIf possible, contact $($permissions_object.Username) to confirm they are not working on anything important." -ForegroundColor Red
  99.     Write-Host "`tThen, delete the file located at $lockfile" -ForegroundColor Red
  100.     return
  101. }
  102.  
  103. function Create-WritePermissionsObject
  104. {
  105.     Param
  106.     (
  107.         [Parameter(Mandatory)]
  108.         [Alias("LockfileContents")]
  109.         [string[]]$lockfile_contents
  110.     )
  111.  
  112.  
  113.     if($lock_contents.Length -ne 2)
  114.     {
  115.         return New-Object PSObject -Property @{
  116.             'Username' = "Unknown"
  117.             'DateTime' = [DateTime]::MinValue
  118.         }
  119.     }
  120.  
  121.     $datetime = [DateTime]::MinValue
  122.     # I don't need to check to see if this succeeded.  If it didn't, the DateTime will be [DateTime]::MinValue, which is what I'm using to signal failure.
  123.     [DateTime]::TryParse($lock_contents[1], [ref]$datetime)
  124.  
  125.     return New-Object PSObject -Property @{
  126.         'Username' = $lock_contents[0]
  127.         'DateTime' = $datetime
  128.     }
  129. }
  130.  
  131. function CommitOrCancel-Changes
  132. {
  133.     Param
  134.     (
  135.         [Parameter(Mandatory)]
  136.         [XElement]$database,
  137.         [Parameter(Mandatory)]
  138.         [Alias("DatabasePath")]
  139.         [string]$database_path,
  140.         [Parameter(Mandatory)]
  141.         [Alias("LockfilePath")]
  142.         [string]$lockfile_path,
  143.         [Parameter(Mandatory)]
  144.         [bool]$commit
  145.     )
  146.  
  147.     #Before saving the file, make *SURE* we have permissions.  It's possible someone has revoked our permissions in the meantime.
  148.     $permissions_object = Check-WritePermissions -LockfilePath $lockfile_path
  149.     if($permissions_object -eq $null)
  150.     {
  151.         #Somehow, we lost permissions, and no one else has them.
  152.  
  153.         #If we're cancelling, just exit the function; we don't have the permissions anyway
  154.         if($commit -eq $false)
  155.         { return $true } #We were able to cancel
  156.  
  157.         #We're committing...
  158.         #So, try to reserve them again.  If this works, just move on.
  159.         if((Reserve-WritePermissions -LockfilePath $lockfile_path) -eq $false)
  160.         { #If it fails, notify and abort
  161.             Notify-NoWritePermissions -PermissionsObject $null -LockfilePath $lockfile_path
  162.             return $false #We were not able to commit
  163.         }
  164.     }
  165.     else
  166.     {
  167.         #We have a permissions object.  Make sure it's ours.
  168.         if($permissions_object.Username -ne [Environment]::UserName)
  169.         {
  170.             Notify-NoWritePermissions $permissions_object -LockfilePath $lockfile_path
  171.             return $false
  172.         }
  173.     }
  174.  
  175.     #By now, we have confirmed that we have permissions.
  176.     #If we're committing....
  177.     if($commit)
  178.     {
  179.         #Go ahead and save the file.  There is a small chance of a race condition happening, and we may overwrite someone's changes.... We've done our best.
  180.         $database.Save($database_path)
  181.     }
  182.  
  183.     #Delete our reservation
  184.     Remove-Item $lockfile_path
  185.     return $true
  186. }
  187.  
  188. function Open-Write
  189. {
  190.     Param
  191.     (
  192.         [Parameter(Mandatory)]
  193.         [Alias("DatabasePath")]
  194.         [string]$database_path,
  195.         [Parameter(Mandatory)]
  196.         [Alias("LockfilePath")]
  197.         [string]$lockfile_path
  198.     )
  199.    
  200.     # First, just check to see if someone has a reservation, instead of trying to make one first.
  201.     $reservation = Check-WritePermissions -LockfilePath $lockfile_path
  202.     if($reservation -ne $null)
  203.     {
  204.         Notify-NoWritePermissions -LockfilePath $lockfile_path -PermissionsObject $reservation
  205.         return
  206.     }
  207.  
  208.     # Now, actually try to make a reservation
  209.     if((Reserve-WritePermissions -LockfilePath $lockfile_path) -eq $false)
  210.     {
  211.         # If this failed, it means someone made a reservation in between our first check, and our actual attempt.
  212.         # Reserve-WritePermissions notifies the user
  213.         return
  214.     }
  215.  
  216.  
  217.     try
  218.     {
  219.         $database = [XElement]::Load($database_path)
  220.         $switchesnode = $database.Element("Switches")
  221.  
  222.         $hostname = Read-Host "Enter the new hostname ('quit' to quit)"
  223.         while($hostname -ne "quit")
  224.         {
  225.             $switchesnode.Add([XElement]::new([XName]"Switch", [XAttribute]::new([XName]"Hostname", $hostname)))
  226.             $hostname = Read-Host "Enter the new hostname ('quit' to quit)"
  227.         }
  228.  
  229.         if((CommitOrCancel-Changes -Database $database -DatabasePath $database_path -LockfilePath $lockfile_path -Commit $true) -eq $false)
  230.         {
  231.             Write-Host "Something went wrong... $($_.Exception.Message)" -ForegroundColor Red
  232.             Write-Host "Reverting changes..." -ForegroundColor Red
  233.             if((CommitOrCancel-Changes -Database $database -DatabasePath $database_path -LockfilePath $lockfile_path -Commit $false) -eq $false)
  234.             {
  235.                 Write-Host "*** Was not able to release the file lock.  Open $lockfile_path and ensure it is reserved to you.  If so, delete that file. ***" -ForegroundColor Red
  236.             }
  237.         }
  238.     }
  239.     catch
  240.     {
  241.         Write-Host "Something went wrong... $($_.Exception.Message)" -ForegroundColor Red
  242.         Write-Host "Reverting changes..." -ForegroundColor Red
  243.         if((CommitOrCancel-Changes -Database $database -DatabasePath $database_path -LockfilePath $lockfile_path -Commit $false) -eq $false)
  244.         {
  245.             Write-Host "*** Was not able to release the file lock.  Open $lockfile_path and ensure it is reserved to you.  If so, delete that file. ***" -ForegroundColor Red
  246.         }
  247.     }
  248. }
  249.  
  250. function Open-Read()
  251. {
  252.     Param
  253.     (
  254.         [Parameter(Mandatory)]
  255.         [Alias("DatabasePath")]
  256.         [string]$database_path
  257.     )
  258.  
  259.     $database = [XElement]::Load($database_path)
  260.  
  261.     if($database -eq $null)
  262.     { return }
  263.  
  264.     $switchesnode = $database.Element("Switches")
  265.     foreach($switch in $switchesnode.Elements())
  266.     {
  267.         Write-Host $switch.Attribute("Hostname").Value
  268.     }
  269. }
  270.  
  271.  
  272.  
  273.  
  274.  
  275. $filename = "C:\Temp\database.xml"
  276. $lockfile = "C:\Temp\file_lock.txt"
  277.  
  278.  
  279. cls
  280.  
  281. Write-Host "1.) Open Read-only, query switches"
  282. Write-Host "2.) Open Read-Write, add switches"
  283. $option = Read-Host "Enter an option"
  284.  
  285. if($option -eq '1')
  286. {
  287.     Open-Read -DatabasePath $filename
  288. }
  289. else
  290. {
  291.     Open-Write -DatabasePath $filename -LockfilePath $lockfile
  292. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement