Mercurial > hg > xemacs-beta
comparison src/fileio.c @ 3728:6765f2581182
[xemacs-hg @ 2006-12-08 02:21:53 by vins]
Added Benson Margulies's patch to avoid the dreaded: "File not found and
directory write-protected" message under Windows.
author | vins |
---|---|
date | Fri, 08 Dec 2006 02:22:02 +0000 |
parents | a0adf5f08c44 |
children | a257e03c580e |
comparison
equal
deleted
inserted
replaced
3727:3246cf3e564d | 3728:6765f2581182 |
---|---|
2289 /* Return nonzero if file FILENAME exists and can be written. */ | 2289 /* Return nonzero if file FILENAME exists and can be written. */ |
2290 | 2290 |
2291 static int | 2291 static int |
2292 check_writable (const Ibyte *filename) | 2292 check_writable (const Ibyte *filename) |
2293 { | 2293 { |
2294 #if defined(WIN32_NATIVE) || defined(CYGWIN) | |
2295 #ifdef CYGWIN | |
2296 char filename_buffer[PATH_MAX]; | |
2297 #endif | |
2298 // Since this has to work for a directory, we can't just call 'CreateFile' | |
2299 PSECURITY_DESCRIPTOR pDesc; /* Must be freed with LocalFree */ | |
2300 /* these need not be freed, they point into pDesc */ | |
2301 PSID psidOwner; | |
2302 PSID psidGroup; | |
2303 PACL pDacl; | |
2304 PACL pSacl; | |
2305 /* end of insides of descriptor */ | |
2306 DWORD error; | |
2307 DWORD attributes; | |
2308 HANDLE tokenHandle; | |
2309 GENERIC_MAPPING genericMapping; | |
2310 DWORD accessMask; | |
2311 PRIVILEGE_SET PrivilegeSet; | |
2312 DWORD dwPrivSetSize = sizeof( PRIVILEGE_SET ); | |
2313 BOOL fAccessGranted = FALSE; | |
2314 DWORD dwAccessAllowed; | |
2315 Extbyte *fnameext; | |
2316 | |
2317 #ifdef CYGWIN | |
2318 cygwin_conv_to_full_win32_path(filename, filename_buffer); | |
2319 filename = (Ibyte*)filename_buffer; | |
2320 #endif | |
2321 | |
2322 C_STRING_TO_TSTR(filename, fnameext); | |
2323 /* Win32 prototype lacks const. */ | |
2324 error = qxeGetNamedSecurityInfo(fnameext, SE_FILE_OBJECT, | |
2325 DACL_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|OWNER_SECURITY_INFORMATION, | |
2326 &psidOwner, &psidGroup, &pDacl, &pSacl, &pDesc); | |
2327 if(error != ERROR_SUCCESS) { // FAT? | |
2328 attributes = qxeGetFileAttributes((Extbyte *)filename); | |
2329 return (attributes & FILE_ATTRIBUTE_DIRECTORY) || (0 == (attributes & FILE_ATTRIBUTE_READONLY)); | |
2330 } | |
2331 | |
2332 genericMapping.GenericRead = FILE_GENERIC_READ; | |
2333 genericMapping.GenericWrite = FILE_GENERIC_WRITE; | |
2334 genericMapping.GenericExecute = FILE_GENERIC_EXECUTE; | |
2335 genericMapping.GenericAll = FILE_ALL_ACCESS; | |
2336 | |
2337 if(!ImpersonateSelf(SecurityDelegation)) { | |
2338 return 0; | |
2339 } | |
2340 if(!OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE, &tokenHandle)) { | |
2341 return 0; | |
2342 } | |
2343 | |
2344 accessMask = GENERIC_WRITE; | |
2345 MapGenericMask(&accessMask, &genericMapping); | |
2346 | |
2347 if(!AccessCheck(pDesc, tokenHandle, accessMask, &genericMapping, | |
2348 &PrivilegeSet, // receives privileges used in check | |
2349 &dwPrivSetSize, // size of PrivilegeSet buffer | |
2350 &dwAccessAllowed, // receives mask of allowed access rights | |
2351 &fAccessGranted)) | |
2352 { | |
2353 CloseHandle(tokenHandle); | |
2354 RevertToSelf(); | |
2355 LocalFree(pDesc); | |
2356 return 0; | |
2357 } | |
2358 CloseHandle(tokenHandle); | |
2359 RevertToSelf(); | |
2360 LocalFree(pDesc); | |
2361 return fAccessGranted == TRUE; | |
2362 #else | |
2294 #ifdef HAVE_EACCESS | 2363 #ifdef HAVE_EACCESS |
2295 return (qxe_eaccess (filename, W_OK) >= 0); | 2364 return (qxe_eaccess (filename, W_OK) >= 0); |
2296 #else | 2365 #else |
2297 /* Access isn't quite right because it uses the real uid | 2366 /* Access isn't quite right because it uses the real uid |
2298 and we really want to test with the effective uid. | 2367 and we really want to test with the effective uid. |
2299 But Unix doesn't give us a right way to do it. | 2368 But Unix doesn't give us a right way to do it. |
2300 Opening with O_WRONLY could work for an ordinary file, | 2369 Opening with O_WRONLY could work for an ordinary file, |
2301 but would lose for directories. */ | 2370 but would lose for directories. */ |
2302 return (qxe_access (filename, W_OK) >= 0); | 2371 return (qxe_access (filename, W_OK) >= 0); |
2372 #endif | |
2303 #endif | 2373 #endif |
2304 } | 2374 } |
2305 | 2375 |
2306 DEFUN ("file-exists-p", Ffile_exists_p, 1, 1, 0, /* | 2376 DEFUN ("file-exists-p", Ffile_exists_p, 1, 1, 0, /* |
2307 Return t if file FILENAME exists. (This does not mean you can read it.) | 2377 Return t if file FILENAME exists. (This does not mean you can read it.) |