X-Git-Url: http://git.chise.org/gitweb/?p=chise%2Fxemacs-chise.git.1;a=blobdiff_plain;f=src%2Ffileio.c;h=c9bc2ae75ce2fc3382dbc0625b7d02aa8417453f;hp=f2b20c391ae7b380b18637c3886b0bfc2384d4fb;hb=8b2e8ef2dee7da2f0d4cea712b0fc55902c3cff7;hpb=de7caee5f47b0888cb3895ce8c09d745f2fc35aa diff --git a/src/fileio.c b/src/fileio.c index f2b20c3..c9bc2ae 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -57,7 +57,13 @@ Boston, MA 02111-1307, USA. */ #define WIN32_FILENAMES #ifdef WIN32_NATIVE #include "nt.h" +#include #endif /* WIN32_NATIVE */ +#ifdef CYGWIN +#include +#endif + + #define IS_DRIVE(x) isalpha (x) /* Need to lower-case the drive letter, or else expanded filenames will sometimes compare inequal, because @@ -2267,11 +2273,81 @@ check_executable (char *filename) #endif /* not WIN32_NATIVE */ } + + /* Return nonzero if file FILENAME exists and can be written. */ static int check_writable (const char *filename) { +#if defined(WIN32_NATIVE) || defined(CYGWIN) +#ifdef CYGWIN + char filename_buffer[PATH_MAX]; +#endif + // Since this has to work for a directory, we can't just call 'CreateFile' + PSECURITY_DESCRIPTOR pDesc; /* Must be freed with LocalFree */ + /* these need not be freed, they point into pDesc */ + PSID psidOwner; + PSID psidGroup; + PACL pDacl; + PACL pSacl; + /* end of insides of descriptor */ + DWORD error; + DWORD attributes; + HANDLE tokenHandle; + GENERIC_MAPPING genericMapping; + DWORD accessMask; + PRIVILEGE_SET PrivilegeSet; + DWORD dwPrivSetSize = sizeof( PRIVILEGE_SET ); + BOOL fAccessGranted = FALSE; + DWORD dwAccessAllowed; + +#ifdef CYGWIN + cygwin_conv_to_full_win32_path(filename, filename_buffer); + filename = filename_buffer; +#endif + + /* Win32 prototype lacks const. */ + error = GetNamedSecurityInfo((LPTSTR)filename, SE_FILE_OBJECT, + DACL_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|OWNER_SECURITY_INFORMATION, + &psidOwner, &psidGroup, &pDacl, &pSacl, &pDesc); + if (error != ERROR_SUCCESS) { // FAT? + attributes = GetFileAttributes(filename); + return (attributes & FILE_ATTRIBUTE_DIRECTORY) || (0 == (attributes & FILE_ATTRIBUTE_READONLY)); + } + + genericMapping.GenericRead = FILE_GENERIC_READ; + genericMapping.GenericWrite = FILE_GENERIC_WRITE; + genericMapping.GenericExecute = FILE_GENERIC_EXECUTE; + genericMapping.GenericAll = FILE_ALL_ACCESS; + + if (!ImpersonateSelf(SecurityDelegation)) { + return 0; + } + if (!OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE, &tokenHandle)) { + return 0; + } + + accessMask = GENERIC_WRITE; + MapGenericMask(&accessMask, &genericMapping); + + if (!AccessCheck(pDesc, tokenHandle, accessMask, &genericMapping, + &PrivilegeSet, // receives privileges used in check + &dwPrivSetSize, // size of PrivilegeSet buffer + &dwAccessAllowed, // receives mask of allowed access rights + &fAccessGranted)) + { + DWORD oops = GetLastError(); + CloseHandle(tokenHandle); + RevertToSelf(); + LocalFree(pDesc); + return 0; + } + CloseHandle(tokenHandle); + RevertToSelf(); + LocalFree(pDesc); + return fAccessGranted == TRUE; +#else #ifdef HAVE_EACCESS return (eaccess (filename, W_OK) >= 0); #else @@ -2282,6 +2358,7 @@ check_writable (const char *filename) but would lose for directories. */ return (access (filename, W_OK) >= 0); #endif +#endif } DEFUN ("file-exists-p", Ffile_exists_p, 1, 1, 0, /*