Browse code

win32: use unc paths

aCaB authored on 2009/10/21 11:31:11
Showing 6 changed files
... ...
@@ -319,7 +319,7 @@ int cfg_tcpsock(const struct optstruct *opts, struct sockaddr_in *tcpsock, in_ad
319 319
 int cli_is_abspath(const char *path) {
320 320
 #ifdef _WIN32
321 321
     int len = strlen(path);
322
-    return (len > 2 && path[0] == '\\' && path[1] == '\\') || (len > 3 && path[1] == ':' && path[2] == '\\');
322
+    return (len > 2 && path[0] == '\\' && path[1] == '\\') || (len >= 2 && ((*path >= 'a' && *path <= 'z') || (*path >= 'A' && *path <= 'Z')) && path[1] == ':');
323 323
 #else
324 324
     return *path == '/';
325 325
 #endif
... ...
@@ -21,6 +21,7 @@
21 21
 #include <errno.h>
22 22
 #include "others.h"
23 23
 #include "dirent.h"
24
+#include "w32_stat.h"
24 25
 #include "shared/misc.h"
25 26
 
26 27
 DIR *opendir(const char *name) {
... ...
@@ -28,11 +29,11 @@ DIR *opendir(const char *name) {
28 28
     DWORD attrs;
29 29
     int len;
30 30
     struct stat sb;
31
+    wchar_t *wpath;
31 32
 
32
-    if(stat(name, &sb) < 0) {
33
-	errno = ENOENT; /* FIXME: should be set by stat() */
33
+    if(stat(name, &sb) < 0)
34 34
 	return NULL;
35
-    }
35
+
36 36
     if(!S_ISDIR(sb.st_mode)) {
37 37
 	errno = ENOTDIR;
38 38
 	return NULL;
... ...
@@ -41,19 +42,26 @@ DIR *opendir(const char *name) {
41 41
 	errno = ENOMEM;
42 42
 	return NULL;
43 43
     }
44
-    len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, d->entry, sizeof(d->entry) / sizeof(d->entry[0]));
45
-    if(!len || len >= PATH_MAX - 4) {
44
+    wpath = uncpath(name);
45
+    if(!wpath)
46
+	return NULL;
47
+    wcsncpy(d->entry, wpath, sizeof(d->entry) / sizeof(d->entry[0]));
48
+    free(wpath);
49
+    d->entry[sizeof(d->entry) / sizeof(d->entry[0])] = L'\0';
50
+    len = wcslen(d->entry);
51
+
52
+    if(len >= sizeof(d->entry) / sizeof(d->entry[0]) - 4) {
46 53
 	free(d);
47
-	errno = (len || (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) ? ENAMETOOLONG : ENOENT;
54
+	errno = ENAMETOOLONG;
48 55
 	return NULL;
49 56
     }
50
-    while(len) {
57
+    while(len--) {
51 58
 	if(d->entry[len] == L'\\')
52 59
 	    d->entry[len] = L'\0';
53 60
 	else
54 61
 	    break;
55 62
     }
56
-    /* FIXME: this should be UNC'd */
63
+
57 64
     wcsncat(d->entry, L"\\*.*", 4);
58 65
     d->dh = INVALID_HANDLE_VALUE;
59 66
     return d;
... ...
@@ -100,7 +100,7 @@ void fix_paths(void) {
100 100
 	if(!have_ddir)
101 101
 	    snprintf(_DATADIR, sizeof(_DATADIR), "%s\\database", dir);
102 102
 	if(!have_cdir) {
103
-	    strncpy(_CONFDIR, dir, sizeof(_DATADIR));
103
+	    strncpy(_CONFDIR, dir, sizeof(_CONFDIR));
104 104
 	    have_cdir = 1;
105 105
 	}
106 106
     }
... ...
@@ -18,36 +18,73 @@
18 18
  *  MA 02110-1301, USA.
19 19
  */
20 20
 
21
+#include <errno.h>
22
+
21 23
 #include "others.h"
24
+#include "shared/misc.h"
22 25
 
23
-w32_stat(const char *path, struct stat *buf) {
24
-    int len = strlen(path) + 2;
25
-    wchar_t *wpath;
26
-    WIN32_FILE_ATTRIBUTE_DATA attrs;
27 26
 
28
-    if(len > PATH_MAX) {
29
-	errno = ENAMETOOLONG;
30
-	return -1;
31
-    }
32
-    if(!(wpath = cli_malloc(len * 2))) {
33
-	errno = ENOMEM;
34
-	return -1;
27
+wchar_t *uncpath(const char *path) {
28
+    DWORD len = 0;
29
+    wchar_t *dest = cli_malloc((PATH_MAX + 1) * sizeof(wchar_t));
30
+
31
+    if(!dest)
32
+	return NULL;
33
+
34
+    if(strncmp(path, "\\\\", 2)) {
35
+	/* NOT already UNC */
36
+	memcpy(dest, L"\\\\?\\", 8);
37
+
38
+	if(!cli_is_abspath(path)) {
39
+	    /* Relative path */
40
+	    len = GetCurrentDirectoryW(PATH_MAX - 5, &dest[4]);
41
+	    if(!len || len > PATH_MAX - 5) {
42
+		free(dest);
43
+		errno = (len || (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) ? ENAMETOOLONG : ENOENT;
44
+		return NULL;
45
+	    }
46
+	    len += 4;
47
+	    dest[len] = L'\\';
48
+	    len++;
49
+	} else {
50
+	    /* C:\ and friends */
51
+	    len = 4;
52
+	}
53
+    } else {
54
+	/* UNC already */
55
+	len = 0;
35 56
     }
36
-    /* FIXME: make it UNC */
37
-    if(!(len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, path, -1, wpath, len))) {
38
-	errno = ENOENT;	
39
-	free(wpath);
40
-	return -1;
57
+    if(!(len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, path, -1, &dest[len], PATH_MAX - len)) || len > PATH_MAX - len) {
58
+        free(dest);
59
+	errno = (len || (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) ? ENAMETOOLONG : ENOENT;
60
+        return NULL;
41 61
     }
42
-    if((len == 3 || (len == 7 && !wcsncmp(wpath, L"\\\\?\\", 4))) && (wpath[len-2] == L':') &&
43
-	((wpath[len-3] >= L'A' && wpath[len-3] <= L'Z') || (wpath[len-3] >= L'a' && wpath[len-2] <= L'z')) ) {
44
-	/* stat drives as dirs */
45
-	wpath[len-1] = L'\\';
46
-	wpath[len] = L'\0';
62
+
63
+    len = wcslen(dest);
64
+    if(len == 6 && !wcsncmp(dest, L"\\\\?\\", 4) && (dest[5] == L':') && ((dest[4] >= L'A' && dest[4] <= L'Z') || (dest[4] >= L'a' && dest[4] <= L'z'))) {
65
+	dest[6] = L'\\';
66
+	dest[7] = L'\0';
47 67
     }
68
+
69
+    return dest;
70
+}
71
+
72
+
73
+w32_stat(const char *path, struct stat *buf) {
74
+    int len;
75
+    wchar_t *wpath = uncpath(path);
76
+    WIN32_FILE_ATTRIBUTE_DATA attrs;
77
+
78
+    if(!wpath)
79
+	return -1;
80
+
81
+    len = wcslen(wpath);
82
+    if(len > 2 && wpath[len-1] == L'.' && wpath[len-2] == L'\\')
83
+	wpath[len-2] = L'\0'; /* windoze can't stat '.' ... */
48 84
     len = GetFileAttributesExW(wpath, GetFileExInfoStandard, &attrs);
49 85
     free(wpath);
50 86
     if(!len) {
87
+	len = GetLastError();
51 88
 	errno = ENOENT;
52 89
 	return -1;
53 90
     }
... ...
@@ -39,4 +39,7 @@ int w32_stat(const char *path, struct stat *buf);
39 39
 #define lstat stat
40 40
 #define stat(path, buf) w32_stat(path, buf)
41 41
 
42
+wchar_t *uncpath(const char *path);
43
+
42 44
 #endif
45
+
... ...
@@ -755,6 +755,10 @@
755 755
 					RelativePath="..\shared\getopt.c"
756 756
 					>
757 757
 				</File>
758
+				<File
759
+					RelativePath="..\shared\misc.c"
760
+					>
761
+				</File>
758 762
 			</Filter>
759 763
 			<Filter
760 764
 				Name="compat"