Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Win32 alternative for _access() C library function? _access() seems broken..

1,388 views
Skip to first unread message

Greg Ercolano

unread,
Apr 11, 2005, 2:15:11 AM4/11/05
to
Is there a WIN32 function similar to the _access() C library
function?

I need an alternative to _access(), because _access() appears
to be broken; it's saying files are writeable when they're not..
(see '** BAD ** below). The environment is Win2K with a VC.NET 7.0
compiler.

I guess I should report this as a security bug to MS.

Meanwhile, I'm hoping that there's a similar Win32 function
that actually works for detect r/w access for files *and directories*.

In my real app (not shown) needs to check for access problems
with files and directories before actually opening or creating files.

I'm not sure I see an equivalent for _access() in Win32.

-------------------------------------------------------------------------------------
C:\temp>type check-bar.c <-- view test program
// Simple program to test access() function
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
#include <errno.h>
#include <string.h>
main()
{
// ACCESS TEST
if ( _access("bar", 6) == 0 ) { printf("access() says bar is OK to r/w. (NO IT'S NOT!)\n"); }
else { perror("_access(bar,6) NOT writable (EXPECT THIS), reason:"); }

// OPEN TEST
{
int fd = _open("bar", O_WRONLY|O_APPEND);
if ( fd == -1 ) { perror("open(bar) fails, as we expect"); }
else { printf("open(bar) OK\n"); close(fd); }
}
}

C:\temp>cl check-bar.c <-- compile it
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13.00.9466 for 80x86
Copyright (C) Microsoft Corporation 1984-2001. All rights reserved.
[..]
/out:check-bar.exe
check-bar.obj

C:\temp>.\check-bar.exe <-- run it
access() says bar is OK to r/w. (NO IT'S NOT!) <-- ** BAD **
open(bar) fails, as we expect: Permission denied <-- OK

C:\temp>echo > bar <-- OK: verify we have NO access..
Access is denied. <-- OK: expect this, we can't access file

C:\temp>echo %USERNAME% <-- OK: Reason: we are 'barney'..
barney
^^^^^^

C:\temp>cacls bar <-- OK: ..and file is accessable..
C:\temp\bar GENEVA\fred:F <-- OK: only to 'fred'
^^^^
----------------------------------------------------------------------------------

Sten Westerback

unread,
Apr 11, 2005, 8:14:55 AM4/11/05
to

"Greg Ercolano" <er...@3dsite.com> wrote in message
news:PBo6e.4293$xN....@fe05.lga...

First of all.. are you sure you are accessing the correct bar ? :=)
That is, are you sure you haven't got another "bar" file in the
default folder used by the process than the one you think you are
testing.

Anyway, to test using WINAPI, CreateFile() is the easiest way.
You could also read the fields security descriptor yourself and
analyse it to find out what access you have. But why not just
find out what access you have by accessing...

- Sten

Greg Ercolano

unread,
Apr 12, 2005, 9:53:36 PM4/12/05
to
>> [..]
>> I'm hoping that there's a similar Win32 function (to _access())

>> that actually works for detect r/w access for files *and directories*.
>>
>> [..] my real app (not shown) needs to check for access problems

>> with files and directories before actually opening or creating files.

Sten writes:
> [..] are you sure you haven't got another "bar" file in the
> default folder

Yes, quite sure.

After posting here, and doing more tests, I was convinced _access()
was broken enough to phone it in to Microsoft as a bug, and they
confirmed it today.

> Anyway, to test using WINAPI, CreateFile() is the easiest way.

Hmm, but then I'm modifying the file system.

This is why I'm using _access(); a non-intrusive write access test.

In my situation, other apps are constantly reading/creating
files in the target directory at all times, and I can't risk race
conditions with those apps (I don't have control over their code).

Regarding testing /existing/ files for write access, Microsoft
recommended using the following workaround:

fopen("bar", "r+")

..which will apparently test for write access in a non-intrusive
way for an exsiting file.

Trouble is that won't work for checking directory write access..
the incedent is still open.

> You could also read the fields security descriptor yourself and
> analyse it to find out what access you have.

That sounds like the correct solution, but the question is
what function(s) should I be looking at to test for access.
I'm not very familiar with the WinAPI with respect to security stuff.

Testing for access involves 1) getting the file|dir attributes,
2) getting the user attributes, 3) comparing the two in a reliable
manner for a test.

I imagine the only clean way to do the above is a single Win32 function
that does all three. Doing those separately in my app would only be
prone to error, if the underlying security system is enhanced.

This is the reason _access() is so useful; it hides the
security internals from the app.

> But why not just find out what access you have by accessing...

Needs to be non-intrusive.

Ralf Buschmann

unread,
Apr 13, 2005, 5:23:16 AM4/13/05
to
Am 13.04.2005 03:53:36 schrieb Greg Ercolano:

>> But why not just find out what access you have by accessing...
>
> Needs to be non-intrusive.

Try AccessCheck() API.

--
Ralf.

Greg Ercolano

unread,
Apr 13, 2005, 11:47:13 AM4/13/05
to

Much thanks.. that looks like the right direction.

Will follow up with a code snippet if I figure it out..

r_z_...@pen_fact.com

unread,
Apr 13, 2005, 3:35:02 PM4/13/05
to
On Tue, 12 Apr 2005 18:53:36 -0700, Greg Ercolano <er...@3dsite.com>
wrote:

clip


>
> Regarding testing /existing/ files for write access, Microsoft
> recommended using the following workaround:
>
> fopen("bar", "r+")
>
> ..which will apparently test for write access in a non-intrusive
> way for an exsiting file.

I'm glad someone gave you a lead on a real solution. But I'm still
curious about this workaround. I'm under the impression that Microsoft
uses CreateFile in its implementation of fopen. So I don't see how
using fopen has any advantages over using CreateFile directly.


clip

-----------------------------------------
To reply to me, remove the underscores (_) from my email address (and please indicate which newsgroup and message).

Robert E. Zaret, eMVP
PenFact, Inc.
500 Harrison Ave., Suite 3R
Boston, MA 02118
www.penfact.com

Greg Ercolano

unread,
Apr 13, 2005, 4:15:58 PM4/13/05
to
r_z_aret@pen_fact.com wrote:
> I'm glad someone gave you a lead on a real solution. But I'm still
> curious about this workaround. I'm under the impression that Microsoft
> uses CreateFile in its implementation of fopen. So I don't see how
> using fopen has any advantages over using CreateFile directly.

Microsoft came back this morning with a more complete response
(below) as a workaround for the half broken _access() function.
FYI:

-------------------------------------------------------------- snip
//Function : CheckAccess( LPCTSTR fname, int mode)
//Returns : 0 when the access is present, -1 when access is not available
//Desc : This function can be used as a substitue for _access. The paramters are the same as in _access()
//fname - file/directory whose access is to be checked
//mode - mode to be checked, pass the code corresponding to the access test required.
// 0 - Test existence
// 2 - Write access
// 4 - Read access
// 6 - Read & Write access.
//
int CheckAccess(LPCTSTR fname, int mode)
{
DWORD dwAccess;
if (mode == 0)
return _access(fname, mode); //access would do when we want to check the existence alone.

if (mode == 2)
dwAccess = GENERIC_WRITE;
else if (mode == 4)
dwAccess = GENERIC_READ;
else if (mode == 6)
dwAccess = GENERIC_READ | GENERIC_WRITE;

HANDLE hFile = 0;
hFile = CreateFile(fname,
dwAccess,
FILE_SHARE_READ|FILE_SHARE_WRITE, // share for reading and writing
NULL, // no security
OPEN_EXISTING, // existing file only
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,
NULL); // no attr. template

if (hFile == INVALID_HANDLE_VALUE)
{ return(-1); }
CloseHandle(hFile);
return(0);
}
-------------------------------------------------------------- snip

I tested it with files and dirs that had read only, write only,
and r/w ACLs, and it all seemed to work fine.

And their solution does in fact use CreateFile(), and it
does indeed work unintrusively for both files AND directories.
(Note they actually use _access() to do the existence check,
but use CreateFile() for everything else)

This workaround was a pleasant surprise in that it was /simple/..
under one page.

All my other encounters with the WINAPI have been generally
very painful (CreateProcess(), registry functions, PDH lib..)
with pages of structures in structures, and calls with zillions
of flags, and very little intuitiveness or readability.

So I'm definitely going to use this approach, thus avoiding
a descent into the security subsystem via AccessCheck().
[I did some investigation into that this morning, and all
I can say is I'm glad I won't have to go there..]


PS. The case was closed with the above solution solving my problem,
and an internal bug report was generated towards the _access()
function.. so maybe it'll be fixed in a future release of the compiler.

Lucian Wischik

unread,
Apr 13, 2005, 5:25:50 PM4/13/05
to
Greg Ercolano <er...@3dsite.com> wrote:

>Someone wrote:
>> Anyway, to test using WINAPI, CreateFile() is the easiest way.
> Hmm, but then I'm modifying the file system.

I don't think you can deduce that.
"CreateFile" is just the name that they happened to use for a
super-function that does everything. It can create files, or open
existing files, or do hardware interaction, or lots of stuff. It
doesn't have to modify the FS at all.

--
Lucian

Greg Ercolano

unread,
Apr 15, 2005, 12:25:37 PM4/15/05
to

Yes, you're right.

Indeed, Microsoft's code workaround (posted by me elsewhere in this thread)
uses CreateFile() to do the non-intrusive 'access checks'.

I thought OpenFile() would be the 'super function' if anything was,
but apparently that's been obsoleted by CreateFile(). *head spins*

Anyway, thanks for all the pointers.


Greg Ercolano

unread,
Sep 20, 2012, 8:55:23 AM9/20/12
to
On Wednesday, April 13, 2005 1:15:58 PM UTC-7, Greg Ercolano wrote:
> PS. The case was closed with the above solution solving my problem,
> and an internal bug report was generated towards the _access()
> function.. so maybe it'll be fixed in a future release of the compiler.

It is now 2012, 7 years later.. following up to this old thread
which can be seen here:
https://groups.google.com/forum/?fromgroups=#!topic/comp.os.ms-windows.programmer.win32/sGozH_cHVuY

Just did the same test with VS 2010 + Windows 7 to see if MS
ever fixed the bug I logged with them back in 2005 through their
support line.

Looks like this bug still exists, so seems MS never did fix it.

-------------------------------------------------------------------------
C:\temp>echo %date% %time%
Thu 09/20/2012 5:46:36.31

C:\temp>ver
Microsoft Windows [Version 6.1.7600]

C:\temp>dir
Volume in drive C has no label.
Volume Serial Number is 348A-1965

Directory of C:\temp

09/20/2012 05:44 AM <DIR> .
09/20/2012 05:44 AM <DIR> ..
09/20/2012 05:25 AM 607 foo.c
1 File(s) 607 bytes
2 Dir(s) 54,282,874,880 bytes free

C:\temp>echo > bar # create 'bar'

C:\temp>echo %USERNAME% # see who I am
erco

C:\temp>cacls bar /e /d erco # remove my write access to bar
processed file: C:\temp\bar

C:\temp>echo >> bar # verify no write access
Access is denied.

C:\temp>type foo.c
// Simple program to test access() function
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
#include <errno.h>
#include <string.h>
main()
{
// ACCESS TEST
if ( _access("bar", 6) == 0 )
{ printf("access() says bar is OK to r/w. (NO IT'S NOT!)\n"); }
else
{ perror("_access(bar,6) NOT writable (EXPECT THIS), reason:"); }

// OPEN TEST
{
int fd = _open("bar", O_WRONLY|O_APPEND);
if ( fd == -1 ) { perror("open(bar) fails, as we expect"); }
else { printf("open(bar) OK\n"); close(fd); }
}
}

C:\temp>cl foo.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.30319.01 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.

foo.c
Microsoft (R) Incremental Linker Version 10.00.30319.01
Copyright (C) Microsoft Corporation. All rights reserved.

/out:foo.exe
foo.obj

C:\temp>.\foo.exe
access() says bar is OK to r/w. (NO IT'S NOT!) <-- still broken
open(bar) fails, as we expect: Permission denied
-------------------------------------------------------------------------

abhishe...@gmail.com

unread,
Jun 15, 2018, 12:32:56 AM6/15/18
to
Hi Greg Ercolano,
i was today working on my project of windows i found the _access is buggy for read and write operation so u said try the CheckAccess method but there is no method exist alternative to _access plz resolve my query
Thanks in advance.

Auric__

unread,
Jun 15, 2018, 3:12:50 AM6/15/18
to
abhishek324576 wrote:

> On Monday, April 11, 2005 at 11:45:11 AM UTC+5:30, Greg Ercolano wrote:
LOOK ^^^^^^^^^^^^^^^^^^^^^^
[snip]
> Hi Greg Ercolano,
> i was today working on my project of windows i found the _access is
> buggy for read and write operation so u said try the CheckAccess method
> but there is no method exist alternative to _access plz resolve my query
> Thanks in advance.

Greg posted his original message ***THIRTEEN YEARS AGO***. His last post in
this thread was almost SIX YEARS AGO.

--
Bandring is fleeing from the dreaded Malevolent Moose.
0 new messages