I've found a difference in behavior between cygwin 1.5.25 and cygwin 1.7.1 that I don't understand. Renaming a file using MoveFileW fails with access denied under cygwin 1.5.25 as expected, but it works under 1.7. Here's what I do:
$ echo foo >foo $ mkdir temp $ chmod a-w temp $ ./my_rename Under cygwin 1.5.25, my_rename prints: MoveFileW failed (5) Under cygwin 1.7.1, my_rename prints: MoveFileW succeeded where my_rename comes from: $ gcc -mno-cygwin my_rename.c $ gcc --version gcc (GCC) 3.4.4 (cygming special, gdc 0.12, using dmd 0.125) Copyright (C) 2004 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 5 (ERROR_ACCESS_DENIED from http://msdn.microsoft.com/en-us/library/ms681382%28VS.85%29.aspx) is the value of GetLastError after the call to MoveFileW. The cygwin 1.5.25 result seems more correct since I've set the destination directory unwriteable. >From http://sourceware.org/ml/cygwin/2010-01/msg01044.html, I thought using attrib +R temp would help...As in: $ echo foo >foo $ mkdir temp $ attrib +R temp $ chmod a-w temp $ ./my_rename This added the FILE_ATTRIBUTE_READONLY bit to temp's attributes under cygwin 1.7.1 (it's there without the attrib call in 1.5.25), but this didn't change the behavior of MoveFileW. I took a look at the DACLs on temp just before the MoveFileW call in both cases. They're different, but not different enough to give me a clue why there's a difference in behavior here. Here they are. I'm running the test as user MACHINE_1\dbyron in 1.7.1 and MACHINE_2\engineer in 1.5.25. cygwin 1.7.1 appears to have fewer privileges than 1.5.25 (no FILE_WRITE_EA in 1.7 for MACHINE_1\dbyron, no SYNCHRONIZE nor FILE_READ_ATTRIBUTES nor FILE_READ_DATA in 1.7 for MACHINE_1\None, \Everyone). I also took a look at the attributes on temp before the MoveFileW call. They're the same on both cygwin 1.5.25 and 1.7.1: attributes of "tmp.hLuxPA/temp": 0x00002011: FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED | FILE_ATTRIBUTE_READONLY attributes of "tmp.hLuxPA/foo": 0x00002020: FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED cygwin 1.7.1 DACL ----------------- dump_acl_intl: tmp.hLuxPA/temp: DACL: 11 ACE(s) dump_ace_details: tmp.hLuxPA/temp: DACL: grant: mask(STANDARD_RIGHTS_ALL | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES, 0x001F0180), flags(0x00000000): S-1-5-21-3405506234-1792454352-3826119157-1005 (MACHINE_1\dbyron) dump_ace_details: tmp.hLuxPA/temp: DACL: grant: mask(READ_CONTROL | FILE_READ_ATTRIBUTES, 0x00020080), flags(0x00000000): S-1-5-21-3405506234-1792454352-3826119157-513 (MACHINE_1\None) dump_ace_details: tmp.hLuxPA/temp: DACL: grant: mask(READ_CONTROL | FILE_READ_ATTRIBUTES, 0x00020080), flags(0x00000000): S-1-1-0 (\Everyone) dump_ace_details: tmp.hLuxPA/temp: DACL: grant: mask(FILE_GENERIC_READ, 0x00120089), flags(OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE, 0x0000000B): S-1-1-0 (\Everyone) dump_ace_details: tmp.hLuxPA/temp: DACL: grant: mask(READ_CONTROL | FILE_READ_ATTRIBUTES, 0x00020080), flags(OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE, 0x0000000B): S-1-1-0 (\Everyone) dump_ace_details: tmp.hLuxPA/temp: DACL: grant: mask(FILE_GENERIC_READ, 0x00120089), flags(OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE | INHERITED_ACE, 0x0000001B): S-1-1-0 (\Everyone) dump_ace_details: tmp.hLuxPA/temp: DACL: grant: mask(FILE_ALL_ACCESS, 0x001F01FF), flags(OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE, 0x0000000B): S-1-3-0 (\CREATOR OWNER) dump_ace_details: tmp.hLuxPA/temp: DACL: grant: mask(FILE_GENERIC_READ, 0x00120089), flags(OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE, 0x0000000B): S-1-3-1 (\CREATOR GROUP) dump_ace_details: tmp.hLuxPA/temp: DACL: grant: mask(FILE_ALL_ACCESS, 0x001F01FF), flags(OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE, 0x0000000B): S-1-3-0 (\CREATOR OWNER) dump_ace_details: tmp.hLuxPA/temp: DACL: grant: mask(FILE_GENERIC_READ, 0x00120089), flags(OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE, 0x0000000B): S-1-3-1 (\CREATOR GROUP) dump_ace_details: tmp.hLuxPA/temp: DACL: grant: mask(FILE_GENERIC_READ, 0x00120089), flags(OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE, 0x0000000B): S-1-1-0 (\Everyone) cygwin 1.5.25 DACL ------------------ dump_acl_intl: tmp.LL4040/temp: DACL: 6 ACE(s) dump_ace_details: tmp.LL4040/temp: DACL: grant: mask(FILE_GENERIC_READ | FILE_GENERIC_EXECUTE | DELETE | WRITE_DAC | WRITE_OWNER | FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES, 0x001F01B9), flags(0x00000000): S-1-5-21-1993959146-703098039-3712230515-1005 (MACHINE_2\engineer) dump_ace_details: tmp.LL4040/temp: DACL: grant: mask(FILE_GENERIC_READ, 0x00120089), flags(0x00000000): S-1-5-21-1993959146-703098039-3712230515-513 (MACHINE_2\None) dump_ace_details: tmp.LL4040/temp: DACL: grant: mask(FILE_GENERIC_READ, 0x00120089), flags(0x00000000): S-1-1-0 (\Everyone) dump_ace_details: tmp.LL4040/temp: DACL: grant: mask(FILE_ALL_ACCESS, 0x001F01FF), flags(OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE, 0x0000000B): S-1-3-0 (\CREATOR OWNER) dump_ace_details: tmp.LL4040/temp: DACL: grant: mask(FILE_GENERIC_READ, 0x00120089), flags(OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE, 0x0000000B): S-1-3-1 (\CREATOR GROUP) dump_ace_details: tmp.LL4040/temp: DACL: grant: mask(FILE_GENERIC_READ, 0x00120089), flags(OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE, 0x0000000B): S-1-1-0 (\Everyone) I can't tell if http://sourceware.org/ml/cygwin/2009-11/msg00960.html is relevant. My reflex is that it's not since it's not cygwin moving the file. In the end I guess I'm asking a straight windows question...what's making MoveFileW succeed with cygwin 1.7.1? I couldn't find any docs on the permissions that MoveFileW requires but the lack of FILE_WRITE_DATA seems like it should cause ERROR_ACCESS_DENIED. Both machines are running XP SP 3. Thanks for your help. -DB
#include <stdio.h> #include <windows.h> int main ( int argc, char **argv ) { const wchar_t *source = L"foo"; const wchar_t *dest = L"temp/bar"; if (!MoveFileW(source,dest)) { printf("MoveFileW failed (%d)\n",GetLastError()); return 1; } printf("MoveFileW succeeded\n"); return 0; }
test.sh
Description: Binary data
-- Problem reports: http://cygwin.com/problems.html FAQ: http://cygwin.com/faq/ Documentation: http://cygwin.com/docs.html Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple