Re: Checking if File Open
- Posted by Derek Parnell <ddparnell at bigpond.com> Jun 30, 2005
- 549 views
OtterDad wrote: > > as much as i hate to commit on-line suicide by questioning Derek, a question > comes to mind. your example appears to handle only files opened by Euphoria > itself, which has no true open shared mode. would your code work to read a > file opened by another language, say PowerBuilder, which supports files > opened in a shared mode by multiple users? > > a trick i often use to test if a file is REALLY closed, is to use a WinAPI > call to move the file to a temp directory and then back home again. the OS > won't move files opened in shared mode. I made the silly mistake of assuming that Euphoria locked files when it opened them. It doesn't! So here is a routine that might be helpful ...
-- File: openlock.e -- Author: Derek Parnell, Melbourne -- Copyright: (c) 2005 -- Licence: Public Domain --======================================== -- function: openlocked(sFileName, sMode, aTimeOut ) -- description: Opens and locks a file. -- return: sequence { iCode, iData, aResidual } -- -- This attempts to open the file 'sFileName' (a sequence) -- with the mode 'sMode' (a sequence). The valid modes are -- the same as supported by the Euphoria 'open' function. -- If the file is already locked, the function will wait -- up to 'aTimeOut' seconds for it to be unlocked. -- If the function succeeds in opening the file, it will -- also lock it to prevent other attempts to write to -- it to fail. -- -- The function returns a sequence. The first element of the -- return is a code that indicates if it was successful or not. -- A 'iCode' (integer) value of 0 (zero) means that the function -- failed to open the file. In this case, the 'iData' element -- is one of -- OPENLOCK_NotFound -- OPENLOCK_Timeout -- OPENLOCK_Folder -- OPENLOCK_Readonly -- that identifies the reason for failure. Further more, if the -- reason is OPENLOCK_Timeout then the 'aResidual' element has -- the value 0 (zero) if the file was locked by a non-Euphoria -- process otherwise the file was locked by a Euphoria process. -- -- A 'iCode' (integer) value of 1 (zero) means that the function -- succeded in opening and locking the file. The 'iData' element -- is the file handle you must subsequently use for file operations -- with the file, and 'aResidual' is either -1 to indicate that -- the function did not have to wait for the file to be unlocked, -- otherwise it is the number of seconds it waited before opening -- the file. -- Example: -- sequence lResult -- int lFH -- -- lResult = openlocked(theFile, theMode, 5) -- if lResult[1] = 0 then -- if lResult[2] = OPENLOCK_NotFound then -- lResult = '"' & theFile & '"' & " does not exist." -- elsif lResult[2] = OPENLOCK_Timeout then -- lResult = '"' & theFile & '"' & " is currently locked." -- elsif lResult[2] = OPENLOCK_Folder then -- lResult = '"' & theFile & '"' & " is a directory." -- elsif lResult[2] = OPENLOCK_Readonly then -- lResult = '"' & theFile & '"' & " is a Read-Only file." -- else -- lResult = '"' & theFile & '"' & " failed to open." -- end if -- else -- lFH = lResult[2] -- end if include file.e global constant OPENLOCK_NotFound = 1, OPENLOCK_Timeout = 2, OPENLOCK_Folder = 3, OPENLOCK_Readonly = 4 global function openlocked(sequence pFileName, sequence pMode, atom pTimeOut) integer lHandle integer lWaiting object lDirInfo atom lEndTime lWaiting = 0 while 1 do lHandle = open(pFileName, pMode) if lHandle = -1 then lDirInfo = dir(pFileName) if equal(lDirInfo,-1) then return {0, OPENLOCK_NotFound} end if if find('d', lDirInfo[1][D_ATTRIBUTES]) != 0 then return {0, OPENLOCK_Folder} end if if pMode[1] = 'w' and find('r', lDirInfo[1][D_ATTRIBUTES]) != 0 then return {0, OPENLOCK_Readonly} end if if lWaiting = 0 then -- Assume its locked, so wait for it to be freed up. lEndTime = time() + pTimeOut lWaiting = 1 else if lEndTime < time() then return {0, OPENLOCK_Timeout, 0} end if end if else -- File was opened by me lDirInfo = lock_file(lHandle, LOCK_SHARED, {}) if lWaiting = 0 then if lDirInfo != 0 then -- I've opened and locked it! return {1, lHandle, -1} end if -- Couldn't lock it, so set timeout lWaiting = 1 lEndTime = time() + pTimeOut else if lDirInfo != 0 then -- It is no longer locked. return {1, lHandle, pTimeOut - lEndTime - time()} end if if lEndTime < time() then close(lHandle) return {0, OPENLOCK_Timeout, 1} end if end if close(lHandle) end if end while end function
-- Derek Parnell Melbourne, Australia irc://irc.sorcery.net:9000/euphoria