1 #if !PLATFORM_WINDOWS 2 // 3 // Copyright (c) 2010-2025 Antmicro 4 // Copyright (c) 2011-2015 Realtime Embedded 5 // 6 // This file is licensed under the MIT License. 7 // Full license text is available in 'licenses/MIT.txt'. 8 // 9 using System; 10 using System.IO; 11 using System.Runtime.InteropServices; 12 using Mono.Unix.Native; 13 14 namespace Antmicro.Renode.Utilities 15 { 16 public class PosixFileLocker : IDisposable 17 { PosixFileLocker(string fileToLock)18 public PosixFileLocker(string fileToLock) 19 { 20 file = fileToLock; 21 fd = Syscall.open(fileToLock, OpenFlags.O_CREAT | OpenFlags.O_RDWR, FilePermissions.DEFFILEMODE); 22 if(!TryDoFileLocking(fd, true)) 23 { 24 throw new InvalidOperationException("File {0} not locked.".FormatWith(file)); 25 } 26 } 27 Dispose()28 public void Dispose() 29 { 30 if(!TryDoFileLocking(fd, false)) 31 { 32 throw new InvalidOperationException("File {0} not unlocked.".FormatWith(file)); 33 } 34 Syscall.close(fd); 35 } 36 TryDoFileLocking(int fd, bool lockFile, FlockOperation? specificFlag = null)37 private static bool TryDoFileLocking(int fd, bool lockFile, FlockOperation? specificFlag = null) 38 { 39 if (fd >= 0) 40 { 41 int res; 42 Errno lastError; 43 do 44 { 45 res = Flock(fd, specificFlag ?? (lockFile ? FlockOperation.LOCK_EX : FlockOperation.LOCK_UN)); 46 lastError = Stdlib.GetLastError(); 47 } 48 while(res != 0 && lastError == Errno.EINTR); 49 // if can't get lock ... 50 return res == 0; 51 } 52 return false; 53 } 54 55 private readonly int fd; 56 private readonly string file; 57 58 [DllImport("libc", EntryPoint = "flock")] Flock(int fd, FlockOperation operation)59 private extern static int Flock(int fd, FlockOperation operation); 60 61 [Flags] 62 private enum FlockOperation 63 { 64 LOCK_SH = 1, 65 LOCK_EX = 2, 66 LOCK_NB = 4, 67 LOCK_UN = 8 68 } 69 } 70 } 71 #endif 72