Re: Checking if File Open

new topic     » goto parent     » topic index » view thread      » older message » newer message

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

new topic     » goto parent     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu