설명 없음

old.js 8.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. // Copyright Joyent, Inc. and other Node contributors.
  2. //
  3. // Permission is hereby granted, free of charge, to any person obtaining a
  4. // copy of this software and associated documentation files (the
  5. // "Software"), to deal in the Software without restriction, including
  6. // without limitation the rights to use, copy, modify, merge, publish,
  7. // distribute, sublicense, and/or sell copies of the Software, and to permit
  8. // persons to whom the Software is furnished to do so, subject to the
  9. // following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included
  12. // in all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  15. // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  16. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  17. // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  18. // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  19. // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  20. // USE OR OTHER DEALINGS IN THE SOFTWARE.
  21. var pathModule = require('path');
  22. var isWindows = process.platform === 'win32';
  23. var fs = require('fs');
  24. // JavaScript implementation of realpath, ported from node pre-v6
  25. var DEBUG = process.env.NODE_DEBUG && /fs/.test(process.env.NODE_DEBUG);
  26. function rethrow() {
  27. // Only enable in debug mode. A backtrace uses ~1000 bytes of heap space and
  28. // is fairly slow to generate.
  29. var callback;
  30. if (DEBUG) {
  31. var backtrace = new Error;
  32. callback = debugCallback;
  33. } else
  34. callback = missingCallback;
  35. return callback;
  36. function debugCallback(err) {
  37. if (err) {
  38. backtrace.message = err.message;
  39. err = backtrace;
  40. missingCallback(err);
  41. }
  42. }
  43. function missingCallback(err) {
  44. if (err) {
  45. if (process.throwDeprecation)
  46. throw err; // Forgot a callback but don't know where? Use NODE_DEBUG=fs
  47. else if (!process.noDeprecation) {
  48. var msg = 'fs: missing callback ' + (err.stack || err.message);
  49. if (process.traceDeprecation)
  50. console.trace(msg);
  51. else
  52. console.error(msg);
  53. }
  54. }
  55. }
  56. }
  57. function maybeCallback(cb) {
  58. return typeof cb === 'function' ? cb : rethrow();
  59. }
  60. var normalize = pathModule.normalize;
  61. // Regexp that finds the next partion of a (partial) path
  62. // result is [base_with_slash, base], e.g. ['somedir/', 'somedir']
  63. if (isWindows) {
  64. var nextPartRe = /(.*?)(?:[\/\\]+|$)/g;
  65. } else {
  66. var nextPartRe = /(.*?)(?:[\/]+|$)/g;
  67. }
  68. // Regex to find the device root, including trailing slash. E.g. 'c:\\'.
  69. if (isWindows) {
  70. var splitRootRe = /^(?:[a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/][^\\\/]+)?[\\\/]*/;
  71. } else {
  72. var splitRootRe = /^[\/]*/;
  73. }
  74. exports.realpathSync = function realpathSync(p, cache) {
  75. // make p is absolute
  76. p = pathModule.resolve(p);
  77. if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
  78. return cache[p];
  79. }
  80. var original = p,
  81. seenLinks = {},
  82. knownHard = {};
  83. // current character position in p
  84. var pos;
  85. // the partial path so far, including a trailing slash if any
  86. var current;
  87. // the partial path without a trailing slash (except when pointing at a root)
  88. var base;
  89. // the partial path scanned in the previous round, with slash
  90. var previous;
  91. start();
  92. function start() {
  93. // Skip over roots
  94. var m = splitRootRe.exec(p);
  95. pos = m[0].length;
  96. current = m[0];
  97. base = m[0];
  98. previous = '';
  99. // On windows, check that the root exists. On unix there is no need.
  100. if (isWindows && !knownHard[base]) {
  101. fs.lstatSync(base);
  102. knownHard[base] = true;
  103. }
  104. }
  105. // walk down the path, swapping out linked pathparts for their real
  106. // values
  107. // NB: p.length changes.
  108. while (pos < p.length) {
  109. // find the next part
  110. nextPartRe.lastIndex = pos;
  111. var result = nextPartRe.exec(p);
  112. previous = current;
  113. current += result[0];
  114. base = previous + result[1];
  115. pos = nextPartRe.lastIndex;
  116. // continue if not a symlink
  117. if (knownHard[base] || (cache && cache[base] === base)) {
  118. continue;
  119. }
  120. var resolvedLink;
  121. if (cache && Object.prototype.hasOwnProperty.call(cache, base)) {
  122. // some known symbolic link. no need to stat again.
  123. resolvedLink = cache[base];
  124. } else {
  125. var stat = fs.lstatSync(base);
  126. if (!stat.isSymbolicLink()) {
  127. knownHard[base] = true;
  128. if (cache) cache[base] = base;
  129. continue;
  130. }
  131. // read the link if it wasn't read before
  132. // dev/ino always return 0 on windows, so skip the check.
  133. var linkTarget = null;
  134. if (!isWindows) {
  135. var id = stat.dev.toString(32) + ':' + stat.ino.toString(32);
  136. if (seenLinks.hasOwnProperty(id)) {
  137. linkTarget = seenLinks[id];
  138. }
  139. }
  140. if (linkTarget === null) {
  141. fs.statSync(base);
  142. linkTarget = fs.readlinkSync(base);
  143. }
  144. resolvedLink = pathModule.resolve(previous, linkTarget);
  145. // track this, if given a cache.
  146. if (cache) cache[base] = resolvedLink;
  147. if (!isWindows) seenLinks[id] = linkTarget;
  148. }
  149. // resolve the link, then start over
  150. p = pathModule.resolve(resolvedLink, p.slice(pos));
  151. start();
  152. }
  153. if (cache) cache[original] = p;
  154. return p;
  155. };
  156. exports.realpath = function realpath(p, cache, cb) {
  157. if (typeof cb !== 'function') {
  158. cb = maybeCallback(cache);
  159. cache = null;
  160. }
  161. // make p is absolute
  162. p = pathModule.resolve(p);
  163. if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
  164. return process.nextTick(cb.bind(null, null, cache[p]));
  165. }
  166. var original = p,
  167. seenLinks = {},
  168. knownHard = {};
  169. // current character position in p
  170. var pos;
  171. // the partial path so far, including a trailing slash if any
  172. var current;
  173. // the partial path without a trailing slash (except when pointing at a root)
  174. var base;
  175. // the partial path scanned in the previous round, with slash
  176. var previous;
  177. start();
  178. function start() {
  179. // Skip over roots
  180. var m = splitRootRe.exec(p);
  181. pos = m[0].length;
  182. current = m[0];
  183. base = m[0];
  184. previous = '';
  185. // On windows, check that the root exists. On unix there is no need.
  186. if (isWindows && !knownHard[base]) {
  187. fs.lstat(base, function(err) {
  188. if (err) return cb(err);
  189. knownHard[base] = true;
  190. LOOP();
  191. });
  192. } else {
  193. process.nextTick(LOOP);
  194. }
  195. }
  196. // walk down the path, swapping out linked pathparts for their real
  197. // values
  198. function LOOP() {
  199. // stop if scanned past end of path
  200. if (pos >= p.length) {
  201. if (cache) cache[original] = p;
  202. return cb(null, p);
  203. }
  204. // find the next part
  205. nextPartRe.lastIndex = pos;
  206. var result = nextPartRe.exec(p);
  207. previous = current;
  208. current += result[0];
  209. base = previous + result[1];
  210. pos = nextPartRe.lastIndex;
  211. // continue if not a symlink
  212. if (knownHard[base] || (cache && cache[base] === base)) {
  213. return process.nextTick(LOOP);
  214. }
  215. if (cache && Object.prototype.hasOwnProperty.call(cache, base)) {
  216. // known symbolic link. no need to stat again.
  217. return gotResolvedLink(cache[base]);
  218. }
  219. return fs.lstat(base, gotStat);
  220. }
  221. function gotStat(err, stat) {
  222. if (err) return cb(err);
  223. // if not a symlink, skip to the next path part
  224. if (!stat.isSymbolicLink()) {
  225. knownHard[base] = true;
  226. if (cache) cache[base] = base;
  227. return process.nextTick(LOOP);
  228. }
  229. // stat & read the link if not read before
  230. // call gotTarget as soon as the link target is known
  231. // dev/ino always return 0 on windows, so skip the check.
  232. if (!isWindows) {
  233. var id = stat.dev.toString(32) + ':' + stat.ino.toString(32);
  234. if (seenLinks.hasOwnProperty(id)) {
  235. return gotTarget(null, seenLinks[id], base);
  236. }
  237. }
  238. fs.stat(base, function(err) {
  239. if (err) return cb(err);
  240. fs.readlink(base, function(err, target) {
  241. if (!isWindows) seenLinks[id] = target;
  242. gotTarget(err, target);
  243. });
  244. });
  245. }
  246. function gotTarget(err, target, base) {
  247. if (err) return cb(err);
  248. var resolvedLink = pathModule.resolve(previous, target);
  249. if (cache) cache[base] = resolvedLink;
  250. gotResolvedLink(resolvedLink);
  251. }
  252. function gotResolvedLink(resolvedLink) {
  253. // resolve the link, then start over
  254. p = pathModule.resolve(resolvedLink, p.slice(pos));
  255. start();
  256. }
  257. };