/*** Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: FileAdvisory.Unix.cpp Date: 2022-1-29 Author: Reece ***/ #include #include "FS.hpp" #include "FileAdvisory.Unix.hpp" #include #if defined(AURORA_COMPILER_CLANG) // warning: enumeration values 'kEnumCount' and 'kEnumInvalid' not handled in switch [-Wswitch #pragma clang diagnostic ignored "-Wswitch" // Yea, I don't give a shit. #endif namespace Aurora::IO::FS { bool ApplyDumbAdvisoryLock(int fd, EFileAdvisoryLockLevel level) { #if !defined(AURORA_IS_LINUX_DERIVED) int operation = LOCK_NB; switch (level) { case EFileAdvisoryLockLevel::eEnumCount: case EFileAdvisoryLockLevel::eNoSafety: return true; case EFileAdvisoryLockLevel::eBlockWrite: operation |= LOCK_SH; break; case EFileAdvisoryLockLevel::eBlockReadWrite: operation |= LOCK_EX; break; } // Assume: // "Furthermore, the lock is release either by an explicit LOCK_UN // operation on any of these duplicate file descriptors, or when // all such file descriptors have been closed" return ::flock(fd, operation) == 0; #else // Linux int lease {}; switch (level) { case EFileAdvisoryLockLevel::eEnumCount: case EFileAdvisoryLockLevel::eNoSafety: return true; case EFileAdvisoryLockLevel::eBlockWrite: lease = F_RDLCK; break; case EFileAdvisoryLockLevel::eBlockReadWrite: lease = F_RDLCK; break; } // Ignore warning bc idc // I assume c++ compilers under posix land allow for struct init the c way struct flock lck = { .l_whence = SEEK_SET, .l_start = 0, .l_len = 0, .l_type = lease }; // Assume this is true: // * If a process closes any file descriptor referring to a file, // then all of the process's locks on that file are released, // regardless of the file descriptor(s) on which the locks were // obtained. This is bad: it means that a process can lose its // locks on a file such as /etc/passwd or /etc/mtab when for some // reason a library function decides to open, read, and close the // same file. // [...] // // Open file description locks solve both of these problems. // // OFD's description implies it inherits non-ofd behaviour // I wanted to confirm a l_len zero would work to lock all contents, // even on expansion of the file. The docs didn't mention anything; // however, I don't really see any real difference len processing in // the kernel. Furthermore, I saw the kernels implementation checking // for MAX_OFFSET of int type (-1) before overloading l_len with zero. // // I assume this will work. Linux locking is trash. return ::fcntl(fd, F_OFD_SETLK, &lck) == 0; #endif } }