[evolution-patches] camel-file-utils.c win32 diff



Here's the diff to camel-file-utils.c. The ChangeLog entry first:

2005-12-01  Tor Lillqvist  <tml novell com>

	* camel-file-utils.c: Win32 port: Include <winsock2.h>. Use
	g_htonl() and g_ntohl().
	(camel_mkdir): Implement using g_mkdir_with_parents() when
	compiling against GLib 2.8 or later.
	(camel_file_util_safe_filename): Need to encode more unsafe chars
	on Win32.
	(camel_read, camel_write): Not cancellable on Win32. But then
	these functions should be used only with regular files, not
	sockets.
	(camel_read_socket, camel_write_socket): New functions, to be used
	for sockets. On Unix just call camel_read() and camel_write(). On
	Win32 use recv() and write(). read() and write() can not be used
	on sockets in Windows. They are in the C library, which know
	nothing about sockets, which are in the winsock API.
	(camel_file_util_savename): Clarify doc comment. Use
	g_path_get_dirname() instead of looking for '/'. Use
	g_path_get_basename(), and g_build_filename() to construct the
	savename.

--tml

Index: camel/camel-file-utils.c
===================================================================
RCS file: /cvs/gnome/evolution-data-server/camel/camel-file-utils.c,v
retrieving revision 1.14
diff -u -2 -r1.14 camel-file-utils.c
--- camel/camel-file-utils.c	31 Aug 2005 04:21:56 -0000	1.14
+++ camel/camel-file-utils.c	1 Dec 2005 12:38:28 -0000
@@ -31,17 +31,21 @@
 #include <sys/stat.h>
 #include <sys/types.h>
-#include <netinet/in.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <errno.h>
 
+#include <glib.h>
+
+#ifdef G_OS_WIN32
+#include <winsock2.h>
+#define EWOULDBLOCK EAGAIN
+#endif
+
+#include "libedataserver/e-util.h"
+
 #include "camel-file-utils.h"
 #include "camel-operation.h"
 #include "camel-url.h"
 
-#ifndef MAX
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-#endif
-
 #define IO_TIMEOUT (60*4)
 
@@ -117,5 +121,5 @@
 	guint32 save;
 
-	save = htonl (value);
+	save = g_htonl (value);
 	if (fwrite (&save, sizeof (save), 1, out) != 1)
 		return -1;
@@ -139,5 +143,5 @@
 
 	if (fread (&save, sizeof (save), 1, in) == 1) {
-		*dest = ntohl (save);
+		*dest = g_ntohl (save);
 		return 0;
 	} else {
@@ -328,4 +332,8 @@
 camel_mkdir (const char *path, mode_t mode)
 {
+#if GLIB_CHECK_VERSION(2,8,0)
+	g_assert(path && g_path_is_absolute (path));
+	return g_mkdir_with_parents (path, mode);
+#else
 	char *copy, *p;
 	
@@ -347,7 +355,7 @@
 	
 	return 0;
+#endif
 }
 
-
 /**
  * camel_file_util_safe_filename:
@@ -362,8 +370,14 @@
 camel_file_util_safe_filename (const char *name)
 {
+#ifdef G_OS_WIN32
+	const char *unsafe_chars = "/?()'*<>:\"\\|";
+#else
+	const char *unsafe_chars = "/?()'*";
+#endif
+
 	if (name == NULL)
 		return NULL;
 	
-	return camel_url_encode(name, "/?()'*");
+	return camel_url_encode(name, unsafe_chars);
 }
 
@@ -392,6 +406,9 @@
 		return -1;
 	}
-	
+#ifndef G_OS_WIN32
 	cancel_fd = camel_operation_cancel_fd (NULL);
+#else
+	cancel_fd = -1;
+#endif
 	if (cancel_fd == -1) {
 		do {
@@ -399,4 +416,5 @@
 		} while (nread == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
 	} else {
+#ifndef G_OS_WIN32
 		int errnosav, flags, fdmax;
 		fd_set rdset;
@@ -435,4 +453,5 @@
 		fcntl (fd, F_SETFL, flags);
 		errno = errnosav;
+#endif
 	}
 	
@@ -462,6 +481,9 @@
 		return -1;
 	}
-	
+#ifndef G_OS_WIN32
 	cancel_fd = camel_operation_cancel_fd (NULL);
+#else
+	cancel_fd = -1;
+#endif
 	if (cancel_fd == -1) {
 		do {
@@ -469,9 +491,9 @@
 				w = write (fd, buf + written, n - written);
 			} while (w == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
-			
 			if (w > 0)
 				written += w;
 		} while (w != -1 && written < n);
 	} else {
+#ifndef G_OS_WIN32
 		int errnosav, flags, fdmax;
 		fd_set rdset, wrset;
@@ -517,4 +539,157 @@
 		fcntl (fd, F_SETFL, flags);
 		errno = errnosav;
+#endif
+	}
+	
+	if (w == -1)
+		return -1;
+	
+	return written;
+}
+
+/**
+ * camel_read_socket:
+ * @fd: a socket
+ * @buf: buffer to fill
+ * @n: number of bytes to read into @buf
+ *
+ * Cancellable read() replacement for sockets. Code that intends to be
+ * portable to Win32 should call camel_read_socket() only on sockets
+ * returned from socket(), or accept().
+ *
+ * Returns number of bytes read or -1 on fail. On failure, errno will
+ * be set appropriately. If the socket is nonblocking
+ * camel_read_socket() will retry the read until it gets something.
+ **/
+ssize_t
+camel_read_socket (int fd, char *buf, size_t n)
+{
+#ifndef G_OS_WIN32
+	return camel_read (fd, buf, n);
+#else
+	ssize_t nread;
+	int cancel_fd;
+	
+	if (camel_operation_cancel_check (NULL)) {
+		errno = EINTR;
+		return -1;
+	}
+	cancel_fd = camel_operation_cancel_fd (NULL);
+
+	if (cancel_fd == -1) {
+		do {
+			nread = recv (fd, buf, n, 0);
+		} while (nread == SOCKET_ERROR && WSAGetLastError () == WSAEWOULDBLOCK);
+	} else {
+		int fdmax;
+		fd_set rdset;
+		u_long yes = 1;
+
+		ioctlsocket (fd, FIONBIO, &yes);
+		fdmax = MAX (fd, cancel_fd) + 1;
+		do {
+			struct timeval tv;
+			int res;
+
+			FD_ZERO (&rdset);
+			FD_SET (fd, &rdset);
+			FD_SET (cancel_fd, &rdset);
+			tv.tv_sec = IO_TIMEOUT;
+			tv.tv_usec = 0;
+			nread = -1;
+
+			res = select(fdmax, &rdset, 0, 0, &tv);
+			if (res == -1)
+				;
+			else if (res == 0)
+				errno = ETIMEDOUT;
+			else if (FD_ISSET (cancel_fd, &rdset)) {
+				errno = EINTR;
+				goto failed;
+			} else {				
+				nread = recv (fd, buf, n, 0);
+			}
+		} while (nread == -1 && WSAGetLastError () == WSAEWOULDBLOCK);
+	failed:
+		;
+	}
+	
+	return nread;
+#endif
+}
+
+/**
+ * camel_write_socket:
+ * @fd: file descriptor
+ * @buf: buffer to write
+ * @n: number of bytes of @buf to write
+ *
+ * Cancellable write() replacement for sockets. Code that intends to
+ * be portable to Win32 should call camel_write() only on sockets
+ * returned from socket() or accept().
+ *
+ * Returns number of bytes written or -1 on fail. On failure, errno will
+ * be set appropriately.
+ **/
+ssize_t
+camel_write_socket (int fd, const char *buf, size_t n)
+{
+#ifndef G_OS_WIN32
+	return camel_write (fd, buf, n);
+#else
+	ssize_t w, written = 0;
+	int cancel_fd;
+	
+	if (camel_operation_cancel_check (NULL)) {
+		errno = EINTR;
+		return -1;
+	}
+
+	cancel_fd = camel_operation_cancel_fd (NULL);
+	if (cancel_fd == -1) {
+		do {
+			do {
+				w = send (fd, buf + written, n - written, 0);
+			} while (w == SOCKET_ERROR && WSAGetLastError () == WSAEWOULDBLOCK);
+			if (w > 0)
+				written += w;
+		} while (w != -1 && written < n);
+	} else {
+		int fdmax;
+		fd_set rdset, wrset;
+		u_long arg = 1;
+
+		ioctlsocket (fd, FIONBIO, &arg);
+		fdmax = MAX (fd, cancel_fd) + 1;
+		do {
+			struct timeval tv;
+			int res;
+
+			FD_ZERO (&rdset);
+			FD_ZERO (&wrset);
+			FD_SET (fd, &wrset);
+			FD_SET (cancel_fd, &rdset);
+			tv.tv_sec = IO_TIMEOUT;
+			tv.tv_usec = 0;			
+			w = -1;
+
+			res = select (fdmax, &rdset, &wrset, 0, &tv);
+			if (res == SOCKET_ERROR) {
+				/* w still being -1 will catch this */
+			} else if (res == 0)
+				errno = ETIMEDOUT;
+			else if (FD_ISSET (cancel_fd, &rdset))
+				errno = EINTR;
+			else {
+				w = send (fd, buf + written, n - written, 0);
+				if (w == SOCKET_ERROR) {
+					if (WSAGetLastError () == WSAEWOULDBLOCK)
+						w = 0;
+				} else
+					written += w;
+			}
+		} while (w != -1 && written < n);
+		arg = 0;
+		ioctlsocket (fd, FIONBIO, &arg);
 	}
 	
@@ -523,33 +698,38 @@
 	
 	return written;
+#endif
 }
 
+
 /**
  * camel_file_util_savename:
- * @filename: 
+ * @filename: a pathname
  * 
- * Builds a filename of the form ".#" + @filename, used to create
- * a two-stage commit file write.
+ * Builds a pathname where the basename is of the form ".#" + the
+ * basename of @filename, for instance used in a two-stage commit file
+ * write.
  * 
- * Return value: ".#" + filename.  It must be free'd with g_free().
+ * Return value: The new pathname.  It must be free'd with g_free().
  **/
 char *
 camel_file_util_savename(const char *filename)
 {
-	char *name, *slash;
-	int off;
+	char *dirname, *retval;
+
+	dirname = g_path_get_dirname(filename);
 
-	name = g_malloc(strlen(filename)+3);
-	slash = strrchr(filename, '/');
-	if (slash) {
-		off = slash-filename;
-
-		memcpy(name, filename, off+1);
-		memcpy(name + off+1, ".#", 2);
-		strcpy(name + off+3, filename+off+1);
+	if (strcmp (dirname, ".") == 0) {
+		retval = g_strconcat (".#", filename, NULL);
 	} else {
-		sprintf(name, ".#%s", filename);
+		char *basename = g_path_get_basename(filename);
+		char *newbasename = g_strconcat (".#", basename, NULL);
+
+		retval = g_build_filename (dirname, newbasename, NULL);
+
+		g_free (newbasename);
+		g_free (basename);
 	}
+	g_free (dirname);
 
-	return name;
+	return retval;
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]