comparison src/fileio.c @ 4834:b3ea9c582280

Use new cygwin_conv_path API with Cygwin 1.7 for converting names between Win32 and POSIX, UTF-8-aware, with attendant changes elsewhere
author Ben Wing <ben@xemacs.org>
date Tue, 12 Jan 2010 01:38:04 -0600
parents 780bb5441c14
children a03421eb562b
comparison
equal deleted inserted replaced
4833:4dd2389173fc 4834:b3ea9c582280
1 /* File IO for XEmacs. 1 /* File IO for XEmacs.
2 Copyright (C) 1985-1988, 1992-1995 Free Software Foundation, Inc. 2 Copyright (C) 1985-1988, 1992-1995 Free Software Foundation, Inc.
3 Copyright (C) 1996, 2001, 2002, 2003, 2004 Ben Wing. 3 Copyright (C) 1996, 2001, 2002, 2003, 2004, 2010 Ben Wing.
4 4
5 This file is part of XEmacs. 5 This file is part of XEmacs.
6 6
7 XEmacs is free software; you can redistribute it and/or modify it 7 XEmacs is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the 8 under the terms of the GNU General Public License as published by the
1386 #if defined (WIN32_FILENAMES) && defined (CYGWIN) 1386 #if defined (WIN32_FILENAMES) && defined (CYGWIN)
1387 /* When using win32 filenames in cygwin we want file-truename to 1387 /* When using win32 filenames in cygwin we want file-truename to
1388 detect that c:/windows == /windows for example. */ 1388 detect that c:/windows == /windows for example. */
1389 if (! (IS_DIRECTORY_SEP (path[0]) && IS_DIRECTORY_SEP (path[1]))) 1389 if (! (IS_DIRECTORY_SEP (path[0]) && IS_DIRECTORY_SEP (path[1])))
1390 { 1390 {
1391 LOCAL_TO_WIN32_FILE_FORMAT (path, p); 1391 LOCAL_FILE_FORMAT_TO_INTERNAL_MSWIN (path, p);
1392 path = p; 1392 path = p;
1393 } 1393 }
1394 #endif 1394 #endif
1395 p = path; 1395 p = path;
1396 1396
2269 2269
2270 /* netunam, being a strange-o system call only used once, is not 2270 /* netunam, being a strange-o system call only used once, is not
2271 encapsulated. */ 2271 encapsulated. */
2272 2272
2273 LISP_STRING_TO_EXTERNAL (path, path_ext, Qfile_name); 2273 LISP_STRING_TO_EXTERNAL (path, path_ext, Qfile_name);
2274 LISP_STRING_TO_EXTERNAL (login, login_ext, Qnative); 2274 LISP_STRING_TO_EXTERNAL (login, login_ext, Quser_name_encoding);
2275 2275
2276 netresult = netunam (path_ext, login_ext); 2276 netresult = netunam (path_ext, login_ext);
2277 2277
2278 return netresult == -1 ? Qnil : Qt; 2278 return netresult == -1 ? Qnil : Qt;
2279 } 2279 }
2322 /* Return nonzero if file FILENAME exists and can be written. */ 2322 /* Return nonzero if file FILENAME exists and can be written. */
2323 2323
2324 static int 2324 static int
2325 check_writable (const Ibyte *filename) 2325 check_writable (const Ibyte *filename)
2326 { 2326 {
2327 #if defined(WIN32_NATIVE) || defined(CYGWIN) 2327 #ifdef WIN32_ANY
2328 #ifdef CYGWIN 2328 // Since this has to work for a directory, we can't just call 'CreateFile'
2329 Extbyte filename_buffer[PATH_MAX]; 2329 PSECURITY_DESCRIPTOR pDesc; /* Must be freed with LocalFree */
2330 #endif 2330 /* these need not be freed, they point into pDesc */
2331 // Since this has to work for a directory, we can't just call 'CreateFile' 2331 PSID psidOwner;
2332 PSECURITY_DESCRIPTOR pDesc; /* Must be freed with LocalFree */ 2332 PSID psidGroup;
2333 /* these need not be freed, they point into pDesc */ 2333 PACL pDacl;
2334 PSID psidOwner; 2334 PACL pSacl;
2335 PSID psidGroup; 2335 /* end of insides of descriptor */
2336 PACL pDacl; 2336 DWORD error;
2337 PACL pSacl; 2337 DWORD attributes;
2338 /* end of insides of descriptor */ 2338 HANDLE tokenHandle;
2339 DWORD error; 2339 GENERIC_MAPPING genericMapping;
2340 DWORD attributes; 2340 DWORD accessMask;
2341 HANDLE tokenHandle; 2341 PRIVILEGE_SET PrivilegeSet;
2342 GENERIC_MAPPING genericMapping; 2342 DWORD dwPrivSetSize = sizeof( PRIVILEGE_SET );
2343 DWORD accessMask; 2343 BOOL fAccessGranted = FALSE;
2344 PRIVILEGE_SET PrivilegeSet; 2344 DWORD dwAccessAllowed;
2345 DWORD dwPrivSetSize = sizeof( PRIVILEGE_SET ); 2345 Extbyte *fnameext;
2346 BOOL fAccessGranted = FALSE; 2346
2347 DWORD dwAccessAllowed; 2347 LOCAL_FILE_FORMAT_TO_TSTR (filename, fnameext);
2348 Extbyte *fnameext; 2348
2349 2349 // First check for a normal file with the old-style readonly bit
2350 C_STRING_TO_TSTR(filename, fnameext); 2350 attributes = qxeGetFileAttributes(fnameext);
2351 2351 if (FILE_ATTRIBUTE_READONLY == (attributes & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_READONLY)))
2352 #ifdef CYGWIN 2352 return 0;
2353 cygwin_conv_to_full_win32_path(fnameext, filename_buffer); 2353
2354 fnameext = filename_buffer; 2354 /* Win32 prototype lacks const. */
2355 #endif 2355 error = qxeGetNamedSecurityInfo(fnameext, SE_FILE_OBJECT,
2356 2356 DACL_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|OWNER_SECURITY_INFORMATION,
2357 // First check for a normal file with the old-style readonly bit 2357 &psidOwner, &psidGroup, &pDacl, &pSacl, &pDesc);
2358 if(error != ERROR_SUCCESS) { // FAT?
2358 attributes = qxeGetFileAttributes(fnameext); 2359 attributes = qxeGetFileAttributes(fnameext);
2359 if (FILE_ATTRIBUTE_READONLY == (attributes & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_READONLY))) 2360 return (attributes & FILE_ATTRIBUTE_DIRECTORY) || (0 == (attributes & FILE_ATTRIBUTE_READONLY));
2361 }
2362
2363 genericMapping.GenericRead = FILE_GENERIC_READ;
2364 genericMapping.GenericWrite = FILE_GENERIC_WRITE;
2365 genericMapping.GenericExecute = FILE_GENERIC_EXECUTE;
2366 genericMapping.GenericAll = FILE_ALL_ACCESS;
2367
2368 if(!ImpersonateSelf(SecurityDelegation)) {
2369 return 0;
2370 }
2371 if(!OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE, &tokenHandle)) {
2372 return 0;
2373 }
2374
2375 accessMask = GENERIC_WRITE;
2376 MapGenericMask(&accessMask, &genericMapping);
2377
2378 if(!AccessCheck(pDesc, tokenHandle, accessMask, &genericMapping,
2379 &PrivilegeSet, // receives privileges used in check
2380 &dwPrivSetSize, // size of PrivilegeSet buffer
2381 &dwAccessAllowed, // receives mask of allowed access rights
2382 &fAccessGranted))
2383 {
2384 CloseHandle(tokenHandle);
2385 RevertToSelf();
2386 LocalFree(pDesc);
2360 return 0; 2387 return 0;
2361 2388 }
2362 /* Win32 prototype lacks const. */ 2389 CloseHandle(tokenHandle);
2363 error = qxeGetNamedSecurityInfo(fnameext, SE_FILE_OBJECT, 2390 RevertToSelf();
2364 DACL_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|OWNER_SECURITY_INFORMATION, 2391 LocalFree(pDesc);
2365 &psidOwner, &psidGroup, &pDacl, &pSacl, &pDesc); 2392 return fAccessGranted == TRUE;
2366 if(error != ERROR_SUCCESS) { // FAT? 2393 #elif defined (HAVE_EACCESS)
2367 attributes = qxeGetFileAttributes(fnameext);
2368 return (attributes & FILE_ATTRIBUTE_DIRECTORY) || (0 == (attributes & FILE_ATTRIBUTE_READONLY));
2369 }
2370
2371 genericMapping.GenericRead = FILE_GENERIC_READ;
2372 genericMapping.GenericWrite = FILE_GENERIC_WRITE;
2373 genericMapping.GenericExecute = FILE_GENERIC_EXECUTE;
2374 genericMapping.GenericAll = FILE_ALL_ACCESS;
2375
2376 if(!ImpersonateSelf(SecurityDelegation)) {
2377 return 0;
2378 }
2379 if(!OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE, &tokenHandle)) {
2380 return 0;
2381 }
2382
2383 accessMask = GENERIC_WRITE;
2384 MapGenericMask(&accessMask, &genericMapping);
2385
2386 if(!AccessCheck(pDesc, tokenHandle, accessMask, &genericMapping,
2387 &PrivilegeSet, // receives privileges used in check
2388 &dwPrivSetSize, // size of PrivilegeSet buffer
2389 &dwAccessAllowed, // receives mask of allowed access rights
2390 &fAccessGranted))
2391 {
2392 CloseHandle(tokenHandle);
2393 RevertToSelf();
2394 LocalFree(pDesc);
2395 return 0;
2396 }
2397 CloseHandle(tokenHandle);
2398 RevertToSelf();
2399 LocalFree(pDesc);
2400 return fAccessGranted == TRUE;
2401 #else
2402 #ifdef HAVE_EACCESS
2403 return (qxe_eaccess (filename, W_OK) >= 0); 2394 return (qxe_eaccess (filename, W_OK) >= 0);
2404 #else 2395 #else
2405 /* Access isn't quite right because it uses the real uid 2396 /* Access isn't quite right because it uses the real uid
2406 and we really want to test with the effective uid. 2397 and we really want to test with the effective uid.
2407 But Unix doesn't give us a right way to do it. 2398 But Unix doesn't give us a right way to do it.
2408 Opening with O_WRONLY could work for an ordinary file, 2399 Opening with O_WRONLY could work for an ordinary file,
2409 but would lose for directories. */ 2400 but would lose for directories. */
2410 return (qxe_access (filename, W_OK) >= 0); 2401 return (qxe_access (filename, W_OK) >= 0);
2411 #endif 2402 #endif /* (not) defined (HAVE_EACCESS) */
2412 #endif
2413 } 2403 }
2414 2404
2415 DEFUN ("file-exists-p", Ffile_exists_p, 1, 1, 0, /* 2405 DEFUN ("file-exists-p", Ffile_exists_p, 1, 1, 0, /*
2416 Return t if file FILENAME exists. (This does not mean you can read it.) 2406 Return t if file FILENAME exists. (This does not mean you can read it.)
2417 See also `file-readable-p' and `file-attributes'. 2407 See also `file-readable-p' and `file-attributes'.