@@ -13,16 +13,20 @@ module.exports = (common, options) => {
13
13
14
14
let ipfs
15
15
16
- async function testMode ( mode , expectedMode ) {
17
- const testPath = `/test-${ hat ( ) } `
16
+ async function testChmod ( initialMode , modification , expectedFinalMode ) {
17
+ const path = `/test-${ hat ( ) } `
18
18
19
- await ipfs . files . write ( testPath , Buffer . from ( 'Hello, world!' ) , {
20
- create : true
19
+ await ipfs . files . write ( path , Buffer . from ( 'Hello world!' ) , {
20
+ create : true ,
21
+ mtime : new Date ( ) ,
22
+ mode : initialMode
23
+ } )
24
+ await ipfs . files . chmod ( path , modification , {
25
+ flush : true
21
26
} )
22
- await ipfs . files . chmod ( testPath , mode )
23
27
24
- const stat = await ipfs . files . stat ( testPath )
25
- expect ( stat ) . to . have . property ( 'mode' ) . that . equals ( expectedMode )
28
+ const updatedMode = ( await ipfs . files . stat ( path ) ) . mode
29
+ expect ( updatedMode ) . to . equal ( parseInt ( expectedFinalMode , 8 ) )
26
30
}
27
31
28
32
before ( async ( ) => {
@@ -31,32 +35,297 @@ module.exports = (common, options) => {
31
35
32
36
after ( ( ) => common . clean ( ) )
33
37
34
- it ( 'should change file mode' , async function ( ) {
35
- const mode = parseInt ( '544' , 8 )
36
- await testMode ( mode , mode )
38
+ it ( 'should update the mode for a file' , async ( ) => {
39
+ const path = `/foo-${ Math . random ( ) } `
40
+
41
+ await ipfs . files . write ( path , Buffer . from ( 'Hello world' ) , {
42
+ create : true ,
43
+ mtime : new Date ( )
44
+ } )
45
+ const originalMode = ( await ipfs . files . stat ( path ) ) . mode
46
+ await ipfs . files . chmod ( path , '0777' , {
47
+ flush : true
48
+ } )
49
+
50
+ const updatedMode = ( await ipfs . files . stat ( path ) ) . mode
51
+ expect ( updatedMode ) . to . not . equal ( originalMode )
52
+ expect ( updatedMode ) . to . equal ( parseInt ( '0777' , 8 ) )
53
+ } )
54
+
55
+ it ( 'should update the mode for a directory' , async ( ) => {
56
+ const path = `/foo-${ Math . random ( ) } `
57
+
58
+ await ipfs . files . mkdir ( path )
59
+ const originalMode = ( await ipfs . files . stat ( path ) ) . mode
60
+ await ipfs . files . chmod ( path , '0777' , {
61
+ flush : true
62
+ } )
63
+
64
+ const updatedMode = ( await ipfs . files . stat ( path ) ) . mode
65
+ expect ( updatedMode ) . to . not . equal ( originalMode )
66
+ expect ( updatedMode ) . to . equal ( parseInt ( '0777' , 8 ) )
37
67
} )
38
68
39
- it ( 'should change file mode as string' , async function ( ) {
40
- const mode = parseInt ( '544' , 8 )
41
- await testMode ( '544' , mode )
69
+ it ( 'should update the mode for a hamt-sharded-directory' , async ( ) => {
70
+ const path = `/foo-${ Math . random ( ) } `
71
+
72
+ await ipfs . files . mkdir ( path )
73
+ await ipfs . files . write ( `${ path } /foo.txt` , Buffer . from ( 'Hello world' ) , {
74
+ create : true ,
75
+ shardSplitThreshold : 0
76
+ } )
77
+ const originalMode = ( await ipfs . files . stat ( path ) ) . mode
78
+ await ipfs . files . chmod ( path , '0777' , {
79
+ flush : true
80
+ } )
81
+
82
+ const updatedMode = ( await ipfs . files . stat ( path ) ) . mode
83
+ expect ( updatedMode ) . to . not . equal ( originalMode )
84
+ expect ( updatedMode ) . to . equal ( parseInt ( '0777' , 8 ) )
42
85
} )
43
86
44
- it ( 'should change file mode to 0' , async function ( ) {
45
- const mode = 0
46
- await testMode ( mode , mode )
87
+ it ( 'should update modes with basic symbolic notation that adds bits' , async ( ) => {
88
+ await testChmod ( '0000' , '+x' , '0111' )
89
+ await testChmod ( '0000' , '+w' , '0222' )
90
+ await testChmod ( '0000' , '+r' , '0444' )
91
+ await testChmod ( '0000' , 'u+x' , '0100' )
92
+ await testChmod ( '0000' , 'u+w' , '0200' )
93
+ await testChmod ( '0000' , 'u+r' , '0400' )
94
+ await testChmod ( '0000' , 'g+x' , '0010' )
95
+ await testChmod ( '0000' , 'g+w' , '0020' )
96
+ await testChmod ( '0000' , 'g+r' , '0040' )
97
+ await testChmod ( '0000' , 'o+x' , '0001' )
98
+ await testChmod ( '0000' , 'o+w' , '0002' )
99
+ await testChmod ( '0000' , 'o+r' , '0004' )
100
+ await testChmod ( '0000' , 'ug+x' , '0110' )
101
+ await testChmod ( '0000' , 'ug+w' , '0220' )
102
+ await testChmod ( '0000' , 'ug+r' , '0440' )
103
+ await testChmod ( '0000' , 'ugo+x' , '0111' )
104
+ await testChmod ( '0000' , 'ugo+w' , '0222' )
105
+ await testChmod ( '0000' , 'ugo+r' , '0444' )
106
+ await testChmod ( '0000' , 'a+x' , '0111' )
107
+ await testChmod ( '0000' , 'a+w' , '0222' )
108
+ await testChmod ( '0000' , 'a+r' , '0444' )
47
109
} )
48
110
49
- it ( 'should change directory mode' , async function ( ) {
50
- const testPath = `/test-${ hat ( ) } `
51
- const mode = parseInt ( '544' , 8 )
111
+ it ( 'should update modes with basic symbolic notation that removes bits' , async ( ) => {
112
+ await testChmod ( '0111' , '-x' , '0000' )
113
+ await testChmod ( '0222' , '-w' , '0000' )
114
+ await testChmod ( '0444' , '-r' , '0000' )
115
+ await testChmod ( '0100' , 'u-x' , '0000' )
116
+ await testChmod ( '0200' , 'u-w' , '0000' )
117
+ await testChmod ( '0400' , 'u-r' , '0000' )
118
+ await testChmod ( '0010' , 'g-x' , '0000' )
119
+ await testChmod ( '0020' , 'g-w' , '0000' )
120
+ await testChmod ( '0040' , 'g-r' , '0000' )
121
+ await testChmod ( '0001' , 'o-x' , '0000' )
122
+ await testChmod ( '0002' , 'o-w' , '0000' )
123
+ await testChmod ( '0004' , 'o-r' , '0000' )
124
+ await testChmod ( '0110' , 'ug-x' , '0000' )
125
+ await testChmod ( '0220' , 'ug-w' , '0000' )
126
+ await testChmod ( '0440' , 'ug-r' , '0000' )
127
+ await testChmod ( '0111' , 'ugo-x' , '0000' )
128
+ await testChmod ( '0222' , 'ugo-w' , '0000' )
129
+ await testChmod ( '0444' , 'ugo-r' , '0000' )
130
+ await testChmod ( '0111' , 'a-x' , '0000' )
131
+ await testChmod ( '0222' , 'a-w' , '0000' )
132
+ await testChmod ( '0444' , 'a-r' , '0000' )
133
+ } )
134
+
135
+ it ( 'should update modes with basic symbolic notation that overrides bits' , async ( ) => {
136
+ await testChmod ( '0777' , '=x' , '0111' )
137
+ await testChmod ( '0777' , '=w' , '0222' )
138
+ await testChmod ( '0777' , '=r' , '0444' )
139
+ await testChmod ( '0777' , 'u=x' , '0177' )
140
+ await testChmod ( '0777' , 'u=w' , '0277' )
141
+ await testChmod ( '0777' , 'u=r' , '0477' )
142
+ await testChmod ( '0777' , 'g=x' , '0717' )
143
+ await testChmod ( '0777' , 'g=w' , '0727' )
144
+ await testChmod ( '0777' , 'g=r' , '0747' )
145
+ await testChmod ( '0777' , 'o=x' , '0771' )
146
+ await testChmod ( '0777' , 'o=w' , '0772' )
147
+ await testChmod ( '0777' , 'o=r' , '0774' )
148
+ await testChmod ( '0777' , 'ug=x' , '0117' )
149
+ await testChmod ( '0777' , 'ug=w' , '0227' )
150
+ await testChmod ( '0777' , 'ug=r' , '0447' )
151
+ await testChmod ( '0777' , 'ugo=x' , '0111' )
152
+ await testChmod ( '0777' , 'ugo=w' , '0222' )
153
+ await testChmod ( '0777' , 'ugo=r' , '0444' )
154
+ await testChmod ( '0777' , 'a=x' , '0111' )
155
+ await testChmod ( '0777' , 'a=w' , '0222' )
156
+ await testChmod ( '0777' , 'a=r' , '0444' )
157
+ } )
52
158
53
- await ipfs . files . mkdir ( testPath , {
54
- create : true
159
+ it ( 'should update modes with multiple symbolic notation' , async ( ) => {
160
+ await testChmod ( '0000' , 'g+x,u+w' , '0210' )
161
+ } )
162
+
163
+ it ( 'should update modes with special symbolic notation' , async ( ) => {
164
+ await testChmod ( '0000' , 'g+s' , '2000' )
165
+ await testChmod ( '0000' , 'u+s' , '4000' )
166
+ await testChmod ( '0000' , '+t' , '1000' )
167
+ await testChmod ( '0000' , '+s' , '6000' )
168
+ } )
169
+
170
+ it ( 'should apply special execute permissions to world' , async ( ) => {
171
+ const path = `/foo-${ Math . random ( ) } `
172
+ const sub = `${ path } /sub`
173
+ const file = `${ path } /sub/foo.txt`
174
+ const bin = `${ path } /sub/bar`
175
+
176
+ await ipfs . files . mkdir ( sub , {
177
+ parents : true
178
+ } )
179
+ await ipfs . files . touch ( file )
180
+ await ipfs . files . touch ( bin )
181
+
182
+ await ipfs . files . chmod ( path , 0o644 , {
183
+ recursive : true
184
+ } )
185
+ await ipfs . files . chmod ( bin , 'u+x' )
186
+
187
+ await expect ( ipfs . files . stat ( path ) ) . to . eventually . have . property ( 'mode' , 0o644 )
188
+ await expect ( ipfs . files . stat ( sub ) ) . to . eventually . have . property ( 'mode' , 0o644 )
189
+ await expect ( ipfs . files . stat ( file ) ) . to . eventually . have . property ( 'mode' , 0o644 )
190
+ await expect ( ipfs . files . stat ( bin ) ) . to . eventually . have . property ( 'mode' , 0o744 )
191
+
192
+ await ipfs . files . chmod ( path , 'a+X' , {
193
+ recursive : true
55
194
} )
56
- await ipfs . files . chmod ( testPath , mode )
57
195
58
- const stat = await ipfs . files . stat ( testPath )
59
- expect ( stat ) . to . have . property ( 'mode' ) . that . equals ( mode )
196
+ // directories should be world-executable
197
+ await expect ( ipfs . files . stat ( path ) ) . to . eventually . have . property ( 'mode' , 0o755 )
198
+ await expect ( ipfs . files . stat ( sub ) ) . to . eventually . have . property ( 'mode' , 0o755 )
199
+
200
+ // files without prior execute bit should be untouched
201
+ await expect ( ipfs . files . stat ( file ) ) . to . eventually . have . property ( 'mode' , 0o644 )
202
+
203
+ // files with prior execute bit should now be world-executable
204
+ await expect ( ipfs . files . stat ( bin ) ) . to . eventually . have . property ( 'mode' , 0o755 )
205
+ } )
206
+
207
+ it ( 'should apply special execute permissions to user' , async ( ) => {
208
+ const path = `/foo-${ Math . random ( ) } `
209
+ const sub = `${ path } /sub`
210
+ const file = `${ path } /sub/foo.txt`
211
+ const bin = `${ path } /sub/bar`
212
+
213
+ await ipfs . files . mkdir ( sub , {
214
+ parents : true
215
+ } )
216
+ await ipfs . files . touch ( file )
217
+ await ipfs . files . touch ( bin )
218
+
219
+ await ipfs . files . chmod ( path , 0o644 , {
220
+ recursive : true
221
+ } )
222
+ await ipfs . files . chmod ( bin , 'u+x' )
223
+
224
+ await expect ( ipfs . files . stat ( path ) ) . to . eventually . have . property ( 'mode' , 0o644 )
225
+ await expect ( ipfs . files . stat ( sub ) ) . to . eventually . have . property ( 'mode' , 0o644 )
226
+ await expect ( ipfs . files . stat ( file ) ) . to . eventually . have . property ( 'mode' , 0o644 )
227
+ await expect ( ipfs . files . stat ( bin ) ) . to . eventually . have . property ( 'mode' , 0o744 )
228
+
229
+ await ipfs . files . chmod ( path , 'u+X' , {
230
+ recursive : true
231
+ } )
232
+
233
+ // directories should be user executable
234
+ await expect ( ipfs . files . stat ( path ) ) . to . eventually . have . property ( 'mode' , 0o744 )
235
+ await expect ( ipfs . files . stat ( sub ) ) . to . eventually . have . property ( 'mode' , 0o744 )
236
+
237
+ // files without prior execute bit should be untouched
238
+ await expect ( ipfs . files . stat ( file ) ) . to . eventually . have . property ( 'mode' , 0o644 )
239
+
240
+ // files with prior execute bit should now be user executable
241
+ await expect ( ipfs . files . stat ( bin ) ) . to . eventually . have . property ( 'mode' , 0o744 )
242
+ } )
243
+
244
+ it ( 'should apply special execute permissions to user and group' , async ( ) => {
245
+ const path = `/foo-${ Math . random ( ) } `
246
+ const sub = `${ path } /sub`
247
+ const file = `${ path } /sub/foo.txt`
248
+ const bin = `${ path } /sub/bar`
249
+
250
+ await ipfs . files . mkdir ( sub , {
251
+ parents : true
252
+ } )
253
+ await ipfs . files . touch ( file )
254
+ await ipfs . files . touch ( bin )
255
+
256
+ await ipfs . files . chmod ( path , 0o644 , {
257
+ recursive : true
258
+ } )
259
+ await ipfs . files . chmod ( bin , 'u+x' )
260
+
261
+ await expect ( ipfs . files . stat ( path ) ) . to . eventually . have . property ( 'mode' , 0o644 )
262
+ await expect ( ipfs . files . stat ( sub ) ) . to . eventually . have . property ( 'mode' , 0o644 )
263
+ await expect ( ipfs . files . stat ( file ) ) . to . eventually . have . property ( 'mode' , 0o644 )
264
+ await expect ( ipfs . files . stat ( bin ) ) . to . eventually . have . property ( 'mode' , 0o744 )
265
+
266
+ await ipfs . files . chmod ( path , 'ug+X' , {
267
+ recursive : true
268
+ } )
269
+
270
+ // directories should be user and group executable
271
+ await expect ( ipfs . files . stat ( path ) ) . to . eventually . have . property ( 'mode' , 0o754 )
272
+ await expect ( ipfs . files . stat ( sub ) ) . to . eventually . have . property ( 'mode' , 0o754 )
273
+
274
+ // files without prior execute bit should be untouched
275
+ await expect ( ipfs . files . stat ( file ) ) . to . eventually . have . property ( 'mode' , 0o644 )
276
+
277
+ // files with prior execute bit should now be user and group executable
278
+ await expect ( ipfs . files . stat ( bin ) ) . to . eventually . have . property ( 'mode' , 0o754 )
279
+ } )
280
+
281
+ it ( 'should apply special execute permissions to sharded directories' , async ( ) => {
282
+ const path = `/foo-${ Math . random ( ) } `
283
+ const sub = `${ path } /sub`
284
+ const file = `${ path } /sub/foo.txt`
285
+ const bin = `${ path } /sub/bar`
286
+
287
+ await ipfs . files . mkdir ( sub , {
288
+ parents : true ,
289
+ shardSplitThreshold : 0
290
+ } )
291
+ await ipfs . files . touch ( file , {
292
+ shardSplitThreshold : 0
293
+ } )
294
+ await ipfs . files . touch ( bin , {
295
+ shardSplitThreshold : 0
296
+ } )
297
+
298
+ await ipfs . files . chmod ( path , 0o644 , {
299
+ recursive : true ,
300
+ shardSplitThreshold : 0
301
+ } )
302
+ await ipfs . files . chmod ( bin , 'u+x' , {
303
+ recursive : true ,
304
+ shardSplitThreshold : 0
305
+ } )
306
+
307
+ await expect ( ipfs . files . stat ( path ) ) . to . eventually . have . property ( 'mode' , 0o644 )
308
+ await expect ( ipfs . files . stat ( sub ) ) . to . eventually . have . property ( 'mode' , 0o644 )
309
+ await expect ( ipfs . files . stat ( file ) ) . to . eventually . have . property ( 'mode' , 0o644 )
310
+ await expect ( ipfs . files . stat ( bin ) ) . to . eventually . have . property ( 'mode' , 0o744 )
311
+
312
+ await ipfs . files . chmod ( path , 'ug+X' , {
313
+ recursive : true ,
314
+ shardSplitThreshold : 0
315
+ } )
316
+
317
+ // directories should be user and group executable
318
+ await expect ( ipfs . files . stat ( path ) ) . to . eventually . include ( {
319
+ type : 'hamt-sharded-directory' ,
320
+ mode : 0o754
321
+ } )
322
+ await expect ( ipfs . files . stat ( sub ) ) . to . eventually . have . property ( 'mode' , 0o754 )
323
+
324
+ // files without prior execute bit should be untouched
325
+ await expect ( ipfs . files . stat ( file ) ) . to . eventually . have . property ( 'mode' , 0o644 )
326
+
327
+ // files with prior execute bit should now be user and group executable
328
+ await expect ( ipfs . files . stat ( bin ) ) . to . eventually . have . property ( 'mode' , 0o754 )
60
329
} )
61
330
} )
62
331
}
0 commit comments