The code below is Windows native and meant to protect against multiple processes attempt to rename the same file simultaneously - what may cause data loss. In simple, what the code does, is exclusively open the file for current process/thread, then check if renaming is needed, and finally write to the file.
consider a case where 2 processes attempt to run the code below simultaneously. Without exclusive access, the renaming operation may occurs twice, So that on the second renaming, the original file will be overrun by an empty file and all the data will be lost.
I'd like to port this logic into macOS, so I'm looking for an equivalent locking mechanism on the file before deciding to rename it (programmatic locking). both objectiveC or C/C++/POSIX are good options.
Specifically, I'm looking for a macOS equivalent native Windows function CreateFile
as called in the following implementation :
while (!handle) {
handle = CreateFile(currFile,
GENERIC_WRITE | DELETE, //dwDesiredAccess
FILE_SHARE_READ, //dwShareMode
NULL, //lpSecurityAttributes
OPEN_ALWAYS, //dwCreationDisposition
FILE_ATTRIBUTE_NORMAL, // dwFlagsAndAttributes
NULL);
if(!handle)
sleep(...) // retry after sleep
}
// NOTE : This stage is reached exclusively for all processes/threads
// create c style file pointer for current file.
int chandle = _open_osfhandle((intptr_t)handle, _O_APPEND);
FILE* f = _wfdopen(chandle, L"a+");
if (std::filesystem::file_size(currFile) > MAX_SIZE)
{
std::wstring prevName = currFile + L".prev";
DWORD buffSz = (DWORD)
(sizeof(FILE_RENAME_INFO) +
prevName.length() * sizeof(WCHAR)
+ 16);
FILE_RENAME_INFO *renameInfo = (FILE_RENAME_INFO *)malloc(buffSz);
renameInfo->ReplaceIfExists = TRUE;
renameInfo->RootDirectory = NULL;
renameInfo->FileNameLength = (DWORD)prevName.length()*2;
wcscpy_s(renameInfo->FileName, prevNAme.length() + 2, prevName.c_str());
//notice that the 'f' still point on the original file name
BOOL res = SetFileInformationByHandle(handle, FileRenameInfo, renameInfo, buffSz);
}
...
// now print message to the original file name using 'f'
fprintf(f, "blablabla");