locked
How to check if a file/folder is writable or not? RRS feed

  • Question

  • Hi,

    I need to check two things:

    1) If a file exists at specified path, Is it writable?

    2) If file doesn't exist, Can it be created at the same path?

    For the first part, I first check ACL level permissions of the file. If ACL allows writability then I check for "read-only" attribute.

    For the second part, I just check the ACL level permissions of the folder.

    This logic is working fine for the local files. But sometimes gives wrong results in case of shared file/folder.

    For example, it's  failing when we check writability of a file whose parent folder is shared from a Linux machine. FYI, Windows ACL is enabled for this folder. Read-write access is given to current user for this folder but below code returns false.

    Also, when the folder is shared from Mac, then GetFileSecurityW gives error "ERROR_NOT_SUPPORTED".

    Below is the code, I use to check the ACL level permissions of file/folder:

    bool HaveWriteAccess ( const std::string & widePath )
    {
    bool writable = false;

    DWORD length = 0;
    LPCWSTR pathLPtr = (LPCWSTR)widePath.data();
    const static SECURITY_INFORMATION requestedFileInfomration =  OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION;

    if (!::GetFileSecurityW( pathLPtr, requestedFileInfomration, NULL, NULL, &length ) && ERROR_INSUFFICIENT_BUFFER == ::GetLastError())
    {
    std::string tempBuffer;
    tempBuffer.reserve(length);
    PSECURITY_DESCRIPTOR security = (PSECURITY_DESCRIPTOR)tempBuffer.data();
    if ( security && ::GetFileSecurity( pathLPtr, requestedFileInfomration, security, length, &length ) )
    {
    HANDLE hToken = NULL;
    const static DWORD tokenDesiredAccess = TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_DUPLICATE | STANDARD_RIGHTS_READ;
    if ( !::OpenThreadToken( ::GetCurrentThread(), tokenDesiredAccess, TRUE, &hToken) )
    {
    if ( !::OpenProcessToken( GetCurrentProcess(), tokenDesiredAccess, &hToken ) )
    {
    XMP_Throw ( "Unable to get any thread or process token", kXMPErr_InternalFailure );
    }
    }

    HANDLE hImpersonatedToken = NULL;
    if ( ::DuplicateToken( hToken, SecurityImpersonation, &hImpersonatedToken ) )
    {
    GENERIC_MAPPING mapping = { 0xFFFFFFFF };
    PRIVILEGE_SET privileges = { 0 };
    DWORD grantedAccess = 0, privilegesLength = sizeof( privileges );
    BOOL result = FALSE;

    mapping.GenericRead = FILE_GENERIC_READ;
    mapping.GenericWrite = FILE_GENERIC_WRITE;
    mapping.GenericExecute = FILE_GENERIC_EXECUTE;
    mapping.GenericAll = FILE_ALL_ACCESS;

    DWORD genericAccessRights = FILE_GENERIC_WRITE;
    ::MapGenericMask( &genericAccessRights, &mapping );

    if ( ::AccessCheck( security, hImpersonatedToken, genericAccessRights, &mapping, &privileges, &privilegesLength, &grantedAccess, &result ) )
    {
    writable = (result == TRUE);
    }
    ::CloseHandle( hImpersonatedToken );
    }

    ::CloseHandle( hToken );
    }
    }
    return writable;
    }

    I have two questions:

    1) Why does it give wrong results in case of above described Linux and Mac case ?

    2) If I check the writability of the file by trying to open it in write mode (using CreateFileW()) then everything works perfect. So, is the logic used internally by CreateFileW() different from what I am doing here?

    Tuesday, September 3, 2013 1:27 PM

All replies

  • 1) If a file exists at specified path, Is it writable?

    Not necessarily. For example the file would be locked by another program

    2) If file doesn't exist, Can it be created at the same path?

    Not necessarily. For you may only have read only permission on the folder.

    1) Why does it give wrong results in case of above described Linux and Mac case ?

    The required Access Control model is only available on NTFS partitions.

    >If I check the writability of the file by trying to open it in write mode (using CreateFileW()) then everything works perfect. So, is the logic used internally by CreateFileW() different from what I am doing here?

    Yes. the only way to check the writability of a file is to actually write to it.



    Visual C++ MVP



    Friday, September 13, 2013 9:03 PM
  • Thanks Sheng for the response.

    Yes. the only way to check the writability of a file is to actually write to it.

    This solution is acceptable to check the writability of the file but what about the case when file doesn't exist. We also need to check whether it can be created or not. How can we check relevant permissions on the parent folder in that case ?

    Wednesday, September 18, 2013 7:27 AM
  • So? Try to create the file. If that fails, it obviously cannot be created, and if it succeeds then you can delete it right away, or just use it for whatever purpose you are checking the writability anyway.
    • Proposed as answer by Jan Ringoš Sunday, October 26, 2014 12:40 AM
    Wednesday, September 18, 2013 11:43 AM