Question

NOTE: This is a complete re-write of this question. I'd previously conflated some ACL issues with the problem I'm hunting, which is probably why there were no answers.

I have a windows service that uses the standard open/close/write routines to write a log file (it reads stuff from a pipe and stuffs it into the log). A new log file is opened each day at midnight. The system is Windows XP Embedded.

The service runs as the Local System service (CreateService with NULL for the user).

When the service initially starts up, it creates a log file and writes to it with no problems. At this point everything is OK, and you can restart the service (or the computer) with no issues.

However, at midnight (when the day changes), the service creates a new log file and writes to it. The funny thing is, this new log file has the 'read only' flag set. That's a problem because if the service (or the computer) restarts, the service can no longer open the file for writing.

Here's the relevant information from the system with the problem having already happened:

 Directory of C:\bbbaudit

09/16/2009  12:00 AM    <DIR>          .
09/16/2009  12:00 AM    <DIR>          ..
09/16/2009  12:00 AM               437 AU090915.ADX
09/16/2009  12:00 AM                62 AU090916.ADX

attrib c:\bbbaudit\*
A          C:\bbbaudit\AU090915.ADX <-- old log file (before midnight)
A    R     C:\bbbaudit\AU090916.ADX <-- new log file (after midnight)

cacls output:
C:\ BUILTIN\Administrators:(OI)(CI)F 
    NT AUTHORITY\SYSTEM:(OI)(CI)F 
    CREATOR OWNER:(OI)(CI)(IO)F 
    BUILTIN\Users:(OI)(CI)R 
    BUILTIN\Users:(CI)(special access:)
                      FILE_APPEND_DATA

    BUILTIN\Users:(CI)(IO)(special access:)
                          FILE_WRITE_DATA

    Everyone:R 

C:\bbbaudit BUILTIN\Administrators:(OI)(CI)F 
            NT AUTHORITY\SYSTEM:(OI)(CI)F 
            CFN3\Administrator:F 
            CREATOR OWNER:(OI)(CI)(IO)F 

Here's the code I use to open/create the log files:

static int open_or_create_file(char *fname, bool &alreadyExists)
{
  int fdes;

  // try to create new file, fail if it already exists
  alreadyExists = false;
  fdes = open(fname, O_WRONLY | O_APPEND | O_CREAT | O_EXCL);
  if (fdes < 0)
  {
    // try to open existing, don't create new file
    alreadyExists = true;
    fdes = open(fname, O_WRONLY | O_APPEND);
  }

  return fdes;
}

I'm having real trouble figuring out how the file is getting that read-only flag on it. Anyone who can give me a clue or a direction, I'd greatly appreciate it.

Compiler is VC 6 (Yea, I know, it's so far out of date it isn't funny. Until you realize that we're just now upgraded to XPE from NT 3.51).

Was it helpful?

Solution

The Microsoft implementation of open() has an optional third argument 'pmode', which is required to be present when the second argument 'oflag' includes the O_CREAT flag. The pmode argument specifies the file permission settings, which are set when the new file is closed for the first time. Typically you would pass S_IREAD | S_IWRITE for pmode, resulting in an ordinary read/write file.

In your case you have specified O_CREAT but omitted the third argument, so open() has used whatever value happened to be on the stack at the third argument position. The value of S_IWRITE is 0x0080, so if the value in the third argument position happened to have bit 7 clear, it would result in a read-only file. The fact that you got a read-only file only some of the time, is consistent with stack junk being passed as the third argument.

Below is the link for the Visual Studio 2010 documentation for open(). This aspect of the function's behaviour has not changed since VC 6.

http://msdn.microsoft.com/en-us/library/z0kc8e3z.aspx

OTHER TIPS

Well, I have no idea what the underlying problem is with the 'open' APIs in this case. In order to 'fix' the problem, I ended up switching to using the Win32 APIs for file management (CreateFile, WriteFile, CloseHandle).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top