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
92
|
/**
* The permissions of a newly created file.
*/
class FilePermissions {
/**
* The permissions for the file's owning user.
*/
val userPerms: Permissions
/**
* The permissions for the file's owning group.
*/
val groupPerms: Permissions
/**
* The permissions for everyone else.
*/
val elsePerms: Permissions
/**
* Is the file a directory? If not, it's a regular file.
*/
val isDirectory: Boolean
private val DMDIR: UInt = 0x80000000u
/**
* Constructor for file permissions with separate fields.
*
* @param userPerms The permissions for the file's owning user.
* @param groupPerms The permissions for the file's owning group.
* @param elsePerms The permissions for everyone else.
* @param isDirectory Is the file a directory? If not, it's a regular file.
*/
constructor(userPerms: Permissions, groupPerms: Permissions, elsePerms: Permissions, isDirectory: Boolean) {
this.userPerms = userPerms
this.groupPerms = groupPerms
this.elsePerms = elsePerms
this.isDirectory = isDirectory
}
/**
* Constructor for raw file permission data. Only the first 4 elements are read.
*
* @param raw The raw file permission data.
* @throws IllegalArgumentException if [raw] does not have at least 4 elements.
*/
constructor(raw: List<UByte>) {
require(raw.size >= 4)
val raw = raw.slice(0..4)
val dirValue = raw[0].toUInt().xor(this.DMDIR)
this.isDirectory = dirValue > 0u
this.userPerms = Permissions.fromByte(raw[1])
this.groupPerms = Permissions.fromByte(raw[2])
this.elsePerms = Permissions.fromByte(raw[3])
}
enum class Permissions(val bits: UByte) {
READ(0x4u),
WRITE(0x2u),
EXECUTE(0x1u),
READ_WRITE(READ.bits.or(WRITE.bits)),
READ_EXECUTE(READ.bits.or(EXECUTE.bits)),
WRITE_EXECUTE(WRITE.bits.or(EXECUTE.bits)),
READ_WRITE_EXECUTE(READ.bits.or(WRITE.bits.or(EXECUTE.bits)));
companion object {
/**
* Obtain a [Permissions] instance by matching its value.
*
* @throws NoSuchElementException if no such element has the provided value.
*/
fun fromByte(bits: UByte) = Permissions.entries.first { it.bits == bits }
}
}
/**
* Turn the permissions described by the [FilePermissions] fields into a permission integer (4 bytes).
*/
fun toPermissionInt(): UInt {
val permFileds = listOf(userPerms, groupPerms, elsePerms)
val perms: UInt = 0u
for (i in 0..permFileds.size) {
perms.or(permFileds[i].bits.toUInt().shl(8 * (permFileds.size - 1 - i)))
}
if (isDirectory) {
perms.or(this.DMDIR)
}
return perms
}
}
|