[Box Backup-commit] COMMIT r957 - box/chris/merge/lib/win32

subversion at fluffy.co.uk subversion at fluffy.co.uk
Mon Sep 4 00:55:55 BST 2006


Author: chris
Date: 2006-09-04 00:55:55 +0100 (Mon, 04 Sep 2006)
New Revision: 957

Modified:
   box/chris/merge/lib/win32/emu.cpp
Log:
(refs #3)

Added emulated utimes, chmod, readv and writev

Added useful utility functions ConvertFileTimeToTime_t and 
ConvertTime_tToFileTime


Modified: box/chris/merge/lib/win32/emu.cpp
===================================================================
--- box/chris/merge/lib/win32/emu.cpp	2006-09-03 23:53:13 UTC (rev 956)
+++ box/chris/merge/lib/win32/emu.cpp	2006-09-03 23:55:55 UTC (rev 957)
@@ -826,6 +826,115 @@
 // --------------------------------------------------------------------------
 //
 // 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 @@
 	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




More information about the Boxbackup-commit mailing list