2
0

filesys.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /* Licensed to the Apache Software Foundation (ASF) under one or more
  2. * contributor license agreements. See the NOTICE file distributed with
  3. * this work for additional information regarding copyright ownership.
  4. * The ASF licenses this file to You under the Apache License, Version 2.0
  5. * (the "License"); you may not use this file except in compliance with
  6. * the License. You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "fspr.h"
  17. #include "fspr_arch_file_io.h"
  18. #include "fspr_strings.h"
  19. /* Win32 Exceptions:
  20. *
  21. * Note that trailing spaces and trailing periods are never recorded
  22. * in the file system, except by a very obscure bug where any file
  23. * that is created with a trailing space or period, followed by the
  24. * ':' stream designator on an NTFS volume can never be accessed again.
  25. * In other words, don't ever accept them when designating a stream!
  26. *
  27. * An interesting side effect is that two or three periods are both
  28. * treated as the parent directory, although the fourth and on are
  29. * not [strongly suggest all trailing periods are trimmed off, or
  30. * down to two if there are no other characters.]
  31. *
  32. * Leading spaces and periods are accepted, however.
  33. * The * ? < > codes all have wildcard side effects
  34. * The " / \ : are exclusively component separator tokens
  35. * The system doesn't accept | for any (known) purpose
  36. * Oddly, \x7f _is_ acceptable ;)
  37. */
  38. /* fspr_c_is_fnchar[] maps Win32's file name and shell escape symbols
  39. *
  40. * element & 1 == valid file name character [excluding delimiters]
  41. * element & 2 == character should be shell (caret) escaped from cmd.exe
  42. *
  43. * this must be in-sync with Apache httpd's gen_test_char.c for cgi escaping.
  44. */
  45. const char fspr_c_is_fnchar[256] =
  46. {/* Reject all ctrl codes... Escape \n and \r (ascii 10 and 13) */
  47. 0,0,0,0,0,0,0,0,0,0,2,0,0,2,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  48. /* ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */
  49. 1,1,2,1,3,3,3,3,3,3,2,1,1,1,1,0, 1,1,1,1,1,1,1,1,1,1,0,3,2,1,2,2,
  50. /* @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ */
  51. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,3,2,3,3,1,
  52. /* ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~ */
  53. 3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,3,2,3,3,1,
  54. /* High bit codes are accepted (subject to utf-8->Unicode xlation) */
  55. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  56. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  57. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  58. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
  59. };
  60. fspr_status_t filepath_root_test(char *path, fspr_pool_t *p)
  61. {
  62. fspr_status_t rv;
  63. #if APR_HAS_UNICODE_FS
  64. if (fspr_os_level >= APR_WIN_NT)
  65. {
  66. fspr_wchar_t wpath[APR_PATH_MAX];
  67. if (rv = utf8_to_unicode_path(wpath, sizeof(wpath)
  68. / sizeof(fspr_wchar_t), path))
  69. return rv;
  70. rv = GetDriveTypeW(wpath);
  71. }
  72. else
  73. #endif
  74. rv = GetDriveType(path);
  75. if (rv == DRIVE_UNKNOWN || rv == DRIVE_NO_ROOT_DIR)
  76. return APR_EBADPATH;
  77. return APR_SUCCESS;
  78. }
  79. fspr_status_t filepath_drive_get(char **rootpath, char drive,
  80. fspr_int32_t flags, fspr_pool_t *p)
  81. {
  82. char path[APR_PATH_MAX];
  83. #if APR_HAS_UNICODE_FS
  84. IF_WIN_OS_IS_UNICODE
  85. {
  86. fspr_wchar_t *ignored;
  87. fspr_wchar_t wdrive[8];
  88. fspr_wchar_t wpath[APR_PATH_MAX];
  89. fspr_status_t rv;
  90. /* ???: This needs review, apparently "\\?\d:." returns "\\?\d:"
  91. * as if that is useful for anything.
  92. */
  93. wcscpy(wdrive, L"D:.");
  94. wdrive[0] = (fspr_wchar_t)(unsigned char)drive;
  95. if (!GetFullPathNameW(wdrive, sizeof(wpath) / sizeof(fspr_wchar_t), wpath, &ignored))
  96. return fspr_get_os_error();
  97. if ((rv = unicode_to_utf8_path(path, sizeof(path), wpath)))
  98. return rv;
  99. }
  100. #endif
  101. #if APR_HAS_ANSI_FS
  102. ELSE_WIN_OS_IS_ANSI
  103. {
  104. char *ignored;
  105. char drivestr[4];
  106. drivestr[0] = drive;
  107. drivestr[1] = ':';
  108. drivestr[2] = '.';;
  109. drivestr[3] = '\0';
  110. if (!GetFullPathName(drivestr, sizeof(path), path, &ignored))
  111. return fspr_get_os_error();
  112. }
  113. #endif
  114. if (!(flags & APR_FILEPATH_NATIVE)) {
  115. for (*rootpath = path; **rootpath; ++*rootpath) {
  116. if (**rootpath == '\\')
  117. **rootpath = '/';
  118. }
  119. }
  120. *rootpath = fspr_pstrdup(p, path);
  121. return APR_SUCCESS;
  122. }
  123. fspr_status_t filepath_root_case(char **rootpath, char *root, fspr_pool_t *p)
  124. {
  125. #if APR_HAS_UNICODE_FS
  126. IF_WIN_OS_IS_UNICODE
  127. {
  128. fspr_wchar_t *ignored;
  129. fspr_wchar_t wpath[APR_PATH_MAX];
  130. fspr_status_t rv;
  131. fspr_wchar_t wroot[APR_PATH_MAX];
  132. /* ???: This needs review, apparently "\\?\d:." returns "\\?\d:"
  133. * as if that is useful for anything.
  134. */
  135. if (rv = utf8_to_unicode_path(wroot, sizeof(wroot)
  136. / sizeof(fspr_wchar_t), root))
  137. return rv;
  138. if (!GetFullPathNameW(wroot, sizeof(wpath) / sizeof(fspr_wchar_t), wpath, &ignored))
  139. return fspr_get_os_error();
  140. /* Borrow wroot as a char buffer (twice as big as necessary)
  141. */
  142. if ((rv = unicode_to_utf8_path((char*)wroot, sizeof(wroot), wpath)))
  143. return rv;
  144. *rootpath = fspr_pstrdup(p, (char*)wroot);
  145. }
  146. #endif
  147. #if APR_HAS_ANSI_FS
  148. ELSE_WIN_OS_IS_ANSI
  149. {
  150. char path[APR_PATH_MAX];
  151. char *ignored;
  152. if (!GetFullPathName(root, sizeof(path), path, &ignored))
  153. return fspr_get_os_error();
  154. *rootpath = fspr_pstrdup(p, path);
  155. }
  156. #endif
  157. return APR_SUCCESS;
  158. }
  159. APR_DECLARE(fspr_status_t) fspr_filepath_get(char **rootpath, fspr_int32_t flags,
  160. fspr_pool_t *p)
  161. {
  162. char path[APR_PATH_MAX];
  163. #if APR_HAS_UNICODE_FS
  164. IF_WIN_OS_IS_UNICODE
  165. {
  166. fspr_wchar_t wpath[APR_PATH_MAX];
  167. fspr_status_t rv;
  168. if (!GetCurrentDirectoryW(sizeof(wpath) / sizeof(fspr_wchar_t), wpath))
  169. return fspr_get_os_error();
  170. if ((rv = unicode_to_utf8_path(path, sizeof(path), wpath)))
  171. return rv;
  172. }
  173. #endif
  174. #if APR_HAS_ANSI_FS
  175. ELSE_WIN_OS_IS_ANSI
  176. {
  177. if (!GetCurrentDirectory(sizeof(path), path))
  178. return fspr_get_os_error();
  179. }
  180. #endif
  181. if (!(flags & APR_FILEPATH_NATIVE)) {
  182. for (*rootpath = path; **rootpath; ++*rootpath) {
  183. if (**rootpath == '\\')
  184. **rootpath = '/';
  185. }
  186. }
  187. *rootpath = fspr_pstrdup(p, path);
  188. return APR_SUCCESS;
  189. }
  190. APR_DECLARE(fspr_status_t) fspr_filepath_set(const char *rootpath,
  191. fspr_pool_t *p)
  192. {
  193. #if APR_HAS_UNICODE_FS
  194. IF_WIN_OS_IS_UNICODE
  195. {
  196. fspr_wchar_t wpath[APR_PATH_MAX];
  197. fspr_status_t rv;
  198. if (rv = utf8_to_unicode_path(wpath, sizeof(wpath)
  199. / sizeof(fspr_wchar_t), rootpath))
  200. return rv;
  201. if (!SetCurrentDirectoryW(wpath))
  202. return fspr_get_os_error();
  203. }
  204. #endif
  205. #if APR_HAS_ANSI_FS
  206. ELSE_WIN_OS_IS_ANSI
  207. {
  208. if (!SetCurrentDirectory(rootpath))
  209. return fspr_get_os_error();
  210. }
  211. #endif
  212. return APR_SUCCESS;
  213. }