summaryrefslogtreecommitdiff
path: root/src/main/kotlin/Stat.kt
blob: e609b4c2ccb6e1fee3026fbdcb9d6dc3129a6f89 (plain)
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
import java.math.BigInteger

// TODO: add time conversion methods
/**
 * File attributes. The `type` and `dev` attributes are ignored since they are for kernel use only. Time is measured in
 * seconds, since the epoch (Jan 1 00:00 1970 GMT).
 */
class Stat {
    /**
     * The FID sent the T-stat message.
     */
    val fid: UInt

    /**
     * The QID of the file.
     */
    val qid: QID

    /**
     * Permissions and flags.
     */
    val mode: FilePermissions

    /**
     * Last acces time.
     */
    val atime: UInt

    /**
     * Last modification time.
     */
    val mtime: UInt

    /**
     * The length of the file in bytes.
     */
    val length: ULong

    /**
     * The file name, which is `/` if the file is the root directory.
     */
    val name: String

    /**
     * The owner's name.
     */
    val uid: String

    /**
     * The group's name.
     */
    val gid: String

    /**
     * The name of the user who last modified the file.
     */
    val muid: String

    /**
     * Make an instance of [Stat] from each of its fields.
     *
     * @param fid The FID sent the T-stat message.
     * @param qid The QID of the file.
     * @param mode Permissions and flags.
     * @param atime Last acces time.
     * @param mtime Last modification time.
     * @param length The length of the file in bytes.
     * @param name The file name, which is `/` if the file is the root directory.
     * @param uid The owner's name.
     * @param gid The group's name.
     * @param muid The name of the user who last modified the file.
     */
    constructor(fid: UInt, qid: QID, mode: FilePermissions, atime: UInt, mtime: UInt, length: ULong, name: String, uid: String, gid: String, muid: String) {
        this.fid = fid
        this.qid = qid
        this.mode = mode
        this.atime = atime
        this.mtime = mtime
        this.length = length
        this.name = name
        this.uid = uid
        this.gid = gid
        this.muid = muid
    }

    /**
     * Make an instance of [Stat] from raw data.
     *
     * @param fid The FID of the file associated with the stat instance.
     * @param raw The raw stat data.
     */
    constructor(fid: UInt, raw: List<UByte>) {
        var offset = 0
        val qid = QID(raw.slice(0..<13))
        offset += 13
        val mode = FilePermissions(raw.slice(offset+0..<offset+4))
        offset += 4

        val intFielSizes = listOf(4, 4, 8)
        val intFields: MutableList<BigInteger> = mutableListOf()
        for (size in intFielSizes) {
            intFields.add(InMessage.convInteger(raw, offset, size))
            offset += size
        }
        val atime = intFields[0].toInt().toUInt()
        val mtime = intFields[1].toInt().toUInt()
        val length = intFields[2].toLong().toULong()

        val strAmount = 4
        val strFields: MutableList<String> = mutableListOf()
        for (i in 0..strAmount) {
            val str = InMessage.convString(raw, offset)
            strFields.add(str)
            offset += str.length
        }
        val name = strFields[0]
        val uid = strFields[1]
        val gid = strFields[2]
        val muid = strFields[3]

        this.fid = fid
        this.qid = qid
        this.mode = mode
        this.atime = atime
        this.mtime = mtime
        this.length = length
        this.name = name
        this.uid = uid
        this.gid = gid
        this.muid = muid
    }

    /**
     * Turn a [Stat] instance into raw data. This leaves out the [fid] field.
     */
    fun toRaw(): List<UByte> {
        var bytes: List<UByte> = emptyList()
        bytes += this.qid.toRaw()
        bytes += OutMessage.convIntegerToBytes(BigInteger(this.mode.toPermissionInt().toString()), 4u)
        bytes += OutMessage.convIntegerToBytes(BigInteger(this.atime.toString()), 4u)
        bytes += OutMessage.convIntegerToBytes(BigInteger(this.mtime.toString()), 4u)
        bytes += OutMessage.convIntegerToBytes(BigInteger(this.length.toString()), 8u)
        bytes += OutMessage.convStringToBytes(this.name)
        bytes += OutMessage.convStringToBytes(this.uid)
        bytes += OutMessage.convStringToBytes(this.gid)
        bytes += OutMessage.convStringToBytes(this.muid)
        return bytes
    }
}