1
1
module Node.FS.Perms
2
- ( permsFromString
3
- , permsToString
4
- , permsToInt
2
+ ( Perm ()
5
3
, none
6
- , r
7
- , w
8
- , x
4
+ , read
5
+ , write
6
+ , execute
9
7
, all
10
- , mkPerms
11
8
, Perms ()
12
- , Perm ()
9
+ , mkPerms
10
+ , permsFromString
11
+ , permsToString
12
+ , permsToInt
13
13
) where
14
14
15
15
import Global (readInt )
16
+ import Data.Array () -- for Semigroup and Functor instances
16
17
import Data.Maybe (Maybe (..))
17
- import Data.Char (Char (), charString )
18
- import Data.String (toCharArray )
18
+ import Data.Char (Char (), charString , fromCharCode )
19
+ import Data.String (toCharArray , joinWith , drop , charAt )
19
20
import Data.Int (Int (), fromNumber , toNumber )
20
21
21
22
-- | A `Perm` value specifies what is allowed to be done with a particular
22
23
-- | file by a particular class of user — that is, whether it is
23
24
-- | readable, writable, and/or executable. It has a semigroup instance, which
24
- -- | allows you to combine permissions; for example, `r <> w ` means "readable
25
- -- | and writable".
25
+ -- | allows you to combine permissions; for example, `read <> write ` means
26
+ -- | "readable and writable".
26
27
newtype Perm = Perm { r :: Boolean , w :: Boolean , x :: Boolean }
27
28
28
- -- | A `Perms` value includes all the permissions information about a
29
- -- | particular file or directory, by storing a `Perm` value for each of the
30
- -- | file owner, the group, and others.
31
- newtype Perms = Perms { u :: Perm , g :: Perm , o :: Perm }
29
+ instance eqPerm :: Eq Perm where
30
+ (==) (Perm { r = r1, w = w1, x = x1 }) (Perm { r = r2, w = w2, x = x2 }) =
31
+ r1 == r2 && w1 == w2 && x1 == x2
32
+ (/=) x y = not (x == y)
33
+
34
+ instance ordPerm :: Ord Perm where
35
+ compare (Perm { r = r1, w = w1, x = x1 }) (Perm { r = r2, w = w2, x = x2 }) =
36
+ compare [r1, w1, x1] [r2, w2, x2]
37
+
38
+ instance showPerm :: Show Perm where
39
+ show p | p == none = " none"
40
+ show p | p == all = " all"
41
+ show (Perm { r = r, w = w, x = x }) =
42
+ joinWith " <> " ps
43
+ where
44
+ ps =
45
+ (if r then [" read" ] else [] ) <>
46
+ (if w then [" write" ] else [] ) <>
47
+ (if x then [" execute" ] else [] )
48
+
49
+ instance semigroupPerm :: Semigroup Perm where
50
+ (<>) (Perm { r = r0, w = w0, x = x0 }) (Perm { r = r1, w = w1, x = x1 }) =
51
+ Perm { r: r0 || r1, w: w0 || w1, x: x0 || x1 }
52
+
53
+ -- | Create a `Perm` value. The arguments represent the readable, writable, and
54
+ -- | executable permissions, in that order.
55
+ mkPerm :: Boolean -> Boolean -> Boolean -> Perm
56
+ mkPerm r w x = Perm { r: r, w: w, x: x }
32
57
33
58
-- | No permissions. This is the identity of the `Semigroup` operation `(<>)`
34
59
-- | for `Perm`.
35
60
none :: Perm
36
61
none = Perm { r: false , w: false , x: false }
37
62
38
63
-- | The "readable" permission.
39
- r :: Perm
40
- r = Perm { r: true , w: false , x: false }
64
+ read :: Perm
65
+ read = Perm { r: true , w: false , x: false }
41
66
42
67
-- | The "writable" permission.
43
- w :: Perm
44
- w = Perm { r: false , w: true , x: false }
68
+ write :: Perm
69
+ write = Perm { r: false , w: true , x: false }
45
70
46
71
-- | The "executable" permission.
47
- x :: Perm
48
- x = Perm { r: false , w: false , x: true }
72
+ execute :: Perm
73
+ execute = Perm { r: false , w: false , x: true }
49
74
50
75
-- | All permissions: readable, writable, and executable.
51
76
all :: Perm
52
- all = r <> w <> x
77
+ all = read <> write <> execute
53
78
54
- instance semigroupPerm :: Semigroup Perm where
55
- (<>) (Perm { r = r0, w = w0, x = x0 }) (Perm { r = r1, w = w1, x = x1 }) =
56
- Perm { r: r0 || r1, w: w0 || w1, x: x0 || x1 }
79
+ -- | A `Perms` value includes all the permissions information about a
80
+ -- | particular file or directory, by storing a `Perm` value for each of the
81
+ -- | file owner, the group, and any other users.
82
+ newtype Perms = Perms { u :: Perm , g :: Perm , o :: Perm }
83
+
84
+ instance eqPerms :: Eq Perms where
85
+ (==) (Perms { u = u1, g = g1, o = o1 }) (Perms { u = u2, g = g2, o = o2 }) =
86
+ u1 == u2 && g1 == g2 && o1 == o2
87
+ (/=) x y = not (x == y)
88
+
89
+ instance ordPerms :: Ord Perms where
90
+ compare (Perms { u = u1, g = g1, o = o1 }) (Perms { u = u2, g = g2, o = o2 }) =
91
+ compare [u1, g1, o1] [u2, g2, o2]
92
+
93
+ instance showPerms :: Show Perms where
94
+ show (Perms { u = u, g = g, o = o }) =
95
+ " mkPerms " <> joinWith " " (f <$> [u, g, o])
96
+ where
97
+ f perm = " (" <> show perm <> " )"
57
98
58
99
-- | Attempt to parse a `Perms` value from a `String` containing an octal
59
100
-- | integer. For example,
60
- -- | `permsFromString "644 " == Just (mkPerms (r <> w) r r )`.
101
+ -- | `permsFromString "0644 " == Just (mkPerms (read <> write) read read )`.
61
102
permsFromString :: String -> Maybe Perms
62
- permsFromString = _perms <<< toCharArray
103
+ permsFromString = _perms <<< toCharArray <<< dropPrefix zeroChar
63
104
where
105
+ zeroChar = fromCharCode 48
106
+
107
+ dropPrefix x xs
108
+ | charAt 0 xs == Just x = drop 1 xs
109
+ | otherwise = xs
110
+
64
111
_perms [u, g, o] =
65
112
mkPerms <$> permFromChar u
66
113
<*> permFromChar g
@@ -71,22 +118,17 @@ permFromChar :: Char -> Maybe Perm
71
118
permFromChar = _perm <<< charString
72
119
where
73
120
_perm " 0" = Just $ none
74
- _perm " 1" = Just $ x
75
- _perm " 2" = Just $ w
76
- _perm " 3" = Just $ w <> x
77
- _perm " 4" = Just $ r
78
- _perm " 5" = Just $ r <> x
79
- _perm " 6" = Just $ r <> w
80
- _perm " 7" = Just $ r <> w <> x
121
+ _perm " 1" = Just $ execute
122
+ _perm " 2" = Just $ write
123
+ _perm " 3" = Just $ write <> execute
124
+ _perm " 4" = Just $ read
125
+ _perm " 5" = Just $ read <> execute
126
+ _perm " 6" = Just $ read <> write
127
+ _perm " 7" = Just $ read <> write <> execute
81
128
_perm _ = Nothing
82
129
83
- -- | Create a `Perm` value. The arguments represent the readable, writable, and
84
- -- | executable permissions, in that order.
85
- mkPerm :: Boolean -> Boolean -> Boolean -> Perm
86
- mkPerm r w x = Perm { r: r, w: w, x: x }
87
-
88
- -- | Create a `Perms` value. The arguments represent the user's, group's, and
89
- -- | others' permission sets, respectively.
130
+ -- | Create a `Perms` value. The arguments represent the owner's, group's, and
131
+ -- | other users' permission sets, respectively.
90
132
mkPerms :: Perm -> Perm -> Perm -> Perms
91
133
mkPerms u g o = Perms { u: u, g: g, o: o }
92
134
@@ -96,10 +138,11 @@ mkPerms u g o = Perms { u: u, g: g, o: o }
96
138
-- | * `permToInt w == 2`
97
139
-- | * `permToInt (r <> w) == 6`
98
140
permToInt :: Perm -> Int
99
- permToInt (Perm { r = r, w = w, x = x }) = fromNumber $
100
- (if r then 4 else 0 )
101
- + (if w then 2 else 0 )
102
- + (if x then 1 else 0 )
141
+ permToInt (Perm { r = r, w = w, x = x }) =
142
+ fromNumber $
143
+ (if r then 4 else 0 )
144
+ + (if w then 2 else 0 )
145
+ + (if x then 1 else 0 )
103
146
104
147
-- | Convert a `Perm` to an octal string, via `permToInt`.
105
148
permToString :: Perm -> String
@@ -116,14 +159,6 @@ permsToString (Perms { u = u, g = g, o = o }) =
116
159
++ permToString g
117
160
++ permToString o
118
161
162
+ -- | Convert a `Perms` value to an `Int`, via `permsToString`.
119
163
permsToInt :: Perms -> Int
120
- permsToInt p = fromNumber $ readInt 8 $ permsToString p
121
-
122
- instance showPerm :: Show Perm where
123
- show (Perm { r = r, w = w, x = x }) =
124
- (if r then " r" else " -" )
125
- ++ (if w then " w" else " -" )
126
- ++ (if x then " x" else " -" )
127
-
128
- instance showPerms :: Show Perms where
129
- show (Perms { u = u, g = g, o = o }) = show u ++ show g ++ show o
164
+ permsToInt = fromNumber <<< readInt 8 <<< permsToString
0 commit comments