threads / patch / 15688

patch, 4 partsmingw: move common functionality to win32.h

Subject: [PATCH 3/4] mingw: move common functionality to win32.h

## tl;dr

5 messages between Sep 27, 2008 and Sep 29, 2008. Diffs are folded; open one to read it.

replies: 4people: 2as markdown or json

Dmitry Potapov· Sep 27, 2008, 08:43 UTC · lore

Some small Win32 specific functions will be shared by MinGW and Cygwin compatibility layer. Place them into a separate header.

Signed-off-by: Dmitry Potapov <dpotapov@gmail.com>
---
 compat/mingw.c |   42 ++++--------------------------------------
 compat/win32.h |   34 ++++++++++++++++++++++++++++++++++
 2 files changed, 38 insertions(+), 38 deletions(-)
 create mode 100644 compat/win32.h
Show changes to 2 files +38 −38

compat/mingw.c, compat/win32.h

diff --git a/compat/mingw.c b/compat/mingw.c
index a2b8cd7..ac77283 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -1,4 +1,5 @@
 #include "../git-compat-util.h"
+#include "win32.h"
 #include "../strbuf.h"
 
 unsigned int _CRT_fmode = _O_BINARY;
@@ -39,46 +40,19 @@ static int do_lstat(const char *file_name, struct stat *buf)
 {
 	WIN32_FILE_ATTRIBUTE_DATA fdata;
 
-	if (GetFileAttributesExA(file_name, GetFileExInfoStandard, &fdata)) {
-		int fMode = S_IREAD;
-		if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
-			fMode |= S_IFDIR;
-		else
-			fMode |= S_IFREG;
-		if (!(fdata.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
-			fMode |= S_IWRITE;
-
+	if (!(errno = get_file_attr(file_name, &fdata))) {
 		buf->st_ino = 0;
 		buf->st_gid = 0;
 		buf->st_uid = 0;
 		buf->st_nlink = 1;
-		buf->st_mode = fMode;
+		buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes);
 		buf->st_size = fdata.nFileSizeLow; /* Can't use nFileSizeHigh, since it's not a stat64 */
 		buf->st_dev = buf->st_rdev = 0; /* not used by Git */
 		buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime));
 		buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));
 		buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));
-		errno = 0;
 		return 0;
 	}
-
-	switch (GetLastError()) {
-	case ERROR_ACCESS_DENIED:
-	case ERROR_SHARING_VIOLATION:
-	case ERROR_LOCK_VIOLATION:
-	case ERROR_SHARING_BUFFER_EXCEEDED:
-		errno = EACCES;
-		break;
-	case ERROR_BUFFER_OVERFLOW:
-		errno = ENAMETOOLONG;
-		break;
-	case ERROR_NOT_ENOUGH_MEMORY:
-		errno = ENOMEM;
-		break;
-	default:
-		errno = ENOENT;
-		break;
-	}
 	return -1;
 }
 
@@ -130,19 +104,11 @@ int mingw_fstat(int fd, struct stat *buf)
 		return fstat(fd, buf);
 
 	if (GetFileInformationByHandle(fh, &fdata)) {
-		int fMode = S_IREAD;
-		if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
-			fMode |= S_IFDIR;
-		else
-			fMode |= S_IFREG;
-		if (!(fdata.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
-			fMode |= S_IWRITE;
-
 		buf->st_ino = 0;
 		buf->st_gid = 0;
 		buf->st_uid = 0;
 		buf->st_nlink = 1;
-		buf->st_mode = fMode;
+		buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes);
 		buf->st_size = fdata.nFileSizeLow; /* Can't use nFileSizeHigh, since it's not a stat64 */
 		buf->st_dev = buf->st_rdev = 0; /* not used by Git */
 		buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime));
diff --git a/compat/win32.h b/compat/win32.h
new file mode 100644
index 0000000..c26384e
--- /dev/null
+++ b/compat/win32.h
@@ -0,0 +1,34 @@
+/* common Win32 functions for MinGW and Cygwin */
+#include <windows.h>
+
+static inline int file_attr_to_st_mode (DWORD attr)
+{
+	int fMode = S_IREAD;
+	if (attr & FILE_ATTRIBUTE_DIRECTORY)
+		fMode |= S_IFDIR;
+	else
+		fMode |= S_IFREG;
+	if (!(attr & FILE_ATTRIBUTE_READONLY))
+		fMode |= S_IWRITE;
+	return fMode;
+}
+
+static inline int get_file_attr(const char *fname, WIN32_FILE_ATTRIBUTE_DATA *fdata)
+{
+	if (GetFileAttributesExA(fname, GetFileExInfoStandard, fdata))
+		return 0;
+
+	switch (GetLastError()) {
+	case ERROR_ACCESS_DENIED:
+	case ERROR_SHARING_VIOLATION:
+	case ERROR_LOCK_VIOLATION:
+	case ERROR_SHARING_BUFFER_EXCEEDED:
+		return EACCES;
+	case ERROR_BUFFER_OVERFLOW:
+		return ENAMETOOLONG;
+	case ERROR_NOT_ENOUGH_MEMORY:
+		return ENOMEM;
+	default:
+		return ENOENT;
+	}
+}
-- 
1.6.0.2.237.g0297e5
Johannes Sixt· Sep 27, 2008, 18:34 UTC · re: Dmitry Potapov · lore

Re: [PATCH 3/4] mingw: move common functionality to win32.h

On Samstag, 27. September 2008, Dmitry Potapov wrote:
Show 19 quoted lines
> +static inline int get_file_attr(const char *fname,
> WIN32_FILE_ATTRIBUTE_DATA *fdata) +{
> +	if (GetFileAttributesExA(fname, GetFileExInfoStandard, fdata))
> +		return 0;
> +
> +	switch (GetLastError()) {
> +	case ERROR_ACCESS_DENIED:
> +	case ERROR_SHARING_VIOLATION:
> +	case ERROR_LOCK_VIOLATION:
> +	case ERROR_SHARING_BUFFER_EXCEEDED:
> +		return EACCES;
> +	case ERROR_BUFFER_OVERFLOW:
> +		return ENAMETOOLONG;
> +	case ERROR_NOT_ENOUGH_MEMORY:
> +		return ENOMEM;
> +	default:
> +		return ENOENT;
> +	}
> +}

I've long wished for a function that translates Win32 error codes to errno codes. It would be useful in a number of other places, too.

Here you introduce a new function get_file_attr() that is nothing but GetFileAttributesExA() followed by such an error code translation.

I suggest that we leave the original call to GetFileAttributesExA() alone and have a function win32_to_errno(void) that is just the switch statement above.

-- Hannes
Dmitry Potapov· Sep 27, 2008, 21:51 UTC · re: Johannes Sixt · lore

Re: [PATCH 3/4] mingw: move common functionality to win32.h

On Sat, Sep 27, 2008 at 08:34:04PM +0200, Johannes Sixt wrote:
Show 29 quoted lines
> On Samstag, 27. September 2008, Dmitry Potapov wrote:
> > +static inline int get_file_attr(const char *fname,
> > WIN32_FILE_ATTRIBUTE_DATA *fdata) +{
> > +	if (GetFileAttributesExA(fname, GetFileExInfoStandard, fdata))
> > +		return 0;
> > +
> > +	switch (GetLastError()) {
> > +	case ERROR_ACCESS_DENIED:
> > +	case ERROR_SHARING_VIOLATION:
> > +	case ERROR_LOCK_VIOLATION:
> > +	case ERROR_SHARING_BUFFER_EXCEEDED:
> > +		return EACCES;
> > +	case ERROR_BUFFER_OVERFLOW:
> > +		return ENAMETOOLONG;
> > +	case ERROR_NOT_ENOUGH_MEMORY:
> > +		return ENOMEM;
> > +	default:
> > +		return ENOENT;
> > +	}
> > +}
> 
> I've long wished for a function that translates Win32 error codes to errno 
> codes. It would be useful in a number of other places, too.
> 
> Here you introduce a new function get_file_attr() that is nothing but 
> GetFileAttributesExA() followed by such an error code translation.
> 
> I suggest that we leave the original call to GetFileAttributesExA() alone and 
> have a function win32_to_errno(void) that is just the switch statement above.

win32_to_errno was the first thing that implemented but then released that translation of Win32 errors to errno cannot be in general case. For instance, ERROR_BUFFER_OVERFLOW means ENAMETOOLONG here, but it can be translated to ETOOSMALL in other cases. How do you propose to deal with that?

So I have not found a better solution than to add get_file_attr(), which calls GetFileAttributesExA() and translates Win32 error.

Dmitry
Johannes Sixt· Sep 28, 2008, 09:10 UTC · re: Dmitry Potapov · lore

Re: [PATCH 3/4] mingw: move common functionality to win32.h

On Samstag, 27. September 2008, Dmitry Potapov wrote:
Show 5 quoted lines
> win32_to_errno was the first thing that implemented but then released
> that translation of Win32 errors to errno cannot be in general case.
> For instance, ERROR_BUFFER_OVERFLOW means ENAMETOOLONG here, but it
> can be translated to ETOOSMALL in other cases. How do you propose to
> deal with that?

We deal with that when the need arises, in an evolutionary manner. The first step is to *have* an error code translation routine.

-- Hannes
Dmitry Potapov· Sep 29, 2008, 18:37 UTC · re: Johannes Sixt · lore

Re: [PATCH 3/4] mingw: move common functionality to win32.h

On Sun, Sep 28, 2008 at 11:10:48AM +0200, Johannes Sixt wrote:
Show 9 quoted lines
> On Samstag, 27. September 2008, Dmitry Potapov wrote:
> > win32_to_errno was the first thing that implemented but then released
> > that translation of Win32 errors to errno cannot be in general case.
> > For instance, ERROR_BUFFER_OVERFLOW means ENAMETOOLONG here, but it
> > can be translated to ETOOSMALL in other cases. How do you propose to
> > deal with that?
> 
> We deal with that when the need arises, in an evolutionary manner. The first 
> step is to *have* an error code translation routine.

Step to what? IMHO, the idea of win32_to_errno is deeply flawed, and, in any case, refactoring handling of Win32 error in MinGW is not the purpose of my series. If you want to introduce win32_to_errno in mingw, you can send your own patch to that effect, and we can discuss that separately. So far, I am not convinced that it will improve anything in the existing code. As to avoiding duplication of Win32 specific code, get_file_attr() fits better. So, let's proceed step-wise, and first finish one thing, namely, speed-up of Cygwin version of Git and then discuss adding win32_to_errno to MinGW.

Dmitry

← back to recent threads