102 } |
102 } |
103 return curDirLenCached; |
103 return curDirLenCached; |
104 } |
104 } |
105 } |
105 } |
106 |
106 |
|
107 /* |
|
108 The "abpathlen" is the size of the buffer needed by _wfullpath. If the |
|
109 "path" is a relative path, it is "the length of the current dir" + "the |
|
110 length of the path", if it's "absolute" already, it's the same as |
|
111 pathlen which is the length of "path". |
|
112 */ |
|
113 WCHAR* prefixAbpath(const WCHAR* path, int pathlen, int abpathlen) { |
|
114 WCHAR* pathbuf = NULL; |
|
115 WCHAR* abpath = NULL; |
|
116 |
|
117 abpathlen += 10; //padding |
|
118 abpath = (WCHAR*)malloc(abpathlen * sizeof(WCHAR)); |
|
119 if (abpath) { |
|
120 /* Collapse instances of "foo\.." and ensure absoluteness before |
|
121 going down to prefixing. |
|
122 */ |
|
123 if (_wfullpath(abpath, path, abpathlen)) { |
|
124 pathbuf = getPrefixed(abpath, abpathlen); |
|
125 } else { |
|
126 /* _wfullpath fails if the pathlength exceeds 32k wchar. |
|
127 Instead of doing more fancy things we simply copy the |
|
128 ps into the return buffer, the subsequent win32 API will |
|
129 probably fail with FileNotFoundException, which is expected |
|
130 */ |
|
131 pathbuf = (WCHAR*)malloc((pathlen + 6) * sizeof(WCHAR)); |
|
132 if (pathbuf != 0) { |
|
133 wcscpy(pathbuf, path); |
|
134 } |
|
135 } |
|
136 free(abpath); |
|
137 } |
|
138 return pathbuf; |
|
139 } |
|
140 |
107 /* If this returns NULL then an exception is pending */ |
141 /* If this returns NULL then an exception is pending */ |
108 WCHAR* |
142 WCHAR* |
109 pathToNTPath(JNIEnv *env, jstring path, jboolean throwFNFE) { |
143 pathToNTPath(JNIEnv *env, jstring path, jboolean throwFNFE) { |
110 int pathlen = 0; |
144 int pathlen = 0; |
111 WCHAR *pathbuf = NULL; |
145 WCHAR *pathbuf = NULL; |
112 int max_path = 248; /* Since CreateDirectoryW() has the limit of |
146 int max_path = 248; /* CreateDirectoryW() has the limit of 248 */ |
113 248 instead of the normal MAX_PATH, we |
147 |
114 use 248 as the max_path to satisfy both |
|
115 */ |
|
116 WITH_UNICODE_STRING(env, path, ps) { |
148 WITH_UNICODE_STRING(env, path, ps) { |
117 pathlen = wcslen(ps); |
149 pathlen = wcslen(ps); |
118 if (pathlen != 0) { |
150 if (pathlen != 0) { |
119 if (pathlen > 2 && |
151 if (pathlen > 2 && |
120 (ps[0] == L'\\' && ps[1] == L'\\' || //UNC |
152 (ps[0] == L'\\' && ps[1] == L'\\' || //UNC |
121 ps[1] == L':' && ps[2] == L'\\')) { //absolute |
153 ps[1] == L':' && ps[2] == L'\\')) //absolute |
|
154 { |
122 if (pathlen > max_path - 1) { |
155 if (pathlen > max_path - 1) { |
123 pathbuf = getPrefixed(ps, pathlen); |
156 pathbuf = prefixAbpath(ps, pathlen, pathlen); |
124 } else { |
157 } else { |
125 pathbuf = (WCHAR*)malloc((pathlen + 6) * sizeof(WCHAR)); |
158 pathbuf = (WCHAR*)malloc((pathlen + 6) * sizeof(WCHAR)); |
126 if (pathbuf != 0) { |
159 if (pathbuf != 0) { |
127 wcscpy(pathbuf, ps); |
160 wcscpy(pathbuf, ps); |
128 } |
161 } |
130 } else { |
163 } else { |
131 /* If the path came in as a relative path, need to verify if |
164 /* If the path came in as a relative path, need to verify if |
132 its absolute form is bigger than max_path or not, if yes |
165 its absolute form is bigger than max_path or not, if yes |
133 need to (1)convert it to absolute and (2)prefix. This is |
166 need to (1)convert it to absolute and (2)prefix. This is |
134 obviously a burden to all relative paths (The current dir/len |
167 obviously a burden to all relative paths (The current dir/len |
135 for "dirve & directory" relative path is cached, so we only |
168 for "drive & directory" relative path is cached, so we only |
136 calculate it once but for "drive-relative path we call |
169 calculate it once but for "drive-relative path we call |
137 _wgetdcwd() and wcslen() everytime), but a hit we have |
170 _wgetdcwd() and wcslen() everytime), but a hit we have |
138 to take if we want to support relative path beyond max_path. |
171 to take if we want to support relative path beyond max_path. |
139 There is no way to predict how long the absolute path will be |
172 There is no way to predict how long the absolute path will be |
140 (therefor allocate the sufficient memory block) before calling |
173 (therefor allocate the sufficient memory block) before calling |
141 _wfullpath(), we have to get the length of "current" dir first. |
174 _wfullpath(), we have to get the length of "current" dir first. |
142 */ |
175 */ |
143 WCHAR *abpath = NULL; |
176 WCHAR *abpath = NULL; |
144 int dirlen = currentDirLength(ps, pathlen); |
177 int dirlen = currentDirLength(ps, pathlen); |
145 if (dirlen + pathlen + 1 > max_path - 1) { |
178 if (dirlen + pathlen + 1 > max_path - 1) { |
146 int abpathlen = dirlen + pathlen + 10; |
179 pathbuf = prefixAbpath(ps, pathlen, dirlen + pathlen); |
147 abpath = (WCHAR*)malloc(abpathlen * sizeof(WCHAR)); |
|
148 if (abpath) { |
|
149 if (_wfullpath(abpath, ps, abpathlen)) { |
|
150 pathbuf = getPrefixed(abpath, abpathlen); |
|
151 } else { |
|
152 /* _wfullpath fails if the pathlength exceeds 32k wchar. |
|
153 Instead of doing more fancy things we simply copy the |
|
154 ps into the return buffer, the subsequent win32 API will |
|
155 probably fail with FileNotFoundException, which is expected |
|
156 */ |
|
157 pathbuf = (WCHAR*)malloc((pathlen + 6) * sizeof(WCHAR)); |
|
158 if (pathbuf != 0) { |
|
159 wcscpy(pathbuf, ps); |
|
160 } |
|
161 } |
|
162 free(abpath); |
|
163 } |
|
164 } else { |
180 } else { |
165 pathbuf = (WCHAR*)malloc((pathlen + 6) * sizeof(WCHAR)); |
181 pathbuf = (WCHAR*)malloc((pathlen + 6) * sizeof(WCHAR)); |
166 if (pathbuf != 0) { |
182 if (pathbuf != 0) { |
167 wcscpy(pathbuf, ps); |
183 wcscpy(pathbuf, ps); |
168 } |
184 } |