diff options
author | Chris Wilson <chris+github@qwirx.com> | 2006-09-03 23:55:55 +0000 |
---|---|---|
committer | Chris Wilson <chris+github@qwirx.com> | 2006-09-03 23:55:55 +0000 |
commit | 83bf070fb425f75bdb85b58dc810791736369814 (patch) | |
tree | fcf7b5e9fa9b79693f458b6085a348faeeb4e822 | |
parent | 3a073296c1630000907ba6385da0e93006adc891 (diff) |
(refs #3)
Added emulated utimes, chmod, readv and writev
Added useful utility functions ConvertFileTimeToTime_t and
ConvertTime_tToFileTime
-rw-r--r-- | lib/win32/emu.cpp | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index e54b2d72..d681335a 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -826,6 +826,115 @@ int statfs(const char * pName, struct statfs * s) // -------------------------------------------------------------------------- // // Function +// Name: emu_utimes +// Purpose: replacement for the POSIX utimes() function, +// works with unicode filenames supplied in utf8 format, +// sets creation time instead of last access time. +// Created: 25th July 2006 +// +// -------------------------------------------------------------------------- +int emu_utimes(const char * pName, const struct timeval times[]) +{ + FILETIME creationTime; + if (!ConvertTime_tToFileTime(times[0].tv_sec, &creationTime)) + { + errno = EINVAL; + return -1; + } + + FILETIME modificationTime; + if (!ConvertTime_tToFileTime(times[1].tv_sec, &modificationTime)) + { + errno = EINVAL; + return -1; + } + + HANDLE handle = OpenFileByNameUtf8(pName, FILE_WRITE_ATTRIBUTES); + + if (handle == NULL) + { + // errno already set and error logged by OpenFileByNameUtf8() + return -1; + } + + if (!SetFileTime(handle, &creationTime, NULL, &modificationTime)) + { + ::syslog(LOG_ERR, "Failed to set times on '%s': error %d", + pName, GetLastError()); + CloseHandle(handle); + return 1; + } + + CloseHandle(handle); + return 0; +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: emu_chmod +// Purpose: replacement for the POSIX chmod function, +// works with unicode filenames supplied in utf8 format +// Created: 26th July 2006 +// +// -------------------------------------------------------------------------- +int emu_chmod(const char * pName, mode_t mode) +{ + std::string AbsPathWithUnicode = + ConvertPathToAbsoluteUnicode(pName); + + if (AbsPathWithUnicode.size() == 0) + { + // error already logged by ConvertPathToAbsoluteUnicode() + return -1; + } + + WCHAR* pBuffer = ConvertUtf8ToWideString(AbsPathWithUnicode.c_str()); + // We are responsible for freeing pBuffer + + if (pBuffer == NULL) + { + // error already logged by ConvertUtf8ToWideString() + free(pBuffer); + return -1; + } + + DWORD attribs = GetFileAttributesW(pBuffer); + if (attribs == INVALID_FILE_ATTRIBUTES) + { + ::syslog(LOG_ERR, "Failed to get file attributes of '%s': " + "error %d", pName, GetLastError()); + errno = EACCES; + free(pBuffer); + return -1; + } + + if (mode & S_IWRITE) + { + attribs &= ~FILE_ATTRIBUTE_READONLY; + } + else + { + attribs |= FILE_ATTRIBUTE_READONLY; + } + + if (!SetFileAttributesW(pBuffer, attribs)) + { + ::syslog(LOG_ERR, "Failed to set file attributes of '%s': " + "error %d", pName, GetLastError()); + errno = EACCES; + free(pBuffer); + return -1; + } + + free(pBuffer); + return 0; +} + + +// -------------------------------------------------------------------------- +// +// Function // Name: opendir // Purpose: replacement for unix function, uses win32 findfirst routines // Created: 25th October 2004 @@ -1263,4 +1372,96 @@ int console_read(char* pBuffer, size_t BufferSize) return strlen(pBuffer); } +int readv (int filedes, const struct iovec *vector, size_t count) +{ + int bytes = 0; + + for (size_t i = 0; i < count; i++) + { + int result = read(filedes, vector[i].iov_base, + vector[i].iov_len); + if (result < 0) + { + return result; + } + bytes += result; + } + + return bytes; +} + +int writev(int filedes, const struct iovec *vector, size_t count) +{ + int bytes = 0; + + for (size_t i = 0; i < count; i++) + { + int result = write(filedes, vector[i].iov_base, + vector[i].iov_len); + if (result < 0) + { + return result; + } + bytes += result; + } + + return bytes; +} + +// need this for conversions +time_t ConvertFileTimeToTime_t(FILETIME *fileTime) +{ + SYSTEMTIME stUTC; + struct tm timeinfo; + + // Convert the last-write time to local time. + FileTimeToSystemTime(fileTime, &stUTC); + + memset(&timeinfo, 0, sizeof(timeinfo)); + timeinfo.tm_sec = stUTC.wSecond; + timeinfo.tm_min = stUTC.wMinute; + timeinfo.tm_hour = stUTC.wHour; + timeinfo.tm_mday = stUTC.wDay; + timeinfo.tm_wday = stUTC.wDayOfWeek; + timeinfo.tm_mon = stUTC.wMonth - 1; + // timeinfo.tm_yday = ...; + timeinfo.tm_year = stUTC.wYear - 1900; + + time_t retVal = mktime(&timeinfo) - _timezone; + return retVal; +} + +bool ConvertTime_tToFileTime(const time_t from, FILETIME *pTo) +{ + time_t adjusted = from + _timezone; + struct tm *time_breakdown = gmtime(&adjusted); + if (time_breakdown == NULL) + { + ::syslog(LOG_ERR, "Error: failed to convert time format: " + "%d is not a valid time\n", from); + return false; + } + + SYSTEMTIME stUTC; + stUTC.wSecond = time_breakdown->tm_sec; + stUTC.wMinute = time_breakdown->tm_min; + stUTC.wHour = time_breakdown->tm_hour; + stUTC.wDay = time_breakdown->tm_mday; + stUTC.wDayOfWeek = time_breakdown->tm_wday; + stUTC.wMonth = time_breakdown->tm_mon + 1; + stUTC.wYear = time_breakdown->tm_year + 1900; + stUTC.wMilliseconds = 0; + + // Convert the last-write time to local time. + if (!SystemTimeToFileTime(&stUTC, pTo)) + { + syslog(LOG_ERR, "Failed to convert between time formats: " + "error %d", GetLastError()); + return false; + } + + return true; +} + + #endif // WIN32 |