3

注意:这是对这个问题的完整重写。我之前将一些 ACL 问题与我正在寻找的问题混为一谈,这可能就是没有答案的原因。

我有一个 Windows 服务,它使用标准的打开/关闭/写入例程来写入日志文件(它从管道中读取内容并将其填充到日志中)。每天午夜打开一个新的日志文件。该系统是 Windows XP Embedded。

该服务作为本地系统服务运行(用户为 NULL 的 CreateService)。

当服务最初启动时,它会创建一个日志文件并毫无问题地写入它。此时一切正常,您可以毫无问题地重新启动服务(或计算机)。

但是,在午夜(当一天发生变化时),该服务会创建一个新的日志文件并写入它。有趣的是,这个新的日志文件设置了“只读”标志。这是一个问题,因为如果服务(或计算机)重新启动,服务将无法再打开文件进行写入。

以下是系统中已经发生问题的相关信息:

 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 

这是我用来打开/创建日志文件的代码:

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;
}

我很难弄清楚文件是如何获得只读标志的。谁能给我线索或方向,我将不胜感激。

编译器是 VC 6(是的,我知道,它已经过时了,这并不好笑。直到您意识到我们刚刚从 NT 3.51 升级到 XPE)。

4

2 回答 2

6

open() 的 Microsoft 实现有一个可选的第三个参数“pmode”,当第二个参数“oflag”包含 O_CREAT 标志时,它必须存在。pmode 参数指定文件权限设置,在第一次关闭新文件时设置。通常你会通过 S_IREAD | S_IWRITE 用于 pmode,产生一个普通的读/写文件。

在您的情况下,您指定了 O_CREAT 但省略了第三个参数,因此 open() 使用了恰好在第三个参数位置的堆栈上的任何值。S_IWRITE 的值是 0x0080,所以如果第三个参数位置的值恰好有第 7 位被清除,就会导致一个只读文件。您仅在某些时候获得只读文件这一事实与作为第三个参数传递的堆栈垃圾一致。

下面是 open() 的 Visual Studio 2010 文档的链接。自 VC 6 以来,函数行为的这一方面没有改变。

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

于 2012-08-04T16:24:52.533 回答
0

好吧,在这种情况下,我不知道“开放”API 的根本问题是什么。为了“解决”这个问题,我最终转而使用 Win32 API 进行文件管理(CreateFile、WriteFile、CloseHandle)。

于 2009-09-16T20:16:43.193 回答