Index: autoload.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/autoload.cc,v retrieving revision 1.52 diff -u -3 -p -u -p -r1.52 autoload.cc --- autoload.cc 3 Jul 2002 09:20:24 -0000 1.52 +++ autoload.cc 3 Jul 2002 12:32:02 -0000 @@ -321,6 +321,7 @@ LoadDLLfuncEx (DuplicateTokenEx, 24, adv LoadDLLfunc (EqualSid, 8, advapi32) LoadDLLfunc (GetAce, 12, advapi32) LoadDLLfunc (GetFileSecurityA, 20, advapi32) +LoadDLLfuncEx (GetFileSecurityW, 20, advapi32, 1) LoadDLLfunc (GetKernelObjectSecurity, 20, advapi32) LoadDLLfunc (GetLengthSid, 4, advapi32) LoadDLLfunc (GetSecurityDescriptorDacl, 16, advapi32) @@ -491,11 +492,24 @@ LoadDLLfunc (CoUninitialize, 0, ole32) LoadDLLfunc (CoCreateInstance, 20, ole32) LoadDLLfuncEx (CancelIo, 4, kernel32, 1) +LoadDLLfuncEx (CreateFileW, 28, kernel32, 1) LoadDLLfuncEx (CreateHardLinkA, 12, kernel32, 1) +LoadDLLfuncEx (CreateHardLinkW, 12, kernel32, 1) +LoadDLLfuncEx (CreateDirectoryW, 8, kernel32, 1) LoadDLLfuncEx (CreateToolhelp32Snapshot, 8, kernel32, 1) +LoadDLLfuncEx (DeleteFileW, 4, kernel32, 1) +LoadDLLfuncEx (FindFirstFileW, 8, kernel32, 1) +LoadDLLfuncEx (FindNextFileW, 8, kernel32, 1) +LoadDLLfuncEx (GetCurrentDirectoryW, 8, kernel32, 1) +LoadDLLfuncEx (GetFileAttributesW, 4, kernel32, 1) LoadDLLfuncEx2 (IsDebuggerPresent, 0, kernel32, 1, 1) +LoadDLLfuncEx (MoveFileW, 8, kernel32, 1) +LoadDLLfuncEx (MoveFileExW, 12, kernel32, 1) LoadDLLfuncEx (Process32First, 8, kernel32, 1) LoadDLLfuncEx (Process32Next, 8, kernel32, 1) +LoadDLLfuncEx (RemoveDirectoryW, 4, kernel32, 1) +LoadDLLfuncEx (SetCurrentDirectoryW, 4, kernel32, 1) +LoadDLLfuncEx (SetFileAttributesW, 8, kernel32, 1) LoadDLLfuncEx (SignalObjectAndWait, 16, kernel32, 1) LoadDLLfunc (TryEnterCriticalSection, 4, kernel32) Index: dcrt0.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/dcrt0.cc,v retrieving revision 1.135 diff -u -3 -p -u -p -r1.135 dcrt0.cc --- dcrt0.cc 27 Jun 2002 20:44:27 -0000 1.135 +++ dcrt0.cc 3 Jul 2002 12:32:05 -0000 @@ -57,6 +57,7 @@ per_thread NO_COPY *threadstuff[] = {&wa BOOL display_title; BOOL strip_title_path; BOOL allow_glob = TRUE; +BOOL use_utf8 = FALSE; codepage_type current_codepage = ansi_cp; int cygwin_finished_initializing; Index: delqueue.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/delqueue.cc,v retrieving revision 1.9 diff -u -3 -p -u -p -r1.9 delqueue.cc --- delqueue.cc 12 Sep 2001 17:46:35 -0000 1.9 +++ delqueue.cc 3 Jul 2002 12:32:06 -0000 @@ -20,6 +20,8 @@ details. */ and move delqueue files to some special location or some such hack... */ +/* FIXME: does not support Unicode filenames */ + void delqueue_list::init () { Index: dir.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/dir.cc,v retrieving revision 1.66 diff -u -3 -p -u -p -r1.66 dir.cc --- dir.cc 5 Jun 2002 16:01:55 -0000 1.66 +++ dir.cc 3 Jul 2002 12:32:07 -0000 @@ -248,7 +248,17 @@ mkdir (const char *dir, mode_t mode) set_security_attribute (S_IFDIR | ((mode & 07777) & ~cygheap->umask), &sa, alloca (4096), 4096); - if (CreateDirectoryA (real_dir.get_win32 (), &sa)) + BOOL success; + WCHAR *wbuf; + if (use_utf8) + { + wbuf = (WCHAR *) alloca (MAX_PATH * sizeof (WCHAR)); + sys_utf8towcs (wbuf, real_dir.get_win32(), MAX_PATH); + success = CreateDirectoryW (wbuf, &sa); + } + else + success = CreateDirectoryA (real_dir.get_win32 (), &sa); + if (success) { if (!allow_ntsec && allow_ntea) set_file_attribute (real_dir.has_acls (), real_dir.get_win32 (), @@ -256,7 +266,12 @@ mkdir (const char *dir, mode_t mode) #ifdef HIDDEN_DOT_FILES char *c = strrchr (real_dir.get_win32 (), '\\'); if ((c && c[1] == '.') || *real_dir.get_win32 () == '.') - SetFileAttributes (real_dir.get_win32 (), FILE_ATTRIBUTE_HIDDEN); + { + if (use_utf8) + SetFileAttributesW (wbuf, FILE_ATTRIBUTE_HIDDEN); + else + SetFileAttributesA (real_dir.get_win32 (), FILE_ATTRIBUTE_HIDDEN); + } #endif res = 0; } @@ -277,6 +292,13 @@ rmdir (const char *dir) path_conv real_dir (dir, PC_SYM_NOFOLLOW); + WCHAR *wbuf; + if (use_utf8) + { + wbuf = (WCHAR *)alloca (MAX_PATH * sizeof (WCHAR)); + sys_utf8towcs (wbuf, real_dir.get_win32(), MAX_PATH); + } + if (real_dir.error) set_errno (real_dir.error); else if ((devn = real_dir.get_devn ()) == FH_PROC || devn == FH_REGISTRY @@ -290,15 +312,31 @@ rmdir (const char *dir) { /* Even own directories can't be removed if R/O attribute is set. */ if (real_dir.has_attribute (FILE_ATTRIBUTE_READONLY)) - SetFileAttributes (real_dir, - (DWORD) real_dir & ~FILE_ATTRIBUTE_READONLY); - - if (RemoveDirectory (real_dir)) + { + if (use_utf8) + SetFileAttributesW (wbuf, + (DWORD) real_dir & ~FILE_ATTRIBUTE_READONLY); + else + SetFileAttributesA (real_dir, + (DWORD) real_dir & ~FILE_ATTRIBUTE_READONLY); + } + + BOOL success; + if (use_utf8) + success = RemoveDirectoryW (wbuf); + else + success = RemoveDirectoryA (real_dir); + if (success) { /* RemoveDirectory on a samba drive doesn't return an error if the directory can't be removed because it's not empty. Checking for existence afterwards keeps us informed about success. */ - if (GetFileAttributes (real_dir) != INVALID_FILE_ATTRIBUTES) + DWORD fileattr; + if (use_utf8) + fileattr = GetFileAttributesW (wbuf); + else + fileattr = GetFileAttributesA (real_dir); + if (fileattr != INVALID_FILE_ATTRIBUTES) set_errno (ENOTEMPTY); else res = 0; @@ -320,10 +358,25 @@ rmdir (const char *dir) && !strcasematch ("c:\\", cygheap->cwd.win32)) { DWORD err = GetLastError (); + if (!SetCurrentDirectory ("c:\\")) SetLastError (err); else if ((res = rmdir (dir))) - SetCurrentDirectory (cygheap->cwd.win32); + { + WCHAR cwd_wbuf[MAX_PATH]; + if (use_utf8) + { + if (sys_utf8towcs (cwd_wbuf, cygheap->cwd.win32, MAX_PATH) == 0) + { + __seterrno (); + /* PANIC! : haven't set directory back! */ + return -1; + } + SetCurrentDirectoryW (cwd_wbuf); + } + else + SetCurrentDirectoryA (cygheap->cwd.win32); + } } if (res) { @@ -337,7 +390,12 @@ rmdir (const char *dir) /* If directory still exists, restore R/O attribute. */ if (real_dir.has_attribute (FILE_ATTRIBUTE_READONLY)) - SetFileAttributes (real_dir, real_dir); + { + if (use_utf8) + SetFileAttributesW (wbuf, real_dir); + else + SetFileAttributesA (real_dir, real_dir); + } } } } Index: dtable.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/dtable.cc,v retrieving revision 1.98 diff -u -3 -p -u -p -r1.98 dtable.cc --- dtable.cc 3 Jul 2002 03:20:50 -0000 1.98 +++ dtable.cc 3 Jul 2002 12:32:09 -0000 @@ -725,12 +725,15 @@ handle_to_fn (HANDLE h, char *posix_fn) ntfn->Name.Buffer[ntfn->Name.Length / sizeof (WCHAR)] = 0; char win32_fn[MAX_PATH + 100]; - sys_wcstombs (win32_fn, ntfn->Name.Buffer, ntfn->Name.Length); + if (use_utf8) + sys_wcstoutf8 (win32_fn, ntfn->Name.Buffer, ntfn->Name.Length); + else + sys_wcstombcs (win32_fn, ntfn->Name.Buffer, ntfn->Name.Length); debug_printf ("nt name '%s'", win32_fn); if (!strncasematch (win32_fn, DEVICE_PREFIX, DEVICE_PREFIX_LEN) || !QueryDosDevice (NULL, fnbuf, sizeof (fnbuf))) return strcpy (posix_fn, win32_fn); - + char *p = strchr (win32_fn + DEVICE_PREFIX_LEN, '\\'); if (!p) p = strchr (win32_fn + DEVICE_PREFIX_LEN, '\0'); Index: environ.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/environ.cc,v retrieving revision 1.85 diff -u -3 -p -u -p -r1.85 environ.cc --- environ.cc 1 Jul 2002 02:11:30 -0000 1.85 +++ environ.cc 3 Jul 2002 12:32:12 -0000 @@ -7,6 +7,8 @@ This software is a copyrighted work lice Cygwin license. Please consult the file "CYGWIN_LICENSE" for details. */ +/* FIXME: does not convert Unicode PATH, etc. to UTF-8 */ + #include "winsup.h" #include #include @@ -34,6 +36,7 @@ extern BOOL allow_ntea; extern BOOL allow_smbntsec; extern BOOL allow_winsymlinks; extern BOOL strip_title_path; +extern BOOL use_utf8; extern int pcheck_case; extern int subauth_id; BOOL reset_com = FALSE; @@ -521,6 +524,7 @@ static struct parse_thing {"subauth_id", {func: &subauth_id_init}, isfunc, NULL, {{0}, {0}}}, {"title", {&display_title}, justset, NULL, {{FALSE}, {TRUE}}}, {"tty", {NULL}, set_process_state, NULL, {{0}, {PID_USETTY}}}, + {"utf8", {&use_utf8}, justset, NULL, {{FALSE}, {TRUE}}}, {"winsymlinks", {&allow_winsymlinks}, justset, NULL, {{FALSE}, {TRUE}}}, {NULL, {0}, justset, 0, {{0}, {0}}} }; Index: fhandler.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/fhandler.cc,v retrieving revision 1.130 diff -u -3 -p -u -p -r1.130 fhandler.cc --- fhandler.cc 24 Jun 2002 02:23:14 -0000 1.130 +++ fhandler.cc 3 Jul 2002 12:32:14 -0000 @@ -424,8 +424,20 @@ fhandler_base::open (path_conv *pc, int if (flags & O_CREAT && get_device () == FH_DISK && allow_ntsec && has_acls ()) set_security_attribute (mode, &sa, alloca (4096), 4096); - x = CreateFile (get_win32_name (), access, shared, &sa, creation_distribution, - file_attributes, 0); + if (use_utf8) + { + WCHAR wbuf[MAX_PATH]; + if (sys_utf8towcs (wbuf, get_win32_name(), MAX_PATH) == 0) + { + __seterrno (); + goto done; + } + x = CreateFileW (wbuf, access, shared, &sa, creation_distribution, + file_attributes, 0); + } + else + x = CreateFileA (get_win32_name (), access, shared, &sa, creation_distribution, + file_attributes, 0); syscall_printf ("%p = CreateFileA (%s, %p, %p, %p, %p, %p, 0)", x, get_win32_name (), access, shared, &sa, Index: fhandler_disk_file.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/fhandler_disk_file.cc,v retrieving revision 1.27 diff -u -3 -p -u -p -r1.27 fhandler_disk_file.cc --- fhandler_disk_file.cc 27 Jun 2002 03:06:44 -0000 1.27 +++ fhandler_disk_file.cc 3 Jul 2002 12:32:17 -0000 @@ -100,7 +100,10 @@ fhandler_disk_file::fstat_by_name (struc { int res; HANDLE handle; - WIN32_FIND_DATA local; + union { + WIN32_FIND_DATAA ansi_find_data; + WIN32_FIND_DATAW unicode_find_data; + } local; if (!pc->exists ()) { @@ -125,7 +128,15 @@ fhandler_disk_file::fstat_by_name (struc name = drivebuf; } - if ((handle = FindFirstFile (name, &local)) == INVALID_HANDLE_VALUE) + if (use_utf8) + { + WCHAR wbuf[MAX_PATH]; + sys_utf8towcs (wbuf, name, MAX_PATH); + handle = FindFirstFileW (wbuf, &local.unicode_find_data); + } + else + handle = FindFirstFileA (name, &local.ansi_find_data); + if (handle == INVALID_HANDLE_VALUE) { debug_printf ("FindFirstFile failed for '%s', %E", name); __seterrno (); @@ -135,13 +146,14 @@ fhandler_disk_file::fstat_by_name (struc { FindClose (handle); res = fstat_helper (buf, pc, - local.ftCreationTime, - local.ftLastAccessTime, - local.ftLastWriteTime, - local.nFileSizeHigh, - local.nFileSizeLow); + local.ansi_find_data.ftCreationTime, + local.ansi_find_data.ftLastAccessTime, + local.ansi_find_data.ftLastWriteTime, + local.ansi_find_data.nFileSizeHigh, + local.ansi_find_data.nFileSizeLow); } } +out: return res; } @@ -623,14 +635,24 @@ fhandler_disk_file::opendir (path_conv& struct dirent * fhandler_disk_file::readdir (DIR *dir) { - WIN32_FIND_DATA buf; + union { + WIN32_FIND_DATAA ansi_find_data; + WIN32_FIND_DATAW unicode_find_data; + } buf; HANDLE handle; struct dirent *res = NULL; if (dir->__d_u.__d_data.__handle == INVALID_HANDLE_VALUE && dir->__d_position == 0) { - handle = FindFirstFileA (dir->__d_dirname, &buf); + if (use_utf8) + { + WCHAR wbuf[MAX_PATH]; + sys_utf8towcs (wbuf, dir->__d_dirname, MAX_PATH); + handle = FindFirstFileW (wbuf, &buf.unicode_find_data); + } + else + handle = FindFirstFileA (dir->__d_dirname, &buf.ansi_find_data); DWORD lasterr = GetLastError (); dir->__d_u.__d_data.__handle = handle; if (handle == INVALID_HANDLE_VALUE && (lasterr != ERROR_NO_MORE_FILES)) @@ -643,25 +665,36 @@ fhandler_disk_file::readdir (DIR *dir) { return res; } - else if (!FindNextFileA (dir->__d_u.__d_data.__handle, &buf)) + else { - DWORD lasterr = GetLastError (); - (void) FindClose (dir->__d_u.__d_data.__handle); - dir->__d_u.__d_data.__handle = INVALID_HANDLE_VALUE; - /* POSIX says you shouldn't set errno when readdir can't - find any more files; so, if another error we leave it set. */ - if (lasterr != ERROR_NO_MORE_FILES) - seterrno_from_win_error (__FILE__, __LINE__, lasterr); - syscall_printf ("%p = readdir (%p)", res, dir); - return res; + BOOL success; + if (use_utf8) + success = FindNextFileW (dir->__d_u.__d_data.__handle, &buf.unicode_find_data); + else + success = FindNextFileA (dir->__d_u.__d_data.__handle, &buf.ansi_find_data); + if (!success) + { + DWORD lasterr = GetLastError (); + (void) FindClose (dir->__d_u.__d_data.__handle); + dir->__d_u.__d_data.__handle = INVALID_HANDLE_VALUE; + /* POSIX says you shouldn't set errno when readdir can't + find any more files; so, if another error we leave it set. */ + if (lasterr != ERROR_NO_MORE_FILES) + seterrno_from_win_error (__FILE__, __LINE__, lasterr); + syscall_printf ("%p = readdir (%p)", res, dir); + return res; + } } /* We get here if `buf' contains valid data. */ - strcpy (dir->__d_dirent->d_name, buf.cFileName); + if (use_utf8) + sys_wcstoutf8 (dir->__d_dirent->d_name, buf.unicode_find_data.cFileName, MAX_PATH); + else + strcpy (dir->__d_dirent->d_name, buf.ansi_find_data.cFileName); /* Check for Windows shortcut. If it's a Cygwin or U/WIN symlink, drop the .lnk suffix. */ - if (buf.dwFileAttributes & FILE_ATTRIBUTE_READONLY) + if (buf.ansi_find_data.dwFileAttributes & FILE_ATTRIBUTE_READONLY) { char *c = dir->__d_dirent->d_name; int len = strlen (c); @@ -679,7 +712,7 @@ fhandler_disk_file::readdir (DIR *dir) dir->__d_position++; res = dir->__d_dirent; syscall_printf ("%p = readdir (%p) (%s)", - &dir->__d_dirent, dir, buf.cFileName); + &dir->__d_dirent, dir, dir->__d_dirent->d_name); return res; } Index: miscfuncs.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/miscfuncs.cc,v retrieving revision 1.12 diff -u -3 -p -u -p -r1.12 miscfuncs.cc --- miscfuncs.cc 26 Jun 2002 05:29:41 -0000 1.12 +++ miscfuncs.cc 3 Jul 2002 12:32:17 -0000 @@ -196,3 +196,31 @@ sys_mbstowcs (WCHAR *tgt, const char *sr { return MultiByteToWideChar (get_cp (), 0, src, -1, tgt, len); } + +int __stdcall +sys_wcstoutf8 (char *tgt, const WCHAR *src, int len) +{ + int res = WideCharToMultiByte (CP_UTF8, 0, src, -1, tgt, len, NULL, NULL); + if (res == 0) + { + DWORD lasterr = GetLastError (); + if (lasterr == ERROR_INVALID_FLAGS || + lasterr == ERROR_INVALID_PARAMETER) + api_fatal ("UTF8 conversion is not supported by this system"); + } + return res; +} + +int __stdcall +sys_utf8towcs (WCHAR *tgt, const char *src, int len) +{ + int res = MultiByteToWideChar (CP_UTF8, 0, src, -1, tgt, len); + if (res == 0) + { + DWORD lasterr = GetLastError (); + if (lasterr == ERROR_INVALID_FLAGS || + lasterr == ERROR_INVALID_PARAMETER) + api_fatal ("UTF8 conversion is not supported by this system"); + } + return res; +} Index: path.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/path.cc,v retrieving revision 1.225 diff -u -3 -p -u -p -r1.225 path.cc --- path.cc 1 Jul 2002 19:03:26 -0000 1.225 +++ path.cc 3 Jul 2002 12:32:27 -0000 @@ -387,7 +387,7 @@ path_conv::fillin (HANDLE h) fs.serial = local.dwVolumeSerialNumber; } fs.drive_type = DRIVE_UNKNOWN; -} +} /* Convert an arbitrary path SRC to a pure Win32 path, suitable for passing to Win32 API routines. @@ -519,7 +519,14 @@ path_conv::check (const char *src, unsig else { devn = FH_BAD; - fileattr = GetFileAttributes (this->path); + if (use_utf8) + { + WCHAR wbuf[MAX_PATH]; + sys_utf8towcs (wbuf, this->path, MAX_PATH); + fileattr = GetFileAttributesW (wbuf); + } + else + fileattr = GetFileAttributesA (this->path); } goto out; } @@ -578,7 +585,14 @@ path_conv::check (const char *src, unsig if ((opt & PC_SYM_IGNORE) && pcheck_case == PCHECK_RELAXED) { - fileattr = GetFileAttributes (this->path); + if (use_utf8) + { + WCHAR wbuf[MAX_PATH]; + sys_utf8towcs (wbuf, this->path, MAX_PATH); + fileattr = GetFileAttributesW (wbuf); + } + else + fileattr = GetFileAttributesA (this->path); goto out; } @@ -2557,6 +2571,7 @@ symlink (const char *topath, const char char w32topath[MAX_PATH + 1]; DWORD written; SECURITY_ATTRIBUTES sa = sec_none_nih; + WCHAR *wbuf = NULL; /* POSIX says that empty 'frompath' is invalid input whlie empty 'topath' is valid -- it's symlink resolver job to verify if @@ -2593,6 +2608,12 @@ symlink (const char *topath, const char goto done; } + if (use_utf8) + { + wbuf = (WCHAR *) alloca (MAX_PATH * sizeof (WCHAR)); + sys_utf8towcs (wbuf, w32topath, MAX_PATH); + } + if (allow_winsymlinks) { if (!isabspath (topath)) @@ -2606,7 +2627,12 @@ symlink (const char *topath, const char } backslashify (topath, w32topath, 0); } - if (!cp || GetFileAttributes (w32topath) == INVALID_FILE_ATTRIBUTES) + DWORD fileattr; + if (use_utf8) + fileattr = GetFileAttributesW (wbuf); + else + fileattr = GetFileAttributesA (w32topath); + if (!cp || fileattr == INVALID_FILE_ATTRIBUTES) { win32_topath.check (topath, PC_SYM_NOFOLLOW); if (!cp || win32_topath.error != ENOENT) @@ -2623,8 +2649,15 @@ symlink (const char *topath, const char set_security_attribute (S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO, &sa, alloca (4096), 4096); - h = CreateFileA(win32_path, GENERIC_WRITE, 0, &sa, - CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0); + if (use_utf8) + { + sys_utf8towcs (wbuf, win32_path, MAX_PATH); + h = CreateFileW(wbuf, GENERIC_WRITE, 0, &sa, + CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0); + } + else + h = CreateFileA(win32_path, GENERIC_WRITE, 0, &sa, + CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0); if (h == INVALID_HANDLE_VALUE) __seterrno (); else @@ -2678,7 +2711,10 @@ symlink (const char *topath, const char if ((cp && cp[1] == '.') || *win32_path == '.') attr |= FILE_ATTRIBUTE_HIDDEN; #endif - SetFileAttributes (win32_path.get_win32 (), attr); + if (use_utf8) + SetFileAttributesW (wbuf, attr); + else + SetFileAttributesA (win32_path.get_win32 (), attr); if (win32_path.fs_fast_ea ()) set_symlink_ea (win32_path, topath); @@ -2688,7 +2724,10 @@ symlink (const char *topath, const char { __seterrno (); CloseHandle (h); - DeleteFileA (win32_path.get_win32 ()); + if (use_utf8) + DeleteFileW (wbuf); + else + DeleteFileA (win32_path.get_win32 ()); } } @@ -2907,7 +2946,14 @@ symlink_info::check (char *path, const s while (suffix.next ()) { error = 0; - fileattr = GetFileAttributes (suffix.path); + if (use_utf8) + { + WCHAR wbuf[MAX_PATH]; + sys_utf8towcs (wbuf, suffix.path, MAX_PATH); + fileattr = GetFileAttributesW (wbuf); + } + else + fileattr = GetFileAttributesA (suffix.path); if (fileattr == INVALID_FILE_ATTRIBUTES) { /* The GetFileAttributes call can fail for reasons that don't @@ -2955,8 +3001,16 @@ symlink_info::check (char *path, const s /* Open the file. */ - h = CreateFileA (suffix.path, GENERIC_READ, FILE_SHARE_READ, &sec_none_nih, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, 0); + if (use_utf8) + { + WCHAR wbuf[MAX_PATH]; + sys_utf8towcs (wbuf, suffix.path, MAX_PATH); + h = CreateFileW (wbuf, GENERIC_READ, FILE_SHARE_READ, &sec_none_nih, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, 0); + } + else + h = CreateFileA (suffix.path, GENERIC_READ, FILE_SHARE_READ, &sec_none_nih, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, 0); res = -1; if (h == INVALID_HANDLE_VALUE) goto file_not_symlink; @@ -3231,7 +3285,16 @@ chdir (const char *in_dir) int res; int devn = path.get_devn(); if (!isvirtual_dev (devn)) - res = SetCurrentDirectory (native_dir) ? 0 : -1; + { + if (use_utf8) + { + WCHAR wbuf[MAX_PATH]; + sys_utf8towcs (wbuf, native_dir, MAX_PATH); + res = SetCurrentDirectoryW (wbuf) ? 0 : -1; + } + else + res = SetCurrentDirectoryA (native_dir) ? 0 : -1; + } else if (!path.exists ()) { set_errno (ENOENT); @@ -3568,11 +3631,27 @@ cwdstuff::get_initial () int i; DWORD len, dlen; - for (i = 0, dlen = MAX_PATH, len = 0; i < 3; dlen *= 2, i++) + if (use_utf8) { - win32 = (char *) crealloc (win32, dlen + 2); - if ((len = GetCurrentDirectoryA (dlen, win32)) < dlen) - break; + WCHAR *wbuf = NULL; + for (i = 0, dlen = MAX_PATH, len = 0; i < 3; dlen *= 2, i++) + { + wbuf = (WCHAR *) crealloc (wbuf, dlen + 2); + if ((len = GetCurrentDirectoryW (dlen, wbuf)) < dlen) + break; + } + int alen = sys_wcstoutf8 (NULL, wbuf, 0); + win32 = (char *) crealloc (win32, alen); + sys_wcstoutf8 (win32, wbuf, alen); + } + else + { + for (i = 0, dlen = MAX_PATH, len = 0; i < 3; dlen *= 2, i++) + { + win32 = (char *) crealloc (win32, dlen + 2); + if ((len = GetCurrentDirectoryA (dlen, win32)) < dlen) + break; + } } if (len == 0) Index: security.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/security.cc,v retrieving revision 1.112 diff -u -3 -p -u -p -r1.112 security.cc --- security.cc 2 Jul 2002 09:02:53 -0000 1.112 +++ security.cc 3 Jul 2002 12:32:31 -0000 @@ -1023,11 +1023,24 @@ read_sd (const char *file, PSECURITY_DES pfile = fbuf; } - if (!GetFileSecurity (pfile, - OWNER_SECURITY_INFORMATION - | GROUP_SECURITY_INFORMATION - | DACL_SECURITY_INFORMATION, - sd_buf, *sd_size, &len)) + BOOL res; + if (use_utf8) + { + WCHAR wbuf[MAX_PATH]; + sys_utf8towcs (wbuf, file, MAX_PATH); + res = GetFileSecurityW (wbuf, + OWNER_SECURITY_INFORMATION + | GROUP_SECURITY_INFORMATION + | DACL_SECURITY_INFORMATION, + sd_buf, *sd_size, &len); + } + else + res = GetFileSecurityA (pfile, + OWNER_SECURITY_INFORMATION + | GROUP_SECURITY_INFORMATION + | DACL_SECURITY_INFORMATION, + sd_buf, *sd_size, &len); + if (!res) { __seterrno (); return -1; @@ -1060,13 +1073,26 @@ write_sd (const char *file, PSECURITY_DE } HANDLE fh; - fh = CreateFile (file, - WRITE_OWNER | WRITE_DAC, - FILE_SHARE_READ | FILE_SHARE_WRITE, - &sec_none_nih, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, - NULL); + if (use_utf8) + { + WCHAR wbuf[MAX_PATH]; + sys_utf8towcs (wbuf, file, MAX_PATH); + fh = CreateFileW (wbuf, + WRITE_OWNER | WRITE_DAC, + FILE_SHARE_READ | FILE_SHARE_WRITE, + &sec_none_nih, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, + NULL); + } + else + fh = CreateFileA (file, + WRITE_OWNER | WRITE_DAC, + FILE_SHARE_READ | FILE_SHARE_WRITE, + &sec_none_nih, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, + NULL); if (fh == INVALID_HANDLE_VALUE) { Index: syscalls.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/syscalls.cc,v retrieving revision 1.214 diff -u -3 -p -u -p -r1.214 syscalls.cc --- syscalls.cc 2 Jul 2002 03:06:32 -0000 1.214 +++ syscalls.cc 3 Jul 2002 12:32:37 -0000 @@ -95,6 +95,7 @@ _unlink (const char *ourname) { int res = -1; DWORD devn; + WCHAR *wbuf = NULL; sigframe thisframe (mainthread); path_conv win32_name (ourname, PC_SYM_NOFOLLOW | PC_FULL); @@ -134,19 +135,35 @@ _unlink (const char *ourname) goto done; } + if (use_utf8) + { + wbuf = (WCHAR *) alloca (MAX_PATH * sizeof (WCHAR)); + sys_utf8towcs (wbuf, win32_name, MAX_PATH); + } + /* Check for shortcut as symlink condition. */ if (win32_name.has_attribute (FILE_ATTRIBUTE_READONLY)) { int len = strlen (win32_name); if (len > 4 && strcasematch ((char *) win32_name + len - 4, ".lnk")) - SetFileAttributes (win32_name, (DWORD) win32_name & ~FILE_ATTRIBUTE_READONLY); + { + if (use_utf8) + SetFileAttributesW (wbuf, (DWORD) win32_name & ~FILE_ATTRIBUTE_READONLY); + else + SetFileAttributesA (win32_name, (DWORD) win32_name & ~FILE_ATTRIBUTE_READONLY); + } } DWORD lasterr; lasterr = 0; for (int i = 0; i < 2; i++) { - if (DeleteFile (win32_name)) + BOOL success; + if (use_utf8) + success = DeleteFileW (wbuf); + else + success = DeleteFileA (win32_name); + if (success) { syscall_printf ("DeleteFile succeeded"); goto ok; @@ -188,8 +205,12 @@ _unlink (const char *ourname) /* Attempt to use "delete on close" semantics to handle removing a file which may be open. */ HANDLE h; - h = CreateFile (win32_name, GENERIC_READ, FILE_SHARE_READ, &sec_none_nih, - OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, 0); + if (use_utf8) + h = CreateFileW (wbuf, GENERIC_READ, FILE_SHARE_READ, &sec_none_nih, + OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, 0); + else + h = CreateFileA (win32_name, GENERIC_READ, FILE_SHARE_READ, &sec_none_nih, + OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, 0); if (h == INVALID_HANDLE_VALUE) { if (GetLastError () == ERROR_FILE_NOT_FOUND) @@ -201,7 +222,12 @@ _unlink (const char *ourname) syscall_printf ("CreateFile/CloseHandle succeeded"); /* Everything is fine if the file has disappeared or if we know that the FILE_FLAG_DELETE_ON_CLOSE will eventually work. */ - if (GetFileAttributes (win32_name) == INVALID_FILE_ATTRIBUTES + DWORD fileattr; + if (use_utf8) + fileattr = GetFileAttributesW (wbuf); + else + fileattr = GetFileAttributesA (win32_name); + if (fileattr == INVALID_FILE_ATTRIBUTES || delete_on_close_ok) goto ok; /* The file is either gone already or will eventually be deleted by the OS. */ @@ -614,6 +640,7 @@ extern "C" int _link (const char *a, const char *b) { int res = -1; + WCHAR *wbuf_a = NULL, *wbuf_b = NULL; sigframe thisframe (mainthread); path_conv real_b (b, PC_SYM_NOFOLLOW | PC_FULL); path_conv real_a (a, PC_SYM_NOFOLLOW | PC_FULL); @@ -644,10 +671,23 @@ _link (const char *a, const char *b) goto done; } + if (use_utf8) + { + wbuf_a = (WCHAR *) alloca (MAX_PATH * sizeof (WCHAR)); + wbuf_b = (WCHAR *) alloca (MAX_PATH * sizeof (WCHAR)); + sys_utf8towcs (wbuf_a, real_a, MAX_PATH); + sys_utf8towcs (wbuf_b, real_b, MAX_PATH); + } + /* Try to make hard link first on Windows NT */ if (wincap.has_hard_links ()) { - if (CreateHardLinkA (real_b, real_a, NULL)) + BOOL success; + if (use_utf8) + success = (BOOL) CreateHardLinkW (wbuf_b, wbuf_a, NULL); + else + success = (BOOL) CreateHardLinkA (real_b, real_a, NULL); + if (success) { res = 0; goto done; @@ -664,7 +704,18 @@ _link (const char *a, const char *b) BOOL bSuccess; - hFileSource = CreateFile ( + if (use_utf8) + hFileSource = CreateFileW ( + wbuf_a, + FILE_WRITE_ATTRIBUTES, + FILE_SHARE_READ | FILE_SHARE_WRITE /*| FILE_SHARE_DELETE*/, + &sec_none_nih, // sa + OPEN_EXISTING, + 0, + NULL + ); + else + hFileSource = CreateFileA ( real_a, FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE /*| FILE_SHARE_DELETE*/, @@ -743,7 +794,12 @@ _link (const char *a, const char *b) } docopy: /* do this with a copy */ - if (CopyFileA (real_a, real_b, 1)) + BOOL success; + if (use_utf8) + success = CopyFileW (wbuf_a, wbuf_b, 1); + else + success = CopyFileA (real_a, real_b, 1); + if (success) res = 0; else __seterrno (); @@ -900,6 +956,7 @@ extern "C" int chmod (const char *path, mode_t mode) { int res = -1; + WCHAR *wbuf = NULL; sigframe thisframe (mainthread); path_conv win32_path (path); @@ -923,7 +980,14 @@ chmod (const char *path, mode_t mode) else { /* temporary erase read only bit, to be able to set file security */ - SetFileAttributes (win32_path, (DWORD) win32_path & ~FILE_ATTRIBUTE_READONLY); + if (use_utf8) + { + wbuf = (WCHAR *) alloca (MAX_PATH * sizeof (WCHAR)); + sys_utf8towcs (wbuf, win32_path, MAX_PATH); + SetFileAttributesW (wbuf, (DWORD) win32_path & ~FILE_ATTRIBUTE_READONLY); + } + else + SetFileAttributesA (win32_path, (DWORD) win32_path & ~FILE_ATTRIBUTE_READONLY); __uid32_t uid; __gid32_t gid; @@ -951,7 +1015,12 @@ chmod (const char *path, mode_t mode) if (S_ISLNK (mode) || S_ISSOCK (mode)) (DWORD) win32_path |= FILE_ATTRIBUTE_SYSTEM; - if (!SetFileAttributes (win32_path, win32_path)) + BOOL success; + if (use_utf8) + success = SetFileAttributesW (wbuf, win32_path); + else + success = SetFileAttributesA (win32_path, win32_path); + if (!success) __seterrno (); else { @@ -1251,6 +1320,7 @@ _rename (const char *oldpath, const char sigframe thisframe (mainthread); int res = 0; char *lnk_suffix = NULL; + WCHAR *wbuf_old = NULL, *wbuf_new = NULL; path_conv real_old (oldpath, PC_SYM_NOFOLLOW); @@ -1298,10 +1368,23 @@ _rename (const char *oldpath, const char return (-1); } + if (use_utf8) + { + wbuf_old = (WCHAR *) alloca (MAX_PATH * sizeof (WCHAR)); + wbuf_new = (WCHAR *) alloca (MAX_PATH * sizeof (WCHAR)); + sys_utf8towcs (wbuf_old, real_old, MAX_PATH); + sys_utf8towcs (wbuf_new, real_new, MAX_PATH); + } + /* Destination file exists and is read only, change that or else the rename won't work. */ if (real_new.has_attribute (FILE_ATTRIBUTE_READONLY)) - SetFileAttributes (real_new, (DWORD) real_new & ~FILE_ATTRIBUTE_READONLY); + { + if (use_utf8) + SetFileAttributesW (wbuf_new, (DWORD) real_new & ~FILE_ATTRIBUTE_READONLY); + else + SetFileAttributesA (real_new, (DWORD) real_new & ~FILE_ATTRIBUTE_READONLY); + } /* Shortcut hack No. 2, part 1 */ if (!real_old.issymlink () && !real_new.error && real_new.issymlink () && @@ -1309,7 +1392,12 @@ _rename (const char *oldpath, const char (lnk_suffix = strrchr (real_new.get_win32 (), '.'))) *lnk_suffix = '\0'; - if (!MoveFile (real_old, real_new)) + BOOL success; + if (use_utf8) + success = MoveFileW (wbuf_old, wbuf_new); + else + success = MoveFileA (real_old, real_new); + if (success) res = -1; if (res == 0 || (GetLastError () != ERROR_ALREADY_EXISTS @@ -1318,8 +1406,12 @@ _rename (const char *oldpath, const char if (wincap.has_move_file_ex ()) { - if (MoveFileEx (real_old.get_win32 (), real_new.get_win32 (), - MOVEFILE_REPLACE_EXISTING)) + if (use_utf8) + success = MoveFileExW (wbuf_old, wbuf_new, + MOVEFILE_REPLACE_EXISTING); + else + success = MoveFileExA (real_old.get_win32 (), real_new.get_win32 (), + MOVEFILE_REPLACE_EXISTING); res = 0; } else @@ -1327,18 +1419,29 @@ _rename (const char *oldpath, const char syscall_printf ("try win95 hack"); for (int i = 0; i < 2; i++) { - if (!DeleteFileA (real_new.get_win32 ()) && + if (use_utf8) + success = DeleteFileW (wbuf_new); + else + success = DeleteFileA (real_new.get_win32()); + if (!success && GetLastError () != ERROR_FILE_NOT_FOUND) { syscall_printf ("deleting %s to be paranoid", real_new.get_win32 ()); break; } - else if (MoveFile (real_old.get_win32 (), real_new.get_win32 ())) - { - res = 0; - break; - } + else + { + if (use_utf8) + success = MoveFileW (wbuf_old, wbuf_new); + else + success = MoveFileA (real_old.get_win32 (), real_new.get_win32 ()); + if (success) + { + res = 0; + break; + } + } } } @@ -1348,7 +1451,12 @@ done: __seterrno (); /* Reset R/O attributes if neccessary. */ if (real_new.has_attribute (FILE_ATTRIBUTE_READONLY)) - SetFileAttributes (real_new, real_new); + { + if (use_utf8) + SetFileAttributesW (wbuf_new, real_new); + else + SetFileAttributesA (real_new, real_new); + } } else { @@ -1362,7 +1470,10 @@ done: if ((c && c[1] == '.') || *real_new.get_win32 () == '.') attr |= FILE_ATTRIBUTE_HIDDEN; #endif - SetFileAttributes (real_new, attr); + if (use_utf8) + SetFileAttributesW (wbuf_new, attr); + else + SetFileAttributesA (real_new, attr); /* Shortcut hack, No. 2, part 2 */ /* if the new filename was an existing shortcut, remove it now if the @@ -1370,7 +1481,10 @@ done: if (lnk_suffix) { *lnk_suffix = '.'; - DeleteFile (real_new); + if (use_utf8) + DeleteFileW (wbuf_new); + else + DeleteFileA (real_new); } } Index: wincap.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/wincap.cc,v retrieving revision 1.14 diff -u -3 -p -u -p -r1.14 wincap.cc --- wincap.cc 10 Jun 2002 17:08:09 -0000 1.14 +++ wincap.cc 3 Jul 2002 12:32:39 -0000 @@ -46,6 +46,8 @@ static NO_COPY wincaps wincap_unknown = has_valid_processorlevel:false, has_64bit_file_access:false, has_process_io_counters:false, + supports_unicode:false, + supports_utf8:false, }; static NO_COPY wincaps wincap_95 = { @@ -83,6 +85,8 @@ static NO_COPY wincaps wincap_95 = { has_valid_processorlevel:false, has_64bit_file_access:false, has_process_io_counters:false, + supports_unicode:false, + supports_utf8:false, }; static NO_COPY wincaps wincap_95osr2 = { @@ -120,6 +124,8 @@ static NO_COPY wincaps wincap_95osr2 = { has_valid_processorlevel:false, has_64bit_file_access:false, has_process_io_counters:false, + supports_unicode:false, + supports_utf8:false, }; static NO_COPY wincaps wincap_98 = { @@ -157,6 +163,8 @@ static NO_COPY wincaps wincap_98 = { has_valid_processorlevel:true, has_64bit_file_access:false, has_process_io_counters:false, + supports_unicode:false, + supports_utf8:false, }; static NO_COPY wincaps wincap_98se = { @@ -194,6 +202,8 @@ static NO_COPY wincaps wincap_98se = { has_valid_processorlevel:true, has_64bit_file_access:false, has_process_io_counters:false, + supports_unicode:false, + supports_utf8:false, }; static NO_COPY wincaps wincap_me = { @@ -231,6 +241,8 @@ static NO_COPY wincaps wincap_me = { has_valid_processorlevel:true, has_64bit_file_access:false, has_process_io_counters:false, + supports_unicode:false, + supports_utf8:false, }; static NO_COPY wincaps wincap_nt3 = { @@ -268,6 +280,8 @@ static NO_COPY wincaps wincap_nt3 = { has_valid_processorlevel:true, has_64bit_file_access:true, has_process_io_counters:false, + supports_unicode:true, + supports_utf8:false, }; static NO_COPY wincaps wincap_nt4 = { @@ -305,6 +319,8 @@ static NO_COPY wincaps wincap_nt4 = { has_valid_processorlevel:true, has_64bit_file_access:true, has_process_io_counters:false, + supports_unicode:true, + supports_utf8:true, }; static NO_COPY wincaps wincap_nt4sp4 = { @@ -342,6 +358,8 @@ static NO_COPY wincaps wincap_nt4sp4 = { has_valid_processorlevel:true, has_64bit_file_access:true, has_process_io_counters:false, + supports_unicode:true, + supports_utf8:true, }; static NO_COPY wincaps wincap_2000 = { @@ -379,6 +397,8 @@ static NO_COPY wincaps wincap_2000 = { has_valid_processorlevel:true, has_64bit_file_access:true, has_process_io_counters:true, + supports_unicode:true, + supports_utf8:true, }; static NO_COPY wincaps wincap_xp = { @@ -416,6 +436,8 @@ static NO_COPY wincaps wincap_xp = { has_valid_processorlevel:true, has_64bit_file_access:true, has_process_io_counters:true, + supports_unicode:true, + supports_utf8:true, }; wincapc wincap; Index: wincap.h =================================================================== RCS file: /cvs/src/src/winsup/cygwin/wincap.h,v retrieving revision 1.11 diff -u -3 -p -u -p -r1.11 wincap.h --- wincap.h 13 Jun 2002 17:28:11 -0000 1.11 +++ wincap.h 3 Jul 2002 12:32:39 -0000 @@ -47,6 +47,8 @@ struct wincaps unsigned has_valid_processorlevel : 1; unsigned has_64bit_file_access : 1; unsigned has_process_io_counters : 1; + unsigned supports_unicode : 1; + unsigned supports_utf8 : 1; }; class wincapc @@ -98,6 +100,8 @@ public: bool IMPLEMENT (has_valid_processorlevel) bool IMPLEMENT (has_64bit_file_access) bool IMPLEMENT (has_process_io_counters) + bool IMPLEMENT (supports_unicode) + bool IMPLEMENT (supports_utf8) #undef IMPLEMENT }; Index: winsup.h =================================================================== RCS file: /cvs/src/src/winsup/cygwin/winsup.h,v retrieving revision 1.96 diff -u -3 -p -u -p -r1.96 winsup.h --- winsup.h 27 Jun 2002 20:44:27 -0000 1.96 +++ winsup.h 3 Jul 2002 12:32:40 -0000 @@ -76,6 +76,12 @@ int __stdcall sys_wcstombs(char *, const int __stdcall sys_mbstowcs(WCHAR *, const char *, int) __attribute__ ((regparm(3))); +int __stdcall sys_wcstoutf8 (char *, const WCHAR *, int) + __attribute__ ((regparm(3))); + +int __stdcall sys_utf8towcs (WCHAR *, const char *, int) + __attribute__ ((regparm(3))); + /* Used to check if Cygwin DLL is dynamically loaded. */ extern int dynamically_loaded; @@ -260,6 +266,7 @@ extern SYSTEM_INFO system_info; /*************************** Unsorted ******************************/ #define WM_ASYNCIO 0x8000 // WM_APP +#define CP_UTF8 65001 /* Note that MAX_PATH is defined in the windows headers */ /* There is also PATH_MAX and MAXPATHLEN. @@ -287,6 +294,8 @@ extern HANDLE hMainProc; extern bool cygwin_testing; extern unsigned _cygwin_testing_magic; extern HMODULE cygwin_hmodule; + +extern BOOL use_utf8; extern char almost_null[];