Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

266 lines
4.2 KiB

  1. // filename conversion/canonicalization facility
  2. //
  3. #include "mbrmake.h"
  4. #include <string.h>
  5. #include <ctype.h>
  6. LSZ ToCanonPath(LSZ lszPath, LSZ lszCwd, LSZ lszCanon);
  7. VOID ToRelativePath(LSZ lszPath, LSZ lszCwd);
  8. VOID ToBackSlashes(LSZ lsz);
  9. #ifdef STANDALONE
  10. #include <stdio.h>
  11. main()
  12. {
  13. static char s[PATH_BUF];
  14. static char canon[PATH_BUF];
  15. static char cwd[PATH_BUF];
  16. getcwd(cwd, PATH_BUF);
  17. printf("Current Dir is %s\n", cwd);
  18. printf("Canonical path?\n");
  19. gets(canon);
  20. while (gets(s)) {
  21. printf("%s\n", ToCanonPath(s, cwd, canon));
  22. }
  23. }
  24. #endif
  25. LSZ
  26. ToCanonPath(LSZ lszPath, LSZ lszCwd, LSZ lszCanon)
  27. // canonicalize the given path
  28. //
  29. {
  30. LSZ p;
  31. static char buf[PATH_BUF];
  32. strcpy(buf, lszPath);
  33. ToBackSlashes(buf);
  34. if (buf[0] == 0 || buf[0] == '\\' || buf[0] == '<')
  35. return buf;
  36. if (buf[1] == ':') {
  37. // different drive is assumed invariant
  38. if (buf[0] != lszCwd[0] || '\\' == buf[2])
  39. return buf;
  40. strcpy(buf, lszCwd);
  41. strcat(buf, "/");
  42. strcat(buf, lszPath+2);
  43. }
  44. else {
  45. strcpy(buf, lszCwd);
  46. strcat(buf, "/");
  47. strcat(buf, lszPath);
  48. }
  49. ToBackSlashes(buf);
  50. p = buf;
  51. for (;;) {
  52. p = strchr(p, '\\');
  53. if (!p) {
  54. ToRelativePath(buf, lszCanon);
  55. return buf;
  56. }
  57. switch (p[1]) {
  58. case '\0':
  59. *p = 0;
  60. ToRelativePath(buf, lszCanon);
  61. return buf;
  62. case '\\':
  63. strcpy(p, p+1);
  64. break;
  65. case '.':
  66. if (p[2] == '\\' || p[2] == 0) {
  67. strcpy(p, p+2);
  68. break;
  69. }
  70. if (p[2] == '.' && (p[3] == '\\' || p[3] == 0)) {
  71. LSZ s;
  72. s = p;
  73. while (--s >= buf) {
  74. if (*s == '\\') {
  75. strcpy(s+1,p+3);
  76. p = s;
  77. break;
  78. }
  79. }
  80. if (s < buf)
  81. p++;
  82. }
  83. break;
  84. default:
  85. p++;
  86. }
  87. }
  88. }
  89. VOID
  90. ToRelativePath(LSZ lszPath, LSZ lszCwd)
  91. // convert absolute path to relative
  92. //
  93. {
  94. WORD ich, ichOK;
  95. int c1, c2;
  96. char buf[PATH_BUF];
  97. ich = ichOK = 0;
  98. for (ich = 0; lszPath[ich] && lszCwd[ich]; ich++) {
  99. c1 = lszPath[ich];
  100. c2 = lszCwd[ich];
  101. if (c1 == c2) {
  102. if (c1 == '\\') ichOK = ich+1;
  103. continue;
  104. }
  105. if (isupper(c1) && islower(c2) && tolower(c1) == c2)
  106. continue;
  107. if (isupper(c2) && islower(c1) && tolower(c2) == c1)
  108. continue;
  109. break;
  110. }
  111. if (ich == 0) // not on the same drive, we can't do the conversion
  112. return;
  113. if (lszCwd[ich] == 0 && lszPath[ich] == '\\') {
  114. ichOK = ich+1;
  115. c2 = 0;
  116. }
  117. else {
  118. c2 = 1;
  119. c1 = ichOK;
  120. for (c1 = ichOK; lszCwd[c1]; c1++)
  121. if (lszCwd[c1] == '\\')
  122. c2++;
  123. }
  124. buf[0] = 0;
  125. for (c1 = 0; c1 < c2; c1++)
  126. strcat(buf, "..\\");
  127. strcat(buf, lszPath+ichOK);
  128. strcpy(lszPath, buf);
  129. }
  130. LSZ
  131. ToAbsPath(LSZ lszPath, LSZ lszCwd)
  132. // canonicalize the given path
  133. //
  134. {
  135. LSZ p;
  136. static char buf[PATH_BUF];
  137. strcpy(buf, lszPath);
  138. ToBackSlashes(buf);
  139. if (buf[0] == '<')
  140. return buf;
  141. if (buf[0] == 0) {
  142. strcpy(buf, lszCwd);
  143. ToBackSlashes(lszCwd);
  144. return buf;
  145. }
  146. if (buf[0] == '\\') {
  147. buf[0] = lszCwd[0];
  148. buf[1] = ':';
  149. strcpy(buf+2, lszPath);
  150. ToBackSlashes(buf);
  151. return buf;
  152. }
  153. if (buf[1] == ':') {
  154. // different drive is assumed invariant
  155. if (buf[0] != lszCwd[0] || buf[2] == '\\')
  156. return buf;
  157. strcpy(buf, lszCwd);
  158. strcat(buf, "/");
  159. strcat(buf, lszPath+2);
  160. }
  161. else {
  162. strcpy(buf, lszCwd);
  163. strcat(buf, "/");
  164. strcat(buf, lszPath);
  165. }
  166. ToBackSlashes(buf);
  167. p = buf;
  168. for (;;) {
  169. p = strchr(p, '\\');
  170. if (!p) return buf;
  171. switch (p[1]) {
  172. case '\0':
  173. *p = 0;
  174. return buf;
  175. case '\\':
  176. strcpy(p, p+1);
  177. break;
  178. case '.':
  179. if (p[2] == '\\' || p[2] == 0) {
  180. strcpy(p, p+2);
  181. break;
  182. }
  183. if (p[2] == '.' && (p[3] == '\\' || p[3] == 0)) {
  184. LSZ s;
  185. s = p;
  186. while (--s >= buf) {
  187. if (*s == '\\') {
  188. strcpy(s+1,p+3);
  189. p = s;
  190. break;
  191. }
  192. }
  193. if (s < buf)
  194. p++;
  195. }
  196. break;
  197. default:
  198. p++;
  199. }
  200. }
  201. }
  202. VOID
  203. ToBackSlashes(LSZ lsz)
  204. // convert forward slashes to backslashes
  205. //
  206. {
  207. while (*lsz) {
  208. if (*lsz == '/') *lsz = '\\';
  209. lsz ++;
  210. }
  211. }