The gethostname function has a problem where a small buffer size will not produce an accurate errno. This is because the Windows error is not being appropriately mapped. This causes programs such as hostname from coreutils to fail because they are not informed about the long name.
Changelog entry: 2015-03-31 Renato Silva <[email protected]> * net.cc: Fix buffer size error handling in cygwin_gethostname. ----- /* Test case */ #include <errno.h> #include <stdio.h> #include <windows.h> int main(int argc, char **argv) { if (argc < 2) { printf("Please provide a buffer length.\n"); return 1; } DWORD HOSTNAME_LENGTH = atoi(argv[1]); char hostname[HOSTNAME_LENGTH]; char error_message[256]; int return_value; printf("gethostname %s\n", gethostname(hostname, HOSTNAME_LENGTH)? "failed" : "succeeded"); if (errno) printf("error is %d, %s\n\n", errno, strerror(errno)); else printf("hostname is %s\n\n", hostname); printf("GetComputerNameEx %s\n", (return_value = GetComputerNameEx(ComputerNameDnsFullyQualified, hostname, &HOSTNAME_LENGTH))? "succeeded": "failed"); FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), error_message, 256, NULL); if (!return_value) printf("error is %d, %s\n", GetLastError(), error_message); else printf("hostname is %s\n", hostname); } ----- >From d691d4b2ac75f00a752c5dc86ab63a4ba425beda Mon Sep 17 00:00:00 2001 From: Renato Silva <[email protected]> Date: Mon, 30 Mar 2015 20:20:49 -0300 Subject: [PATCH] Fix buffer size error handling in gethostname. GetComputerNameEx sets a generic ERROR_MORE_DATA when buffer is too small. This is now more accurately mapped into ENAMETOOLONG instead of the generic EPERM. --- winsup/cygwin/net.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc index f9b317c..02fa142 100644 --- a/winsup/cygwin/net.cc +++ b/winsup/cygwin/net.cc @@ -1076,7 +1076,10 @@ cygwin_gethostname (char *name, size_t len) if (!GetComputerNameExA (ComputerNameDnsFullyQualified, name, &local_len)) { - set_winsock_errno (); + if (GetLastError () == ERROR_MORE_DATA) + set_errno (ENAMETOOLONG); + else + set_winsock_errno (); __leave; } } -- 2.3.4
