Revision: 8669 https://osdn.net/projects/ttssh2/scm/svn/commits/8669 Author: zmatsuo Date: 2020-04-01 23:31:24 +0900 (Wed, 01 Apr 2020) Log Message: ----------- ファイル操作コマンドの Unicode 対応 - 内部文字コード(UTF-8) <-> wchar_t文字列の変換 - Cライブラリではなく、直にWin32 APIを使用する方針 - Cライブラリの実装に左右されないようにするため - _lopen, _lcreat の wchar_t 版へ差し替え(common/win16api, CreateFileW()) - fileconcat - filecreate - fileopen - CopyFileA() -> CopyFileW() - filecopy - remove() -> DeleteFileW() - filedelete - rename() -> MoveFileW() - filerename - DoesFileExist()#ttlib.c(内部で_stat()) -> GetFileAttributesW() - filesearch - _stat() -> CreateFileW(), GetFileSize(), GetFileTime() - filestat - _sopen_s() -> _chsize_s(), _close() -> CreateFileW(), SetFilePointer(), SetEndOfFile(), CloseHandle() - filetruncate - _findfirst(),_findnext() -> FindFirstFileW(), FindNextFileW() - findfirst - findnext - RemoveDirectoryA() -> RemoveDirectoryW() - folderdelete - DoesFolderExist()(内部で_stat()) -> GetFileAttributesW() - foldersearch - GetFileAttributesA() -> GetFileAttributesW() - getfileattr - _getcwd(),_chdir() -> GetCurrentDirectoryW(), SetCurrentDirectoryW() - setdir - SetFileAttributes() -> SetFileAttributesW() - setfileattr Modified Paths: -------------- branches/unicode_macro_2/teraterm/common/win16api.c branches/unicode_macro_2/teraterm/common/win16api.h branches/unicode_macro_2/teraterm/ttpmacro/ttl.cpp branches/unicode_macro_2/teraterm/ttpmacro/ttmlib.c branches/unicode_macro_2/teraterm/ttpmacro/ttmlib.h -------------- next part -------------- Modified: branches/unicode_macro_2/teraterm/common/win16api.c =================================================================== --- branches/unicode_macro_2/teraterm/common/win16api.c 2020-04-01 14:31:14 UTC (rev 8668) +++ branches/unicode_macro_2/teraterm/common/win16api.c 2020-04-01 14:31:24 UTC (rev 8669) @@ -2,11 +2,28 @@ #include <assert.h> /** + * win16_lcreat() \x82\xCC wchar_t\x94\xC5 * @param[in] iAttribute teraterm\x82ł\xCD0\x82\xB5\x82\xA9\x8Eg\x97p\x82\xB5\x82Ȃ\xA2 * @retval handle * @retval INVALID_HANDLE_VALUE((HANDLE)(LONG_PTR)-1) \x83I\x81[\x83v\x83\x93\x82ł\xAB\x82Ȃ\xA9\x82\xC1\x82\xBD * (\x8E\xC0\x8Dۂ\xCCAPI\x82\xCDHFILE_ERROR((HFILE)-1)\x82\xF0\x95Ԃ\xB7) */ +HANDLE win16_lcreatW(const wchar_t *FileName, int iAttribute) +{ + HANDLE handle; + assert(iAttribute == 0); + handle = CreateFileW(FileName, + GENERIC_WRITE, FILE_SHARE_WRITE, NULL, + CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + return handle; +} + +/** + * @param[in] iAttribute teraterm\x82ł\xCD0\x82\xB5\x82\xA9\x8Eg\x97p\x82\xB5\x82Ȃ\xA2 + * @retval handle + * @retval INVALID_HANDLE_VALUE((HANDLE)(LONG_PTR)-1) \x83I\x81[\x83v\x83\x93\x82ł\xAB\x82Ȃ\xA9\x82\xC1\x82\xBD + * (\x8E\xC0\x8Dۂ\xCCAPI\x82\xCDHFILE_ERROR((HFILE)-1)\x82\xF0\x95Ԃ\xB7) + */ HANDLE win16_lcreat(const char *FileName, int iAttribute) { HANDLE handle; @@ -18,10 +35,46 @@ } /** + * win16_lopen() \x82\xCC wchar_t \x94\xC5 * @retval handle * @retval INVALID_HANDLE_VALUE((HANDLE)(LONG_PTR)-1) \x83I\x81[\x83v\x83\x93\x82ł\xAB\x82Ȃ\xA9\x82\xC1\x82\xBD * (\x8E\xC0\x8Dۂ\xCCAPI\x82\xCDHFILE_ERROR((HFILE)-1)\x82\xF0\x95Ԃ\xB7) */ +HANDLE win16_lopenW(const wchar_t *FileName, int iReadWrite) +{ + HANDLE handle; + switch(iReadWrite) { + case OF_READ: + // read only + handle = CreateFileW(FileName, + GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + break; + case OF_WRITE: + // write + handle = CreateFileW(FileName, + GENERIC_WRITE, FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + break; + case OF_READWRITE: + // read/write (teraterm\x82ł\xCDttpmacro/ttl.c\x93\xE0\x82\xCC1\x89ӏ\x8A\x82݂̂Ŏg\x97p\x82\xB3\x82\xEA\x82Ă\xA2\x82\xE9 + handle = CreateFileW(FileName, + GENERIC_WRITE|GENERIC_READ, FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + break; + default: + assert(FALSE); + handle = INVALID_HANDLE_VALUE; + break; + } + return handle; +} + +/** + * @retval handle + * @retval INVALID_HANDLE_VALUE((HANDLE)(LONG_PTR)-1) \x83I\x81[\x83v\x83\x93\x82ł\xAB\x82Ȃ\xA9\x82\xC1\x82\xBD + * (\x8E\xC0\x8Dۂ\xCCAPI\x82\xCDHFILE_ERROR((HFILE)-1)\x82\xF0\x95Ԃ\xB7) + */ HANDLE win16_lopen(const char *FileName, int iReadWrite) { HANDLE handle; Modified: branches/unicode_macro_2/teraterm/common/win16api.h =================================================================== --- branches/unicode_macro_2/teraterm/common/win16api.h 2020-04-01 14:31:14 UTC (rev 8668) +++ branches/unicode_macro_2/teraterm/common/win16api.h 2020-04-01 14:31:24 UTC (rev 8669) @@ -4,7 +4,9 @@ extern "C" { #endif +HANDLE win16_lcreatW(const wchar_t *FileName, int iAttribute); HANDLE win16_lcreat(const char *FileName, int iAttribute); +HANDLE win16_lopenW(const wchar_t *FileName, int iReadWrite); HANDLE win16_lopen(const char *FileName, int iReadWrite); void win16_lclose(HANDLE hFile); UINT win16_lread(HANDLE hFile, void *buf, UINT uBytes); Modified: branches/unicode_macro_2/teraterm/ttpmacro/ttl.cpp =================================================================== --- branches/unicode_macro_2/teraterm/ttpmacro/ttl.cpp 2020-04-01 14:31:14 UTC (rev 8668) +++ branches/unicode_macro_2/teraterm/ttpmacro/ttl.cpp 2020-04-01 14:31:24 UTC (rev 8669) @@ -54,9 +54,6 @@ #include <sys/stat.h> #include <share.h> -// for _findXXXX() functions -#include <io.h> - #include "ttl.h" #include "SFMT.h" @@ -90,12 +87,17 @@ // for "FindXXXX" commands #define NumDirHandle 8 -static intptr_t DirHandle[NumDirHandle] = {-1,-1, -1, -1, -1, -1, -1, -1}; +static HANDLE DirHandle[NumDirHandle]; /* for "FileMarkPtr" and "FileSeekBack" commands */ #define NumFHandle 16 static HANDLE FHandle[NumFHandle]; static long FPointer[NumFHandle]; +#undef _lcreat +#define _lcreat(p1,p2) win16_lcreatW(p1,p2) +#undef _lopen +#define _lopen(p1,p2) win16_lopenW(p1,p2) + // forward declaration int ExecCmnd(); @@ -218,7 +220,7 @@ EndIfFlag = 0; for (i=0; i<NumDirHandle; i++) - DirHandle[i] = -1L; + DirHandle[i] = INVALID_HANDLE_VALUE; HandleInit(); if (! InitBuff(FileName)) @@ -253,9 +255,9 @@ for (i=0; i<NumDirHandle; i++) { - if (DirHandle[i]!=-1L) - _findclose(DirHandle[i]); - DirHandle[i] = -1L; + if (DirHandle[i] != INVALID_HANDLE_VALUE) + FindClose(DirHandle[i]); + DirHandle[i] = INVALID_HANDLE_VALUE; } UnlockVar(); @@ -1210,9 +1212,10 @@ return Err; } - FH1 = _lopen(FName1,OF_WRITE); + wc FName1W = wc::fromUtf8(FName1); + FH1 = _lopen(FName1W,OF_WRITE); if (FH1 == INVALID_HANDLE_VALUE) - FH1 = _lcreat(FName1,0); + FH1 = _lcreat(FName1W,0); if (FH1 == INVALID_HANDLE_VALUE) { SetResult(3); return Err; @@ -1219,7 +1222,8 @@ } _llseek(FH1,0,2); - FH2 = _lopen(FName2,OF_READ); + wc FName2W = wc::fromUtf8(FName2); + FH2 = _lopen(FName2W,OF_READ); if (FH2 != INVALID_HANDLE_VALUE) { do { @@ -1267,7 +1271,7 @@ return Err; } - ret = CopyFile(FName1, FName2, FALSE); + ret = CopyFileW(wc::fromUtf8(FName1), wc::fromUtf8(FName2), FALSE); if (ret == 0) { SetResult(-4); return Err; @@ -1301,7 +1305,8 @@ SetResult(-1); return Err; } - FH = _lcreat(FName,0); + wc FNameW = wc::fromUtf8(FName); + FH = _lcreat(FNameW,0); if (FH == INVALID_HANDLE_VALUE) { SetResult(2); } @@ -1335,8 +1340,8 @@ SetResult(-1); return Err; } - - if (remove(FName) != 0) { + + if (DeleteFileW(wc::fromUtf8(FName)) != 0) { SetResult(-1); } else { @@ -1394,13 +1399,14 @@ return Err; } + wc FNameW = wc::fromUtf8(FName); if (ReadonlyFlag) { - FH = _lopen(FName,OF_READ); + FH = _lopen(FNameW,OF_READ); } else { - FH = _lopen(FName,OF_READWRITE); + FH = _lopen(FNameW,OF_READWRITE); if (FH == INVALID_HANDLE_VALUE) - FH = _lcreat(FName,0); + FH = _lcreat(FNameW,0); } if (FH == INVALID_HANDLE_VALUE) { SetIntVal(VarId, -1); @@ -1622,7 +1628,7 @@ SetResult(-2); return Err; } - if (rename(FName1,FName2) != 0) { + if (MoveFileW(wc::fromUtf8(FName1), wc::fromUtf8(FName2)) != 0) { // \x83\x8A\x83l\x81[\x83\x80\x82Ɏ\xB8\x94s\x82\xB5\x82\xBD\x82\xE7\x81A\x83G\x83\x89\x81[\x82ŕԂ\xB7\x81B SetResult(-3); return Err; @@ -1645,7 +1651,9 @@ if (Err!=0) return Err; GetAbsPath(FName,sizeof(FName)); - if (DoesFileExist(FName)) + DWORD attr = GetFileAttributesW(wc::fromUtf8(FName)); + if (attr != INVALID_FILE_ATTRIBUTES) + // exists file or folder SetResult(1); else SetResult(0); @@ -1688,15 +1696,24 @@ return Err; } +/* + * FILETIME -> time_t + */ +static time_t FileTimeToUnixTime(const FILETIME *ft) +{ + // FILETIME start 1601-01-01 00:00:00 , 100ns + // Unix epoch 1970-01-01 00:00:00 , 1sec + static const unsigned long long unix_epoch_offset = 116444736000000000LL; + + unsigned long long ll = ((unsigned long long)ft->dwHighDateTime << 32) + ft->dwLowDateTime; + return (time_t)((ll - 116444736000000000) / 10000000); +} + WORD TTLFileStat() { WORD Err; - TVarId SizeVarId, TimeVarId, DrvVarId; - TStrVal FName, TimeStr, DrvStr; - struct _stat st; - int ret; + TStrVal FName; int result = -1; - struct tm *tmp; Err = 0; GetStrVal(FName,&Err); @@ -1709,29 +1726,57 @@ goto end; } - ret = _stat(FName, &st); - if (ret != 0) { + HANDLE hFile = CreateFileW(wc::fromUtf8(FName), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) { goto end; } - if (CheckParameterGiven()) { + DWORD file_size_hi; + DWORD file_size_low; + file_size_low = GetFileSize(hFile, &file_size_hi); + if (file_size_low == INVALID_FILE_SIZE && GetLastError() != NO_ERROR) { + CloseHandle(hFile); + goto end; + } + + unsigned long long file_size = ((unsigned long long)file_size_hi << 32) + file_size_low; + FILETIME last_write_time; + if (GetFileTime(hFile, NULL, &last_write_time, NULL) == FALSE) { + CloseHandle(hFile); + goto end; + } + CloseHandle(hFile); + + if (CheckParameterGiven()) { + TVarId SizeVarId; GetIntVar(&SizeVarId,&Err); if (Err!=0) return Err; - SetIntVal(SizeVarId, st.st_size); + SetIntVal(SizeVarId, (int)file_size); } - if (CheckParameterGiven()) { + if (CheckParameterGiven()) { + TVarId TimeVarId; GetStrVar(&TimeVarId,&Err); if (Err!=0) return Err; - tmp = localtime(&st.st_mtime); + time_t st_mtime = FileTimeToUnixTime(&last_write_time); // \x8DŏI\x8FC\x90\xB3\x8E\x9E\x8D\x8F + struct tm* tmp = localtime(&st_mtime); + char TimeStr[128]; strftime(TimeStr, sizeof(TimeStr), "%Y-%m-%d %H:%M:%S", tmp); SetStrVal(TimeVarId, TimeStr); } - if (CheckParameterGiven()) { + if (CheckParameterGiven()) { + TVarId DrvVarId; GetStrVar(&DrvVarId,&Err); if (Err!=0) return Err; - _snprintf_s(DrvStr, sizeof(DrvStr), _TRUNCATE, "%c", st.st_dev + 'A'); + char DrvStr[2]; + char d = FName[0]; + DrvStr[0] = + (d >= 'a' && d <= 'z') ? d - 'a' + 'A' : + (d >= 'A' && d <= 'Z') ? d : + '?'; + DrvStr[1] = 0; SetStrVal(DrvVarId, DrvStr); } @@ -1844,14 +1889,14 @@ WORD TTLFileTruncate() { - WORD Err; + WORD Err = 0; TStrVal FName; int result = -1; int TruncByte; - int fh = -1; - int ret; + BOOL r; + HANDLE hFile; + DWORD pos_low; - Err = 0; GetStrVal(FName,&Err); if ((Err==0) && (strlen(FName)==0)) @@ -1862,7 +1907,7 @@ goto end; } - if (CheckParameterGiven()) { + if (CheckParameterGiven()) { GetIntVal(&TruncByte,&Err); if (Err!=0) return Err; } else { @@ -1869,26 +1914,32 @@ Err = ErrSyntax; goto end; } + Err = 0; - // \x83t\x83@\x83C\x83\x8B\x82\xF0\x8Ew\x92肵\x82\xBD\x83T\x83C\x83Y\x82Ő\xE8\x8Bl\x82߂\xE9\x81B - ret = _sopen_s( &fh, FName, _O_RDWR | _O_CREAT, _SH_DENYNO, _S_IREAD | _S_IWRITE ); - if (ret != 0) { + // \x83t\x83@\x83C\x83\x8B\x83I\x81[\x83v\x83\x93\x81A\x91\xB6\x8D݂\xB5\x82Ȃ\xA2\x8Fꍇ\x82͐V\x8BK\x8D쐬 + hFile = CreateFileW(wc::fromUtf8(FName), GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) { goto end; } - ret = _chsize_s(fh, TruncByte); - if (ret != 0) { - goto end; + + // \x83t\x83@\x83C\x83\x8B\x82\xF0\x8Ew\x92肵\x82\xBD\x83T\x83C\x83Y\x82ɂ\xB7\x82\xE9\x81A + // \x8Ag\x92\xA3\x82\xB5\x82\xBD\x8Fꍇ\x81A\x8Ag\x92\xA3\x95\x94\x95\xAA\x82̓\xE0\x97e\x82͖\xA2\x92\xE8\x8B` + pos_low = SetFilePointer(hFile, TruncByte, NULL, FILE_BEGIN ); + if (pos_low == INVALID_SET_FILE_POINTER) { + goto end_close; } + r = SetEndOfFile(hFile); + if (r == FALSE) { + goto end_close; + } result = 0; Err = 0; +end_close: + CloseHandle( hFile ); end: SetResult(result); - - if (fh != -1) - _close(fh); - return Err; } @@ -1946,10 +1997,10 @@ if (Err!=0) return Err; if ((DH>=0) && (DH<NumDirHandle) && - (DirHandle[DH]!=-1L)) + (DirHandle[DH]!= INVALID_HANDLE_VALUE)) { - _findclose(DirHandle[DH]); - DirHandle[DH] = -1L; + FindClose(DirHandle[DH]); + DirHandle[DH] = INVALID_HANDLE_VALUE; } return Err; } @@ -1960,7 +2011,7 @@ WORD Err; TStrVal Dir; int i; - struct _finddata_t data; + WIN32_FIND_DATAW data; Err = 0; GetIntVar(&DH,&Err); @@ -1974,13 +2025,13 @@ GetAbsPath(Dir,sizeof(Dir)); i = 0; while ((i<NumDirHandle) && - (DirHandle[i]!=-1L)) + (DirHandle[i]!= INVALID_HANDLE_VALUE)) i++; if (i<NumDirHandle) { - DirHandle[i] = _findfirst(Dir,&data); - if (DirHandle[i]!=-1L) - SetStrVal(Name,data.name); + DirHandle[i] = FindFirstFileW(wc::fromUtf8(Dir),&data); + if (DirHandle[i]!= INVALID_HANDLE_VALUE) + SetStrVal(Name,(u8)data.cFileName); else i = -1; } @@ -2003,7 +2054,7 @@ TVarId Name; WORD Err; int DH; - struct _finddata_t data; + WIN32_FIND_DATAW data; Err = 0; GetIntVal(&DH,&Err); @@ -2013,10 +2064,10 @@ if (Err!=0) return Err; if ((DH>=0) && (DH<NumDirHandle) && - (DirHandle[DH]!=-1L) && - (_findnext(DirHandle[DH],&data)==0)) + (DirHandle[DH]!= INVALID_HANDLE_VALUE) && + (FindNextFileW(DirHandle[DH],&data) != FALSE)) { - SetStrVal(Name,data.name); + SetStrVal(Name,(u8)data.cFileName); SetResult(1); } else { @@ -2054,7 +2105,7 @@ return Err; } - if (CreateDirectory(FName, NULL) == 0) { + if (CreateDirectoryW(wc::fromUtf8(FName), NULL) == 0) { SetResult(2); } else { @@ -2083,7 +2134,7 @@ return Err; } - if (RemoveDirectory(FName) == 0) { + if (RemoveDirectoryW(wc::fromUtf8(FName)) == 0) { SetResult(2); } else { @@ -2105,7 +2156,8 @@ if (Err!=0) return Err; GetAbsPath(FName,sizeof(FName)); - if (DoesFolderExist(FName)) { + DWORD attr = GetFileAttributesW(wc::fromUtf8(FName)); + if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { SetResult(1); } else { @@ -2204,7 +2256,7 @@ if (Err!=0) return Err; GetAbsPath(Filename, sizeof(Filename)); - SetResult(GetFileAttributes(Filename)); + SetResult(GetFileAttributesW(wc::fromUtf8(Filename))); return Err; } @@ -3913,7 +3965,7 @@ Err = ErrSyntax; if (Err!=0) return Err; - if (SetFileAttributes(Filename, attributes) == 0) { + if (SetFileAttributesW(wc::fromUtf8(Filename), attributes) == 0) { SetResult(0); } else { Modified: branches/unicode_macro_2/teraterm/ttpmacro/ttmlib.c =================================================================== --- branches/unicode_macro_2/teraterm/ttpmacro/ttmlib.c 2020-04-01 14:31:14 UTC (rev 8668) +++ branches/unicode_macro_2/teraterm/ttpmacro/ttmlib.c 2020-04-01 14:31:24 UTC (rev 8669) @@ -37,6 +37,7 @@ #include "compat_win.h" #include "ttmlib.h" +#include "codeconv.h" static char CurrentDir[MAXPATHLEN]; @@ -178,15 +179,23 @@ strncpy_s(Dir, destlen, CurrentDir, _TRUNCATE); } -void TTMSetDir(PCHAR Dir) +void TTMSetDir(const char *Dir) { - char Temp[MAXPATHLEN]; - - _getcwd(Temp,sizeof(Temp)); - _chdir(CurrentDir); - _chdir(Dir); - _getcwd(CurrentDir,sizeof(CurrentDir)); - _chdir(Temp); + wchar_t Temp[MAX_PATH]; + wchar_t CurrentDirW[MAX_PATH]; + wchar_t *pCurrentDirW = ToWcharU8(CurrentDir); + wchar_t *DirW = ToWcharU8(Dir); + char *pCurrentDirU8; + GetCurrentDirectoryW(_countof(Temp), Temp); + SetCurrentDirectoryW(pCurrentDirW); + SetCurrentDirectoryW(DirW); + GetCurrentDirectoryW(_countof(CurrentDirW), CurrentDirW); + pCurrentDirU8 = ToU8W(CurrentDirW); + strncpy_s(CurrentDir, _countof(CurrentDir), pCurrentDirU8, _TRUNCATE); + SetCurrentDirectoryW(Temp); + free(pCurrentDirW); + free(DirW); + free(pCurrentDirU8); } BOOL GetAbsPath(PCHAR FName, int destlen) Modified: branches/unicode_macro_2/teraterm/ttpmacro/ttmlib.h =================================================================== --- branches/unicode_macro_2/teraterm/ttpmacro/ttmlib.h 2020-04-01 14:31:14 UTC (rev 8668) +++ branches/unicode_macro_2/teraterm/ttpmacro/ttmlib.h 2020-04-01 14:31:24 UTC (rev 8669) @@ -42,7 +42,7 @@ void CalcTextExtent(HWND hWnd, HFONT Font, const char *Text, LPSIZE s); void CalcTextExtentW(HWND hWnd, HFONT Font, const wchar_t *Text, LPSIZE s); void TTMGetDir(PCHAR Dir, int destlen); -void TTMSetDir(PCHAR Dir); +void TTMSetDir(const char *Dir); int GetAbsPath(PCHAR FName, int destlen); int GetSpecialFolder(PCHAR dest, int dest_len, PCHAR type); void BringupWindow(HWND hWnd);