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