Browse Source

perform correct case resolution in sys_full_path

Nicolas Cannasse 8 years ago
parent
commit
6eef53e430
1 changed files with 45 additions and 3 deletions
  1. 45 3
      src/std/sys.c

+ 45 - 3
src/std/sys.c

@@ -415,10 +415,52 @@ HL_PRIM varray *hl_sys_read_dir( vbyte *_path ) {
 
 HL_PRIM vbyte *hl_sys_full_path( vbyte *path ) {
 #ifdef HL_WIN
-	pchar buf[MAX_PATH+1];
-	if( GetFullPathNameW((pchar*)path,MAX_PATH+1,buf,NULL) == 0 )
+	pchar out[MAX_PATH+1];
+	int len, i, last;
+	HANDLE handle;
+	WIN32_FIND_DATA data;
+	const char sep = '\\';
+	if( GetFullPathNameW((pchar*)path,MAX_PATH+1,out,NULL) == 0 )
 		return NULL;
-	return (vbyte*)pstrdup(buf,-1);
+	len = ustrlen(out);
+	i = 0;
+
+	if (len >= 2 && out[1] == ':') {
+		// convert drive letter to uppercase
+		if (out[0] >= 'a' && out[0] <= 'z')
+			out[0] += (pchar)('A' - 'a');
+		if (len >= 3 && out[2] == sep)
+			i = 3;
+		else
+			i = 2;
+	}
+
+	last = i;
+
+	while (i < len) {
+		// skip until separator
+		while (i < len && out[i] != sep)
+			i++;
+
+		// temporarily strip string to last found component
+		out[i] = 0;
+
+		// get actual file/dir name with proper case
+		if ((handle = FindFirstFileW(out, &data)) != INVALID_HANDLE_VALUE) {
+			// replace the component with proper case
+			memcpy(out + last, data.cFileName, i - last);
+			FindClose(handle);
+		}
+
+		// if we're not at the end, restore the path
+		if (i < len)
+			out[i] = sep;
+
+		// advance
+		i++;
+		last = i;
+	}
+	return (vbyte*)pstrdup(out,len);
 #else
 	pchar buf[PATH_MAX];
 	if( realpath((pchar*)path,buf) == NULL )