@@ -53,6 +53,14 @@ from random import sample
53
53
MIN_VERSIONS = {
54
54
'datalad' : '0.7'
55
55
}
56
+
57
+ # Some variables for reuse
58
+ import stat
59
+
60
+ ALL_CAN_WRITE = (stat .S_IWUSR | stat .S_IWGRP | stat .S_IWOTH )
61
+ ALL_CAN_READ = (stat .S_IRUSR | stat .S_IRGRP | stat .S_IROTH )
62
+ assert ALL_CAN_READ >> 1 == ALL_CAN_WRITE # Assumption in the code
63
+
56
64
PY3 = sys .version_info [0 ] >= 3
57
65
58
66
import logging
@@ -306,6 +314,35 @@ def find_files(regex, topdir=curdir, exclude=None, exclude_vcs=True, dirs=False)
306
314
find_files .__doc__ %= (_VCS_REGEX ,)
307
315
308
316
317
+ def set_readonly (path , read_only = True ):
318
+ """Make file read only or writeable while preserving "access levels"
319
+
320
+ So if file was not readable by "others" it should remain not readable
321
+ by others
322
+
323
+ Parameters
324
+ ----------
325
+ path : str
326
+ read_only : bool, optional
327
+ If True (default) - would make it read-only. If False, would make it
328
+ writeable for levels where it is readable
329
+ """
330
+ # get current permissions
331
+ perms = stat .S_IMODE (os .lstat (path ).st_mode )
332
+ # set new permissions
333
+ if read_only :
334
+ new_perms = perms & (~ ALL_CAN_WRITE )
335
+ else :
336
+ # need to set only for those which had read bit set
337
+ # read bit is <<1 away from write bit
338
+ whocanread = perms & ALL_CAN_READ
339
+ thosecanwrite = whocanread >> 1
340
+ new_perms = perms | thosecanwrite
341
+ # apply and return those target permissions
342
+ os .chmod (path , new_perms )
343
+ return new_perms
344
+
345
+
309
346
def group_dicoms_into_seqinfos (
310
347
files , file_filter = None , dcmfilter = None , grouping = 'studyUID'
311
348
):
@@ -959,7 +996,7 @@ def convert(items, symlink=True, converter=None,
959
996
if exists (scaninfo ):
960
997
lgr .info ("Post-treating %s file" , scaninfo )
961
998
treat_infofile (scaninfo )
962
- os . chmod (outname , 0o0440 )
999
+ set_readonly (outname )
963
1000
964
1001
if custom_callable is not None :
965
1002
custom_callable (* item )
@@ -1143,9 +1180,9 @@ def tuneup_bids_json_files(json_files):
1143
1180
lgr .error ("Failed to open magnitude file: %s" , exc )
1144
1181
1145
1182
# might have been made R/O already
1146
- os . chmod (json_phasediffname , 0o0664 )
1183
+ set_readonly (json_phasediffname , False )
1147
1184
json .dump (json_ , open (json_phasediffname , 'w' ), indent = 2 )
1148
- os . chmod (json_phasediffname , 0o0444 )
1185
+ set_readonly (json_phasediffname )
1149
1186
1150
1187
# phasediff one should contain two PhaseDiff's
1151
1188
# -- one for original amplitude and the other already replicating what is there
@@ -1219,15 +1256,15 @@ in that one though
1219
1256
if global_options ['overwrite' ] and os .path .lexists (scaninfo ):
1220
1257
# TODO: handle annexed file case
1221
1258
if not os .path .islink (scaninfo ):
1222
- os . chmod (scaninfo , 0o0660 )
1259
+ set_readonly (scaninfo , False )
1223
1260
res = embedfunc .run ()
1224
- os . chmod (scaninfo , 0o0444 )
1261
+ set_readonly (scaninfo )
1225
1262
if with_prov :
1226
1263
g = res .provenance .rdf ()
1227
1264
g .parse (prov_file ,
1228
1265
format = 'turtle' )
1229
1266
g .serialize (prov_file , format = 'turtle' )
1230
- os . chmod (prov_file , 0o0440 )
1267
+ set_readonly (prov_file )
1231
1268
except Exception as exc :
1232
1269
lgr .error ("Embedding failed: %s" , str (exc ))
1233
1270
os .chdir (cwd )
@@ -1244,10 +1281,10 @@ def treat_infofile(filename):
1244
1281
j_slim = slim_down_info (j )
1245
1282
j_pretty = json_dumps_pretty (j_slim , indent = 2 , sort_keys = True )
1246
1283
1247
- os . chmod (filename , 0o0664 )
1284
+ set_readonly (filename , False )
1248
1285
with open (filename , 'wt' ) as fp :
1249
1286
fp .write (j_pretty )
1250
- os . chmod (filename , 0o0444 )
1287
+ set_readonly (filename )
1251
1288
1252
1289
1253
1290
def convert_dicoms (sid ,
0 commit comments