« index

Coverage for /Users/kris/q-io/fs-root.js : 87%

91 lines | 80 run | 11 missing | 0 partial | 21 blocks | 10 blocks run | 11 blocks missing

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

  var Q = require("q");
  var BOOT = require("./fs-boot");
  var COMMON = require("./fs-common");
  
  module.exports = RootFs;
  
  function RootFs(outer, root) {
      var inner = Object.create(BOOT);
  
      function attenuate(path) {
  
          // the machinations of projecting a path inside a
          // subroot
          var actual;
          // if it's absolute, we want the path relative to
          // the root of the inner file system
          if (outer.isAbsolute(path)) {
              actual = outer.relativeFromDirectory(outer.ROOT, path);
          } else {
              actual = path;
          }
          // we join the path onto the root of the inner file
          // system so that parent references from the root
          // return to the root, emulating standard unix
          // behavior
          actual = outer.join(outer.ROOT, actual);
          // then we reconstruct the path relative to the
          // inner root
          actual = outer.relativeFromDirectory(outer.ROOT, actual);
          // and rejoin it on the outer root
          actual = outer.join(root, actual);
          // and find the corresponding real path
          actual = outer.canonical(actual);
          return Q.when(actual, function (actual) {
              // and verify that the outer canonical path is
              // actually inside the inner canonical path, to
              // prevent break-outs
              if (outer.contains(root, actual)) {
                  return {
                      "inner": outer.join(outer.ROOT, outer.relativeFromDirectory(root, actual)),
                      "outer": actual
                  };
              } else {
                  return Q.reject("Can't find: " + JSON.stringify(path));
              }
          });
      }
  
      function workingDirectory() {
          return outer.ROOT;
      }
  
      COMMON.update(inner, workingDirectory);
  
      inner.list = function (path) {
          return Q.when(attenuate(path), function (path) {
              return outer.list(path.outer);
          }).then(null, function (reason) {
              return Q.reject("Can't list " + JSON.stringify(path));
          });
      };
  
      inner.open = function (path, flags, charset) {
          return Q.when(attenuate(path), function (path) {
              return outer.open(path.outer, flags, charset);
          }).then(null, function (reason) {
              return Q.reject("Can't open " + JSON.stringify(path));
          });
      };
  
      inner.stat = function (path) {
          return Q.when(attenuate(path), function (path) {
              return outer.stat(path.outer);
          }).then(null, function (reason) {
              return Q.reject("Can't stat " + JSON.stringify(path));
          });
      };
  
      inner.canonical = function (path) {
          return Q.when(attenuate(path), function (path) {
              return path.inner;
          }).then(null, function (reason) {
              return Q.reject("Can't find canonical of " + JSON.stringify(path));
          });
      };
  
      return Q.when(outer.canonical(root), function (_root) {
          root = _root;
          return inner;
      });
  }
« index | cover.io