/** * 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 DIRECTORY_BIT: 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) { require(raw.size >= 4) val raw = raw.slice(0..4) val dirValue = raw[0].toUInt().xor(this.DIRECTORY_BIT) 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.DIRECTORY_BIT) } return perms } }