diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/w32.c | 65 |
1 files changed, 54 insertions, 11 deletions
| @@ -1304,7 +1304,7 @@ filename_from_utf16 (const wchar_t *fn_in, char *fn_out) | |||
| 1304 | static int | 1304 | static int |
| 1305 | filename_to_ansi (const char *fn_in, char *fn_out) | 1305 | filename_to_ansi (const char *fn_in, char *fn_out) |
| 1306 | { | 1306 | { |
| 1307 | wchar_t fn_utf16[MAXPATHLEN]; | 1307 | wchar_t fn_utf16[MAX_PATH]; |
| 1308 | 1308 | ||
| 1309 | if (filename_to_utf16 (fn_in, fn_utf16) == 0) | 1309 | if (filename_to_utf16 (fn_in, fn_utf16) == 0) |
| 1310 | { | 1310 | { |
| @@ -1312,7 +1312,7 @@ filename_to_ansi (const char *fn_in, char *fn_out) | |||
| 1312 | int codepage = codepage_for_filenames (NULL); | 1312 | int codepage = codepage_for_filenames (NULL); |
| 1313 | 1313 | ||
| 1314 | result = WideCharToMultiByte (codepage, 0, fn_utf16, -1, | 1314 | result = WideCharToMultiByte (codepage, 0, fn_utf16, -1, |
| 1315 | fn_out, MAX_UTF8_PATH, NULL, NULL); | 1315 | fn_out, MAX_PATH, NULL, NULL); |
| 1316 | if (!result) | 1316 | if (!result) |
| 1317 | { | 1317 | { |
| 1318 | DWORD err = GetLastError (); | 1318 | DWORD err = GetLastError (); |
| @@ -1339,7 +1339,7 @@ filename_to_ansi (const char *fn_in, char *fn_out) | |||
| 1339 | int | 1339 | int |
| 1340 | filename_from_ansi (const char *fn_in, char *fn_out) | 1340 | filename_from_ansi (const char *fn_in, char *fn_out) |
| 1341 | { | 1341 | { |
| 1342 | wchar_t fn_utf16[MAXPATHLEN]; | 1342 | wchar_t fn_utf16[MAX_PATH]; |
| 1343 | int codepage = codepage_for_filenames (NULL); | 1343 | int codepage = codepage_for_filenames (NULL); |
| 1344 | int result = MultiByteToWideChar (codepage, MB_ERR_INVALID_CHARS, fn_in, -1, | 1344 | int result = MultiByteToWideChar (codepage, MB_ERR_INVALID_CHARS, fn_in, -1, |
| 1345 | fn_utf16, MAX_PATH); | 1345 | fn_utf16, MAX_PATH); |
| @@ -4573,13 +4573,32 @@ utime (const char *name, struct utimbuf *times) | |||
| 4573 | times = &deftime; | 4573 | times = &deftime; |
| 4574 | } | 4574 | } |
| 4575 | 4575 | ||
| 4576 | /* Need write access to set times. */ | 4576 | if (w32_unicode_filenames) |
| 4577 | fh = CreateFile (name, FILE_WRITE_ATTRIBUTES, | 4577 | { |
| 4578 | /* If NAME specifies a directory, FILE_SHARE_DELETE | 4578 | wchar_t name_utf16[MAX_PATH]; |
| 4579 | allows other processes to delete files inside it, | 4579 | |
| 4580 | while we have the directory open. */ | 4580 | if (filename_to_utf16 (name, name_utf16) != 0) |
| 4581 | FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, | 4581 | return -1; /* errno set by filename_to_utf16 */ |
| 4582 | 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); | 4582 | |
| 4583 | /* Need write access to set times. */ | ||
| 4584 | fh = CreateFileW (name_utf16, FILE_WRITE_ATTRIBUTES, | ||
| 4585 | /* If NAME specifies a directory, FILE_SHARE_DELETE | ||
| 4586 | allows other processes to delete files inside it, | ||
| 4587 | while we have the directory open. */ | ||
| 4588 | FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, | ||
| 4589 | 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); | ||
| 4590 | } | ||
| 4591 | else | ||
| 4592 | { | ||
| 4593 | char name_ansi[MAX_PATH]; | ||
| 4594 | |||
| 4595 | if (filename_to_ansi (name, name_ansi) != 0) | ||
| 4596 | return -1; /* errno set by filename_to_ansi */ | ||
| 4597 | |||
| 4598 | fh = CreateFileA (name_ansi, FILE_WRITE_ATTRIBUTES, | ||
| 4599 | FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, | ||
| 4600 | 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); | ||
| 4601 | } | ||
| 4583 | if (fh != INVALID_HANDLE_VALUE) | 4602 | if (fh != INVALID_HANDLE_VALUE) |
| 4584 | { | 4603 | { |
| 4585 | convert_from_time_t (times->actime, &atime); | 4604 | convert_from_time_t (times->actime, &atime); |
| @@ -4594,7 +4613,31 @@ utime (const char *name, struct utimbuf *times) | |||
| 4594 | } | 4613 | } |
| 4595 | else | 4614 | else |
| 4596 | { | 4615 | { |
| 4597 | errno = EINVAL; | 4616 | DWORD err = GetLastError (); |
| 4617 | |||
| 4618 | switch (err) | ||
| 4619 | { | ||
| 4620 | case ERROR_FILE_NOT_FOUND: | ||
| 4621 | case ERROR_PATH_NOT_FOUND: | ||
| 4622 | case ERROR_INVALID_DRIVE: | ||
| 4623 | case ERROR_BAD_NETPATH: | ||
| 4624 | case ERROR_DEV_NOT_EXIST: | ||
| 4625 | /* ERROR_INVALID_NAME is the error CreateFile sets when the | ||
| 4626 | file name includes ?s, i.e. translation to ANSI failed. */ | ||
| 4627 | case ERROR_INVALID_NAME: | ||
| 4628 | errno = ENOENT; | ||
| 4629 | break; | ||
| 4630 | case ERROR_TOO_MANY_OPEN_FILES: | ||
| 4631 | errno = ENFILE; | ||
| 4632 | break; | ||
| 4633 | case ERROR_ACCESS_DENIED: | ||
| 4634 | case ERROR_SHARING_VIOLATION: | ||
| 4635 | errno = EACCES; | ||
| 4636 | break; | ||
| 4637 | default: | ||
| 4638 | errno = EINVAL; | ||
| 4639 | break; | ||
| 4640 | } | ||
| 4598 | return -1; | 4641 | return -1; |
| 4599 | } | 4642 | } |
| 4600 | return 0; | 4643 | return 0; |